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_part( nullptr ),
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_libIdValidator( LIB_ID::ID_PCB ),
m_urlValidator( 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 );
}
@ -320,6 +320,11 @@ wxGridCellAttr* FIELDS_GRID_TABLE<T>::GetAttr( int aRow, int aCol, wxGridCellAtt
m_urlAttr->IncRef();
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 )
{
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." );
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 );
wxString sheetName = sheet->GetFields()[ SHEETNAME ].GetShownText();
m_nbsheets++;
wxTreeItemId menu;
menu = m_Tree->AppendItem( *aPreviousmenu, sheet->GetName(), 0, 1 );
menu = m_Tree->AppendItem( *aPreviousmenu, sheetName, 0, 1 );
aList->push_back( sheet );
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() )
{
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 )
{
std::vector< DANGLING_END_ITEM > endPoints;
@ -1065,7 +1081,7 @@ void SCH_SCREENS::ClearAnnotationOfNewSheetPaths( SCH_SHEET_LIST& aInitialSheetP
int SCH_SCREENS::ReplaceDuplicateTimeStamps()
{
EDA_ITEMS items;
std::vector<SCH_ITEM*> items;
int count = 0;
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 );
for( SCH_SCREEN* screen : m_screens )
screen->GetHierarchicalItems( items );
screen->GetHierarchicalItems( &items );
if( items.size() < 2 )
return 0;

View File

@ -392,8 +392,14 @@ public:
*
* @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.

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;
}
@ -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
wxString msgU, msgL;
msgU << _( "UUID" ) << ": " << m_Uuid.AsString();
msgL << _( "Path" ) << ": " <<g_CurrentSheet->PathHumanReadable();
msgL << _( "Path" ) << ": " << g_CurrentSheet->PathHumanReadable();
aList.push_back( MSG_PANEL_ITEM( msgU, msgL, BLUE ) );
#endif

View File

@ -163,7 +163,7 @@ wxString SCH_SHEET_PATH::PathHumanReadable() const
// Start at 1 to avoid the root sheet, as above.
for( unsigned i = 1; i < size(); i++ )
s = s + at( i )->GetName() + wxT( "/" );
s = s + at( i )->GetFields()[ SHEETNAME ].GetShownText() + wxT( "/" );
return s;
}
@ -364,7 +364,10 @@ void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet )
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 );

View File

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

View File

@ -36,6 +36,8 @@
#define FIELD_NAME -1
#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