Commit 784c0420 authored by jean-pierre charras's avatar jean-pierre charras
Browse files

Finish work to enhance annotation algorithm.

Fix a minor warning when starting Kicad in debug mode (wxWidgets 2.9.1 specific)
parent 92c69a9c
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -680,7 +680,11 @@ bool WinEDA_App::SetLanguage( bool first_time )
        delete m_Locale;
        delete m_Locale;
    m_Locale = new wxLocale;
    m_Locale = new wxLocale;


#if wxCHECK_VERSION( 2, 9, 0 )
    if( !m_Locale->Init( m_LanguageId ) )
#else
    if( !m_Locale->Init( m_LanguageId, wxLOCALE_CONV_ENCODING ) )
    if( !m_Locale->Init( m_LanguageId, wxLOCALE_CONV_ENCODING ) )
#endif
    {
    {
        wxLogDebug( wxT("This language is not supported by the system.") );
        wxLogDebug( wxT("This language is not supported by the system.") );


+159 −66
Original line number Original line Diff line number Diff line
@@ -19,14 +19,11 @@
#include "sch_component.h"
#include "sch_component.h"
#include "lib_pin.h"
#include "lib_pin.h"


//#define USE_OLD_ALGO


static void BreakReference( SCH_REFERENCE_LIST& aComponentsList );
static void ReAnnotateComponents( SCH_REFERENCE_LIST& aComponentsList );
static void ComputeReferenceNumber( SCH_REFERENCE_LIST& aComponentsList, bool aUseSheetNum );
static void ComputeReferenceNumber( SCH_REFERENCE_LIST& aComponentsList, bool aUseSheetNum );
static int  GetLastReferenceNumber( int aObjet,SCH_REFERENCE_LIST& aComponentsList );
static int  ExistUnit( int aObjet, int aUnit, SCH_REFERENCE_LIST& aComponentList );
static int  ExistUnit( int aObjet, int aUnit, SCH_REFERENCE_LIST& aComponentList );



/**
/**
 * Function DeleteAnnotation
 * Function DeleteAnnotation
 * Remove current component annotations
 * Remove current component annotations
@@ -109,7 +106,7 @@ void SCH_EDIT_FRAME::AnnotateComponents(
    // Update the screen date.
    // Update the screen date.
    screens.SetDate( GenDate() );
    screens.SetDate( GenDate() );


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


    /* Build component list */
    /* Build component list */
@@ -124,7 +121,7 @@ void SCH_EDIT_FRAME::AnnotateComponents(


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


    bool useSheetNum = false;
    bool useSheetNum = false;
    switch( sortOption )
    switch( sortOption )
@@ -152,36 +149,126 @@ void SCH_EDIT_FRAME::AnnotateComponents(
        break;
        break;
    }
    }


    /* Recalculate reference numbers */
    // Recalculate and update reference numbers in schematic
    ComputeReferenceNumber( references, useSheetNum );
    ComputeReferenceNumber( references, useSheetNum );
    ReAnnotateComponents( references );
    references.UpdateAnnotation();


    /* Final control (just in case ... )*/
    /* Final control (just in case ... )*/
    CheckAnnotate( NULL, !annotateSchematic );
    CheckAnnotate( NULL, !annotateSchematic );
    OnModify();
    OnModify();

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

    DrawPanel->Refresh( true );
    DrawPanel->Refresh( true );
}
}


#ifdef USE_OLD_ALGO
/** helper function
 * Search the last used (greatest) reference number in the component list
 * for the prefix reference given by Objet
 * The component list must be sorted.
 *
 * @param aObjet = reference item ( aComponentsList[aObjet].m_TextRef is
 *                 the search pattern)
 * @param aComponentsList = list of items
 * @param aMinValue = min value for the current search
 */
