KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_lib_symbol_properties.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
21
22#include <pgm_base.h>
23#include <eeschema_settings.h>
24#include <bitmaps.h>
25#include <confirm.h>
27#include <kiway.h>
28#include <symbol_edit_frame.h>
30#include <math/util.h> // for KiROUND
31#include <sch_symbol.h>
32#include <kiplatform/ui.h>
34#include <widgets/wx_grid.h>
36#include <string_utils.h>
37#include <template_fieldnames.h>
38#include <project_sch.h>
39#include <refdes_utils.h>
40#include <dialog_sim_model.h>
41#include <vector>
42
48
49#include <wx/clipbrd.h>
50#include <wx/msgdlg.h>
51
52
56
57
59 LIB_SYMBOL* aLibEntry ) :
61 m_Parent( aParent ),
62 m_libEntry( aLibEntry ),
64 m_delayedFocusCtrl( nullptr ),
65 m_delayedFocusGrid( nullptr ),
70{
71 std::vector<const EMBEDDED_FILES*> inheritedEmbeddedFiles;
72
73 if( std::shared_ptr<LIB_SYMBOL> parent = m_libEntry->GetParent().lock() )
74 {
75 while( parent )
76 {
77 inheritedEmbeddedFiles.push_back( parent->GetEmbeddedFiles() );
78 parent = parent->GetParent().lock();
79 }
80 }
81
82 m_embeddedFiles = new PANEL_EMBEDDED_FILES( m_NoteBook, m_libEntry, 0, std::move( inheritedEmbeddedFiles ) );
83 m_NoteBook->AddPage( m_embeddedFiles, _( "Embedded Files" ) );
84
85 m_pinMapPanel = new PANEL_SYMBOL_PIN_MAP( m_pinMapPage );
86 bPinMapPageSizer->Add( m_pinMapPanel, 1, wxEXPAND, 5 );
87
88 m_fields = new FIELDS_GRID_TABLE( this, aParent, m_grid, m_libEntry, { m_embeddedFiles->GetLocalFiles() } );
89 m_grid->SetTable( m_fields );
90 m_grid->OverrideMinSize( 1.0, 1.0 );
91 m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this, { m_embeddedFiles->GetLocalFiles() },
92 [&]( wxCommandEvent& aEvent )
93 {
94 OnAddField( aEvent );
95 } ) );
96 m_grid->SetSelectionMode( wxGrid::wxGridSelectRows );
97
98 // Load the FIELDS_GRID_TABLE -- ensure we are calling the overloaded push_back method
99 std::vector<SCH_FIELD> fields;
100 m_libEntry->CopyFields( fields );
101
102 for( const SCH_FIELD& f : fields )
103 m_fields->push_back( f );
104
105 if( std::shared_ptr<LIB_SYMBOL> parent = m_libEntry->GetParent().lock() )
106 addInheritedFields( parent );
107
108 m_grid->ShowHideColumns( "0 1 2 3 4 5 6 7" );
109
110 m_SymbolNameCtrl->SetValidator( FIELD_VALIDATOR( FIELD_T::VALUE ) );
111
112 m_unitNamesGrid->PushEventHandler( new GRID_TRICKS( m_unitNamesGrid ) );
113 m_unitNamesGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
114
115 m_bodyStyleNamesGrid->PushEventHandler( new GRID_TRICKS( m_bodyStyleNamesGrid,
116 [this]( wxCommandEvent& aEvent )
117 {
118 OnAddBodyStyle( aEvent );
119 } ) );
120 m_bodyStyleNamesGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
121
122 m_jumperGroupsGrid->SetupColumnAutosizer( 0 );
123 m_jumperGroupsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
124
125 m_jumperGroupsGrid->PushEventHandler( new GRID_TRICKS( m_jumperGroupsGrid,
126 [this]( wxCommandEvent& aEvent )
127 {
128 OnAddJumperGroup( aEvent );
129 } ) );
130
131 // Configure button logos
132 m_bpAdd->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
133 m_bpMoveUp->SetBitmap( KiBitmapBundle( BITMAPS::small_up ) );
134 m_bpMoveDown->SetBitmap( KiBitmapBundle( BITMAPS::small_down ) );
135 m_bpDelete->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
136
137 m_bpAddBodyStyle->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
138 m_bpMoveUpBodyStyle->SetBitmap( KiBitmapBundle( BITMAPS::small_up ) );
139 m_bpMoveDownBodyStyle->SetBitmap( KiBitmapBundle( BITMAPS::small_down ) );
140 m_bpDeleteBodyStyle->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
141
142 m_addFilterButton->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
143 m_editFilterButton->SetBitmap( KiBitmapBundle( BITMAPS::small_edit ) );
144 m_deleteFilterButton->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
145
146 m_bpAddJumperGroup->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
147 m_bpRemoveJumperGroup->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
148
149 SetupStandardButtons();
150
151 if( aParent->IsSymbolFromLegacyLibrary() && !aParent->IsSymbolFromSchematic() )
152 {
153 m_stdSizerButtonCancel->SetDefault();
154 m_stdSizerButtonOK->SetLabel( _( "Read Only" ) );
155 m_stdSizerButtonOK->Enable( false );
156 }
157
158 // wxFormBuilder doesn't include this event...
159 m_grid->Bind( wxEVT_GRID_CELL_CHANGING, &DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanging, this );
160 m_grid->Bind( wxEVT_GRID_CELL_CHANGED, &DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanged, this );
161 m_grid->GetGridWindow()->Bind( wxEVT_MOTION, &DIALOG_LIB_SYMBOL_PROPERTIES::OnGridMotion, this );
162
163
164 // Forward the delete button to the tricks
165 m_deleteFilterButton->Bind( wxEVT_BUTTON,
166 [&]( wxCommandEvent& aEvent )
167 {
168 wxCommandEvent cmdEvent( EDA_EVT_LISTBOX_DELETE );
169 m_fpFilterTricks->ProcessEvent( cmdEvent );
170 } );
171
172 // When the filter tricks modifies something, update ourselves
173 m_FootprintFilterListBox->Bind( EDA_EVT_LISTBOX_CHANGED,
174 [&]( wxCommandEvent& aEvent )
175 {
176 OnModify();
177 } );
178
180 {
181 if( ( m_lastLayout == DIALOG_LIB_SYMBOL_PROPERTIES::LAST_LAYOUT::ALIAS && aLibEntry->IsRoot() )
182 || ( m_lastLayout == DIALOG_LIB_SYMBOL_PROPERTIES::LAST_LAYOUT::PARENT && aLibEntry->IsDerived() ) )
183 {
184 resetSize();
185 }
186 }
187
188 m_lastLayout = ( aLibEntry->IsDerived() ) ? DIALOG_LIB_SYMBOL_PROPERTIES::LAST_LAYOUT::ALIAS
190
191 m_grid->GetParent()->Layout();
192 syncControlStates( m_libEntry->IsDerived() );
193 Layout();
194
195 finishDialogSettings();
196}
197
198
200{
201 // TransferDataToWindow restores the remembered page, so defer the switch to a flag it honours.
202 m_forcePinMapPage = true;
203
204 for( size_t page = 0; page < m_NoteBook->GetPageCount(); ++page )
205 {
206 if( m_NoteBook->GetPage( page ) == m_pinMapPage )
207 {
208 m_NoteBook->SetSelection( page );
209 return;
210 }
211 }
212}
213
214
216{
217 m_lastOpenedPage = m_NoteBook->GetSelection( );
218
219 // Prevents crash bug in wxGrid's d'tor
220 m_grid->DestroyTable( m_fields );
221
222 m_grid->Unbind( wxEVT_GRID_CELL_CHANGING, &DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanging, this );
223 m_grid->Unbind( wxEVT_GRID_CELL_CHANGED, &DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanged, this );
224 m_grid->GetGridWindow()->Unbind( wxEVT_MOTION, &DIALOG_LIB_SYMBOL_PROPERTIES::OnGridMotion, this );
225
226 // Delete the GRID_TRICKS.
227 m_grid->PopEventHandler( true );
228 m_unitNamesGrid->PopEventHandler( true );
229 m_bodyStyleNamesGrid->PopEventHandler( true );
230 m_jumperGroupsGrid->PopEventHandler( true );
231}
232
233
234void DIALOG_LIB_SYMBOL_PROPERTIES::addInheritedFields( const std::shared_ptr<LIB_SYMBOL>& aParent )
235{
236 if( std::shared_ptr<LIB_SYMBOL> ancestor = aParent->GetParent().lock() )
237 addInheritedFields( ancestor );
238
239 std::vector<SCH_FIELD*> parentFields;
240 aParent->GetFields( parentFields );
241
242 for( SCH_FIELD* parentField : parentFields )
243 {
244 bool found = false;
245
246 if( parentField->IsMandatory() )
247 continue; // Don't inherit mandatory fields
248
249 for( size_t ii = 0; ii < m_fields->size(); ++ii )
250 {
251 SCH_FIELD& field = m_fields->at( ii );
252
253 if( field.IsMandatory() )
254 continue; // Don't inherit mandatory fields
255
256 if( field.GetCanonicalName() == parentField->GetCanonicalName() )
257 {
258 m_fields->SetFieldInherited( ii, *parentField );
259 found = true;
260 break;
261 }
262 }
263
264 if( !found )
265 m_fields->AddInheritedField( *parentField );
266 }
267}
268
269
271{
272 if( !wxDialog::TransferDataToWindow() )
273 return false;
274
275 std::set<wxString> defined;
276
277 for( SCH_FIELD& field : *m_fields )
278 defined.insert( field.GetName() );
279
280 // Add in any template fieldnames not yet defined:
281 // Read global fieldname templates
283 {
284 TEMPLATES templateMgr;
285
286 if( !cfg->m_Drawing.field_names.IsEmpty() )
287 templateMgr.AddTemplateFieldNames( cfg->m_Drawing.field_names );
288
289 for( const TEMPLATE_FIELDNAME& templateFieldname : templateMgr.GetTemplateFieldNames() )
290 {
291 if( defined.count( templateFieldname.m_Name ) <= 0 )
292 {
293 SCH_FIELD field( m_libEntry, FIELD_T::USER, templateFieldname.m_Name );
294 field.SetVisible( templateFieldname.m_Visible );
295 m_fields->push_back( field );
296 m_addedTemplateFields.insert( templateFieldname.m_Name );
297 }
298 }
299 }
300
301 // The Y axis for components in library file is from bottom to top while the screen axis is top
302 // to bottom.However it is nowhandled by the lib file parser/writer.
303
304 // notify the grid
305 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_fields->GetNumberRows() );
306 m_grid->ProcessTableMessage( msg );
307
308 m_SymbolNameCtrl->ChangeValue( UnescapeString( m_libEntry->GetName() ) );
309
310 m_KeywordCtrl->ChangeValue( m_libEntry->GetKeyWords() );
311 m_unitSpinCtrl->SetValue( m_libEntry->GetUnitCount() );
312 m_OptionPartsInterchangeable->SetValue( !m_libEntry->UnitsLocked() || m_libEntry->GetUnitCount() == 1 );
313
315
316 for( int unit = 0; unit < m_libEntry->GetUnitCount(); unit++ )
317 {
318 if( m_libEntry->GetUnitDisplayNames().contains( unit + 1 ) )
319 m_unitNamesGrid->SetCellValue( unit, 1, m_libEntry->GetUnitDisplayNames().at( unit + 1 ) );
320 }
321
322 if( m_libEntry->HasDeMorganBodyStyles() )
323 {
324 m_radioDeMorgan->SetValue( true );
325 }
326 else if( m_libEntry->IsMultiBodyStyle() )
327 {
328 m_radioCustom->SetValue( true );
329
330 for( const wxString& name : m_libEntry->GetBodyStyleNames() )
331 {
332 int row = m_bodyStyleNamesGrid->GetNumberRows();
333 m_bodyStyleNamesGrid->AppendRows( 1 );
334 m_bodyStyleNamesGrid->SetCellValue( row, 0, name );
335 }
336 }
337 else
338 {
339 m_radioSingle->SetValue( true );
340 }
341
342 m_OptionPower->SetValue( m_libEntry->IsPower() );
343 m_OptionLocalPower->SetValue( m_libEntry->IsLocalPower() );
344
345 if( m_libEntry->IsPower() )
346 {
347 m_spiceFieldsButton->Hide();
348 m_OptionLocalPower->Enable();
349 }
350 else
351 {
352 m_OptionLocalPower->Enable( false );
353 }
354
355 m_excludeFromSimCheckBox->SetValue( m_libEntry->GetExcludedFromSim() );
356 m_excludeFromBomCheckBox->SetValue( m_libEntry->GetExcludedFromBOM() );
357 m_excludeFromBoardCheckBox->SetValue( m_libEntry->GetExcludedFromBoard() );
358 m_excludeFromPosFilesCheckBox->SetValue( m_libEntry->GetExcludedFromPosFiles() );
359
360 m_ShowPinNumButt->SetValue( m_libEntry->GetShowPinNumbers() );
361 m_ShowPinNameButt->SetValue( m_libEntry->GetShowPinNames() );
362 m_PinsNameInsideButt->SetValue( m_libEntry->GetPinNameOffset() != 0 );
363 m_pinNameOffset.ChangeValue( m_libEntry->GetPinNameOffset() );
364
365 wxArrayString tmp = m_libEntry->GetFPFilters();
366 m_FootprintFilterListBox->Append( tmp );
367
368 m_cbDuplicatePinsAreJumpers->SetValue( m_libEntry->GetDuplicatePinNumbersAreJumpers() );
369
370 std::set<wxString> availablePins;
371
372 for( const SCH_PIN* pin : m_libEntry->GetGraphicalPins( 0, 0 ) )
373 availablePins.insert( pin->GetNumber() );
374
375 for( const std::set<wxString>& group : m_libEntry->JumperPinGroups() )
376 {
377 wxString groupTxt;
378
379 for( const wxString& pinNumber : group )
380 {
381 if( !groupTxt.IsEmpty() )
382 groupTxt << ", ";
383
384 groupTxt << pinNumber;
385 }
386
387 m_jumperGroupsGrid->AppendRows( 1 );
388 m_jumperGroupsGrid->SetCellValue( m_jumperGroupsGrid->GetNumberRows() - 1, 0, groupTxt );
389 }
390
391 // Populate the list of root parts for inherited objects.
392 if( m_libEntry->IsDerived() )
393 {
394 wxArrayString symbolNames;
395 wxString libName = m_libEntry->GetLibNickname();
396
397 if( !libName.empty() )
398 {
399 m_Parent->GetLibManager().GetSymbolNames( libName, symbolNames );
400
401 // Sort the list of symbols for easier search
402 symbolNames.Sort(
403 []( const wxString& a, const wxString& b ) -> int
404 {
405 return StrNumCmp( a, b, true );
406 } );
407
408 // Don't allow a symbol to be derived from itself
409 if( symbolNames.Index( m_libEntry->GetName() ) != wxNOT_FOUND )
410 symbolNames.Remove( m_libEntry->GetName() );
411
412 // Don't allow a symbol to be derived from any of its descendants (would create
413 // circular inheritance)
414 wxArrayString descendants;
415 m_Parent->GetLibManager().GetDerivedSymbolNames( m_libEntry->GetName(), libName, descendants );
416
417 for( const wxString& descendant : descendants )
418 {
419 if( symbolNames.Index( descendant ) != wxNOT_FOUND )
420 symbolNames.Remove( descendant );
421 }
422
423 m_inheritanceSelectCombo->Append( symbolNames );
424
425 if( std::shared_ptr<LIB_SYMBOL> rootSymbol = m_libEntry->GetParent().lock() )
426 {
427 wxString parentName = UnescapeString( rootSymbol->GetName() );
428 int selection = m_inheritanceSelectCombo->FindString( parentName );
429
430 if( selection != wxNOT_FOUND )
431 m_inheritanceSelectCombo->SetSelection( selection );
432 }
433 }
434
436 }
437
438 m_NoteBook->SetSelection( (unsigned) m_lastOpenedPage );
439
440 m_embeddedFiles->TransferDataToWindow();
441
442 m_grid->SetMinVisibleRows( this, 4 );
443
444 m_pinMapPanel->SetSymbol( m_libEntry );
445 m_pinMapPanel->TransferDataToWindow();
446
447 // Always open on the General page, unless the caller explicitly asked for the Pin Map
448 // tab (the Edit Pin Map button). This overrides DIALOG_SHIM's remembered-tab restore.
449 int targetPage = 0;
450
452 {
453 for( size_t page = 0; page < m_NoteBook->GetPageCount(); ++page )
454 {
455 if( m_NoteBook->GetPage( page ) == m_pinMapPage )
456 {
457 targetPage = (int) page;
458 break;
459 }
460 }
461 }
462
463 m_NoteBook->ChangeSelection( targetPage );
464
465 return true;
466}
467
468
470{
471 if( !m_grid->CommitPendingChanges() )
472 return false;
473
474 // Symbol reference can be empty because it inherits from the parent symbol.
475 if( m_libEntry->IsRoot() )
476 {
477 SCH_FIELD* field = m_fields->GetField( FIELD_T::REFERENCE );
478
479 if( UTIL::GetRefDesPrefix( field->GetText() ).IsEmpty() )
480 {
481 if( m_NoteBook->GetSelection() != 0 )
482 m_NoteBook->SetSelection( 0 );
483
484 m_delayedErrorMessage = _( "References must start with a letter." );
489
490 return false;
491 }
492 }
493
494 // Check for missing field names.
495 for( int ii = 0; ii < (int) m_fields->size(); ++ii )
496 {
497 SCH_FIELD& field = m_fields->at( ii );
498
499 if( field.IsMandatory() )
500 continue;
501
502 wxString fieldName = field.GetName( false );
503
504 if( fieldName.IsEmpty() && !field.GetText().IsEmpty() )
505 {
506 if( m_NoteBook->GetSelection() != 0 )
507 m_NoteBook->SetSelection( 0 );
508
509 m_delayedErrorMessage = _( "Fields must have a name." );
514
515 return false;
516 }
517 }
518
519 // Verify that the parent name is set if the symbol is inherited
520 if( m_libEntry->IsDerived() )
521 {
522 wxString parentName = m_inheritanceSelectCombo->GetValue();
523
524 if( parentName.IsEmpty() )
525 {
526 m_delayedErrorMessage = _( "Derived symbol must have a parent selected" );
527 return false;
528 }
529 }
530
531 if( !m_unitNamesGrid->CommitPendingChanges() )
532 return false;
533
534 std::set<wxString> seenSubRefs;
535
536 for( int row = 0; row < m_unitNamesGrid->GetNumberRows(); ++row )
537 {
538 wxString subRef = m_unitNamesGrid->GetCellValue( row, 1 );
539
540 if( subRef.IsEmpty() )
541 subRef = LIB_SYMBOL::LetterSubReference( row + 1, 'A' );
542
543 if( !seenSubRefs.insert( subRef.Upper() ).second )
544 {
545 m_delayedErrorMessage = wxString::Format( _( "The unit name '%s' is already in use." ), subRef );
548 m_delayedFocusRow = row;
550 return false;
551 }
552 }
553
554 /*
555 * Confirm destructive actions.
556 */
557
558 if( m_unitSpinCtrl->GetValue() < m_libEntry->GetUnitCount() )
559 {
560 if( !IsOK( this, _( "Delete extra units from symbol?" ) ) )
561 return false;
562 }
563
564 int bodyStyleCount = 0;
565
566 if( m_radioSingle->GetValue() )
567 {
568 bodyStyleCount = 1;
569 }
570 else if( m_radioDeMorgan->GetValue() )
571 {
572 bodyStyleCount = 2;
573 }
574 else if( m_radioCustom->GetValue() )
575 {
576 if( !m_bodyStyleNamesGrid->CommitPendingChanges() )
577 return false;
578
579 for( int ii = 0; ii < m_bodyStyleNamesGrid->GetNumberRows(); ++ii )
580 {
581 if( !m_bodyStyleNamesGrid->GetCellValue( ii, 0 ).IsEmpty() )
582 bodyStyleCount++;
583 }
584 }
585
586 if( m_radioCustom->GetValue() && bodyStyleCount < 2 )
587 {
588 m_delayedErrorMessage = _( "Custom body styles must have at least 2 entries" );
589 return false;
590 }
591
592 if( bodyStyleCount < m_libEntry->GetBodyStyleCount() )
593 {
594 if( !IsOK( this, _( "Delete extra body styles from symbol?" ) ) )
595 return false;
596 }
597
598 return true;
599}
600
601
603{
604 if( !m_grid->CommitPendingChanges()
605 || !m_unitNamesGrid->CommitPendingChanges()
606 || !m_bodyStyleNamesGrid->CommitPendingChanges()
607 || !m_jumperGroupsGrid->CommitPendingChanges()
608 || !m_embeddedFiles->TransferDataFromWindow() )
609 {
610 return false;
611 }
612
613 wxString newName = EscapeString( m_SymbolNameCtrl->GetValue(), CTX_LIBID );
614 wxString oldName = m_libEntry->GetName();
615
616 if( newName.IsEmpty() )
617 {
618 wxMessageBox( _( "Symbol must have a name." ) );
619 return false;
620 }
621
623
624 if( oldName != newName )
625 {
626 wxString libName = m_libEntry->GetLibNickname();
627
628 if( !libName.empty() && m_Parent->GetLibManager().SymbolNameInUse( newName, libName ) )
629 {
630 wxString msg;
631
632 msg.Printf( _( "Symbol name '%s' already in use in library '%s'." ),
633 UnescapeString( newName ),
634 libName );
635 DisplayErrorMessage( this, msg );
636 return false;
637 }
638
639 opType = UNDO_REDO::LIB_RENAME;
640 }
641
642 // When invoked from the library tree (Symbol Properties context menu) we edit a buffered
643 // copy that is not the symbol loaded in the editor. The editor-coupled side effects below
644 // (undo list, view/title refresh) operate on the frame's current symbol, so only run them
645 // when we are actually editing it. The library-tree path does its own buffer/tree update.
646 bool editingCurrentSymbol = ( m_libEntry == m_Parent->GetCurSymbol() );
647
648 if( editingCurrentSymbol )
649 m_Parent->SaveCopyInUndoList( _( "Edit Symbol Properties" ), m_libEntry, opType );
650
651 // The Y axis for components in lib is from bottom to top while the screen axis is top
652 // to bottom: we must change the y coord sign when writing back to the library
653 std::vector<SCH_FIELD> fieldsToSave;
654 int ordinal = 42; // Arbitrarily larger than any mandatory FIELD_T ids.
655
656 for( size_t ii = 0; ii < m_fields->size(); ++ii )
657 {
658 SCH_FIELD& field = m_fields->at( ii );
659
660 if( !field.IsMandatory() )
661 field.SetOrdinal( ordinal++ );
662
663 wxString fieldName = field.GetCanonicalName();
664
665 // Writing an unmodified inherited row into the derived symbol would stop it from
666 // tracking the parent field. Fields the symbol already owns (transferred user
667 // fields) are kept even when they match the parent. operator== is owner-sensitive,
668 // so compare content.
669 if( m_fields->IsInherited( ii ) && !m_libEntry->GetField( fieldName )
670 && field.HasSameContent( m_fields->ParentField( ii ) ) )
671 {
672 continue;
673 }
674
675 if( field.GetText().IsEmpty() )
676 {
677 if( fieldName.IsEmpty() || m_addedTemplateFields.contains( fieldName ) )
678 continue; // Skip empty fields that are not mandatory or template fields
679 }
680 else if( fieldName.IsEmpty() )
681 {
682 field.SetName( _( "untitled" ) ); // Set a default name for unnamed fields
683 }
684
685 fieldsToSave.push_back( field );
686 }
687
688 m_libEntry->SetFields( fieldsToSave );
689
690 // Update the parent for inherited symbols
691 if( m_libEntry->IsDerived() && !m_libEntry->GetLibNickname().empty() )
692 {
693 wxString parentName = EscapeString( m_inheritanceSelectCombo->GetValue(), CTX_LIBID );
694 wxString libName = m_libEntry->GetLibNickname();
695
696 // Get the parent from the libManager based on the name set in the inheritance combo box.
697 LIB_SYMBOL* newParent = m_Parent->GetLibManager().GetSymbol( parentName, libName );
698
699 // Verify that the requested parent exists
700 wxCHECK( newParent, false );
701
702 m_libEntry->SetParent( newParent );
703 }
704
705 m_libEntry->SetName( newName );
706 m_libEntry->SetKeyWords( m_KeywordCtrl->GetValue() );
707 m_libEntry->SetUnitCount( m_unitSpinCtrl->GetValue(), true );
708 m_libEntry->LockUnits( m_libEntry->GetUnitCount() > 1 && !m_OptionPartsInterchangeable->GetValue() );
709
710 m_libEntry->GetUnitDisplayNames().clear();
711
712 for( int row = 0; row < m_unitNamesGrid->GetNumberRows(); row++ )
713 {
714 if( !m_unitNamesGrid->GetCellValue( row, 1 ).IsEmpty() )
715 m_libEntry->GetUnitDisplayNames()[row+1] = m_unitNamesGrid->GetCellValue( row, 1 );
716 }
717
718 if( m_radioSingle->GetValue() )
719 {
720 m_libEntry->SetHasDeMorganBodyStyles( false );
721 m_libEntry->SetBodyStyleCount( 1, false, false );
722 m_libEntry->SetBodyStyleNames( {} );
723 }
724 else if( m_radioDeMorgan->GetValue() )
725 {
726 m_libEntry->SetHasDeMorganBodyStyles( true );
727 m_libEntry->SetBodyStyleCount( 2, false, true );
728 m_libEntry->SetBodyStyleNames( {} );
729 }
730 else
731 {
732 std::vector<wxString> bodyStyleNames;
733
734 for( int row = 0; row < m_bodyStyleNamesGrid->GetNumberRows(); ++row )
735 {
736 if( !m_bodyStyleNamesGrid->GetCellValue( row, 0 ).IsEmpty() )
737 bodyStyleNames.push_back( m_bodyStyleNamesGrid->GetCellValue( row, 0 ) );
738 }
739
740 m_libEntry->SetHasDeMorganBodyStyles( false );
741 m_libEntry->SetBodyStyleCount( bodyStyleNames.size(), true, true );
742 m_libEntry->SetBodyStyleNames( bodyStyleNames );
743 }
744
745 if( m_OptionPower->GetValue() )
746 {
747 if( m_OptionLocalPower->GetValue() )
748 m_libEntry->SetLocalPower();
749 else
750 m_libEntry->SetGlobalPower();
751
752 // Power symbols must have value matching name for now
753 m_libEntry->GetValueField().SetText( newName );
754 }
755 else
756 {
757 m_libEntry->SetNormal();
758 }
759
760 m_libEntry->SetExcludedFromSim( m_excludeFromSimCheckBox->GetValue() );
761 m_libEntry->SetExcludedFromBOM( m_excludeFromBomCheckBox->GetValue() );
762 m_libEntry->SetExcludedFromBoard( m_excludeFromBoardCheckBox->GetValue() );
763 m_libEntry->SetExcludedFromPosFiles( m_excludeFromPosFilesCheckBox->GetValue() );
764
765 m_libEntry->SetShowPinNumbers( m_ShowPinNumButt->GetValue() );
766 m_libEntry->SetShowPinNames( m_ShowPinNameButt->GetValue() );
767
768 if( m_PinsNameInsideButt->GetValue() )
769 {
770 int offset = KiROUND( (double) m_pinNameOffset.GetValue() );
771
772 // We interpret an offset of 0 as "outside", so make sure it's non-zero
773 m_libEntry->SetPinNameOffset( offset == 0 ? 20 : offset );
774 }
775 else
776 {
777 m_libEntry->SetPinNameOffset( 0 ); // pin text outside the body (name is on the pin)
778 }
779
780 m_libEntry->SetFPFilters( m_FootprintFilterListBox->GetStrings());
781
782 m_libEntry->SetDuplicatePinNumbersAreJumpers( m_cbDuplicatePinsAreJumpers->GetValue() );
783
784 std::set<wxString> availablePins;
785
786 for( const SCH_PIN* pin : m_libEntry->GetGraphicalPins( 0, 0 ) )
787 availablePins.insert( pin->GetNumber() );
788
789 std::vector<std::set<wxString>>& jumpers = m_libEntry->JumperPinGroups();
790 jumpers.clear();
791
792 for( int ii = 0; ii < m_jumperGroupsGrid->GetNumberRows(); ++ii )
793 {
794 wxStringTokenizer tokenizer( m_jumperGroupsGrid->GetCellValue( ii, 0 ), ", \t\r\n", wxTOKEN_STRTOK );
795 std::set<wxString>& group = jumpers.emplace_back();
796
797 while( tokenizer.HasMoreTokens() )
798 {
799 wxString token = tokenizer.GetNextToken();
800
801 if( token.IsEmpty() )
802 continue;
803
804 if( !availablePins.count( token ) )
805 {
806 wxString msg;
807 msg.Printf( _( "Pin '%s' in jumper pin group %d does not exist in this symbol." ),
808 token, ii + 1 );
809 DisplayErrorMessage( this, msg );
810 return false;
811 }
812
813 group.insert( token );
814 }
815 }
816
817 if( !m_pinMapPanel->CommitPendingChanges() )
818 return false;
819
820 m_pinMapPanel->ApplyToSymbol( m_libEntry );
821
822 if( editingCurrentSymbol )
823 m_Parent->UpdateAfterSymbolProperties( &oldName );
824
825 return true;
826}
827
828
829void DIALOG_LIB_SYMBOL_PROPERTIES::OnBodyStyle( wxCommandEvent& event )
830{
831 m_bodyStyleNamesGrid->Enable( m_radioCustom->GetValue() );
832
833 m_bpAddBodyStyle->Enable( m_radioCustom->GetValue() );
834 m_bpMoveUpBodyStyle->Enable( m_radioCustom->GetValue() );
835 m_bpMoveDownBodyStyle->Enable( m_radioCustom->GetValue() );
836 m_bpDeleteBodyStyle->Enable( m_radioCustom->GetValue() );
837}
838
839
841{
842 aEvent.Skip();
843
844 wxPoint pos = aEvent.GetPosition();
845 wxPoint unscolled_pos = m_grid->CalcUnscrolledPosition( pos );
846 int row = m_grid->YToRow( unscolled_pos.y );
847 int col = m_grid->XToCol( unscolled_pos.x );
848
849 if( row == wxNOT_FOUND || col == wxNOT_FOUND || !m_fields->IsInherited( row ) )
850 {
851 m_grid->SetToolTip( "" );
852 return;
853 }
854
855 m_grid->SetToolTip( wxString::Format( _( "This field is inherited from '%s'." ),
856 m_fields->ParentField( row ).GetName() ) );
857}
858
859
861{
862 wxGridCellEditor* editor = m_grid->GetCellEditor( event.GetRow(), event.GetCol() );
863 wxControl* control = editor->GetControl();
864
865 if( control && control->GetValidator() && !control->GetValidator()->Validate( control ) )
866 {
867 event.Veto();
868
870 m_delayedFocusRow = event.GetRow();
871 m_delayedFocusColumn = event.GetCol();
873 }
874 else if( event.GetCol() == FDC_NAME )
875 {
876 wxString newName = event.GetString();
877
878 for( int i = 0; i < m_grid->GetNumberRows(); ++i )
879 {
880 if( i == event.GetRow() )
881 continue;
882
883 if( FieldNamesAreDuplicates( newName, m_grid->GetCellValue( i, FDC_NAME ) ) )
884 {
885 DisplayError( this, wxString::Format( _( "The name '%s' is already in use." ), newName ) );
886 event.Veto();
887 m_delayedFocusRow = event.GetRow();
888 m_delayedFocusColumn = event.GetCol();
889 }
890 }
891 }
892
893 editor->DecRef();
894}
895
896
898{
899 m_grid->ForceRefresh();
900 OnModify();
901}
902
903
905{
906 if( m_OptionPower->IsChecked() )
907 m_grid->SetCellValue( m_fields->GetFieldRow( FIELD_T::VALUE ), FDC_VALUE, m_SymbolNameCtrl->GetValue() );
908
909 OnModify();
910}
911
912
914{
915 if( !m_delayedFocusCtrl )
916 {
917 // If the validation fails and we throw up a dialog then GTK will give us another
918 // KillFocus event and we end up in infinite recursion. So we use m_delayedFocusCtrl
919 // as a re-entrancy block and then clear it again if validation passes.
922
923 if( m_SymbolNameCtrl->GetValidator()->Validate( m_SymbolNameCtrl ) )
924 {
925 m_delayedFocusCtrl = nullptr;
927 }
928 }
929
930 event.Skip();
931}
932
933
934void DIALOG_LIB_SYMBOL_PROPERTIES::OnAddField( wxCommandEvent& event )
935{
936 m_grid->OnAddRow(
937 [&]() -> std::pair<int, int>
938 {
939 SYMBOL_EDITOR_SETTINGS* settings = m_Parent->GetSettings();
941
942 newField.SetTextSize( VECTOR2I( schIUScale.MilsToIU( settings->m_Defaults.text_size ),
943 schIUScale.MilsToIU( settings->m_Defaults.text_size ) ) );
944 newField.SetVisible( false );
945
946 m_fields->push_back( newField );
947
948 // notify the grid
949 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
950 m_grid->ProcessTableMessage( msg );
951 OnModify();
952
953 return { m_fields->size() - 1, FDC_NAME };
954 } );
955}
956
957
959{
960 m_grid->OnDeleteRows(
961 [&]( int row )
962 {
963 if( row < m_fields->GetMandatoryRowCount() )
964 {
965 DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
966 m_fields->GetMandatoryRowCount() ) );
967 return false;
968 }
969
970 return true;
971 },
972 [&]( int row )
973 {
974 if( !m_fields->EraseRow( row ) )
975 return;
976
977 // notify the grid
978 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 );
979 m_grid->ProcessTableMessage( msg );
980 } );
981
982 OnModify();
983}
984
985
986void DIALOG_LIB_SYMBOL_PROPERTIES::OnMoveUp( wxCommandEvent& event )
987{
988 m_grid->OnMoveRowUp(
989 [&]( int row )
990 {
991 return row > m_fields->GetMandatoryRowCount();
992 },
993 [&]( int row )
994 {
995 m_fields->SwapRows( row, row - 1 );
996 m_grid->ForceRefresh();
997 OnModify();
998 } );
999}
1000
1001
1002void DIALOG_LIB_SYMBOL_PROPERTIES::OnMoveDown( wxCommandEvent& event )
1003{
1004 m_grid->OnMoveRowDown(
1005 [&]( int row )
1006 {
1007 return row >= m_fields->GetMandatoryRowCount();
1008 },
1009 [&]( int row )
1010 {
1011 m_fields->SwapRows( row, row + 1 );
1012 m_grid->ForceRefresh();
1013 OnModify();
1014 } );
1015}
1016
1017
1019{
1020 m_bodyStyleNamesGrid->OnAddRow(
1021 [&]() -> std::pair<int, int>
1022 {
1023 m_bodyStyleNamesGrid->AppendRows( 1 );
1024 OnModify();
1025
1026 return { m_bodyStyleNamesGrid->GetNumberRows() - 1, 0 };
1027 } );
1028}
1029
1030
1032{
1033 m_bodyStyleNamesGrid->OnDeleteRows(
1034 [&]( int row )
1035 {
1036 m_bodyStyleNamesGrid->DeleteRows( row );
1037 } );
1038
1039 OnModify();
1040}
1041
1042
1044{
1045 m_bodyStyleNamesGrid->OnMoveRowUp(
1046 [&]( int row )
1047 {
1048 m_bodyStyleNamesGrid->SwapRows( row, row - 1 );
1049 OnModify();
1050 } );
1051}
1052
1053
1055{
1056 m_bodyStyleNamesGrid->OnMoveRowDown(
1057 [&]( int row )
1058 {
1059 m_bodyStyleNamesGrid->SwapRows( row, row + 1 );
1060 OnModify();
1061 } );
1062}
1063
1064
1066{
1067 if( !m_grid->CommitPendingChanges() )
1068 return;
1069
1070 m_grid->ClearSelection();
1071
1072 std::vector<SCH_FIELD> fields;
1073
1074 for( const SCH_FIELD& field : *m_fields )
1075 fields.emplace_back( field );
1076
1077 DIALOG_SIM_MODEL dialog( this, m_parentFrame, *m_libEntry, fields );
1078
1079 if( dialog.ShowModal() != wxID_OK )
1080 return;
1081
1082 // Add in any new fields
1083 for( const SCH_FIELD& editedField : fields )
1084 {
1085 bool found = false;
1086
1087 for( SCH_FIELD& existingField : *m_fields )
1088 {
1089 if( existingField.GetName() == editedField.GetName() )
1090 {
1091 found = true;
1092 existingField.SetText( editedField.GetText() );
1093 break;
1094 }
1095 }
1096
1097 if( !found )
1098 {
1099 m_fields->emplace_back( editedField );
1100 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
1101 m_grid->ProcessTableMessage( msg );
1102 }
1103 }
1104
1105 // Remove any deleted fields
1106 for( int ii = (int) m_fields->size() - 1; ii >= 0; --ii )
1107 {
1108 SCH_FIELD& existingField = m_fields->at( ii );
1109 bool found = false;
1110
1111 for( SCH_FIELD& editedField : fields )
1112 {
1113 if( editedField.GetName() == existingField.GetName() )
1114 {
1115 found = true;
1116 break;
1117 }
1118 }
1119
1120 if( !found )
1121 {
1122 m_grid->ClearSelection();
1123 m_fields->erase( m_fields->begin() + ii );
1124
1125 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, ii, 1 );
1126 m_grid->ProcessTableMessage( msg );
1127 }
1128 }
1129
1130 OnModify();
1131 m_grid->ForceRefresh();
1132}
1133
1134
1136{
1137 int idx = m_FootprintFilterListBox->HitTest( event.GetPosition() );
1138 wxCommandEvent dummy;
1139
1140 if( idx >= 0 )
1142 else
1144}
1145
1146
1148{
1149 // Running the Footprint Browser gums up the works and causes the automatic cancel
1150 // stuff to no longer work. So we do it here ourselves.
1151 EndDialogShim( wxID_CANCEL );
1152}
1153
1154
1156{
1157 wxString filterLine;
1158 WX_TEXT_ENTRY_DIALOG dlg( this, _( "Filter:" ), _( "Add Footprint Filter" ), filterLine );
1159
1160 if( dlg.ShowModal() == wxID_CANCEL || dlg.GetValue().IsEmpty() )
1161 return;
1162
1163 filterLine = dlg.GetValue();
1164 filterLine.Replace( wxT( " " ), wxT( "_" ) );
1165
1166 // duplicate filters do no harm, so don't be a nanny.
1167 m_FootprintFilterListBox->Append( filterLine );
1168 m_FootprintFilterListBox->SetSelection( (int) m_FootprintFilterListBox->GetCount() - 1 );
1169
1170 OnModify();
1171}
1172
1173
1175{
1176 wxArrayInt selections;
1177 int n = m_FootprintFilterListBox->GetSelections( selections );
1178
1179 if( n > 0 )
1180 {
1181 // Just edit the first one
1182 int idx = selections[0];
1183 wxString filter = m_FootprintFilterListBox->GetString( idx );
1184
1185 WX_TEXT_ENTRY_DIALOG dlg( this, _( "Filter:" ), _( "Edit Footprint Filter" ), filter );
1186
1187 if( dlg.ShowModal() == wxID_OK && !dlg.GetValue().IsEmpty() )
1188 {
1189 m_FootprintFilterListBox->SetString( (unsigned) idx, dlg.GetValue() );
1190 OnModify();
1191 }
1192 }
1193}
1194
1195
1196void DIALOG_LIB_SYMBOL_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
1197{
1198 m_OptionPartsInterchangeable->Enable( m_unitSpinCtrl->GetValue() > 1 );
1199 m_pinNameOffset.Enable( m_PinsNameInsideButt->GetValue() );
1200
1201 if( m_grid->IsCellEditControlShown() )
1202 {
1203 int row = m_grid->GetGridCursorRow();
1204 int col = m_grid->GetGridCursorCol();
1205
1206 if( row == m_fields->GetFieldRow( FIELD_T::VALUE ) && col == FDC_VALUE && m_OptionPower->IsChecked() )
1207 {
1208 wxGridCellEditor* editor = m_grid->GetCellEditor( row, col );
1209 m_SymbolNameCtrl->ChangeValue( editor->GetValue() );
1210 editor->DecRef();
1211 }
1212 }
1213
1214 // Handle shown columns changes
1215 std::bitset<64> shownColumns = m_grid->GetShownColumns();
1216
1217 if( shownColumns != m_shownColumns )
1218 {
1219 m_shownColumns = shownColumns;
1220
1221 if( !m_grid->IsCellEditControlShown() )
1222 m_grid->SetGridWidthsDirty();
1223 }
1224
1225 // Handle a delayed focus. The delay allows us to:
1226 // a) change focus when the error was triggered from within a killFocus handler
1227 // b) show the correct notebook page in the background before the error dialog comes up
1228 // when triggered from an OK or a notebook page change
1229
1230 if( m_delayedFocusPage >= 0 && m_NoteBook->GetSelection() != m_delayedFocusPage )
1231 {
1232 m_NoteBook->ChangeSelection( (unsigned) m_delayedFocusPage );
1233 m_delayedFocusPage = -1;
1234 }
1235
1236 if( !m_delayedErrorMessage.IsEmpty() )
1237 {
1238 // We will re-enter this routine when the error dialog is displayed, so make
1239 // sure we don't keep putting up more dialogs.
1240 wxString msg = m_delayedErrorMessage;
1241 m_delayedErrorMessage = wxEmptyString;
1242
1243 // Do not use DisplayErrorMessage(); it screws up window order on Mac
1244 DisplayError( nullptr, msg );
1245 }
1246
1247 if( m_delayedFocusCtrl )
1248 {
1249 m_delayedFocusCtrl->SetFocus();
1250
1251 if( wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_delayedFocusCtrl ) )
1252 textEntry->SelectAll();
1253
1254 m_delayedFocusCtrl = nullptr;
1255 }
1256 else if( m_delayedFocusGrid )
1257 {
1258 m_delayedFocusGrid->SetFocus();
1261
1262 m_delayedFocusGrid->EnableCellEditControl( true );
1263 m_delayedFocusGrid->ShowCellEditControl();
1264
1265 m_delayedFocusGrid = nullptr;
1266 m_delayedFocusRow = -1;
1268 }
1269}
1270
1271
1273{
1274 bSizerLowerBasicPanel->Show( !aIsAlias );
1275 m_inheritanceSelectCombo->Enable( aIsAlias );
1276 m_inheritsStaticText->Enable( aIsAlias );
1277 m_grid->ForceRefresh();
1278}
1279
1280
1282{
1283 if( m_OptionPower->IsChecked() )
1284 {
1285 m_excludeFromSimCheckBox->SetValue( true );
1286 m_excludeFromBomCheckBox->SetValue( true );
1287 m_excludeFromBoardCheckBox->SetValue( true );
1288 m_excludeFromPosFilesCheckBox->SetValue( true );
1289 m_excludeFromBomCheckBox->Enable( false );
1290 m_excludeFromBoardCheckBox->Enable( false );
1291 m_excludeFromSimCheckBox->Enable( false );
1292 m_excludeFromPosFilesCheckBox->Enable( false );
1293 m_spiceFieldsButton->Show( false );
1294 m_OptionLocalPower->Enable( true );
1295 }
1296 else
1297 {
1298 m_excludeFromBomCheckBox->Enable( true );
1299 m_excludeFromBoardCheckBox->Enable( true );
1300 m_excludeFromSimCheckBox->Enable( true );
1301 m_excludeFromPosFilesCheckBox->Enable( true );
1302 m_spiceFieldsButton->Show( true );
1303 m_OptionLocalPower->Enable( false );
1304 }
1305
1306 OnModify();
1307}
1308
1309
1310void DIALOG_LIB_SYMBOL_PROPERTIES::OnText( wxCommandEvent& event )
1311{
1312 OnModify();
1313}
1314
1315
1316void DIALOG_LIB_SYMBOL_PROPERTIES::OnCombobox( wxCommandEvent& event )
1317{
1318 OnModify();
1319}
1320
1321
1322void DIALOG_LIB_SYMBOL_PROPERTIES::OnCheckBox( wxCommandEvent& event )
1323{
1324 OnModify();
1325}
1326
1327
1329{
1330 m_unitNamesGrid->CommitPendingChanges( true /* aQuietMode */ );
1331
1332 int extra = m_unitNamesGrid->GetNumberRows() - m_unitSpinCtrl->GetValue();
1333 int needed = m_unitSpinCtrl->GetValue() - m_unitNamesGrid->GetNumberRows();
1334
1335 if( extra > 0 )
1336 {
1337 m_unitNamesGrid->DeleteRows( m_unitNamesGrid->GetNumberRows() - extra, extra );
1338 return true;
1339 }
1340
1341 if( needed > 0 )
1342 {
1343 m_unitNamesGrid->AppendRows( needed );
1344
1345 for( int row = m_unitNamesGrid->GetNumberRows() - needed; row < m_unitNamesGrid->GetNumberRows(); ++row )
1346 m_unitNamesGrid->SetCellValue( row, 0, LIB_SYMBOL::LetterSubReference( row + 1, 'A' ) );
1347
1348 return true;
1349 }
1350
1351 return false;
1352}
1353
1354
1356{
1357 if( updateUnitCount() )
1358 OnModify();
1359}
1360
1361
1363{
1364 // wait for kill focus to update unit count
1365}
1366
1367
1369{
1370 if( updateUnitCount() )
1371 OnModify();
1372}
1373
1374
1376{
1377 if( updateUnitCount() )
1378 OnModify();
1379}
1380
1381
1383{
1384 if( !m_grid->CommitPendingChanges() )
1385 aEvent.Veto();
1386}
1387
1388
1390{
1391 m_jumperGroupsGrid->OnAddRow(
1392 [&]() -> std::pair<int, int>
1393 {
1394 m_jumperGroupsGrid->AppendRows( 1 );
1395 OnModify();
1396
1397 return { m_jumperGroupsGrid->GetNumberRows() - 1, 0 };
1398 } );
1399}
1400
1401
1403{
1404 m_jumperGroupsGrid->OnDeleteRows(
1405 [&]( int row )
1406 {
1407 m_jumperGroupsGrid->DeleteRows( row, 1 );
1408 } );
1409
1410 OnModify();
1411}
1412
1413
const char * name
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:123
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:106
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:986
DIALOG_LIB_SYMBOL_PROPERTIES_BASE(wxWindow *parent, wxWindowID id=ID_LIBEDIT_NOTEBOOK, const wxString &title=_("Library Symbol Properties"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
void OnSymbolNameKillFocus(wxFocusEvent &event) override
void OnUnitSpinCtrlText(wxCommandEvent &event) override
std::unique_ptr< LISTBOX_TRICKS > m_fpFilterTricks
void OnPageChanging(wxNotebookEvent &event) override
void OnBodyStyle(wxCommandEvent &event) override
DIALOG_LIB_SYMBOL_PROPERTIES(SYMBOL_EDIT_FRAME *parent, LIB_SYMBOL *aLibEntry)
void OnUpdateUI(wxUpdateUIEvent &event) override
void OnBodyStyleMoveUp(wxCommandEvent &event) override
void OnCancelButtonClick(wxCommandEvent &event) override
void OnEditFootprintFilter(wxCommandEvent &event) override
void OnDeleteField(wxCommandEvent &event) override
void OnCombobox(wxCommandEvent &event) override
void OnFpFilterDClick(wxMouseEvent &event) override
void OnUnitSpinCtrlEnter(wxCommandEvent &event) override
void OnAddBodyStyle(wxCommandEvent &event) override
void OnMoveUp(wxCommandEvent &event) override
void OnDeleteBodyStyle(wxCommandEvent &event) override
void OnAddJumperGroup(wxCommandEvent &event) override
void OnText(wxCommandEvent &event) override
void OnUnitSpinCtrlKillFocus(wxFocusEvent &event) override
void OnMoveDown(wxCommandEvent &event) override
void SelectPinMapPage()
Switch the notebook to the Pin Map page (issue #2282).
bool m_forcePinMapPage
When set by SelectPinMapPage(), TransferDataToWindow opens the Pin Map page instead of the remembered...
void OnAddFootprintFilter(wxCommandEvent &event) override
void OnCheckBox(wxCommandEvent &event) override
void OnSymbolNameText(wxCommandEvent &event) override
void OnBodyStyleMoveDown(wxCommandEvent &event) override
void OnRemoveJumperGroup(wxCommandEvent &event) override
void onPowerCheckBox(wxCommandEvent &aEvent) override
void OnAddField(wxCommandEvent &event) override
void OnEditSpiceModel(wxCommandEvent &event) override
void addInheritedFields(const std::shared_ptr< LIB_SYMBOL > &aParent)
void OnUnitSpinCtrl(wxSpinEvent &event) override
void EndDialogShim(int aReturnCode)
A mode agnostic way to close a dialog.
EDA_BASE_FRAME * m_parentFrame
int ShowModal() override
virtual void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition eda_text.cpp:532
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:381
void push_back(const SCH_FIELD &field)
A text control validator used for validating the text allowed in fields.
Definition validators.h:138
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition grid_tricks.h:57
Define a library symbol object.
Definition lib_symbol.h:114
static wxString LetterSubReference(int aUnit, wxChar aInitialLetter)
Composed widget that edits a symbol's named pin maps and the footprint each is bound to.
void SetOrdinal(int aOrdinal)
Definition sch_field.h:138
bool IsMandatory() const
bool HasSameContent(const SCH_FIELD &aOther) const
Test if this field has the same name, content and presentation as another field, ignoring the owning ...
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:128
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
void SetName(const wxString &aName)
The symbol library editor main window.
void AddTemplateFieldNames(const wxString &aSerializedFieldNames)
Add a serialized list of template field names.
const std::vector< TEMPLATE_FIELDNAME > & GetTemplateFieldNames()
Return a template field name list for read only access.
A KICAD version of wxTextEntryDialog which supports the various improvements/work-arounds from DIALOG...
wxString GetValue() const
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:274
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:217
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:192
This file is part of the common library.
#define _(s)
@ FDC_NAME
@ FDC_VALUE
wxString GetRefDesPrefix(const wxString &aRefDes)
Get the (non-numeric) prefix from a refdes - e.g.
STL namespace.
see class PGM_BASE
Collection of utility functions for component reference designators (refdes)
T * GetAppSettings(const char *aFilename)
std::vector< FAB_LAYER_COLOR > dummy
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.
wxString UnescapeString(const wxString &aSource)
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
@ CTX_LIBID
Hold a name of a symbol's field, field value, and default visibility.
bool FieldNamesAreDuplicates(const wxString &aLhs, const wxString &aRhs, std::initializer_list< FIELD_T > aMandatoryFields)
Test whether two field names should be treated as duplicates for the purposes of field name uniquenes...
wxString GetUserFieldName(int aFieldNdx, bool aTranslateForHI)
#define DO_TRANSLATE
@ USER
The field ID hasn't been set yet; field is invalid.
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
KIBIS_PIN * pin
UNDO_REDO
Undo Redo considerations: Basically we have 3 cases New item Deleted item Modified item there is also...
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683