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 <wx/uiaction.h>
31#include <grid_tricks.h>
32#include <confirm.h>
33#include <kiface_base.h>
34#include <pin_numbers.h>
35#include <string_utils.h>
36#include <kiplatform/ui.h>
41#include <sch_collectors.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>
52
53
54wxDEFINE_EVENT( SYMBOL_DELAY_FOCUS, wxCommandEvent );
55wxDEFINE_EVENT( SYMBOL_DELAY_SELECTION, wxCommandEvent );
56
57
62static void EnableFocusDebugging( wxWindow* aWindow, const wxString& aWindowName = wxEmptyString )
63{
64 // Lambda-based focus event handler
65 auto onFocus = [aWindowName]( wxFocusEvent& aEvent ) -> void
66 {
67 wxWindow* window = static_cast<wxWindow*>( aEvent.GetEventObject() );
68 if( !window )
69 return;
70
71 wxString controlName = window->GetName();
72 wxString controlLabel;
73
74 // Try to get a human-readable label for the control
75 wxControl* ctrl = dynamic_cast<wxControl*>( window );
76 if( ctrl && !ctrl->GetLabel().empty() )
77 controlLabel = ctrl->GetLabel();
78
79 wxString windowInfo = aWindowName.empty() ? wxString( "" ) : aWindowName + wxString( ": " );
80 // fix a conflict that happens with a Windows header on MINGW. so undefine GetClassName
81 #if defined( GetClassName ) && defined( __MINGW32__ )
82 #undef GetClassName
83 #endif
84
85 if( aEvent.GetEventType() == wxEVT_SET_FOCUS )
86 {
87 wxLogTrace( wxS( "FOCUS_DEBUG" ), wxS( "%sFocus SET on: %s (name=%s, label=%s)" ),
88 windowInfo,
89 window->GetClassInfo()->GetClassName(),
90 controlName,
91 controlLabel );
92 }
93 else if( aEvent.GetEventType() == wxEVT_KILL_FOCUS )
94 {
95 wxLogTrace( wxS( "FOCUS_DEBUG" ), wxS( "%sFocus LOST from: %s (name=%s, label=%s)" ),
96 windowInfo,
97 window->GetClassInfo()->GetClassName(),
98 controlName,
99 controlLabel );
100 }
101
102 aEvent.Skip(); // Allow event to propagate
103 };
104
105 // Recursively attach handler to this window and all children
106 std::function<void( wxWindow* )> attachToTree = [&]( wxWindow* w ) -> void
107 {
108 if( !w )
109 return;
110
111 w->Bind( wxEVT_SET_FOCUS, onFocus );
112 w->Bind( wxEVT_KILL_FOCUS, onFocus );
113
114 // Recursively attach to all child windows
115 for( wxWindow* child : w->GetChildren() )
116 attachToTree( child );
117 };
118
119 attachToTree( aWindow );
120
121 wxLogTrace( wxS( "FOCUS_DEBUG" ), wxS( "Focus debugging enabled for: %s" ), aWindowName );
122}
123
124
135
136
137class SCH_PIN_TABLE_DATA_MODEL : public WX_GRID_TABLE_BASE, public std::vector<SCH_PIN>
138{
139public:
141 m_readOnlyAttr( nullptr ),
142 m_typeAttr( nullptr ),
143 m_shapeAttr( nullptr )
144 {
145 }
146
148 {
149 for( wxGridCellAttr* attr : m_nameAttrs )
150 attr->DecRef();
151
152 m_readOnlyAttr->DecRef();
153 m_typeAttr->DecRef();
154 m_shapeAttr->DecRef();
155 }
156
158 {
159 for( wxGridCellAttr* attr : m_nameAttrs )
160 attr->DecRef();
161
162 m_nameAttrs.clear();
163
164 if( m_readOnlyAttr )
165 m_readOnlyAttr->DecRef();
166
167 m_readOnlyAttr = new wxGridCellAttr;
168 m_readOnlyAttr->SetReadOnly( true );
169
170 for( const SCH_PIN& pin : *this )
171 {
172 SCH_PIN* lib_pin = pin.GetLibPin();
173 wxGridCellAttr* attr = nullptr;
174
175 if( !lib_pin || lib_pin->GetAlternates().empty() )
176 {
177 attr = new wxGridCellAttr;
178 attr->SetReadOnly( true );
179 attr->SetBackgroundColour( KIPLATFORM::UI::GetDialogBGColour() );
180 }
181 else
182 {
183 wxArrayString choices;
184 choices.push_back( lib_pin->GetName() );
185
186 for( const std::pair<const wxString, SCH_PIN::ALT>& alt : lib_pin->GetAlternates() )
187 choices.push_back( alt.first );
188
189 attr = new wxGridCellAttr();
190 attr->SetEditor( new GRID_CELL_COMBOBOX( choices ) );
191 }
192
193 m_nameAttrs.push_back( attr );
194 }
195
196 if( m_typeAttr )
197 m_typeAttr->DecRef();
198
199 m_typeAttr = new wxGridCellAttr;
201 m_typeAttr->SetReadOnly( true );
202
203 if( m_shapeAttr )
204 m_shapeAttr->DecRef();
205
206 m_shapeAttr = new wxGridCellAttr;
208 m_shapeAttr->SetReadOnly( true );
209 }
210
211 int GetNumberRows() override { return (int) size(); }
212 int GetNumberCols() override { return COL_COUNT; }
213
214 wxString GetColLabelValue( int aCol ) override
215 {
216 switch( aCol )
217 {
218 case COL_NUMBER: return _( "Number" );
219 case COL_BASE_NAME: return _( "Base Name" );
220 case COL_ALT_NAME: return _( "Alternate Assignment" );
221 case COL_TYPE: return _( "Electrical Type" );
222 case COL_SHAPE: return _( "Graphic Style" );
223 default: wxFAIL; return wxEmptyString;
224 }
225 }
226
227 bool IsEmptyCell( int row, int col ) override
228 {
229 return false; // don't allow adjacent cell overflow, even if we are actually empty
230 }
231
232 bool CanSetValueAs( int aRow, int aCol, const wxString& aTypeName ) override
233 {
234 // Don't accept random values; must use the popup to change to a known alternate
235 return false;
236 }
237
238 wxString GetValue( int aRow, int aCol ) override
239 {
240 return GetValue( at( aRow ), aCol );
241 }
242
243 static wxString GetValue( const SCH_PIN& aPin, int aCol )
244 {
245 if( aCol == COL_ALT_NAME )
246 {
247 if( !aPin.GetLibPin() || aPin.GetLibPin()->GetAlternates().empty() )
248 return wxEmptyString;
249 else if( aPin.GetAlt().IsEmpty() )
250 return aPin.GetName();
251 else
252 return aPin.GetAlt();
253 }
254
255 switch( aCol )
256 {
257 case COL_NUMBER: return aPin.GetNumber();
258 case COL_BASE_NAME: return aPin.GetBaseName();
259 case COL_TYPE: return PinTypeNames()[static_cast<int>( aPin.GetType() )];
260 case COL_SHAPE: return PinShapeNames()[static_cast<int>( aPin.GetShape() )];
261 default: wxFAIL; return wxEmptyString;
262 }
263 }
264
265 wxGridCellAttr* GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind ) override
266 {
267 switch( aCol )
268 {
269 case COL_NUMBER:
270 case COL_BASE_NAME:
271 m_readOnlyAttr->IncRef();
272 return enhanceAttr( m_readOnlyAttr, aRow, aCol, aKind );
273
274 case COL_ALT_NAME:
275 m_nameAttrs[ aRow ]->IncRef();
276 return enhanceAttr( m_nameAttrs[ aRow ], aRow, aCol, aKind );
277
278 case COL_TYPE:
279 m_typeAttr->IncRef();
280 return enhanceAttr( m_typeAttr, aRow, aCol, aKind );
281
282 case COL_SHAPE:
283 m_shapeAttr->IncRef();
284 return enhanceAttr( m_shapeAttr, aRow, aCol, aKind );
285
286 default:
287 wxFAIL;
288 return nullptr;
289 }
290 }
291
292 void SetValue( int aRow, int aCol, const wxString &aValue ) override
293 {
294 SCH_PIN& pin = at( aRow );
295
296 switch( aCol )
297 {
298 case COL_ALT_NAME:
299 if( pin.GetLibPin() && aValue == pin.GetLibPin()->GetName() )
300 pin.SetAlt( wxEmptyString );
301 else
302 pin.SetAlt( aValue );
303 break;
304
305 case COL_NUMBER:
306 case COL_BASE_NAME:
307 case COL_TYPE:
308 case COL_SHAPE:
309 // Read-only.
310 break;
311
312 default:
313 wxFAIL;
314 break;
315 }
316 }
317
318 static bool compare( const SCH_PIN& lhs, const SCH_PIN& rhs, int sortCol, bool ascending )
319 {
320 wxString lhStr = GetValue( lhs, sortCol );
321 wxString rhStr = GetValue( rhs, sortCol );
322
323 if( lhStr == rhStr )
324 {
325 // Secondary sort key is always COL_NUMBER
326 sortCol = COL_NUMBER;
327 lhStr = GetValue( lhs, sortCol );
328 rhStr = GetValue( rhs, sortCol );
329 }
330
331 bool res;
332
333 // N.B. To meet the iterator sort conditions, we cannot simply invert the truth
334 // to get the opposite sort. i.e. ~(a<b) != (a>b)
335 auto cmp = [ ascending ]( const auto a, const auto b )
336 {
337 if( ascending )
338 return a < b;
339 else
340 return b < a;
341 };
342
343 switch( sortCol )
344 {
345 case COL_NUMBER:
346 case COL_BASE_NAME:
347 case COL_ALT_NAME:
348 res = cmp( PIN_NUMBERS::Compare( lhStr, rhStr ), 0 );
349 break;
350 case COL_TYPE:
351 case COL_SHAPE:
352 res = cmp( lhStr.CmpNoCase( rhStr ), 0 );
353 break;
354 default:
355 res = cmp( StrNumCmp( lhStr, rhStr ), 0 );
356 break;
357 }
358
359 return res;
360 }
361
362 void SortRows( int aSortCol, bool ascending )
363 {
364 std::sort( begin(), end(),
365 [ aSortCol, ascending ]( const SCH_PIN& lhs, const SCH_PIN& rhs ) -> bool
366 {
367 return compare( lhs, rhs, aSortCol, ascending );
368 } );
369 }
370
371protected:
372 std::vector<wxGridCellAttr*> m_nameAttrs;
373 wxGridCellAttr* m_readOnlyAttr;
374 wxGridCellAttr* m_typeAttr;
375 wxGridCellAttr* m_shapeAttr;
376};
377
378
381 m_symbol( nullptr ),
382 m_part( nullptr ),
384 m_editorShown( false ),
385 m_fields( nullptr ),
386 m_dataModel( nullptr ),
387 m_embeddedFiles( nullptr )
388{
389 m_symbol = aSymbol;
390 m_part = m_symbol->GetLibSymbolRef().get();
391
392 // GetLibSymbolRef() now points to the cached part in the schematic, which should always be
393 // there for usual cases, but can be null when opening old schematics not storing the part
394 // so we need to handle m_part == nullptr
395 // wxASSERT( m_part );
396
397 m_fields = new FIELDS_GRID_TABLE( this, aParent, m_fieldsGrid, m_symbol );
398
399 m_fieldsGrid->SetTable( m_fields );
400 m_fieldsGrid->PushEventHandler( new FIELDS_GRID_TRICKS( m_fieldsGrid, this,
401 { &aParent->Schematic(), m_part },
402 [&]( wxCommandEvent& aEvent )
403 {
404 OnAddField( aEvent );
405 } ) );
406 m_fieldsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
407 m_fieldsGrid->ShowHideColumns( "0 1 2 3 4 5 6 7" );
408 m_shownColumns = m_fieldsGrid->GetShownColumns();
409
410 if( m_symbol->GetEmbeddedFiles() )
411 {
412 m_embeddedFiles = new PANEL_EMBEDDED_FILES( m_notebook1, m_symbol->GetEmbeddedFiles() );
413 m_notebook1->AddPage( m_embeddedFiles, _( "Embedded Files" ) );
414 }
415
416 if( m_part && m_part->IsMultiBodyStyle() )
417 {
418 // Multiple body styles are a superclass of alternate pin assignments, so don't allow
419 // free-form alternate assignments as well. (We won't know how to map the alternates
420 // back and forth when the body style is changed.)
421 m_pinTablePage->Disable();
422 m_pinTablePage->SetToolTip( _( "Alternate pin assignments are not available for symbols with multiple "
423 "body styles." ) );
424 }
425 else
426 {
428
429 // Make a copy of the pins for editing
430 for( const std::unique_ptr<SCH_PIN>& pin : m_symbol->GetRawPins() )
431 m_dataModel->push_back( *pin );
432
433 m_dataModel->SortRows( COL_NUMBER, true );
434 m_dataModel->BuildAttrs();
435
436 m_pinGrid->SetTable( m_dataModel );
437 }
438
439 if( m_part && m_part->IsPower() )
440 m_spiceFieldsButton->Hide();
441
442 m_pinGrid->PushEventHandler( new GRID_TRICKS( m_pinGrid ) );
443 m_pinGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
444
445 wxFont infoFont = KIUI::GetSmallInfoFont( this );
446 m_libraryIDLabel->SetFont( infoFont );
447 m_tcLibraryID->SetFont( infoFont );
448 m_tcLibraryID->SetBackgroundColour( KIPLATFORM::UI::GetDialogBGColour() );
449
450 wxToolTip::Enable( true );
452
453 // Configure button logos
458
459 // Enable focus debugging to track which element has focus
460 EnableFocusDebugging( this, wxS( "DIALOG_SYMBOL_PROPERTIES" ) );
461
462 // wxFormBuilder doesn't include this event...
463 m_fieldsGrid->Bind( wxEVT_GRID_CELL_CHANGING, &DIALOG_SYMBOL_PROPERTIES::OnGridCellChanging, this );
464 m_pinGrid->Bind( wxEVT_GRID_COL_SORT, &DIALOG_SYMBOL_PROPERTIES::OnPinTableColSort, this );
465 Bind( SYMBOL_DELAY_FOCUS, &DIALOG_SYMBOL_PROPERTIES::HandleDelayedFocus, this );
466 Bind( SYMBOL_DELAY_SELECTION, &DIALOG_SYMBOL_PROPERTIES::HandleDelayedSelection, this );
467
468 wxCommandEvent* evt = new wxCommandEvent( SYMBOL_DELAY_SELECTION );
469 evt->SetClientData( new VECTOR2I( 0, FDC_VALUE ) );
470 QueueEvent( evt );
471
472 evt = new wxCommandEvent( SYMBOL_DELAY_FOCUS );
473 evt->SetClientData( new VECTOR2I( 0, FDC_VALUE ) );
474 QueueEvent( evt );
475
476 // Remind user that they are editing the current variant.
477 if( !aParent->Schematic().GetCurrentVariant().IsEmpty() )
478 SetTitle( GetTitle() + wxS( " - " ) + aParent->Schematic().GetCurrentVariant() + _( " Variant" ) );
479
480 Layout();
481 m_fieldsGrid->Layout();
482
483 if( GetSizer() )
484 GetSizer()->Fit( this );
485
487}
488
489
491{
492 // Prevents crash bug in wxGrid's d'tor
493 m_fieldsGrid->DestroyTable( m_fields );
494
495 if( m_dataModel )
496 m_pinGrid->DestroyTable( m_dataModel );
497
498 m_fieldsGrid->Unbind( wxEVT_GRID_CELL_CHANGING, &DIALOG_SYMBOL_PROPERTIES::OnGridCellChanging, this );
499 m_pinGrid->Unbind( wxEVT_GRID_COL_SORT, &DIALOG_SYMBOL_PROPERTIES::OnPinTableColSort, this );
500 Unbind( SYMBOL_DELAY_FOCUS, &DIALOG_SYMBOL_PROPERTIES::HandleDelayedFocus, this );
501 Unbind( SYMBOL_DELAY_SELECTION, &DIALOG_SYMBOL_PROPERTIES::HandleDelayedSelection, this );
502
503 // Delete the GRID_TRICKS.
504 m_fieldsGrid->PopEventHandler( true );
505 m_pinGrid->PopEventHandler( true );
506}
507
508
510{
511 return dynamic_cast<SCH_EDIT_FRAME*>( wxDialog::GetParent() );
512}
513
514
516{
517 if( !wxDialog::TransferDataToWindow() )
518 return false;
519
520 const SCHEMATIC& schematic = GetParent()->Schematic();
521 SCH_SHEET_PATH& sheetPath = schematic.CurrentSheet();
522 wxString variantName = schematic.GetCurrentVariant();
523 std::optional<SCH_SYMBOL_VARIANT> variant = m_symbol->GetVariant( sheetPath, variantName );
524 std::set<wxString> defined;
525
526 // Push a copy of each field into m_updateFields
527 for( SCH_FIELD& srcField : m_symbol->GetFields() )
528 {
529 SCH_FIELD field( srcField );
530
531 // change offset to be symbol-relative
532 field.Offset( -m_symbol->GetPosition() );
533 field.SetText( schematic.ConvertKIIDsToRefs( m_symbol->GetFieldText( field.GetName(), &sheetPath,
534 variantName ) ) );
535
536 defined.insert( field.GetName() );
537 m_fields->push_back( field );
538 }
539
540 // Add in any template fieldnames not yet defined:
541 for( const TEMPLATE_FIELDNAME& templateFieldname :
543 {
544 if( defined.count( templateFieldname.m_Name ) <= 0 )
545 {
546 SCH_FIELD field( m_symbol, FIELD_T::USER, templateFieldname.m_Name );
547 field.SetVisible( templateFieldname.m_Visible );
548 m_fields->push_back( field );
549 }
550 }
551
552 // notify the grid
553 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_fields->GetNumberRows() );
554 m_fieldsGrid->ProcessTableMessage( msg );
555
556 // If a multi-unit symbol, set up the unit selector and interchangeable checkbox.
557 if( m_symbol->IsMultiUnit() )
558 {
559 // Ensure symbol unit is the currently selected unit (mandatory in complex hierarchies)
560 // from the current sheet path, because it can be modified by previous calculations
561 m_symbol->SetUnit( m_symbol->GetUnitSelection( &sheetPath ) );
562
563 for( int ii = 1; ii <= m_symbol->GetUnitCount(); ii++ )
564 m_unitChoice->Append( m_symbol->GetUnitDisplayName( ii, false ) );
565
566 if( m_symbol->GetUnit() <= ( int )m_unitChoice->GetCount() )
567 m_unitChoice->SetSelection( m_symbol->GetUnit() - 1 );
568 }
569 else
570 {
571 m_unitLabel->Enable( false );
572 m_unitChoice->Enable( false );
573 }
574
575 if( m_part && m_part->IsMultiBodyStyle() )
576 {
577 if( m_part->HasDeMorganBodyStyles() )
578 {
579 m_bodyStyleChoice->Append( _( "Standard" ) );
580 m_bodyStyleChoice->Append( _( "Alternate" ) );
581 }
582 else
583 {
584 wxASSERT( (int)m_part->GetBodyStyleNames().size() == m_part->GetBodyStyleCount() );
585
586 for( int ii = 0; ii < m_part->GetBodyStyleCount(); ii++ )
587 {
588 try
589 {
590 m_bodyStyleChoice->Append( m_part->GetBodyStyleNames().at( ii ) );
591 }
592 catch( ... )
593 {
594 m_bodyStyleChoice->Append( wxT( "???" ) );
595 }
596 }
597 }
598
599 if( m_symbol->GetBodyStyle() <= (int) m_bodyStyleChoice->GetCount() )
600 m_bodyStyleChoice->SetSelection( m_symbol->GetBodyStyle() - 1 );
601 }
602 else
603 {
604 m_bodyStyle->Enable( false );
605 m_bodyStyleChoice->Enable( false );
606 }
607
608 // Set the symbol orientation and mirroring.
609 int orientation = m_symbol->GetOrientation() & ~( SYM_MIRROR_X | SYM_MIRROR_Y );
610
611 switch( orientation )
612 {
613 default:
614 case SYM_ORIENT_0: m_orientationCtrl->SetSelection( 0 ); break;
615 case SYM_ORIENT_90: m_orientationCtrl->SetSelection( 1 ); break;
616 case SYM_ORIENT_270: m_orientationCtrl->SetSelection( 2 ); break;
617 case SYM_ORIENT_180: m_orientationCtrl->SetSelection( 3 ); break;
618 }
619
620 int mirror = m_symbol->GetOrientation() & ( SYM_MIRROR_X | SYM_MIRROR_Y );
621
622 switch( mirror )
623 {
624 default: m_mirrorCtrl->SetSelection( 0 ) ; break;
625 case SYM_MIRROR_X: m_mirrorCtrl->SetSelection( 1 ); break;
626 case SYM_MIRROR_Y: m_mirrorCtrl->SetSelection( 2 ); break;
627 }
628
629 m_cbExcludeFromSim->SetValue( m_symbol->GetExcludedFromSim( &sheetPath, variantName ) );
630 m_cbExcludeFromBom->SetValue( m_symbol->GetExcludedFromBOM( &sheetPath, variantName ) );
631 m_cbExcludeFromBoard->SetValue( m_symbol->GetExcludedFromBoard() );
632 m_cbExcludeFromPosFiles->SetValue( m_symbol->GetExcludedFromPosFiles() );
633 m_cbDNP->SetValue( m_symbol->GetDNP( &sheetPath, variantName ) );
634
635 if( m_part )
636 {
637 m_ShowPinNumButt->SetValue( m_part->GetShowPinNumbers() );
638 m_ShowPinNameButt->SetValue( m_part->GetShowPinNames() );
639 }
640
641 // Set the symbol's library name.
642 m_tcLibraryID->SetValue( UnescapeString( m_symbol->GetLibId().Format() ) );
643
644 if( m_embeddedFiles && !m_embeddedFiles->TransferDataToWindow() )
645 return false;
646
647 // Recalculate the dialog size now that the grid is populated. On first run, the dialog was
648 // sized before data was available, so the grid had zero height. Recalculating ensures the
649 // minimum size accounts for the actual grid content.
650 m_fieldsGrid->Layout();
651 Layout();
652 GetSizer()->SetSizeHints( this );
653
654 wxSize minSize = GetMinSize();
655 wxSize curSize = GetSize();
656
657 if( curSize.y < minSize.y )
658 SetSize( wxSize( curSize.x, minSize.y ) );
659
660 return true;
661}
662
663
665{
666 if( !m_fieldsGrid->CommitPendingChanges() )
667 return;
668
669 m_fieldsGrid->ClearSelection();
670
671 std::vector<SCH_FIELD> fields;
672
673 for( const SCH_FIELD& field : *m_fields )
674 fields.emplace_back( field );
675
676 DIALOG_SIM_MODEL dialog( this, m_parentFrame, *m_symbol, fields );
677
678 if( dialog.ShowModal() != wxID_OK )
679 return;
680
681 // Add in any new fields
682 for( const SCH_FIELD& editedField : fields )
683 {
684 bool found = false;
685
686 for( SCH_FIELD& existingField : *m_fields )
687 {
688 if( existingField.GetName() == editedField.GetName() )
689 {
690 found = true;
691 existingField.SetText( editedField.GetText() );
692 break;
693 }
694 }
695
696 if( !found )
697 {
698 m_fields->emplace_back( editedField );
699 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
700 m_fieldsGrid->ProcessTableMessage( msg );
701 }
702 }
703
704 // Remove any deleted fields
705 for( int ii = (int) m_fields->size() - 1; ii >= 0; --ii )
706 {
707 SCH_FIELD& existingField = m_fields->at( ii );
708 bool found = false;
709
710 for( SCH_FIELD& editedField : fields )
711 {
712 if( editedField.GetName() == existingField.GetName() )
713 {
714 found = true;
715 break;
716 }
717 }
718
719 if( !found )
720 {
721 m_fieldsGrid->ClearSelection();
722 m_fields->erase( m_fields->begin() + ii );
723
724 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, ii, 1 );
725 m_fieldsGrid->ProcessTableMessage( msg );
726 }
727 }
728
729 OnModify();
730 m_fieldsGrid->ForceRefresh();
731}
732
733
735{
736 // Running the Footprint Browser gums up the works and causes the automatic cancel
737 // stuff to no longer work. So we do it here ourselves.
738 EndQuasiModal( wxID_CANCEL );
739}
740
741
743{
744 LIB_ID id;
745
746 if( !m_fieldsGrid->CommitPendingChanges() || !m_fieldsGrid->Validate() )
747 return false;
748
749 // Check for missing field names.
750 for( size_t i = 0; i < m_fields->size(); ++i )
751 {
752 SCH_FIELD& field = m_fields->at( i );
753
754 if( field.IsMandatory() )
755 continue;
756
757 wxString fieldName = field.GetName( false );
758
759 if( fieldName.IsEmpty() )
760 {
761 DisplayErrorMessage( this, _( "Fields must have a name." ) );
762
763 wxCommandEvent *evt = new wxCommandEvent( SYMBOL_DELAY_FOCUS );
764 evt->SetClientData( new VECTOR2I( i, FDC_VALUE ) );
765 QueueEvent( evt );
766
767 return false;
768 }
769 }
770
771 return true;
772}
773
774
776{
777 if( !wxDialog::TransferDataFromWindow() ) // Calls our Validate() method.
778 return false;
779
780 if( m_embeddedFiles && !m_embeddedFiles->TransferDataFromWindow() )
781 return false;
782
783 if( !m_fieldsGrid->CommitPendingChanges() )
784 return false;
785
786 if( !m_pinGrid->CommitPendingChanges() )
787 return false;
788
789 SCH_COMMIT commit( GetParent() );
790 SCH_SCREEN* currentScreen = GetParent()->GetScreen();
791 SCH_SHEET_PATH currentSheet = GetParent()->Schematic().CurrentSheet();
792 wxString currentVariant = GetParent()->Schematic().GetCurrentVariant();
793 bool replaceOnCurrentScreen;
794
795 wxCHECK( currentScreen, false );
796
797 // This needs to be done before the LIB_ID is changed to prevent stale library symbols in
798 // the schematic file.
799 replaceOnCurrentScreen = currentScreen->Remove( m_symbol );
800
801 // save old cmp in undo list if not already in edit, or moving ...
802 if( m_symbol->GetEditFlags() == 0 )
803 commit.Modify( m_symbol, currentScreen );
804
805 // Save current flags which could be modified by next change settings
806 EDA_ITEM_FLAGS flags = m_symbol->GetFlags();
807
808 //Set the part selection in multiple part per package
809 int unit_selection = m_unitChoice->IsEnabled() ? m_unitChoice->GetSelection() + 1 : 1;
810 m_symbol->SetUnitSelection( &GetParent()->GetCurrentSheet(), unit_selection );
811 m_symbol->SetUnit( unit_selection );
812
813 int bodyStyle_selection = m_bodyStyleChoice->IsEnabled() ? m_bodyStyleChoice->GetSelection() + 1 : 1;
814 m_symbol->SetBodyStyle( bodyStyle_selection );
815
816 switch( m_orientationCtrl->GetSelection() )
817 {
818 case 0: m_symbol->SetOrientation( SYM_ORIENT_0 ); break;
819 case 1: m_symbol->SetOrientation( SYM_ORIENT_90 ); break;
820 case 2: m_symbol->SetOrientation( SYM_ORIENT_270 ); break;
821 case 3: m_symbol->SetOrientation( SYM_ORIENT_180 ); break;
822 }
823
824 switch( m_mirrorCtrl->GetSelection() )
825 {
826 case 0: break;
827 case 1: m_symbol->SetOrientation( SYM_MIRROR_X ); break;
828 case 2: m_symbol->SetOrientation( SYM_MIRROR_Y ); break;
829 }
830
831 m_symbol->SetShowPinNames( m_ShowPinNameButt->GetValue() );
832 m_symbol->SetShowPinNumbers( m_ShowPinNumButt->GetValue() );
833
834 // Restore m_Flag modified by SetUnit() and other change settings from the dialog
835 m_symbol->ClearFlags();
836 m_symbol->SetFlags( flags );
837
838 // change all field positions from relative to absolute
839 for( SCH_FIELD& field : *m_fields )
840 field.Offset( m_symbol->GetPosition() );
841
842 int ordinal = 42; // Arbitrarily larger than any mandatory FIELD_T ids.
843
844 for( SCH_FIELD& field : *m_fields )
845 {
846 const wxString& fieldName = field.GetCanonicalName();
847
848 if( fieldName.IsEmpty() && field.GetText().IsEmpty() )
849 continue;
850 else if( fieldName.IsEmpty() )
851 field.SetName( _( "untitled" ) );
852
853 const SCH_FIELD* existingField = m_symbol->GetField( fieldName );
854 SCH_FIELD* tmp;
855
856 if( !existingField )
857 {
858 tmp = m_symbol->AddField( field );
859 tmp->SetParent( m_symbol );
860 }
861 else
862 {
863 wxString defaultText = m_symbol->Schematic()->ConvertRefsToKIIDs( existingField->GetText() );
864 tmp = const_cast<SCH_FIELD*>( existingField );
865
866 *tmp = field;
867
868 if( !currentVariant.IsEmpty() )
869 {
870 // Restore the default field text for existing fields.
871 tmp->SetText( defaultText, &currentSheet );
872
873 wxString variantText = m_symbol->Schematic()->ConvertRefsToKIIDs( field.GetText() );
874 tmp->SetText( variantText, &currentSheet, currentVariant );
875 }
876 }
877
878 if( !field.IsMandatory() )
879 field.SetOrdinal( ordinal++ );
880 }
881
882 if( currentVariant.IsEmpty() )
883 {
884 // Reference has a specific initialization, depending on the current active sheet
885 // because for a given symbol, in a complex hierarchy, there are more than one
886 // reference.
887 m_symbol->SetRef( &GetParent()->GetCurrentSheet(), m_fields->GetField( FIELD_T::REFERENCE )->GetText() );
888 }
889
890 m_symbol->SetExcludedFromSim( m_cbExcludeFromSim->IsChecked(), &currentSheet, currentVariant );
891 m_symbol->SetExcludedFromBOM( m_cbExcludeFromBom->IsChecked(), &currentSheet, currentVariant );
892 m_symbol->SetExcludedFromBoard( m_cbExcludeFromBoard->IsChecked() );
893 m_symbol->SetExcludedFromPosFiles( m_cbExcludeFromPosFiles->IsChecked() );
894 m_symbol->SetDNP( m_cbDNP->IsChecked(), &currentSheet, currentVariant );
895
896 // Update any assignments
897 if( m_dataModel )
898 {
899 for( const SCH_PIN& model_pin : *m_dataModel )
900 {
901 // map from the edited copy back to the "real" pin in the symbol.
902 SCH_PIN* src_pin = m_symbol->GetPin( model_pin.GetNumber() );
903
904 if( src_pin )
905 src_pin->SetAlt( model_pin.GetAlt() );
906 }
907 }
908
909 // Keep fields other than the reference, include/exclude flags, and alternate pin assignements
910 // in sync in multi-unit parts.
911 m_symbol->SyncOtherUnits( currentSheet, commit, nullptr, currentVariant );
912
913 if( replaceOnCurrentScreen )
914 currentScreen->Append( m_symbol );
915
916 if( !commit.Empty() )
917 commit.Push( _( "Edit Symbol Properties" ) );
918
919 return true;
920}
921
922
924{
925 wxGridCellEditor* editor = m_fieldsGrid->GetCellEditor( event.GetRow(), event.GetCol() );
926 wxControl* control = editor->GetControl();
927
928 if( control && control->GetValidator() && !control->GetValidator()->Validate( control ) )
929 {
930 event.Veto();
931 wxCommandEvent *evt = new wxCommandEvent( SYMBOL_DELAY_FOCUS );
932 evt->SetClientData( new VECTOR2I( event.GetRow(), event.GetCol() ) );
933 QueueEvent( evt );
934 }
935 else if( event.GetCol() == FDC_NAME )
936 {
937 wxString newName = event.GetString();
938
939 for( int i = 0; i < m_fieldsGrid->GetNumberRows(); ++i )
940 {
941 if( i == event.GetRow() )
942 continue;
943
944 if( newName.CmpNoCase( m_fieldsGrid->GetCellValue( i, FDC_NAME ) ) == 0 )
945 {
946 DisplayError( this, wxString::Format( _( "Field name '%s' already in use." ),
947 newName ) );
948 event.Veto();
949 wxCommandEvent *evt = new wxCommandEvent( SYMBOL_DELAY_FOCUS );
950 evt->SetClientData( new VECTOR2I( event.GetRow(), event.GetCol() ) );
951 QueueEvent( evt );
952 }
953 }
954 }
955
956 editor->DecRef();
957}
958
959
961{
962 if( m_fields->at( aEvent.GetRow() ).GetId() == FIELD_T::REFERENCE
963 && aEvent.GetCol() == FDC_VALUE )
964 {
965 wxCommandEvent* evt = new wxCommandEvent( SYMBOL_DELAY_SELECTION );
966 evt->SetClientData( new VECTOR2I( aEvent.GetRow(), aEvent.GetCol() ) );
967 QueueEvent( evt );
968 }
969
970 m_editorShown = true;
971}
972
973
975{
976 m_editorShown = false;
977}
978
979
980void DIALOG_SYMBOL_PROPERTIES::OnAddField( wxCommandEvent& event )
981{
982 m_fieldsGrid->OnAddRow(
983 [&]() -> std::pair<int, int>
984 {
986
987 newField.SetTextAngle( m_fields->GetField( FIELD_T::REFERENCE )->GetTextAngle() );
988 newField.SetVisible( false );
989
990 m_fields->push_back( newField );
991
992 // notify the grid
993 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
994 m_fieldsGrid->ProcessTableMessage( msg );
995 OnModify();
996
997 return { m_fields->size() - 1, FDC_NAME };
998 } );
999}
1000
1001
1002void DIALOG_SYMBOL_PROPERTIES::OnDeleteField( wxCommandEvent& event )
1003{
1004 m_fieldsGrid->OnDeleteRows(
1005 [&]( int row )
1006 {
1007 if( row < m_fields->GetMandatoryRowCount() )
1008 {
1009 DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ),
1010 m_fields->GetMandatoryRowCount() ) );
1011 return false;
1012 }
1013
1014 return true;
1015 },
1016 [&]( int row )
1017 {
1018 m_fields->erase( m_fields->begin() + row );
1019
1020 // notify the grid
1021 wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 );
1022 m_fieldsGrid->ProcessTableMessage( msg );
1023 } );
1024
1025 OnModify();
1026}
1027
1028
1029void DIALOG_SYMBOL_PROPERTIES::OnMoveUp( wxCommandEvent& event )
1030{
1031 m_fieldsGrid->OnMoveRowUp(
1032 [&]( int row )
1033 {
1034 return row > m_fields->GetMandatoryRowCount();
1035 },
1036 [&]( int row )
1037 {
1038 std::swap( *( m_fields->begin() + row ), *( m_fields->begin() + row - 1 ) );
1039 m_fieldsGrid->ForceRefresh();
1040 OnModify();
1041 } );
1042}
1043
1044
1045void DIALOG_SYMBOL_PROPERTIES::OnMoveDown( wxCommandEvent& event )
1046{
1047 m_fieldsGrid->OnMoveRowDown(
1048 [&]( int row )
1049 {
1050 return row >= m_fields->GetMandatoryRowCount();
1051 },
1052 [&]( int row )
1053 {
1054 std::swap( *( m_fields->begin() + row ), *( m_fields->begin() + row + 1 ) );
1055 m_fieldsGrid->ForceRefresh();
1056 OnModify();
1057 } );
1058}
1059
1060
1066
1067
1073
1074
1080
1081
1087
1088
1090{
1091 int row = aEvent.GetRow();
1092
1093 if( m_pinGrid->GetCellValue( row, COL_ALT_NAME ) == m_dataModel->GetValue( row, COL_BASE_NAME ) )
1094 m_dataModel->SetValue( row, COL_ALT_NAME, wxEmptyString );
1095
1096 // These are just to get the cells refreshed
1097 m_dataModel->SetValue( row, COL_TYPE, m_dataModel->GetValue( row, COL_TYPE ) );
1098 m_dataModel->SetValue( row, COL_SHAPE, m_dataModel->GetValue( row, COL_SHAPE ) );
1099
1100 OnModify();
1101}
1102
1103
1105{
1106 int sortCol = aEvent.GetCol();
1107 bool ascending;
1108
1109 // This is bonkers, but wxWidgets doesn't tell us ascending/descending in the
1110 // event, and if we ask it will give us pre-event info.
1111 if( m_pinGrid->IsSortingBy( sortCol ) )
1112 // same column; invert ascending
1113 ascending = !m_pinGrid->IsSortOrderAscending();
1114 else
1115 // different column; start with ascending
1116 ascending = true;
1117
1118 m_dataModel->SortRows( sortCol, ascending );
1119 m_dataModel->BuildAttrs();
1120}
1121
1122
1124{
1125 wxGridUpdateLocker deferRepaintsTillLeavingScope( m_pinGrid );
1126
1127 // Account for scroll bars
1128 int pinTblWidth = KIPLATFORM::UI::GetUnobscuredSize( m_pinGrid ).x;
1129
1130 // Stretch the Base Name and Alternate Assignment columns to fit.
1131 for( int i = 0; i < COL_COUNT; ++i )
1132 {
1133 if( i != COL_BASE_NAME && i != COL_ALT_NAME )
1134 pinTblWidth -= m_pinGrid->GetColSize( i );
1135 }
1136
1137 if( pinTblWidth > 2 )
1138 {
1139 m_pinGrid->SetColSize( COL_BASE_NAME, pinTblWidth / 2 );
1140 m_pinGrid->SetColSize( COL_ALT_NAME, pinTblWidth / 2 );
1141 }
1142}
1143
1144
1145void DIALOG_SYMBOL_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
1146{
1147 std::bitset<64> shownColumns = m_fieldsGrid->GetShownColumns();
1148
1149 if( shownColumns != m_shownColumns )
1150 {
1151 m_shownColumns = shownColumns;
1152
1153 if( !m_fieldsGrid->IsCellEditControlShown() )
1154 m_fieldsGrid->SetGridWidthsDirty();
1155 }
1156}
1157
1158
1160{
1161 VECTOR2I *loc = static_cast<VECTOR2I*>( event.GetClientData() );
1162
1163 wxCHECK_RET( loc, wxT( "Missing focus cell location" ) );
1164
1165 // Run the AutoColumnSizer before setting focus (as it will clear any shown cell edit control
1166 // if it has to resize that column).
1167 m_fieldsGrid->RecomputeGridWidths();
1168
1169 // Handle a delayed focus
1170
1171 m_fieldsGrid->SetFocus();
1172 m_fieldsGrid->MakeCellVisible( loc->x, loc->y );
1173 m_fieldsGrid->SetGridCursor( loc->x, loc->y );
1174
1175 delete loc;
1176
1177 CallAfter(
1178 [this]()
1179 {
1180 m_fieldsGrid->EnableCellEditControl( true );
1181 } );
1182}
1183
1184
1186{
1187 VECTOR2I *loc = static_cast<VECTOR2I*>( event.GetClientData() );
1188
1189 wxCHECK_RET( loc, wxT( "Missing focus cell location" ) );
1190
1191 // Handle a delayed selection
1192 wxGridCellEditor* cellEditor = m_fieldsGrid->GetCellEditor( loc->x, loc->y );
1193
1194 if( wxTextEntry* txt = dynamic_cast<wxTextEntry*>( cellEditor->GetControl() ) )
1196
1197 cellEditor->DecRef(); // we're done; must release
1198 delete loc;
1199}
1200
1201
1203{
1204 wxSize new_size = event.GetSize();
1205
1206 if( ( !m_editorShown || m_lastRequestedPinsSize != new_size ) && m_pinsSize != new_size )
1207 {
1208 m_pinsSize = new_size;
1209
1211 }
1212
1213 // We store this value to check whether the dialog is changing size. This might indicate
1214 // that the user is scaling the dialog with a grid-cell-editor shown. Some editors do not
1215 // close (at least on GTK) when the user drags a dialog corner
1216 m_lastRequestedPinsSize = new_size;
1217
1218 // Always propagate for a grid repaint (needed if the height changes, as well as width)
1219 event.Skip();
1220}
1221
1222
1223void DIALOG_SYMBOL_PROPERTIES::OnCheckBox( wxCommandEvent& event )
1224{
1225 OnModify();
1226}
1227
1228
1229void DIALOG_SYMBOL_PROPERTIES::OnUnitChoice( wxCommandEvent& event )
1230{
1231 if( m_dataModel )
1232 {
1233 EDA_ITEM_FLAGS flags = m_symbol->GetFlags();
1234
1235 int unit_selection = m_unitChoice->GetSelection() + 1;
1236
1237 // We need to select a new unit to build the new unit pin list
1238 // but we should not change the symbol, so the initial unit will be selected
1239 // after rebuilding the pin list
1240 int old_unit = m_symbol->GetUnit();
1241 m_symbol->SetUnit( unit_selection );
1242
1243 // Rebuild a copy of the pins of the new unit for editing
1244 m_dataModel->clear();
1245
1246 for( const std::unique_ptr<SCH_PIN>& pin : m_symbol->GetRawPins() )
1247 m_dataModel->push_back( *pin );
1248
1249 m_dataModel->SortRows( COL_NUMBER, true );
1250 m_dataModel->BuildAttrs();
1251
1252 m_symbol->SetUnit( old_unit );
1253
1254 // Restore m_Flag modified by SetUnit()
1255 m_symbol->ClearFlags();
1256 m_symbol->SetFlags( flags );
1257 }
1258
1259 OnModify();
1260}
1261
1262
1264{
1265 event.Enable( m_symbol && m_symbol->GetLibSymbolRef() );
1266}
1267
1268
1270{
1271 event.Enable( m_symbol && m_symbol->GetLibSymbolRef() );
1272}
1273
1274
1275void DIALOG_SYMBOL_PROPERTIES::OnPageChanging( wxBookCtrlEvent& aEvent )
1276{
1277 if( !m_fieldsGrid->CommitPendingChanges() )
1278 aEvent.Veto();
1279
1280 if( !m_pinGrid->CommitPendingChanges() )
1281 aEvent.Veto();
1282}
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 OnPinTableColSort(wxGridEvent &aEvent)
void OnMoveUp(wxCommandEvent &event) override
void OnDeleteField(wxCommandEvent &event) override
void OnAddField(wxCommandEvent &event) override
void OnGridEditorHidden(wxGridEvent &event) override
PANEL_EMBEDDED_FILES * m_embeddedFiles
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 void SetParent(EDA_ITEM *aParent)
Definition eda_item.h:113
void Offset(const VECTOR2I &aOffset)
Definition eda_text.cpp:603
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:395
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition eda_text.cpp:308
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition grid_tricks.h:61
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)
Holds all the data relating to one schematic.
Definition schematic.h:88
SCHEMATIC_SETTINGS & Settings() const
wxString ConvertKIIDsToRefs(const wxString &aSource) const
wxString GetCurrentVariant() const
Return the current variant being edited.
SCH_SHEET_PATH & CurrentSheet() const
Definition schematic.h:187
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
void SetOrdinal(int aOrdinal)
Definition sch_field.h:128
bool IsMandatory() const
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:118
wxString 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:423
const std::map< wxString, ALT > & GetAlternates() const
Definition sch_pin.h:160
ALT GetAlt(const wxString &aAlt)
Definition sch_pin.h:174
SCH_PIN * GetLibPin() const
Definition sch_pin.h:89
const wxString & GetName() const
Definition sch_pin.cpp:391
const wxString & GetBaseName() const
Get the name without any alternates.
Definition sch_pin.cpp:400
const wxString & GetNumber() const
Definition sch_pin.h:124
GRAPHIC_PINSHAPE GetShape() const
Definition sch_pin.cpp:278
ELECTRICAL_PINTYPE GetType() const
Definition sch_pin.cpp:313
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.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Schematic symbol object.
Definition sch_symbol.h:76
const std::vector< TEMPLATE_FIELDNAME > & GetTemplateFieldNames()
Return a template field name list for read only access.
wxGridCellAttr * enhanceAttr(wxGridCellAttr *aInputAttr, int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind)
Definition wx_grid.cpp:46
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:202
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:177
This file is part of the common library.
static void EnableFocusDebugging(wxWindow *aWindow, const wxString &aWindowName=wxEmptyString)
Debug helper to trap all SetFocus events on a window and its children.
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
const int minSize
Push and Shove router track width and via size dialog.
#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:162
const wxArrayString & PinTypeNames()
Definition pin_type.cpp:153
const wxArrayString & PinShapeNames()
Definition pin_type.cpp:171
const std::vector< BITMAPS > & PinShapeIcons()
Definition pin_type.cpp:180
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
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".
KIBIS_PIN * pin
VECTOR3I res
VECTOR2I end
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695