From ac59a65d8d121e9d08c81c3e7941c1bca301d71a Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Wed, 29 May 2024 22:52:39 +0100 Subject: [PATCH] Resolve variables in LIB_SYMBOLs. Fixes https://gitlab.com/kicad/code/kicad/-/issues/18099 --- eeschema/lib_symbol.cpp | 101 ++++++++++++++++++++++++++++++++++++++++ eeschema/lib_symbol.h | 7 +++ eeschema/sch_field.cpp | 27 ++++++++--- 3 files changed, 128 insertions(+), 7 deletions(-) diff --git a/eeschema/lib_symbol.cpp b/eeschema/lib_symbol.cpp index 928de88695..4ff1b5ba9c 100644 --- a/eeschema/lib_symbol.cpp +++ b/eeschema/lib_symbol.cpp @@ -737,6 +737,107 @@ wxString LIB_SYMBOL::LetterSubReference( int aUnit, int aFirstId ) } +bool LIB_SYMBOL::ResolveTextVar( wxString* token, int aDepth ) const +{ + wxString footprint; + + for( const SCH_ITEM& item : m_drawings ) + { + if( item.Type() == SCH_FIELD_T ) + { + const SCH_FIELD& field = static_cast( item ); + + if( field.GetId() == FOOTPRINT_FIELD ) + footprint = field.GetShownText( nullptr, false, aDepth + 1 ); + + if( token->IsSameAs( field.GetCanonicalName().Upper() ) + || token->IsSameAs( field.GetName(), false ) ) + { + *token = field.GetShownText( nullptr, false, aDepth + 1 ); + return true; + } + } + } + + // Consider missing simulation fields as empty, not un-resolved + if( token->IsSameAs( wxT( "SIM.DEVICE" ) ) + || token->IsSameAs( wxT( "SIM.TYPE" ) ) + || token->IsSameAs( wxT( "SIM.PINS" ) ) + || token->IsSameAs( wxT( "SIM.PARAMS" ) ) + || token->IsSameAs( wxT( "SIM.LIBRARY" ) ) + || token->IsSameAs( wxT( "SIM.NAME" ) ) ) + { + *token = wxEmptyString; + return true; + } + + if( token->IsSameAs( wxT( "FOOTPRINT_LIBRARY" ) ) ) + { + wxArrayString parts = wxSplit( footprint, ':' ); + + if( parts.Count() > 0 ) + *token = parts[ 0 ]; + else + *token = wxEmptyString; + + return true; + } + else if( token->IsSameAs( wxT( "FOOTPRINT_NAME" ) ) ) + { + wxArrayString parts = wxSplit( footprint, ':' ); + + if( parts.Count() > 1 ) + *token = parts[ std::min( 1, (int) parts.size() - 1 ) ]; + else + *token = wxEmptyString; + + return true; + } + else if( token->IsSameAs( wxT( "SYMBOL_LIBRARY" ) ) ) + { + *token = m_libId.GetUniStringLibNickname(); + return true; + } + else if( token->IsSameAs( wxT( "SYMBOL_NAME" ) ) ) + { + *token = m_libId.GetUniStringLibItemName(); + return true; + } + else if( token->IsSameAs( wxT( "SYMBOL_DESCRIPTION" ) ) ) + { + *token = GetDescription(); + return true; + } + else if( token->IsSameAs( wxT( "SYMBOL_KEYWORDS" ) ) ) + { + *token = GetKeyWords(); + return true; + } + else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOM" ) ) ) + { + *token = this->GetExcludedFromBOM() ? _( "Excluded from BOM" ) : wxString( "" ); + return true; + } + else if( token->IsSameAs( wxT( "EXCLUDE_FROM_BOARD" ) ) ) + { + *token = this->GetExcludedFromBoard() ? _( "Excluded from board" ) : wxString( "" ); + return true; + } + else if( token->IsSameAs( wxT( "EXCLUDE_FROM_SIM" ) ) ) + { + *token = this->GetExcludedFromSim() ? _( "Excluded from simulation" ) : wxString( "" ); + return true; + } + else if( token->IsSameAs( wxT( "DNP" ) ) ) + { + *token = this->GetDNP() ? _( "DNP" ) : wxString( "" ); + return true; + } + + return false; +} + + void LIB_SYMBOL::Print( const SCH_RENDER_SETTINGS* aSettings, int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aForceNoFill, bool aDimmed ) { diff --git a/eeschema/lib_symbol.h b/eeschema/lib_symbol.h index 8280d24daf..e032bf2e2c 100644 --- a/eeschema/lib_symbol.h +++ b/eeschema/lib_symbol.h @@ -346,6 +346,13 @@ public: int GetNextAvailableFieldId() const; + /** + * Resolve any references to system tokens supported by the symbol. + * + * @param aDepth a counter to limit recursion and circular references. + */ + bool ResolveTextVar( wxString* token, int aDepth = 0 ) const; + void Print( const SCH_RENDER_SETTINGS* aSettings, int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aForceNoFill, bool aDimmed ) override; diff --git a/eeschema/sch_field.cpp b/eeschema/sch_field.cpp index 893b448a78..678d8aa04f 100644 --- a/eeschema/sch_field.cpp +++ b/eeschema/sch_field.cpp @@ -197,6 +197,13 @@ wxString SCH_FIELD::GetShownName() const wxString SCH_FIELD::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraText, int aDepth ) const { + std::function libSymbolResolver = + [&]( wxString* token ) -> bool + { + LIB_SYMBOL* symbol = static_cast( m_parent ); + return symbol->ResolveTextVar( token, aDepth + 1 ); + }; + std::function symbolResolver = [&]( wxString* token ) -> bool { @@ -207,6 +214,9 @@ wxString SCH_FIELD::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraT std::function schematicResolver = [&]( wxString* token ) -> bool { + if( !aPath ) + return false; + if( SCHEMATIC* schematic = Schematic() ) return schematic->ResolveTextVar( aPath, token, aDepth + 1 ); @@ -216,6 +226,9 @@ wxString SCH_FIELD::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraT std::function sheetResolver = [&]( wxString* token ) -> bool { + if( !aPath ) + return false; + SCH_SHEET* sheet = static_cast( m_parent ); SCHEMATIC* schematic = Schematic(); @@ -233,6 +246,9 @@ wxString SCH_FIELD::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraT std::function labelResolver = [&]( wxString* token ) -> bool { + if( !aPath ) + return false; + SCH_LABEL_BASE* label = static_cast( m_parent ); return label->ResolveTextVar( aPath, token, aDepth + 1 ); }; @@ -242,19 +258,16 @@ wxString SCH_FIELD::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraT if( IsNameShown() && aAllowExtraText ) text = GetShownName() << wxS( ": " ) << text; - if( !aPath ) - return text; - if( text == wxS( "~" ) ) // Legacy placeholder for empty string - { text = wxS( "" ); - } for( int ii = 0; ii < 10 && text.Contains( wxT( "${" ) ); ++ii ) { if( aDepth < 10 ) { - if( m_parent && m_parent->Type() == SCH_SYMBOL_T ) + if( m_parent && m_parent->Type() == LIB_SYMBOL_T ) + text = ExpandTextVars( text, &libSymbolResolver ); + else if( m_parent && m_parent->Type() == SCH_SYMBOL_T ) text = ExpandTextVars( text, &symbolResolver ); else if( m_parent && m_parent->Type() == SCH_SHEET_T ) text = ExpandTextVars( text, &sheetResolver ); @@ -275,7 +288,7 @@ wxString SCH_FIELD::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraT { SCH_SYMBOL* parentSymbol = static_cast( m_parent ); - if( m_id == REFERENCE_FIELD ) + if( m_id == REFERENCE_FIELD && aPath ) { // For more than one part per package, we must add the part selection // A, B, ... or 1, 2, .. to the reference.