22#include <wx/settings.h>
39 bool aAddedByUser,
bool aIsCheckbox )
45 m_cols.push_back( { aFieldName, aLabel, aAddedByUser,
false,
false, aIsCheckbox } );
53 const wxString& aFieldName )
74 else if( aFieldName == wxS(
"Keywords" ) )
95 const wxString fieldName =
m_cols[aCol].m_fieldName;
99 std::map<wxString, LIB_DATA_ELEMENT>& fieldStore =
m_dataStore[symbol->m_Uuid];
100 auto it = fieldStore.find( fieldName );
101 if( it != fieldStore.end() )
103 it->second.m_currentData = wxEmptyString;
104 it->second.m_currentlyEmpty =
true;
105 it->second.m_isModified =
true;
106 fieldStore.erase( it );
120 if(
auto node =
m_dataStore[symbol->m_Uuid].extract(
m_cols[aCol].m_fieldName ) )
122 node.key() = newName;
123 node.mapped().m_isModified =
true;
124 m_dataStore[symbol->m_Uuid].insert( std::move( node ) );
128 m_cols[aCol].m_fieldName = newName;
129 m_cols[aCol].m_label = newName;
136 for(
size_t i = 0; i <
m_cols.size(); i++ )
138 if(
m_cols[i].m_fieldName == aFieldName )
148 size_t foundCount = 0;
150 if( aNewOrder.size() >
m_cols.size() )
151 wxLogDebug(
"New order contains more fields than existing columns." );
153 for(
const wxString& newField : aNewOrder )
156 for(
size_t i = 0; i <
m_cols.size() && foundCount <
m_cols.size(); i++ )
158 if(
m_cols[i].m_fieldName == newField )
168 wxLogDebug(
"Field '%s' not found in existing columns.", newField );
171 if( foundCount !=
m_cols.size() && foundCount != aNewOrder.size() )
173 wxLogDebug(
"Not all fields in the new order were found in the existing columns." );
181 bool isFirstVisible =
true;
183 for(
int col = 0; col < aCol; ++col )
187 isFirstVisible =
false;
192 GetView()->SetReadOnly( aRow, aCol,
false );
198 GetView()->SetReadOnly( aRow, aCol,
true );
203 GetView()->SetReadOnly( aRow, aCol,
true );
223 wxCHECK( aCol >= 0 && aCol < (
int)
m_cols.size(), fieldValue );
239 if( ref ==
group.m_Refs.front() )
240 fieldValue = refFieldValue;
241 else if( fieldValue != refFieldValue )
251 wxCHECK_RET( aCol >= 0 && aCol < (
int)
m_cols.size(), wxS(
"Invalid column number" ) );
268 wxGridCellAttr* attr = wxGridTableBase::GetAttr( aRow, aCol, aKind );
276 wxGridCellAttr* newAttr =
m_colAttrs[aCol]->Clone();
279 if( attr->HasBackgroundColour() && !newAttr->HasBackgroundColour() )
280 newAttr->SetBackgroundColour( attr->GetBackgroundColour() );
281 if( attr->HasTextColour() && !newAttr->HasTextColour() )
282 newAttr->SetTextColour( attr->GetTextColour() );
283 if( attr->HasFont() && !newAttr->HasFont() )
284 newAttr->SetFont( attr->GetFont() );
296 attr =
new wxGridCellAttr;
299 bool rowModified =
false;
300 bool cellModified =
false;
301 bool cellEmpty =
true;
302 bool blankModified =
false;
304 const wxString& fieldName =
m_cols[aCol].m_fieldName;
320 blankModified =
true;
326 if(
m_dataStore[ref->m_Uuid][col.m_fieldName].m_isModified )
334 if( cellModified && rowModified && !cellEmpty )
343 if( stripedRenderer )
345 attr->SetRenderer( stripedRenderer );
346 attr->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
350 if(
m_dataStore[ref->m_Uuid][fieldName].m_isModified )
352 m_dataStore[ref->m_Uuid][fieldName].m_isStriped =
true;
354 if(
m_dataStore[ref->m_Uuid][fieldName].m_currentlyEmpty )
356 if(
m_dataStore[ref->m_Uuid][fieldName].m_originallyEmpty )
358 attr->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
360 else if(
m_dataStore[ref->m_Uuid][fieldName].m_originalData.empty() )
362 attr->SetBackgroundColour( wxColour( 180, 220, 180 ) );
366 attr->SetBackgroundColour( wxColour( 220, 180, 180 ) );
369 else if(
m_dataStore[ref->m_Uuid][fieldName].m_currentData.IsEmpty() )
371 attr->SetBackgroundColour( wxColour( 180, 200, 180 ) );
375 attr->SetBackgroundColour( wxColour( 200, 180, 180 ) );
383 bool wasStriped =
false;
387 if(
m_dataStore[ref->m_Uuid][fieldName].m_isStriped )
390 m_dataStore[ref->m_Uuid][fieldName].m_isStriped =
false;
396 attr =
new wxGridCellAttr;
399 attr->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWFRAME ) );
402 attr->SetBackgroundColour( wxColour( 192, 255, 192 ) );
409 if( attr->HasFont() )
411 font = attr->GetFont();
415 font = GetView()->GetDefaultCellFont();
425 attr->SetFont( font );
435 wxCHECK_RET( aRow >= 0 && aRow < (
int)
m_rows.size(),
"Invalid Row Number" );
436 wxCHECK_RET( aCol >= 0 && aCol < (
int)
m_cols.size(),
"Invalid Column Number" );
439 const wxString& fieldName =
m_cols[aCol].m_fieldName;
441 std::map<wxString, LIB_DATA_ELEMENT>& parentFieldStore =
m_dataStore[parentSymbol->
m_Uuid];
444 wxString derivedSymbolFieldName =
"__DERIVED_SYMBOL_" + fieldName +
"__";
454 wxLogTrace(
traceLibFieldTable,
"CreateDerivedSymbol: Parent symbol name='%s', UUID='%s'",
456 wxLogTrace(
traceLibFieldTable,
"CreateDerivedSymbol: Stored creation request for symbol '%s' under parent UUID %s, special field '%s'",
457 aNewSymbolName, parentSymbol->
m_Uuid.
AsString(), derivedSymbolFieldName );
464 wxCHECK_RET( aRow >= 0 && aRow < (
int)
m_rows.size(),
"Invalid Row Number" );
465 wxCHECK_RET( aCol >= 0 && aCol < (
int)
m_cols.size(),
"Invalid Column Number" );
469 wxLogTrace(
traceLibFieldTable,
"CreateDerivedSymbolImmediate: Creating '%s' from parent '%s' immediately",
470 aNewSymbolName, parentSymbol->
GetName() );
473 KIID newDerivedSymbolUuid;
486 wxLogTrace(
traceLibFieldTable,
"createActualDerivedSymbol: Creating '%s' from parent '%s', symbol list size before: %zu",
493 if( sym->m_Uuid == aNewSymbolUuid )
503 newSymbol->
SetName( aNewSymbolName );
510 const_cast<KIID&
>( newSymbol->
m_Uuid ) = aNewSymbolUuid;
513 wxLogTrace(
traceLibFieldTable,
"createActualDerivedSymbol: Added new symbol to list, size now: %zu",
517 for(
const auto& col :
m_cols )
522 wxLogTrace(
traceLibFieldTable,
"createActualDerivedSymbol: Initialized field data for new symbol" );
529 wxLogTrace(
traceLibFieldTable,
"Created derived symbol '%s' for library '%s', total tracked: %zu",
541 for(
auto& [
name, element] : fieldStore )
543 element.m_currentData = element.m_originalData;
544 element.m_isModified =
false;
545 element.m_currentlyEmpty =
false;
551 for(
const auto& [symId, fieldStore] :
m_dataStore )
553 for(
const auto& [
name, element] : fieldStore )
555 if( element.m_isModified )
567 wxCHECK_RET( aCol >= 0 && aCol < (
int)
m_cols.size(), wxS(
"Invalid column number" ) );
574 if(
m_cols[aCol].m_fieldName == wxS(
"Keywords" ) )
595 wxCHECK( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ),
false );
602 wxCHECK( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ),
false );
603 return m_cols[aCol].m_isCheckbox;
613 if( lhGroup.
m_Refs.size() == 0 )
615 else if( rhGroup.
m_Refs.size() == 0 )
621 [ ascending ](
const wxString& a,
const wxString& b )
630 wxString lhs = dataModel->
GetValue( lhGroup, sortCol ).Trim(
true ).Trim(
false );
631 wxString rhs = dataModel->
GetValue( rhGroup, sortCol ).Trim(
true ).Trim(
false );
633 if( lhs == rhs && lhGroup.
m_Refs.size() > 1 && rhGroup.
m_Refs.size() > 1 )
635 wxString lhRef = lhGroup.
m_Refs[1]->GetRef(
nullptr );
636 wxString rhRef = rhGroup.
m_Refs[1]->GetRef(
nullptr );
637 return local_cmp( lhRef, rhRef );
641 return local_cmp( lhs, rhs );
654 std::sort( row.m_Refs.begin(), row.m_Refs.end(),
657 wxString lhs_ref( lhs->GetRef( nullptr ) );
658 wxString rhs_ref( rhs->GetRef( nullptr ) );
659 return StrNumCmp( lhs_ref, rhs_ref, true ) < 0;
666 return cmp( lhs, rhs, this, m_sortColumn, m_sortAscending );
674 row.m_ItemNumber = itemNumber++;
684 bool matchFound =
false;
689 for(
size_t i = 0; i <
m_cols.size(); ++i )
707 const wxString& aAttributeName )
709 if( aAttributeName == wxS(
"${DNP}" ) )
710 return aSymbol->
GetDNP() ? wxS(
"1" ) : wxS(
"0" );
712 if( aAttributeName == wxS(
"${EXCLUDE_FROM_BOARD}" ) )
715 if( aAttributeName == wxS(
"${EXCLUDE_FROM_BOM}" ) )
718 if( aAttributeName == wxS(
"${EXCLUDE_FROM_SIM}" ) )
721 if( aAttributeName == wxS(
"Power" ) )
722 return aSymbol->
IsPower() ? wxS(
"1" ) : wxS(
"0" );
724 if( aAttributeName == wxS(
"LocalPower" ) )
725 return aSymbol->
IsLocalPower() ? wxS(
"1" ) : wxS(
"0" );
732 const wxString& aAttributeName,
733 const wxString& aValue )
735 if( aAttributeName == wxS(
"${DNP}" ) )
736 aSymbol->
SetDNP( aValue == wxS(
"1" ) );
737 else if( aAttributeName == wxS(
"${EXCLUDE_FROM_BOARD}" ) )
739 else if( aAttributeName == wxS(
"${EXCLUDE_FROM_BOM}" ) )
741 else if( aAttributeName == wxS(
"${EXCLUDE_FROM_SIM}" ) )
743 else if( aAttributeName == wxS(
"LocalPower" ) )
746 if( aValue == wxS(
"0" ) )
751 else if( aAttributeName == wxS(
"Power" ) )
753 if( aValue == wxS(
"0" ) )
759 wxLogDebug(
"Unknown attribute name: %s", aAttributeName );
771 static_cast<WX_GRID*
>( GetView() )->CommitPendingChanges(
true );
773 wxGridTableMessage msg(
this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, 0, (
int)
m_rows.size() );
774 GetView()->ProcessTableMessage( msg );
784 ref->GetName(), ref->m_Uuid.AsString() );
790 std::map<wxString, LIB_DATA_ELEMENT>& fieldStore =
m_dataStore[ref->m_Uuid];
794 auto it = fieldStore.find( col.m_fieldName );
807 bool matchFound =
false;
825 row.m_Refs.push_back( ref );
837 wxGridTableMessage msg(
this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, (
int)
m_rows.size() );
838 GetView()->ProcessTableMessage( msg );
848 std::vector<LIB_DATA_MODEL_ROW> children;
852 bool matchFound =
false;
858 if( children.size() < 2 )
861 std::sort( children.begin(), children.end(),
864 return cmp( lhs, rhs, this, m_sortColumn, m_sortAscending );
868 m_rows.insert(
m_rows.begin() + aRow + 1, children.begin(), children.end() );
870 wxGridTableMessage msg(
this, wxGRIDTABLE_NOTIFY_ROWS_INSERTED, aRow, (
int) children.size() );
871 GetView()->ProcessTableMessage( msg );
877 auto firstChild =
m_rows.begin() + aRow + 1;
878 auto afterLastChild = firstChild;
881 while( afterLastChild !=
m_rows.end() && afterLastChild->m_Flag ==
CHILD_ITEM )
888 m_rows.erase( firstChild, afterLastChild );
890 wxGridTableMessage msg(
this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, aRow + 1, deleted );
891 GetView()->ProcessTableMessage( msg );
908 for(
size_t i = 0; i <
m_rows.size(); ++i )
921 for(
size_t i = 0; i <
m_rows.size(); ++i )
930 std::function<
void()> postApplyHandler )
934 std::map<wxString, LIB_DATA_ELEMENT>& fieldStore =
m_dataStore[symbol->m_Uuid];
936 for(
auto& srcData : fieldStore )
938 const wxString& srcName = srcData.first;
944 symbolChangeHandler( symbol );
959 if( srcName.StartsWith(
"__DERIVED_SYMBOL_" ) && srcName.EndsWith(
"__" ) )
962 if( srcName == wxS(
"Keywords" ) )
964 symbol->SetKeyWords( srcValue );
972 SCH_FIELD* destField = symbol->GetField( srcName );
973 bool userAdded = ( col != -1 &&
m_cols[col].m_userAdded );
976 bool createField = !destField && ( !srcValue.IsEmpty() || userAdded );
980 const VECTOR2I symbolPos = symbol->GetPosition();
983 symbol->AddField( destField );
996 if( !srcValue.IsEmpty() )
1005 destField->
SetText( srcValue );
1014 std::vector<SCH_FIELD*> symbolFields;
1015 symbol->GetFields( symbolFields );
1020 if( field->IsMandatory() )
1024 if( !fieldStore.contains( field->GetName() ) )
1026 symbolChangeHandler( symbol );
1027 symbol->RemoveField( field );
1036 for(
auto& [fieldName, element] : fieldStore )
1038 if( element.m_createDerivedSymbol )
1045 KIID parentUuid( element.m_originalData );
1049 if( sym->m_Uuid == parentUuid )
1066 if( sym->GetName() == element.m_originalData )
1076 wxString actualDerivedName = element.m_derivedSymbolName;
1079 if( actualDerivedName == parentSymbol->
GetName() )
1082 actualDerivedName = parentSymbol->
GetName() +
"_1";
1086 bool nameExists =
true;
1088 while( nameExists && variant < 100 )
1094 if( sym->GetName() == actualDerivedName )
1103 actualDerivedName = parentSymbol->
GetName() +
"_" + wxString::Format(
"%d", variant );
1110 KIID newDerivedSymbolUuid;
1115 element.m_createDerivedSymbol =
false;
1124 if( postApplyHandler )
1148 return wxGRID_VALUE_BOOL;
1150 return wxGridTableBase::GetTypeName( row, col );
1156 wxCHECK( aCol >= 0 && aCol < (
int)
m_cols.size(),
nullptr );
1158 const wxString& fieldName =
m_cols[aCol].m_fieldName;
1164 it->second->IncRef();
1168 wxGridCellRenderer* stripedRenderer =
nullptr;
1173 stripedRenderer->IncRef();
1177 stripedRenderer->IncRef();
1178 return stripedRenderer;
1185 wxCHECK( aCol >= 0 && aCol < (
int)
m_cols.size(),
false );
wxString AsString() const
void SetFieldsOrder(const std::vector< wxString > &aNewOrder)
wxGridCellRenderer * getStripedRenderer(int aCol) const
void SetValue(int aRow, int aCol, const wxString &aValue) override
wxString GetColFieldName(int aCol)
wxString getAttributeValue(const LIB_SYMBOL *, const wxString &aAttributeName)
std::vector< std::pair< LIB_SYMBOL *, wxString > > m_createdDerivedSymbols
static bool cmp(const LIB_DATA_MODEL_ROW &lhGroup, const LIB_DATA_MODEL_ROW &rhGroup, LIB_FIELDS_EDITOR_GRID_DATA_MODEL *dataModel, int sortCol, bool ascending)
std::map< KIID, std::map< wxString, LIB_DATA_ELEMENT > > m_dataStore
static const wxString ITEM_NUMBER_VARIABLE
std::map< wxString, wxGridCellRenderer * > m_stripedRenderers
wxGridCellAttr * GetAttr(int row, int col, wxGridCellAttr::wxAttrKind kind) override
bool ColIsValue(int aCol)
void CreateDerivedSymbolImmediate(int aRow, int aCol, wxString &aNewSymbolName)
bool isStripeableField(int aCol)
wxString GetValue(int aRow, int aCol) override
void RemoveColumn(int aCol)
bool ColIsCheck(int aCol)
void createActualDerivedSymbol(const LIB_SYMBOL *aParentSymbol, const wxString &aNewSymbolName, const KIID &aNewSymbolUuid)
std::vector< LIB_DATA_MODEL_COL > m_cols
void AddColumn(const wxString &aFieldName, const wxString &aLabel, bool aAddedByUser, bool aIsCheckbox)
void ApplyData(std::function< void(LIB_SYMBOL *)> symbolChangeHandler, std::function< void()> postApplyHandler=nullptr)
void ExpandCollapseRow(int aRow)
std::vector< LIB_DATA_MODEL_ROW > m_rows
int GetFieldNameCol(const wxString &aFieldName)
void updateDataStoreSymbolField(const LIB_SYMBOL *aSymbol, const wxString &aFieldName)
void RenameColumn(int aCol, const wxString &newName)
std::vector< LIB_SYMBOL * > m_symbolsList
bool groupMatch(const LIB_SYMBOL *lhRef, const LIB_SYMBOL *rhRef)
int GetDataWidth(int aCol)
void CreateDerivedSymbol(int aRow, int aCol, wxString &aNewSymbolName)
void ClearCell(int aRow, int aCol)
void setAttributeValue(LIB_SYMBOL *aSymbol, const wxString &aAttributeName, const wxString &aValue)
void CollapseRow(int aRow)
wxString GetTypeName(int row, int col) override
LIB_FIELDS_EDITOR_GRID_DATA_MODEL()
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Define a library symbol object.
const LIB_ID & GetLibId() const override
wxString GetKeyWords() const override
bool IsPower() const override
SCH_FIELD * GetField(const wxString &aFieldName)
Find a field within this symbol matching aFieldName; return nullptr if not found.
void SetParent(LIB_SYMBOL *aParent=nullptr)
wxString GetName() const override
SCH_FIELD & GetValueField()
Return reference to the value field.
bool IsLocalPower() const override
virtual void SetName(const wxString &aName)
void SetPosition(const VECTOR2I &aPosition) override
void SetText(const wxString &aText) override
void SetExcludedFromBoard(bool aExcludeFromBoard) override
Set or clear exclude from board netlist flag.
void SetDNP(bool aDNP) override
void SetExcludedFromSim(bool aExcludeFromSim) override
Set or clear the exclude from simulation flag.
bool GetExcludedFromBoard() const override
void SetExcludedFromBOM(bool aExcludeFromBOM) override
Set or clear the exclude from schematic bill of materials flag.
bool GetDNP() const override
Set or clear the 'Do Not Populate' flag.
bool GetExcludedFromBOM() const override
bool GetExcludedFromSim() const override
std::map< int, wxGridCellAttr * > m_colAttrs
bool IsGeneratedField(const wxString &aSource)
Returns true if the string is generated, e.g contains a single text var reference.
@ GROUP_COLLAPSED_DURING_SORT
STRIPED_CELL_RENDERER< wxGridCellStringRenderer > STRIPED_STRING_RENDERER
const wxChar *const traceLibFieldTable
KICOMMON_API wxSize GetTextSize(const wxString &aSingleLine, wxWindow *aWindow)
Return the size of aSingleLine of text when it is rendered in aWindow using whatever font is currentl...
bool WildCompareString(const wxString &pattern, const wxString &string_to_tst, bool case_sensitive)
Compare a string against wild card (* and ?) pattern using the usual rules.
bool m_createDerivedSymbol
wxString m_derivedSymbolName
std::vector< const LIB_SYMBOL * > m_Refs
Definition for symbol library class.
@ USER
The field ID hasn't been set yet; field is invalid.
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
wxString GetCanonicalFieldName(FIELD_T aFieldType)
wxLogTrace helper definitions.
#define INDETERMINATE_STATE
Used for holding indeterminate values, such as with multiple selections holding different values or c...
VECTOR2< int32_t > VECTOR2I