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
323 m_viewControlsGrid->ShowHideColumns( "0 2 3" );
324
325 CallAfter( [this, cfg]()
326 {
327 if( cfg.sidebar_collapsed )
329 else
330 m_splitterMainWindow->SetSashPosition( cfg.sash_pos );
331
333 } );
334
335 Center();
336
337 // Connect Events
338 m_grid->Bind( wxEVT_GRID_COL_SORT, &DIALOG_LIB_FIELDS_TABLE::OnColSort, this );
339 m_grid->Bind( wxEVT_GRID_COL_MOVE, &DIALOG_LIB_FIELDS_TABLE::OnColMove, this );
340 m_grid->Bind( wxEVT_GRID_CELL_LEFT_CLICK, &DIALOG_LIB_FIELDS_TABLE::OnTableCellClick, this );
341 m_viewControlsGrid->Bind( wxEVT_GRID_CELL_CHANGED, &DIALOG_LIB_FIELDS_TABLE::OnViewControlsCellChanged, this );
342}
343
344
346{
347 SYMBOL_EDITOR_SETTINGS::PANEL_LIB_FIELDS_TABLE& cfg = m_parent->libeditconfig()->m_LibFieldEditor;
348
349 if( !cfg.sidebar_collapsed )
350 cfg.sash_pos = m_splitterMainWindow->GetSashPosition();
351
352 for( int i = 0; i < m_grid->GetNumberCols(); i++ )
353 {
354 if( m_grid->IsColShown( i ) )
355 {
356 std::string fieldName( m_dataModel->GetColFieldName( i ).ToUTF8() );
357 cfg.field_widths[fieldName] = m_grid->GetColSize( i );
358 }
359 }
360
361 // Disconnect Events
362 m_grid->Unbind( wxEVT_GRID_COL_SORT, &DIALOG_LIB_FIELDS_TABLE::OnColSort, this );
363 m_grid->Unbind( wxEVT_GRID_COL_MOVE, &DIALOG_LIB_FIELDS_TABLE::OnColMove, this );
364 m_grid->Unbind( wxEVT_GRID_CELL_LEFT_CLICK, &DIALOG_LIB_FIELDS_TABLE::OnTableCellClick, this );
365 m_viewControlsGrid->Unbind( wxEVT_GRID_CELL_CHANGED, &DIALOG_LIB_FIELDS_TABLE::OnViewControlsCellChanged, this );
366
367 // Delete the GRID_TRICKS.
368 m_viewControlsGrid->PopEventHandler( true );
369 m_grid->PopEventHandler( true );
370
371 // we gave ownership of m_viewControlsDataModel & m_dataModel to the wxGrids...
372}
373
374
375void DIALOG_LIB_FIELDS_TABLE::setSideBarButtonLook( bool aIsLeftPanelCollapsed )
376{
377 // Set bitmap and tooltip according to left panel visibility
378
379 if( aIsLeftPanelCollapsed )
380 {
382 m_sidebarButton->SetToolTip( _( "Expand left panel" ) );
383 }
384 else
385 {
387 m_sidebarButton->SetToolTip( _( "Collapse left panel" ) );
388 }
389}
390
391
393{
394 wxGridCellAttr* attr = new wxGridCellAttr;
395 attr->SetReadOnly( false );
396
397 // Set some column types to specific editors
398 if( m_dataModel->GetColFieldName( aCol ) == GetCanonicalFieldName( FIELD_T::FOOTPRINT ) )
399 {
400 // Create symbol netlist for footprint picker
401 wxString symbolNetlist;
402
403 if( !m_symbolsList.empty() )
404 {
405 // Use the first symbol's netlist (all symbols in lib should have similar pin structure)
406 LIB_SYMBOL* symbol = m_symbolsList[0];
407 wxArrayString pins;
408
409 for( SCH_PIN* pin : symbol->GetGraphicalPins( 0 /* all units */, 1 /* single bodyStyle */ ) )
410 pins.push_back( pin->GetNumber() + ' ' + pin->GetShownName() );
411
412 if( !pins.IsEmpty() )
413 symbolNetlist << EscapeString( wxJoin( pins, '\t' ), CTX_LINE );
414
415 symbolNetlist << wxS( "\r" );
416
417 wxArrayString fpFilters = symbol->GetFPFilters();
418 if( !fpFilters.IsEmpty() )
419 symbolNetlist << EscapeString( wxJoin( fpFilters, ' ' ), CTX_LINE );
420
421 symbolNetlist << wxS( "\r" );
422 }
423
424 attr->SetEditor( new GRID_CELL_FPID_EDITOR( this, symbolNetlist ) );
425 m_dataModel->SetColAttr( attr, aCol );
426 }
427 else if( m_dataModel->GetColFieldName( aCol ) == GetCanonicalFieldName( FIELD_T::DATASHEET ) )
428 {
429 // set datasheet column viewer button
430 attr->SetEditor( new GRID_CELL_URL_EDITOR( this, PROJECT_SCH::SchSearchS( &Prj() ) ) );
431 m_dataModel->SetColAttr( attr, aCol );
432 }
433 else if( m_dataModel->ColIsCheck( aCol ) )
434 {
435 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
436 attr->SetRenderer( new GRID_CELL_CHECKBOX_RENDERER() );
437 m_dataModel->SetColAttr( attr, aCol );
438 }
439 else if( IsGeneratedField( m_dataModel->GetColFieldName( aCol ) ) )
440 {
441 attr->SetReadOnly();
442 m_dataModel->SetColAttr( attr, aCol );
443 }
444 else
445 {
446 attr->SetRenderer( new GRID_CELL_TEXT_RENDERER() );
447 attr->SetEditor( m_grid->GetDefaultEditor() );
448 m_dataModel->SetColAttr( attr, aCol );
449 }
450}
451
452
454{
455 SYMBOL_EDITOR_SETTINGS* cfg = m_parent->GetSettings();
456 wxSize defaultDlgSize = ConvertDialogToPixels( wxSize( 600, 300 ) );
457
458 // Restore column sorting order and widths
459 m_grid->AutoSizeColumns( false );
460 int sortCol = 0;
461 bool sortAscending = true;
462
463 // Find the symbol name column for initial sorting
464 int nameCol = m_dataModel->GetFieldNameCol( LIB_FIELDS_EDITOR_GRID_DATA_MODEL::SYMBOL_NAME );
465
466 // Set initial sort to VALUE field (ascending) if no previous sort preference exists
467 if( m_dataModel->GetSortCol() == 0 && nameCol != -1 )
468 {
469 sortCol = nameCol;
470 sortAscending = true;
471 m_dataModel->SetSorting( sortCol, sortAscending );
472 }
473
474 for( int col = 0; col < m_grid->GetNumberCols(); ++col )
475 {
477
478 if( col == m_dataModel->GetSortCol() )
479 {
480 sortCol = col;
481 sortAscending = m_dataModel->GetSortAsc();
482 }
483 }
484
485 // sync m_grid's column visibilities to Show checkboxes in m_viewControlsGrid
486 for( int i = 0; i < m_viewControlsDataModel->GetNumberRows(); ++i )
487 {
488 int col = m_dataModel->GetFieldNameCol( m_viewControlsDataModel->GetCanonicalFieldName( i ) );
489
490 if( col == -1 )
491 continue;
492
493 bool show = m_viewControlsDataModel->GetValueAsBool( i, SHOW_FIELD_COLUMN );
494 m_dataModel->SetShowColumn( col, show );
495
496 if( show )
497 {
498 m_grid->ShowCol( col );
499
500 std::string key( m_dataModel->GetColFieldName( col ).ToUTF8() );
501
502 if( cfg->m_LibFieldEditor.field_widths.count( key )
503 && ( cfg->m_LibFieldEditor.field_widths.at( key ) > 0 ) )
504 {
505 m_grid->SetColSize( col, cfg->m_LibFieldEditor.field_widths.at( key ) );
506 }
507 else
508 {
509 int textWidth = m_dataModel->GetDataWidth( col ) + COLUMN_MARGIN;
510 int maxWidth = defaultDlgSize.x / 3;
511
512 m_grid->SetColSize( col, std::clamp( textWidth, 100, maxWidth ) );
513 }
514 }
515 else
516 {
517 m_grid->HideCol( col );
518 }
519 }
520
521 m_dataModel->SetSorting( sortCol, sortAscending );
522 m_grid->SetSortingColumn( sortCol, sortAscending );
523}
524
525
527{
528 m_dataModel->SetGroupingEnabled( m_groupSymbolsBox->GetValue() );
529
530 switch( m_scope )
531 {
532 case SCOPE::SCOPE_LIBRARY: m_choiceScope->SetSelection( 0 ); break;
533 case SCOPE::SCOPE_RELATED_SYMBOLS: m_choiceScope->SetSelection( 1 ); break;
534 }
535
536 setScope( m_scope );
537
538 return true;
539}
540
541
542void DIALOG_LIB_FIELDS_TABLE::loadSymbols( const wxArrayString& aSymbolNames )
543{
544 // Clear any existing data
545 m_symbolsList.clear();
546
547 wxString libName = m_parent->GetTreeLIBID().GetLibNickname();
548
549 if( aSymbolNames.IsEmpty() )
550 {
552 wxMessageBox( wxString::Format( _( "No related symbols found in library '%s'." ), libName ) );
553 else
554 wxMessageBox( wxString::Format( _( "No symbols found in library '%s'." ), libName ) );
555
556 return;
557 }
558
559 // Load each symbol from the library manager and add it to our list
560 for( const wxString& symbolName : aSymbolNames )
561 {
562 LIB_SYMBOL* canvasSymbol = m_parent->GetCurSymbol();
563
564 if( canvasSymbol && canvasSymbol->GetLibraryName() == libName && canvasSymbol->GetName() == symbolName )
565 {
566 m_symbolsList.push_back( canvasSymbol );
567 }
568 else
569 {
570 try
571 {
572 if( LIB_SYMBOL* symbol = m_parent->GetLibManager().GetSymbol( symbolName, libName ) )
573 m_symbolsList.push_back( symbol );
574 }
575 catch( const IO_ERROR& ioe )
576 {
577 // Log the error and continue
578 wxLogWarning( wxString::Format( _( "Error loading symbol '%s': %s" ), symbolName, ioe.What() ) );
579 }
580 }
581 }
582
583 if( m_symbolsList.empty() )
584 {
586 wxMessageBox( _( "No related symbols could be loaded from the library." ) );
587 else
588 wxMessageBox( _( "No symbols could be loaded from the library." ) );
589 }
590
591 m_dataModel->SetSymbols( m_symbolsList );
592}
593
594
596{
597 if( !m_grid->CommitPendingChanges() )
598 return false;
599
600 if( !wxDialog::TransferDataFromWindow() )
601 return false;
602
603 bool updateCanvas = false;
604
605 m_dataModel->ApplyData(
606 [&]( LIB_SYMBOL* symbol )
607 {
608 m_parent->GetLibManager().UpdateSymbol( symbol, symbol->GetLibNickname() );
609
610 if( m_parent->GetCurSymbol() == symbol )
611 updateCanvas = true;
612 },
613 [&]()
614 {
615 // Handle newly created derived symbols
616 auto createdSymbols = m_dataModel->GetAndClearCreatedDerivedSymbols();
617
618 wxLogTrace( traceLibFieldTable, "Post-apply handler: found %zu created derived symbols",
619 createdSymbols.size() );
620
621 for( const auto& [symbol, libraryName] : createdSymbols )
622 {
623 if( !libraryName.IsEmpty() )
624 {
625 wxLogTrace( traceLibFieldTable, "Updating symbol '%s' (UUID: %s) in library '%s'",
626 symbol->GetName(), symbol->m_Uuid.AsString(), libraryName );
627 // Update the symbol in the library manager to properly register it
628 m_parent->GetLibManager().UpdateSymbol( symbol, libraryName );
629 }
630 }
631
632 // Sync libraries and refresh tree if there were changes
633 if( !createdSymbols.empty() )
634 {
635 wxLogTrace( traceLibFieldTable, "Syncing libraries due to %zu new symbols", createdSymbols.size() );
636
637 // Store references to the created symbols before sync
638 std::vector<LIB_SYMBOL*> symbolsToPreserve;
639 for( const auto& [symbol, libraryName] : createdSymbols )
640 {
641 symbolsToPreserve.push_back( symbol );
642 }
643
644 // Synchronize libraries to update the tree view
645 m_parent->SyncLibraries( false );
646
647 // Ensure created symbols are still in the symbol list after sync
648 for( LIB_SYMBOL* symbol : symbolsToPreserve )
649 {
650 bool found = false;
651 for( LIB_SYMBOL* existingSymbol : m_symbolsList )
652 {
653 if( existingSymbol->m_Uuid == symbol->m_Uuid )
654 {
655 found = true;
656 break;
657 }
658 }
659 if( !found )
660 {
661 wxLogTrace( traceLibFieldTable, "Re-adding symbol '%s' to list after sync", symbol->GetName() );
662 m_symbolsList.push_back( symbol );
663 }
664 }
665 }
666
667 wxLogTrace( traceLibFieldTable, "Dialog symbol list size after processing: %zu", m_symbolsList.size() );
668 } );
669
670 ClearModify();
671
672 wxLogTrace( traceLibFieldTable, "About to rebuild grid rows to include new symbols" );
674 wxLogTrace( traceLibFieldTable, "Grid rebuild completed" );
675
676 m_parent->RefreshLibraryTree();
677
678 if( updateCanvas )
679 {
680 m_parent->OnModify();
681 m_parent->HardRedraw();
682 }
683
684 return true;
685}
686
687
688void DIALOG_LIB_FIELDS_TABLE::OnAddField(wxCommandEvent& event)
689{
690 wxTextEntryDialog dlg( this, _( "New field name:" ), _( "Add Field" ) );
691
692 if( dlg.ShowModal() != wxID_OK )
693 return;
694
695 wxString fieldName = dlg.GetValue();
696
697 if( fieldName.IsEmpty() )
698 {
699 DisplayError( this, _( "Field must have a name." ) );
700 return;
701 }
702
703 for( int i = 0; i < m_dataModel->GetNumberCols(); ++i )
704 {
705 if( fieldName == m_dataModel->GetColFieldName( i ) )
706 {
707 DisplayError( this, wxString::Format( _( "Field name '%s' already in use." ), fieldName ) );
708 return;
709 }
710 }
711
712 AddField( fieldName, GetGeneratedFieldDisplayName( fieldName ), true, false, true );
713
714 SetupColumnProperties( m_dataModel->GetColsCount() - 1 );
715
716 OnModify();
717}
718
719
720void DIALOG_LIB_FIELDS_TABLE::OnRemoveField(wxCommandEvent& event)
721{
722 m_viewControlsGrid->OnDeleteRows(
723 [&]( int row )
724 {
725 return IsOK( this, wxString::Format( _( "Are you sure you want to remove the field '%s'?" ),
726 m_viewControlsDataModel->GetValue( row, DISPLAY_NAME_COLUMN ) ) );
727 },
728 [&]( int row )
729 {
730 wxString fieldName = m_viewControlsDataModel->GetCanonicalFieldName( row );
731
732 RemoveField( fieldName );
733
734 m_viewControlsDataModel->DeleteRow( row );
735 OnModify();
736 } );
737}
738
739
740void DIALOG_LIB_FIELDS_TABLE::OnRenameField(wxCommandEvent& event)
741{
742 wxArrayInt selectedRows = m_viewControlsGrid->GetSelectedRows();
743
744 if( selectedRows.empty() && m_viewControlsGrid->GetGridCursorRow() >= 0 )
745 selectedRows.push_back( m_viewControlsGrid->GetGridCursorRow() );
746
747 if( selectedRows.empty() )
748 return;
749
750 int row = selectedRows[0];
751
752 wxString fieldName = m_viewControlsDataModel->GetCanonicalFieldName( row );
753
754 int col = m_dataModel->GetFieldNameCol( fieldName );
755 wxCHECK_RET( col != -1, wxS( "Existing field name missing from data model" ) );
756
757 wxTextEntryDialog dlg( this, _( "New field name:" ), _( "Rename Field" ), fieldName );
758
759 if( dlg.ShowModal() != wxID_OK )
760 return;
761
762 wxString newFieldName = dlg.GetValue();
763
764 if( newFieldName == fieldName )
765 return;
766
767 if( m_dataModel->GetFieldNameCol( newFieldName ) != -1 )
768 {
769 DisplayError( this, wxString::Format( _( "Field name '%s' already exists." ), newFieldName ) );
770 return;
771 }
772
773 RenameField( fieldName, newFieldName );
774
775 m_viewControlsDataModel->SetCanonicalFieldName( row, newFieldName );
776 m_viewControlsDataModel->SetValue( row, DISPLAY_NAME_COLUMN, newFieldName );
777 m_viewControlsDataModel->SetValue( row, LABEL_COLUMN, GetGeneratedFieldDisplayName( newFieldName ) );
778
780 OnModify();
781}
782
783
784void DIALOG_LIB_FIELDS_TABLE::OnFilterText( wxCommandEvent& event )
785{
786 m_dataModel->SetFilter( m_filter->GetValue() );
788}
789
790
792{
793#if defined( __WXOSX__ ) // Doesn't work properly on other ports
794 wxPoint pos = aEvent.GetPosition();
795 wxRect ctrlRect = m_filter->GetScreenRect();
796 int buttonWidth = ctrlRect.GetHeight(); // Presume buttons are square
797
798 // TODO: restore cursor when mouse leaves the filter field (or is it a MSW bug?)
799 if( m_filter->IsSearchButtonVisible() && pos.x < buttonWidth )
800 SetCursor( wxCURSOR_ARROW );
801 else if( m_filter->IsCancelButtonVisible() && pos.x > ctrlRect.GetWidth() - buttonWidth )
802 SetCursor( wxCURSOR_ARROW );
803 else
804 SetCursor( wxCURSOR_IBEAM );
805#endif
806}
807
808
810{
811 LIB_SYMBOL_LIBRARY_MANAGER& libMgr = m_parent->GetLibManager();
812 wxString targetLib = m_parent->GetTargetLibId().GetLibNickname();
813 wxString targetSymbol = m_parent->GetTargetLibId().GetLibItemName();
814 wxArrayString symbolNames;
815
816 SetTitle( wxString::Format( _( "Symbol Fields Table ('%s' Library)" ), targetLib ) );
817
818 m_scope = aScope;
819
820 if( m_scope == SCOPE::SCOPE_RELATED_SYMBOLS )
821 {
822 const LIB_SYMBOL* symbol = libMgr.GetBufferedSymbol( targetSymbol, targetLib );
823 std::shared_ptr<LIB_SYMBOL> root = symbol ? symbol->GetRootSymbol() : nullptr;
824
825 if( root )
826 {
827 symbolNames.Add( root->GetName() );
828
829 // Now we have the root symbol, collect all its derived symbols
830 libMgr.GetDerivedSymbolNames( root->GetName(), targetLib, symbolNames );
831 }
832 }
833 else
834 {
835 // Get all symbol names from the library manager
836 libMgr.GetSymbolNames( targetLib, symbolNames );
837 }
838
839 // Get all symbols from the library
840 loadSymbols( symbolNames );
841
842 // Update the field list and refresh the grid
846}
847
848
849void DIALOG_LIB_FIELDS_TABLE::OnScope( wxCommandEvent& aEvent )
850{
851 switch( aEvent.GetSelection() )
852 {
853 case 0: setScope( SCOPE::SCOPE_LIBRARY ); break;
854 case 1: setScope( SCOPE::SCOPE_RELATED_SYMBOLS ); break;
855 }
856}
857
858
859void DIALOG_LIB_FIELDS_TABLE::OnRegroupSymbols( wxCommandEvent& event )
860{
862}
863
864
866{
867 m_grid->ForceRefresh();
868 OnModify();
869}
870
871
873{
874 if( m_dataModel->IsExpanderColumn( event.GetCol() ) )
875 {
876 m_grid->ClearSelection();
877 m_dataModel->ExpandCollapseRow( event.GetRow() );
878 m_grid->SetGridCursor( event.GetRow(), event.GetCol() );
879 // Don't call event.Skip() - we've handled this event
880 }
881 else
882 {
883 event.Skip(); // Let normal cell editing proceed
884 }
885}
886
887
889{
890 if( m_grid )
891 {
892 // Get global mouse position and convert to grid client coords
893 wxPoint mousePos = wxGetMousePosition();
894 wxPoint gridPt = m_grid->ScreenToClient( mousePos );
895
896 int row = m_grid->YToRow( gridPt.y );
897 int col = m_grid->XToCol( gridPt.x );
898
899 if ( row != -1 && col != -1 )
900 m_grid->SetGridCursor( row, col );
901 }
902
903 event.Skip();
904}
905
906
908{
909 m_dataModel->SetGroupingEnabled( m_groupSymbolsBox->GetValue() );
910 m_dataModel->RebuildRows();
911 m_grid->ForceRefresh();
912}
913
914
915void DIALOG_LIB_FIELDS_TABLE::OnTableColSize(wxGridSizeEvent& aEvent)
916{
917 aEvent.Skip();
918
919 m_grid->ForceRefresh();
920}
921
922
924{
925 const wxString& showColLabel = m_viewControlsGrid->GetColLabelValue( SHOW_FIELD_COLUMN );
926 const wxString& groupByColLabel = m_viewControlsGrid->GetColLabelValue( GROUP_BY_COLUMN );
927 int showColWidth = KIUI::GetTextSize( showColLabel, m_viewControlsGrid ).x + COLUMN_MARGIN;
928 int groupByColWidth = KIUI::GetTextSize( groupByColLabel, m_viewControlsGrid ).x + COLUMN_MARGIN;
929 int remainingWidth = m_viewControlsGrid->GetSize().GetX() - showColWidth - groupByColWidth;
930
931 m_viewControlsGrid->SetColSize( showColWidth, SHOW_FIELD_COLUMN );
932 m_viewControlsGrid->SetColSize( groupByColWidth, GROUP_BY_COLUMN );
933
934 if( m_viewControlsGrid->IsColShown( DISPLAY_NAME_COLUMN ) && m_viewControlsGrid->IsColShown( LABEL_COLUMN ) )
935 {
936 m_viewControlsGrid->SetColSize( DISPLAY_NAME_COLUMN, std::max( remainingWidth / 2, 60 ) );
937 m_viewControlsGrid->SetColSize( LABEL_COLUMN, std::max( remainingWidth - ( remainingWidth / 2 ), 60 ) );
938 }
939 else if( m_viewControlsGrid->IsColShown( DISPLAY_NAME_COLUMN ) )
940 {
941 m_viewControlsGrid->SetColSize( DISPLAY_NAME_COLUMN, std::max( remainingWidth, 60 ) );
942 }
943 else if( m_viewControlsGrid->IsColShown( LABEL_COLUMN ) )
944 {
945 m_viewControlsGrid->SetColSize( LABEL_COLUMN, std::max( remainingWidth, 60 ) );
946 }
947
948 event.Skip();
949}
950
951
952void DIALOG_LIB_FIELDS_TABLE::OnSidebarToggle( wxCommandEvent& event )
953{
954 SYMBOL_EDITOR_SETTINGS::PANEL_LIB_FIELDS_TABLE& cfg = m_parent->libeditconfig()->m_LibFieldEditor;
955
956 if( cfg.sidebar_collapsed )
957 {
958 cfg.sidebar_collapsed = false;
959 m_splitterMainWindow->SplitVertically( m_leftPanel, m_rightPanel, cfg.sash_pos );
960 }
961 else
962 {
963 cfg.sash_pos = m_splitterMainWindow->GetSashPosition();
964 cfg.sidebar_collapsed = true;
966 }
967
969}
970
971
972void DIALOG_LIB_FIELDS_TABLE::OnApply(wxCommandEvent& event)
973{
975}
976
977
978void DIALOG_LIB_FIELDS_TABLE::OnCancel(wxCommandEvent& event)
979{
980 m_grid->CommitPendingChanges( true );
981
982 if( m_dataModel->IsEdited() )
983 {
984 if( !HandleUnsavedChanges( this, _( "Save changes?" ),
985 [&]() -> bool
986 {
987 return TransferDataFromWindow();
988 } ) )
989 return;
990 }
991
992 EndModal( wxID_CANCEL );
993}
994
995
996void DIALOG_LIB_FIELDS_TABLE::OnOk(wxCommandEvent& event)
997{
999 EndModal( wxID_OK );
1000}
1001
1002
1003void DIALOG_LIB_FIELDS_TABLE::OnClose( wxCloseEvent& aEvent )
1004{
1005 m_grid->CommitPendingChanges( true );
1006
1007 if( m_dataModel->IsEdited() )
1008 {
1009 if( !HandleUnsavedChanges( this, _( "Save changes?" ),
1010 [&]() -> bool
1011 {
1012 return TransferDataFromWindow();
1013 } ) )
1014 {
1015 aEvent.Veto();
1016 return;
1017 }
1018 }
1019
1020 aEvent.Skip();
1021}
1022
1023
1025{
1026 auto addMandatoryField =
1027 [&]( FIELD_T fieldId, bool show, bool groupBy )
1028 {
1029 AddField( GetCanonicalFieldName( fieldId ),
1030 GetDefaultFieldName( fieldId, DO_TRANSLATE ), show, groupBy );
1031 };
1032
1033 AddField( LIB_FIELDS_EDITOR_GRID_DATA_MODEL::SYMBOL_NAME, _( "Symbol Name" ), true, false );
1034
1035 // Add mandatory fields first show groupBy
1036 addMandatoryField( FIELD_T::REFERENCE, false, false );
1037 addMandatoryField( FIELD_T::VALUE, true, false );
1038 addMandatoryField( FIELD_T::FOOTPRINT, true, false );
1039 addMandatoryField( FIELD_T::DATASHEET, true, false );
1040 addMandatoryField( FIELD_T::DESCRIPTION, false, false );
1041
1042 AddField( wxS( "Keywords" ), _( "Keywords" ), true, false );
1043
1044 // Add attribute fields as checkboxes show groupBy user checkbox
1045 AddField( wxS( "${EXCLUDE_FROM_BOM}" ), _( "Exclude From BOM" ), true, false, false, true );
1046 AddField( wxS( "${EXCLUDE_FROM_SIM}" ), _( "Exclude From Simulation" ), true, false, false, true );
1047 AddField( wxS( "${EXCLUDE_FROM_BOARD}" ), _( "Exclude From Board" ), true, false, false, true );
1048
1049 AddField( wxS( "Power" ), _( "Power Symbol" ), true, false, false, true );
1050 AddField( wxS( "LocalPower" ), _( "Local Power Symbol" ), true, false, false, true );
1051
1052 // User fields next
1053 std::set<wxString> userFieldNames;
1054
1055 for( LIB_SYMBOL* symbol : m_symbolsList )
1056 {
1057 std::vector< SCH_FIELD* > fields;
1058 symbol->GetFields( fields );
1059
1060 for( SCH_FIELD* field : fields )
1061 {
1062 if( !field->IsMandatory() && !field->IsPrivate() )
1063 userFieldNames.insert( field->GetName() );
1064 }
1065 }
1066
1067 for( const wxString& fieldName : userFieldNames )
1068 AddField( fieldName, GetGeneratedFieldDisplayName( fieldName ), true, false );
1069}
1070
1071
1072void DIALOG_LIB_FIELDS_TABLE::AddField( const wxString& aFieldName, const wxString& aLabelValue, bool show,
1073 bool groupBy, bool addedByUser, bool aIsCheckbox )
1074{
1075 // Users can add fields with variable names that match the special names in the grid,
1076 // e.g. ${QUANTITY} so make sure we don't add them twice
1077 for( int row = 0; row < m_viewControlsDataModel->GetNumberRows(); row++ )
1078 {
1079 if( m_viewControlsDataModel->GetCanonicalFieldName( row ) == aFieldName )
1080 return;
1081 }
1082
1083 m_dataModel->AddColumn( aFieldName, aLabelValue, addedByUser, aIsCheckbox );
1084
1085 wxGridTableMessage msg( m_dataModel, wxGRIDTABLE_NOTIFY_COLS_APPENDED, 1 );
1086 m_grid->ProcessTableMessage( msg );
1087
1088 m_viewControlsGrid->OnAddRow(
1089 [&]() -> std::pair<int, int>
1090 {
1091 m_viewControlsDataModel->AppendRow( aFieldName, aLabelValue, show, groupBy );
1092
1093 return { m_viewControlsDataModel->GetNumberRows() - 1, -1 };
1094 } );
1095}
1096
1097
1098void DIALOG_LIB_FIELDS_TABLE::RemoveField(const wxString& fieldName)
1099{
1100 int col = m_dataModel->GetFieldNameCol( fieldName );
1101 wxCHECK_RET( col != -1, wxS( "Field name not found" ) );
1102
1103 m_dataModel->RemoveColumn( col );
1104}
1105
1106
1107void DIALOG_LIB_FIELDS_TABLE::RenameField(const wxString& oldName, const wxString& newName)
1108{
1109 int col = m_dataModel->GetFieldNameCol( oldName );
1110 wxCHECK_RET( col != -1, wxS( "Existing field name missing from data model" ) );
1111
1112 m_dataModel->RenameColumn( col, newName );
1113}
1114
1115
1117{
1118 m_dataModel->RebuildRows();
1119 m_grid->ForceRefresh();
1120}
1121
1122
1123void DIALOG_LIB_FIELDS_TABLE::OnColSort(wxGridEvent& aEvent)
1124{
1125 int sortCol = aEvent.GetCol();
1126 std::string key( m_dataModel->GetColFieldName( sortCol ).ToUTF8() );
1127 bool ascending;
1128
1129 // This is bonkers, but wxWidgets doesn't tell us ascending/descending in the event, and
1130 // if we ask it will give us pre-event info.
1131 if( m_grid->IsSortingBy( sortCol ) )
1132 {
1133 // same column; invert ascending
1134 ascending = !m_grid->IsSortOrderAscending();
1135 }
1136 else
1137 {
1138 // different column; start with ascending
1139 ascending = true;
1140 }
1141
1142 m_dataModel->SetSorting( sortCol, ascending );
1144}
1145
1146
1147void DIALOG_LIB_FIELDS_TABLE::OnColMove(wxGridEvent& aEvent)
1148{
1149 int origPos = aEvent.GetCol();
1150
1151 // Save column widths since the setup function uses the saved config values
1152 SYMBOL_EDITOR_SETTINGS* cfg = m_parent->GetSettings();
1153
1154 for( int i = 0; i < m_grid->GetNumberCols(); i++ )
1155 {
1156 if( m_grid->IsColShown( i ) )
1157 {
1158 std::string fieldName( m_dataModel->GetColFieldName( i ).ToUTF8() );
1159 cfg->m_LibFieldEditor.field_widths[fieldName] = m_grid->GetColSize( i );
1160 }
1161 }
1162
1163 CallAfter(
1164 [origPos, this]()
1165 {
1166 int newPos = m_grid->GetColPos( origPos );
1167
1168#ifdef __WXMAC__
1169 if( newPos < origPos )
1170 newPos += 1;
1171#endif
1172
1173 m_dataModel->MoveColumn( origPos, newPos );
1174
1175 // "Unmove" the column since we've moved the column internally
1176 m_grid->ResetColPos();
1177
1178 // We need to reset all the column attr's to the correct column order
1180
1181 m_grid->ForceRefresh();
1182 } );
1183}
1184
1185
1187{
1188 if( aShow )
1189 m_grid->ShowCol( aCol );
1190 else
1191 m_grid->HideCol( aCol );
1192
1193 m_dataModel->SetShowColumn( aCol, aShow );
1194
1195 m_grid->ForceRefresh();
1196 OnModify();
1197}
1198
1199
1201{
1202 int row = aEvent.GetRow();
1203
1204 wxCHECK( row < m_viewControlsGrid->GetNumberRows(), /* void */ );
1205
1206 switch( aEvent.GetCol() )
1207 {
1209 {
1210 wxString label = m_viewControlsDataModel->GetValue( row, DISPLAY_NAME_COLUMN );
1211 wxString fieldName = m_viewControlsDataModel->GetCanonicalFieldName( row );
1212 int dataCol = m_dataModel->GetFieldNameCol( fieldName );
1213
1214 if( dataCol != -1 )
1215 {
1216 m_dataModel->SetColLabelValue( dataCol, label );
1217 m_grid->SetColLabelValue( dataCol, label );
1218
1219 m_grid->ForceRefresh();
1220 OnModify();
1221 }
1222
1223 break;
1224 }
1225
1226 case SHOW_FIELD_COLUMN:
1227 {
1228 wxString fieldName = m_viewControlsDataModel->GetCanonicalFieldName( row );
1229 bool value = m_viewControlsDataModel->GetValueAsBool( row, SHOW_FIELD_COLUMN );
1230 int dataCol = m_dataModel->GetFieldNameCol( fieldName );
1231
1232 if( dataCol != -1 )
1233 ShowHideColumn( dataCol, value );
1234
1235 break;
1236 }
1237
1238 case GROUP_BY_COLUMN:
1239 {
1240 wxString fieldName = m_viewControlsDataModel->GetCanonicalFieldName( row );
1241 bool value = m_viewControlsDataModel->GetValueAsBool( row, GROUP_BY_COLUMN );
1242 int dataCol = m_dataModel->GetFieldNameCol( fieldName );
1243
1244 m_dataModel->SetGroupColumn( dataCol, value );
1245 m_dataModel->RebuildRows();
1246
1247 m_grid->ForceRefresh();
1248 OnModify();
1249 break;
1250 }
1251
1252 default:
1253 break;
1254 }
1255}
1256
1257
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: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:83
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:146
wxArrayString GetFPFilters() const
Definition lib_symbol.h:215
wxString GetLibNickname() const override
Sets the Description field text value.
Definition lib_symbol.h:159
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.
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:274
bool IsGeneratedField(const wxString &aSource)
Returns true if the string is generated, e.g contains a single text var reference.
Definition common.cpp:286
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.