/**
     * Do the actual autoplacement.
     * @param aManual - if true, use extra heuristics for smarter placement when manually
     * called up.
     */
    void DoAutoplace( bool aManual )
    {
        bool force_wire_spacing = false;
        SIDE field_side = choose_side_for_fields( aManual );
        wxPoint fbox_pos = field_box_placement( field_side );
        EDA_RECT field_box( fbox_pos, m_fbox_size );

        if( aManual )
            force_wire_spacing = fit_fields_between_wires( &field_box, field_side );

        // Move the fields
        int last_y_coord = field_box.GetTop();
        for( unsigned field_idx = 0; field_idx < m_fields.size(); ++field_idx )
        {
            SCH_FIELD* field = m_fields[field_idx];

            if( m_allow_rejustify )
                justify_field( field, field_side );

            wxPoint pos(
                field_horiz_placement( field, field_box ),
                field_vert_placement( field, field_box, &last_y_coord, !force_wire_spacing ) );

            if( m_align_to_grid )
            {
                pos.x = round_n( pos.x, 50, field_side.x >= 0 );
                pos.y = round_n( pos.y, 50, field_side.y == 1 );
            }

            field->SetPosition( pos );
        }
    }
示例#2
0
/**
 * If any changes have been made to this component,
 * they are now applied to the schematic component
 */
void BOM_TABLE_COMPONENT::ApplyFieldChanges()
{
    for( auto& unit : Units )
    {
        auto cmp = unit.GetComp();

        if( !cmp )
            continue;

        // Iterate over each column
        SCH_FIELD* field;

        for( auto& column : m_columnList->Columns )
        {
            if( column && HasValueChanged( column ) )
            {
                wxString value = GetFieldValue( column->Id() );

                switch( column->Id() )
                {
                // Ignore read-only fields
                case BOM_COL_ID_REFERENCE:
                case BOM_COL_ID_QUANTITY:
                    continue;

                // Special field considerations
                case BOM_COL_ID_FOOTPRINT:
                    field = cmp->GetField( FOOTPRINT );
                    break;

                case BOM_COL_ID_VALUE:
                    field = cmp->GetField( VALUE );
                    break;
                case BOM_COL_ID_DATASHEET:
                    field = cmp->GetField( DATASHEET );
                    break;

                default:
                    // Find the field by name (but ignore default fields)
                    field = cmp->FindField( column->Title(), false );
                    break;
                }

                // New field needs to be added?
                if( !field && !value.IsEmpty() )
                {
                    SCH_FIELD newField( wxPoint( 0, 0 ), -1, cmp, column->Title() );
                    field = cmp->AddField( newField );
                }

                if( field )
                {
                    field->SetText( value );
                }
            }
        }
    }
}
示例#3
0
/**
 * Extract field data from all components
 * Compiles an inclusive list of all field names from all components
 */
