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

Finish work to enhance annotation algorithm.

Fix a minor warning when starting Kicad in debug mode (wxWidgets 2.9.1 specific)
parent 92c69a9c
...@@ -680,7 +680,11 @@ bool WinEDA_App::SetLanguage( bool first_time ) ...@@ -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.") );
......
...@@ -19,14 +19,11 @@ ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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
* Update the reference component for the schematic project (or the current sheet) * 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 void ReAnnotateComponents( SCH_REFERENCE_LIST& aComponentList ) static int GetLastNumberInReference( int aObjet,SCH_REFERENCE_LIST& aComponentsList,
int aMinValue )
{ {
/* update the reference numbers */ int lastNumber = aMinValue;
for( unsigned ii = 0; ii < aComponentList.GetCount(); ii++ )
for( unsigned ii = 0; ii < aComponentsList.GetCount(); ii++ )
{ {
aComponentList[ii].Annotate(); // 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;
}
void BreakReference( SCH_REFERENCE_LIST& aComponentsList ) #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 BuildRefIdInUseList( int aObjet,SCH_REFERENCE_LIST& aComponentsList,
std::vector<int>& aIdList, int aMinRefId )
{ {
aIdList.clear();
for( unsigned ii = 0; ii < aComponentsList.GetCount(); ii++ ) for( unsigned ii = 0; ii < aComponentsList.GetCount(); ii++ )
aComponentsList[ii].Split(); {
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;
// We search for expectedId a value >= aFirstValue.
// Skip existing Id < aFirstValue
unsigned ii = 0;
for( ; ii < aIdList.size(); ii++ )
{
if( expectedId <= aIdList[ii] )
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 ) ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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();
......
...@@ -226,6 +226,39 @@ public: ...@@ -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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment