KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_lib_fields_table.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2025 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
21
22#include <set>
23
24#include <bitmaps.h>
25#include <common.h>
26#include <confirm.h>
27#include <eda_doc.h>
29#include <grid_tricks.h>
30#include <kiface_base.h>
31#include <kiplatform/ui.h>
32#include <kiway_player.h>
33#include <string_utils.h>
35#include <project_sch.h>
36#include <symbol_edit_frame.h>
38#include <template_fieldnames.h>
44#include <tools/sch_actions.h>
45#include <tool/tool_manager.h>
46#include <trace_helpers.h>
47#include <fields_data_model.h>
49#include <wx/arrstr.h>
50#include <wx/msgdlg.h>
51#include <wx/srchctrl.h>
52
53#include <wx/textdlg.h>
54
56
57#ifdef __WXMAC__
58#define COLUMN_MARGIN 3
59#else
60#define COLUMN_MARGIN 15
61#endif
62
63
65{
66public:
68 GRID_TRICKS( aGrid )
69 {}
70
71protected:
72 void doPopupSelection( wxCommandEvent& event ) override
73 {
74 if( event.GetId() >= GRIDTRICKS_FIRST_SHOWHIDE )
75 m_grid->PostSizeEvent();
76
78 }
79};
80
81
82enum
83{
89};
90
91
93{
94public:
96 VIEW_CONTROLS_GRID_DATA_MODEL* aViewFieldsData,
98 GRID_TRICKS( aGrid ),
99 m_dlg( aParent ),
100 m_viewControlsDataModel( aViewFieldsData ),
101 m_dataModel( aDataModel )
102 {}
103
104protected:
105 void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent ) override
106 {
107 wxMenuItem* revertMenu = menu.Append( MYID_REVERT_ROW, _( "Revert symbol" ),
108 _( "Revert the symbol to its last saved state" ), wxITEM_NORMAL );
109 wxMenuItem* clearMenu = menu.Append( MYID_CLEAR_CELL, _( "Clear cell" ),
110 _( "Clear the cell value" ), wxITEM_NORMAL );
111 menu.AppendSeparator();
112 wxMenuItem* deriveMenu = menu.Append( MYID_CREATE_DERIVED_SYMBOL, _( "Create Derived Symbol" ),
113 _( "Create a new symbol derived from the selected one" ),
114 wxITEM_NORMAL );
115
116 // Get global mouse position and convert to grid client coords
117 wxPoint mousePos = wxGetMousePosition();
118 wxPoint gridPt = m_grid->ScreenToClient( mousePos );
119
120 // Offset by grid header (column label) height so header area doesn't map to a row.
121 int headerHeight = m_grid->GetColLabelSize();
122 gridPt.y -= headerHeight;
123 if ( gridPt.y < 0 )
124 gridPt.y = 0;
125
126 int row = m_grid->YToRow( gridPt.y );
127 int col = m_grid->XToCol( gridPt.x );
128 m_grid->SetGridCursor( row, col );
129
130 revertMenu->Enable( m_dataModel->IsCellEdited( row, col ) );
131 clearMenu->Enable( !m_dataModel->IsCellClear( row, col ) );
132 deriveMenu->Enable( m_dataModel->IsRowSingleSymbol( row ) );
133
134 if( m_dataModel->GetColFieldName( col ) == GetCanonicalFieldName( FIELD_T::FOOTPRINT ) )
135 {
136 menu.Append( MYID_SELECT_FOOTPRINT, _( "Select Footprint..." ), _( "Browse for footprint" ) );
137 menu.AppendSeparator();
138 }
139 else if( m_dataModel->GetColFieldName( col ) == GetCanonicalFieldName( FIELD_T::DATASHEET ) )
140 {
141 menu.Append( MYID_SHOW_DATASHEET, _( "Show Datasheet" ), _( "Show datasheet in browser" ) );
142 menu.AppendSeparator();
143 }
144
145 GRID_TRICKS::showPopupMenu( menu, aEvent );
146 }
147
148 void doPopupSelection( wxCommandEvent& event ) override
149 {
150 int row = m_grid->GetGridCursorRow();
151 int col = m_grid->GetGridCursorCol();
152
153 if( event.GetId() == MYID_REVERT_ROW )
154 {
155 if( m_grid->CommitPendingChanges( false ) )
156 m_dataModel->RevertRow( row );
157
158 if( m_dataModel->IsEdited() )
159 m_dlg->OnModify();
160 else
161 m_dlg->ClearModify();
162
163 m_grid->ForceRefresh();
164 }
165 else if( event.GetId() == MYID_CLEAR_CELL )
166 {
167 if( m_grid->CommitPendingChanges( false ) )
168 m_dataModel->ClearCell( row, col );
169
170 if( m_dataModel->IsEdited() )
171 m_dlg->OnModify();
172 else
173 m_dlg->ClearModify();
174
175 m_grid->ForceRefresh();
176 }
177 else if( event.GetId() == MYID_CREATE_DERIVED_SYMBOL )
178 {
179 EDA_DRAW_FRAME* frame = dynamic_cast<EDA_DRAW_FRAME*>( m_dlg->GetParent() );
180 wxCHECK( frame, /* void */ );
181
182 const LIB_SYMBOL* parentSymbol = m_dataModel->GetSymbolForRow( row );
183
184 wxArrayString symbolNames;
185 m_dataModel->GetSymbolNames( symbolNames );
186
187 auto validator =
188 [&]( const wxString& newName ) -> bool
189 {
190 return symbolNames.Index( newName ) == wxNOT_FOUND;
191 };
192
193 DIALOG_NEW_SYMBOL dlg( frame, symbolNames, parentSymbol->GetName(), validator );
194
195 if( dlg.ShowModal() != wxID_OK )
196 return;
197
198 wxString derivedName = dlg.GetName();
199
200 m_dataModel->CreateDerivedSymbolImmediate( row, col, derivedName );
201
202 if( m_dataModel->IsEdited() )
203 m_dlg->OnModify();
204
205 m_grid->ForceRefresh();
206 }
207 else if( event.GetId() == MYID_SELECT_FOOTPRINT )
208 {
209 // pick a footprint using the footprint picker.
210 wxString fpid = m_grid->GetCellValue( row, col );
211
212 if( KIWAY_PLAYER* frame = m_dlg->Kiway().Player( FRAME_FOOTPRINT_CHOOSER, true, m_dlg ) )
213 {
214 if( frame->ShowModal( &fpid, m_dlg ) )
215 m_grid->SetCellValue( row, col, fpid );
216
217 frame->Destroy();
218 }
219 }
220 else if (event.GetId() == MYID_SHOW_DATASHEET )
221 {
222 wxString datasheet_uri = m_grid->GetCellValue( row, col );
223 GetAssociatedDocument( m_dlg, datasheet_uri, &m_dlg->Prj(), PROJECT_SCH::SchSearchS( &m_dlg->Prj() ) );
224 }
225 else if( event.GetId() >= GRIDTRICKS_FIRST_SHOWHIDE )
226 {
227 if( !m_grid->CommitPendingChanges( false ) )
228 return;
229
230 // Pop-up column order is the order of the shown fields, not the viewControls order
231 col = event.GetId() - GRIDTRICKS_FIRST_SHOWHIDE;
232
233 bool show = !m_dataModel->GetShowColumn( col );
234
235 m_dlg->ShowHideColumn( col, show );
236
237 wxString fieldName = m_dataModel->GetColFieldName( col );
238
239 for( row = 0; row < m_viewControlsDataModel->GetNumberRows(); row++ )
240 {
241 if( m_viewControlsDataModel->GetCanonicalFieldName( row ) == fieldName )
242 m_viewControlsDataModel->SetValueAsBool( row, SHOW_FIELD_COLUMN, show );
243 }
244
245 if( m_viewControlsDataModel->GetView() )
246 m_viewControlsDataModel->GetView()->ForceRefresh();
247 }
248 else
249 {
251 }
252 }
253
257};
258
259
261 DIALOG_LIB_FIELDS_TABLE_BASE( parent, wxID_ANY ),
262 m_parent( parent ),
263 m_scope( aScope ),
264 m_viewControlsDataModel( nullptr ),
265 m_dataModel( nullptr )
266{
268
272
274
276
277 m_viewControlsGrid->UseNativeColHeader( true );
279
280 // must be done after SetTable(), which appears to re-set it
281 m_viewControlsGrid->SetSelectionMode( wxGrid::wxGridSelectCells );
282
283 // add Cut, Copy, and Paste to wxGrid
285
286 wxGridCellAttr* attr = new wxGridCellAttr;
287 attr->SetReadOnly( true );
288 m_viewControlsDataModel->SetColAttr( attr, DISPLAY_NAME_COLUMN );
289
290 attr = new wxGridCellAttr;
291 attr->SetRenderer( new wxGridCellBoolRenderer() );
292 attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
293 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
294 m_viewControlsDataModel->SetColAttr( attr, SHOW_FIELD_COLUMN );
295
296 attr = new wxGridCellAttr;
297 attr->SetRenderer( new wxGridCellBoolRenderer() );
298 attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
299 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
300 m_viewControlsDataModel->SetColAttr( attr, GROUP_BY_COLUMN );
301
302 // Compress the view controls grid. (We want it to look different from the fields grid.)
303 m_viewControlsGrid->SetDefaultRowSize( m_viewControlsGrid->GetDefaultRowSize() - FromDIP( 4 ) );
304
305 m_filter->SetDescriptiveText( _( "Filter" ) );
306
308
309 m_grid->UseNativeColHeader( true );
310 m_grid->SetTable( m_dataModel, true );
311
312 // must be done after SetTable(), which appears to re-set it
313 m_grid->SetSelectionMode( wxGrid::wxGridSelectCells );
314
315 // add Cut, Copy, and Paste to wxGrid
317 m_dataModel ) );
318
320 m_grid->ClearSelection();
321
323
325
326 SetSize( wxSize( horizPixelsFromDU( 600 ), vertPixelsFromDU( 300 ) ) );
327
328 SYMBOL_EDITOR_SETTINGS::PANEL_LIB_FIELDS_TABLE& cfg = m_parent->libeditconfig()->m_LibFieldEditor;
329
330 m_viewControlsGrid->ShowHideColumns( "0 2 3" );
331
332 CallAfter( [this, cfg]()
333 {
334 if( cfg.sidebar_collapsed )
336 else
337 m_splitterMainWindow->SetSashPosition( cfg.sash_pos );
338
340 } );
341
342 Center();
343
344 // Connect Events
345 m_grid->Bind( wxEVT_GRID_COL_SORT, &DIALOG_LIB_FIELDS_TABLE::OnColSort, this );
346 m_grid->Bind( wxEVT_GRID_COL_MOVE, &DIALOG_LIB_FIELDS_TABLE::OnColMove, this );
347 m_grid->Bind( wxEVT_GRID_CELL_LEFT_CLICK, &DIALOG_LIB_FIELDS_TABLE::OnTableCellClick, this );
348 m_viewControlsGrid->Bind( wxEVT_GRID_CELL_CHANGED, &DIALOG_LIB_FIELDS_TABLE::OnViewControlsCellChanged, this );
349}
350
351
353{
354 SYMBOL_EDITOR_SETTINGS::PANEL_LIB_FIELDS_TABLE& cfg = m_parent->libeditconfig()->m_LibFieldEditor;
355
356 if( !cfg.sidebar_collapsed )
357 cfg.sash_pos = m_splitterMainWindow->GetSashPosition();
358
359 for( int i = 0; i < m_grid->GetNumberCols(); i++ )
360 {
361 if( m_grid->IsColShown( i ) )
362 {
363 std::string fieldName( m_dataModel->GetColFieldName( i ).ToUTF8() );
364 cfg.field_widths[fieldName] = m_grid->GetColSize( i );
365 }
366 }
367
368 // Disconnect Events
369 m_grid->Unbind( wxEVT_GRID_COL_SORT, &DIALOG_LIB_FIELDS_TABLE::OnColSort, this );
370 m_grid->Unbind( wxEVT_GRID_COL_MOVE, &DIALOG_LIB_FIELDS_TABLE::OnColMove, this );
371 m_grid->Unbind( wxEVT_GRID_CELL_LEFT_CLICK, &DIALOG_LIB_FIELDS_TABLE::OnTableCellClick, this );
372 m_viewControlsGrid->Unbind( wxEVT_GRID_CELL_CHANGED, &DIALOG_LIB_FIELDS_TABLE::OnViewControlsCellChanged, this );
373
374 // Delete the GRID_TRICKS.
375 m_viewControlsGrid->PopEventHandler( true );
376 m_grid->PopEventHandler( true );
377
378 // we gave ownership of m_viewControlsDataModel & m_dataModel to the wxGrids...
379}
380
381
382void DIALOG_LIB_FIELDS_TABLE::setSideBarButtonLook( bool aIsLeftPanelCollapsed )
383{
384 // Set bitmap and tooltip according to left panel visibility
385
386 if( aIsLeftPanelCollapsed )
387 {
389 m_sidebarButton->SetToolTip( _( "Expand left panel" ) );
390 }
391 else
392 {
394 m_sidebarButton->SetToolTip( _( "Collapse left panel" ) );
395 }
396}
397
398
400{
401 wxGridCellAttr* attr = new wxGridCellAttr;
402 attr->SetReadOnly( false );
403
404 // Set some column types to specific editors
405 if( m_dataModel->GetColFieldName( aCol ) == GetCanonicalFieldName( FIELD_T::FOOTPRINT ) )
406 {
407 // Create symbol netlist for footprint picker
408 wxString symbolNetlist;
409
410 if( !m_symbolsList.empty() )
411 {
412 // Use the first symbol's netlist (all symbols in lib should have similar pin structure)
413 LIB_SYMBOL* symbol = m_symbolsList[0];
414 wxArrayString pins;
415
416 for( SCH_PIN* pin : symbol->GetGraphicalPins( 0 /* all units */, 1 /* single bodyStyle */ ) )
417 pins.push_back( pin->GetNumber() + ' ' + pin->GetShownName() );
418
419 if( !pins.IsEmpty() )
420 symbolNetlist << EscapeString( wxJoin( pins, '\t' ), CTX_LINE );
421
422 symbolNetlist << wxS( "\r" );
423
424 wxArrayString fpFilters = symbol->GetFPFilters();
425 if( !fpFilters.IsEmpty() )
426 symbolNetlist << EscapeString( wxJoin( fpFilters, ' ' ), CTX_LINE );
427
428 symbolNetlist << wxS( "\r" );
429 }
430
431 attr->SetEditor( new GRID_CELL_FPID_EDITOR( this, symbolNetlist ) );
432 m_dataModel->SetColAttr( attr, aCol );
433 }
434 else if( m_dataModel->GetColFieldName( aCol ) == GetCanonicalFieldName( FIELD_T::DATASHEET ) )
435 {
436 // set datasheet column viewer button
437 attr->SetEditor( new GRID_CELL_URL_EDITOR( this, PROJECT_SCH::SchSearchS( &Prj() ) ) );
438 m_dataModel->SetColAttr( attr, aCol );
439 }
440 else if( m_dataModel->ColIsCheck( aCol ) )
441 {
442 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
443 attr->SetRenderer( new GRID_CELL_CHECKBOX_RENDERER() );
444 m_dataModel->SetColAttr( attr, aCol );
445 }
446 else if( IsGeneratedField( m_dataModel->GetColFieldName( aCol ) ) )
447 {
448 attr->SetReadOnly();
449 m_dataModel->SetColAttr( attr, aCol );
450 }
451 else
452 {
453 attr->SetRenderer( new GRID_CELL_TEXT_RENDERER() );
454 attr->SetEditor( m_grid->GetDefaultEditor() );
455 m_dataModel->SetColAttr( attr, aCol );
456 }
457}
458
459
461{
462 SYMBOL_EDITOR_SETTINGS* cfg = m_parent->GetSettings();
463 wxSize defaultDlgSize = ConvertDialogToPixels( wxSize( 600, 300 ) );
464
465 // Restore column sorting order and widths
466 m_grid->AutoSizeColumns( false );
467 int sortCol = 0;
468 bool sortAscending = true;
469
470 // Find the symbol name column for initial sorting
471 int nameCol = m_dataModel->GetFieldNameCol( LIB_FIELDS_EDITOR_GRID_DATA_MODEL::SYMBOL_NAME );
472
473 // Set initial sort to VALUE field (ascending) if no previous sort preference exists
474 if( m_dataModel->GetSortCol() == 0 && nameCol != -1 )
475 {
476 sortCol = nameCol;
477 sortAscending = true;
478 m_dataModel->SetSorting( sortCol, sortAscending );
479 }
480
481 for( int col = 0; col < m_grid->GetNumberCols(); ++col )
482 {
484
485 if( col == m_dataModel->GetSortCol() )
486 {
487 sortCol = col;
488 sortAscending = m_dataModel->GetSortAsc();
489 }
490 }
491
492 // sync m_grid's column visibilities to Show checkboxes in m_viewControlsGrid
493 for( int i = 0; i < m_viewControlsDataModel->GetNumberRows(); ++i )
494 {
495 int col = m_dataModel->GetFieldNameCol( m_viewControlsDataModel->GetCanonicalFieldName( i ) );
496
497 if( col == -1 )
498 continue;
499
500 bool show = m_viewControlsDataModel->GetValueAsBool( i, SHOW_FIELD_COLUMN );
501 m_dataModel->SetShowColumn( col, show );
502
503 if( show )
504 {
505 m_grid->ShowCol( col );
506
507 std::string key( m_dataModel->GetColFieldName( col ).ToUTF8() );
508
509 if( cfg->m_LibFieldEditor.field_widths.count( key )
510 && ( cfg->m_LibFieldEditor.field_widths.at( key ) > 0 ) )
511 {
512 m_grid->SetColSize( col, cfg->m_LibFieldEditor.field_widths.at( key ) );
513 }
514 else
515 {
516 int textWidth = m_dataModel->GetDataWidth( col ) + COLUMN_MARGIN;
517 int maxWidth = defaultDlgSize.x / 3;
518
519 m_grid->SetColSize( col, std::clamp( textWidth, 100, maxWidth ) );
520 }
521 }
522 else
523 {
524 m_grid->HideCol( col );
525 }
526 }
527
528 m_dataModel->SetSorting( sortCol, sortAscending );
529 m_grid->SetSortingColumn( sortCol, sortAscending );
530}
531
532
534{
535 m_dataModel->SetGroupingEnabled( m_groupSymbolsBox->GetValue() );
536
537 switch( m_scope )
538 {
539 case SCOPE::SCOPE_LIBRARY: m_choiceScope->SetSelection( 0 ); break;
540 case SCOPE::SCOPE_RELATED_SYMBOLS: m_choiceScope->SetSelection( 1 ); break;
541 }
542
543 setScope( m_scope );
544
545 return true;
546}
547
548
549void DIALOG_LIB_FIELDS_TABLE::loadSymbols( const wxArrayString& aSymbolNames )
550{
551 // Clear any existing data
552 m_symbolsList.clear();
553
554 wxString libName = m_parent->GetTreeLIBID().GetLibNickname();
555
556 if( aSymbolNames.IsEmpty() )
557 {
559 wxMessageBox( wxString::Format( _( "No related symbols found in library '%s'." ), libName ) );
560 else
561 wxMessageBox( wxString::Format( _( "No symbols found in library '%s'." ), libName ) );
562
563 return;
564 }
565
566 // Load each symbol from the library manager and add it to our list
567 for( const wxString& symbolName : aSymbolNames )
568 {
569 LIB_SYMBOL* canvasSymbol = m_parent->GetCurSymbol();
570
571 if( canvasSymbol && canvasSymbol->GetLibraryName() == libName && canvasSymbol->GetName() == symbolName )
572 {
573 m_symbolsList.push_back( canvasSymbol );
574 }
575 else
576 {
577 try
578 {
579 if( LIB_SYMBOL* symbol = m_parent->GetLibManager().GetSymbol( symbolName, libName ) )
580 m_symbolsList.push_back( symbol );
581 }
582 catch( const IO_ERROR& ioe )
583 {
584 // Log the error and continue
585 wxLogWarning( wxString::Format( _( "Error loading symbol '%s': %s" ), symbolName, ioe.What() ) );
586 }
587 }
588 }
589
590 if( m_symbolsList.empty() )
591 {
593 wxMessageBox( _( "No related symbols could be loaded from the library." ) );
594 else
595 wxMessageBox( _( "No symbols could be loaded from the library." ) );
596 }
597
598 m_dataModel->SetSymbols( m_symbolsList );
599}
600
601
603{
604 if( !m_grid->CommitPendingChanges() )
605 return false;
606
607 if( !wxDialog::TransferDataFromWindow() )
608 return false;
609
610 bool updateCanvas = false;
611
612 m_dataModel->ApplyData(
613 [&]( LIB_SYMBOL* symbol )
614 {
615 m_parent->GetLibManager().UpdateSymbol( symbol, symbol->GetLibNickname() );
616
617 if( m_parent->GetCurSymbol() == symbol )
618 updateCanvas = true;
619 },
620 [&]()
621 {
622 // Handle newly created derived symbols
623 auto createdSymbols = m_dataModel->GetAndClearCreatedDerivedSymbols();
624
625 wxLogTrace( traceLibFieldTable, "Post-apply handler: found %zu created derived symbols",
626 createdSymbols.size() );
627
628 for( const auto& [symbol, libraryName] : createdSymbols )
629 {
630 if( !libraryName.IsEmpty() )
631 {
632 wxLogTrace( traceLibFieldTable, "Updating symbol '%s' (UUID: %s) in library '%s'",
633 symbol->GetName(), symbol->m_Uuid.AsString(), libraryName );
634 // Update the symbol in the library manager to properly register it
635 m_parent->GetLibManager().UpdateSymbol( symbol, libraryName );
636 }
637 }
638
639 // Sync libraries and refresh tree if there were changes
640 if( !createdSymbols.empty() )
641 {
642 wxLogTrace( traceLibFieldTable, "Syncing libraries due to %zu new symbols", createdSymbols.size() );
643
644 // Store references to the created symbols before sync
645 std::vector<LIB_SYMBOL*> symbolsToPreserve;
646 for( const auto& [symbol, libraryName] : createdSymbols )
647 {
648 symbolsToPreserve.push_back( symbol );
649 }
650
651 // Synchronize libraries to update the tree view
652 m_parent->SyncLibraries( false );
653
654 // Ensure created symbols are still in the symbol list after sync
655 for( LIB_SYMBOL* symbol : symbolsToPreserve )
656 {
657 bool found = false;
658 for( LIB_SYMBOL* existingSymbol : m_symbolsList )
659 {
660 if( existingSymbol->m_Uuid == symbol->m_Uuid )
661 {
662 found = true;
663 break;
664 }
665 }
666 if( !found )
667 {
668 wxLogTrace( traceLibFieldTable, "Re-adding symbol '%s' to list after sync", symbol->GetName() );
669 m_symbolsList.push_back( symbol );
670 }
671 }
672 }
673
674 wxLogTrace( traceLibFieldTable, "Dialog symbol list size after processing: %zu", m_symbolsList.size() );
675 } );
676
677 ClearModify();
678
679 wxLogTrace( traceLibFieldTable, "About to rebuild grid rows to include new symbols" );
681 wxLogTrace( traceLibFieldTable, "Grid rebuild completed" );
682
683 m_parent->RefreshLibraryTree();
684
685 if( updateCanvas )
686 {
687 m_parent->OnModify();
688 m_parent->HardRedraw();
689 }
690
691 return true;
692}
693
694
695void DIALOG_LIB_FIELDS_TABLE::OnAddField(wxCommandEvent& event)
696{
697 wxTextEntryDialog dlg( this, _( "New field name:" ), _( "Add Field" ) );
698
699 if( dlg.ShowModal() != wxID_OK )
700 return;
701
702 wxString fieldName = dlg.GetValue();
703
704 if( fieldName.IsEmpty() )
705 {
706 DisplayError( this, _( "Field must have a name." ) );
707 return;
708 }
709
710 for( int i = 0; i < m_dataModel->GetNumberCols(); ++i )
711 {
712 if( FieldNamesAreDuplicates( fieldName, m_dataModel->GetColFieldName( i ) ) )
713 {
714 DisplayError( this, wxString::Format( _( "Field name '%s' already in use." ), fieldName ) );
715 return;
716 }
717 }
718
719 AddField( fieldName, GetGeneratedFieldDisplayName( fieldName ), true, false, true );
720
721 SetupColumnProperties( m_dataModel->GetColsCount() - 1 );
722
723 OnModify();
724}
725
726
727void DIALOG_LIB_FIELDS_TABLE::OnRemoveField(wxCommandEvent& event)
728{
729 m_viewControlsGrid->OnDeleteRows(
730 [&]( int row )
731 {
732 return IsOK( this, wxString::Format( _( "Are you sure you want to remove the field '%s'?" ),
733 m_viewControlsDataModel->GetValue( row, DISPLAY_NAME_COLUMN ) ) );
734 },
735 [&]( int row )
736 {
737 wxString fieldName = m_viewControlsDataModel->GetCanonicalFieldName( row );
738
739 RemoveField( fieldName );
740
741 m_viewControlsDataModel->DeleteRow( row );
742 OnModify();
743 } );
744}
745
746
747void DIALOG_LIB_FIELDS_TABLE::OnRenameField(wxCommandEvent& event)
748{
749 wxArrayInt selectedRows = m_viewControlsGrid->GetSelectedRows();
750
751 if( selectedRows.empty() && m_viewControlsGrid->GetGridCursorRow() >= 0 )
752 selectedRows.push_back( m_viewControlsGrid->GetGridCursorRow() );
753
754 if( selectedRows.empty() )
755 return;
756
757 int row = selectedRows[0];
758
759 wxString fieldName = m_viewControlsDataModel->GetCanonicalFieldName( row );
760
761 int col = m_dataModel->GetFieldNameCol( fieldName );
762 wxCHECK_RET( col != -1, wxS( "Existing field name missing from data model" ) );
763
764 wxTextEntryDialog dlg( this, _( "New field name:" ), _( "Rename Field" ), fieldName );
765
766 if( dlg.ShowModal() != wxID_OK )
767 return;
768
769 wxString newFieldName = dlg.GetValue();
770
771 if( newFieldName == fieldName )
772 return;
773
774 if( m_dataModel->GetFieldNameCol( newFieldName ) != -1 )
775 {
776 DisplayError( this, wxString::Format( _( "Field name '%s' already exists." ), newFieldName ) );
777 return;
778 }
779
780 RenameField( fieldName, newFieldName );
781
782 m_viewControlsDataModel->SetCanonicalFieldName( row, newFieldName );
783 m_viewControlsDataModel->SetValue( row, DISPLAY_NAME_COLUMN, newFieldName );
784 m_viewControlsDataModel->SetValue( row, LABEL_COLUMN, GetGeneratedFieldDisplayName( newFieldName ) );
785
787 OnModify();
788}
789
790
791void DIALOG_LIB_FIELDS_TABLE::OnFilterText( wxCommandEvent& event )
792{
793 m_dataModel->SetFilter( m_filter->GetValue() );
795}
796
797
799{
800#if defined( __WXOSX__ ) // Doesn't work properly on other ports
801 wxPoint pos = aEvent.GetPosition();
802 wxRect ctrlRect = m_filter->GetScreenRect();
803 int buttonWidth = ctrlRect.GetHeight(); // Presume buttons are square
804
805 // TODO: restore cursor when mouse leaves the filter field (or is it a MSW bug?)
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 );
810 else
811 SetCursor( wxCURSOR_IBEAM );
812#endif
813}
814
815
817{
818 LIB_SYMBOL_LIBRARY_MANAGER& libMgr = m_parent->GetLibManager();
819 wxString targetLib = m_parent->GetTargetLibId().GetLibNickname();
820 wxString targetSymbol = m_parent->GetTargetLibId().GetLibItemName();
821 wxArrayString symbolNames;
822
823 SetTitle( wxString::Format( _( "Symbol Fields Table ('%s' Library)" ), targetLib ) );
824
825 m_scope = aScope;
826
827 if( m_scope == SCOPE::SCOPE_RELATED_SYMBOLS )
828 {
829 const LIB_SYMBOL* symbol = libMgr.GetBufferedSymbol( targetSymbol, targetLib );
830 std::shared_ptr<LIB_SYMBOL> root = symbol ? symbol->GetRootSymbol() : nullptr;
831
832 if( root )
833 {
834 symbolNames.Add( root->GetName() );
835
836 // Now we have the root symbol, collect all its derived symbols
837 libMgr.GetDerivedSymbolNames( root->GetName(), targetLib, symbolNames );
838 }
839 }
840 else
841 {
842 // Get all symbol names from the library manager
843 libMgr.GetSymbolNames( targetLib, symbolNames );
844 }
845
846 // Get all symbols from the library
847 loadSymbols( symbolNames );
848
849 // Update the field list and refresh the grid
853}
854
855
856void DIALOG_LIB_FIELDS_TABLE::OnScope( wxCommandEvent& aEvent )
857{
858 switch( aEvent.GetSelection() )
859 {
860 case 0: setScope( SCOPE::SCOPE_LIBRARY ); break;
861 case 1: setScope( SCOPE::SCOPE_RELATED_SYMBOLS ); break;
862 }
863}
864
865
866void DIALOG_LIB_FIELDS_TABLE::OnRegroupSymbols( wxCommandEvent& event )
867{
869}
870
871
873{
874 m_grid->ForceRefresh();
875 OnModify();
876}
877
878
880{
881 if( m_dataModel->IsExpanderColumn( event.GetCol() ) )
882 {
883 m_grid->ClearSelection();
884 m_dataModel->ExpandCollapseRow( event.GetRow() );
885 m_grid->SetGridCursor( event.GetRow(), event.GetCol() );
886 // Don't call event.Skip() - we've handled this event
887 }
888 else
889 {
890 event.Skip(); // Let normal cell editing proceed
891 }
892}
893
894
896{
897 if( m_grid )
898 {
899 // Get global mouse position and convert to grid client coords
900 wxPoint mousePos = wxGetMousePosition();
901 wxPoint gridPt = m_grid->ScreenToClient( mousePos );
902
903 int row = m_grid->YToRow( gridPt.y );
904 int col = m_grid->XToCol( gridPt.x );
905
906 if ( row != -1 && col != -1 )
907 m_grid->SetGridCursor( row, col );
908 }
909
910 event.Skip();
911}
912
913
915{
916 m_dataModel->SetGroupingEnabled( m_groupSymbolsBox->GetValue() );
917 m_dataModel->RebuildRows();
918 m_grid->ForceRefresh();
919}
920
921
922void DIALOG_LIB_FIELDS_TABLE::OnTableColSize(wxGridSizeEvent& aEvent)
923{
924 aEvent.Skip();
925
926 m_grid->ForceRefresh();
927}
928
929
931{
932 const wxString& showColLabel = m_viewControlsGrid->GetColLabelValue( SHOW_FIELD_COLUMN );
933 const wxString& groupByColLabel = m_viewControlsGrid->GetColLabelValue( GROUP_BY_COLUMN );
934 int showColWidth = KIUI::GetTextSize( showColLabel, m_viewControlsGrid ).x + COLUMN_MARGIN;
935 int groupByColWidth = KIUI::GetTextSize( groupByColLabel, m_viewControlsGrid ).x + COLUMN_MARGIN;
936 int remainingWidth = m_viewControlsGrid->GetSize().GetX() - showColWidth - groupByColWidth;
937
938 m_viewControlsGrid->SetColSize( showColWidth, SHOW_FIELD_COLUMN );
939 m_viewControlsGrid->SetColSize( groupByColWidth, GROUP_BY_COLUMN );
940
941 if( m_viewControlsGrid->IsColShown( DISPLAY_NAME_COLUMN ) && m_viewControlsGrid->IsColShown( LABEL_COLUMN ) )
942 {
943 m_viewControlsGrid->SetColSize( DISPLAY_NAME_COLUMN, std::max( remainingWidth / 2, 60 ) );
944 m_viewControlsGrid->SetColSize( LABEL_COLUMN, std::max( remainingWidth - ( remainingWidth / 2 ), 60 ) );
945 }
946 else if( m_viewControlsGrid->IsColShown( DISPLAY_NAME_COLUMN ) )
947 {
948 m_viewControlsGrid->SetColSize( DISPLAY_NAME_COLUMN, std::max( remainingWidth, 60 ) );
949 }
950 else if( m_viewControlsGrid->IsColShown( LABEL_COLUMN ) )
951 {
952 m_viewControlsGrid->SetColSize( LABEL_COLUMN, std::max( remainingWidth, 60 ) );
953 }
954
955 event.Skip();
956}
957
958
959void DIALOG_LIB_FIELDS_TABLE::OnSidebarToggle( wxCommandEvent& event )
960{
961 SYMBOL_EDITOR_SETTINGS::PANEL_LIB_FIELDS_TABLE& cfg = m_parent->libeditconfig()->m_LibFieldEditor;
962
963 if( cfg.sidebar_collapsed )
964 {
965 cfg.sidebar_collapsed = false;
966 m_splitterMainWindow->SplitVertically( m_leftPanel, m_rightPanel, cfg.sash_pos );
967 }
968 else
969 {
970 cfg.sash_pos = m_splitterMainWindow->GetSashPosition();
971 cfg.sidebar_collapsed = true;
973 }
974
976}
977
978
979void DIALOG_LIB_FIELDS_TABLE::OnApply(wxCommandEvent& event)
980{
982}
983
984
985void DIALOG_LIB_FIELDS_TABLE::OnCancel(wxCommandEvent& event)
986{
987 m_grid->CommitPendingChanges( true );
988
989 if( m_dataModel->IsEdited() )
990 {
991 if( !HandleUnsavedChanges( this, _( "Save changes?" ),
992 [&]() -> bool
993 {
994 return TransferDataFromWindow();
995 } ) )
996 return;
997 }
998
999 EndModal( wxID_CANCEL );
1000}
1001
1002
1003void DIALOG_LIB_FIELDS_TABLE::OnOk(wxCommandEvent& event)
1004{
1006 EndModal( wxID_OK );
1007}
1008
1009
1010void DIALOG_LIB_FIELDS_TABLE::OnClose( wxCloseEvent& aEvent )
1011{
1012 m_grid->CommitPendingChanges( true );
1013
1014 if( m_dataModel->IsEdited() )
1015 {
1016 if( !HandleUnsavedChanges( this, _( "Save changes?" ),
1017 [&]() -> bool
1018 {
1019 return TransferDataFromWindow();
1020 } ) )
1021 {
1022 aEvent.Veto();
1023 return;
1024 }
1025 }
1026
1027 aEvent.Skip();
1028}
1029
1030
1032{
1033 auto addMandatoryField =
1034 [&]( FIELD_T fieldId, bool show, bool groupBy )
1035 {
1036 AddField( GetCanonicalFieldName( fieldId ),
1037 GetDefaultFieldName( fieldId, DO_TRANSLATE ), show, groupBy );
1038 };
1039
1040 AddField( LIB_FIELDS_EDITOR_GRID_DATA_MODEL::SYMBOL_NAME, _( "Symbol Name" ), true, false );
1041
1042 // Add mandatory fields first show groupBy
1043 addMandatoryField( FIELD_T::REFERENCE, false, false );
1044 addMandatoryField( FIELD_T::VALUE, true, false );
1045 addMandatoryField( FIELD_T::FOOTPRINT, true, false );
1046 addMandatoryField( FIELD_T::DATASHEET, true, false );
1047 addMandatoryField( FIELD_T::DESCRIPTION, false, false );
1048
1049 AddField( wxS( "Keywords" ), _( "Keywords" ), true, false );
1050
1051 // Add attribute fields as checkboxes show groupBy user checkbox
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 );
1055
1056 AddField( wxS( "Power" ), _( "Power Symbol" ), true, false, false, true );
1057 AddField( wxS( "LocalPower" ), _( "Local Power Symbol" ), true, false, false, true );
1058
1059 // User field names are stored and matched case-sensitively (see issue #24021), so each
1060 // distinct name gets its own column rather than collapsing case variants together.
1061 std::set<wxString> userFieldNames;
1062
1063 for( LIB_SYMBOL* symbol : m_symbolsList )
1064 {
1065 std::vector< SCH_FIELD* > fields;
1066 symbol->GetFields( fields );
1067
1068 for( SCH_FIELD* field : fields )
1069 {
1070 if( !field->IsMandatory() && !field->IsPrivate() )
1071 userFieldNames.insert( field->GetName() );
1072 }
1073 }
1074
1075 for( const wxString& fieldName : userFieldNames )
1076 AddField( fieldName, GetGeneratedFieldDisplayName( fieldName ), true, false );
1077}
1078
1079
1080void DIALOG_LIB_FIELDS_TABLE::AddField( const wxString& aFieldName, const wxString& aLabelValue, bool show,
1081 bool groupBy, bool addedByUser, bool aIsCheckbox )
1082{
1083 // Users can add fields with variable names that match the special names in the grid,
1084 // e.g. ${QUANTITY} so make sure we don't add them twice
1085 for( int row = 0; row < m_viewControlsDataModel->GetNumberRows(); row++ )
1086 {
1087 if( FieldNamesAreDuplicates( m_viewControlsDataModel->GetCanonicalFieldName( row ),
1088 aFieldName ) )
1089 {
1090 return;
1091 }
1092 }
1093
1094 m_dataModel->AddColumn( aFieldName, aLabelValue, addedByUser, aIsCheckbox );
1095
1096 wxGridTableMessage msg( m_dataModel, wxGRIDTABLE_NOTIFY_COLS_APPENDED, 1 );
1097 m_grid->ProcessTableMessage( msg );
1098
1099 m_viewControlsGrid->OnAddRow(
1100 [&]() -> std::pair<int, int>
1101 {
1102 m_viewControlsDataModel->AppendRow( aFieldName, aLabelValue, show, groupBy );
1103
1104 return { m_viewControlsDataModel->GetNumberRows() - 1, -1 };
1105 } );
1106}
1107
1108
1109void DIALOG_LIB_FIELDS_TABLE::RemoveField(const wxString& fieldName)
1110{
1111 int col = m_dataModel->GetFieldNameCol( fieldName );
1112 wxCHECK_RET( col != -1, wxS( "Field name not found" ) );
1113
1114 m_dataModel->RemoveColumn( col );
1115}
1116
1117
1118void DIALOG_LIB_FIELDS_TABLE::RenameField(const wxString& oldName, const wxString& newName)
1119{
1120 int col = m_dataModel->GetFieldNameCol( oldName );
1121 wxCHECK_RET( col != -1, wxS( "Existing field name missing from data model" ) );
1122
1123 m_dataModel->RenameColumn( col, newName );
1124}
1125
1126
1128{
1129 m_dataModel->RebuildRows();
1130 m_grid->ForceRefresh();
1131}
1132
1133
1134void DIALOG_LIB_FIELDS_TABLE::OnColSort(wxGridEvent& aEvent)
1135{
1136 int sortCol = aEvent.GetCol();
1137 std::string key( m_dataModel->GetColFieldName( sortCol ).ToUTF8() );
1138 bool ascending;
1139
1140 // This is bonkers, but wxWidgets doesn't tell us ascending/descending in the event, and
1141 // if we ask it will give us pre-event info.
1142 if( m_grid->IsSortingBy( sortCol ) )
1143 {
1144 // same column; invert ascending
1145 ascending = !m_grid->IsSortOrderAscending();
1146 }
1147 else
1148 {
1149 // different column; start with ascending
1150 ascending = true;
1151 }
1152
1153 m_dataModel->SetSorting( sortCol, ascending );
1155}
1156
1157
1158void DIALOG_LIB_FIELDS_TABLE::OnColMove(wxGridEvent& aEvent)
1159{
1160 int origPos = aEvent.GetCol();
1161
1162 // Save column widths since the setup function uses the saved config values
1163 SYMBOL_EDITOR_SETTINGS* cfg = m_parent->GetSettings();
1164
1165 for( int i = 0; i < m_grid->GetNumberCols(); i++ )
1166 {
1167 if( m_grid->IsColShown( i ) )
1168 {
1169 std::string fieldName( m_dataModel->GetColFieldName( i ).ToUTF8() );
1170 cfg->m_LibFieldEditor.field_widths[fieldName] = m_grid->GetColSize( i );
1171 }
1172 }
1173
1174 CallAfter(
1175 [origPos, this]()
1176 {
1177 int newPos = m_grid->GetColPos( origPos );
1178
1179#ifdef __WXMAC__
1180 if( newPos < origPos )
1181 newPos += 1;
1182#endif
1183
1184 m_dataModel->MoveColumn( origPos, newPos );
1185
1186 // "Unmove" the column since we've moved the column internally
1187 m_grid->ResetColPos();
1188
1189 // We need to reset all the column attr's to the correct column order
1191
1192 m_grid->ForceRefresh();
1193 } );
1194}
1195
1196
1198{
1199 if( aShow )
1200 m_grid->ShowCol( aCol );
1201 else
1202 m_grid->HideCol( aCol );
1203
1204 m_dataModel->SetShowColumn( aCol, aShow );
1205
1206 m_grid->ForceRefresh();
1207 OnModify();
1208}
1209
1210
1212{
1213 int row = aEvent.GetRow();
1214
1215 wxCHECK( row < m_viewControlsGrid->GetNumberRows(), /* void */ );
1216
1217 switch( aEvent.GetCol() )
1218 {
1220 {
1221 wxString label = m_viewControlsDataModel->GetValue( row, DISPLAY_NAME_COLUMN );
1222 wxString fieldName = m_viewControlsDataModel->GetCanonicalFieldName( row );
1223 int dataCol = m_dataModel->GetFieldNameCol( fieldName );
1224
1225 if( dataCol != -1 )
1226 {
1227 m_dataModel->SetColLabelValue( dataCol, label );
1228 m_grid->SetColLabelValue( dataCol, label );
1229
1230 m_grid->ForceRefresh();
1231 OnModify();
1232 }
1233
1234 break;
1235 }
1236
1237 case SHOW_FIELD_COLUMN:
1238 {
1239 wxString fieldName = m_viewControlsDataModel->GetCanonicalFieldName( row );
1240 bool value = m_viewControlsDataModel->GetValueAsBool( row, SHOW_FIELD_COLUMN );
1241 int dataCol = m_dataModel->GetFieldNameCol( fieldName );
1242
1243 if( dataCol != -1 )
1244 ShowHideColumn( dataCol, value );
1245
1246 break;
1247 }
1248
1249 case GROUP_BY_COLUMN:
1250 {
1251 wxString fieldName = m_viewControlsDataModel->GetCanonicalFieldName( row );
1252 bool value = m_viewControlsDataModel->GetValueAsBool( row, GROUP_BY_COLUMN );
1253 int dataCol = m_dataModel->GetFieldNameCol( fieldName );
1254
1255 m_dataModel->SetGroupColumn( dataCol, value );
1256 m_dataModel->RebuildRows();
1257
1258 m_grid->ForceRefresh();
1259 OnModify();
1260 break;
1261 }
1262
1263 default:
1264 break;
1265 }
1266}
1267
1268
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:106
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)
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 OnSidebarToggle(wxCommandEvent &event) override
void OnAddField(wxCommandEvent &event) override
void ShowHideColumn(int aCol, bool aShow)
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
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 setSideBarButtonLook(bool aIsLeftPanelCollapsed)
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.
Definition dialog_shim.h:94
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...
int ShowModal() override
The base class for create windows for drawing purpose.
const KIID m_Uuid
Definition eda_item.h:531
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
Definition kiid.cpp:264
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.
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
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.
Definition lib_symbol.h:114
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
Definition lib_symbol.h:176
wxArrayString GetFPFilters() const
Definition lib_symbol.h:242
wxString GetLibNickname() const override
Sets the Description field text value.
Definition lib_symbol.h:189
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.
void doPopupSelection(wxCommandEvent &event) override
wxString GetGeneratedFieldDisplayName(const wxString &aSource)
Returns any variables unexpanded, e.g.
Definition common.cpp:458
bool IsGeneratedField(const wxString &aSource)
Returns true if the string is generated, e.g contains a single text var reference.
Definition common.cpp:470
The common library.
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:274
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Display a dialog with Save, Cancel and Discard Changes buttons.
Definition confirm.cpp:146
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:192
This file is part of the common library.
#define COLUMN_MARGIN
DIALOG_LIB_NEW_SYMBOL DIALOG_NEW_SYMBOL
@ MYID_CREATE_DERIVED_SYMBOL
@ MYID_SELECT_FOOTPRINT
#define _(s)
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.
Definition eda_doc.cpp:59
This file is part of the common library.
@ FRAME_FOOTPRINT_CHOOSER
Definition frame_type.h:40
@ GRIDTRICKS_FIRST_SHOWHIDE
Definition grid_tricks.h:47
@ GRIDTRICKS_FIRST_CLIENT_ID
Definition grid_tricks.h:44
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...
Definition ui_common.cpp:78
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
@ CTX_LINE
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.
#define DO_TRANSLATE
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
KIBIS_PIN * pin
wxLogTrace helper definitions.