void BOM_TABLE_MODEL::AddComponentFields( SCH_COMPONENT* aCmp )
{
    std::vector< SCH_FIELD* > fields;

    SCH_FIELD* field;
    wxString fieldName;

    if( nullptr == aCmp )
        return;

    // Extract custom columns from component
    fields.clear();
    aCmp->GetFields( fields, false );

    // Iterate over custom field datas
    for( unsigned int i=MANDATORY_FIELDS; i<fields.size(); i++ )
    {
        field = fields[i];

        if( nullptr == field ) continue;

        fieldName = field->GetName();

        bool userMatchFound = false;

        // Search for the column within the existing columns
        for( auto col : ColumnList.Columns )
        {
            if( !col )
            {
                continue;
            }

            if( col->Title().Cmp( fieldName ) == 0 )
            {
                if( col->Id() >= BOM_COL_ID_USER )
                {
                    userMatchFound = true;
                    break;
                }
            }
        }

        // If a user-made column already exists with the same name, abort
        if( userMatchFound )
        {
            continue;
        }

        ColumnList.AddColumn( new BOM_COLUMN( ColumnList.NextFieldId(),
                                              BOM_COL_TYPE_USER,
                                              field->GetName(),
                                              true, false ) );
    }
}
SCH_ITEM* SCH_SCREEN::GetItem( const wxPoint& aPosition, int aAccuracy, KICAD_T aType ) const
{
    for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
    {
        if( item->HitTest( aPosition, aAccuracy ) && (aType == NOT_USED) )
            return item;

        if( (aType == SCH_FIELD_T) && (item->Type() == SCH_COMPONENT_T) )
        {
            SCH_COMPONENT* component = (SCH_COMPONENT*) item;

            for( int i = REFERENCE; i < component->GetFieldCount(); i++ )
            {
                SCH_FIELD* field = component->GetField( i );

                if( field->HitTest( aPosition, aAccuracy ) )
                    return (SCH_ITEM*) field;
            }
        }
        else if( (aType == SCH_SHEET_PIN_T) && (item->Type() == SCH_SHEET_T) )
        {
            SCH_SHEET* sheet = (SCH_SHEET*)item;

            SCH_SHEET_PIN* label = sheet->GetPin( aPosition );

            if( label )
                return (SCH_ITEM*) label;
        }
        else if( (item->Type() == aType) && item->HitTest( aPosition, aAccuracy ) )
        {
            return item;
        }
    }

    return NULL;
}
示例#5
0
文件: backanno.cpp 项目: jerkey/kicad
bool SCH_EDIT_FRAME::ProcessCmpToFootprintLinkFile( wxString& aFullFilename,
                                                    bool aForceFieldsVisibleAttribute,
                                                    bool aFieldsVisibleAttributeState )
{
    // Build a flat list of components in schematic:
    SCH_REFERENCE_LIST referencesList;
    SCH_SHEET_LIST SheetList;
    SheetList.GetComponents( referencesList, false );

    FILE* cmpFile = wxFopen( aFullFilename, wxT( "rt" ) );
    if( cmpFile == NULL )
        return false;

    // cmpFileReader dtor will close cmpFile
    FILE_LINE_READER cmpFileReader( cmpFile, aFullFilename );

    // Now, for each component found in file,
    // replace footprint field value by the new value:
    wxString reference;
    wxString footprint;
    wxString buffer;
    wxString value;

    while( cmpFileReader.ReadLine() )
    {
        buffer = FROM_UTF8( cmpFileReader.Line() );

        if( ! buffer.StartsWith( wxT("BeginCmp") ) )
            continue;

        // Begin component description.
        reference.Empty();
        footprint.Empty();

        while( cmpFileReader.ReadLine() )
        {
            buffer = FROM_UTF8( cmpFileReader.Line() );

            if( buffer.StartsWith( wxT("EndCmp") ) )
                break;

            // store string value, stored between '=' and ';' delimiters.
            value = buffer.AfterFirst( '=' );
            value = value.BeforeLast( ';');
            value.Trim(true);
            value.Trim(false);

            if( buffer.StartsWith( wxT("Reference") ) )
            {
                reference = value;
                continue;
            }

            if( buffer.StartsWith( wxT("IdModule  =" ) ) )
            {
                footprint = value;
                continue;
            }
        }

        // A block is read: initialize the footprint field of the correponding component
        // if the footprint name is not empty
        if( reference.IsEmpty() )
            continue;
        // Search the component in the flat list
        for( unsigned ii = 0; ii < referencesList.GetCount(); ii++ )
        {
            if( reference.CmpNoCase( referencesList[ii].GetRef() ) == 0 )
            {
                // We have found a candidate.
                // Note: it can be not unique (multiple parts per package)
                // So we *do not* stop the search here
                SCH_COMPONENT* component = referencesList[ii].GetComponent();
                SCH_FIELD * fpfield = component->GetField( FOOTPRINT );
                fpfield->SetText( footprint );

                if( aForceFieldsVisibleAttribute )
                {
                        component->GetField( FOOTPRINT )
                            ->SetVisible( aFieldsVisibleAttributeState );
                }
            }
        }
    }
    return true;
}
XNODE* NETLIST_EXPORTER_GENERIC::makeComponents()
{
    XNODE*      xcomps = node( wxT( "components" ) );

    wxString    timeStamp;

    // some strings we need many times, but don't want to construct more
    // than once for performance.  These are used within loops so the
    // enclosing wxString constructor would fire on each loop iteration if
    // they were in a nested scope.

    // these are actually constructor invocations, not assignments as it appears:
    wxString    sFields     = wxT( "fields" );
    wxString    sField      = wxT( "field" );
    wxString    sComponent  = wxT( "comp" );          // use "part" ?
    wxString    sName       = wxT( "name" );
    wxString    sRef        = wxT( "ref" );
    wxString    sPins       = wxT( "pins" );
    wxString    sPin        = wxT( "pin" );
    wxString    sValue      = wxT( "value" );
    wxString    sSheetPath  = wxT( "sheetpath" );
    wxString    sFootprint  = wxT( "footprint" );
    wxString    sDatasheet  = wxT( "datasheet" );
    wxString    sTStamp     = wxT( "tstamp" );
    wxString    sTStamps    = wxT( "tstamps" );
    wxString    sTSFmt      = wxT( "%8.8lX" );        // comp->m_TimeStamp
    wxString    sLibSource  = wxT( "libsource" );
    wxString    sLibPart    = wxT( "libpart" );
    wxString    sLib        = wxT( "lib" );
    wxString    sPart       = wxT( "part" );
    wxString    sNames      = wxT( "names" );

    m_ReferencesAlreadyFound.Clear();

    SCH_SHEET_LIST sheetList( g_RootSheet );

    // Output is xml, so there is no reason to remove spaces from the field values.
    // And XML element names need not be translated to various languages.

    for( unsigned i = 0;  i < sheetList.size();  i++ )
    {
        for( EDA_ITEM* schItem = sheetList[i].LastDrawList();  schItem;  schItem = schItem->Next() )
        {
            SCH_COMPONENT*  comp = findNextComponentAndCreatePinList( schItem, &sheetList[i] );
            if( !comp )
                break;  // No component left

            schItem = comp;

            XNODE* xcomp;  // current component being constructed

            // Output the component's elements in order of expected access frequency.
            // This may not always look best, but it will allow faster execution
            // under XSL processing systems which do sequential searching within
            // an element.

            xcomps->AddChild( xcomp = node( sComponent ) );
            xcomp->AddAttribute( sRef, comp->GetRef( &sheetList[i] ) );

            xcomp->AddChild( node( sValue, comp->GetField( VALUE )->GetText() ) );

            if( !comp->GetField( FOOTPRINT )->IsVoid() )
                xcomp->AddChild( node( sFootprint, comp->GetField( FOOTPRINT )->GetText() ) );

            if( !comp->GetField( DATASHEET )->IsVoid() )
                xcomp->AddChild( node( sDatasheet, comp->GetField( DATASHEET )->GetText() ) );

            // Export all user defined fields within the component,
            // which start at field index MANDATORY_FIELDS.  Only output the <fields>
            // container element if there are any <field>s.
            if( comp->GetFieldCount() > MANDATORY_FIELDS )
            {
                XNODE* xfields;
                xcomp->AddChild( xfields = node( sFields ) );

                for( int fldNdx = MANDATORY_FIELDS; fldNdx < comp->GetFieldCount(); ++fldNdx )
                {
                    SCH_FIELD*  f = comp->GetField( fldNdx );

                    // only output a field if non empty and not just "~"
                    if( !f->IsVoid() )
                    {
                        XNODE*  xfield;
                        xfields->AddChild( xfield = node( sField, f->GetText() ) );
                        xfield->AddAttribute( sName, f->GetName() );
                    }
                }
            }

            XNODE*  xlibsource;
            xcomp->AddChild( xlibsource = node( sLibSource ) );

            // "logical" library name, which is in anticipation of a better search
            // algorithm for parts based on "logical_lib.part" and where logical_lib
            // is merely the library name minus path and extension.
            LIB_PART* part = m_libs->FindLibPart( comp->GetLibId() );
            if( part )
                xlibsource->AddAttribute( sLib, part->GetLib()->GetLogicalName() );

            // We only want the symbol name, not the full LIB_ID.
            xlibsource->AddAttribute( sPart, comp->GetLibId().GetLibItemName() );

            XNODE* xsheetpath;

            xcomp->AddChild( xsheetpath = node( sSheetPath ) );
            xsheetpath->AddAttribute( sNames, sheetList[i].PathHumanReadable() );
            xsheetpath->AddAttribute( sTStamps, sheetList[i].Path() );

            timeStamp.Printf( sTSFmt, (unsigned long)comp->GetTimeStamp() );
            xcomp->AddChild( node( sTStamp, timeStamp ) );
        }
    }

    return xcomps;
}
示例#7
0
bool SCH_SCREEN::SetComponentFootprint( SCH_SHEET_PATH* aSheetPath, const wxString& aReference,
                                        const wxString& aFootPrint, bool aSetVisible )
{
    SCH_COMPONENT* component;
    bool           found = false;

    for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
    {
        if( item->Type() != SCH_COMPONENT_T )
            continue;

        component = (SCH_COMPONENT*) item;

        if( aReference.CmpNoCase( component->GetRef( aSheetPath ) ) == 0 )
        {
            // Found: Init Footprint Field

            /* Give a reasonable value to the field position and
             * orientation, if the text is empty at position 0, because
             * it is probably not yet initialized
             */
            SCH_FIELD * fpfield = component->GetField( FOOTPRINT );
            if( fpfield->GetText().IsEmpty()
              && ( fpfield->GetTextPosition() == component->GetPosition() ) )
            {
                fpfield->SetOrientation( component->GetField( VALUE )->GetOrientation() );
                fpfield->SetTextPosition( component->GetField( VALUE )->GetTextPosition() );
                fpfield->SetSize( component->GetField( VALUE )->GetSize() );

                if( fpfield->GetOrientation() == 0 )
                    fpfield->Offset( wxPoint( 0, 100 ) );
                else
                    fpfield->Offset( wxPoint( 100, 0 ) );
            }

            fpfield->SetText( aFootPrint );
            fpfield->SetVisible( aSetVisible );

            found = true;
        }
    }

    return found;
}
void SCH_EDIT_FRAME::backAnnotateFootprints( const std::string& aChangedSetOfReferences )
    throw( IO_ERROR, boost::bad_pointer )
{
    // Build a flat list of components in schematic:
    SCH_REFERENCE_LIST  refs;
    SCH_SHEET_LIST      sheets( g_RootSheet );
    bool                isChanged = false;

    sheets.GetComponents( Prj().SchLibs(), refs, false );

    DSNLEXER    lexer( aChangedSetOfReferences, FROM_UTF8( __func__ ) );
    PTREE       doc;

    try
    {
        Scan( &doc, &lexer );

#if defined(DEBUG) && 0
        STRING_FORMATTER sf;
        Format( &sf, 0, 0, doc );
        printf( "%s: '%s'\n", __func__, sf.GetString().c_str() );
#endif

        CPTREE& back_anno = doc.get_child( "back_annotation" );
        wxString footprint;

        for( PTREE::const_iterator ref = back_anno.begin();  ref != back_anno.end();  ++ref )
        {
            wxASSERT( ref->first == "ref" );

            wxString reference = (UTF8&) ref->second.front().first;

            // Ensure the "fpid" node contains a footprint name,
            // and get it if exists
            if( ref->second.get_child( "fpid" ).size() )
            {
                wxString tmp = (UTF8&) ref->second.get_child( "fpid" ).front().first;
                footprint = tmp;
            }
            else
                footprint.Empty();

            // DBG( printf( "%s: ref:%s  fpid:%s\n", __func__, TO_UTF8( reference ), TO_UTF8( footprint ) ); )

            // Search the component in the flat list
            for( unsigned ii = 0;  ii < refs.GetCount();  ++ii )
            {
                if( reference == refs[ii].GetRef() )
                {
                    // We have found a candidate.
                    // Note: it can be not unique (multiple parts per package)
                    // So we *do not* stop the search here
                    SCH_COMPONENT*  component = refs[ii].GetComp();
                    SCH_FIELD*      fpfield   = component->GetField( FOOTPRINT );
                    const wxString& oldfp = fpfield->GetText();

                    if( !oldfp && fpfield->IsVisible() )
                    {
                        fpfield->SetVisible( false );
                    }

                    // DBG( printf("%s: ref:%s  fpid:%s\n", __func__, TO_UTF8( refs[ii].GetRef() ), TO_UTF8( footprint ) );)
                    if( oldfp != footprint )
                        isChanged = true;

                    fpfield->SetText( footprint );
                }
            }
        }
    }
    catch( const PTREE_ERROR& ex )
    {
        // remap the exception to something the caller is likely to understand.
        THROW_IO_ERROR( ex.what() );
    }

    if( isChanged )
        OnModify();
}
bool NETLIST_EXPORTER_PSPICE::ProcessNetlist( unsigned aCtl )
{
    const wxString      delimiters( "{:,; }" );
    SCH_SHEET_LIST      sheetList( g_RootSheet );
    // Set of reference names, to check for duplications
    std::set<wxString>  refNames;

    // Prepare list of nets generation (not used here, but...
    for( unsigned ii = 0; ii < m_masterList->size(); ii++ )
        m_masterList->GetItem( ii )->m_Flag = 0;

    m_netMap.clear();
    m_netMap["GND"] = 0;        // 0 is reserved for "GND"
    int netIdx = 1;

    m_libraries.clear();
    m_ReferencesAlreadyFound.Clear();

    UpdateDirectives( aCtl );

    for( unsigned sheet_idx = 0; sheet_idx < sheetList.size(); sheet_idx++ )
    {
        // Process component attributes to find Spice directives
        for( EDA_ITEM* item = sheetList[sheet_idx].LastDrawList(); item; item = item->Next() )
        {
            SCH_COMPONENT* comp = findNextComponentAndCreatePinList( item, &sheetList[sheet_idx] );

            if( !comp )
                break;

            item = comp;

            SPICE_ITEM spiceItem;
            spiceItem.m_parent = comp;

            // Obtain Spice fields
            SCH_FIELD* fieldLibFile = comp->FindField( GetSpiceFieldName( SF_LIB_FILE ) );
            SCH_FIELD* fieldSeq = comp->FindField( GetSpiceFieldName( SF_NODE_SEQUENCE ) );

            spiceItem.m_primitive = GetSpiceField( SF_PRIMITIVE, comp, aCtl )[0];
            spiceItem.m_model = GetSpiceField( SF_MODEL, comp, aCtl );
            spiceItem.m_refName = comp->GetRef( &sheetList[sheet_idx] );

            // Duplicate references will result in simulation errors
            if( refNames.count( spiceItem.m_refName ) )
            {
                DisplayError( NULL, wxT( "There are duplicate components. "
                            "You need to annotate schematics first." ) );
                return false;
            }

            refNames.insert( spiceItem.m_refName );

            // Check to see if component should be removed from Spice netlist
            spiceItem.m_enabled = StringToBool( GetSpiceField( SF_ENABLED, comp, aCtl ) );

            if( fieldLibFile && !fieldLibFile->GetText().IsEmpty() )
                m_libraries.insert( fieldLibFile->GetText() );

            wxArrayString pinNames;

            // Store pin information
            for( unsigned ii = 0; ii < m_SortedComponentPinList.size(); ii++ )
            {
                NETLIST_OBJECT* pin = m_SortedComponentPinList[ii];

                // NETLIST_EXPORTER marks removed pins by setting them to NULL
                if( !pin )
                    continue;

                spiceItem.m_pins.push_back( pin );
                pinNames.Add( pin->GetPinNumText() );

                // Create net mapping
                const wxString& netName = pin->GetNetName();
                if( m_netMap.count( netName ) == 0 )
                    m_netMap[netName] = netIdx++;
            }

            // Check if an alternative pin sequence is available:
            if( fieldSeq )
            {
                // Get the string containing the sequence of nodes:
                wxString nodeSeqIndexLineStr = fieldSeq->GetText();

                // Verify field exists and is not empty:
                if( !nodeSeqIndexLineStr.IsEmpty() )
                {
                    // Get Alt Pin Name Array From User:
                    wxStringTokenizer tkz( nodeSeqIndexLineStr, delimiters );

                    while( tkz.HasMoreTokens() )
                    {
                        wxString    pinIndex = tkz.GetNextToken();
                        int         seq;

                        // Find PinName In Standard List assign Standard List Index to Name:
                        seq = pinNames.Index( pinIndex );

                        if( seq != wxNOT_FOUND )
                            spiceItem.m_pinSequence.push_back( seq );
                    }
                }
            }

            m_spiceItems.push_back( spiceItem );
        }
    }

    return true;
}
wxString NETLIST_EXPORTER_PSPICE::GetSpiceField( SPICE_FIELD aField,
        SCH_COMPONENT* aComponent, unsigned aCtl )
{
    SCH_FIELD* field = aComponent->FindField( GetSpiceFieldName( aField ) );
    return field ? field->GetText() : GetSpiceFieldDefVal( aField, aComponent, aCtl );
}