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