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