KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_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 <memory>
27
28#include <bitmaps.h>
29#include <wx/tooltip.h>
30#include <grid_tricks.h>
31#include <confirm.h>
32#include <kiface_base.h>
33#include <pin_numbers.h>
34#include <string_utils.h>
35#include <kiplatform/ui.h>
40#include <sch_collectors.h>
41#include <symbol_library.h>
42#include <fields_grid_table.h>
43#include <sch_edit_frame.h>
44#include <sch_reference_list.h>
45#include <schematic.h>
46#include <sch_commit.h>
47#include <tool/tool_manager.h>
48#include <tool/actions.h>
49
50#include <dialog_sim_model.h>
51
52
53wxDEFINE_EVENT( SYMBOL_DELAY_FOCUS, wxCommandEvent );
54wxDEFINE_EVENT( SYMBOL_DELAY_SELECTION, wxCommandEvent );
55
66
67
68class SCH_PIN_TABLE_DATA_MODEL : public WX_GRID_TABLE_BASE, public std::vector<SCH_PIN>
69{
70public:
72 m_readOnlyAttr( nullptr ),
73 m_typeAttr( nullptr ),
74 m_shapeAttr( nullptr )
75 {
76 }
77
79 {
80 for( wxGridCellAttr* attr : m_nameAttrs )
81 attr->DecRef();
82
83 m_readOnlyAttr->DecRef();
84 m_typeAttr->DecRef();
85 m_shapeAttr->DecRef();
86 }
87
89 {
90 for( wxGridCellAttr* attr : m_nameAttrs )
91 attr->DecRef();
92
93 m_nameAttrs.clear();
94
95 if( m_readOnlyAttr )
96 m_readOnlyAttr->DecRef();
97
98 m_readOnlyAttr = new wxGridCellAttr;
99 m_readOnlyAttr->SetReadOnly( true );
100
101 for( const SCH_PIN& pin : *this )
102 {
103 SCH_PIN* lib_pin = pin.GetLibPin();
104 wxGridCellAttr* attr = nullptr;
105
106 if( lib_pin->GetAlternates().empty() )
107 {
108 attr = new wxGridCellAttr;
109 attr->SetReadOnly( true );
110 attr->SetBackgroundColour( KIPLATFORM::UI::GetDialogBGColour() );
111 }
112 else
113 {
114 wxArrayString choices;
115 choices.push_back( lib_pin->GetName() );
116
117 for( const std::pair<const wxString, SCH_PIN::ALT>& alt : lib_pin->GetAlternates() )
118 choices.push_back( alt.first );
119
120 attr = new wxGridCellAttr();
121 attr->SetEditor( new GRID_CELL_COMBOBOX( choices ) );
122 }
123
124 m_nameAttrs.push_back( attr );
125 }
126
127 if( m_typeAttr )
128 m_typeAttr->DecRef();
129
130 m_typeAttr = new wxGridCellAttr;
132 m_typeAttr->SetReadOnly( true );
133
134 if( m_shapeAttr )
135 m_shapeAttr->DecRef();
136
137 m_shapeAttr = new wxGridCellAttr;
139 m_shapeAttr->SetReadOnly( true );
140 }
141
142 int GetNumberRows() override { return (int) size(); }
143 int GetNumberCols() override { return COL_COUNT; }
144
145 wxString GetColLabelValue( int aCol ) override
146 {
147 switch( aCol )
148 {
149 case COL_NUMBER: return _( "Number" );
150 case COL_BASE_NAME: return _( "Base Name" );
151 case COL_ALT_NAME: return _( "Alternate Assignment" );
152 case COL_TYPE: return _( "Electrical Type" );
153 case COL_SHAPE: return _( "Graphic Style" );
154 default: wxFAIL; return wxEmptyString;
155 }
156 }
157
158 bool IsEmptyCell( int row, int col ) override
159 {
160 return false; // don't allow adjacent cell overflow, even if we are actually empty
161 }
162
163 bool CanSetValueAs( int aRow, int aCol, const wxString& aTypeName ) override
164 {
165 // Don't accept random values; must use the popup to change to a known alternate
166 return false;
167 }
168
169 wxString GetValue( int aRow, int aCol ) override
170 {
171 return GetValue( at( aRow ), aCol );
172 }
173
174 static wxString GetValue( const SCH_PIN& aPin, int aCol )
175 {
176 if( aCol == COL_ALT_NAME )
177 {
178 if( aPin.GetLibPin()->GetAlternates().empty() )
179 return wxEmptyString;
180 else if( aPin.GetAlt().IsEmpty() )
181 return aPin.GetName();
182 else
183 return aPin.GetAlt();
184 }
185
186 switch( aCol )
187 {
188 case COL_NUMBER: return aPin.GetNumber();
189 case COL_BASE_NAME: return aPin.GetLibPin()->GetName();
190 case COL_TYPE: return PinTypeNames()[static_cast<int>( aPin.GetType() )];
191 case COL_SHAPE: return PinShapeNames()[static_cast<int>( aPin.GetShape() )];
192 default: wxFAIL; return wxEmptyString;
193 }
194 }
195
196 wxGridCellAttr* GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind ) override
197 {
198 switch( aCol )
199 {
200 case COL_NUMBER:
201 case COL_BASE_NAME:
202 m_readOnlyAttr->IncRef();
203 return enhanceAttr( m_readOnlyAttr, aRow, aCol, aKind );
204
205 case COL_ALT_NAME:
206 m_nameAttrs[ aRow ]->IncRef();
207 return enhanceAttr( m_nameAttrs[ aRow ], aRow, aCol, aKind );
208
209 case COL_TYPE:
210 m_typeAttr->IncRef();
211 return enhanceAttr( m_typeAttr, aRow, aCol, aKind );
212
213 case COL_SHAPE:
214 m_shapeAttr->IncRef();
215 return enhanceAttr( m_shapeAttr, aRow, aCol, aKind );
216
217 default:
218 wxFAIL;
219 return nullptr;
220 }
221 }
222
223 void SetValue( int aRow, int aCol, const wxString &aValue ) override
224 {
225 switch( aCol )
226 {
227 case COL_ALT_NAME:
228 if( aValue == at( aRow ).GetLibPin()->GetName() )
229 at( aRow ).SetAlt( wxEmptyString );
230 else
231 at( aRow ).SetAlt( aValue );
232 break;
233
234 case COL_NUMBER:
235 case COL_BASE_NAME:
236 case COL_TYPE:
237 case COL_SHAPE:
238 // Read-only.
239 break;
240
241 default:
242 wxFAIL;
243 break;
244 }
245 }
246
247 static bool compare( const SCH_PIN& lhs, const SCH_PIN& rhs, int sortCol, bool ascending )
248 {
249 wxString lhStr = GetValue( lhs, sortCol );
250 wxString rhStr = GetValue( rhs, sortCol );
251
252 if( lhStr == rhStr )
253 {
254 // Secondary sort key is always COL_NUMBER
255 sortCol = COL_NUMBER;
256 lhStr = GetValue( lhs, sortCol );
257 rhStr = GetValue( rhs, sortCol );
258 }
259
260 bool res;
261
262 // N.B. To meet the iterator sort conditions, we cannot simply invert the truth
263 // to get the opposite sort. i.e. ~(a<b) != (a>b)
264 auto cmp = [ ascending ]( const auto a, const auto b )
265 {
266 if( ascending )
267 return a < b;
268 else
269 return b < a;
270 };
271
272 switch( sortCol )
273 {
274 case COL_NUMBER:
275 case COL_BASE_NAME:
276 case COL_ALT_NAME:
277 res = cmp( PIN_NUMBERS::Compare( lhStr, rhStr ), 0 );
278 break;
279 case COL_TYPE:
280 case COL_SHAPE:
281 res = cmp( lhStr.CmpNoCase( rhStr ), 0 );
282 break;
283 default:
284 res = cmp( StrNumCmp( lhStr, rhStr ), 0 );
285 break;
286 }
287
288 return res;
289 }
290
291 void SortRows( int aSortCol, bool ascending )
292 {
293 std::sort( begin(), end(),
294 [ aSortCol, ascending ]( const SCH_PIN& lhs, const SCH_PIN& rhs ) -> bool
295 {
296 return compare( lhs, rhs, aSortCol, ascending );
297 } );
298 }
299
300protected:
301 std::vector<wxGridCellAttr*> m_nameAttrs;
302 wxGridCellAttr* m_readOnlyAttr;
303 wxGridCellAttr* m_typeAttr;
304 wxGridCellAttr* m_shapeAttr;
305};
306
307
310 m_symbol( nullptr ),
311 m_part( nullptr ),
312 m_fieldsSize( 0, 0 ),
315 m_editorShown( false ),
316 m_fields( nullptr ),
317 m_dataModel( nullptr )
318{
319 m_symbol = aSymbol;
320 m_part = m_symbol->GetLibSymbolRef().get();
321
322 // GetLibSymbolRef() now points to the cached part in the schematic, which should always be
323 // there for usual cases, but can be null when opening old schematics not storing the part
324 // so we need to handle m_part == nullptr
325 // wxASSERT( m_part );
326
327 m_fields = new FIELDS_GRID_TABLE( this, aParent, m_fieldsGrid, m_symbol );
328
329 m_fieldsGrid->SetTable( m_fields );
330 m_fieldsGrid->PushEventHandler( new FIELDS_GRID_TRICKS( m_fieldsGrid, this,
331 { &aParent->Schematic(), m_part },
332 [&]( wxCommandEvent& aEvent )
333 {
334 OnAddField( aEvent );
335 } ) );
336 m_fieldsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
337
338 // Show/hide columns according to user's preference
339 if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
340 {
341 m_fieldsGrid->ShowHideColumns( cfg->m_Appearance.edit_symbol_visible_columns );
342 m_shownColumns = m_fieldsGrid->GetShownColumns();
343 }
344
345 if( m_part && m_part->IsMultiBodyStyle() )
346 {
347 // Multiple body styles are a superclass of alternate pin assignments, so don't allow
348 // free-form alternate assignments as well. (We won't know how to map the alternates
349 // back and forth when the body style is changed.)
350 m_pinTablePage->Disable();
351 m_pinTablePage->SetToolTip( _( "Alternate pin assignments are not available for symbols with multiple "
352 "body styles." ) );
353 }
354 else
355 {
357
358 // Make a copy of the pins for editing
359 for( const std::unique_ptr<SCH_PIN>& pin : m_symbol->GetRawPins() )
360 m_dataModel->push_back( *pin );
361
362 m_dataModel->SortRows( COL_NUMBER, true );
363 m_dataModel->BuildAttrs();
364
365 m_pinGrid->SetTable( m_dataModel );
366 }
367
368 if( m_part && m_part->IsPower() )
369 m_spiceFieldsButton->Hide();
370
371 m_pinGrid->PushEventHandler( new GRID_TRICKS( m_pinGrid ) );
372 m_pinGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
373
374 wxFont infoFont = KIUI::GetSmallInfoFont( this );
375 m_libraryIDLabel->SetFont( infoFont );
376 m_tcLibraryID->SetFont( infoFont );
377 m_tcLibraryID->SetBackgroundColour( KIPLATFORM::UI::GetDialogBGColour() );
378
379 wxToolTip::Enable( true );
381
382 // Configure button logos
387
388 // wxFormBuilder doesn't include this event...
389 m_fieldsGrid->Bind( wxEVT_GRID_CELL_CHANGING, &DIALOG_SYMBOL_PROPERTIES::OnGridCellChanging, this );
390 m_pinGrid->Bind( wxEVT_GRID_COL_SORT, &DIALOG_SYMBOL_PROPERTIES::OnPinTableColSort, this );
391 Bind( SYMBOL_DELAY_FOCUS, &DIALOG_SYMBOL_PROPERTIES::HandleDelayedFocus, this );
392 Bind( SYMBOL_DELAY_SELECTION, &DIALOG_SYMBOL_PROPERTIES::HandleDelayedSelection, this );
393
394 wxCommandEvent* evt = new wxCommandEvent( SYMBOL_DELAY_SELECTION );
395 evt->SetClientData( new VECTOR2I( 0, FDC_VALUE ) );
396 QueueEvent( evt );
397 evt = new wxCommandEvent( SYMBOL_DELAY_FOCUS );
398 evt->SetClientData( new VECTOR2I( 0, FDC_VALUE ) );
399 QueueEvent( evt );
400
402}
403
404
406{
407 if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
408 {
409 cfg->m_Appearance.edit_symbol_visible_columns = m_fieldsGrid->GetShownColumnsAsString();
410 cfg->m_Appearance.edit_symbol_width = GetSize().x;
411 cfg->m_Appearance.edit_symbol_height = GetSize().y;
412 }
413
414 // Prevents crash bug in wxGrid's d'tor
415 m_fieldsGrid->DestroyTable( m_fields );
416
417 if( m_dataModel )
418 m_pinGrid->DestroyTable( m_dataModel );
419
420 m_fieldsGrid->Unbind( wxEVT_GRID_CELL_CHANGING, &DIALOG_SYMBOL_PROPERTIES::OnGridCellChanging, this );
421 m_pinGrid->Unbind( wxEVT_GRID_COL_SORT, &DIALOG_SYMBOL_PROPERTIES::OnPinTableColSort, this );
422 Unbind( SYMBOL_DELAY_FOCUS, &DIALOG_SYMBOL_PROPERTIES::HandleDelayedFocus, this );
423 Unbind( SYMBOL_DELAY_SELECTION, &DIALOG_SYMBOL_PROPERTIES::HandleDelayedSelection, this );
424
425 // Delete the GRID_TRICKS.
426 m_fieldsGrid->PopEventHandler( true );
427 m_pinGrid->PopEventHandler( true );
428}
429
430
432{
433 return dynamic_cast<SCH_EDIT_FRAME*>( wxDialog::GetParent() );
434}
435
436
438{
439 if( !wxDialog::TransferDataToWindow() )
440 return false;
441
442 std::set<wxString> defined;
443
444 // Push a copy of each field into m_updateFields
445 for( SCH_FIELD& srcField : m_symbol->GetFields() )
446 {
447 SCH_FIELD field( srcField );
448
449 // change offset to be symbol-relative
450 field.Offset( -m_symbol->GetPosition() );
451
452 field.SetText( m_symbol->Schematic()->ConvertKIIDsToRefs( field.GetText() ) );
453
454 defined.insert( field.GetName() );
455 m_fields->push_back( field );
456 }
457
458 // Add in any template fieldnames not yet defined:
459 for( const TEMPLATE_FIELDNAME& templateFieldname :
460 GetParent()->Schematic().Settings().m_TemplateFieldNames.GetTemplateFieldNames() )
461 {
462 if( defined.count( templateFieldname.m_Name ) <= 0 )
463 {
464 SCH_FIELD field( m_symbol, FIELD_T::USER, templateFieldname.m_Name );
465 field.SetVisible( templateFieldname.m_Visible );
466 m_fields->push_back( field );
467 }
468 }
469
470 // notify the grid
471 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_fields->GetNumberRows() );
472 m_fieldsGrid->ProcessTableMessage( msg );
474
475 // If a multi-unit symbol, set up the unit selector and interchangeable checkbox.
476 if( m_symbol->IsMultiUnit() )
477 {
478 // Ensure symbol unit is the currently selected unit (mandatory in complex hierarchies)
479 // from the current sheet path, because it can be modified by previous calculations
480 m_symbol->SetUnit( m_symbol->GetUnitSelection( &GetParent()->GetCurrentSheet() ) );
481
482 for( int ii = 1; ii <= m_symbol->GetUnitCount(); ii++ )
483 m_unitChoice->Append( m_symbol->GetUnitDisplayName( ii, false ) );
484
485 if( m_symbol->GetUnit() <= ( int )m_unitChoice->GetCount() )
486 m_unitChoice->SetSelection( m_symbol->GetUnit() - 1 );
487 }
488 else
489 {
490 m_unitLabel->Enable( false );
491 m_unitChoice->Enable( false );
492 }
493
494 if( m_part && m_part->IsMultiBodyStyle() )
495 {
496 for( int ii = 0; ii < m_part->GetBodyStyleCount(); ii++ )
497 m_bodyStyleChoice->Append( m_part->GetBodyStyleNames()[ii] );
498
499 if( m_symbol->GetBodyStyle() <= (int) m_bodyStyleChoice->GetCount() )
500 m_bodyStyleChoice->SetSelection( m_symbol->GetBodyStyle() - 1 );
501 }
502 else
503 {
504 m_bodyStyle->Enable( false );
505 m_bodyStyleChoice->Enable( false );
506 }
507
508 // Set the symbol orientation and mirroring.
509 int orientation = m_symbol->GetOrientation() & ~( SYM_MIRROR_X | SYM_MIRROR_Y );
510
511 switch( orientation )
512 {
513 default:
514 case SYM_ORIENT_0: m_orientationCtrl->SetSelection( 0 ); break;
515 case SYM_ORIENT_90: m_orientationCtrl->SetSelection( 1 ); break;
516 case SYM_ORIENT_270: m_orientationCtrl->SetSelection( 2 ); break;
517 case SYM_ORIENT_180: m_orientationCtrl->SetSelection( 3 ); break;
518 }
519
520 int mirror = m_symbol->GetOrientation() & ( SYM_MIRROR_X | SYM_MIRROR_Y );
521
522 switch( mirror )
523 {
524 default: m_mirrorCtrl->SetSelection( 0 ) ; break;
525 case SYM_MIRROR_X: m_mirrorCtrl->SetSelection( 1 ); break;
526 case SYM_MIRROR_Y: m_mirrorCtrl->SetSelection( 2 ); break;
527 }
528
529 m_cbExcludeFromSim->SetValue( m_symbol->GetExcludedFromSim() );
530 m_cbExcludeFromBom->SetValue( m_symbol->GetExcludedFromBOM() );
531 m_cbExcludeFromBoard->SetValue( m_symbol->GetExcludedFromBoard() );
532 m_cbDNP->SetValue( m_symbol->GetDNP() );
533
534 if( m_part )
535 {
536 m_ShowPinNumButt->SetValue( m_part->GetShowPinNumbers() );
537 m_ShowPinNameButt->SetValue( m_part->GetShowPinNames() );
538 }
539
540 // Set the symbol's library name.
541 m_tcLibraryID->SetValue( UnescapeString( m_symbol->GetLibId().Format() ) );
542
543 Layout();
544 m_fieldsGrid->Layout();
545 wxSafeYield();
546
547 return true;
548}
549
550
552{
553 if( !m_fieldsGrid->CommitPendingChanges() )
554 return;
555
556 m_fieldsGrid->ClearSelection();
557
558 std::vector<SCH_FIELD> fields;
559
560 for( const SCH_FIELD& field : *m_fields )
561 fields.emplace_back( field );
562
563 DIALOG_SIM_MODEL dialog( this, m_parentFrame, *m_symbol, fields );
564
565 if( dialog.ShowModal() != wxID_OK )
566 return;
567
568 // Add in any new fields
569 for( const SCH_FIELD& editedField : fields )
570 {
571 bool found = false;
572
573 for( SCH_FIELD& existingField : *m_fields )
574 {
575 if( existingField.GetName() == editedField.GetName() )
576 {
577 found = true;
578 existingField.SetText( editedField.GetText() );
579 break;
580 }
581 }
582
583 if( !found )
584 {
585 m_fields->emplace_back( editedField );
586 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
587 m_fieldsGrid->ProcessTableMessage( msg );
588 }
589 }
590
591 // Remove any deleted fields
592 for( int ii = (int) m_fields->size() - 1; ii >= 0; --ii )
593 {
594 SCH_FIELD& existingField = m_fields->at( ii );
595 bool found = false;
596
597 for( SCH_FIELD& editedField : fields )
598 {
599 if( editedField.GetName() == existingField.GetName() )
600 {
601 found = true;
602 break;
603 }
604 }
605
606 if( !found )
607 {
608 m_fieldsGrid->ClearSelection();
609 m_fields->erase( m_fields->begin() + ii );
610
611 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, ii, 1 );
612 m_fieldsGrid->ProcessTableMessage( msg );
613 }
614 }
615
616 OnModify();
617 m_fieldsGrid->ForceRefresh();
618}
619
620
622{
623 // Running the Footprint Browser gums up the works and causes the automatic cancel
624 // stuff to no longer work. So we do it here ourselves.
625 EndQuasiModal( wxID_CANCEL );
626}
627
628
630{
631 LIB_ID id;
632
633 if( !m_fieldsGrid->CommitPendingChanges() || !m_fieldsGrid->Validate() )
634 return false;
635
636 // Check for missing field names.
637 for( size_t i = 0; i < m_fields->size(); ++i )
638 {
639 SCH_FIELD& field = m_fields->at( i );
640
641 if( field.IsMandatory() )
642 continue;
643
644 wxString fieldName = field.GetName( false );
645
646 if( fieldName.IsEmpty() )
647 {
648 DisplayErrorMessage( this, _( "Fields must have a name." ) );
649
650 wxCommandEvent *evt = new wxCommandEvent( SYMBOL_DELAY_FOCUS );
651 evt->SetClientData( new VECTOR2I( i, FDC_VALUE ) );
652 QueueEvent( evt );
653
654 return false;
655 }
656 }
657
658 return true;
659}
660
661
663{
664 if( !wxDialog::TransferDataFromWindow() ) // Calls our Validate() method.
665 return false;
666
667 if( !m_fieldsGrid->CommitPendingChanges() )
668 return false;
669
670 if( !m_pinGrid->CommitPendingChanges() )
671 return false;
672
673 SCH_COMMIT commit( GetParent() );
674 SCH_SCREEN* currentScreen = GetParent()->GetScreen();
675 bool replaceOnCurrentScreen;
676 wxCHECK( currentScreen, false );
677
678 // This needs to be done before the LIB_ID is changed to prevent stale library symbols in
679 // the schematic file.
680 replaceOnCurrentScreen = currentScreen->Remove( m_symbol );
681
682 // save old cmp in undo list if not already in edit, or moving ...
683 if( m_symbol->GetEditFlags() == 0 )
684 commit.Modify( m_symbol, currentScreen );
685
686 // Save current flags which could be modified by next change settings
687 EDA_ITEM_FLAGS flags = m_symbol->GetFlags();
688
689 //Set the part selection in multiple part per package
690 int unit_selection = m_unitChoice->IsEnabled() ? m_unitChoice->GetSelection() + 1 : 1;
691 m_symbol->SetUnitSelection( &GetParent()->GetCurrentSheet(), unit_selection );
692 m_symbol->SetUnit( unit_selection );
693
694 int bodyStyle_selection = m_bodyStyleChoice->IsEnabled() ? m_bodyStyleChoice->GetSelection() + 1 : 1;
695 m_symbol->SetBodyStyle( bodyStyle_selection );
696
697 switch( m_orientationCtrl->GetSelection() )
698 {
699 case 0: m_symbol->SetOrientation( SYM_ORIENT_0 ); break;
700 case 1: m_symbol->SetOrientation( SYM_ORIENT_90 ); break;
701 case 2: m_symbol->SetOrientation( SYM_ORIENT_270 ); break;
702 case 3: m_symbol->SetOrientation( SYM_ORIENT_180 ); break;
703 }
704
705 switch( m_mirrorCtrl->GetSelection() )
706 {
707 case 0: break;
708 case 1: m_symbol->SetOrientation( SYM_MIRROR_X ); break;
709 case 2: m_symbol->SetOrientation( SYM_MIRROR_Y ); break;
710 }
711
712 m_symbol->SetShowPinNames( m_ShowPinNameButt->GetValue() );
713 m_symbol->SetShowPinNumbers( m_ShowPinNumButt->GetValue() );
714
715 // Restore m_Flag modified by SetUnit() and other change settings from the dialog
716 m_symbol->ClearFlags();
717 m_symbol->SetFlags( flags );
718
719 // change all field positions from relative to absolute
720 for( SCH_FIELD& field : *m_fields )
721 {
722 field.Offset( m_symbol->GetPosition() );
723 field.SetText( m_symbol->Schematic()->ConvertRefsToKIIDs( field.GetText() ) );
724 }
725
726 SCH_FIELDS& fields = m_symbol->GetFields();
727 fields.clear();
728
729 for( SCH_FIELD& field : *m_fields )
730 {
731 const wxString& fieldName = field.GetCanonicalName();
732
733 if( fieldName.IsEmpty() && field.GetText().IsEmpty() )
734 continue;
735 else if( fieldName.IsEmpty() )
736 field.SetName( _( "untitled" ) );
737
738 fields.push_back( field );
739 }
740
741 int ordinal = 42; // Arbitrarily larger than any mandatory FIELD_T ids.
742
743 for( SCH_FIELD& field : fields )
744 {
745 if( !field.IsMandatory() )
746 field.SetOrdinal( ordinal++ );
747 }
748
749 // Reference has a specific initialization, depending on the current active sheet
750 // because for a given symbol, in a complex hierarchy, there are more than one
751 // reference.
752 m_symbol->SetRef( &GetParent()->GetCurrentSheet(), m_fields->GetField( FIELD_T::REFERENCE )->GetText() );
753
754 // Similar for Value and Footprint, except that the GUI behavior is that they are kept
755 // in sync between multiple instances.
756 m_symbol->SetValueFieldText( m_fields->GetField( FIELD_T::VALUE )->GetText() );
757 m_symbol->SetFootprintFieldText( m_fields->GetField( FIELD_T::FOOTPRINT )->GetText() );
758
759 m_symbol->SetExcludedFromSim( m_cbExcludeFromSim->IsChecked() );
760 m_symbol->SetExcludedFromBOM( m_cbExcludeFromBom->IsChecked() );
761 m_symbol->SetExcludedFromBoard( m_cbExcludeFromBoard->IsChecked() );
762 m_symbol->SetDNP( m_cbDNP->IsChecked() );
763
764 // Update any assignments
765 if( m_dataModel )
766 {
767 for( const SCH_PIN& model_pin : *m_dataModel )
768 {
769 // map from the edited copy back to the "real" pin in the symbol.
770 SCH_PIN* src_pin = m_symbol->GetPin( model_pin.GetNumber() );
771
772 if( src_pin )
773 src_pin->SetAlt( model_pin.GetAlt() );
774 }
775 }
776
777 // Keep fields other than the reference, include/exclude flags, and alternate pin assignements
778 // in sync in multi-unit parts.
779 m_symbol->SyncOtherUnits( GetParent()->GetCurrentSheet(), commit, nullptr );
780
781 if( replaceOnCurrentScreen )
782 currentScreen->Append( m_symbol );
783
784 if( !commit.Empty() )
785 commit.Push( _( "Edit Symbol Properties" ) );
786
787 return true;
788}
789
790
792{
793 wxGridCellEditor* editor = m_fieldsGrid->GetCellEditor( event.GetRow(), event.GetCol() );
794 wxControl* control = editor->GetControl();
795
796 if( control && control->GetValidator() && !control->GetValidator()->Validate( control ) )
797 {
798 event.Veto();
799 wxCommandEvent *evt = new wxCommandEvent( SYMBOL_DELAY_FOCUS );
800 evt->SetClientData( new VECTOR2I( event.GetRow(), event.GetCol() ) );
801 QueueEvent( evt );
802 }
803 else if( event.GetCol() == FDC_NAME )
804 {
805 wxString newName = event.GetString();
806
807 for( int i = 0; i < m_fieldsGrid->GetNumberRows(); ++i )
808 {
809 if( i == event.GetRow() )
810 continue;
811
812 if( newName.CmpNoCase( m_fieldsGrid->GetCellValue( i, FDC_NAME ) ) == 0 )
813 {
814 DisplayError( this, wxString::Format( _( "Field name '%s' already in use." ),
815 newName ) );
816 event.Veto();
817 wxCommandEvent *evt = new wxCommandEvent( SYMBOL_DELAY_FOCUS );
818 evt->SetClientData( new VECTOR2I( event.GetRow(), event.GetCol() ) );
819 QueueEvent( evt );
820 }
821 }
822 }
823
824 editor->DecRef();
825}
826
827
829{
830 if( m_fields->at( aEvent.GetRow() ).GetId() == FIELD_T::REFERENCE
831 && aEvent.GetCol() == FDC_VALUE )
832 {
833 wxCommandEvent* evt = new wxCommandEvent( SYMBOL_DELAY_SELECTION );
834 evt->SetClientData( new VECTOR2I( aEvent.GetRow(), aEvent.GetCol() ) );
835 QueueEvent( evt );
836 }
837
838 m_editorShown = true;
839}
840
841
843{
844 m_editorShown = false;
845}
846
847
848void DIALOG_SYMBOL_PROPERTIES::OnAddField( wxCommandEvent& event )
849{
850 m_fieldsGrid->OnAddRow(
851 [&]() -> std::pair<int, int>
852 {
854
855 newField.SetTextAngle( m_fields->GetField( FIELD_T::REFERENCE )->GetTextAngle() );
856 newField.SetVisible( false );
857
858 m_fields->push_back( newField );
859
860 // notify the grid
861 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
862 m_fieldsGrid->ProcessTableMessage( msg );
863 OnModify();
864
865 return { m_fields->size() - 1, FDC_NAME };
866 } );
867}
868
869
870void DIALOG_SYMBOL_PROPERTIES::OnDeleteField( wxCommandEvent& event )
871{
872 m_fieldsGrid->OnDeleteRows(
873 [&]( int row )
874 {
875 if( row < m_fields->GetMandatoryRowCount() )
876 {
877 DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
878 m_fields->GetMandatoryRowCount() ) );
879 return false;
880 }
881
882 return true;
883 },
884 [&]( int row )
885 {
886 m_fields->erase( m_fields->begin() + row );
887
888 // notify the grid
889 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 );
890 m_fieldsGrid->ProcessTableMessage( msg );
891 } );
892
893 OnModify();
894}
895
896
897void DIALOG_SYMBOL_PROPERTIES::OnMoveUp( wxCommandEvent& event )
898{
899 m_fieldsGrid->OnMoveRowUp(
900 [&]( int row )
901 {
902 return row > m_fields->GetMandatoryRowCount();
903 },
904 [&]( int row )
905 {
906 std::swap( *( m_fields->begin() + row ), *( m_fields->begin() + row - 1 ) );
907 m_fieldsGrid->ForceRefresh();
908 OnModify();
909 } );
910}
911
912
913void DIALOG_SYMBOL_PROPERTIES::OnMoveDown( wxCommandEvent& event )
914{
915 m_fieldsGrid->OnMoveRowDown(
916 [&]( int row )
917 {
918 return row >= m_fields->GetMandatoryRowCount();
919 },
920 [&]( int row )
921 {
922 std::swap( *( m_fields->begin() + row ), *( m_fields->begin() + row + 1 ) );
923 m_fieldsGrid->ForceRefresh();
924 OnModify();
925 } );
926}
927
928
934
935
941
942
948
949
955
956
958{
959 int row = aEvent.GetRow();
960
961 if( m_pinGrid->GetCellValue( row, COL_ALT_NAME ) == m_dataModel->GetValue( row, COL_BASE_NAME ) )
962 m_dataModel->SetValue( row, COL_ALT_NAME, wxEmptyString );
963
964 // These are just to get the cells refreshed
965 m_dataModel->SetValue( row, COL_TYPE, m_dataModel->GetValue( row, COL_TYPE ) );
966 m_dataModel->SetValue( row, COL_SHAPE, m_dataModel->GetValue( row, COL_SHAPE ) );
967
968 OnModify();
969}
970
971
973{
974 int sortCol = aEvent.GetCol();
975 bool ascending;
976
977 // This is bonkers, but wxWidgets doesn't tell us ascending/descending in the
978 // event, and if we ask it will give us pre-event info.
979 if( m_pinGrid->IsSortingBy( sortCol ) )
980 // same column; invert ascending
981 ascending = !m_pinGrid->IsSortOrderAscending();
982 else
983 // different column; start with ascending
984 ascending = true;
985
986 m_dataModel->SortRows( sortCol, ascending );
987 m_dataModel->BuildAttrs();
988}
989
990
992{
993 wxGridUpdateLocker deferRepaintsTillLeavingScope( m_fieldsGrid );
994
995 // Account for scroll bars
996 int fieldsWidth = KIPLATFORM::UI::GetUnobscuredSize( m_fieldsGrid ).x;
997
998 m_fieldsGrid->AutoSizeColumn( 0 );
999 m_fieldsGrid->SetColSize( 0, std::max( 72, m_fieldsGrid->GetColSize( 0 ) ) );
1000
1001 int fixedColsWidth = m_fieldsGrid->GetColSize( 0 );
1002
1003 for( int i = 2; i < m_fieldsGrid->GetNumberCols(); i++ )
1004 fixedColsWidth += m_fieldsGrid->GetColSize( i );
1005
1006 m_fieldsGrid->SetColSize( 1, std::max( 120, fieldsWidth - fixedColsWidth ) );
1007}
1008
1009
1011{
1012 wxGridUpdateLocker deferRepaintsTillLeavingScope( m_pinGrid );
1013
1014 // Account for scroll bars
1015 int pinTblWidth = KIPLATFORM::UI::GetUnobscuredSize( m_pinGrid ).x;
1016
1017 // Stretch the Base Name and Alternate Assignment columns to fit.
1018 for( int i = 0; i < COL_COUNT; ++i )
1019 {
1020 if( i != COL_BASE_NAME && i != COL_ALT_NAME )
1021 pinTblWidth -= m_pinGrid->GetColSize( i );
1022 }
1023
1024 if( pinTblWidth > 2 )
1025 {
1026 m_pinGrid->SetColSize( COL_BASE_NAME, pinTblWidth / 2 );
1027 m_pinGrid->SetColSize( COL_ALT_NAME, pinTblWidth / 2 );
1028 }
1029}
1030
1031
1032void DIALOG_SYMBOL_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
1033{
1034 std::bitset<64> shownColumns = m_fieldsGrid->GetShownColumns();
1035
1036 if( shownColumns != m_shownColumns )
1037 {
1038 m_shownColumns = shownColumns;
1039
1040 if( !m_fieldsGrid->IsCellEditControlShown() )
1042 }
1043}
1044
1045
1047{
1048 VECTOR2I *loc = static_cast<VECTOR2I*>( event.GetClientData() );
1049
1050 wxCHECK_RET( loc, wxT( "Missing focus cell location" ) );
1051
1052 // Handle a delayed focus
1053
1054 m_fieldsGrid->SetFocus();
1055 m_fieldsGrid->MakeCellVisible( loc->x, loc->y );
1056 m_fieldsGrid->SetGridCursor( loc->x, loc->y );
1057
1058 m_fieldsGrid->EnableCellEditControl( true );
1059 m_fieldsGrid->ShowCellEditControl();
1060
1061 delete loc;
1062}
1063
1064
1066{
1067 VECTOR2I *loc = static_cast<VECTOR2I*>( event.GetClientData() );
1068
1069 wxCHECK_RET( loc, wxT( "Missing focus cell location" ) );
1070
1071 // Handle a delayed selection
1072 wxGridCellEditor* cellEditor = m_fieldsGrid->GetCellEditor( loc->x, loc->y );
1073
1074 if( wxTextEntry* txt = dynamic_cast<wxTextEntry*>( cellEditor->GetControl() ) )
1076
1077 cellEditor->DecRef(); // we're done; must release
1078}
1079
1081{
1082 wxSize new_size = event.GetSize();
1083
1084 if( ( !m_editorShown || m_lastRequestedFieldsSize != new_size ) && m_fieldsSize != new_size )
1085 {
1086 m_fieldsSize = new_size;
1087
1089 }
1090
1091 // We store this value to check whether the dialog is changing size. This might indicate
1092 // that the user is scaling the dialog with a grid-cell-editor shown. Some editors do not
1093 // close (at least on GTK) when the user drags a dialog corner
1094 m_lastRequestedFieldsSize = new_size;
1095
1096 // Always propagate for a grid repaint (needed if the height changes, as well as width)
1097 event.Skip();
1098}
1099
1100
1102{
1103 wxSize new_size = event.GetSize();
1104
1105 if( ( !m_editorShown || m_lastRequestedPinsSize != new_size ) && m_pinsSize != new_size )
1106 {
1107 m_pinsSize = new_size;
1108
1110 }
1111
1112 // We store this value to check whether the dialog is changing size. This might indicate
1113 // that the user is scaling the dialog with a grid-cell-editor shown. Some editors do not
1114 // close (at least on GTK) when the user drags a dialog corner
1115 m_lastRequestedPinsSize = new_size;
1116
1117 // Always propagate for a grid repaint (needed if the height changes, as well as width)
1118 event.Skip();
1119}
1120
1121
1122void DIALOG_SYMBOL_PROPERTIES::OnInitDlg( wxInitDialogEvent& event )
1123{
1125
1126 // Now all widgets have the size fixed, call FinishDialogSettings
1128
1129 EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
1130
1131 if( cfg && cfg->m_Appearance.edit_symbol_width > 0 && cfg->m_Appearance.edit_symbol_height > 0 )
1133}
1134
1135
1136void DIALOG_SYMBOL_PROPERTIES::OnCheckBox( wxCommandEvent& event )
1137{
1138 OnModify();
1139}
1140
1141
1142void DIALOG_SYMBOL_PROPERTIES::OnUnitChoice( wxCommandEvent& event )
1143{
1144 if( m_dataModel )
1145 {
1146 EDA_ITEM_FLAGS flags = m_symbol->GetFlags();
1147
1148 int unit_selection = m_unitChoice->GetSelection() + 1;
1149
1150 // We need to select a new unit to build the new unit pin list
1151 // but we should not change the symbol, so the initial unit will be selected
1152 // after rebuilding the pin list
1153 int old_unit = m_symbol->GetUnit();
1154 m_symbol->SetUnit( unit_selection );
1155
1156 // Rebuild a copy of the pins of the new unit for editing
1157 m_dataModel->clear();
1158
1159 for( const std::unique_ptr<SCH_PIN>& pin : m_symbol->GetRawPins() )
1160 m_dataModel->push_back( *pin );
1161
1162 m_dataModel->SortRows( COL_NUMBER, true );
1163 m_dataModel->BuildAttrs();
1164
1165 m_symbol->SetUnit( old_unit );
1166
1167 // Restore m_Flag modified by SetUnit()
1168 m_symbol->ClearFlags();
1169 m_symbol->SetFlags( flags );
1170 }
1171
1172 OnModify();
1173}
1174
1175
1177{
1178 event.Enable( m_symbol && m_symbol->GetLibSymbolRef() );
1179}
1180
1181
1183{
1184 event.Enable( m_symbol && m_symbol->GetLibSymbolRef() );
1185}
1186
1187
1188void DIALOG_SYMBOL_PROPERTIES::OnPageChanging( wxBookCtrlEvent& aEvent )
1189{
1190 if( !m_fieldsGrid->CommitPendingChanges() )
1191 aEvent.Veto();
1192
1193 if( !m_pinGrid->CommitPendingChanges() )
1194 aEvent.Veto();
1195}
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:110
bool Empty() const
Definition commit.h:137
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:106
void SetupStandardButtons(std::map< int, wxString > aLabels={})
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
DIALOG_SYMBOL_PROPERTIES_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Symbol Properties"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxCAPTION|wxCLOSE_BOX|wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxRESIZE_BORDER|wxSYSTEM_MENU)
void OnSizePinsGrid(wxSizeEvent &event) override
void OnPinTableCellEdited(wxGridEvent &event) override
void OnGridEditorShown(wxGridEvent &event) override
void OnUpdateUI(wxUpdateUIEvent &event) override
void OnEditSymbol(wxCommandEvent &) override
void OnCancelButtonClick(wxCommandEvent &event) override
virtual void onUpdateEditLibrarySymbol(wxUpdateUIEvent &event) override
SCH_PIN_TABLE_DATA_MODEL * m_dataModel
void OnMoveDown(wxCommandEvent &event) override
void OnSizeFieldsGrid(wxSizeEvent &event) override
void OnPinTableColSort(wxGridEvent &aEvent)
void OnMoveUp(wxCommandEvent &event) override
void OnDeleteField(wxCommandEvent &event) override
void OnInitDlg(wxInitDialogEvent &event) override
void OnAddField(wxCommandEvent &event) override
void OnGridEditorHidden(wxGridEvent &event) override
void OnUnitChoice(wxCommandEvent &event) override
void OnEditSpiceModel(wxCommandEvent &event) override
void OnPageChanging(wxNotebookEvent &event) override
DIALOG_SYMBOL_PROPERTIES(SCH_EDIT_FRAME *aParent, SCH_SYMBOL *aSymbol)
void HandleDelayedFocus(wxCommandEvent &event)
void HandleDelayedSelection(wxCommandEvent &event)
void OnCheckBox(wxCommandEvent &event) override
void OnGridCellChanging(wxGridEvent &event)
void OnEditLibrarySymbol(wxCommandEvent &) override
void OnUpdateSymbol(wxCommandEvent &) override
void OnExchangeSymbol(wxCommandEvent &) override
virtual void onUpdateEditSymbol(wxUpdateUIEvent &event) override
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:97
void Offset(const VECTOR2I &aOffset)
Definition eda_text.cpp:597
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:387
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition eda_text.cpp:300
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition grid_tricks.h:61
APP_SETTINGS_BASE * KifaceSettings() const
Definition kiface_base.h:95
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:49
static int Compare(const wxString &lhs, const wxString &rhs)
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Execute the changes.
Schematic editor (Eeschema) main window.
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
SCHEMATIC & Schematic() const
bool IsMandatory() const
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
void SetText(const wxString &aText) override
bool IsEmptyCell(int row, int col) override
wxString GetValue(int aRow, int aCol) override
std::vector< wxGridCellAttr * > m_nameAttrs
static bool compare(const SCH_PIN &lhs, const SCH_PIN &rhs, int sortCol, bool ascending)
void SortRows(int aSortCol, bool ascending)
bool CanSetValueAs(int aRow, int aCol, const wxString &aTypeName) override
static wxString GetValue(const SCH_PIN &aPin, int aCol)
wxString GetColLabelValue(int aCol) override
void SetValue(int aRow, int aCol, const wxString &aValue) override
wxGridCellAttr * GetAttr(int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind) override
void SetAlt(const wxString &aAlt)
Set the name of the alternate pin.
Definition sch_pin.cpp:432
const std::map< wxString, ALT > & GetAlternates() const
Definition sch_pin.h:147
ALT GetAlt(const wxString &aAlt)
Definition sch_pin.h:161
SCH_PIN * GetLibPin() const
Definition sch_pin.h:89
const wxString & GetName() const
Definition sch_pin.cpp:400
const wxString & GetNumber() const
Definition sch_pin.h:124
GRAPHIC_PINSHAPE GetShape() const
Definition sch_pin.cpp:277
ELECTRICAL_PINTYPE GetType() const
Definition sch_pin.cpp:312
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
bool Remove(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Remove aItem from the schematic associated with this screen.
Schematic symbol object.
Definition sch_symbol.h:75
wxGridCellAttr * enhanceAttr(wxGridCellAttr *aInputAttr, int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind)
Definition wx_grid.cpp:45
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.
wxDEFINE_EVENT(SYMBOL_DELAY_FOCUS, wxCommandEvent)
@ SYMBOL_PROPS_EDIT_SCHEMATIC_SYMBOL
@ SYMBOL_PROPS_WANT_EXCHANGE_SYMBOL
@ SYMBOL_PROPS_WANT_UPDATE_SYMBOL
@ SYMBOL_PROPS_EDIT_LIBRARY_SYMBOL
#define _(s)
std::uint32_t EDA_ITEM_FLAGS
@ FDC_NAME
@ FDC_VALUE
wxColour GetDialogBGColour()
Definition wxgtk/ui.cpp:61
wxSize GetUnobscuredSize(const wxWindow *aWindow)
Tries to determine the size of the viewport of a scrollable widget (wxDataViewCtrl,...
Definition wxgtk/ui.cpp:264
KICOMMON_API wxFont GetSmallInfoFont(wxWindow *aWindow)
KICOMMON_API void SelectReferenceNumber(wxTextEntry *aTextEntry)
Select the number (or "?") in a reference for ease of editing.
const std::vector< BITMAPS > & PinTypeIcons()
Definition pin_type.cpp:167
const wxArrayString & PinTypeNames()
Definition pin_type.cpp:158
const wxArrayString & PinShapeNames()
Definition pin_type.cpp:176
const std::vector< BITMAPS > & PinShapeIcons()
Definition pin_type.cpp:185
std::vector< SCH_FIELD > SCH_FIELDS
A container for several SCH_FIELD items.
Definition sch_symbol.h:63
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.
wxString UnescapeString(const wxString &aSource)
Hold a name of a symbol's field, field value, and default visibility.
@ SYM_ORIENT_270
Definition symbol.h:42
@ SYM_MIRROR_Y
Definition symbol.h:44
@ SYM_ORIENT_180
Definition symbol.h:41
@ SYM_MIRROR_X
Definition symbol.h:43
@ SYM_ORIENT_90
Definition symbol.h:40
@ SYM_ORIENT_0
Definition symbol.h:39
Definition for symbol library class.
wxString GetUserFieldName(int aFieldNdx, bool aTranslateForHI)
#define DO_TRANSLATE
@ USER
The field ID hasn't been set yet; field is invalid.
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
VECTOR3I res
VECTOR2I end
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695