static int GetLastNumberInReference( int aObjet,SCH_REFERENCE_LIST& aComponentsList,
                              int aMinValue )
{
    int lastNumber = aMinValue;


/*
    for( unsigned ii = 0; ii < aComponentsList.GetCount(); ii++ )
 * Update the reference component for the schematic project (or the current sheet)
    {
        // search only for the current reference prefix:
        if( aComponentsList[aObjet].CompareRef( aComponentsList[ii] ) != 0 )
            continue;

        // update max value for the current reference prefix
        if( lastNumber < aComponentsList[ii].m_NumRef )
            lastNumber = aComponentsList[ii].m_NumRef;
    }

    return lastNumber;
}

#else
/**
 * helper function BuildRefIdInUseList
 * creates the list of reference numbers in use for a given reference prefix.
 * @param aObjet = the current component index to use for reference prefix filtering.
 * @param aComponentsList = the full list of components
 * @param aIdList = the buffer to fill
 * @param aMinRefId = the min id value to store. all values < aMinRefId are ignored
 */
 */
static void ReAnnotateComponents( SCH_REFERENCE_LIST& aComponentList )
static void  BuildRefIdInUseList( int aObjet,SCH_REFERENCE_LIST& aComponentsList,
                           std::vector<int>& aIdList, int aMinRefId )
{
{
    /* update the reference numbers */
    aIdList.clear();
    for( unsigned ii = 0; ii < aComponentList.GetCount(); ii++ )

    for( unsigned ii = 0; ii < aComponentsList.GetCount(); ii++ )
    {
    {
        aComponentList[ii].Annotate();
        if(    ( aComponentsList[aObjet].CompareRef( aComponentsList[ii] ) == 0 )
            && ( aComponentsList[ii].m_NumRef >= aMinRefId ) )
            aIdList.push_back( aComponentsList[ii].m_NumRef );
    }
    sort( aIdList.begin(), aIdList.end() );

    // Ensure each reference Id appears only once
    // If there are multiple parts per package the same Id will be stored for each part.
    for( unsigned ii = 1; ii < aIdList.size(); ii++ )
    {
        if( aIdList[ii] != aIdList[ii-1] )
            continue;
        aIdList.erase(aIdList.begin() + ii );
        ii--;
    }
    }
}
}


/**
 * helper function CreateFirstFreeRefId
 * Search for a free ref Id inside a list of reference numbers in use.
 * This list is expected sorted by increasing values, and each value stored only once
 * @see BuildRefIdInUseList to prepare this list
 * @param aIdList = the buffer that contains Ids in use
 * @param aFirstValue = the first expected free value
 * @return a free (not yet used) Id
 * and this new id is added in list
 */
static int CreateFirstFreeRefId(  std::vector<int>& aIdList, int aFirstValue )
{
    int expectedId = aFirstValue;


void BreakReference( SCH_REFERENCE_LIST& aComponentsList )
    // We search for expectedId a value >= aFirstValue.
    // Skip existing Id < aFirstValue
    unsigned ii = 0;
    for( ; ii < aIdList.size(); ii++ )
    {
    {
    for( unsigned ii = 0; ii < aComponentsList.GetCount(); ii++ )
        if( expectedId <= aIdList[ii]  )
        aComponentsList[ii].Split();
            break;
    }

    // Ids are sorted by increasing value, from aFirstValue
    // So we search from aFirstValue the first not used value, i.e. the first hole in list.
     for(; ii < aIdList.size(); ii++ )
    {
        if( expectedId != aIdList[ii]  )    // This id is not yet used.
        {
            // Insert this free Id, in order to keep list sorted
            aIdList.insert(aIdList.begin() + ii, expectedId);
            return expectedId;
        }
        expectedId++;
    }
    }


    // All existing Id are tested, and all values are found in use.
    // So Create a new one.
    aIdList.push_back( expectedId );
    return expectedId;
}
#endif


/*
/*
 * Compute the reference number for components without reference number
 * Compute the reference number for components without reference number
@@ -189,7 +276,11 @@ void BreakReference( SCH_REFERENCE_LIST& aComponentsList )
 */
 */
static void ComputeReferenceNumber( SCH_REFERENCE_LIST& aComponentsList, bool aUseSheetNum  )
static void ComputeReferenceNumber( SCH_REFERENCE_LIST& aComponentsList, bool aUseSheetNum  )
{
{
    int LastReferenceNumber, NumberOfUnits, Unit;
    if ( aComponentsList.GetCount() == 0 )
        return;

    int LastReferenceNumber = 0;
    int NumberOfUnits, Unit;


    /* Components with an invisible reference (power...) always are
    /* Components with an invisible reference (power...) always are
     * re-annotated.  So set their .m_IsNew member to true
     * re-annotated.  So set their .m_IsNew member to true
@@ -209,33 +300,59 @@ static void ComputeReferenceNumber( SCH_REFERENCE_LIST& aComponentsList, bool aU
     * IC .. will be set to IC4, IC4, IC5 ...
     * IC .. will be set to IC4, IC4, IC5 ...
     */
     */
    unsigned first = 0;
    unsigned first = 0;

    /* calculate the last used number for this reference prefix: */
    /* calculate the last used number for this reference prefix: */
    LastReferenceNumber = GetLastReferenceNumber( first, aComponentsList );
#ifdef USE_OLD_ALGO
    int minRefId = 0;
    // when using sheet number, ensure ref number >= sheet number* 100
    if( aUseSheetNum )
        minRefId = aComponentsList[first].m_SheetNum * 100;
    LastReferenceNumber = GetLastNumberInReference( first, aComponentsList, minRefId );
#else
    int minRefId = 1;
    // when using sheet number, ensure ref number >= sheet number* 100
    if( aUseSheetNum )
        minRefId = aComponentsList[first].m_SheetNum * 100 + 1;
    // This is the list of all Id already in use for a given reference prefix.
    // Will be refilled for each new reference prefix.
    std::vector<int>idList;
    BuildRefIdInUseList( first, aComponentsList, idList, minRefId );
#endif
    for( unsigned ii = 0; ii < aComponentsList.GetCount(); ii++ )
    for( unsigned ii = 0; ii < aComponentsList.GetCount(); ii++ )
    {
    {
        if( aComponentsList[ii].m_Flag )
        if( aComponentsList[ii].m_Flag )
            continue;
            continue;

        if( ( aComponentsList[first].CompareRef( aComponentsList[ii] ) != 0 ) ||
        if( aComponentsList[first].CompareRef( aComponentsList[ii] ) != 0 )
            ( aUseSheetNum && ( aComponentsList[first].m_SheetNum != aComponentsList[ii].m_SheetNum ) )
            )
        {
        {
            /* New reference found: we need a new ref number for this
            /* New reference found: we need a new ref number for this
             * reference */
             * reference */
            first = ii;
            first = ii;
            LastReferenceNumber = GetLastReferenceNumber( ii, aComponentsList );
#ifdef USE_OLD_ALGO
        }
            minRefId = 0;
        // when using sheet number, ensure annot number >= sheet number* 100
            // when using sheet number, ensure ref number >= sheet number* 100
            if( aUseSheetNum )
            if( aUseSheetNum )
        {
                minRefId = aComponentsList[ii].m_SheetNum * 100;
            int min_num = aComponentsList[ii].m_SheetNum * 100;
            LastReferenceNumber = GetLastNumberInReference( ii, aComponentsList, minRefId);
            if( LastReferenceNumber < min_num )
#else
                LastReferenceNumber = min_num;
            minRefId = 1;
            // when using sheet number, ensure ref number >= sheet number* 100
            if( aUseSheetNum )
                minRefId = aComponentsList[ii].m_SheetNum * 100 + 1;
            BuildRefIdInUseList( first, aComponentsList, idList, minRefId );
#endif
        }
        }
        /* Annotation of one part per package components (trivial case)*/
        /* Annotation of one part per package components (trivial case)*/
        if( aComponentsList[ii].m_Entry->GetPartCount() <= 1 )
        if( aComponentsList[ii].m_Entry->GetPartCount() <= 1 )
        {
        {
            if( aComponentsList[ii].m_IsNew )
            if( aComponentsList[ii].m_IsNew )
            {
            {
#ifdef USE_OLD_ALGO
                LastReferenceNumber++;
                LastReferenceNumber++;
#else
                LastReferenceNumber = CreateFirstFreeRefId( idList, minRefId );
#endif
                aComponentsList[ii].m_NumRef = LastReferenceNumber;
                aComponentsList[ii].m_NumRef = LastReferenceNumber;
            }
            }


@@ -251,7 +368,11 @@ static void ComputeReferenceNumber( SCH_REFERENCE_LIST& aComponentsList, bool aU


        if( aComponentsList[ii].m_IsNew )
        if( aComponentsList[ii].m_IsNew )
        {
        {
#ifdef USE_OLD_ALGO
            LastReferenceNumber++;
            LastReferenceNumber++;
#else
            LastReferenceNumber = CreateFirstFreeRefId( idList, minRefId );
#endif
            aComponentsList[ii].m_NumRef = LastReferenceNumber;
            aComponentsList[ii].m_NumRef = LastReferenceNumber;


            if( !aComponentsList[ii].IsPartsLocked() )
            if( !aComponentsList[ii].IsPartsLocked() )
@@ -307,33 +428,6 @@ static void ComputeReferenceNumber( SCH_REFERENCE_LIST& aComponentsList, bool aU
}
}




/**
 * Search the last used (greatest) reference number in the component list
 * for the prefix reference given by Objet
 * The component list must be sorted.
 *
 * @param aObjet = reference item ( aComponentsList[aObjet].m_TextRef is
 *                 the search pattern)
 * @param aComponentsList = list of items
 */
int GetLastReferenceNumber( int aObjet,SCH_REFERENCE_LIST& aComponentsList )
{
    int LastNumber = 0;

    for( unsigned ii = 0; ii < aComponentsList.GetCount(); ii++ )
    {
        /* New identifier. */
        if( aComponentsList[aObjet].CompareRef( aComponentsList[ii] ) != 0 )
            continue;

        if( LastNumber < aComponentsList[ii].m_NumRef )
            LastNumber = aComponentsList[ii].m_NumRef;
    }

    return LastNumber;
}


/**
/**
 * Search in the sorted list of components, for a given component an other
 * Search in the sorted list of components, for a given component an other
 * component with the same reference and a given part unit.  Mainly used to
 * component with the same reference and a given part unit.  Mainly used to
@@ -391,7 +485,7 @@ static int ExistUnit( int aObjet, int Unit, SCH_REFERENCE_LIST& aComponentsList
 */
 */
int SCH_EDIT_FRAME::CheckAnnotate( wxArrayString* aMessageList, bool aOneSheetOnly )
int SCH_EDIT_FRAME::CheckAnnotate( wxArrayString* aMessageList, bool aOneSheetOnly )
{
{
    int            error;
    int            error = 0;
    wxString       Buff;
    wxString       Buff;
    wxString       msg, cmpref;
    wxString       msg, cmpref;


@@ -410,18 +504,15 @@ int SCH_EDIT_FRAME::CheckAnnotate( wxArrayString* aMessageList, bool aOneSheetOn


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


    /* count not yet annotated items */
    /* count not yet annotated items or annottaion error*/
    error = 0;
    for( unsigned ii = 0; ii < ComponentsList.GetCount(); ii++ )
    int imax = ComponentsList.GetCount() - 1;

    for( int ii = 0; ii < imax; ii++ )
    {
    {
        msg.Empty();
        msg.Empty();
        Buff.Empty();
        Buff.Empty();


        if( ComponentsList[ii].m_IsNew )
        if( ComponentsList[ii].m_IsNew )    // Not yet annotated
        {
        {
            if( ComponentsList[ii].m_NumRef >= 0 )
            if( ComponentsList[ii].m_NumRef >= 0 )
                Buff << ComponentsList[ii].m_NumRef;
                Buff << ComponentsList[ii].m_NumRef;
@@ -446,7 +537,8 @@ int SCH_EDIT_FRAME::CheckAnnotate( wxArrayString* aMessageList, bool aOneSheetOn
            break;
            break;
        }
        }


        // Annotate error
        // Annotate error if unit selected does not exist ( i.e. > number of parts )
        // Can happen if a component has changed in a lib, after a previous annotation
        if( MAX( ComponentsList[ii].m_Entry->GetPartCount(), 1 ) < ComponentsList[ii].m_Unit )
        if( MAX( ComponentsList[ii].m_Entry->GetPartCount(), 1 ) < ComponentsList[ii].m_Unit )
        {
        {
            if( ComponentsList[ii].m_NumRef >= 0 )
            if( ComponentsList[ii].m_NumRef >= 0 )
@@ -477,6 +569,7 @@ int SCH_EDIT_FRAME::CheckAnnotate( wxArrayString* aMessageList, bool aOneSheetOn
        return error;
        return error;


    // count the duplicated elements (if all are annotated)
    // count the duplicated elements (if all are annotated)
    int imax = ComponentsList.GetCount() - 1;
    for( int ii = 0; (ii < imax) && (error < 4); ii++ )
    for( int ii = 0; (ii < imax) && (error < 4); ii++ )
    {
    {
        msg.Empty();
        msg.Empty();
+33 −0
Original line number Original line Diff line number Diff line
@@ -226,6 +226,39 @@ public:
     *    When annotating,  some or all components are not annotated,
     *    When annotating,  some or all components are not annotated,
     *    i.e. ref is only U or R, with no number.
     *    i.e. ref is only U or R, with no number.
     */
     */


    /**
     * Function SplitReferences
     * attempts to split all reference designators into a name (U) and number (1).  If the
     * last character is '?' or not a digit, the reference is tagged as not annotated.
     * For components with multiple parts per package that are not already annotated, set
     * m_Unit to a max value (0x7FFFFFFF).
     * @see SCH_REFERENCE::Split()
     */
    void SplitReferences()
    {
        for( unsigned ii = 0; ii < GetCount(); ii++ )
            componentFlatList[ii].Split();
    }

    /**
     * function UpdateAnnotation
     * Update the reference components for the schematic project (or the current sheet)
     * Note: this function does not calculate the reference numbers
     * stored in m_NumRef
     * So, it must be called after calcultaion of new reference numbers
     * @see SCH_REFERENCE::Annotate()
     */
    void UpdateAnnotation()
    {
        /* update the reference numbers */
        for( unsigned ii = 0; ii < GetCount(); ii++ )
        {
            componentFlatList[ii].Annotate();
        }
    }

    /**
    /**
     * Function SortCmpByXCoordinate
     * Function SortCmpByXCoordinate
     * sort the flat list by X coordinates.
     * sort the flat list by X coordinates.