51#include <wx/srchctrl.h>
53#include <wx/textdlg.h>
58#define COLUMN_MARGIN 3
60#define COLUMN_MARGIN 15
107 wxMenuItem* revertMenu = menu.Append(
MYID_REVERT_ROW,
_(
"Revert symbol" ),
108 _(
"Revert the symbol to its last saved state" ), wxITEM_NORMAL );
110 _(
"Clear the cell value" ), wxITEM_NORMAL );
111 menu.AppendSeparator();
113 _(
"Create a new symbol derived from the selected one" ),
117 wxPoint mousePos = wxGetMousePosition();
118 wxPoint gridPt =
m_grid->ScreenToClient( mousePos );
121 int headerHeight =
m_grid->GetColLabelSize();
122 gridPt.y -= headerHeight;
126 int row =
m_grid->YToRow( gridPt.y );
127 int col =
m_grid->XToCol( gridPt.x );
128 m_grid->SetGridCursor( row, col );
130 revertMenu->Enable(
m_dataModel->IsCellEdited( row, col ) );
131 clearMenu->Enable( !
m_dataModel->IsCellClear( row, col ) );
132 deriveMenu->Enable(
m_dataModel->IsRowSingleSymbol( row ) );
137 menu.AppendSeparator();
142 menu.AppendSeparator();
150 int row =
m_grid->GetGridCursorRow();
151 int col =
m_grid->GetGridCursorCol();
155 if(
m_grid->CommitPendingChanges(
false ) )
161 m_dlg->ClearModify();
167 if(
m_grid->CommitPendingChanges(
false ) )
173 m_dlg->ClearModify();
184 wxArrayString symbolNames;
188 [&](
const wxString& newName ) ->
bool
190 return symbolNames.Index( newName ) == wxNOT_FOUND;
198 wxString derivedName = dlg.
GetName();
200 m_dataModel->CreateDerivedSymbolImmediate( row, col, derivedName );
210 wxString fpid =
m_grid->GetCellValue( row, col );
214 if( frame->ShowModal( &fpid,
m_dlg ) )
215 m_grid->SetCellValue( row, col, fpid );
222 wxString datasheet_uri =
m_grid->GetCellValue( row, col );
227 if( !
m_grid->CommitPendingChanges(
false ) )
235 m_dlg->ShowHideColumn( col, show );
237 wxString fieldName =
m_dataModel->GetColFieldName( col );
286 wxGridCellAttr* attr =
new wxGridCellAttr;
287 attr->SetReadOnly(
true );
290 attr =
new wxGridCellAttr;
291 attr->SetRenderer(
new wxGridCellBoolRenderer() );
293 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
296 attr =
new wxGridCellAttr;
297 attr->SetRenderer(
new wxGridCellBoolRenderer() );
299 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
305 m_filter->SetDescriptiveText(
_(
"Filter" ) );
309 m_grid->UseNativeColHeader(
true );
313 m_grid->SetSelectionMode( wxGrid::wxGridSelectCells );
332 CallAfter( [
this, cfg]()
359 for(
int i = 0; i <
m_grid->GetNumberCols(); i++ )
361 if(
m_grid->IsColShown( i ) )
363 std::string fieldName(
m_dataModel->GetColFieldName( i ).ToUTF8() );
376 m_grid->PopEventHandler(
true );
386 if( aIsLeftPanelCollapsed )
401 wxGridCellAttr* attr =
new wxGridCellAttr;
402 attr->SetReadOnly(
false );
408 wxString symbolNetlist;
417 pins.push_back(
pin->GetNumber() +
' ' +
pin->GetShownName() );
419 if( !pins.IsEmpty() )
422 symbolNetlist << wxS(
"\r" );
425 if( !fpFilters.IsEmpty() )
428 symbolNetlist << wxS(
"\r" );
442 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
454 attr->SetEditor(
m_grid->GetDefaultEditor() );
463 wxSize defaultDlgSize = ConvertDialogToPixels( wxSize( 600, 300 ) );
466 m_grid->AutoSizeColumns(
false );
468 bool sortAscending =
true;
474 if(
m_dataModel->GetSortCol() == 0 && nameCol != -1 )
477 sortAscending =
true;
481 for(
int col = 0; col <
m_grid->GetNumberCols(); ++col )
507 std::string key(
m_dataModel->GetColFieldName( col ).ToUTF8() );
517 int maxWidth = defaultDlgSize.x / 3;
519 m_grid->SetColSize( col, std::clamp( textWidth, 100, maxWidth ) );
529 m_grid->SetSortingColumn( sortCol, sortAscending );
539 case SCOPE::SCOPE_LIBRARY:
m_choiceScope->SetSelection( 0 );
break;
540 case SCOPE::SCOPE_RELATED_SYMBOLS:
m_choiceScope->SetSelection( 1 );
break;
554 wxString libName =
m_parent->GetTreeLIBID().GetLibNickname();
556 if( aSymbolNames.IsEmpty() )
559 wxMessageBox( wxString::Format(
_(
"No related symbols found in library '%s'." ), libName ) );
561 wxMessageBox( wxString::Format(
_(
"No symbols found in library '%s'." ), libName ) );
567 for(
const wxString& symbolName : aSymbolNames )
571 if( canvasSymbol && canvasSymbol->
GetLibraryName() == libName && canvasSymbol->
GetName() == symbolName )
585 wxLogWarning( wxString::Format(
_(
"Error loading symbol '%s': %s" ), symbolName, ioe.
What() ) );
593 wxMessageBox(
_(
"No related symbols could be loaded from the library." ) );
595 wxMessageBox(
_(
"No symbols could be loaded from the library." ) );
604 if( !
m_grid->CommitPendingChanges() )
607 if( !wxDialog::TransferDataFromWindow() )
610 bool updateCanvas =
false;
617 if(
m_parent->GetCurSymbol() == symbol )
623 auto createdSymbols =
m_dataModel->GetAndClearCreatedDerivedSymbols();
625 wxLogTrace(
traceLibFieldTable,
"Post-apply handler: found %zu created derived symbols",
626 createdSymbols.size() );
628 for(
const auto& [symbol, libraryName] : createdSymbols )
630 if( !libraryName.IsEmpty() )
635 m_parent->GetLibManager().UpdateSymbol( symbol, libraryName );
640 if( !createdSymbols.empty() )
642 wxLogTrace(
traceLibFieldTable,
"Syncing libraries due to %zu new symbols", createdSymbols.size() );
645 std::vector<LIB_SYMBOL*> symbolsToPreserve;
646 for(
const auto& [symbol, libraryName] : createdSymbols )
648 symbolsToPreserve.push_back( symbol );
660 if( existingSymbol->m_Uuid == symbol->
m_Uuid )
679 wxLogTrace(
traceLibFieldTable,
"About to rebuild grid rows to include new symbols" );
697 wxTextEntryDialog dlg(
this,
_(
"New field name:" ),
_(
"Add Field" ) );
699 if( dlg.ShowModal() != wxID_OK )
702 wxString fieldName = dlg.GetValue();
704 if( fieldName.IsEmpty() )
710 for(
int i = 0; i <
m_dataModel->GetNumberCols(); ++i )
714 DisplayError(
this, wxString::Format(
_(
"Field name '%s' already in use." ), fieldName ) );
732 return IsOK(
this, wxString::Format(
_(
"Are you sure you want to remove the field '%s'?" ),
754 if( selectedRows.empty() )
757 int row = selectedRows[0];
761 int col =
m_dataModel->GetFieldNameCol( fieldName );
762 wxCHECK_RET( col != -1, wxS(
"Existing field name missing from data model" ) );
764 wxTextEntryDialog dlg(
this,
_(
"New field name:" ),
_(
"Rename Field" ), fieldName );
766 if( dlg.ShowModal() != wxID_OK )
769 wxString newFieldName = dlg.GetValue();
771 if( newFieldName == fieldName )
774 if(
m_dataModel->GetFieldNameCol( newFieldName ) != -1 )
776 DisplayError(
this, wxString::Format(
_(
"Field name '%s' already exists." ), newFieldName ) );
800#if defined( __WXOSX__ )
801 wxPoint pos = aEvent.GetPosition();
802 wxRect ctrlRect =
m_filter->GetScreenRect();
803 int buttonWidth = ctrlRect.GetHeight();
806 if(
m_filter->IsSearchButtonVisible() && pos.x < buttonWidth )
807 SetCursor( wxCURSOR_ARROW );
808 else if(
m_filter->IsCancelButtonVisible() && pos.x > ctrlRect.GetWidth() - buttonWidth )
809 SetCursor( wxCURSOR_ARROW );
811 SetCursor( wxCURSOR_IBEAM );
819 wxString targetLib =
m_parent->GetTargetLibId().GetLibNickname();
820 wxString targetSymbol =
m_parent->GetTargetLibId().GetLibItemName();
821 wxArrayString symbolNames;
823 SetTitle( wxString::Format(
_(
"Symbol Fields Table ('%s' Library)" ), targetLib ) );
827 if(
m_scope == SCOPE::SCOPE_RELATED_SYMBOLS )
830 std::shared_ptr<LIB_SYMBOL> root = symbol ? symbol->
GetRootSymbol() :
nullptr;
834 symbolNames.Add( root->GetName() );
858 switch( aEvent.GetSelection() )
860 case 0:
setScope( SCOPE::SCOPE_LIBRARY );
break;
861 case 1:
setScope( SCOPE::SCOPE_RELATED_SYMBOLS );
break;
881 if(
m_dataModel->IsExpanderColumn( event.GetCol() ) )
885 m_grid->SetGridCursor( event.GetRow(), event.GetCol() );
900 wxPoint mousePos = wxGetMousePosition();
901 wxPoint gridPt =
m_grid->ScreenToClient( mousePos );
903 int row =
m_grid->YToRow( gridPt.y );
904 int col =
m_grid->XToCol( gridPt.x );
906 if ( row != -1 && col != -1 )
907 m_grid->SetGridCursor( row, col );
936 int remainingWidth =
m_viewControlsGrid->GetSize().GetX() - showColWidth - groupByColWidth;
987 m_grid->CommitPendingChanges(
true );
999 EndModal( wxID_CANCEL );
1006 EndModal( wxID_OK );
1012 m_grid->CommitPendingChanges(
true );
1033 auto addMandatoryField =
1034 [&](
FIELD_T fieldId,
bool show,
bool groupBy )
1049 AddField( wxS(
"Keywords" ),
_(
"Keywords" ),
true,
false );
1052 AddField( wxS(
"${EXCLUDE_FROM_BOM}" ),
_(
"Exclude From BOM" ),
true,
false,
false,
true );
1053 AddField( wxS(
"${EXCLUDE_FROM_SIM}" ),
_(
"Exclude From Simulation" ),
true,
false,
false,
true );
1054 AddField( wxS(
"${EXCLUDE_FROM_BOARD}" ),
_(
"Exclude From Board" ),
true,
false,
false,
true );
1056 AddField( wxS(
"Power" ),
_(
"Power Symbol" ),
true,
false,
false,
true );
1057 AddField( wxS(
"LocalPower" ),
_(
"Local Power Symbol" ),
true,
false,
false,
true );
1061 std::set<wxString> userFieldNames;
1065 std::vector< SCH_FIELD* > fields;
1066 symbol->GetFields( fields );
1070 if( !field->IsMandatory() && !field->IsPrivate() )
1071 userFieldNames.insert( field->GetName() );
1075 for(
const wxString& fieldName : userFieldNames )
1081 bool groupBy,
bool addedByUser,
bool aIsCheckbox )
1094 m_dataModel->AddColumn( aFieldName, aLabelValue, addedByUser, aIsCheckbox );
1096 wxGridTableMessage msg(
m_dataModel, wxGRIDTABLE_NOTIFY_COLS_APPENDED, 1 );
1097 m_grid->ProcessTableMessage( msg );
1100 [&]() -> std::pair<int, int>
1111 int col =
m_dataModel->GetFieldNameCol( fieldName );
1112 wxCHECK_RET( col != -1, wxS(
"Field name not found" ) );
1120 int col =
m_dataModel->GetFieldNameCol( oldName );
1121 wxCHECK_RET( col != -1, wxS(
"Existing field name missing from data model" ) );
1136 int sortCol = aEvent.GetCol();
1137 std::string key(
m_dataModel->GetColFieldName( sortCol ).ToUTF8() );
1142 if(
m_grid->IsSortingBy( sortCol ) )
1145 ascending = !
m_grid->IsSortOrderAscending();
1160 int origPos = aEvent.GetCol();
1165 for(
int i = 0; i <
m_grid->GetNumberCols(); i++ )
1167 if(
m_grid->IsColShown( i ) )
1169 std::string fieldName(
m_dataModel->GetColFieldName( i ).ToUTF8() );
1177 int newPos =
m_grid->GetColPos( origPos );
1180 if( newPos < origPos )
1213 int row = aEvent.GetRow();
1215 wxCHECK( row < m_viewControlsGrid->GetNumberRows(), );
1217 switch( aEvent.GetCol() )
1223 int dataCol =
m_dataModel->GetFieldNameCol( fieldName );
1228 m_grid->SetColLabelValue( dataCol, label );
1241 int dataCol =
m_dataModel->GetFieldNameCol( fieldName );
1253 int dataCol =
m_dataModel->GetFieldNameCol( fieldName );
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
STD_BITMAP_BUTTON * m_bRefresh
STD_BITMAP_BUTTON * m_sidebarButton
wxSplitterWindow * m_splitterMainWindow
DIALOG_LIB_FIELDS_TABLE_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Symbol Fields Table ('%s' Library)"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER)
STD_BITMAP_BUTTON * m_renameFieldButton
wxCheckBox * m_groupSymbolsBox
STD_BITMAP_BUTTON * m_addFieldButton
WX_GRID * m_viewControlsGrid
STD_BITMAP_BUTTON * m_removeFieldButton
bool TransferDataToWindow() override
void OnTableColSize(wxGridSizeEvent &event) override
void OnFilterMouseMoved(wxMouseEvent &event) override
void OnScope(wxCommandEvent &event) override
void OnTableItemContextMenu(wxGridEvent &event) override
void OnGroupSymbolsToggled(wxCommandEvent &event) override
void setScope(SCOPE aScope)
void SetupColumnProperties(int aCol)
void OnSidebarToggle(wxCommandEvent &event) override
void OnAddField(wxCommandEvent &event) override
void ShowHideColumn(int aCol, bool aShow)
~DIALOG_LIB_FIELDS_TABLE() override
LIB_FIELDS_EDITOR_GRID_DATA_MODEL * m_dataModel
void OnTableCellClick(wxGridEvent &event) override
void OnViewControlsCellChanged(wxGridEvent &aEvent) override
void RenameField(const wxString &oldName, const wxString &newName)
void OnClose(wxCloseEvent &event) override
void OnOk(wxCommandEvent &event) override
void OnTableValueChanged(wxGridEvent &event) override
void AddField(const wxString &aFieldName, const wxString &aLabelValue, bool show, bool groupBy, bool addedByUser=false, bool aIsCheckbox=false)
void OnApply(wxCommandEvent &event) override
SYMBOL_EDIT_FRAME * m_parent
std::vector< LIB_SYMBOL * > m_symbolsList
void OnRegroupSymbols(wxCommandEvent &event) override
void OnSizeViewControlsGrid(wxSizeEvent &event) override
void OnCancel(wxCommandEvent &event) override
void OnRenameField(wxCommandEvent &event) override
void RemoveField(const wxString &fieldName)
DIALOG_LIB_FIELDS_TABLE(SYMBOL_EDIT_FRAME *parent, DIALOG_LIB_FIELDS_TABLE::SCOPE aScope)
void OnColSort(wxGridEvent &aEvent)
VIEW_CONTROLS_GRID_DATA_MODEL * m_viewControlsDataModel
void OnColMove(wxGridEvent &aEvent)
void SetupAllColumnProperties()
void setSideBarButtonLook(bool aIsLeftPanelCollapsed)
bool TransferDataFromWindow() override
void loadSymbols(const wxArrayString &aSymbolNames)
void OnFilterText(wxCommandEvent &event) override
void OnRemoveField(wxCommandEvent &event) override
wxString GetName() const override
int vertPixelsFromDU(int y) const
Convert an integer number of dialog units to pixels, vertically.
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
void SetupStandardButtons(std::map< int, wxString > aLabels={})
int horizPixelsFromDU(int x) const
Convert an integer number of dialog units to pixels, horizontally.
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
The base class for create windows for drawing purpose.
A general-purpose text renderer for WX_GRIDs backed by WX_GRID_TABLE_BASE tables that can handle draw...
GRID_TRICKS(WX_GRID *aGrid)
virtual void doPopupSelection(wxCommandEvent &event)
virtual void showPopupMenu(wxMenu &menu, wxGridEvent &aEvent)
WX_GRID * m_grid
I don't own the grid, but he owns me.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
wxString AsString() const
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
static const wxString SYMBOL_NAME
LIB_FIELDS_EDITOR_GRID_DATA_MODEL * m_dataModel
LIB_FIELDS_EDITOR_GRID_TRICKS(DIALOG_LIB_FIELDS_TABLE *aParent, WX_GRID *aGrid, VIEW_CONTROLS_GRID_DATA_MODEL *aViewFieldsData, LIB_FIELDS_EDITOR_GRID_DATA_MODEL *aDataModel)
VIEW_CONTROLS_GRID_DATA_MODEL * m_viewControlsDataModel
DIALOG_LIB_FIELDS_TABLE * m_dlg
void doPopupSelection(wxCommandEvent &event) override
void showPopupMenu(wxMenu &menu, wxGridEvent &aEvent) override
Symbol library management helper that is specific to the symbol library editor frame.
Define a library symbol object.
std::vector< const SCH_PIN * > GetGraphicalPins(int aUnit=0, int aBodyStyle=0) const
Graphical pins: Return schematic pin objects as drawn (unexpanded), filtered by unit/body.
const wxString GetLibraryName() const
std::shared_ptr< LIB_SYMBOL > GetRootSymbol() const
Get the parent symbol that does not have another parent.
wxString GetName() const override
wxArrayString GetFPFilters() const
wxString GetLibNickname() const override
Sets the Description field text value.
static SEARCH_STACK * SchSearchS(PROJECT *aProject)
Accessor for Eeschema search stack.
PANEL_LIB_FIELDS_TABLE m_LibFieldEditor
The symbol library editor main window.
LIB_SYMBOL * GetBufferedSymbol(const wxString &aSymbolName, const wxString &aLibrary)
Return the symbol copy from the buffer.
void GetSymbolNames(const wxString &aLibName, wxArrayString &aSymbolNames, SYMBOL_NAME_FILTER aFilter=SYMBOL_NAME_FILTER::ALL)
size_t GetDerivedSymbolNames(const wxString &aSymbolName, const wxString &aLibraryName, wxArrayString &aList)
Fetch all of the symbols derived from a aSymbolName into aList.
VIEW_CONTROLS_GRID_TRICKS(WX_GRID *aGrid)
void doPopupSelection(wxCommandEvent &event) override
wxString GetGeneratedFieldDisplayName(const wxString &aSource)
Returns any variables unexpanded, e.g.
bool IsGeneratedField(const wxString &aSource)
Returns true if the string is generated, e.g contains a single text var reference.
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Display a dialog with Save, Cancel and Discard Changes buttons.
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
This file is part of the common library.
DIALOG_LIB_NEW_SYMBOL DIALOG_NEW_SYMBOL
@ MYID_CREATE_DERIVED_SYMBOL
bool GetAssociatedDocument(wxWindow *aParent, const wxString &aDocName, PROJECT *aProject, SEARCH_STACK *aPaths, std::vector< EMBEDDED_FILES * > aFilesStack)
Open a document (file) with the suitable browser.
This file is part of the common library.
#define DISPLAY_NAME_COLUMN
#define SHOW_FIELD_COLUMN
@ FRAME_FOOTPRINT_CHOOSER
@ GRIDTRICKS_FIRST_SHOWHIDE
@ GRIDTRICKS_FIRST_CLIENT_ID
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...
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
std::map< std::string, int > field_widths
bool FieldNamesAreDuplicates(const wxString &aLhs, const wxString &aRhs, std::initializer_list< FIELD_T > aMandatoryFields)
Test whether two field names should be treated as duplicates for the purposes of field name uniquenes...
wxString GetDefaultFieldName(FIELD_T aFieldId, bool aTranslateForHI)
Return a default symbol field name for a mandatory field type.
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
@ DESCRIPTION
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ DATASHEET
name of datasheet
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
wxString GetCanonicalFieldName(FIELD_T aFieldType)
nlohmann::json_schema::json_validator validator
wxLogTrace helper definitions.