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 ),
64 m_pinNameOffset( aParent, m_nameOffsetLabel, m_nameOffsetCtrl, m_nameOffsetUnits, true ),
65 m_delayedFocusCtrl( nullptr ),
66 m_delayedFocusGrid( nullptr ),
67 m_delayedFocusRow( -1 ),
68 m_delayedFocusColumn( -1 ),
69 m_delayedFocusPage( -1 ),
70 m_fpFilterTricks( std::make_unique<LISTBOX_TRICKS>( *this, *m_FootprintFilterListBox ) )
71{
73 m_NoteBook->AddPage( m_embeddedFiles, _( "Embedded Files" ) );
74
75 m_fields = new FIELDS_GRID_TABLE( this, aParent, m_grid, m_libEntry,
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 )
124 }
125 }
126 }
127
128 // Show/hide columns according to the user's preference
131
132 m_SymbolNameCtrl->SetValidator( FIELD_VALIDATOR( FIELD_T::VALUE ) );
133
134 // Configure button logos
135 m_bpAdd->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
136 m_bpDelete->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
137 m_bpMoveUp->SetBitmap( KiBitmapBundle( BITMAPS::small_up ) );
138 m_bpMoveDown->SetBitmap( KiBitmapBundle( BITMAPS::small_down ) );
139 m_addFilterButton->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
140 m_deleteFilterButton->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
141 m_editFilterButton->SetBitmap( KiBitmapBundle( BITMAPS::small_edit ) );
142
143 m_btnCreateJumperPinGroup->SetBitmap( KiBitmapBundle( BITMAPS::right ) );
144 m_btnRemoveJumperPinGroup->SetBitmap( KiBitmapBundle( BITMAPS::left ) );
145
147
148 if( aParent->IsSymbolFromLegacyLibrary() && !aParent->IsSymbolFromSchematic() )
149 {
150 m_stdSizerButtonCancel->SetDefault();
151 m_stdSizerButtonOK->SetLabel( _( "Read Only" ) );
152 m_stdSizerButtonOK->Enable( false );
153 }
154
155 // wxFormBuilder doesn't include this event...
156 m_grid->Connect( wxEVT_GRID_CELL_CHANGING,
157 wxGridEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanging ), nullptr, this );
158 m_grid->Connect( wxEVT_GRID_CELL_CHANGED,
159 wxGridEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanged ), nullptr, this );
160 m_grid->GetGridWindow()->Bind( wxEVT_MOTION, &DIALOG_LIB_SYMBOL_PROPERTIES::OnGridMotion, this );
161
162
163 // Forward the delete button to the tricks
164 m_deleteFilterButton->Bind( wxEVT_BUTTON,
165 [&]( wxCommandEvent& aEvent )
166 {
167 wxCommandEvent cmdEvent( EDA_EVT_LISTBOX_DELETE );
168 m_fpFilterTricks->ProcessEvent( cmdEvent );
169 } );
170
171 // When the filter tricks modifies something, update ourselves
172 m_FootprintFilterListBox->Bind( EDA_EVT_LISTBOX_CHANGED,
173 [&]( wxCommandEvent& aEvent )
174 {
175 OnModify();
176 } );
177
179 {
182 {
183 resetSize();
184 }
185 }
186
189
190 m_grid->GetParent()->Layout();
192 Layout();
193
195}
196
197
199{
200 m_lastOpenedPage = m_NoteBook->GetSelection( );
201
203 cfg->m_EditSymbolVisibleColumns = m_grid->GetShownColumnsAsString();
204
205 // Prevents crash bug in wxGrid's d'tor
207
208 m_grid->Disconnect( wxEVT_GRID_CELL_CHANGING,
209 wxGridEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanging ), nullptr, this );
210 m_grid->Disconnect( wxEVT_GRID_CELL_CHANGED,
211 wxGridEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanged ), nullptr, this );
212 m_grid->GetGridWindow()->Unbind( wxEVT_MOTION, &DIALOG_LIB_SYMBOL_PROPERTIES::OnGridMotion, this );
213
214 // Delete the GRID_TRICKS.
215 m_grid->PopEventHandler( true );
216}
217
218
220{
221 if( !wxDialog::TransferDataToWindow() )
222 return false;
223
224 std::set<wxString> defined;
225
226 for( SCH_FIELD& field : *m_fields )
227 defined.insert( field.GetName() );
228
229 // Add in any template fieldnames not yet defined:
230 // Read global fieldname templates
231 if( EESCHEMA_SETTINGS* cfg = GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" ) )
232 {
233 TEMPLATES templateMgr;
234
235 if( !cfg->m_Drawing.field_names.IsEmpty() )
236 templateMgr.AddTemplateFieldNames( cfg->m_Drawing.field_names );
237
238 for( const TEMPLATE_FIELDNAME& templateFieldname : templateMgr.GetTemplateFieldNames() )
239 {
240 if( defined.count( templateFieldname.m_Name ) <= 0 )
241 {
242 SCH_FIELD field( m_libEntry, FIELD_T::USER, templateFieldname.m_Name );
243 field.SetVisible( templateFieldname.m_Visible );
244 m_fields->push_back( field );
245 m_addedTemplateFields.insert( templateFieldname.m_Name );
246 }
247 }
248 }
249
250 // The Y axis for components in lib is from bottom to top while the screen axis is top
251 // to bottom: we must change the y coord sign for editing
252 for( size_t i = 0; i < m_fields->size(); ++i )
253 {
254 VECTOR2I pos = m_fields->at( i ).GetPosition();
255 pos.y = -pos.y;
256 m_fields->at( i ).SetPosition( pos );
257 }
258
259 // notify the grid
260 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_fields->GetNumberRows() );
261 m_grid->ProcessTableMessage( msg );
263
265
266 m_KeywordCtrl->ChangeValue( m_libEntry->GetKeyWords() );
269
270 // If a symbol contains no body-style-specific pins or graphic items,
271 // symbol->HasAlternateBodyStyle() will return false.
272 // But when editing a symbol with DeMorgan option set, we don't want to keep turning it off
273 // just because there aren't any body-style-specific items yet, so we force it to on if the
274 // parent frame has it enabled.
276
277 m_OptionPower->SetValue( m_libEntry->IsPower() );
279
280 if( m_libEntry->IsPower() )
281 {
282 m_spiceFieldsButton->Hide();
283 m_OptionLocalPower->Enable();
284 }
285 else
286 {
287 m_OptionLocalPower->Enable( false );
288 }
289
293
298
299 wxArrayString tmp = m_libEntry->GetFPFilters();
300 m_FootprintFilterListBox->Append( tmp );
301
303 m_btnCreateJumperPinGroup->Disable();
304 m_btnRemoveJumperPinGroup->Disable();
305
306 std::set<wxString> availablePins;
307
308 for( const SCH_PIN* pin : m_libEntry->GetPins() )
309 availablePins.insert( pin->GetNumber() );
310
311 for( const std::set<wxString>& group : m_libEntry->JumperPinGroups() )
312 {
313 wxString groupTxt;
314 size_t i = 0;
315
316 for( const wxString& pinNumber : group )
317 {
318 availablePins.erase( pinNumber );
319 groupTxt << pinNumber;
320
321 if( ++i < group.size() )
322 groupTxt << ", ";
323 }
324
325 m_listJumperPinGroups->Append( groupTxt );
326 }
327
328 for( const wxString& pin : availablePins )
329 m_listAvailablePins->AppendString( pin );
330
331 // Populate the list of root parts for inherited objects.
332 if( m_libEntry->IsDerived() )
333 {
334 wxArrayString symbolNames;
335 wxString libName = m_Parent->GetCurLib();
336
337 // Someone forgot to set the current library in the editor frame window.
338 wxCHECK( !libName.empty(), false );
339
340 m_Parent->GetLibManager().GetSymbolNames( libName, symbolNames );
341
342 // Sort the list of symbols for easier search
343 symbolNames.Sort(
344 []( const wxString& a, const wxString& b ) -> int
345 {
346 return StrNumCmp( a, b, true );
347 } );
348
349 // Do allow an inherited symbol to be derived from itself.
350 if( symbolNames.Index( m_libEntry->GetName() ) != wxNOT_FOUND )
351 symbolNames.Remove( m_libEntry->GetName() );
352
353 m_inheritanceSelectCombo->Append( symbolNames );
354
355 if( LIB_SYMBOL_SPTR rootSymbol = m_libEntry->GetParent().lock() )
356 {
357 wxString parentName = UnescapeString( rootSymbol->GetName() );
358 int selection = m_inheritanceSelectCombo->FindString( parentName );
359
360 if( selection == wxNOT_FOUND )
361 return false;
362
363 m_inheritanceSelectCombo->SetSelection( selection );
364 }
365
367 }
368
369 m_NoteBook->SetSelection( (unsigned) m_lastOpenedPage );
370
372
373 return true;
374}
375
376
378{
380 return false;
381
382 // Symbol reference can be empty because it inherits from the parent symbol.
383 if( m_libEntry->IsRoot() )
384 {
385 SCH_FIELD* field = m_fields->GetField( FIELD_T::REFERENCE );
386
387 if( UTIL::GetRefDesPrefix( field->GetText() ).IsEmpty() )
388 {
389 if( m_NoteBook->GetSelection() != 0 )
390 m_NoteBook->SetSelection( 0 );
391
392 m_delayedErrorMessage = _( "References must start with a letter." );
395 m_delayedFocusRow = m_fields->GetFieldRow( FIELD_T::REFERENCE );
397
398 return false;
399 }
400 }
401
402 // Check for missing field names.
403 for( int ii = 0; ii < (int) m_fields->size(); ++ii )
404 {
405 SCH_FIELD& field = m_fields->at( ii );
406
407 if( field.IsMandatory() )
408 continue;
409
410 wxString fieldName = field.GetName( false );
411
412 if( fieldName.IsEmpty() && !field.GetText().IsEmpty() )
413 {
414 if( m_NoteBook->GetSelection() != 0 )
415 m_NoteBook->SetSelection( 0 );
416
417 m_delayedErrorMessage = _( "Fields must have a name." );
422
423 return false;
424 }
425 }
426
427 // Verify that the parent name is set if the symbol is inherited
428 if( m_libEntry->IsDerived() )
429 {
430 wxString parentName = m_inheritanceSelectCombo->GetValue();
431
432 if( parentName.IsEmpty() )
433 {
434 m_delayedErrorMessage = _( "Derived symbol must have a parent selected" );
435 return false;
436 }
437 }
438
439 /*
440 * Confirm destructive actions.
441 */
442
443 if( m_SelNumberOfUnits->GetValue() < m_libEntry->GetUnitCount() )
444 {
445 if( !IsOK( this, _( "Delete extra units from symbol?" ) ) )
446 return false;
447 }
448
450 {
451 if( !IsOK( this, _( "Delete alternate body style (De Morgan) from symbol?" ) ) )
452 return false;
453 }
454
455 return true;
456}
457
458
460{
461 if( !wxDialog::TransferDataFromWindow() )
462 return false;
463
465 return false;
466
467 wxString newName = EscapeString( m_SymbolNameCtrl->GetValue(), CTX_LIBID );
468 wxString oldName = m_libEntry->GetName();
469
470 if( newName.IsEmpty() )
471 {
472 wxMessageBox( _( "Symbol must have a name." ) );
473 return false;
474 }
475
476 UNDO_REDO opType = UNDO_REDO::LIBEDIT;
477
478 if( oldName != newName )
479 {
480 wxString libName = m_Parent->GetCurLib();
481
482 if( m_Parent->GetLibManager().SymbolNameInUse( newName, libName ) )
483 {
484 wxString msg;
485
486 msg.Printf( _( "Symbol name '%s' already in use in library '%s'." ),
487 UnescapeString( newName ),
488 libName );
489 DisplayErrorMessage( this, msg );
490 return false;
491 }
492
493 opType = UNDO_REDO::LIB_RENAME;
494 }
495
496 m_Parent->SaveCopyInUndoList( _( "Edit Symbol Properties" ), m_libEntry, opType );
497
498 // The Y axis for components in lib is from bottom to top while the screen axis is top
499 // to bottom: we must change the y coord sign when writing back to the library
500 std::vector<SCH_FIELD> fieldsToSave;
501 int ordinal = 42; // Arbitrarily larger than any mandatory FIELD_T ids.
502
503 for( size_t ii = 0; ii < m_fields->size(); ++ii )
504 {
505 SCH_FIELD& field = m_fields->at( ii );
506
507 VECTOR2I pos = field.GetPosition();
508 pos.y = -pos.y;
509 field.SetPosition( pos );
510
511 if( !field.IsMandatory() )
512 field.SetOrdinal( ordinal++ );
513
514 wxString fieldName = field.GetCanonicalName();
515
516 if( m_fields->IsInherited( ii ) && field == m_fields->ParentField( ii ) )
517 continue; // Skip inherited fields
518
519 if( field.GetText().IsEmpty() )
520 {
521 if( fieldName.IsEmpty() || m_addedTemplateFields.contains( fieldName ) )
522 continue; // Skip empty fields that are not mandatory or template fields
523 }
524 else if( fieldName.IsEmpty() )
525 {
526 field.SetName( _( "untitled" ) ); // Set a default name for unnamed fields
527 }
528
529 fieldsToSave.push_back( field );
530 }
531
532 m_libEntry->SetFields( fieldsToSave );
533
534 // Update the parent for inherited symbols
535 if( m_libEntry->IsDerived() )
536 {
537 wxString parentName = EscapeString( m_inheritanceSelectCombo->GetValue(), CTX_LIBID );
538
539 // The parentName was verified to be non-empty in the Validator
540 wxString libName = m_Parent->GetCurLib();
541
542 // Get the parent from the libManager based on the name set in the inheritance combo box.
543 LIB_SYMBOL* newParent = m_Parent->GetLibManager().GetSymbol( parentName, libName );
544
545 // Verify that the requested parent exists
546 wxCHECK( newParent, false );
547
548 m_libEntry->SetParent( newParent );
549 }
550
551 m_libEntry->SetName( newName );
552 m_libEntry->SetKeyWords( m_KeywordCtrl->GetValue() );
557
558 if( m_OptionPower->GetValue() )
559 {
560 if( m_OptionLocalPower->GetValue() )
562 else
564
565 // Power symbols must have value matching name for now
566 m_libEntry->GetValueField().SetText( newName );
567 }
568 else
569 {
571 }
572
576
579
580 if( m_PinsNameInsideButt->GetValue() )
581 {
582 int offset = KiROUND( (double) m_pinNameOffset.GetValue() );
583
584 // We interpret an offset of 0 as "outside", so make sure it's non-zero
585 m_libEntry->SetPinNameOffset( offset == 0 ? 20 : offset );
586 }
587 else
588 {
589 m_libEntry->SetPinNameOffset( 0 ); // pin text outside the body (name is on the pin)
590 }
591
593
595
596 std::vector<std::set<wxString>>& jumpers = m_libEntry->JumperPinGroups();
597 jumpers.clear();
598
599 for( unsigned i = 0; i < m_listJumperPinGroups->GetCount(); ++i )
600 {
601 wxStringTokenizer tokenizer( m_listJumperPinGroups->GetString( i ), ", " );
602 std::set<wxString>& group = jumpers.emplace_back();
603
604 while( tokenizer.HasMoreTokens() )
605 {
606 if( wxString token = tokenizer.GetNextToken(); !token.IsEmpty() )
607 group.insert( token );
608 }
609 }
610
612
613 // It's possible that the symbol being edited has no pins, in which case there may be no
614 // alternate body style objects causing #LIB_SYMBOL::HasAlternateBodyStyle() to always return
615 // false. This allows the user to edit the alternate body style just in case this condition
616 // occurs.
618
619 return true;
620}
621
622
624{
625 aEvent.Skip();
626
627 wxPoint pos = aEvent.GetPosition();
628 wxPoint unscolled_pos = m_grid->CalcUnscrolledPosition( pos );
629 int row = m_grid->YToRow( unscolled_pos.y );
630 int col = m_grid->XToCol( unscolled_pos.x );
631
632 if( row == wxNOT_FOUND || col == wxNOT_FOUND || !m_fields->IsInherited( row ) )
633 {
634 m_grid->SetToolTip( "" );
635 return;
636 }
637
638 m_grid->SetToolTip(
639 wxString::Format( _( "This field is inherited from '%s'." ),
640 m_fields->ParentField( row ).GetName() ) );
641}
642
643
645{
646 wxGridCellEditor* editor = m_grid->GetCellEditor( event.GetRow(), event.GetCol() );
647 wxControl* control = editor->GetControl();
648
649 if( control && control->GetValidator() && !control->GetValidator()->Validate( control ) )
650 {
651 event.Veto();
652
654 m_delayedFocusRow = event.GetRow();
655 m_delayedFocusColumn = event.GetCol();
657 }
658 else if( event.GetCol() == FDC_NAME )
659 {
660 wxString newName = event.GetString();
661
662 for( int i = 0; i < m_grid->GetNumberRows(); ++i )
663 {
664 if( i == event.GetRow() )
665 continue;
666
667 if( newName.CmpNoCase( m_grid->GetCellValue( i, FDC_NAME ) ) == 0 )
668 {
669 DisplayError( this, wxString::Format( _( "The name '%s' is already in use." ), newName ) );
670 event.Veto();
671 m_delayedFocusRow = event.GetRow();
672 m_delayedFocusColumn = event.GetCol();
673 }
674 }
675 }
676
677 editor->DecRef();
678}
679
680
682{
683 m_grid->ForceRefresh();
684 OnModify();
685}
686
687
689{
690 if( m_OptionPower->IsChecked() )
691 m_grid->SetCellValue( m_fields->GetFieldRow( FIELD_T::VALUE ), FDC_VALUE, m_SymbolNameCtrl->GetValue() );
692
693 OnModify();
694}
695
696
698{
699 if( !m_delayedFocusCtrl )
700 {
701 // If the validation fails and we throw up a dialog then GTK will give us another
702 // KillFocus event and we end up in infinite recursion. So we use m_delayedFocusCtrl
703 // as a re-entrancy block and then clear it again if validation passes.
706
707 if( m_SymbolNameCtrl->GetValidator()->Validate( m_SymbolNameCtrl ) )
708 {
709 m_delayedFocusCtrl = nullptr;
711 }
712 }
713
714 event.Skip();
715}
716
717
718void DIALOG_LIB_SYMBOL_PROPERTIES::OnAddField( wxCommandEvent& event )
719{
721 [&]() -> std::pair<int, int>
722 {
724 SCH_FIELD newField( m_libEntry, FIELD_T::USER, GetUserFieldName( m_fields->size(), DO_TRANSLATE ) );
725
727 schIUScale.MilsToIU( settings->m_Defaults.text_size ) ) );
728 newField.SetVisible( false );
729
730 m_fields->push_back( newField );
731
732 // notify the grid
733 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
734 m_grid->ProcessTableMessage( msg );
735 OnModify();
736
737 return { m_fields->size() - 1, FDC_NAME };
738 } );
739}
740
741
743{
745 [&]( int row )
746 {
747 if( row < m_fields->GetMandatoryRowCount() )
748 {
749 DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
751 return false;
752 }
753
754 return true;
755 },
756 [&]( int row )
757 {
758 if( !m_fields->EraseRow( row ) )
759 return;
760
761 // notify the grid
762 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 );
763 m_grid->ProcessTableMessage( msg );
764 } );
765
766 OnModify();
767}
768
769
770void DIALOG_LIB_SYMBOL_PROPERTIES::OnMoveUp( wxCommandEvent& event )
771{
773 [&]( int row )
774 {
775 return row > m_fields->GetMandatoryRowCount();
776 },
777 [&]( int row )
778 {
779 m_fields->SwapRows( row, row - 1 );
780 m_grid->ForceRefresh();
781 OnModify();
782 } );
783}
784
785
786void DIALOG_LIB_SYMBOL_PROPERTIES::OnMoveDown( wxCommandEvent& event )
787{
789 [&]( int row )
790 {
791 return row >= m_fields->GetMandatoryRowCount();
792 },
793 [&]( int row )
794 {
795 m_fields->SwapRows( row, row + 1 );
796 m_grid->ForceRefresh();
797 OnModify();
798 } );
799}
800
801
803{
805 return;
806
807 m_grid->ClearSelection();
808
809 std::vector<SCH_FIELD> fields;
810
811 for( const SCH_FIELD& field : *m_fields )
812 fields.emplace_back( field );
813
814 DIALOG_SIM_MODEL dialog( this, m_parentFrame, *m_libEntry, fields );
815
816 if( dialog.ShowModal() != wxID_OK )
817 return;
818
819 // Add in any new fields
820 for( const SCH_FIELD& editedField : fields )
821 {
822 bool found = false;
823
824 for( SCH_FIELD& existingField : *m_fields )
825 {
826 if( existingField.GetName() == editedField.GetName() )
827 {
828 found = true;
829 existingField.SetText( editedField.GetText() );
830 break;
831 }
832 }
833
834 if( !found )
835 {
836 m_fields->emplace_back( editedField );
837 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
838 m_grid->ProcessTableMessage( msg );
839 }
840 }
841
842 // Remove any deleted fields
843 for( int ii = (int) m_fields->size() - 1; ii >= 0; --ii )
844 {
845 SCH_FIELD& existingField = m_fields->at( ii );
846 bool found = false;
847
848 for( SCH_FIELD& editedField : fields )
849 {
850 if( editedField.GetName() == existingField.GetName() )
851 {
852 found = true;
853 break;
854 }
855 }
856
857 if( !found )
858 {
859 m_grid->ClearSelection();
860 m_fields->erase( m_fields->begin() + ii );
861
862 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, ii, 1 );
863 m_grid->ProcessTableMessage( msg );
864 }
865 }
866
867 OnModify();
868 m_grid->ForceRefresh();
869}
870
871
873{
874 int idx = m_FootprintFilterListBox->HitTest( event.GetPosition() );
875 wxCommandEvent dummy;
876
877 if( idx >= 0 )
879 else
881}
882
883
885{
886 // Running the Footprint Browser gums up the works and causes the automatic cancel
887 // stuff to no longer work. So we do it here ourselves.
888 EndQuasiModal( wxID_CANCEL );
889}
890
891
893{
894 wxString filterLine;
895 WX_TEXT_ENTRY_DIALOG dlg( this, _( "Filter:" ), _( "Add Footprint Filter" ), filterLine );
896
897 if( dlg.ShowModal() == wxID_CANCEL || dlg.GetValue().IsEmpty() )
898 return;
899
900 filterLine = dlg.GetValue();
901 filterLine.Replace( wxT( " " ), wxT( "_" ) );
902
903 // duplicate filters do no harm, so don't be a nanny.
904 m_FootprintFilterListBox->Append( filterLine );
905 m_FootprintFilterListBox->SetSelection( (int) m_FootprintFilterListBox->GetCount() - 1 );
906
907 OnModify();
908}
909
910
912{
913 wxArrayInt selections;
914 int n = m_FootprintFilterListBox->GetSelections( selections );
915
916 if( n > 0 )
917 {
918 // Just edit the first one
919 int idx = selections[0];
920 wxString filter = m_FootprintFilterListBox->GetString( idx );
921
922 WX_TEXT_ENTRY_DIALOG dlg( this, _( "Filter:" ), _( "Edit Footprint Filter" ), filter );
923
924 if( dlg.ShowModal() == wxID_OK && !dlg.GetValue().IsEmpty() )
925 {
926 m_FootprintFilterListBox->SetString( (unsigned) idx, dlg.GetValue() );
927 OnModify();
928 }
929 }
930}
931
932
934{
935 // Account for scroll bars
937
938 m_grid->AutoSizeColumn( FDC_NAME );
939 m_grid->SetColSize( FDC_NAME, std::max( 72, m_grid->GetColSize( FDC_NAME ) ) );
940
941 int fixedColsWidth = m_grid->GetColSize( FDC_NAME );
942
943 for( int i = 2; i < m_grid->GetNumberCols(); i++ )
944 fixedColsWidth += m_grid->GetColSize( i );
945
946 m_grid->SetColSize( FDC_VALUE, std::max( 120, width - fixedColsWidth ) );
947}
948
949
950void DIALOG_LIB_SYMBOL_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
951{
952 m_OptionPartsInterchangeable->Enable( m_SelNumberOfUnits->GetValue() > 1 );
954
955 if( m_grid->IsCellEditControlShown() )
956 {
957 int row = m_grid->GetGridCursorRow();
958 int col = m_grid->GetGridCursorCol();
959
960 if( row == m_fields->GetFieldRow( FIELD_T::VALUE ) && col == FDC_VALUE && m_OptionPower->IsChecked() )
961 {
962 wxGridCellEditor* editor = m_grid->GetCellEditor( row, col );
963 m_SymbolNameCtrl->ChangeValue( editor->GetValue() );
964 editor->DecRef();
965 }
966 }
967
968 // Handle shown columns changes
969 std::bitset<64> shownColumns = m_grid->GetShownColumns();
970
971 if( shownColumns != m_shownColumns )
972 {
973 m_shownColumns = shownColumns;
974
975 if( !m_grid->IsCellEditControlShown() )
977 }
978
979 // Handle a delayed focus. The delay allows us to:
980 // a) change focus when the error was triggered from within a killFocus handler
981 // b) show the correct notebook page in the background before the error dialog comes up
982 // when triggered from an OK or a notebook page change
983
984 if( m_delayedFocusPage >= 0 && m_NoteBook->GetSelection() != m_delayedFocusPage )
985 {
986 m_NoteBook->ChangeSelection( (unsigned) m_delayedFocusPage );
988 }
989
990 if( !m_delayedErrorMessage.IsEmpty() )
991 {
992 // We will re-enter this routine when the error dialog is displayed, so make
993 // sure we don't keep putting up more dialogs.
994 wxString msg = m_delayedErrorMessage;
995 m_delayedErrorMessage = wxEmptyString;
996
997 // Do not use DisplayErrorMessage(); it screws up window order on Mac
998 DisplayError( nullptr, msg );
999 }
1000
1001 if( m_delayedFocusCtrl )
1002 {
1003 m_delayedFocusCtrl->SetFocus();
1004
1005 if( wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_delayedFocusCtrl ) )
1006 textEntry->SelectAll();
1007
1008 m_delayedFocusCtrl = nullptr;
1009 }
1010 else if( m_delayedFocusGrid )
1011 {
1012 m_delayedFocusGrid->SetFocus();
1015
1016 m_delayedFocusGrid->EnableCellEditControl( true );
1017 m_delayedFocusGrid->ShowCellEditControl();
1018
1019 m_delayedFocusGrid = nullptr;
1020 m_delayedFocusRow = -1;
1022 }
1023}
1024
1025
1027{
1028 auto new_size = event.GetSize();
1029
1030 if( new_size != m_size )
1031 {
1032 m_size = new_size;
1033
1035 }
1036
1037 // Always propagate a wxSizeEvent:
1038 event.Skip();
1039}
1040
1041
1043{
1044 bSizerLowerBasicPanel->Show( !aIsAlias );
1045 m_inheritanceSelectCombo->Enable( aIsAlias );
1046 m_inheritsStaticText->Enable( aIsAlias );
1047 m_grid->ForceRefresh();
1048}
1049
1050
1052{
1053 if( m_OptionPower->IsChecked() )
1054 {
1055 m_excludeFromSimCheckBox->SetValue( true );
1056 m_excludeFromBomCheckBox->SetValue( true );
1057 m_excludeFromBoardCheckBox->SetValue( true );
1058 m_excludeFromBomCheckBox->Enable( false );
1059 m_excludeFromBoardCheckBox->Enable( false );
1060 m_excludeFromSimCheckBox->Enable( false );
1061 m_spiceFieldsButton->Show( false );
1062 m_OptionLocalPower->Enable( true );
1063 }
1064 else
1065 {
1066 m_excludeFromBomCheckBox->Enable( true );
1067 m_excludeFromBoardCheckBox->Enable( true );
1068 m_excludeFromSimCheckBox->Enable( true );
1069 m_spiceFieldsButton->Show( true );
1070 m_OptionLocalPower->Enable( false );
1071 }
1072
1073 OnModify();
1074}
1075
1076
1077void DIALOG_LIB_SYMBOL_PROPERTIES::OnText( wxCommandEvent& event )
1078{
1079 OnModify();
1080}
1081
1082
1083void DIALOG_LIB_SYMBOL_PROPERTIES::OnCombobox( wxCommandEvent& event )
1084{
1085 OnModify();
1086}
1087
1088
1089void DIALOG_LIB_SYMBOL_PROPERTIES::OnCheckBox( wxCommandEvent& event )
1090{
1091 OnModify();
1092}
1093
1094
1096{
1097 OnModify();
1098}
1099
1100
1102{
1103 OnModify();
1104}
1105
1106
1108{
1110 aEvent.Veto();
1111}
1112
1113
1115{
1116 wxArrayInt selections;
1117 m_listAvailablePins->GetSelections( selections );
1118
1119 if( !selections.empty() )
1120 {
1121 m_listJumperPinGroups->Freeze();
1122 m_listAvailablePins->Freeze();
1123
1124 wxString group;
1125 unsigned i = 0;
1126
1127 for( int idx : selections )
1128 {
1129 group << m_listAvailablePins->GetString( idx );
1130
1131 if( ++i < selections.Count() )
1132 group << ", ";
1133 }
1134
1135 for( int idx = (int) selections.size() - 1; idx >= 0; --idx )
1136 m_listAvailablePins->Delete( selections[idx] );
1137
1138 m_listJumperPinGroups->AppendString( group );
1139
1140 m_listJumperPinGroups->Thaw();
1141 m_listAvailablePins->Thaw();
1142 }
1143}
1144
1145
1147{
1148 wxArrayInt selections;
1149 m_listJumperPinGroups->GetSelections( selections );
1150
1151 if( !selections.empty() )
1152 {
1153 m_listJumperPinGroups->Freeze();
1154 m_listAvailablePins->Freeze();
1155
1156 for( int idx : selections )
1157 {
1158 wxStringTokenizer tokenizer( m_listJumperPinGroups->GetString( idx ), ", " );
1159
1160 while( tokenizer.HasMoreTokens() )
1161 {
1162 if( wxString token = tokenizer.GetNextToken(); !token.IsEmpty() )
1163 m_listAvailablePins->AppendString( token );
1164 }
1165 }
1166
1167 for( int idx = (int) selections.size() - 1; idx >= 0; --idx )
1168 m_listJumperPinGroups->Delete( selections[idx] );
1169
1170 m_listJumperPinGroups->Thaw();
1171 m_listAvailablePins->Thaw();
1172 }
1173}
1174
1175
1177{
1178 wxArrayInt selections;
1179 int n = m_listJumperPinGroups->GetSelections( selections );
1180 m_btnRemoveJumperPinGroup->Enable( n > 0 );
1181}
1182
1183
1185{
1186 wxArrayInt selections;
1187 int n = m_listAvailablePins->GetSelections( selections );
1188 m_btnCreateJumperPinGroup->Enable( n > 0 );
1189}
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
Class DIALOG_LIB_SYMBOL_PROPERTIES_BASE.
void OnSymbolNameKillFocus(wxFocusEvent &event) override
std::unique_ptr< LISTBOX_TRICKS > m_fpFilterTricks
void OnPageChanging(wxNotebookEvent &event) override
void OnSpinCtrlText(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 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 OnMoveUp(wxCommandEvent &event) override
void OnAvailablePinsClick(wxCommandEvent &event) override
void OnText(wxCommandEvent &event) override
void OnMoveDown(wxCommandEvent &event) override
void OnAddFootprintFilter(wxCommandEvent &event) override
void OnCheckBox(wxCommandEvent &event) override
void OnSymbolNameText(wxCommandEvent &event) override
void onPowerCheckBox(wxCommandEvent &aEvent) override
void OnBtnCreateJumperPinGroup(wxCommandEvent &event) override
void OnAddField(wxCommandEvent &event) override
void OnEditSpiceModel(wxCommandEvent &event) override
void OnSpinCtrl(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 OnModify()
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
Definition: dialog_shim.h:254
int ShowModal() override
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition: eda_text.cpp:533
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:386
bool IsInherited(size_t aRow) const
SCH_FIELD * GetField(FIELD_T aFieldId)
int GetNumberRows() override
void push_back(const SCH_FIELD &field)
int GetMandatoryRowCount() const
bool EraseRow(size_t row)
void SetFieldInherited(size_t aRow, const SCH_FIELD &aParent)
int GetFieldRow(FIELD_T aFieldId)
const SCH_FIELD & ParentField(size_t row) const
void AddInheritedField(const SCH_FIELD &aParent)
void emplace_back(const SCH_FIELD &field)
void SwapRows(size_t a, size_t b)
A text control validator used for validating the text allowed in fields.
Definition: validators.h:142
Define a library symbol object.
Definition: lib_symbol.h:85
wxString GetKeyWords() const override
Definition: lib_symbol.h:183
void SetGlobalPower()
Definition: lib_symbol.cpp:475
std::vector< SCH_PIN * > GetPins(int aUnit, int aBodyStyle) const
Return a list of pin object pointers from the draw item list.
Definition: lib_symbol.cpp:799
bool IsPower() const override
Definition: lib_symbol.cpp:469
void SetUnitCount(int aCount, bool aDuplicateDrawItems=true)
Set the units per symbol count.
bool UnitsLocked() const
Check whether symbol units are interchangeable.
Definition: lib_symbol.h:289
bool IsRoot() const override
For symbols derived from other symbols, IsRoot() indicates no derivation.
Definition: lib_symbol.h:206
bool IsDerived() const
Definition: lib_symbol.h:207
void SetDuplicatePinNumbersAreJumpers(bool aEnabled)
Definition: lib_symbol.h:573
void SetFields(const std::vector< SCH_FIELD > &aFieldsList)
Overwrite all the existing fields in this symbol with fields supplied in aFieldsList.
Definition: lib_symbol.cpp:999
bool HasAlternateBodyStyle() const override
Test if symbol has more than one body conversion type (DeMorgan).
void LockUnits(bool aLockUnits)
Set interchangeable the property for symbol units.
Definition: lib_symbol.h:283
void SetParent(LIB_SYMBOL *aParent=nullptr)
Definition: lib_symbol.cpp:335
wxString GetName() const override
Definition: lib_symbol.h:149
void SetKeyWords(const wxString &aKeyWords)
Definition: lib_symbol.h:181
SCH_FIELD & GetValueField()
Return reference to the value field.
Definition: lib_symbol.h:334
bool IsLocalPower() const override
Definition: lib_symbol.cpp:423
wxArrayString GetFPFilters() const
Definition: lib_symbol.h:218
void SetLocalPower()
Definition: lib_symbol.cpp:439
void SetFPFilters(const wxArrayString &aFilters)
Definition: lib_symbol.h:216
void CopyFields(std::vector< SCH_FIELD > &aList)
Create a copy of the SCH_FIELDs, sorted in ordinal order.
void SetHasAlternateBodyStyle(bool aHasAlternate, bool aDuplicatePins=true)
Set or clear the alternate body style (DeMorgan) for the symbol.
int GetUnitCount() const override
bool GetDuplicatePinNumbersAreJumpers() const
Definition: lib_symbol.h:572
LIB_SYMBOL_REF & GetParent()
Definition: lib_symbol.h:118
std::vector< std::set< wxString > > & JumperPinGroups()
Each jumper pin group is a set of pin numbers that should be treated as internally connected.
Definition: lib_symbol.h:579
virtual void SetName(const wxString &aName)
Definition: lib_symbol.cpp:328
void SetNormal()
Definition: lib_symbol.cpp:503
EMBEDDED_FILES * GetLocalFiles()
bool TransferDataToWindow() override
void SetOrdinal(int aOrdinal)
Definition: sch_field.h:122
bool IsMandatory() const
Definition: sch_field.cpp:1359
VECTOR2I GetPosition() const override
Definition: sch_field.cpp:1337
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
Definition: sch_field.cpp:1117
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
Definition: sch_field.cpp:1103
void SetPosition(const VECTOR2I &aPosition) override
Definition: sch_field.cpp:1317
void SetName(const wxString &aName)
Definition: sch_field.cpp:1079
void SetText(const wxString &aText) override
Definition: sch_field.cpp:1089
void SetBitmap(const wxBitmapBundle &aBmp)
The symbol library editor main window.
void UpdateAfterSymbolProperties(wxString *aOldName=nullptr)
wxString GetCurLib() const
The nickname of the current library being edited and empty string if none.
bool GetShowDeMorgan() const
bool IsSymbolFromLegacyLibrary() const
bool IsSymbolFromSchematic() const
void SaveCopyInUndoList(const wxString &aDescription, LIB_SYMBOL *aSymbol, UNDO_REDO aUndoType=UNDO_REDO::LIBEDIT)
Create a copy of the current symbol, and save it in the undo list.
SYMBOL_EDITOR_SETTINGS * GetSettings() const
LIB_SYMBOL_LIBRARY_MANAGER & GetLibManager()
void SetShowDeMorgan(bool show)
bool SymbolNameInUse(const wxString &aName, const wxString &aLibrary)
Return true if the symbol name is already in use in the specified library.
LIB_SYMBOL * GetSymbol(const wxString &aSymbolName, const wxString &aLibrary) const
Return either an alias of a working LIB_SYMBOL copy, or alias of the original symbol if there is no w...
void GetSymbolNames(const wxString &aLibName, wxArrayString &aSymbolNames, SYMBOL_NAME_FILTER aFilter=SYMBOL_NAME_FILTER::ALL)
void SetExcludedFromBoard(bool aExcludeFromBoard) override
Set or clear exclude from board netlist flag.
Definition: symbol.h:186
virtual void SetShowPinNumbers(bool aShow)
Set or clear the pin number visibility flag.
Definition: symbol.h:164
void SetExcludedFromSim(bool aExcludeFromSim) override
Set or clear the exclude from simulation flag.
Definition: symbol.h:170
int GetPinNameOffset() const
Definition: symbol.h:153
virtual void SetShowPinNames(bool aShow)
Set or clear the pin name visibility flag.
Definition: symbol.h:158
bool GetExcludedFromBoard() const override
Definition: symbol.h:187
void SetExcludedFromBOM(bool aExcludeFromBOM) override
Set or clear the exclude from schematic bill of materials flag.
Definition: symbol.h:180
virtual bool GetShowPinNames() const
Definition: symbol.h:159
void SetPinNameOffset(int aOffset)
Set the offset in mils of the pin name text from the pin symbol.
Definition: symbol.h:152
virtual bool GetShowPinNumbers() const
Definition: symbol.h:165
bool GetExcludedFromBOM() const override
Definition: symbol.h:181
bool GetExcludedFromSim() const override
Definition: symbol.h:175
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.
virtual long long int GetValue()
Return the current value in Internal Units.
void Enable(bool aEnable)
Enable/disable the label, widget and units label.
virtual void ChangeValue(int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion WITHOUT trigger...
void ShowHideColumns(const wxString &shownColumns)
Show/hide the grid columns based on a tokenized string of shown column indexes.
Definition: wx_grid.cpp:494
void OnMoveRowUp(const std::function< void(int row)> &aMover)
Definition: wx_grid.cpp:766
void SetTable(wxGridTableBase *table, bool aTakeOwnership=false)
Hide wxGrid's SetTable() method with one which doesn't mess up the grid column widths when setting th...
Definition: wx_grid.cpp:273
void DestroyTable(wxGridTableBase *aTable)
Work-around for a bug in wxGrid which crashes when deleting the table if the cell edit control was no...
Definition: wx_grid.cpp:450
void OnMoveRowDown(const std::function< void(int row)> &aMover)
Definition: wx_grid.cpp:799
void OnDeleteRows(const std::function< void(int row)> &aDeleter)
Handles a row deletion event.
Definition: wx_grid.cpp:704
wxString GetShownColumnsAsString()
Get a tokenized string containing the shown column indexes.
Definition: wx_grid.cpp:464
void OnAddRow(const std::function< std::pair< int, int >()> &aAdder)
Definition: wx_grid.cpp:684
std::bitset< 64 > GetShownColumns()
Definition: wx_grid.cpp:483
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:632
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:258
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)
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
Definition: string_utils.h:54
constexpr int MilsToIU(int mils) const
Definition: base_units.h:97
Hold a name of a symbol's field, field value, and default visibility.
wxString GetUserFieldName(int aFieldNdx, bool aTranslateForHI)
#define DO_TRANSLATE
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