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
343 m_ShowPinNumButt->SetValue( m_libEntry->GetShowPinNumbers() );
344 m_ShowPinNameButt->SetValue( m_libEntry->GetShowPinNames() );
345 m_PinsNameInsideButt->SetValue( m_libEntry->GetPinNameOffset() != 0 );
346 m_pinNameOffset.ChangeValue( m_libEntry->GetPinNameOffset() );
347
348 wxArrayString tmp = m_libEntry->GetFPFilters();
349 m_FootprintFilterListBox->Append( tmp );
350
351 m_cbDuplicatePinsAreJumpers->SetValue( m_libEntry->GetDuplicatePinNumbersAreJumpers() );
352
353 std::set<wxString> availablePins;
354
355 for( const SCH_PIN* pin : m_libEntry->GetPins() )
356 availablePins.insert( pin->GetNumber() );
357
358 for( const std::set<wxString>& group : m_libEntry->JumperPinGroups() )
359 {
360 wxString groupTxt;
361
362 for( const wxString& pinNumber : group )
363 {
364 if( !groupTxt.IsEmpty() )
365 groupTxt << ", ";
366
367 groupTxt << pinNumber;
368 }
369
370 m_jumperGroupsGrid->AppendRows( 1 );
371 m_jumperGroupsGrid->SetCellValue( m_jumperGroupsGrid->GetNumberRows() - 1, 0, groupTxt );
372 }
373
374 // Populate the list of root parts for inherited objects.
375 if( m_libEntry->IsDerived() )
376 {
377 wxArrayString symbolNames;
378 wxString libName = m_Parent->GetCurLib();
379
380 // Someone forgot to set the current library in the editor frame window.
381 wxCHECK( !libName.empty(), false );
382
383 m_Parent->GetLibManager().GetSymbolNames( libName, symbolNames );
384
385 // Sort the list of symbols for easier search
386 symbolNames.Sort(
387 []( const wxString& a, const wxString& b ) -> int
388 {
389 return StrNumCmp( a, b, true );
390 } );
391
392 // Do allow an inherited symbol to be derived from itself.
393 if( symbolNames.Index( m_libEntry->GetName() ) != wxNOT_FOUND )
394 symbolNames.Remove( m_libEntry->GetName() );
395
396 m_inheritanceSelectCombo->Append( symbolNames );
397
398 if( std::shared_ptr<LIB_SYMBOL> rootSymbol = m_libEntry->GetParent().lock() )
399 {
400 wxString parentName = UnescapeString( rootSymbol->GetName() );
401 int selection = m_inheritanceSelectCombo->FindString( parentName );
402
403 if( selection == wxNOT_FOUND )
404 return false;
405
406 m_inheritanceSelectCombo->SetSelection( selection );
407 }
408
410 }
411
412 m_NoteBook->SetSelection( (unsigned) m_lastOpenedPage );
413
414 m_embeddedFiles->TransferDataToWindow();
415
416 return true;
417}
418
419
421{
422 if( !m_grid->CommitPendingChanges() )
423 return false;
424
425 // Symbol reference can be empty because it inherits from the parent symbol.
426 if( m_libEntry->IsRoot() )
427 {
428 SCH_FIELD* field = m_fields->GetField( FIELD_T::REFERENCE );
429
430 if( UTIL::GetRefDesPrefix( field->GetText() ).IsEmpty() )
431 {
432 if( m_NoteBook->GetSelection() != 0 )
433 m_NoteBook->SetSelection( 0 );
434
435 m_delayedErrorMessage = _( "References must start with a letter." );
440
441 return false;
442 }
443 }
444
445 // Check for missing field names.
446 for( int ii = 0; ii < (int) m_fields->size(); ++ii )
447 {
448 SCH_FIELD& field = m_fields->at( ii );
449
450 if( field.IsMandatory() )
451 continue;
452
453 wxString fieldName = field.GetName( false );
454
455 if( fieldName.IsEmpty() && !field.GetText().IsEmpty() )
456 {
457 if( m_NoteBook->GetSelection() != 0 )
458 m_NoteBook->SetSelection( 0 );
459
460 m_delayedErrorMessage = _( "Fields must have a name." );
465
466 return false;
467 }
468 }
469
470 // Verify that the parent name is set if the symbol is inherited
471 if( m_libEntry->IsDerived() )
472 {
473 wxString parentName = m_inheritanceSelectCombo->GetValue();
474
475 if( parentName.IsEmpty() )
476 {
477 m_delayedErrorMessage = _( "Derived symbol must have a parent selected" );
478 return false;
479 }
480 }
481
482 /*
483 * Confirm destructive actions.
484 */
485
486 if( m_unitSpinCtrl->GetValue() < m_libEntry->GetUnitCount() )
487 {
488 if( !IsOK( this, _( "Delete extra units from symbol?" ) ) )
489 return false;
490 }
491
492 int bodyStyleCount = 0;
493
494 if( m_radioSingle->GetValue() )
495 {
496 bodyStyleCount = 1;
497 }
498 if( m_radioDeMorgan->GetValue() )
499 {
500 bodyStyleCount = 2;
501 }
502 else if( m_radioCustom->GetValue() )
503 {
504 for( int ii = 0; ii < m_bodyStyleNamesGrid->GetNumberRows(); ++ii )
505 {
506 if( !m_bodyStyleNamesGrid->GetCellValue( ii, 0 ).IsEmpty() )
507 bodyStyleCount++;
508 }
509 }
510
511 if( bodyStyleCount == 0 )
512 {
513 m_delayedErrorMessage = _( "Symbol must have at least 1 body style" );
514 return false;
515 }
516
517 if( bodyStyleCount < m_libEntry->GetBodyStyleCount() )
518 {
519 if( !IsOK( this, _( "Delete extra body styles from symbol?" ) ) )
520 return false;
521 }
522
523 return true;
524}
525
526
528{
529 if( !m_grid->CommitPendingChanges()
530 || !m_unitNamesGrid->CommitPendingChanges()
531 || !m_bodyStyleNamesGrid->CommitPendingChanges()
532 || !m_jumperGroupsGrid->CommitPendingChanges()
533 || !m_embeddedFiles->TransferDataFromWindow() )
534 {
535 return false;
536 }
537
538 wxString newName = EscapeString( m_SymbolNameCtrl->GetValue(), CTX_LIBID );
539 wxString oldName = m_libEntry->GetName();
540
541 if( newName.IsEmpty() )
542 {
543 wxMessageBox( _( "Symbol must have a name." ) );
544 return false;
545 }
546
548
549 if( oldName != newName )
550 {
551 wxString libName = m_Parent->GetCurLib();
552
553 if( m_Parent->GetLibManager().SymbolNameInUse( newName, libName ) )
554 {
555 wxString msg;
556
557 msg.Printf( _( "Symbol name '%s' already in use in library '%s'." ),
558 UnescapeString( newName ),
559 libName );
560 DisplayErrorMessage( this, msg );
561 return false;
562 }
563
564 opType = UNDO_REDO::LIB_RENAME;
565 }
566
567 m_Parent->SaveCopyInUndoList( _( "Edit Symbol Properties" ), m_libEntry, opType );
568
569 // The Y axis for components in lib is from bottom to top while the screen axis is top
570 // to bottom: we must change the y coord sign when writing back to the library
571 std::vector<SCH_FIELD> fieldsToSave;
572 int ordinal = 42; // Arbitrarily larger than any mandatory FIELD_T ids.
573
574 for( size_t ii = 0; ii < m_fields->size(); ++ii )
575 {
576 SCH_FIELD& field = m_fields->at( ii );
577
578 if( !field.IsMandatory() )
579 field.SetOrdinal( ordinal++ );
580
581 wxString fieldName = field.GetCanonicalName();
582
583 if( m_fields->IsInherited( ii ) && field == m_fields->ParentField( ii ) )
584 continue; // Skip inherited fields
585
586 if( field.GetText().IsEmpty() )
587 {
588 if( fieldName.IsEmpty() || m_addedTemplateFields.contains( fieldName ) )
589 continue; // Skip empty fields that are not mandatory or template fields
590 }
591 else if( fieldName.IsEmpty() )
592 {
593 field.SetName( _( "untitled" ) ); // Set a default name for unnamed fields
594 }
595
596 fieldsToSave.push_back( field );
597 }
598
599 m_libEntry->SetFields( fieldsToSave );
600
601 // Update the parent for inherited symbols
602 if( m_libEntry->IsDerived() )
603 {
604 wxString parentName = EscapeString( m_inheritanceSelectCombo->GetValue(), CTX_LIBID );
605
606 // The parentName was verified to be non-empty in the Validator
607 wxString libName = m_Parent->GetCurLib();
608
609 // Get the parent from the libManager based on the name set in the inheritance combo box.
610 LIB_SYMBOL* newParent = m_Parent->GetLibManager().GetSymbol( parentName, libName );
611
612 // Verify that the requested parent exists
613 wxCHECK( newParent, false );
614
615 m_libEntry->SetParent( newParent );
616 }
617
618 m_libEntry->SetName( newName );
619 m_libEntry->SetKeyWords( m_KeywordCtrl->GetValue() );
620 m_libEntry->SetUnitCount( m_unitSpinCtrl->GetValue(), true );
621 m_libEntry->LockUnits( m_libEntry->GetUnitCount() > 1 && !m_OptionPartsInterchangeable->GetValue() );
622
623 m_libEntry->GetUnitDisplayNames().clear();
624
625 for( int row = 0; row < m_unitNamesGrid->GetNumberRows(); row++ )
626 {
627 if( !m_unitNamesGrid->GetCellValue( row, 1 ).IsEmpty() )
628 m_libEntry->GetUnitDisplayNames()[row+1] = m_unitNamesGrid->GetCellValue( row, 1 );
629 }
630
631 if( m_radioSingle->GetValue() )
632 {
633 m_libEntry->SetHasDeMorganBodyStyles( false );
634 m_libEntry->SetBodyStyleCount( 1, false, false );
635 m_libEntry->SetBodyStyleNames( {} );
636 }
637 else if( m_radioDeMorgan->GetValue() )
638 {
639 m_libEntry->SetHasDeMorganBodyStyles( true );
640 m_libEntry->SetBodyStyleCount( 2, false, true );
641 m_libEntry->SetBodyStyleNames( {} );
642 }
643 else
644 {
645 std::vector<wxString> bodyStyleNames;
646
647 for( int row = 0; row < m_bodyStyleNamesGrid->GetNumberRows(); ++row )
648 {
649 if( !m_bodyStyleNamesGrid->GetCellValue( row, 0 ).IsEmpty() )
650 bodyStyleNames.push_back( m_bodyStyleNamesGrid->GetCellValue( row, 0 ) );
651 }
652
653 m_libEntry->SetHasDeMorganBodyStyles( false );
654 m_libEntry->SetBodyStyleCount( bodyStyleNames.size(), true, true );
655 m_libEntry->SetBodyStyleNames( bodyStyleNames );
656 }
657
658 if( m_OptionPower->GetValue() )
659 {
660 if( m_OptionLocalPower->GetValue() )
661 m_libEntry->SetLocalPower();
662 else
663 m_libEntry->SetGlobalPower();
664
665 // Power symbols must have value matching name for now
666 m_libEntry->GetValueField().SetText( newName );
667 }
668 else
669 {
670 m_libEntry->SetNormal();
671 }
672
673 m_libEntry->SetExcludedFromSim( m_excludeFromSimCheckBox->GetValue() );
674 m_libEntry->SetExcludedFromBOM( m_excludeFromBomCheckBox->GetValue() );
675 m_libEntry->SetExcludedFromBoard( m_excludeFromBoardCheckBox->GetValue() );
676
677 m_libEntry->SetShowPinNumbers( m_ShowPinNumButt->GetValue() );
678 m_libEntry->SetShowPinNames( m_ShowPinNameButt->GetValue() );
679
680 if( m_PinsNameInsideButt->GetValue() )
681 {
682 int offset = KiROUND( (double) m_pinNameOffset.GetValue() );
683
684 // We interpret an offset of 0 as "outside", so make sure it's non-zero
685 m_libEntry->SetPinNameOffset( offset == 0 ? 20 : offset );
686 }
687 else
688 {
689 m_libEntry->SetPinNameOffset( 0 ); // pin text outside the body (name is on the pin)
690 }
691
692 m_libEntry->SetFPFilters( m_FootprintFilterListBox->GetStrings());
693
694 m_libEntry->SetDuplicatePinNumbersAreJumpers( m_cbDuplicatePinsAreJumpers->GetValue() );
695
696 std::vector<std::set<wxString>>& jumpers = m_libEntry->JumperPinGroups();
697 jumpers.clear();
698
699 for( int ii = 0; ii < m_jumperGroupsGrid->GetNumberRows(); ++ii )
700 {
701 wxStringTokenizer tokenizer( m_jumperGroupsGrid->GetCellValue( ii, 0 ), ", \t\r\n", wxTOKEN_STRTOK );
702 std::set<wxString>& group = jumpers.emplace_back();
703
704 while( tokenizer.HasMoreTokens() )
705 {
706 if( wxString token = tokenizer.GetNextToken(); !token.IsEmpty() )
707 group.insert( token );
708 }
709 }
710
711 m_Parent->UpdateAfterSymbolProperties( &oldName );
712
713 return true;
714}
715
716
717void DIALOG_LIB_SYMBOL_PROPERTIES::OnBodyStyle( wxCommandEvent& event )
718{
719 m_bodyStyleNamesGrid->Enable( m_radioCustom->GetValue() );
720
721 m_bpAddBodyStyle->Enable( m_radioCustom->GetValue() );
722 m_bpMoveUpBodyStyle->Enable( m_radioCustom->GetValue() );
723 m_bpMoveDownBodyStyle->Enable( m_radioCustom->GetValue() );
724 m_bpDeleteBodyStyle->Enable( m_radioCustom->GetValue() );
725}
726
727
729{
730 aEvent.Skip();
731
732 wxPoint pos = aEvent.GetPosition();
733 wxPoint unscolled_pos = m_grid->CalcUnscrolledPosition( pos );
734 int row = m_grid->YToRow( unscolled_pos.y );
735 int col = m_grid->XToCol( unscolled_pos.x );
736
737 if( row == wxNOT_FOUND || col == wxNOT_FOUND || !m_fields->IsInherited( row ) )
738 {
739 m_grid->SetToolTip( "" );
740 return;
741 }
742
743 m_grid->SetToolTip( wxString::Format( _( "This field is inherited from '%s'." ),
744 m_fields->ParentField( row ).GetName() ) );
745}
746
747
749{
750 wxGridCellEditor* editor = m_grid->GetCellEditor( event.GetRow(), event.GetCol() );
751 wxControl* control = editor->GetControl();
752
753 if( control && control->GetValidator() && !control->GetValidator()->Validate( control ) )
754 {
755 event.Veto();
756
758 m_delayedFocusRow = event.GetRow();
759 m_delayedFocusColumn = event.GetCol();
761 }
762 else if( event.GetCol() == FDC_NAME )
763 {
764 wxString newName = event.GetString();
765
766 for( int i = 0; i < m_grid->GetNumberRows(); ++i )
767 {
768 if( i == event.GetRow() )
769 continue;
770
771 if( newName.CmpNoCase( m_grid->GetCellValue( i, FDC_NAME ) ) == 0 )
772 {
773 DisplayError( this, wxString::Format( _( "The name '%s' is already in use." ), newName ) );
774 event.Veto();
775 m_delayedFocusRow = event.GetRow();
776 m_delayedFocusColumn = event.GetCol();
777 }
778 }
779 }
780
781 editor->DecRef();
782}
783
784
786{
787 m_grid->ForceRefresh();
788 OnModify();
789}
790
791
793{
794 if( m_OptionPower->IsChecked() )
795 m_grid->SetCellValue( m_fields->GetFieldRow( FIELD_T::VALUE ), FDC_VALUE, m_SymbolNameCtrl->GetValue() );
796
797 OnModify();
798}
799
800
802{
803 if( !m_delayedFocusCtrl )
804 {
805 // If the validation fails and we throw up a dialog then GTK will give us another
806 // KillFocus event and we end up in infinite recursion. So we use m_delayedFocusCtrl
807 // as a re-entrancy block and then clear it again if validation passes.
810
811 if( m_SymbolNameCtrl->GetValidator()->Validate( m_SymbolNameCtrl ) )
812 {
813 m_delayedFocusCtrl = nullptr;
815 }
816 }
817
818 event.Skip();
819}
820
821
822void DIALOG_LIB_SYMBOL_PROPERTIES::OnAddField( wxCommandEvent& event )
823{
824 m_grid->OnAddRow(
825 [&]() -> std::pair<int, int>
826 {
827 SYMBOL_EDITOR_SETTINGS* settings = m_Parent->GetSettings();
829
830 newField.SetTextSize( VECTOR2I( schIUScale.MilsToIU( settings->m_Defaults.text_size ),
831 schIUScale.MilsToIU( settings->m_Defaults.text_size ) ) );
832 newField.SetVisible( false );
833
834 m_fields->push_back( newField );
835
836 // notify the grid
837 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
838 m_grid->ProcessTableMessage( msg );
839 OnModify();
840
841 return { m_fields->size() - 1, FDC_NAME };
842 } );
843}
844
845
847{
848 m_grid->OnDeleteRows(
849 [&]( int row )
850 {
851 if( row < m_fields->GetMandatoryRowCount() )
852 {
853 DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
854 m_fields->GetMandatoryRowCount() ) );
855 return false;
856 }
857
858 return true;
859 },
860 [&]( int row )
861 {
862 if( !m_fields->EraseRow( row ) )
863 return;
864
865 // notify the grid
866 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 );
867 m_grid->ProcessTableMessage( msg );
868 } );
869
870 OnModify();
871}
872
873
874void DIALOG_LIB_SYMBOL_PROPERTIES::OnMoveUp( wxCommandEvent& event )
875{
876 m_grid->OnMoveRowUp(
877 [&]( int row )
878 {
879 return row > m_fields->GetMandatoryRowCount();
880 },
881 [&]( int row )
882 {
883 m_fields->SwapRows( row, row - 1 );
884 m_grid->ForceRefresh();
885 OnModify();
886 } );
887}
888
889
890void DIALOG_LIB_SYMBOL_PROPERTIES::OnMoveDown( wxCommandEvent& event )
891{
892 m_grid->OnMoveRowDown(
893 [&]( int row )
894 {
895 return row >= m_fields->GetMandatoryRowCount();
896 },
897 [&]( int row )
898 {
899 m_fields->SwapRows( row, row + 1 );
900 m_grid->ForceRefresh();
901 OnModify();
902 } );
903}
904
905
907{
908 m_bodyStyleNamesGrid->OnAddRow(
909 [&]() -> std::pair<int, int>
910 {
911 m_bodyStyleNamesGrid->AppendRows( 1 );
912 OnModify();
913
914 return { m_bodyStyleNamesGrid->GetNumberRows() - 1, 0 };
915 } );
916}
917
918
920{
921 m_bodyStyleNamesGrid->OnDeleteRows(
922 [&]( int row )
923 {
924 m_bodyStyleNamesGrid->DeleteRows( row );
925 } );
926
927 OnModify();
928}
929
930
932{
933 m_bodyStyleNamesGrid->OnMoveRowUp(
934 [&]( int row )
935 {
936 m_bodyStyleNamesGrid->SwapRows( row, row - 1 );
937 OnModify();
938 } );
939}
940
941
943{
944 m_bodyStyleNamesGrid->OnMoveRowDown(
945 [&]( int row )
946 {
947 m_bodyStyleNamesGrid->SwapRows( row, row + 1 );
948 OnModify();
949 } );
950}
951
952
954{
955 if( !m_grid->CommitPendingChanges() )
956 return;
957
958 m_grid->ClearSelection();
959
960 std::vector<SCH_FIELD> fields;
961
962 for( const SCH_FIELD& field : *m_fields )
963 fields.emplace_back( field );
964
965 DIALOG_SIM_MODEL dialog( this, m_parentFrame, *m_libEntry, fields );
966
967 if( dialog.ShowModal() != wxID_OK )
968 return;
969
970 // Add in any new fields
971 for( const SCH_FIELD& editedField : fields )
972 {
973 bool found = false;
974
975 for( SCH_FIELD& existingField : *m_fields )
976 {
977 if( existingField.GetName() == editedField.GetName() )
978 {
979 found = true;
980 existingField.SetText( editedField.GetText() );
981 break;
982 }
983 }
984
985 if( !found )
986 {
987 m_fields->emplace_back( editedField );
988 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
989 m_grid->ProcessTableMessage( msg );
990 }
991 }
992
993 // Remove any deleted fields
994 for( int ii = (int) m_fields->size() - 1; ii >= 0; --ii )
995 {
996 SCH_FIELD& existingField = m_fields->at( ii );
997 bool found = false;
998
999 for( SCH_FIELD& editedField : fields )
1000 {
1001 if( editedField.GetName() == existingField.GetName() )
1002 {
1003 found = true;
1004 break;
1005 }
1006 }
1007
1008 if( !found )
1009 {
1010 m_grid->ClearSelection();
1011 m_fields->erase( m_fields->begin() + ii );
1012
1013 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, ii, 1 );
1014 m_grid->ProcessTableMessage( msg );
1015 }
1016 }
1017
1018 OnModify();
1019 m_grid->ForceRefresh();
1020}
1021
1022
1024{
1025 int idx = m_FootprintFilterListBox->HitTest( event.GetPosition() );
1026 wxCommandEvent dummy;
1027
1028 if( idx >= 0 )
1030 else
1032}
1033
1034
1036{
1037 // Running the Footprint Browser gums up the works and causes the automatic cancel
1038 // stuff to no longer work. So we do it here ourselves.
1039 EndQuasiModal( wxID_CANCEL );
1040}
1041
1042
1044{
1045 wxString filterLine;
1046 WX_TEXT_ENTRY_DIALOG dlg( this, _( "Filter:" ), _( "Add Footprint Filter" ), filterLine );
1047
1048 if( dlg.ShowModal() == wxID_CANCEL || dlg.GetValue().IsEmpty() )
1049 return;
1050
1051 filterLine = dlg.GetValue();
1052 filterLine.Replace( wxT( " " ), wxT( "_" ) );
1053
1054 // duplicate filters do no harm, so don't be a nanny.
1055 m_FootprintFilterListBox->Append( filterLine );
1056 m_FootprintFilterListBox->SetSelection( (int) m_FootprintFilterListBox->GetCount() - 1 );
1057
1058 OnModify();
1059}
1060
1061
1063{
1064 wxArrayInt selections;
1065 int n = m_FootprintFilterListBox->GetSelections( selections );
1066
1067 if( n > 0 )
1068 {
1069 // Just edit the first one
1070 int idx = selections[0];
1071 wxString filter = m_FootprintFilterListBox->GetString( idx );
1072
1073 WX_TEXT_ENTRY_DIALOG dlg( this, _( "Filter:" ), _( "Edit Footprint Filter" ), filter );
1074
1075 if( dlg.ShowModal() == wxID_OK && !dlg.GetValue().IsEmpty() )
1076 {
1077 m_FootprintFilterListBox->SetString( (unsigned) idx, dlg.GetValue() );
1078 OnModify();
1079 }
1080 }
1081}
1082
1083
1084void DIALOG_LIB_SYMBOL_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
1085{
1086 m_OptionPartsInterchangeable->Enable( m_unitSpinCtrl->GetValue() > 1 );
1087 m_pinNameOffset.Enable( m_PinsNameInsideButt->GetValue() );
1088
1089 if( m_grid->IsCellEditControlShown() )
1090 {
1091 int row = m_grid->GetGridCursorRow();
1092 int col = m_grid->GetGridCursorCol();
1093
1094 if( row == m_fields->GetFieldRow( FIELD_T::VALUE ) && col == FDC_VALUE && m_OptionPower->IsChecked() )
1095 {
1096 wxGridCellEditor* editor = m_grid->GetCellEditor( row, col );
1097 m_SymbolNameCtrl->ChangeValue( editor->GetValue() );
1098 editor->DecRef();
1099 }
1100 }
1101
1102 // Handle shown columns changes
1103 std::bitset<64> shownColumns = m_grid->GetShownColumns();
1104
1105 if( shownColumns != m_shownColumns )
1106 {
1107 m_shownColumns = shownColumns;
1108
1109 if( !m_grid->IsCellEditControlShown() )
1110 m_grid->SetGridWidthsDirty();
1111 }
1112
1113 // Handle a delayed focus. The delay allows us to:
1114 // a) change focus when the error was triggered from within a killFocus handler
1115 // b) show the correct notebook page in the background before the error dialog comes up
1116 // when triggered from an OK or a notebook page change
1117
1118 if( m_delayedFocusPage >= 0 && m_NoteBook->GetSelection() != m_delayedFocusPage )
1119 {
1120 m_NoteBook->ChangeSelection( (unsigned) m_delayedFocusPage );
1121 m_delayedFocusPage = -1;
1122 }
1123
1124 if( !m_delayedErrorMessage.IsEmpty() )
1125 {
1126 // We will re-enter this routine when the error dialog is displayed, so make
1127 // sure we don't keep putting up more dialogs.
1128 wxString msg = m_delayedErrorMessage;
1129 m_delayedErrorMessage = wxEmptyString;
1130
1131 // Do not use DisplayErrorMessage(); it screws up window order on Mac
1132 DisplayError( nullptr, msg );
1133 }
1134
1135 if( m_delayedFocusCtrl )
1136 {
1137 m_delayedFocusCtrl->SetFocus();
1138
1139 if( wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_delayedFocusCtrl ) )
1140 textEntry->SelectAll();
1141
1142 m_delayedFocusCtrl = nullptr;
1143 }
1144 else if( m_delayedFocusGrid )
1145 {
1146 m_delayedFocusGrid->SetFocus();
1149
1150 m_delayedFocusGrid->EnableCellEditControl( true );
1151 m_delayedFocusGrid->ShowCellEditControl();
1152
1153 m_delayedFocusGrid = nullptr;
1154 m_delayedFocusRow = -1;
1156 }
1157}
1158
1159
1161{
1162 bSizerLowerBasicPanel->Show( !aIsAlias );
1163 m_inheritanceSelectCombo->Enable( aIsAlias );
1164 m_inheritsStaticText->Enable( aIsAlias );
1165 m_grid->ForceRefresh();
1166}
1167
1168
1170{
1171 if( m_OptionPower->IsChecked() )
1172 {
1173 m_excludeFromSimCheckBox->SetValue( true );
1174 m_excludeFromBomCheckBox->SetValue( true );
1175 m_excludeFromBoardCheckBox->SetValue( true );
1176 m_excludeFromBomCheckBox->Enable( false );
1177 m_excludeFromBoardCheckBox->Enable( false );
1178 m_excludeFromSimCheckBox->Enable( false );
1179 m_spiceFieldsButton->Show( false );
1180 m_OptionLocalPower->Enable( true );
1181 }
1182 else
1183 {
1184 m_excludeFromBomCheckBox->Enable( true );
1185 m_excludeFromBoardCheckBox->Enable( true );
1186 m_excludeFromSimCheckBox->Enable( true );
1187 m_spiceFieldsButton->Show( true );
1188 m_OptionLocalPower->Enable( false );
1189 }
1190
1191 OnModify();
1192}
1193
1194
1195void DIALOG_LIB_SYMBOL_PROPERTIES::OnText( wxCommandEvent& event )
1196{
1197 OnModify();
1198}
1199
1200
1201void DIALOG_LIB_SYMBOL_PROPERTIES::OnCombobox( wxCommandEvent& event )
1202{
1203 OnModify();
1204}
1205
1206
1207void DIALOG_LIB_SYMBOL_PROPERTIES::OnCheckBox( wxCommandEvent& event )
1208{
1209 OnModify();
1210}
1211
1212
1214{
1215 m_unitNamesGrid->CommitPendingChanges( true /* aQuietMode */ );
1216
1217 int extra = m_unitNamesGrid->GetNumberRows() - m_unitSpinCtrl->GetValue();
1218 int needed = m_unitSpinCtrl->GetValue() - m_unitNamesGrid->GetNumberRows();
1219
1220 if( extra > 0 )
1221 {
1222 m_unitNamesGrid->DeleteRows( m_unitNamesGrid->GetNumberRows() - extra, extra );
1223 return true;
1224 }
1225
1226 if( needed > 0 )
1227 {
1228 m_unitNamesGrid->AppendRows( needed );
1229
1230 for( int row = m_unitNamesGrid->GetNumberRows() - needed; row < m_unitNamesGrid->GetNumberRows(); ++row )
1231 m_unitNamesGrid->SetCellValue( row, 0, LIB_SYMBOL::LetterSubReference( row + 1, 'A' ) );
1232
1233 return true;
1234 }
1235
1236 return false;
1237}
1238
1239
1241{
1242 if( updateUnitCount() )
1243 OnModify();
1244}
1245
1246
1248{
1249 // wait for kill focus to update unit count
1250}
1251
1252
1254{
1255 if( updateUnitCount() )
1256 OnModify();
1257}
1258
1259
1261{
1262 if( updateUnitCount() )
1263 OnModify();
1264}
1265
1266
1268{
1269 if( !m_grid->CommitPendingChanges() )
1270 aEvent.Veto();
1271}
1272
1273
1275{
1276 m_jumperGroupsGrid->OnAddRow(
1277 [&]() -> std::pair<int, int>
1278 {
1279 m_jumperGroupsGrid->AppendRows( 1 );
1280 OnModify();
1281
1282 return { m_jumperGroupsGrid->GetNumberRows() - 1, 0 };
1283 } );
1284}
1285
1286
1288{
1289 m_jumperGroupsGrid->OnDeleteRows(
1290 [&]( int row )
1291 {
1292 m_jumperGroupsGrid->DeleteRows( row, 1 );
1293 } );
1294
1295 OnModify();
1296}
1297
1298
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:540
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:98
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:394
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:122
bool IsMandatory() const
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