Comboboxes for units and body styles.

Also for pin-types in pad properties.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/19904

Fixes https://gitlab.com/kicad/code/kicad/-/issues/19905
This commit is contained in:
Jeff Young 2025-07-23 14:33:29 +01:00
parent c63e2edfff
commit ec155c00f3
35 changed files with 472 additions and 447 deletions

View File

@ -134,29 +134,12 @@ LIB_TREE_NODE::LIB_TREE_NODE()
LIB_TREE_NODE_UNIT::LIB_TREE_NODE_UNIT( LIB_TREE_NODE* aParent, LIB_TREE_ITEM* aItem, int aUnit )
{
static void* locale = nullptr;
static wxString namePrefix;
// Fetching translations can take a surprising amount of time when loading libraries,
// so only do it when necessary.
if( Pgm().GetLocale() != locale )
{
namePrefix = _( "Unit" );
locale = Pgm().GetLocale();
}
m_Parent = aParent;
m_Type = TYPE::UNIT;
m_Unit = aUnit;
m_LibId = aParent->m_LibId;
m_Name = namePrefix + " " + aItem->GetUnitReference( aUnit );
if( aItem->HasUnitDisplayName( aUnit ) )
m_Desc = aItem->GetUnitDisplayName( aUnit );
else
m_Desc = wxEmptyString;
m_Name = aItem->GetUnitName( aUnit );
m_IntrinsicRank = -aUnit;
}

View File

