Add sheet number processing to sheet fields.

Also fixes a bug where we were depending on the old deque stuff's
deterministic traversal, which isn't provided by the new RTree stuff.

Fixes https://gitlab.com/kicad/code/kicad/issues/2433
This commit is contained in:
Jeff Young 2020-05-03 15:52:31 +01:00
parent 889b6cb1b1
commit 0370eff7ba
8 changed files with 95 additions and 17 deletions

View File

@ -74,12 +74,12 @@ FIELDS_GRID_TABLE<T>::FIELDS_GRID_TABLE( DIALOG_SHIM* aDialog, SCH_BASE_FRAME* a
m_mandatoryFieldCount( SHEET_MANDATORY_FIELDS ), m_mandatoryFieldCount( SHEET_MANDATORY_FIELDS ),
m_part( nullptr ), m_part( nullptr ),
m_fieldNameValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_NAME ), m_fieldNameValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_NAME ),
m_referenceValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), REFERENCE ), m_referenceValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), SHEETNAME_V ),
m_valueValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), VALUE ), m_valueValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), VALUE ),
m_libIdValidator( LIB_ID::ID_PCB ), m_libIdValidator( LIB_ID::ID_PCB ),
m_urlValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_VALUE ), m_urlValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_VALUE ),
m_nonUrlValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_VALUE ), m_nonUrlValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_VALUE ),
m_filepathValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), SHEETFILENAME ) m_filepathValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), SHEETFILENAME_V )
{ {
initGrid( aDialog ); initGrid( aDialog );
} }
@ -320,6 +320,11 @@ wxGridCellAttr* FIELDS_GRID_TABLE<T>::GetAttr( int aRow, int aCol, wxGridCellAtt
m_urlAttr->IncRef(); m_urlAttr->IncRef();
return m_urlAttr; return m_urlAttr;
} }
else if( m_parentType == SCH_SHEET_T && aRow == SHEETNAME )
{
m_referenceAttr->IncRef();
return m_referenceAttr;
}
else if( m_parentType == SCH_SHEET_T && aRow == SHEETFILENAME ) else if( m_parentType == SCH_SHEET_T && aRow == SHEETFILENAME )
{ {
m_filepathAttr->IncRef(); m_filepathAttr->IncRef();

View File

@ -160,12 +160,16 @@ void HIERARCHY_NAVIG_DLG::buildHierarchyTree( SCH_SHEET_PATH* aList, wxTreeItemI
{ {
wxCHECK_RET( m_nbsheets < NB_MAX_SHEET, "Maximum number of sheets exceeded." ); wxCHECK_RET( m_nbsheets < NB_MAX_SHEET, "Maximum number of sheets exceeded." );
for( auto aItem : aList->LastScreen()->Items().OfType( SCH_SHEET_T ) ) std::vector<SCH_ITEM*> sheetChildren;
aList->LastScreen()->GetSheets( &sheetChildren );
for( SCH_ITEM* aItem : sheetChildren )
{ {
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem ); SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
wxString sheetName = sheet->GetFields()[ SHEETNAME ].GetShownText();
m_nbsheets++; m_nbsheets++;
wxTreeItemId menu; wxTreeItemId menu;
menu = m_Tree->AppendItem( *aPreviousmenu, sheet->GetName(), 0, 1 ); menu = m_Tree->AppendItem( *aPreviousmenu, sheetName, 0, 1 );
aList->push_back( sheet ); aList->push_back( sheet );
m_Tree->SetItemData( menu, new TreeItemData( *aList ) ); m_Tree->SetItemData( menu, new TreeItemData( *aList ) );

View File

@ -759,16 +759,32 @@ void SCH_SCREEN::EnsureAlternateReferencesExist()
} }
void SCH_SCREEN::GetHierarchicalItems( EDA_ITEMS& aItems ) void SCH_SCREEN::GetHierarchicalItems( std::vector<SCH_ITEM*>* aItems )
{ {
for( SCH_ITEM* item : Items() ) for( SCH_ITEM* item : Items() )
{ {
if( ( item->Type() == SCH_SHEET_T ) || ( item->Type() == SCH_COMPONENT_T ) ) if( ( item->Type() == SCH_SHEET_T ) || ( item->Type() == SCH_COMPONENT_T ) )
aItems.push_back( item ); aItems->push_back( item );
} }
} }
void SCH_SCREEN::GetSheets( std::vector<SCH_ITEM*>* aItems )
{
for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
aItems->push_back( item );
std::sort( aItems->begin(), aItems->end(),
[]( EDA_ITEM* a, EDA_ITEM* b ) -> bool
{
if( a->GetPosition().x == b->GetPosition().x )
return a->GetPosition().y < b->GetPosition().y;
else
return a->GetPosition().x < b->GetPosition().x;
} );
}
bool SCH_SCREEN::TestDanglingEnds( const SCH_SHEET_PATH* aPath ) bool SCH_SCREEN::TestDanglingEnds( const SCH_SHEET_PATH* aPath )
{ {
std::vector< DANGLING_END_ITEM > endPoints; std::vector< DANGLING_END_ITEM > endPoints;
@ -1065,7 +1081,7 @@ void SCH_SCREENS::ClearAnnotationOfNewSheetPaths( SCH_SHEET_LIST& aInitialSheetP
int SCH_SCREENS::ReplaceDuplicateTimeStamps() int SCH_SCREENS::ReplaceDuplicateTimeStamps()
{ {
EDA_ITEMS items; std::vector<SCH_ITEM*> items;
int count = 0; int count = 0;
auto timestamp_cmp = []( const EDA_ITEM* a, const EDA_ITEM* b ) -> bool auto timestamp_cmp = []( const EDA_ITEM* a, const EDA_ITEM* b ) -> bool
@ -1076,7 +1092,7 @@ int SCH_SCREENS::ReplaceDuplicateTimeStamps()
std::set<EDA_ITEM*, decltype( timestamp_cmp )> unique_stamps( timestamp_cmp ); std::set<EDA_ITEM*, decltype( timestamp_cmp )> unique_stamps( timestamp_cmp );
for( SCH_SCREEN* screen : m_screens ) for( SCH_SCREEN* screen : m_screens )
screen->GetHierarchicalItems( items ); screen->GetHierarchicalItems( &items );
if( items.size() < 2 ) if( items.size() < 2 )
return 0; return 0;

View File

@ -392,8 +392,14 @@ public:
* *
* @param aItems Hierarchical item list to fill. * @param aItems Hierarchical item list to fill.
*/ */
void GetHierarchicalItems( EDA_ITEMS& aItems ); void GetHierarchicalItems( std::vector<SCH_ITEM*>* aItems );
/**
* Similar to GetItems().OfType( SCH_SHEET_T ), but return the sheets in a
* deterministic order (L-R, T-B) for sheet numbering.
* @param aItems
*/
void GetSheets( std::vector<SCH_ITEM*>* aItems );
/** /**
* Return a line item located at \a aPosition. * Return a line item located at \a aPosition.

View File

@ -228,6 +228,26 @@ bool SCH_SHEET::ResolveTextVar( wxString* token, int aDepth ) const
} }
} }
if( token->IsSameAs( wxT( "#" ) ) )
{
SCH_SHEET_LIST sheetList( g_RootSheet );
for( const SCH_SHEET_PATH& sheet : sheetList )
{
if( sheet.Last() == this ) // Current sheet path found
{
*token = wxString::Format( wxT( "%d" ), sheet.GetPageNumber() );
return true;
}
}
}
else if( token->IsSameAs( wxT( "##" ) ) )
{
SCH_SHEET_LIST sheetList( g_RootSheet );
*token = wxString::Format( wxT( "%d" ), (int) sheetList.size() );
return true;
}
return false; return false;
} }
@ -705,7 +725,7 @@ void SCH_SHEET::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, MSG_PANEL_ITEMS& aList
#if 1 // Set to 1 to display the sheet UUID and hierarchical path #if 1 // Set to 1 to display the sheet UUID and hierarchical path
wxString msgU, msgL; wxString msgU, msgL;
msgU << _( "UUID" ) << ": " << m_Uuid.AsString(); msgU << _( "UUID" ) << ": " << m_Uuid.AsString();
msgL << _( "Path" ) << ": " <<g_CurrentSheet->PathHumanReadable(); msgL << _( "Path" ) << ": " << g_CurrentSheet->PathHumanReadable();
aList.push_back( MSG_PANEL_ITEM( msgU, msgL, BLUE ) ); aList.push_back( MSG_PANEL_ITEM( msgU, msgL, BLUE ) );
#endif #endif

View File

@ -163,7 +163,7 @@ wxString SCH_SHEET_PATH::PathHumanReadable() const
// Start at 1 to avoid the root sheet, as above. // Start at 1 to avoid the root sheet, as above.
for( unsigned i = 1; i < size(); i++ ) for( unsigned i = 1; i < size(); i++ )
s = s + at( i )->GetName() + wxT( "/" ); s = s + at( i )->GetFields()[ SHEETNAME ].GetShownText() + wxT( "/" );
return s; return s;
} }
@ -364,7 +364,10 @@ void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet )
if( m_currentSheetPath.LastScreen() ) if( m_currentSheetPath.LastScreen() )
{ {
for( auto item : m_currentSheetPath.LastScreen()->Items().OfType( SCH_SHEET_T ) ) std::vector<SCH_ITEM*> childSheets;
m_currentSheetPath.LastScreen()->GetSheets( &childSheets );
for( SCH_ITEM* item : childSheets )
{ {
auto sheet = static_cast<SCH_SHEET*>( item ); auto sheet = static_cast<SCH_SHEET*>( item );

View File

@ -44,15 +44,27 @@ SCH_FIELD_VALIDATOR::SCH_FIELD_VALIDATOR( bool aIsLibEditor, int aFieldId, wxSt
// The reference field cannot contain spaces. // The reference field cannot contain spaces.
if( aFieldId == REFERENCE ) if( aFieldId == REFERENCE )
{
excludes += " "; excludes += " ";
else if( aFieldId == VALUE && m_isLibEditor ) }
else if( ( aFieldId == VALUE && m_isLibEditor )
|| aFieldId == SHEETNAME_V
|| aFieldId == SHEETFILENAME_V )
{
excludes += " :/\\"; excludes += " :/\\";
}
long style = GetStyle(); long style = GetStyle();
// The reference and value fields cannot be empty. // The reference, value sheetname and sheetfilename fields cannot be empty.
if( aFieldId == REFERENCE || aFieldId == VALUE || aFieldId == FIELD_NAME ) if( aFieldId == REFERENCE
|| aFieldId == VALUE
|| aFieldId == SHEETNAME_V
|| aFieldId == SHEETFILENAME_V
|| aFieldId == FIELD_NAME )
{
style |= wxFILTER_EMPTY; style |= wxFILTER_EMPTY;
}
SetStyle( style ); SetStyle( style );
SetCharExcludes( excludes ); SetCharExcludes( excludes );
@ -101,6 +113,14 @@ bool SCH_FIELD_VALIDATOR::Validate( wxWindow *aParent )
fieldCharError = _( "The datasheet field cannot contain %s character(s)." ); fieldCharError = _( "The datasheet field cannot contain %s character(s)." );
break; break;
case SHEETNAME_V:
fieldCharError = _( "The sheet name cannot contain %s character(s)." );
break;
case SHEETFILENAME_V:
fieldCharError = _( "The sheet filename cannot contain %s character(s)." );
break;
default: default:
fieldCharError = _( "The field cannot contain %s character(s)." ); fieldCharError = _( "The field cannot contain %s character(s)." );
break; break;
@ -121,8 +141,10 @@ bool SCH_FIELD_VALIDATOR::Validate( wxWindow *aParent )
else if( HasFlag( wxFILTER_EXCLUDE_CHAR_LIST ) && ContainsExcludedCharacters( val ) ) else if( HasFlag( wxFILTER_EXCLUDE_CHAR_LIST ) && ContainsExcludedCharacters( val ) )
{ {
wxArrayString whiteSpace; wxArrayString whiteSpace;
bool spaceIllegal = ( m_fieldId == REFERENCE ) || bool spaceIllegal = m_fieldId == REFERENCE
( m_fieldId == VALUE && m_isLibEditor ); || ( m_fieldId == VALUE && m_isLibEditor )
|| m_fieldId == SHEETNAME_V
|| m_fieldId == SHEETFILENAME_V;
if( val.Find( '\r' ) != wxNOT_FOUND ) if( val.Find( '\r' ) != wxNOT_FOUND )
whiteSpace.Add( _( "carriage return" ) ); whiteSpace.Add( _( "carriage return" ) );

View File

@ -36,6 +36,8 @@
#define FIELD_NAME -1 #define FIELD_NAME -1
#define FIELD_VALUE -2 #define FIELD_VALUE -2
#define SHEETNAME_V 100 // We can't use SHEETNAME and SHEETFILENAME because they
#define SHEETFILENAME_V 101 // overlap with REFERENCE and VALUE
/** /**
* A text control validator used for validating the text allowed in library and * A text control validator used for validating the text allowed in library and