void SCH_EDIT_FRAME::AnnotateComponents( bool              aAnnotateSchematic,
                                         ANNOTATE_ORDER_T  aSortOption,
                                         ANNOTATE_OPTION_T aAlgoOption,
                                         bool              aResetAnnotation,
                                         bool              aRepairTimestamps,
                                         bool              aLockUnits )
{
    SCH_REFERENCE_LIST references;

    SCH_SCREENS screens;

    // Build the sheet list.
    SCH_SHEET_LIST sheets;

    // Map of locked components
    SCH_MULTI_UNIT_REFERENCE_MAP lockedComponents;

    // Test for and replace duplicate time stamps in components and sheets.  Duplicate
    // time stamps can happen with old schematics, schematic conversions, or manual
    // editing of files.
    if( aRepairTimestamps )
    {
        int count = screens.ReplaceDuplicateTimeStamps();

        if( count )
        {
            wxString msg;
            msg.Printf( _( "%d duplicate time stamps were found and replaced." ), count );
            DisplayInfoMessage( NULL, msg, 2 );
        }
    }

    // If units must be locked, collect all the sets that must be annotated together.
    if( aLockUnits )
    {
        if( aAnnotateSchematic )
        {
            sheets.GetMultiUnitComponents( Prj().SchLibs(), lockedComponents );
        }
        else
        {
            m_CurrentSheet->GetMultiUnitComponents( Prj().SchLibs(), lockedComponents );
        }
    }

    // If it is an annotation for all the components, reset previous annotation.
    if( aResetAnnotation )
        DeleteAnnotation( !aAnnotateSchematic );

    // Set sheet number and number of sheets.
    SetSheetNumberAndCount();

    // Build component list
    if( aAnnotateSchematic )
    {
        sheets.GetComponents( Prj().SchLibs(), references );
    }
    else
    {
        m_CurrentSheet->GetComponents( Prj().SchLibs(), references );
    }

    // Break full components reference in name (prefix) and number:
    // example: IC1 become IC, and 1
    references.SplitReferences();

    switch( aSortOption )
    {
    default:
    case SORT_BY_X_POSITION:
        references.SortByXCoordinate();
        break;

    case SORT_BY_Y_POSITION:
        references.SortByYCoordinate();
        break;
    }

    bool useSheetNum = false;
    int idStep = 100;

    switch( aAlgoOption )
    {
    default:
    case INCREMENTAL_BY_REF:
        break;

    case SHEET_NUMBER_X_100:
        useSheetNum = true;
        break;

    case SHEET_NUMBER_X_1000:
        useSheetNum = true;
        idStep = 1000;
        break;
    }

    // Recalculate and update reference numbers in schematic
    references.Annotate( useSheetNum, idStep, lockedComponents );
    references.UpdateAnnotation();

    wxArrayString errors;

    // Final control (just in case ... ).
    if( CheckAnnotate( &errors, !aAnnotateSchematic ) )
    {
        wxString msg;

        for( size_t i = 0; i < errors.GetCount(); i++ )
            msg += errors[i];

        // wxLogWarning is a cheap and dirty way to dump a potentially long list of
        // strings to a dialog that can be saved to a file.  This should be replaced
        // by a more elegant solution.
        wxLogWarning( msg );
    }

    OnModify();

    // Update on screen references, that can be modified by previous calculations:
    m_CurrentSheet->UpdateAllScreenReferences();
    SetSheetNumberAndCount();

    m_canvas->Refresh( true );
}
Exemple #2
0
int TestMultiunitFootprints( SCH_SHEET_LIST& aSheetList )
{
    int errors = 0;
    std::map<wxString, LIB_ID> footprints;
    SCH_MULTI_UNIT_REFERENCE_MAP refMap;
    aSheetList.GetMultiUnitComponents( refMap, true );

    for( auto& component : refMap )
    {
        auto& refList = component.second;

        if( refList.GetCount() == 0 )
        {
            wxFAIL;   // it should not happen
            continue;
        }

        // Reference footprint
        wxString fp;
        wxString unitName;

        for( unsigned i = 0; i < component.second.GetCount(); ++i )
        {
            SCH_COMPONENT* cmp = refList.GetItem( i ).GetComp();
            SCH_SHEET_PATH sheetPath = refList.GetItem( i ).GetSheetPath();
            fp = cmp->GetField( FOOTPRINT )->GetText();

            if( !fp.IsEmpty() )
            {
                unitName = cmp->GetRef( &sheetPath )
                    + LIB_PART::SubReference( cmp->GetUnit(), false );
                break;
            }
        }

        for( unsigned i = 0; i < component.second.GetCount(); ++i )
        {
            SCH_REFERENCE& ref = refList.GetItem( i );
            SCH_COMPONENT* unit = ref.GetComp();
            SCH_SHEET_PATH sheetPath = refList.GetItem( i ).GetSheetPath();
            const wxString curFp = unit->GetField( FOOTPRINT )->GetText();

            if( !curFp.IsEmpty() && fp != curFp )
            {
                wxString curUnitName = unit->GetRef( &sheetPath )
                    + LIB_PART::SubReference( unit->GetUnit(), false );
                wxString msg = wxString::Format( _( "Unit %s has '%s' assigned, "
                                                    "whereas unit %s has '%s' assigned" ),
                                                 unitName,
                                                 fp,
                                                 curUnitName,
                                                 curFp );
                wxPoint pos = unit->GetPosition();

                SCH_MARKER* marker = new SCH_MARKER();
                marker->SetTimeStamp( GetNewTimeStamp() );
                marker->SetData( ERCE_DIFFERENT_UNIT_FP, pos, msg, pos );
                marker->SetMarkerType( MARKER_BASE::MARKER_ERC );
                marker->SetErrorLevel( MARKER_BASE::MARKER_SEVERITY_WARNING );
                ref.GetSheetPath().LastScreen()->Append( marker );

                ++errors;
            }
        }
    }

    return errors;
}