@ -55,6 +55,31 @@ enum class ELECTRICAL_PINTYPE
#define ELECTRICAL_PINTYPES_TOTAL ( static_cast<int>( ELECTRICAL_PINTYPE::PT_LAST_OPTION ) + 1 )
inline wxString GetCanonicalElectricalTypeName( ELECTRICAL_PINTYPE aType )
{
// These strings are the canonical name of the electrictal type
// Not translated, no space in name, only ASCII chars.
// to use when the string name must be known and well defined
// must have same order than enum ELECTRICAL_PINTYPE (see sch_pin.h)
static const wxChar* msgPinElectricType[] =
{
wxT( "input" ),
wxT( "output" ),
wxT( "bidirectional" ),
wxT( "tri_state" ),
wxT( "passive" ),
wxT( "free" ),
wxT( "unspecified" ),
wxT( "power_in" ),
wxT( "power_out" ),
wxT( "open_collector" ),
wxT( "open_emitter" ),
wxT( "no_connect" )
};
return msgPinElectricType[static_cast<int>( aType )];
}
enum class GRAPHIC_PINSHAPE
{
LINE,

View File

@ -25,10 +25,15 @@
#include <properties/property.h>
#include <algorithm>
#include <ranges>
#include <utility>
#include <wx/wx.h>
static wxString EMPTY_STRING( wxEmptyString );
// Global to prevent simultaneous multi-threaded static initialization
static const std::vector<PROPERTY_BASE*> EMPTY_PROP_LIST;
static const std::map<PROPERTY_BASE*, int> EMPTY_PROP_DISPLAY_ORDER;
std::vector<wxString> EMPTY_GROUP_DISPLAY_ORDER;
void PROPERTY_MANAGER::RegisterType( TYPE_ID aType, const wxString& aName )
@ -38,13 +43,6 @@ void PROPERTY_MANAGER::RegisterType( TYPE_ID aType, const wxString& aName )
}
const wxString& PROPERTY_MANAGER::ResolveType( TYPE_ID aType ) const
{
auto it = m_classNames.find( aType );
return it != m_classNames.end() ? it->second : EMPTY_STRING;
}
PROPERTY_BASE* PROPERTY_MANAGER::GetProperty( TYPE_ID aType, const wxString& aProperty ) const
{
if( m_dirty )
@ -67,31 +65,29 @@ PROPERTY_BASE* PROPERTY_MANAGER::GetProperty( TYPE_ID aType, const wxString& aPr
}
const PROPERTY_LIST& PROPERTY_MANAGER::GetProperties( TYPE_ID aType ) const
const std::vector<PROPERTY_BASE*>& PROPERTY_MANAGER::GetProperties( TYPE_ID aType ) const
{
if( m_dirty )
const_cast<PROPERTY_MANAGER*>( this )->Rebuild();
static const PROPERTY_LIST empty;
auto it = m_classes.find( aType );
if( it == m_classes.end() )
return empty;
return EMPTY_PROP_LIST;
return it->second.m_allProperties;
}
const PROPERTY_DISPLAY_ORDER& PROPERTY_MANAGER::GetDisplayOrder( TYPE_ID aType ) const
const std::map<PROPERTY_BASE*, int>& PROPERTY_MANAGER::GetDisplayOrder( TYPE_ID aType ) const
{
if( m_dirty )
const_cast<PROPERTY_MANAGER*>( this )->Rebuild();
static const PROPERTY_DISPLAY_ORDER empty;
auto it = m_classes.find( aType );
if( it == m_classes.end() )
return empty;
return EMPTY_PROP_DISPLAY_ORDER;
return it->second.m_displayOrder;
}
@ -102,11 +98,10 @@ const std::vector<wxString>& PROPERTY_MANAGER::GetGroupDisplayOrder( TYPE_ID aTy
if( m_dirty )
const_cast<PROPERTY_MANAGER*>( this )->Rebuild();
static const std::vector<wxString> empty;
auto it = m_classes.find( aType );
if( it == m_classes.end() )
return empty;
return EMPTY_GROUP_DISPLAY_ORDER;
return it->second.m_groupDisplayOrder;
}
@ -122,7 +117,7 @@ const void* PROPERTY_MANAGER::TypeCast( const void* aSource, TYPE_ID aBase, TYPE
if( classDesc == m_classes.end() )
return aSource;
auto& converters = classDesc->second.m_typeCasts;
const std::map<TYPE_ID, std::unique_ptr<TYPE_CAST_BASE>>& converters = classDesc->second.m_typeCasts;
auto converter = converters.find( aTarget );
if( converter == converters.end() ) // explicit type cast not found
@ -135,8 +130,9 @@ const void* PROPERTY_MANAGER::TypeCast( const void* aSource, TYPE_ID aBase, TYPE
PROPERTY_BASE& PROPERTY_MANAGER::AddProperty( PROPERTY_BASE* aProperty, const wxString& aGroup )
{
const wxString& name = aProperty->Name();
TYPE_ID hash = aProperty->OwnerHash();
CLASS_DESC& classDesc = getClass( hash );
TYPE_ID hash = aProperty->OwnerHash();
CLASS_DESC& classDesc = getClass( hash );
classDesc.m_ownProperties.emplace( name, aProperty );
classDesc.m_ownDisplayOrder.emplace_back( aProperty );
@ -153,8 +149,8 @@ PROPERTY_BASE& PROPERTY_MANAGER::AddProperty( PROPERTY_BASE* aProperty, const wx
}
PROPERTY_BASE& PROPERTY_MANAGER::ReplaceProperty( size_t aBase, const wxString& aName,
PROPERTY_BASE* aNew, const wxString& aGroup )
PROPERTY_BASE& PROPERTY_MANAGER::ReplaceProperty( size_t aBase, const wxString& aName, PROPERTY_BASE* aNew,
const wxString& aGroup )
{
CLASS_DESC& classDesc = getClass( aNew->OwnerHash() );
classDesc.m_replaced.insert( std::make_pair( aBase, aName ) );
@ -164,31 +160,30 @@ PROPERTY_BASE& PROPERTY_MANAGER::ReplaceProperty( size_t aBase, const wxString&
void PROPERTY_MANAGER::AddTypeCast( TYPE_CAST_BASE* aCast )
{
TYPE_ID derivedHash = aCast->DerivedHash();
TYPE_ID derivedHash = aCast->DerivedHash();
CLASS_DESC& classDesc = getClass( aCast->BaseHash() );
auto& typeCasts = classDesc.m_typeCasts;
wxASSERT_MSG( typeCasts.count( derivedHash ) == 0, "Such converter already exists" );
typeCasts.emplace( derivedHash, aCast );
wxASSERT_MSG( classDesc.m_typeCasts.count( derivedHash ) == 0, wxT( "Such converter already exists" ) );
classDesc.m_typeCasts.emplace( derivedHash, aCast );
}
void PROPERTY_MANAGER::InheritsAfter( TYPE_ID aDerived, TYPE_ID aBase )
{
wxASSERT_MSG( aDerived != aBase, "Class cannot inherit from itself" );
wxASSERT_MSG( aDerived != aBase, wxT( "Class cannot inherit from itself" ) );
CLASS_DESC& derived = getClass( aDerived );
CLASS_DESC& base = getClass( aBase );
derived.m_bases.push_back( base );
derived.m_bases.push_back( getClass( aBase ) );
m_dirty = true;
wxASSERT_MSG( derived.m_bases.size() == 1 || derived.m_typeCasts.count( aBase ) == 1,
"You need to add a TYPE_CAST for classes inheriting from multiple bases" );
wxT( "You need to add a TYPE_CAST for classes inheriting from multiple bases" ) );
}
void PROPERTY_MANAGER::Mask( TYPE_ID aDerived, TYPE_ID aBase, const wxString& aName )
{
wxASSERT_MSG( aDerived != aBase, "Class cannot mask from itself" );
wxASSERT_MSG( aDerived != aBase, wxT( "Class cannot mask from itself" ) );
CLASS_DESC& derived = getClass( aDerived );
derived.m_maskedBaseProperties.insert( std::make_pair( aBase, aName ) );
@ -196,11 +191,10 @@ void PROPERTY_MANAGER::Mask( TYPE_ID aDerived, TYPE_ID aBase, const wxString& aN
}
void PROPERTY_MANAGER::OverrideAvailability( TYPE_ID aDerived, TYPE_ID aBase,
const wxString& aName,
void PROPERTY_MANAGER::OverrideAvailability( TYPE_ID aDerived, TYPE_ID aBase, const wxString& aName,
std::function<bool( INSPECTABLE* )> aFunc )
{
wxASSERT_MSG( aDerived != aBase, "Class cannot override from itself" );
wxASSERT_MSG( aDerived != aBase, wxT( "Class cannot override from itself" ) );
CLASS_DESC& derived = getClass( aDerived );
derived.m_availabilityOverrides[std::make_pair( aBase, aName )] = std::move( aFunc );
@ -208,11 +202,10 @@ void PROPERTY_MANAGER::OverrideAvailability( TYPE_ID aDerived, TYPE_ID aBase,
}
void PROPERTY_MANAGER::OverrideWriteability( TYPE_ID aDerived, TYPE_ID aBase,
const wxString& aName,
void PROPERTY_MANAGER::OverrideWriteability( TYPE_ID aDerived, TYPE_ID aBase, const wxString& aName,
std::function<bool( INSPECTABLE* )> aFunc )
{
wxASSERT_MSG( aDerived != aBase, "Class cannot override from itself" );
wxASSERT_MSG( aDerived != aBase, wxT( "Class cannot override from itself" ) );
CLASS_DESC& derived = getClass( aDerived );
derived.m_writeabilityOverrides[std::make_pair( aBase, aName )] = std::move( aFunc );
@ -220,16 +213,14 @@ void PROPERTY_MANAGER::OverrideWriteability( TYPE_ID aDerived, TYPE_ID aBase,
}
bool PROPERTY_MANAGER::IsAvailableFor( TYPE_ID aItemClass, PROPERTY_BASE* aProp,
INSPECTABLE* aItem )
bool PROPERTY_MANAGER::IsAvailableFor( TYPE_ID aItemClass, PROPERTY_BASE* aProp, INSPECTABLE* aItem )
{
if( !aProp->Available( aItem ) )
return false;
CLASS_DESC& derived = getClass( aItemClass );
auto it = derived.m_availabilityOverrides.find( std::make_pair( aProp->BaseHash(),
aProp->Name() ) );
auto it = derived.m_availabilityOverrides.find( std::make_pair( aProp->BaseHash(), aProp->Name() ) );
if( it != derived.m_availabilityOverrides.end() )
return it->second( aItem );
@ -238,16 +229,14 @@ bool PROPERTY_MANAGER::IsAvailableFor( TYPE_ID aItemClass, PROPERTY_BASE* aProp,
}
bool PROPERTY_MANAGER::IsWriteableFor( TYPE_ID aItemClass, PROPERTY_BASE* aProp,
INSPECTABLE* aItem )
bool PROPERTY_MANAGER::IsWriteableFor( TYPE_ID aItemClass, PROPERTY_BASE* aProp, INSPECTABLE* aItem )
{
if( !aProp->Writeable( aItem ) )
return false;
CLASS_DESC& derived = getClass( aItemClass );
auto it = derived.m_writeabilityOverrides.find( std::make_pair( aProp->BaseHash(),
aProp->Name() ) );
auto it = derived.m_writeabilityOverrides.find( std::make_pair( aProp->BaseHash(), aProp->Name() ) );
if( it != derived.m_writeabilityOverrides.end() )
return it->second( aItem );
@ -265,7 +254,7 @@ bool PROPERTY_MANAGER::IsOfType( TYPE_ID aDerived, TYPE_ID aBase ) const
wxCHECK( derived != m_classes.end(), false ); // missing class description
// traverse the hierarchy seeking for the base class
for( auto& base : derived->second.m_bases )
for( const std::reference_wrapper<CLASS_DESC>& base : derived->second.m_bases )
{
if( IsOfType( base.get().m_id, aBase ) )
return true;
@ -297,8 +286,8 @@ PROPERTY_MANAGER::CLASS_DESC& PROPERTY_MANAGER::getClass( TYPE_ID aTypeId )
void PROPERTY_MANAGER::CLASS_DESC::rebuild()
{
PROPERTY_SET replaced;
PROPERTY_SET masked;
std::set<std::pair<size_t, wxString>> replaced;
std::set<std::pair<size_t, wxString>> masked;
m_allProperties.clear();
collectPropsRecur( m_allProperties, replaced, m_displayOrder, masked );
@ -338,10 +327,10 @@ void PROPERTY_MANAGER::CLASS_DESC::rebuild()
}
void PROPERTY_MANAGER::CLASS_DESC::collectPropsRecur( PROPERTY_LIST& aResult,
PROPERTY_SET& aReplaced,
PROPERTY_DISPLAY_ORDER& aDisplayOrder,
PROPERTY_SET& aMasked ) const
void PROPERTY_MANAGER::CLASS_DESC::collectPropsRecur( std::vector<PROPERTY_BASE*>& aResult,
std::set<std::pair<size_t, wxString>>& aReplaced,
std::map<PROPERTY_BASE*, int>& aDisplayOrder,
std::set<std::pair<size_t, wxString>>& aMasked ) const
{
for( const std::pair<size_t, wxString>& replacedEntry : m_replaced )
aReplaced.emplace( replacedEntry );
@ -371,8 +360,8 @@ void PROPERTY_MANAGER::CLASS_DESC::collectPropsRecur( PROPERTY_LIST& aResult,
for( PROPERTY_BASE* property : m_ownDisplayOrder )
{
PROPERTY_SET::key_type propertyKey = std::make_pair( property->OwnerHash(),
property->Name() );
std::set<std::pair<size_t, wxString>>::key_type propertyKey = std::make_pair( property->OwnerHash(),
property->Name() );
// Do not store replaced properties
if( aReplaced.count( propertyKey ) )
continue;
@ -386,28 +375,8 @@ void PROPERTY_MANAGER::CLASS_DESC::collectPropsRecur( PROPERTY_LIST& aResult,
}
// Iterate backwards so that replaced properties appear before base properties
for( auto it = m_bases.rbegin(); it != m_bases.rend(); ++it )
it->get().collectPropsRecur( aResult, aReplaced, aDisplayOrder, aMasked );
}
std::vector<TYPE_ID> PROPERTY_MANAGER::GetMatchingClasses( PROPERTY_BASE* aProperty )
{
std::vector<TYPE_ID> ids;
/*
for( auto& cls : m_classes )
{
CLASS_INFO info;
for( auto prop : cls.second.m_allProperties )
info.properties.push_back(prop);
}
*/
return ids;
for( std::reference_wrapper<CLASS_DESC> base : std::ranges::reverse_view( m_bases ) )
base.get().collectPropsRecur( aResult, aReplaced, aDisplayOrder, aMasked );
}
@ -458,7 +427,7 @@ void PROPERTY_MANAGER::PropertyChanged( INSPECTABLE* aObject, PROPERTY_BASE* aPr
PROPERTY_COMMIT_HANDLER::PROPERTY_COMMIT_HANDLER( COMMIT* aCommit )
{
wxCHECK2_MSG( PROPERTY_MANAGER::Instance().m_managedCommit == nullptr,
return, "Can't have more than one managed commit at a time!" );
return, wxT( "Can't have more than one managed commit at a time!" ) );
PROPERTY_MANAGER::Instance().m_managedCommit = aCommit;
}
@ -467,7 +436,7 @@ PROPERTY_COMMIT_HANDLER::PROPERTY_COMMIT_HANDLER( COMMIT* aCommit )
PROPERTY_COMMIT_HANDLER::~PROPERTY_COMMIT_HANDLER()
{
wxASSERT_MSG( PROPERTY_MANAGER::Instance().m_managedCommit != nullptr,
"Something went wrong: m_managedCommit already null!" );
wxT( "Something went wrong: m_managedCommit already null!" ) );
PROPERTY_MANAGER::Instance().m_managedCommit = nullptr;
}

View File

@ -122,17 +122,14 @@ PROPERTIES_PANEL::PROPERTIES_PANEL( wxWindow* aParent, EDA_BASE_FRAME* aFrame )
m_grid->CenterSplitter();
Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( PROPERTIES_PANEL::onCharHook ), nullptr, this );
Connect( wxEVT_PG_CHANGED, wxPropertyGridEventHandler( PROPERTIES_PANEL::valueChanged ),
nullptr, this );
Connect( wxEVT_PG_CHANGING, wxPropertyGridEventHandler( PROPERTIES_PANEL::valueChanging ),
nullptr, this );
Connect( wxEVT_PG_CHANGED, wxPropertyGridEventHandler( PROPERTIES_PANEL::valueChanged ), nullptr, this );
Connect( wxEVT_PG_CHANGING, wxPropertyGridEventHandler( PROPERTIES_PANEL::valueChanging ), nullptr, this );
Connect( wxEVT_SHOW, wxShowEventHandler( PROPERTIES_PANEL::onShow ), nullptr, this );
Bind( wxEVT_PG_COL_END_DRAG,
[&]( wxPropertyGridEvent& )
{
m_splitter_key_proportion =
static_cast<float>( m_grid->GetSplitterPosition() ) / m_grid->GetSize().x;
m_splitter_key_proportion = static_cast<float>( m_grid->GetSplitterPosition() ) / m_grid->GetSize().x;
} );
Bind( wxEVT_SIZE,
@ -225,33 +222,27 @@ void PROPERTIES_PANEL::rebuildProperties( const SELECTION& aSelection )
wxCHECK( !types.empty(), /* void */ ); // already guarded above, but Coverity doesn't know that
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
std::set<PROPERTY_BASE*> commonProps;
const PROPERTY_LIST& allProperties = propMgr.GetProperties( *types.begin() );
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
std::set<PROPERTY_BASE*> commonProps;
const std::vector<PROPERTY_BASE*>& allProperties = propMgr.GetProperties( *types.begin() );
copy( allProperties.begin(), allProperties.end(),
inserter( commonProps, commonProps.begin() ) );
copy( allProperties.begin(), allProperties.end(), inserter( commonProps, commonProps.begin() ) );
PROPERTY_DISPLAY_ORDER displayOrder = propMgr.GetDisplayOrder( *types.begin() );
std::vector<wxString> groupDisplayOrder = propMgr.GetGroupDisplayOrder( *types.begin() );
std::set<wxString> groups( groupDisplayOrder.begin(), groupDisplayOrder.end() );
std::map<PROPERTY_BASE*, int> displayOrder = propMgr.GetDisplayOrder( *types.begin() );
std::vector<wxString> groupDisplayOrder = propMgr.GetGroupDisplayOrder( *types.begin() );
std::set<wxString> groups( groupDisplayOrder.begin(), groupDisplayOrder.end() );
std::set<PROPERTY_BASE*> availableProps;
// Get all possible properties
for( const TYPE_ID& type : types )
{
const PROPERTY_LIST& itemProps = propMgr.GetProperties( type );
const std::vector<PROPERTY_BASE*>& itemProps = propMgr.GetProperties( type );
const std::map<PROPERTY_BASE*, int>& itemDisplayOrder = propMgr.GetDisplayOrder( type );
const PROPERTY_DISPLAY_ORDER& itemDisplayOrder = propMgr.GetDisplayOrder( type );
copy( itemDisplayOrder.begin(), itemDisplayOrder.end(), inserter( displayOrder, displayOrder.begin() ) );
copy( itemDisplayOrder.begin(), itemDisplayOrder.end(),
inserter( displayOrder, displayOrder.begin() ) );
const std::vector<wxString>& itemGroups = propMgr.GetGroupDisplayOrder( type );
for( const wxString& group : itemGroups )
for( const wxString& group : propMgr.GetGroupDisplayOrder( type ) )
{
if( !groups.count( group ) )
{
@ -305,9 +296,10 @@ void PROPERTIES_PANEL::rebuildProperties( const SELECTION& aSelection )
if( !property )
continue;
wxVariant commonVal;
wxVariant commonVal;
wxPGChoices choices;
extractValueAndWritability( aSelection, property, commonVal, writeable );
extractValueAndWritability( aSelection, property, commonVal, writeable, choices );
pgProp->SetValue( commonVal );
pgProp->Enable( writeable );
@ -326,13 +318,17 @@ void PROPERTIES_PANEL::rebuildProperties( const SELECTION& aSelection )
for( PROPERTY_BASE* property : availableProps )
{
wxPGProperty* pgProp = createPGProperty( property );
wxVariant commonVal;
wxVariant commonVal;
wxPGChoices choices;
if( !extractValueAndWritability( aSelection, property, commonVal, writeable ) )
if( !extractValueAndWritability( aSelection, property, commonVal, writeable, choices ) )
continue;
if( pgProp )
{
if( choices.GetCount() )
pgProp->SetChoices( choices );
pgProp->SetValue( commonVal );
pgProp->Enable( writeable );
m_displayed.push_back( property );
@ -403,13 +399,12 @@ bool PROPERTIES_PANEL::getItemValue( EDA_ITEM* aItem, PROPERTY_BASE* aProperty,
}
bool PROPERTIES_PANEL::extractValueAndWritability( const SELECTION& aSelection,
PROPERTY_BASE* aProperty,
wxVariant& aValue, bool& aWritable )
bool PROPERTIES_PANEL::extractValueAndWritability( const SELECTION& aSelection, PROPERTY_BASE* aProperty,
wxVariant& aValue, bool& aWritable, wxPGChoices& aChoices )
{
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
bool different = false;
wxVariant commonVal;
bool first = true;
aWritable = true;
@ -421,6 +416,22 @@ bool PROPERTIES_PANEL::extractValueAndWritability( const SELECTION& aSelection,
if( aProperty->IsHiddenFromPropertiesManager() )
return false;
wxPGChoices choices = aProperty->GetChoices( item );
if( first )
{
aChoices = choices;
first = false;
}
else
{
wxArrayString labels = choices.GetLabels();
wxArrayInt values = choices.GetValuesForStrings( labels );
if( labels != aChoices.GetLabels() || values != aChoices.GetValuesForStrings( labels ) )
return false;
}
// If read-only for any of the selection, read-only for the whole selection.
if( !propMgr.IsWriteableFor( TYPE_HASH( *item ), aProperty, item ) )
aWritable = false;

View File

@ -102,7 +102,7 @@ protected:
* @return true if the property is available for all the items in the selection
*/
bool extractValueAndWritability( const SELECTION& aSelection, PROPERTY_BASE* aProperty,
wxVariant& aValue, bool& aWritable );
wxVariant& aValue, bool& aWritable, wxPGChoices& aChoices );
public:
int m_SuppressGridChangeEvents;

View File

@ -445,12 +445,7 @@ bool DIALOG_FIELD_PROPERTIES::TransferDataToWindow()
const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( parent );
for( int ii = 1; ii <= symbol->GetUnitCount(); ii++ )
{
if( symbol->HasUnitDisplayName( ii ) )
m_unitChoice->Append( symbol->GetUnitDisplayName( ii ) );
else
m_unitChoice->Append( symbol->SubReference( ii, false ) );
}
m_unitChoice->Append( symbol->GetUnitDisplayName( ii, false ) );
if( symbol->GetUnit() <= (int) m_unitChoice->GetCount() )
m_unitChoice->SetSelection( symbol->GetUnit() - 1 );

View File

@ -1143,7 +1143,7 @@ DIALOG_LIB_EDIT_PIN_TABLE::DIALOG_LIB_EDIT_PIN_TABLE( SYMBOL_EDIT_FRAME* parent,
m_unitFilter->Append( wxGetTranslation( UNITS_ALL ) );
for( int ii = 0; ii < aSymbol->GetUnitCount(); ++ii )
m_unitFilter->Append( aSymbol->GetUnitReference( ii + 1 ) );
m_unitFilter->Append( LIB_SYMBOL::LetterSubReference( ii + 1, 'A' ) );
m_unitFilter->SetSelection( -1 );
}

View File

@ -483,12 +483,7 @@ bool DIALOG_SYMBOL_PROPERTIES::TransferDataToWindow()
m_symbol->SetUnit( m_symbol->GetUnitSelection( &GetParent()->GetCurrentSheet() ) );
for( int ii = 1; ii <= m_symbol->GetUnitCount(); ii++ )
{
if( m_symbol->HasUnitDisplayName( ii ) )
m_unitChoice->Append( m_symbol->GetUnitDisplayName( ii ) );
else
m_unitChoice->Append( m_symbol->SubReference( ii, false ) );
}
m_unitChoice->Append( m_symbol->GetUnitDisplayName( ii, false ) );
if( m_symbol->GetUnit() <= ( int )m_unitChoice->GetCount() )
m_unitChoice->SetSelection( m_symbol->GetUnit() - 1 );

View File

@ -575,11 +575,11 @@ int ERC_TESTER::TestMissingUnits()
{
if( ii++ == 3 )
{
missing_pin_units += wxS( "....." );
missing_pin_units += wxS( "..." );
break;
}
missing_pin_units += libSymbol->GetUnitDisplayName( missing_unit ) + ", " ;
missing_pin_units += libSymbol->GetUnitDisplayName( missing_unit, false ) + ", " ;
}
missing_pin_units.Truncate( missing_pin_units.length() - 2 );

View File

@ -286,24 +286,31 @@ LIB_SYMBOL_SPTR LIB_SYMBOL::GetRootSymbol() const
}
wxString LIB_SYMBOL::GetUnitReference( int aUnit )
{
return LIB_SYMBOL::LetterSubReference( aUnit, 'A' );
}
bool LIB_SYMBOL::HasUnitDisplayName( int aUnit )
bool LIB_SYMBOL::HasUnitDisplayName( int aUnit ) const
{
return ( m_unitDisplayNames.count( aUnit ) == 1 );
}
wxString LIB_SYMBOL::GetUnitDisplayName( int aUnit )
wxString LIB_SYMBOL::GetUnitDisplayName( int aUnit, bool aLabel ) const
{
if( HasUnitDisplayName( aUnit ) )
return m_unitDisplayNames[aUnit];
if( m_unitDisplayNames.contains( aUnit ) )
return m_unitDisplayNames.at( aUnit );
else if( aLabel )
return wxString::Format( _( "Unit %s" ), LIB_SYMBOL::LetterSubReference( aUnit, 'A' ) );
else
return wxString::Format( _( "Unit %s" ), GetUnitReference( aUnit ) );
return LIB_SYMBOL::LetterSubReference( aUnit, 'A' );
}
wxString LIB_SYMBOL::GetBodyStyleDescription( int aBodyStyle, bool aLabel ) const
{
if( aBodyStyle == BODY_STYLE::DEMORGAN )
return aLabel ? _( "Alternate" ) : _HKI( "Alternate" );
else if( aBodyStyle == BODY_STYLE::BASE )
return aLabel ? _( "Standard" ) : _HKI( "Standard" );
else
return wxT( "?" );
}
@ -515,7 +522,7 @@ void LIB_SYMBOL::SetNormal()
}
wxString LIB_SYMBOL::LetterSubReference( int aUnit, int aFirstId )
wxString LIB_SYMBOL::LetterSubReference( int aUnit, wxChar aInitialLetter )
{
// use letters as notation. To allow more than 26 units, the sub ref
// use one letter if letter = A .. Z or a ... z, and 2 letters otherwise
@ -526,7 +533,7 @@ wxString LIB_SYMBOL::LetterSubReference( int aUnit, int aFirstId )
do
{
u = ( aUnit - 1 ) % 26;
suffix = wxChar( aFirstId + u ) + suffix;
suffix = wxChar( aInitialLetter + u ) + suffix;
aUnit = ( aUnit - u ) / 26;
} while( aUnit > 0 );

View File

@ -542,20 +542,22 @@ public:
void SetUnitCount( int aCount, bool aDuplicateDrawItems = true );
int GetUnitCount() const override;
/**
* Return an identifier for \a aUnit for symbols with units.
*/
wxString GetUnitReference( int aUnit ) override;
/**
* Return true if the given unit \a aUnit has a display name defined
*/
bool HasUnitDisplayName( int aUnit ) override;
bool HasUnitDisplayName( int aUnit ) const;
wxString GetUnitName( int aUnit ) const override
{
return GetUnitDisplayName( aUnit, true );
}
/**
* Return the user-defined display name for \a aUnit for symbols with units.
*/
wxString GetUnitDisplayName( int aUnit ) override;
wxString GetUnitDisplayName( int aUnit, bool aLabel ) const override;
wxString GetBodyStyleDescription( int aBodyStyle, bool aLabel ) const override;
/**
* Copy all unit display names into the given map \a aTarget
@ -586,7 +588,7 @@ public:
*/
bool IsMulti() const override { return m_unitCount > 1; }
static wxString LetterSubReference( int aUnit, int aFirstId );
static wxString LetterSubReference( int aUnit, wxChar aInitialLetter );
/**
* Set or clear the alternate body style (DeMorgan) for the symbol.

View File

@ -119,8 +119,8 @@ void SCH_EDIT_FRAME::SelectUnit( SCH_SYMBOL* aSymbol, int aUnit )
if( otherSymbolRef )
{
const wxString targetUnitName = symbol->GetUnitDisplayName( aUnit );
const wxString currUnitName = symbol->GetUnitDisplayName( currentUnit );
const wxString targetUnitName = symbol->GetUnitDisplayName( aUnit, false );
const wxString currUnitName = symbol->GetUnitDisplayName( currentUnit, false );
wxString otherSheetName = otherSymbolRef->GetSheetPath().PathHumanReadable( true, true );
if( otherSheetName.IsEmpty() )

View File

@ -260,7 +260,7 @@ void SCH_IO_KICAD_SEXPR_LIB_CACHE::SaveSymbol( LIB_SYMBOL* aSymbol, OUTPUTFORMAT
// if the unit has a display name, write that
if( aSymbol->HasUnitDisplayName( unit.m_unit ) )
{
name = aSymbol->GetUnitDisplayName( unit.m_unit );
name = aSymbol->GetUnitDisplayName( unit.m_unit, false );
aFormatter.Print( "(unit_name %s)", aFormatter.Quotes( name ).c_str() );
}

View File

@ -45,28 +45,6 @@
#define BITMAP_FONT_SIZE_THRESHOLD 3
wxString SCH_ITEM::GetUnitDescription( int aUnit )
{
if( aUnit == 0 )
return _( "All" );
else
return LIB_SYMBOL::LetterSubReference( aUnit, 'A' );
}
wxString SCH_ITEM::GetBodyStyleDescription( int aBodyStyle )
{
if( aBodyStyle == 0 )
return _( "All" );
else if( aBodyStyle == BODY_STYLE::DEMORGAN )
return _( "Alternate" );
else if( aBodyStyle == BODY_STYLE::BASE )
return _( "Standard" );
else
return wxT( "?" );
}
/* Constructor and destructor for SCH_ITEM */
/* They are not inline because this creates problems with gcc at linking time in debug mode */
@ -187,25 +165,81 @@ SCH_ITEM* SCH_ITEM::Duplicate( bool addToParentGroup, SCH_COMMIT* aCommit, bool
}
void SCH_ITEM::SetUnitProp( int aUnit )
void SCH_ITEM::SetUnitProp( const wxString& aUnit )
{
if( GetParentSymbol() )
aUnit = std::min( aUnit, GetParentSymbol()->GetUnitCount() );
if( aUnit == _HKI( "All units" ) )
{
m_unit = 0;
return;
}
aUnit = std::max( aUnit, 0 );
m_unit = aUnit;
if( SYMBOL* symbol = GetParentSymbol() )
{
for( int unit = 1; unit <= symbol->GetUnitCount(); unit++ )
{
if( symbol->GetUnitDisplayName( unit, false ) == aUnit )
{
m_unit = unit;
return;
}
}
}
}
void SCH_ITEM::SetBodyStyleProp( int aBodyStyle )
wxString SCH_ITEM::GetUnitDisplayName( int aUnit, bool aLabel ) const
{
if( GetParentSymbol() && GetParentSymbol()->HasAlternateBodyStyle() )
aBodyStyle = std::min( aBodyStyle, (int) BODY_STYLE::DEMORGAN );
if( aUnit == 0 )
return aLabel ? _( "All units" ) : _HKI( "All units" );
else if( const SYMBOL* symbol = GetParentSymbol() )
return symbol->GetUnitDisplayName( aUnit, aLabel );
aBodyStyle = std::max( aBodyStyle, 0 );
return wxEmptyString;
}
m_bodyStyle = aBodyStyle;
wxString SCH_ITEM::GetBodyStyleDescription( int aBodyStyle, bool aLabel ) const
{
if( aBodyStyle == 0 )
return aLabel ? _( "All body styles" ) : _HKI( "All body styles" );
else if( const SYMBOL* symbol = GetParentSymbol() )
return symbol->GetBodyStyleDescription( aBodyStyle, aLabel );
return wxEmptyString;
}
wxString SCH_ITEM::GetUnitProp() const
{
return GetUnitDisplayName( m_unit, false );
}
void SCH_ITEM::SetBodyStyleProp( const wxString& aBodyStyle )
{
if( aBodyStyle == _HKI( "All body styles" ) )
{
m_bodyStyle = 0;
return;
}
if( SYMBOL* symbol = GetParentSymbol() )
{
for( int bodyStyle : { BODY_STYLE::BASE, BODY_STYLE::DEMORGAN } )
{
if( symbol->GetBodyStyleDescription( bodyStyle, false ) == aBodyStyle )
{
m_bodyStyle = bodyStyle;
return;
}
}
}
}
wxString SCH_ITEM::GetBodyStyleProp() const
{
return GetBodyStyleDescription( m_bodyStyle, false );
}
@ -625,21 +659,18 @@ bool SCH_ITEM::RenderAsBitmap( double aWorldScale ) const
}
void SCH_ITEM::getSymbolEditorMsgPanelInfo( EDA_DRAW_FRAME* aFrame,
std::vector<MSG_PANEL_ITEM>& aList )
void SCH_ITEM::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
{
aList.emplace_back( _( "Type" ), GetFriendlyName() );
wxString msg;
SYMBOL* symbol = GetParentSymbol();
if( const SYMBOL* parent = GetParentSymbol() )
{
if( parent->GetUnitCount() )
aList.emplace_back( _( "Unit" ), GetUnitDescription( m_unit ) );
if( symbol->GetUnitCount() )
aList.emplace_back( _( "Unit" ), GetUnitDisplayName( GetUnit(), false ) );
if( parent->HasAlternateBodyStyle() )
aList.emplace_back( _( "Body Style" ), GetBodyStyleDescription( m_bodyStyle ) );
}
if( symbol->HasAlternateBodyStyle() )
aList.emplace_back( _( "Body Style" ), GetBodyStyleDescription( GetBodyStyle(), true ) );
if( IsPrivate() )
if( dynamic_cast<LIB_SYMBOL*>( symbol ) && IsPrivate() )
aList.emplace_back( _( "Private" ), wxEmptyString );
}
@ -682,15 +713,48 @@ static struct SCH_ITEM_DESC
return false;
};
propMgr.AddProperty( new PROPERTY<SCH_ITEM, int>( _HKI( "Unit" ),
&SCH_ITEM::SetUnitProp, &SCH_ITEM::GetUnit ) )
propMgr.AddProperty( new PROPERTY<SCH_ITEM, wxString>( _HKI( "Unit" ),
&SCH_ITEM::SetUnitProp, &SCH_ITEM::GetUnitProp ) )
.SetAvailableFunc( multiUnit )
.SetIsHiddenFromDesignEditors();
.SetIsHiddenFromDesignEditors()
.SetChoicesFunc( []( INSPECTABLE* aItem )
{
wxPGChoices choices;
choices.Add( _HKI( "All units" ) );
propMgr.AddProperty( new PROPERTY<SCH_ITEM, int>( _HKI( "Body Style" ),
&SCH_ITEM::SetBodyStyle, &SCH_ITEM::GetBodyStyle ) )
if( SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItem ) )
{
if( SYMBOL* symbol = item->GetParentSymbol() )
{
for( int ii = 1; ii <= symbol->GetUnitCount(); ii++ )
choices.Add( symbol->GetUnitDisplayName( ii, false ) );
}
}
return choices;
} );
propMgr.AddProperty( new PROPERTY<SCH_ITEM, wxString>( _HKI( "Body Style" ),
&SCH_ITEM::SetBodyStyleProp, &SCH_ITEM::GetBodyStyleProp ) )
.SetAvailableFunc( multiBodyStyle )
.SetIsHiddenFromDesignEditors();
.SetIsHiddenFromDesignEditors()
.SetChoicesFunc( []( INSPECTABLE* aItem )
{
wxPGChoices choices;
choices.Add( _HKI( "All body styles" ) );
if( SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItem ) )
{
if( SYMBOL* symbol = item->GetParentSymbol() )
{
for( int ii : { BODY_STYLE::BASE, BODY_STYLE::DEMORGAN } )
choices.Add( symbol->GetBodyStyleDescription( ii, false ) );
}
}
return choices;
} );
propMgr.AddProperty( new PROPERTY<SCH_ITEM, bool>( _HKI( "Private" ),
&SCH_ITEM::SetPrivate, &SCH_ITEM::IsPrivate ) )

View File

@ -235,16 +235,20 @@ public:
*/
SCH_ITEM* Duplicate( bool addToParentGroup, SCH_COMMIT* aCommit = nullptr, bool doClone = false ) const;
static wxString GetUnitDescription( int aUnit );
static wxString GetBodyStyleDescription( int aBodyStyle );
virtual void SetUnit( int aUnit ) { m_unit = aUnit; }
int GetUnit() const { return m_unit; }
void SetUnitProp( int aUnit );
virtual wxString GetUnitDisplayName( int aUnit, bool aLabel ) const;
virtual wxString GetBodyStyleDescription( int aBodyStyle, bool aLabel ) const;
virtual void SetUnitProp( const wxString& aUnit );
virtual wxString GetUnitProp() const;
virtual void SetBodyStyle( int aBodyStyle ) { m_bodyStyle = aBodyStyle; }
int GetBodyStyle() const { return m_bodyStyle; }
void SetBodyStyleProp( int aBodyStyle );
virtual void SetBodyStyleProp( const wxString& aBodyStyle );
virtual wxString GetBodyStyleProp() const;
void SetPrivate( bool aPrivate ) { m_private = aPrivate; }
bool IsPrivate() const { return m_private; }
@ -612,6 +616,8 @@ public:
virtual void SetStroke( const STROKE_PARAMS& aStroke ) { wxCHECK( false, /* void */ ); }
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
/**
* Plot the item to \a aPlotter.
*
@ -692,8 +698,6 @@ protected:
bool operator()( const SCH_ITEM* aFirst, const SCH_ITEM* aSecond ) const;
};
void getSymbolEditorMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList );
/**
* Provide the draw object specific comparison called by the == and < operators.
*

View File

@ -43,32 +43,6 @@
// small margin in internal units between the pin text and the pin line
#define PIN_TEXT_MARGIN 4
wxString SCH_PIN::GetCanonicalElectricalTypeName( ELECTRICAL_PINTYPE aType )
{
// These strings are the canonical name of the electrictal type
// Not translated, no space in name, only ASCII chars.
// to use when the string name must be known and well defined
// must have same order than enum ELECTRICAL_PINTYPE (see sch_pin.h)
static const wxChar* msgPinElectricType[] =
{
wxT( "input" ),
wxT( "output" ),
wxT( "bidirectional" ),
wxT( "tri_state" ),
wxT( "passive" ),
wxT( "free" ),
wxT( "unspecified" ),
wxT( "power_in" ),
wxT( "power_out" ),
wxT( "open_collector" ),
wxT( "open_emitter" ),
wxT( "no_connect" )
};
return msgPinElectricType[static_cast<int>( aType )];
}
/// Utility for getting the size of the 'internal' pin decorators (as a radius)
/// i.e. the clock symbols (falling clock is actually external but is of
/// the same kind)
@ -324,29 +298,25 @@ void SCH_PIN::SetType( ELECTRICAL_PINTYPE aType )
wxString SCH_PIN::GetCanonicalElectricalTypeName() const
{
if( m_type == ELECTRICAL_PINTYPE::PT_INHERIT )
{
if( !m_libPin )
return GetCanonicalElectricalTypeName( ELECTRICAL_PINTYPE::PT_UNSPECIFIED );
if( m_type != ELECTRICAL_PINTYPE::PT_INHERIT )
return ::GetCanonicalElectricalTypeName( m_type );
return m_libPin->GetCanonicalElectricalTypeName();
}
if( !m_libPin )
return ::GetCanonicalElectricalTypeName( ELECTRICAL_PINTYPE::PT_UNSPECIFIED );
return GetCanonicalElectricalTypeName( m_type );
return m_libPin->GetCanonicalElectricalTypeName();
}
wxString SCH_PIN::GetElectricalTypeName() const
{
if( m_type == ELECTRICAL_PINTYPE::PT_INHERIT )
{
if( !m_libPin )
return ElectricalPinTypeGetText( ELECTRICAL_PINTYPE::PT_UNSPECIFIED );
if( m_type != ELECTRICAL_PINTYPE::PT_INHERIT )
return ElectricalPinTypeGetText( m_type );
return m_libPin->GetElectricalTypeName();
}
if( !m_libPin )
return ElectricalPinTypeGetText( ELECTRICAL_PINTYPE::PT_UNSPECIFIED );
return ElectricalPinTypeGetText( m_type );
return m_libPin->GetElectricalTypeName();
}
@ -1156,28 +1126,9 @@ void SCH_PIN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITE
wxString msg;
SYMBOL* symbol = GetParentSymbol();
if( dynamic_cast<LIB_SYMBOL*>( symbol ) )
{
getSymbolEditorMsgPanelInfo( aFrame, aList );
}
else
{
aList.emplace_back( _( "Type" ), _( "Pin" ) );
aList.emplace_back( _( "Type" ), _( "Pin" ) );
if( symbol->GetUnitCount() )
{
msg = m_libPin ? GetUnitDescription( m_libPin->GetUnit() ) :
wxString( "Undefined library pin." );
aList.emplace_back( _( "Unit" ), msg );
}
if( symbol->HasAlternateBodyStyle() )
{
msg = m_libPin ? GetBodyStyleDescription( m_libPin->GetBodyStyle() ) :
wxString( "Undefined library pin." );
aList.emplace_back( _( "Body Style" ), msg );
}
}
SCH_ITEM::GetMsgPanelInfo( aFrame, aList );
aList.emplace_back( _( "Name" ), UnescapeString( GetShownName() ) );
aList.emplace_back( _( "Number" ), GetShownNumber() );

View File

@ -317,10 +317,7 @@ const BOX2I SCH_SHAPE::GetBoundingBox() const
void SCH_SHAPE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
{
if( m_layer == LAYER_DEVICE )
getSymbolEditorMsgPanelInfo( aFrame, aList );
else
SCH_ITEM::GetMsgPanelInfo( aFrame, aList );
SCH_ITEM::GetMsgPanelInfo( aFrame, aList );
ShapeGetMsgPanelInfo( aFrame, aList );
}

View File

@ -441,24 +441,32 @@ int SCH_SYMBOL::GetUnitCount() const
}
wxString SCH_SYMBOL::GetUnitDisplayName( int aUnit ) const
wxString SCH_SYMBOL::GetUnitDisplayName( int aUnit, bool aLabel ) const
{
wxCHECK( m_part, ( wxString::Format( _( "Unit %s" ), SubReference( aUnit ) ) ) );
return m_part->GetUnitDisplayName( aUnit );
if( m_part )
return m_part->GetUnitDisplayName( aUnit, aLabel );
else if( aLabel )
return wxString::Format( _( "Unit %s" ), SubReference( aUnit ) );
else
return SubReference( aUnit );
}
bool SCH_SYMBOL::HasUnitDisplayName( int aUnit ) const
wxString SCH_SYMBOL::GetBodyStyleDescription( int aBodyStyle, bool aLabel ) const
{
wxCHECK( m_part, false );
return m_part->HasUnitDisplayName( aUnit );
if( m_part )
return m_part->GetBodyStyleDescription( aBodyStyle, aLabel );
else if( aBodyStyle == BODY_STYLE::DEMORGAN )
return aLabel ? _( "Alternate" ) : _HKI( "Alternate" );
else if( aBodyStyle == BODY_STYLE::BASE )
return aLabel ? _( "Standard" ) : _HKI( "Standard" );
else
return wxT( "?" );
}
bool SCH_SYMBOL::GetInstance( SCH_SYMBOL_INSTANCE& aInstance,
const KIID_PATH& aSheetPath, bool aTestFromEnd ) const
bool SCH_SYMBOL::GetInstance( SCH_SYMBOL_INSTANCE& aInstance, const KIID_PATH& aSheetPath,
bool aTestFromEnd ) const
{
for( const SCH_SYMBOL_INSTANCE& instance : m_instanceReferences )
{
@ -2918,11 +2926,35 @@ static struct SCH_SYMBOL_DESC
propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, wxString>( _HKI( "Unit" ),
&SCH_SYMBOL::SetUnitProp, &SCH_SYMBOL::GetUnitProp ) )
.SetAvailableFunc( multiUnit );
.SetAvailableFunc( multiUnit )
.SetChoicesFunc( []( INSPECTABLE* aItem )
{
wxPGChoices choices;
propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, int>( _HKI( "Body Style" ),
if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aItem ) )
{
for( int ii = 1; ii <= symbol->GetUnitCount(); ii++ )
choices.Add( symbol->GetUnitDisplayName( ii, false ) );
}
return choices;
} );
propMgr.AddProperty( new PROPERTY<SCH_SYMBOL, wxString>( _HKI( "Body Style" ),
&SCH_SYMBOL::SetBodyStyleProp, &SCH_SYMBOL::GetBodyStyleProp ) )
.SetAvailableFunc( multiBodyStyle );
.SetAvailableFunc( multiBodyStyle )
.SetChoicesFunc( []( INSPECTABLE* aItem )
{
wxPGChoices choices;
if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aItem ) )
{
for( int ii : { BODY_STYLE::BASE, BODY_STYLE::DEMORGAN } )
choices.Add( symbol->GetBodyStyleDescription( ii, false ) );
}
return choices;
} );
const wxString groupAttributes = _HKI( "Attributes" );

View File

@ -221,19 +221,14 @@ public:
*/
void UpdatePins();
/**
* Return true if the given unit \a aUnit has a display name set.
*
* @return true if the display name of a unit is set, otherwise false.
*/
bool HasUnitDisplayName( int aUnit ) const;
/**
* Return the display name for a given unit \a aUnit.
*
* @return the display name of a unit if set, or the ordinal name of the unit otherwise.
*/
wxString GetUnitDisplayName( int aUnit ) const;
wxString GetUnitDisplayName( int aUnit, bool aLabel ) const override;
wxString GetBodyStyleDescription( int aBodyStyle, bool aLabel ) const override;
void SetBodyStyle( int aBodyStyle ) override;
@ -489,6 +484,7 @@ public:
}
void SetRefProp( const wxString& aRef );
wxString GetValueProp() const
{
return GetValue( false, &Schematic()->CurrentSheet(), false );
@ -499,31 +495,18 @@ public:
SetValueFieldText( aRef );
}
wxString GetUnitProp() const
wxString GetUnitProp() const override
{
int unit = GetUnitSelection( &Schematic()->CurrentSheet() );
if( HasUnitDisplayName( unit ) )
return GetUnitDisplayName( unit );
else
return SubReference( unit, false );
return GetUnitDisplayName( unit, false );
}
void SetUnitProp( const wxString& aUnit )
void SetUnitProp( const wxString& aUnit ) override
{
for( int unit = 1; unit <= GetUnitCount(); unit++ )
{
if( HasUnitDisplayName( unit ) && GetUnitDisplayName( unit ) == aUnit )
{
SetUnitSelection( &Schematic()->CurrentSheet(), unit );
SetUnit( unit );
return;
}
}
for( int unit = 1; unit <= GetUnitCount(); unit++ )
{
if( SubReference( unit, false ) == aUnit )
if( GetUnitDisplayName( unit, false ) == aUnit )
{
SetUnitSelection( &Schematic()->CurrentSheet(), unit );
SetUnit( unit );
@ -532,14 +515,21 @@ public:
}
}
int GetBodyStyleProp() const
wxString GetBodyStyleProp() const override
{
return GetBodyStyle();
return GetBodyStyleDescription( GetBodyStyle(), false );
}
void SetBodyStyleProp( int aBodyStyle )
void SetBodyStyleProp( const wxString& aBodyStyle ) override
{
SetBodyStyle( aBodyStyle );
for( int bodyStyle : { BODY_STYLE::BASE, BODY_STYLE::DEMORGAN } )
{
if( GetBodyStyleDescription( bodyStyle, false ) == aBodyStyle )
{
SetBodyStyle( bodyStyle );
return;
}
}
}
/**

View File

@ -447,6 +447,8 @@ void SCH_TABLE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_I
{
// Don't use GetShownText() here; we want to show the user the variable references
aList.emplace_back( _( "Table" ), wxString::Format( _( "%d Columns" ), m_colCount ) );
SCH_ITEM::GetMsgPanelInfo( aFrame, aList );
}

View File

@ -544,6 +544,8 @@ void SCH_TEXT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_IT
// Don't use GetShownText() here; we want to show the user the variable references
aList.emplace_back( _( "Text" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
SCH_ITEM::GetMsgPanelInfo( aFrame, aList );
if( m_excludedFromSim )
aList.emplace_back( _( "Exclude from" ), _( "Simulation" ) );

View File

@ -455,6 +455,8 @@ void SCH_TEXTBOX::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL
// Don't use GetShownText() here; we want to show the user the variable references
aList.emplace_back( _( "Text Box" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
SCH_ITEM::GetMsgPanelInfo( aFrame, aList );
if( m_excludedFromSim )
aList.emplace_back( _( "Exclude from" ), _( "Simulation" ) );

View File

@ -86,7 +86,7 @@ void CheckDuplicatePins( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
pin->GetName(),
aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ),
SCH_ITEM::GetBodyStyleDescription( pin->GetBodyStyle() ).Lower() );
aSymbol->GetBodyStyleDescription( pin->GetBodyStyle(), true ).Lower() );
}
else
{
@ -101,9 +101,9 @@ void CheckDuplicatePins( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
pinName,
aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ),
aSymbol->GetUnitReference( next->GetUnit() ),
aSymbol->GetUnitReference( pin->GetUnit() ),
SCH_ITEM::GetBodyStyleDescription( pin->GetBodyStyle() ).Lower() );
aSymbol->GetUnitDisplayName( next->GetUnit(), false ),
aSymbol->GetUnitDisplayName( pin->GetUnit(), false ),
aSymbol->GetBodyStyleDescription( pin->GetBodyStyle(), true ).Lower() );
}
}
else
@ -134,8 +134,8 @@ void CheckDuplicatePins( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
pinName,
aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ),
aSymbol->GetUnitReference( next->GetUnit() ),
aSymbol->GetUnitReference( pin->GetUnit() ) );
aSymbol->GetUnitDisplayName( next->GetUnit(), false ),
aSymbol->GetUnitDisplayName( pin->GetUnit(), false ) );
}
}
@ -264,7 +264,7 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
pinName,
aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ),
SCH_ITEM::GetBodyStyleDescription( pin->GetBodyStyle() ).Lower() );
aSymbol->GetBodyStyleDescription( pin->GetBodyStyle(), true ).Lower() );
}
else
{
@ -275,7 +275,7 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ),
'A' + pin->GetUnit() - 1,
SCH_ITEM::GetBodyStyleDescription( pin->GetBodyStyle() ).Lower() );
aSymbol->GetBodyStyleDescription( pin->GetBodyStyle(), true ).Lower() );
}
}
else
@ -323,7 +323,7 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
pinName,
aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ),
SCH_ITEM::GetBodyStyleDescription( pin->GetBodyStyle() ).Lower() );
aSymbol->GetBodyStyleDescription( pin->GetBodyStyle(), true ).Lower() );
}
else
{
@ -334,7 +334,7 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
aUnitsProvider->MessageTextFromValue( pin->GetPosition().x ),
aUnitsProvider->MessageTextFromValue( -pin->GetPosition().y ),
'A' + pin->GetUnit() - 1,
SCH_ITEM::GetBodyStyleDescription( pin->GetBodyStyle() ).Lower() );
aSymbol->GetBodyStyleDescription( pin->GetBodyStyle(), true ).Lower() );
}
}
else

View File

@ -715,7 +715,7 @@ void SYMBOL_EDIT_FRAME::RebuildSymbolUnitsList()
{
for( int i = 0; i < m_symbol->GetUnitCount(); i++ )
{
wxString unitDisplayName = m_symbol->GetUnitDisplayName( i + 1 );
wxString unitDisplayName = m_symbol->GetUnitDisplayName( i + 1, true );
m_unitSelectBox->Append( unitDisplayName );
}
}

View File

@ -1736,20 +1736,6 @@ void SYMBOL_EDIT_FRAME::UpdateSymbolMsgPanelInfo()
AppendMsgPanel( _( "Parent" ), UnescapeString( msg ), 8 );
}
static wxChar UnitLetter[] = wxT( "?ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
msg = UnitLetter[m_unit];
AppendMsgPanel( _( "Unit" ), msg, 8 );
if( m_bodyStyle == BODY_STYLE::DEMORGAN )
msg = _( "Alternate" );
else if( m_bodyStyle == BODY_STYLE::BASE )
msg = _( "Standard" );
else
msg = wxT( "?" );
AppendMsgPanel( _( "Body" ), msg, 8 );
if( m_symbol->IsGlobalPower() )
msg = _( "Power Symbol" );
else if( m_symbol->IsLocalPower() )

View File

@ -504,7 +504,7 @@ void SYMBOL_VIEWER_FRAME::onUpdateUnitChoice( wxUpdateUIEvent& aEvent )
for( int ii = 0; ii < unit_count; ii++ )
{
wxString unit = symbol->GetUnitDisplayName( ii + 1 );
wxString unit = symbol->GetUnitDisplayName( ii + 1, true );
m_unitChoice->Append( unit );
}

View File

@ -102,12 +102,7 @@ private:
for( int ii = 0; ii < nUnits; ii++ )
{
wxString unit_text;
if( symbol->GetLibSymbolRef()->HasUnitDisplayName( ii + 1 ) )
unit_text = symbol->GetLibSymbolRef()->GetUnitDisplayName( ii + 1 );
else
unit_text.Printf( _( "Unit %s" ), symbol->SubReference( ii + 1, false ) );
wxString unit_text = symbol->GetUnitDisplayName( ii + 1, false );
if( missingUnits.count( ii + 1 ) == 0 )
unit_text += _( " (already placed)" );

View File

@ -841,13 +841,11 @@ int SYMBOL_EDITOR_EDIT_TOOL::SetUnitDisplayName( const TOOL_EVENT& aEvent )
}
wxString promptText = wxString::Format( _( "Enter display name for unit %s" ),
symbol->GetUnitReference( unitid ) );
LIB_SYMBOL::LetterSubReference( unitid, 'A' ) );
wxString currentvalue;
if( symbol->HasUnitDisplayName( unitid ) )
{
currentvalue = symbol->GetUnitDisplayName( unitid );
}
currentvalue = symbol->GetUnitDisplayName( unitid, false );
wxTextEntryDialog dlg( m_frame, promptText, _( "Set Unit Display Name" ), currentvalue );

View File

@ -261,8 +261,7 @@ void SCH_PROPERTIES_PANEL::updateFontList()
// Regnerate font names
std::vector<std::string> fontNames;
Fontconfig()->ListFonts( fontNames, std::string( Pgm().GetLanguageTag().utf8_str() ),
fontFiles );
Fontconfig()->ListFonts( fontNames, std::string( Pgm().GetLanguageTag().utf8_str() ), fontFiles );
fonts.Add( _( "Default Font" ), -1 );
fonts.Add( KICAD_FONT_NAME, -2 );

View File

@ -60,7 +60,7 @@ public:
bool Set( PROPERTY_BASE* aProperty, T aValue, bool aNotify = true )
{
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
void* object = propMgr.TypeCast( this, TYPE_HASH( *this ), aProperty->OwnerHash() );
void* object = propMgr.TypeCast( this, TYPE_HASH( *this ), aProperty->OwnerHash() );
if( object )
{
@ -73,6 +73,27 @@ public:
return object != nullptr;
}
bool Set( PROPERTY_BASE* aProperty, wxVariant aValue, bool aNotify = true )
{
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
void* object = propMgr.TypeCast( this, TYPE_HASH( *this ), aProperty->OwnerHash() );
if( object )
{
wxPGChoices choices = aProperty->GetChoices( this );
if( choices.GetCount() )
aProperty->set<wxString>( object, choices.GetLabel( aValue.GetInteger() ) );
else
aProperty->set<wxVariant>( object, aValue );
if( aNotify )
propMgr.PropertyChanged( this, aProperty );
}
return object != nullptr;
}
template<typename T>
bool Set( const wxString& aProperty, T aValue, bool aNotify = true )
{

View File

@ -81,17 +81,7 @@ public:
/**
* For items with units, return an identifier for unit x.
*/
virtual wxString GetUnitReference( int aUnit ) { return wxEmptyString; }
/**
* For items with units, return a display name for unit x.
*/
virtual wxString GetUnitDisplayName( int aUnit ) { return wxEmptyString; }
/**
* For items with units, return true if a display name is set for x.
*/
virtual bool HasUnitDisplayName( int aUnit ) { return false; }
virtual wxString GetUnitName( int aUnit ) const { return wxEmptyString; }
};
#endif //LIB_TREE_ITEM_H

View File

@ -241,7 +241,7 @@ public:
*/
virtual bool HasChoices() const
{
return false;
return m_choicesFunc != nullptr;
}
/**
@ -261,6 +261,20 @@ public:
return *this;
}
wxPGChoices GetChoices( INSPECTABLE* aObject ) const
{
if( m_choicesFunc )
return m_choicesFunc( aObject );
return {};
}
PROPERTY_BASE& SetChoicesFunc( std::function<wxPGChoices(INSPECTABLE*)> aFunc )
{
m_choicesFunc = std::move( aFunc );
return *this;
}
virtual bool Writeable( INSPECTABLE* aObject ) const
{
return m_writeableFunc( aObject );
@ -434,6 +448,8 @@ private:
std::function<bool(INSPECTABLE*)> m_writeableFunc; ///< Eval to determine if prop is read-only
std::function<wxPGChoices(INSPECTABLE*)> m_choicesFunc;
PROPERTY_VALIDATOR_FN m_validator;
friend class INSPECTABLE;

View File

@ -46,17 +46,6 @@ class COMMIT;
///< Unique type identifier
using TYPE_ID = size_t;
using PROPERTY_LIST = std::vector<PROPERTY_BASE*>;
using PROPERTY_SET = std::set<std::pair<size_t, wxString>>;
template<typename ValueType>
using PROPERTY_MAP = std::map<std::pair<size_t, wxString>, ValueType>;
using PROPERTY_FUNCTOR_MAP = PROPERTY_MAP<std::function<bool( INSPECTABLE* )>>;
using PROPERTY_DISPLAY_ORDER = std::map<PROPERTY_BASE*, int>;
using PROPERTY_LISTENER = std::function<void( INSPECTABLE*, PROPERTY_BASE*, COMMIT* )>;
class PROPERTY_COMMIT_HANDLER
@ -100,14 +89,6 @@ public:
*/
void RegisterType( TYPE_ID aType, const wxString& aName );
/**
* Return name of a type.
*
* @param aType is the type identifier (obtained using TYPE_HASH()).
* @return Name of the type or empty string, if not available.
*/
const wxString& ResolveType( TYPE_ID aType ) const;
/**
* Return a property for a specific type.
*
@ -123,9 +104,9 @@ public:
* @param aType is the type identifier (obtained using TYPE_HASH()).
* @return Vector storing all properties of the requested type.
*/
const PROPERTY_LIST& GetProperties( TYPE_ID aType ) const;
const std::vector<PROPERTY_BASE*>& GetProperties( TYPE_ID aType ) const;
const PROPERTY_DISPLAY_ORDER& GetDisplayOrder( TYPE_ID aType ) const;
const std::map<PROPERTY_BASE*, int>& GetDisplayOrder( TYPE_ID aType ) const;
const std::vector<wxString>& GetGroupDisplayOrder( TYPE_ID aType ) const;
@ -258,8 +239,6 @@ public:
CLASSES_INFO GetAllClasses();
std::vector<TYPE_ID> GetMatchingClasses( PROPERTY_BASE* aProperty );
/**
* Callback to alert the notification system that a property has changed
* @param aObject is the object whose property just changed
@ -314,19 +293,19 @@ private:
std::map<TYPE_ID, std::unique_ptr<TYPE_CAST_BASE>> m_typeCasts;
///< Properties from bases that should be masked (hidden) on this subclass
PROPERTY_SET m_maskedBaseProperties;
std::set<std::pair<size_t, wxString>> m_maskedBaseProperties;
///< Overrides for base class property availabilities
PROPERTY_FUNCTOR_MAP m_availabilityOverrides;
std::map<std::pair<size_t, wxString>, std::function<bool( INSPECTABLE* )>> m_availabilityOverrides;
///< Overrides for base class property writeable status
PROPERTY_FUNCTOR_MAP m_writeabilityOverrides;
std::map<std::pair<size_t, wxString>, std::function<bool( INSPECTABLE* )>> m_writeabilityOverrides;
///< All properties (both unique to the type and inherited)
std::vector<PROPERTY_BASE*> m_allProperties;
///< Compiled display order for all properties
PROPERTY_DISPLAY_ORDER m_displayOrder;
std::map<PROPERTY_BASE*, int> m_displayOrder;
///< List of property groups provided by this class in display order
std::vector<wxString> m_groupDisplayOrder;
@ -338,16 +317,17 @@ private:
std::set<wxString> m_groups;
///< Replaced properties (TYPE_ID / name)
PROPERTY_SET m_replaced;
std::set<std::pair<size_t, wxString>> m_replaced;
///< Recreates the list of properties
void rebuild();
///< Traverses the class inheritance hierarchy bottom-to-top, gathering
///< all properties available to a type
void collectPropsRecur( PROPERTY_LIST& aResult, PROPERTY_SET& aReplaced,
PROPERTY_DISPLAY_ORDER& aDisplayOrder,
PROPERTY_SET& aMasked ) const;
void collectPropsRecur( std::vector<PROPERTY_BASE*>& aResult,
std::set<std::pair<size_t, wxString>>& aReplaced,
std::map<PROPERTY_BASE*, int>& aDisplayOrder,
std::set<std::pair<size_t, wxString>>& aMasked ) const;
};
///< Returns metadata for a specific type

View File

@ -538,7 +538,7 @@ void PANEL_SETUP_RULES::onScintillaCharAdded( wxStyledTextEvent &aEvent )
for( const PROPERTY_MANAGER::CLASS_INFO& cls : propMgr.GetAllClasses() )
{
const PROPERTY_LIST& props = propMgr.GetProperties( cls.type );
const std::vector<PROPERTY_BASE*>& props = propMgr.GetProperties( cls.type );
for( PROPERTY_BASE* prop : props )
{

View File

@ -66,6 +66,7 @@
#include <pcb_group.h>
#include <gal/graphics_abstraction_layer.h>
#include <pin_type.h>
using KIGFX::PCB_PAINTER;
using KIGFX::PCB_RENDER_SETTINGS;
@ -2803,42 +2804,51 @@ static struct PAD_DESC
.SetIsHiddenFromLibraryEditors();
propMgr.AddProperty( new PROPERTY<PAD, wxString>( _HKI( "Pin Type" ),
&PAD::SetPinType, &PAD::GetPinType ), groupPad )
.SetIsHiddenFromLibraryEditors();
.SetIsHiddenFromLibraryEditors()
.SetChoicesFunc( []( INSPECTABLE* aItem )
{
wxPGChoices choices;
for( int ii = 0; ii < ELECTRICAL_PINTYPES_TOTAL; ii++ )
choices.Add( GetCanonicalElectricalTypeName( (ELECTRICAL_PINTYPE) ii ) );
return choices;
} );
propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Size X" ),
&PAD::SetSizeX, &PAD::GetSizeX, PROPERTY_DISPLAY::PT_SIZE ), groupPad )
.SetAvailableFunc( hasNormalPadstack );
propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Size Y" ),
&PAD::SetSizeY, &PAD::GetSizeY, PROPERTY_DISPLAY::PT_SIZE ), groupPad )
.SetAvailableFunc(
[=]( INSPECTABLE* aItem ) -> bool
{
if( PAD* pad = dynamic_cast<PAD*>( aItem ) )
{
// Custom padstacks can't have size modified through panel
if( pad->Padstack().Mode() != PADSTACK::MODE::NORMAL )
return false;
.SetAvailableFunc( []( INSPECTABLE* aItem ) -> bool
{
if( PAD* pad = dynamic_cast<PAD*>( aItem ) )
{
// Custom padstacks can't have size modified through panel
if( pad->Padstack().Mode() != PADSTACK::MODE::NORMAL )
return false;
// Circle pads have no usable y-size
return pad->GetShape( PADSTACK::ALL_LAYERS ) != PAD_SHAPE::CIRCLE;
}
// Circle pads have no usable y-size
return pad->GetShape( PADSTACK::ALL_LAYERS ) != PAD_SHAPE::CIRCLE;
}
return true;
} );
return true;
} );
const auto hasRoundRadius =
[]( INSPECTABLE* aItem ) -> bool
{
if( PAD* pad = dynamic_cast<PAD*>( aItem ) )
{
// Custom padstacks can't have this property modified through panel
if( pad->Padstack().Mode() != PADSTACK::MODE::NORMAL )
return false;
return PAD_UTILS::PadHasMeaningfulRoundingRadius( *pad, F_Cu );
}
const auto hasRoundRadius = [=]( INSPECTABLE* aItem ) -> bool
{
if( PAD* pad = dynamic_cast<PAD*>( aItem ) )
{
// Custom padstacks can't have this property modified through panel
if( pad->Padstack().Mode() != PADSTACK::MODE::NORMAL )
return false;
return PAD_UTILS::PadHasMeaningfulRoundingRadius( *pad, F_Cu );
}
return false;
};
};
propMgr.AddProperty( new PROPERTY<PAD, double>( _HKI( "Corner Radius Ratio" ),
&PAD::SetFrontRoundRectRadiusRatio, &PAD::GetFrontRoundRectRadiusRatio ), groupPad )
@ -2862,15 +2872,14 @@ static struct PAD_DESC
&PAD::SetDrillSizeY, &PAD::GetDrillSizeY, PROPERTY_DISPLAY::PT_SIZE ), groupPad )
.SetWriteableFunc( padCanHaveHole )
.SetValidator( PROPERTY_VALIDATORS::PositiveIntValidator )
.SetAvailableFunc(
[=]( INSPECTABLE* aItem ) -> bool
{
// Circle holes have no usable y-size
if( PAD* pad = dynamic_cast<PAD*>( aItem ) )
return pad->GetDrillShape() != PAD_DRILL_SHAPE::CIRCLE;
.SetAvailableFunc( []( INSPECTABLE* aItem ) -> bool
{
// Circle holes have no usable y-size
if( PAD* pad = dynamic_cast<PAD*>( aItem ) )
return pad->GetDrillShape() != PAD_DRILL_SHAPE::CIRCLE;
return true;
} );
return true;
} );
propMgr.AddProperty( new PROPERTY_ENUM<PAD, PAD_PROP>( _HKI( "Fabrication Property" ),
&PAD::SetProperty, &PAD::GetProperty ), groupPad );