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, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
25
26#include <pgm_base.h>
27#include <eeschema_settings.h>
28#include <bitmaps.h>
29#include <confirm.h>
31#include <kiway.h>
32#include <symbol_edit_frame.h>
34#include <math/util.h> // for KiROUND
35#include <sch_symbol.h>
36#include <kiplatform/ui.h>
38#include <widgets/wx_grid.h>
40#include <string_utils.h>
41#include <project_sch.h>
42#include <refdes_utils.h>
43#include <dialog_sim_model.h>
44#include <vector>
45
50
51#include <wx/clipbrd.h>
52#include <wx/msgdlg.h>
53
54
58
59
61 LIB_SYMBOL* aLibEntry ) :
63 m_Parent( aParent ),
64 m_libEntry( aLibEntry ),
66 m_delayedFocusCtrl( nullptr ),
67 m_delayedFocusGrid( nullptr ),
72{
73 std::vector<const EMBEDDED_FILES*> inheritedEmbeddedFiles;
74
75 if( std::shared_ptr<LIB_SYMBOL> parent = m_libEntry->GetParent().lock() )
76 {
77 while( parent )
78 {
79 inheritedEmbeddedFiles.push_back( parent->GetEmbeddedFiles() );
80 parent = parent->GetParent().lock();
81 }
82 }
83
84 m_embeddedFiles = new PANEL_EMBEDDED_FILES( m_NoteBook, m_libEntry, 0,
85 std::move( inheritedEmbeddedFiles ) );
86 m_NoteBook->AddPage( m_embeddedFiles, _( "Embedded Files" ) );
87
88 m_fields = new FIELDS_GRID_TABLE( this, aParent, m_grid, m_libEntry,
89 { m_embeddedFiles->GetLocalFiles() } );
90 m_grid->SetTable( m_fields );
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 m_lastOpenedPage = m_NoteBook->GetSelection( );
202
203 // Prevents crash bug in wxGrid's d'tor
204 m_grid->DestroyTable( m_fields );
205
206 m_grid->Unbind( wxEVT_GRID_CELL_CHANGING, &DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanging, this );
207 m_grid->Unbind( wxEVT_GRID_CELL_CHANGED, &DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanged, this );
208 m_grid->GetGridWindow()->Unbind( wxEVT_MOTION, &DIALOG_LIB_SYMBOL_PROPERTIES::OnGridMotion, this );
209
210 // Delete the GRID_TRICKS.
211 m_grid->PopEventHandler( true );
212 m_unitNamesGrid->PopEventHandler( true );
213 m_bodyStyleNamesGrid->PopEventHandler( true );
214 m_jumperGroupsGrid->PopEventHandler( true );
215}
216
217
218void DIALOG_LIB_SYMBOL_PROPERTIES::addInheritedFields( const std::shared_ptr<LIB_SYMBOL>& aParent )
219{
220 if( std::shared_ptr<LIB_SYMBOL> ancestor = aParent->GetParent().lock() )
221 addInheritedFields( ancestor );
222
223 std::vector<SCH_FIELD*> parentFields;
224 aParent->GetFields( parentFields );
225
226 for( SCH_FIELD* parentField : parentFields )
227 {
228 bool found = false;
229
230 if( parentField->IsMandatory() )
231 continue; // Don't inherit mandatory fields
232
233 for( size_t ii = 0; ii < m_fields->size(); ++ii )
234 {
235 SCH_FIELD& field = m_fields->at( ii );
236
237 if( field.IsMandatory() )
238 continue; // Don't inherit mandatory fields
239
240 if( field.GetCanonicalName() == parentField->GetCanonicalName() )
241 {
242 m_fields->SetFieldInherited( ii, *parentField );
243 found = true;
244 break;
245 }
246 }
247
248 if( !found )
249 m_fields->AddInheritedField( *parentField );
250 }
251}
252
253
255{
256 if( !wxDialog::TransferDataToWindow() )
257 return false;
258
259 std::set<wxString> defined;
260
261 for( SCH_FIELD& field : *m_fields )
262 defined.insert( field.GetName() );
263
264 // Add in any template fieldnames not yet defined:
265 // Read global fieldname templates
267 {
268 TEMPLATES templateMgr;
269
270 if( !cfg->m_Drawing.field_names.IsEmpty() )
271 templateMgr.AddTemplateFieldNames( cfg->m_Drawing.field_names );
272
273 for( const TEMPLATE_FIELDNAME& templateFieldname : templateMgr.GetTemplateFieldNames() )
274 {
275 if( defined.count( templateFieldname.m_Name ) <= 0 )
276 {
277 SCH_FIELD field( m_libEntry, FIELD_T::USER, templateFieldname.m_Name );
278 field.SetVisible( templateFieldname.m_Visible );
279 m_fields->push_back( field );
280 m_addedTemplateFields.insert( templateFieldname.m_Name );
281 }
282 }
283 }
284
285 // The Y axis for components in library file is from bottom to top while the screen axis is top
286 // to bottom.However it is nowhandled by the lib file parser/writer.
287
288 // notify the grid
289 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_fields->GetNumberRows() );
290 m_grid->ProcessTableMessage( msg );
291
292 m_SymbolNameCtrl->ChangeValue( UnescapeString( m_libEntry->GetName() ) );
293
294 m_KeywordCtrl->ChangeValue( m_libEntry->GetKeyWords() );
295 m_unitSpinCtrl->SetValue( m_libEntry->GetUnitCount() );
296 m_OptionPartsInterchangeable->SetValue( !m_libEntry->UnitsLocked() || m_libEntry->GetUnitCount() == 1 );
297
299
300 for( int unit = 0; unit < m_libEntry->GetUnitCount(); unit++ )
301 {
302 if( m_libEntry->GetUnitDisplayNames().contains( unit + 1 ) )
303 m_unitNamesGrid->SetCellValue( unit, 1, m_libEntry->GetUnitDisplayNames().at( unit + 1 ) );
304 }
305
306 if( m_libEntry->HasDeMorganBodyStyles() )
307 {
308 m_radioDeMorgan->SetValue( true );
309 }
310 else if( m_libEntry->IsMultiBodyStyle() )
311 {
312 m_radioCustom->SetValue( true );
313
314 for( const wxString& name : m_libEntry->GetBodyStyleNames() )
315 {
316 int row = m_bodyStyleNamesGrid->GetNumberRows();
317 m_bodyStyleNamesGrid->AppendRows( 1 );
318 m_bodyStyleNamesGrid->SetCellValue( row, 0, name );
319 }
320 }
321 else
322 {
323 m_radioSingle->SetValue( true );
324 }
325
326 m_OptionPower->SetValue( m_libEntry->IsPower() );
327 m_OptionLocalPower->SetValue( m_libEntry->IsLocalPower() );
328
329 if( m_libEntry->IsPower() )
330 {
331 m_spiceFieldsButton->Hide();
332 m_OptionLocalPower->Enable();
333 }
334 else
335 {
336 m_OptionLocalPower->Enable( false );
337 }
338
339 m_excludeFromSimCheckBox->SetValue( m_libEntry->GetExcludedFromSim() );
340 m_excludeFromBomCheckBox->SetValue( m_libEntry->GetExcludedFromBOM() );
341 m_excludeFromBoardCheckBox->SetValue( m_libEntry->GetExcludedFromBoard() );
342 m_excludeFromPosFilesCheckBox->SetValue( m_libEntry->GetExcludedFromPosFiles() );
343
344 m_ShowPinNumButt->SetValue( m_libEntry->GetShowPinNumbers() );
345 m_ShowPinNameButt->SetValue( m_libEntry->GetShowPinNames() );
346 m_PinsNameInsideButt->SetValue( m_libEntry->GetPinNameOffset() != 0 );
347 m_pinNameOffset.ChangeValue( m_libEntry->GetPinNameOffset() );
348
349 wxArrayString tmp = m_libEntry->GetFPFilters();
350 m_FootprintFilterListBox->Append( tmp );
351
352 m_cbDuplicatePinsAreJumpers->SetValue( m_libEntry->GetDuplicatePinNumbersAreJumpers() );
353
354 std::set<wxString> availablePins;
355
356 for( const SCH_PIN* pin : m_libEntry->GetPins() )
357 availablePins.insert( pin->GetNumber() );
358
359 for( const std::set<wxString>& group : m_libEntry->JumperPinGroups() )
360 {
361 wxString groupTxt;
362
363 for( const wxString& pinNumber : group )
364 {
365 if( !groupTxt.IsEmpty() )
366 groupTxt << ", ";
367
368 groupTxt << pinNumber;
369 }
370
371 m_jumperGroupsGrid->AppendRows( 1 );
372 m_jumperGroupsGrid->SetCellValue( m_jumperGroupsGrid->GetNumberRows() - 1, 0, groupTxt );
373 }
374
375 // Populate the list of root parts for inherited objects.
376 if( m_libEntry->IsDerived() )
377 {
378 wxArrayString symbolNames;
379 wxString libName = m_Parent->GetCurLib();
380
381 // Someone forgot to set the current library in the editor frame window.
382 wxCHECK( !libName.empty(), false );
383
384 m_Parent->GetLibManager().GetSymbolNames( libName, symbolNames );
385
386 // Sort the list of symbols for easier search
387 symbolNames.Sort(
388 []( const wxString& a, const wxString& b ) -> int
389 {
390 return StrNumCmp( a, b, true );
391 } );
392
393 // Don't allow a symbol to be derived from itself
394 if( symbolNames.Index( m_libEntry->GetName() ) != wxNOT_FOUND )
395 symbolNames.Remove( m_libEntry->GetName() );
396
397 // Don't allow a symbol to be derived from any of its descendants (would create
398 // circular inheritance)
399 wxArrayString descendants;
400 m_Parent->GetLibManager().GetDerivedSymbolNames( m_libEntry->GetName(), libName,
401 descendants );
402
403 for( const wxString& descendant : descendants )
404 {
405 if( symbolNames.Index( descendant ) != wxNOT_FOUND )
406 symbolNames.Remove( descendant );
407 }
408
409 m_inheritanceSelectCombo->Append( symbolNames );
410
411 if( std::shared_ptr<LIB_SYMBOL> rootSymbol = m_libEntry->GetParent().lock() )
412 {
413 wxString parentName = UnescapeString( rootSymbol->GetName() );
414 int selection = m_inheritanceSelectCombo->FindString( parentName );
415
416 if( selection == wxNOT_FOUND )
417 return false;
418
419 m_inheritanceSelectCombo->SetSelection( selection );
420 }
421
423 }
424
425 m_NoteBook->SetSelection( (unsigned) m_lastOpenedPage );
426
427 m_embeddedFiles->TransferDataToWindow();
428
429 return true;
430}
431
432
434{
435 if( !m_grid->CommitPendingChanges() )
436 return false;
437
438 // Symbol reference can be empty because it inherits from the parent symbol.
439 if( m_libEntry->IsRoot() )
440 {
441 SCH_FIELD* field = m_fields->GetField( FIELD_T::REFERENCE );
442
443 if( UTIL::GetRefDesPrefix( field->GetText() ).IsEmpty() )
444 {
445 if( m_NoteBook->GetSelection() != 0 )
446 m_NoteBook->SetSelection( 0 );
447
448 m_delayedErrorMessage = _( "References must start with a letter." );
453
454 return false;
455 }
456 }
457
458 // Check for missing field names.
459 for( int ii = 0; ii < (int) m_fields->size(); ++ii )
460 {
461 SCH_FIELD& field = m_fields->at( ii );
462
463 if( field.IsMandatory() )
464 continue;
465
466 wxString fieldName = field.GetName( false );
467
468 if( fieldName.IsEmpty() && !field.GetText().IsEmpty() )
469 {
470 if( m_NoteBook->GetSelection() != 0 )
471 m_NoteBook->SetSelection( 0 );
472
473 m_delayedErrorMessage = _( "Fields must have a name." );
478
479 return false;
480 }
481 }
482
483 // Verify that the parent name is set if the symbol is inherited
484 if( m_libEntry->IsDerived() )
485 {
486 wxString parentName = m_inheritanceSelectCombo->GetValue();
487
488 if( parentName.IsEmpty() )
489 {
490 m_delayedErrorMessage = _( "Derived symbol must have a parent selected" );
491 return false;
492 }
493 }
494
495 /*
496 * Confirm destructive actions.
497 */
498
499 if( m_unitSpinCtrl->GetValue() < m_libEntry->GetUnitCount() )
500 {
501 if( !IsOK( this, _( "Delete extra units from symbol?" ) ) )
502 return false;
503 }
504
505 int bodyStyleCount = 0;
506
507 if( m_radioSingle->GetValue() )
508 {
509 bodyStyleCount = 1;
510 }
511 if( m_radioDeMorgan->GetValue() )
512 {
513 bodyStyleCount = 2;
514 }
515 else if( m_radioCustom->GetValue() )
516 {
517 for( int ii = 0; ii < m_bodyStyleNamesGrid->GetNumberRows(); ++ii )
518 {
519 if( !m_bodyStyleNamesGrid->GetCellValue( ii, 0 ).IsEmpty() )
520 bodyStyleCount++;
521 }
522 }
523
524 if( bodyStyleCount == 0 )
525 {
526 m_delayedErrorMessage = _( "Symbol must have at least 1 body style" );
527 return false;
528 }
529
530 if( bodyStyleCount < m_libEntry->GetBodyStyleCount() )
531 {
532 if( !IsOK( this, _( "Delete extra body styles from symbol?" ) ) )
533 return false;
534 }
535
536 return true;
537}
538
539
541{
542 if( !m_grid->CommitPendingChanges()
543 || !m_unitNamesGrid->CommitPendingChanges()
544 || !m_bodyStyleNamesGrid->CommitPendingChanges()
545 || !m_jumperGroupsGrid->CommitPendingChanges()
546 || !m_embeddedFiles->TransferDataFromWindow() )
547 {
548 return false;
549 }
550
551 wxString newName = EscapeString( m_SymbolNameCtrl->GetValue(), CTX_LIBID );
552 wxString oldName = m_libEntry->GetName();
553
554 if( newName.IsEmpty() )
555 {
556 wxMessageBox( _( "Symbol must have a name." ) );
557 return false;
558 }
559
561
562 if( oldName != newName )
563 {
564 wxString libName = m_Parent->GetCurLib();
565
566 if( m_Parent->GetLibManager().SymbolNameInUse( newName, libName ) )
567 {
568 wxString msg;
569
570 msg.Printf( _( "Symbol name '%s' already in use in library '%s'." ),
571 UnescapeString( newName ),
572 libName );
573 DisplayErrorMessage( this, msg );
574 return false;
575 }
576
577 opType = UNDO_REDO::LIB_RENAME;
578 }
579
580 m_Parent->SaveCopyInUndoList( _( "Edit Symbol Properties" ), m_libEntry, opType );
581
582 // The Y axis for components in lib is from bottom to top while the screen axis is top
583 // to bottom: we must change the y coord sign when writing back to the library
584 std::vector<SCH_FIELD> fieldsToSave;
585 int ordinal = 42; // Arbitrarily larger than any mandatory FIELD_T ids.
586
587 for( size_t ii = 0; ii < m_fields->size(); ++ii )
588 {
589 SCH_FIELD& field = m_fields->at( ii );
590
591 if( !field.IsMandatory() )
592 field.SetOrdinal( ordinal++ );
593
594 wxString fieldName = field.GetCanonicalName();
595
596 if( m_fields->IsInherited( ii ) && field == m_fields->ParentField( ii ) )
597 continue; // Skip inherited fields
598
599 if( field.GetText().IsEmpty() )
600 {
601 if( fieldName.IsEmpty() || m_addedTemplateFields.contains( fieldName ) )
602 continue; // Skip empty fields that are not mandatory or template fields
603 }
604 else if( fieldName.IsEmpty() )
605 {
606 field.SetName( _( "untitled" ) ); // Set a default name for unnamed fields
607 }
608
609 fieldsToSave.push_back( field );
610 }
611
612 m_libEntry->SetFields( fieldsToSave );
613
614 // Update the parent for inherited symbols
615 if( m_libEntry->IsDerived() )
616 {
617 wxString parentName = EscapeString( m_inheritanceSelectCombo->GetValue(), CTX_LIBID );
618
619 // The parentName was verified to be non-empty in the Validator
620 wxString libName = m_Parent->GetCurLib();
621
622 // Get the parent from the libManager based on the name set in the inheritance combo box.
623 LIB_SYMBOL* newParent = m_Parent->GetLibManager().GetSymbol( parentName, libName );
624
625 // Verify that the requested parent exists
626 wxCHECK( newParent, false );
627
628 m_libEntry->SetParent( newParent );
629 }
630
631 m_libEntry->SetName( newName );
632 m_libEntry->SetKeyWords( m_KeywordCtrl->GetValue() );
633 m_libEntry->SetUnitCount( m_unitSpinCtrl->GetValue(), true );
634 m_libEntry->LockUnits( m_libEntry->GetUnitCount() > 1 && !m_OptionPartsInterchangeable->GetValue() );
635
636 m_libEntry->GetUnitDisplayNames().clear();
637
638 for( int row = 0; row < m_unitNamesGrid->GetNumberRows(); row++ )
639 {
640 if( !m_unitNamesGrid->GetCellValue( row, 1 ).IsEmpty() )
641 m_libEntry->GetUnitDisplayNames()[row+1] = m_unitNamesGrid->GetCellValue( row, 1 );
642 }
643
644 if( m_radioSingle->GetValue() )
645 {
646 m_libEntry->SetHasDeMorganBodyStyles( false );
647 m_libEntry->SetBodyStyleCount( 1, false, false );
648 m_libEntry->SetBodyStyleNames( {} );
649 }
650 else if( m_radioDeMorgan->GetValue() )
651 {
652 m_libEntry->SetHasDeMorganBodyStyles( true );
653 m_libEntry->SetBodyStyleCount( 2, false, true );
654 m_libEntry->SetBodyStyleNames( {} );
655 }
656 else
657 {
658 std::vector<wxString> bodyStyleNames;
659
660 for( int row = 0; row < m_bodyStyleNamesGrid->GetNumberRows(); ++row )
661 {
662 if( !m_bodyStyleNamesGrid->GetCellValue( row, 0 ).IsEmpty() )
663 bodyStyleNames.push_back( m_bodyStyleNamesGrid->GetCellValue( row, 0 ) );
664 }
665
666 m_libEntry->SetHasDeMorganBodyStyles( false );
667 m_libEntry->SetBodyStyleCount( bodyStyleNames.size(), true, true );
668 m_libEntry->SetBodyStyleNames( bodyStyleNames );
669 }
670
671 if( m_OptionPower->GetValue() )
672 {
673 if( m_OptionLocalPower->GetValue() )
674 m_libEntry->SetLocalPower();
675 else
676 m_libEntry->SetGlobalPower();
677
678 // Power symbols must have value matching name for now
679 m_libEntry->GetValueField().SetText( newName );
680 }
681 else
682 {
683 m_libEntry->SetNormal();
684 }
685
686 m_libEntry->SetExcludedFromSim( m_excludeFromSimCheckBox->GetValue() );
687 m_libEntry->SetExcludedFromBOM( m_excludeFromBomCheckBox->GetValue() );
688 m_libEntry->SetExcludedFromBoard( m_excludeFromBoardCheckBox->GetValue() );
689 m_libEntry->SetExcludedFromPosFiles( m_excludeFromPosFilesCheckBox->GetValue() );
690
691 m_libEntry->SetShowPinNumbers( m_ShowPinNumButt->GetValue() );
692 m_libEntry->SetShowPinNames( m_ShowPinNameButt->GetValue() );
693
694 if( m_PinsNameInsideButt->GetValue() )
695 {
696 int offset = KiROUND( (double) m_pinNameOffset.GetValue() );
697
698 // We interpret an offset of 0 as "outside", so make sure it's non-zero
699 m_libEntry->SetPinNameOffset( offset == 0 ? 20 : offset );
700 }
701 else
702 {
703 m_libEntry->SetPinNameOffset( 0 ); // pin text outside the body (name is on the pin)
704 }
705
706 m_libEntry->SetFPFilters( m_FootprintFilterListBox->GetStrings());
707
708 m_libEntry->SetDuplicatePinNumbersAreJumpers( m_cbDuplicatePinsAreJumpers->GetValue() );
709
710 std::vector<std::set<wxString>>& jumpers = m_libEntry->JumperPinGroups();
711 jumpers.clear();
712
713 for( int ii = 0; ii < m_jumperGroupsGrid->GetNumberRows(); ++ii )
714 {
715 wxStringTokenizer tokenizer( m_jumperGroupsGrid->GetCellValue( ii, 0 ), ", \t\r\n", wxTOKEN_STRTOK );
716 std::set<wxString>& group = jumpers.emplace_back();
717
718 while( tokenizer.HasMoreTokens() )
719 {
720 if( wxString token = tokenizer.GetNextToken(); !token.IsEmpty() )
721 group.insert( token );
722 }
723 }
724
725 m_Parent->UpdateAfterSymbolProperties( &oldName );
726
727 return true;
728}
729
730
731void DIALOG_LIB_SYMBOL_PROPERTIES::OnBodyStyle( wxCommandEvent& event )
732{
733 m_bodyStyleNamesGrid->Enable( m_radioCustom->GetValue() );
734
735 m_bpAddBodyStyle->Enable( m_radioCustom->GetValue() );
736 m_bpMoveUpBodyStyle->Enable( m_radioCustom->GetValue() );
737 m_bpMoveDownBodyStyle->Enable( m_radioCustom->GetValue() );
738 m_bpDeleteBodyStyle->Enable( m_radioCustom->GetValue() );
739}
740
741
743{
744 aEvent.Skip();
745
746 wxPoint pos = aEvent.GetPosition();
747 wxPoint unscolled_pos = m_grid->CalcUnscrolledPosition( pos );
748 int row = m_grid->YToRow( unscolled_pos.y );
749 int col = m_grid->XToCol( unscolled_pos.x );
750
751 if( row == wxNOT_FOUND || col == wxNOT_FOUND || !m_fields->IsInherited( row ) )
752 {
753 m_grid->SetToolTip( "" );
754 return;
755 }
756
757 m_grid->SetToolTip( wxString::Format( _( "This field is inherited from '%s'." ),
758 m_fields->ParentField( row ).GetName() ) );
759}
760
761
763{
764 wxGridCellEditor* editor = m_grid->GetCellEditor( event.GetRow(), event.GetCol() );
765 wxControl* control = editor->GetControl();
766
767 if( control && control->GetValidator() && !control->GetValidator()->Validate( control ) )
768 {
769 event.Veto();
770
772 m_delayedFocusRow = event.GetRow();
773 m_delayedFocusColumn = event.GetCol();
775 }
776 else if( event.GetCol() == FDC_NAME )
777 {
778 wxString newName = event.GetString();
779
780 for( int i = 0; i < m_grid->GetNumberRows(); ++i )
781 {
782 if( i == event.GetRow() )
783 continue;
784
785 if( newName.CmpNoCase( m_grid->GetCellValue( i, FDC_NAME ) ) == 0 )
786 {
787 DisplayError( this, wxString::Format( _( "The name '%s' is already in use." ), newName ) );
788 event.Veto();
789 m_delayedFocusRow = event.GetRow();
790 m_delayedFocusColumn = event.GetCol();
791 }
792 }
793 }
794
795 editor->DecRef();
796}
797
798
800{
801 m_grid->ForceRefresh();
802 OnModify();
803}
804
805
807{
808 if( m_OptionPower->IsChecked() )
809 m_grid->SetCellValue( m_fields->GetFieldRow( FIELD_T::VALUE ), FDC_VALUE, m_SymbolNameCtrl->GetValue() );
810
811 OnModify();
812}
813
814
816{
817 if( !m_delayedFocusCtrl )
818 {
819 // If the validation fails and we throw up a dialog then GTK will give us another
820 // KillFocus event and we end up in infinite recursion. So we use m_delayedFocusCtrl
821 // as a re-entrancy block and then clear it again if validation passes.
824
825 if( m_SymbolNameCtrl->GetValidator()->Validate( m_SymbolNameCtrl ) )
826 {
827 m_delayedFocusCtrl = nullptr;
829 }
830 }
831
832 event.Skip();
833}
834
835
836void DIALOG_LIB_SYMBOL_PROPERTIES::OnAddField( wxCommandEvent& event )
837{
838 m_grid->OnAddRow(
839 [&]() -> std::pair<int, int>
840 {
841 SYMBOL_EDITOR_SETTINGS* settings = m_Parent->GetSettings();
843
844 newField.SetTextSize( VECTOR2I( schIUScale.MilsToIU( settings->m_Defaults.text_size ),
845 schIUScale.MilsToIU( settings->m_Defaults.text_size ) ) );
846 newField.SetVisible( false );
847
848 m_fields->push_back( newField );
849
850 // notify the grid
851 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
852 m_grid->ProcessTableMessage( msg );
853 OnModify();
854
855 return { m_fields->size() - 1, FDC_NAME };
856 } );
857}
858
859
861{
862 m_grid->OnDeleteRows(
863 [&]( int row )
864 {
865 if( row < m_fields->GetMandatoryRowCount() )
866 {
867 DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
868 m_fields->GetMandatoryRowCount() ) );
869 return false;
870 }
871
872 return true;
873 },
874 [&]( int row )
875 {
876 if( !m_fields->EraseRow( row ) )
877 return;
878
879 // notify the grid
880 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 );
881 m_grid->ProcessTableMessage( msg );
882 } );
883
884 OnModify();
885}
886
887
888void DIALOG_LIB_SYMBOL_PROPERTIES::OnMoveUp( wxCommandEvent& event )
889{
890 m_grid->OnMoveRowUp(
891 [&]( int row )
892 {
893 return row > m_fields->GetMandatoryRowCount();
894 },
895 [&]( int row )
896 {
897 m_fields->SwapRows( row, row - 1 );
898 m_grid->ForceRefresh();
899 OnModify();
900 } );
901}
902
903
904void DIALOG_LIB_SYMBOL_PROPERTIES::OnMoveDown( wxCommandEvent& event )
905{
906 m_grid->OnMoveRowDown(
907 [&]( int row )
908 {
909 return row >= m_fields->GetMandatoryRowCount();
910 },
911 [&]( int row )
912 {
913 m_fields->SwapRows( row, row + 1 );
914 m_grid->ForceRefresh();
915 OnModify();
916 } );
917}
918
919
921{
922 m_bodyStyleNamesGrid->OnAddRow(
923 [&]() -> std::pair<int, int>
924 {
925 m_bodyStyleNamesGrid->AppendRows( 1 );
926 OnModify();
927
928 return { m_bodyStyleNamesGrid->GetNumberRows() - 1, 0 };
929 } );
930}
931
932
934{
935 m_bodyStyleNamesGrid->OnDeleteRows(
936 [&]( int row )
937 {
938 m_bodyStyleNamesGrid->DeleteRows( row );
939 } );
940
941 OnModify();
942}
943
944
946{
947 m_bodyStyleNamesGrid->OnMoveRowUp(
948 [&]( int row )
949 {
950 m_bodyStyleNamesGrid->SwapRows( row, row - 1 );
951 OnModify();
952 } );
953}
954
955
957{
958 m_bodyStyleNamesGrid->OnMoveRowDown(
959 [&]( int row )
960 {
961 m_bodyStyleNamesGrid->SwapRows( row, row + 1 );
962 OnModify();
963 } );
964}
965
966
968{
969 if( !m_grid->CommitPendingChanges() )
970 return;
971
972 m_grid->ClearSelection();
973
974 std::vector<SCH_FIELD> fields;
975
976 for( const SCH_FIELD& field : *m_fields )
977 fields.emplace_back( field );
978
979 DIALOG_SIM_MODEL dialog( this, m_parentFrame, *m_libEntry, fields );
980
981 if( dialog.ShowModal() != wxID_OK )
982 return;
983
984 // Add in any new fields
985 for( const SCH_FIELD& editedField : fields )
986 {
987 bool found = false;
988
989 for( SCH_FIELD& existingField : *m_fields )
990 {
991 if( existingField.GetName() == editedField.GetName() )
992 {
993 found = true;
994 existingField.SetText( editedField.GetText() );
995 break;
996 }
997 }
998
999 if( !found )
1000 {
1001 m_fields->emplace_back( editedField );
1002 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
1003 m_grid->ProcessTableMessage( msg );
1004 }
1005 }
1006
1007 // Remove any deleted fields
1008 for( int ii = (int) m_fields->size() - 1; ii >= 0; --ii )
1009 {
1010 SCH_FIELD& existingField = m_fields->at( ii );
1011 bool found = false;
1012
1013 for( SCH_FIELD& editedField : fields )
1014 {
1015 if( editedField.GetName() == existingField.GetName() )
1016 {
1017 found = true;
1018 break;
1019 }
1020 }
1021
1022 if( !found )
1023 {
1024 m_grid->ClearSelection();
1025 m_fields->erase( m_fields->begin() + ii );
1026
1027 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, ii, 1 );
1028 m_grid->ProcessTableMessage( msg );
1029 }
1030 }
1031
1032 OnModify();
1033 m_grid->ForceRefresh();
1034}
1035
1036
1038{
1039 int idx = m_FootprintFilterListBox->HitTest( event.GetPosition() );
1040 wxCommandEvent dummy;
1041
1042 if( idx >= 0 )
1044 else
1046}
1047
1048
1050{
1051 // Running the Footprint Browser gums up the works and causes the automatic cancel
1052 // stuff to no longer work. So we do it here ourselves.
1053 EndQuasiModal( wxID_CANCEL );
1054}
1055
1056
1058{
1059 wxString filterLine;
1060 WX_TEXT_ENTRY_DIALOG dlg( this, _( "Filter:" ), _( "Add Footprint Filter" ), filterLine );
1061
1062 if( dlg.ShowModal() == wxID_CANCEL || dlg.GetValue().IsEmpty() )
1063 return;
1064
1065 filterLine = dlg.GetValue();
1066 filterLine.Replace( wxT( " " ), wxT( "_" ) );
1067
1068 // duplicate filters do no harm, so don't be a nanny.
1069 m_FootprintFilterListBox->Append( filterLine );
1070 m_FootprintFilterListBox->SetSelection( (int) m_FootprintFilterListBox->GetCount() - 1 );
1071
1072 OnModify();
1073}
1074
1075
1077{
1078 wxArrayInt selections;
1079 int n = m_FootprintFilterListBox->GetSelections( selections );
1080
1081 if( n > 0 )
1082 {
1083 // Just edit the first one
1084 int idx = selections[0];
1085 wxString filter = m_FootprintFilterListBox->GetString( idx );
1086
1087 WX_TEXT_ENTRY_DIALOG dlg( this, _( "Filter:" ), _( "Edit Footprint Filter" ), filter );
1088
1089 if( dlg.ShowModal() == wxID_OK && !dlg.GetValue().IsEmpty() )
1090 {
1091 m_FootprintFilterListBox->SetString( (unsigned) idx, dlg.GetValue() );
1092 OnModify();
1093 }
1094 }
1095}
1096
1097
1098void DIALOG_LIB_SYMBOL_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
1099{
1100 m_OptionPartsInterchangeable->Enable( m_unitSpinCtrl->GetValue() > 1 );
1101 m_pinNameOffset.Enable( m_PinsNameInsideButt->GetValue() );
1102
1103 if( m_grid->IsCellEditControlShown() )
1104 {
1105 int row = m_grid->GetGridCursorRow();
1106 int col = m_grid->GetGridCursorCol();
1107
1108 if( row == m_fields->GetFieldRow( FIELD_T::VALUE ) && col == FDC_VALUE && m_OptionPower->IsChecked() )
1109 {
1110 wxGridCellEditor* editor = m_grid->GetCellEditor( row, col );
1111 m_SymbolNameCtrl->ChangeValue( editor->GetValue() );
1112 editor->DecRef();
1113 }
1114 }
1115
1116 // Handle shown columns changes
1117 std::bitset<64> shownColumns = m_grid->GetShownColumns();
1118
1119 if( shownColumns != m_shownColumns )
1120 {
1121 m_shownColumns = shownColumns;
1122
1123 if( !m_grid->IsCellEditControlShown() )
1124 m_grid->SetGridWidthsDirty();
1125 }
1126
1127 // Handle a delayed focus. The delay allows us to:
1128 // a) change focus when the error was triggered from within a killFocus handler
1129 // b) show the correct notebook page in the background before the error dialog comes up
1130 // when triggered from an OK or a notebook page change
1131
1132 if( m_delayedFocusPage >= 0 && m_NoteBook->GetSelection() != m_delayedFocusPage )
1133 {
1134 m_NoteBook->ChangeSelection( (unsigned) m_delayedFocusPage );
1135 m_delayedFocusPage = -1;
1136 }
1137
1138 if( !m_delayedErrorMessage.IsEmpty() )
1139 {
1140 // We will re-enter this routine when the error dialog is displayed, so make
1141 // sure we don't keep putting up more dialogs.
1142 wxString msg = m_delayedErrorMessage;
1143 m_delayedErrorMessage = wxEmptyString;
1144
1145 // Do not use DisplayErrorMessage(); it screws up window order on Mac
1146 DisplayError( nullptr, msg );
1147 }
1148
1149 if( m_delayedFocusCtrl )
1150 {
1151 m_delayedFocusCtrl->SetFocus();
1152
1153 if( wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_delayedFocusCtrl ) )
1154 textEntry->SelectAll();
1155
1156 m_delayedFocusCtrl = nullptr;
1157 }
1158 else if( m_delayedFocusGrid )
1159 {
1160 m_delayedFocusGrid->SetFocus();
1163
1164 m_delayedFocusGrid->EnableCellEditControl( true );
1165 m_delayedFocusGrid->ShowCellEditControl();
1166
1167 m_delayedFocusGrid = nullptr;
1168 m_delayedFocusRow = -1;
1170 }
1171}
1172
1173
1175{
1176 bSizerLowerBasicPanel->Show( !aIsAlias );
1177 m_inheritanceSelectCombo->Enable( aIsAlias );
1178 m_inheritsStaticText->Enable( aIsAlias );
1179 m_grid->ForceRefresh();
1180}
1181
1182
1184{
1185 if( m_OptionPower->IsChecked() )
1186 {
1187 m_excludeFromSimCheckBox->SetValue( true );
1188 m_excludeFromBomCheckBox->SetValue( true );
1189 m_excludeFromBoardCheckBox->SetValue( true );
1190 m_excludeFromPosFilesCheckBox->SetValue( true );
1191 m_excludeFromBomCheckBox->Enable( false );
1192 m_excludeFromBoardCheckBox->Enable( false );
1193 m_excludeFromSimCheckBox->Enable( false );
1194 m_excludeFromPosFilesCheckBox->Enable( false );
1195 m_spiceFieldsButton->Show( false );
1196 m_OptionLocalPower->Enable( true );
1197 }
1198 else
1199 {
1200 m_excludeFromBomCheckBox->Enable( true );
1201 m_excludeFromBoardCheckBox->Enable( true );
1202 m_excludeFromSimCheckBox->Enable( true );
1203 m_excludeFromPosFilesCheckBox->Enable( true );
1204 m_spiceFieldsButton->Show( true );
1205 m_OptionLocalPower->Enable( false );
1206 }
1207
1208 OnModify();
1209}
1210
1211
1212void DIALOG_LIB_SYMBOL_PROPERTIES::OnText( wxCommandEvent& event )
1213{
1214 OnModify();
1215}
1216
1217
1218void DIALOG_LIB_SYMBOL_PROPERTIES::OnCombobox( wxCommandEvent& event )
1219{
1220 OnModify();
1221}
1222
1223
1224void DIALOG_LIB_SYMBOL_PROPERTIES::OnCheckBox( wxCommandEvent& event )
1225{
1226 OnModify();
1227}
1228
1229
1231{
1232 m_unitNamesGrid->CommitPendingChanges( true /* aQuietMode */ );
1233
1234 int extra = m_unitNamesGrid->GetNumberRows() - m_unitSpinCtrl->GetValue();
1235 int needed = m_unitSpinCtrl->GetValue() - m_unitNamesGrid->GetNumberRows();
1236
1237 if( extra > 0 )
1238 {
1239 m_unitNamesGrid->DeleteRows( m_unitNamesGrid->GetNumberRows() - extra, extra );
1240 return true;
1241 }
1242
1243 if( needed > 0 )
1244 {
1245 m_unitNamesGrid->AppendRows( needed );
1246
1247 for( int row = m_unitNamesGrid->GetNumberRows() - needed; row < m_unitNamesGrid->GetNumberRows(); ++row )
1248 m_unitNamesGrid->SetCellValue( row, 0, LIB_SYMBOL::LetterSubReference( row + 1, 'A' ) );
1249
1250 return true;
1251 }
1252
1253 return false;
1254}
1255
1256
1258{
1259 if( updateUnitCount() )
1260 OnModify();
1261}
1262
1263
1265{
1266 // wait for kill focus to update unit count
1267}
1268
1269
1271{
1272 if( updateUnitCount() )
1273 OnModify();
1274}
1275
1276
1278{
1279 if( updateUnitCount() )
1280 OnModify();
1281}
1282
1283
1285{
1286 if( !m_grid->CommitPendingChanges() )
1287 aEvent.Veto();
1288}
1289
1290
1292{
1293 m_jumperGroupsGrid->OnAddRow(
1294 [&]() -> std::pair<int, int>
1295 {
1296 m_jumperGroupsGrid->AppendRows( 1 );
1297 OnModify();
1298
1299 return { m_jumperGroupsGrid->GetNumberRows() - 1, 0 };
1300 } );
1301}
1302
1303
1305{
1306 m_jumperGroupsGrid->OnDeleteRows(
1307 [&]( int row )
1308 {
1309 m_jumperGroupsGrid->DeleteRows( row, 1 );
1310 } );
1311
1312 OnModify();
1313}
1314
1315
const char * name
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:114
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:110
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
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 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
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition eda_text.cpp:541
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:395
void push_back(const SCH_FIELD &field)
A text control validator used for validating the text allowed in fields.
Definition validators.h:142
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition grid_tricks.h:61
Define a library symbol object.
Definition lib_symbol.h:83
static wxString LetterSubReference(int aUnit, wxChar aInitialLetter)
void SetOrdinal(int aOrdinal)
Definition sch_field.h:128
bool IsMandatory() const
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:118
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:259
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:202
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.
#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:695