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