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