KiCad PCB EDA Suite
Loading...
Searching...
No Matches
panel_symbol_pin_map.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 modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
21
22#include <algorithm>
23#include <map>
24#include <set>
25
26#include <wx/menu.h>
27#include <wx/msgdlg.h>
28#include <wx/textdlg.h>
29#include <wx/wupdlock.h>
30
31#include <bitmaps.h>
32#include <confirm.h>
33#include <dialog_shim.h>
34#include <grid_tricks.h>
35#include <kiface_ids.h>
36#include <kiplatform/ui.h>
37#include <kiway.h>
38#include <kiway_holder.h>
39#include <lib_id.h>
40#include <lib_symbol.h>
41#include <sch_pin.h>
42#include <string_utils.h>
45#include <widgets/wx_grid.h>
46
47
48// Menu ids carved out of the GRID_TRICKS client range so they coexist with the base cut/copy/paste.
49enum
50{
54};
55
56
59{
60public:
62 GRID_TRICKS( aGrid ),
63 m_panel( aPanel )
64 {
65 }
66
67protected:
68 void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent ) override
69 {
70 const int col = aEvent.GetCol();
71
72 m_menuCol = col;
73 m_copyFromCols.clear();
74
76 {
77 menu.Append( PIN_MAP_MENU_RENAME, _( "Rename Map..." ) );
78 menu.Append( PIN_MAP_MENU_RESET_COLUMN,
79 wxString::Format( _( "Reset '%s' to 1:1" ), m_panel->GetColumnMapName( col ) ) );
80
81 wxMenu* copyMenu = new wxMenu;
83
84 for( int other = PANEL_SYMBOL_PIN_MAP::FIXED_COLS; other < m_grid->GetNumberCols(); ++other )
85 {
86 if( other == col )
87 continue;
88
89 copyMenu->Append( copyId, m_panel->GetColumnMapName( other ) );
90 m_copyFromCols[copyId] = other;
91 ++copyId;
92 }
93
94 if( copyMenu->GetMenuItemCount() > 0 )
95 menu.Append( wxID_ANY, _( "Copy From..." ), copyMenu );
96 else
97 delete copyMenu;
98
99 menu.AppendSeparator();
100 }
101
102 GRID_TRICKS::showPopupMenu( menu, aEvent );
103 }
104
105 void doPopupSelection( wxCommandEvent& aEvent ) override
106 {
107 const int id = aEvent.GetId();
108
109 if( id == PIN_MAP_MENU_RESET_COLUMN )
110 {
111 m_panel->ResetColumnToIdentity( m_menuCol );
112 }
113 else if( id == PIN_MAP_MENU_RENAME )
114 {
115 m_panel->RenameColumn( m_menuCol );
116 }
117 else if( m_copyFromCols.count( id ) )
118 {
119 m_panel->CopyColumn( m_copyFromCols[id], m_menuCol );
120 }
121 else
122 {
124 }
125 }
126
127private:
129 int m_menuCol = -1;
130 std::map<int, int> m_copyFromCols;
131};
132
133
135 PANEL_SYMBOL_PIN_MAP_BASE( aParent ),
136 m_symbol( nullptr )
137{
138 m_grid->SetUseNativeColLabels();
139 m_grid->ClearGrid();
140
141 if( m_grid->GetNumberCols() > 0 )
142 m_grid->DeleteCols( 0, m_grid->GetNumberCols() );
143
144 m_grid->AppendCols( FIXED_COLS );
145 m_grid->SetColLabelValue( 0, _( "Unit" ) );
146 m_grid->SetColLabelValue( 1, _( "Symbol Pin" ) );
147 m_grid->SetColLabelValue( 2, _( "Name" ) );
148
151
152 m_gridTricks = std::make_unique<PIN_MAP_GRID_TRICKS>( m_grid, this );
153 m_grid->PushEventHandler( m_gridTricks.get() );
154
155 m_grid->Bind( wxEVT_GRID_CELL_CHANGED, &PANEL_SYMBOL_PIN_MAP::onCellChanged, this );
156 m_grid->Bind( wxEVT_GRID_LABEL_LEFT_DCLICK, &PANEL_SYMBOL_PIN_MAP::onLabelDClick, this );
157}
158
159
161{
162 m_grid->PopEventHandler();
163}
164
165
167{
168 m_symbol = aSymbol;
169
170 m_pinNumbers.clear();
172 m_associations.clear();
173
174 if( !m_symbol )
175 return;
176
177 std::set<wxString> seen;
178
179 for( const LIB_SYMBOL::LOGICAL_PIN& logical : m_symbol->GetLogicalPins( 0, 0 ) )
180 {
181 if( seen.insert( logical.number ).second )
182 m_pinNumbers.push_back( logical.number );
183 }
184
185 m_pinMaps = m_symbol->GetPinMaps();
186 m_associations = m_symbol->GetAssociatedFootprints();
187}
188
189
191{
192 rebuildGrid();
193 return true;
194}
195
196
198{
199 if( !m_grid->CommitPendingChanges() )
200 return false;
201
202 if( m_symbol )
204
205 return true;
206}
207
208
210{
211 return m_grid->CommitPendingChanges();
212}
213
214
216{
217 if( !aSymbol )
218 return;
219
220 harvestGrid();
221
222 aSymbol->SetPinMaps( m_pinMaps );
224}
225
226
228{
229 wxWindowUpdateLocker lock( m_grid );
230
231 const std::vector<PIN_MAP>& maps = m_pinMaps.GetAll();
232 const int wantCols = FIXED_COLS + (int) maps.size();
233
234 if( m_grid->GetNumberCols() > wantCols )
235 m_grid->DeleteCols( wantCols, m_grid->GetNumberCols() - wantCols );
236 else if( m_grid->GetNumberCols() < wantCols )
237 m_grid->AppendCols( wantCols - m_grid->GetNumberCols() );
238
239 for( size_t ii = 0; ii < maps.size(); ++ii )
240 m_grid->SetColLabelValue( FIXED_COLS + (int) ii, maps[ii].GetName() );
241
242 if( m_grid->GetNumberRows() > 0 )
243 m_grid->DeleteRows( 0, m_grid->GetNumberRows() );
244
245 m_grid->AppendRows( (int) m_pinNumbers.size() + 1 );
246
247 m_grid->SetCellSize( 0, 0, 1, FIXED_COLS );
248 m_grid->SetCellValue( 0, 0, _( "Footprint" ) );
249 m_grid->SetReadOnly( 0, 0 );
250
251 DIALOG_SHIM* dlg = dynamic_cast<DIALOG_SHIM*>( wxGetTopLevelParent( this ) );
252
253 for( size_t col = 0; col < maps.size(); ++col )
254 {
255 wxString footprint;
256
257 for( const ASSOCIATED_FOOTPRINT& assoc : m_associations )
258 {
259 if( assoc.m_MapName == maps[col].GetName() )
260 {
261 footprint = assoc.m_FootprintLibId.GetUniStringLibId();
262 break;
263 }
264 }
265
266 m_grid->SetCellValue( 0, FIXED_COLS + (int) col, footprint );
267
268 if( dlg )
269 m_grid->SetCellEditor( 0, FIXED_COLS + (int) col, new GRID_CELL_FPID_EDITOR( dlg ) );
270 else
271 m_grid->SetReadOnly( 0, FIXED_COLS + (int) col );
272 }
273
274 std::vector<wxString> pinNames( m_pinNumbers.size() );
275 std::vector<int> pinUnits( m_pinNumbers.size(), 0 );
276
277 if( m_symbol )
278 {
279 for( const LIB_SYMBOL::LOGICAL_PIN& logical : m_symbol->GetLogicalPins( 0, 0 ) )
280 {
281 auto it = std::find( m_pinNumbers.begin(), m_pinNumbers.end(), logical.number );
282
283 if( it == m_pinNumbers.end() )
284 continue;
285
286 const size_t row = std::distance( m_pinNumbers.begin(), it );
287
288 if( pinNames[row].IsEmpty() && logical.pin )
289 {
290 pinNames[row] = logical.pin->GetName();
291 pinUnits[row] = logical.pin->GetUnit();
292 }
293 }
294 }
295
296 for( size_t row = 0; row < m_pinNumbers.size(); ++row )
297 {
298 const int gridRow = (int) row + 1;
299 const wxString unit = pinUnits[row] > 0 ? wxString::Format( wxT( "%d" ), pinUnits[row] )
300 : wxString( wxT( "-" ) );
301
302 m_grid->SetCellValue( gridRow, 0, unit );
303 m_grid->SetCellValue( gridRow, 1, m_pinNumbers[row] );
304 m_grid->SetCellValue( gridRow, 2, pinNames[row] );
305
306 m_grid->SetReadOnly( gridRow, 0 );
307 m_grid->SetReadOnly( gridRow, 1 );
308 m_grid->SetReadOnly( gridRow, 2 );
309
310 for( size_t col = 0; col < maps.size(); ++col )
311 {
312 wxString pad = m_pinNumbers[row];
313
314 if( maps[col].HasEntry( m_pinNumbers[row] ) )
315 pad = maps[col].GetPadNumber( m_pinNumbers[row] );
316
317 m_grid->SetCellValue( gridRow, FIXED_COLS + (int) col, pad );
318 }
319 }
320
323 m_removeMapButton->Enable( !maps.empty() );
324}
325
326
328{
329 for( int row = 1; row < m_grid->GetNumberRows(); ++row )
330 {
331 for( int col = FIXED_COLS; col < m_grid->GetNumberCols(); ++col )
332 ValidateCell( row, col );
333 }
334}
335
336
337void PANEL_SYMBOL_PIN_MAP::ValidateCell( int aRow, int aCol )
338{
339 if( aRow < 1 || aRow >= m_grid->GetNumberRows() || aCol < FIXED_COLS || aCol >= m_grid->GetNumberCols() )
340 return;
341
342 const wxString pad = m_grid->GetCellValue( aRow, aCol );
343
344 // A blank pad means the pin resolves 1:1 by identity, which is always valid. Malformed bracketed
345 // stacked syntax is flagged red. A syntactically valid pad absent from the map's footprints is
346 // flagged yellow.
347 bool valid = true;
348 std::vector<wxString> expanded;
349
350 if( !pad.IsEmpty() )
351 expanded = ExpandStackedPinNotation( pad, &valid );
352
353 const wxColour defaultColour = m_grid->GetDefaultCellBackgroundColour();
354 wxColour background = defaultColour;
355
356 if( !valid )
357 {
358 background.Set( 255, 190, 190 );
359 }
360 else if( !expanded.empty() )
361 {
362 const size_t index = (size_t) ( aCol - FIXED_COLS );
363 const std::vector<PIN_MAP>& maps = m_pinMaps.GetAll();
364
365 if( index < maps.size() )
366 {
367 std::set<wxString> pads;
368
369 for( const ASSOCIATED_FOOTPRINT& assoc : m_associations )
370 {
371 if( assoc.m_MapName != maps[index].GetName() )
372 continue;
373
374 const std::set<wxString>& fpPads = padNumbersFor( assoc.m_FootprintLibId.GetUniStringLibId() );
375 pads.insert( fpPads.begin(), fpPads.end() );
376 }
377
378 if( !pads.empty()
379 && std::any_of( expanded.begin(), expanded.end(),
380 [&]( const wxString& p )
381 {
382 return !pads.count( p );
383 } ) )
384 {
385 background.Set( 250, 230, 150 );
386 }
387 }
388 }
389
390 if( background != defaultColour && KIPLATFORM::UI::IsDarkTheme() )
391 background = background.ChangeLightness( 50 );
392
393 m_grid->SetCellBackgroundColour( aRow, aCol, background );
394}
395
396
397void PANEL_SYMBOL_PIN_MAP::onCellChanged( wxGridEvent& aEvent )
398{
399 if( aEvent.GetRow() == 0 && aEvent.GetCol() >= FIXED_COLS )
400 {
401 applyColumnFootprint( aEvent.GetCol(), m_grid->GetCellValue( 0, aEvent.GetCol() ) );
402 aEvent.Skip();
403 return;
404 }
405
406 ValidateCell( aEvent.GetRow(), aEvent.GetCol() );
407 m_grid->ForceRefresh();
408 aEvent.Skip();
409}
410
411
412void PANEL_SYMBOL_PIN_MAP::onLabelDClick( wxGridEvent& aEvent )
413{
414 if( aEvent.GetCol() >= FIXED_COLS )
415 RenameColumn( aEvent.GetCol() );
416 else
417 aEvent.Skip();
418}
419
420
422{
423 const size_t index = (size_t) ( aCol - FIXED_COLS );
424 const std::vector<PIN_MAP>& maps = m_pinMaps.GetAll();
425
426 if( index >= maps.size() )
427 return wxEmptyString;
428
429 return maps[index].GetName();
430}
431
432
434{
435 if( !m_grid->CommitPendingChanges() || aCol < FIXED_COLS || aCol >= m_grid->GetNumberCols() )
436 return;
437
438 for( int row = 1; row < m_grid->GetNumberRows(); ++row )
439 {
440 m_grid->SetCellValue( row, aCol, m_grid->GetCellValue( row, 1 ) );
441 ValidateCell( row, aCol );
442 }
443
444 m_grid->ForceRefresh();
445}
446
447
448void PANEL_SYMBOL_PIN_MAP::CopyColumn( int aSrcCol, int aDstCol )
449{
450 if( !m_grid->CommitPendingChanges() )
451 return;
452
453 if( aSrcCol < FIXED_COLS || aSrcCol >= m_grid->GetNumberCols() )
454 return;
455
456 if( aDstCol < FIXED_COLS || aDstCol >= m_grid->GetNumberCols() )
457 return;
458
459 for( int row = 1; row < m_grid->GetNumberRows(); ++row )
460 {
461 m_grid->SetCellValue( row, aDstCol, m_grid->GetCellValue( row, aSrcCol ) );
462 ValidateCell( row, aDstCol );
463 }
464
465 m_grid->ForceRefresh();
466}
467
468
470{
471 if( !m_grid->CommitPendingChanges() || aCol < FIXED_COLS || aCol >= m_grid->GetNumberCols() )
472 return;
473
474 const wxString oldName = GetColumnMapName( aCol );
475
476 if( oldName.IsEmpty() )
477 return;
478
479 wxTextEntryDialog dlg( this, _( "Map name:" ), _( "Rename Map" ), oldName );
480
481 if( dlg.ShowModal() != wxID_OK )
482 return;
483
484 const wxString newName = dlg.GetValue().Trim().Trim( false );
485
486 if( newName.IsEmpty() || newName == oldName )
487 return;
488
489 if( m_pinMaps.FindByName( newName ) )
490 {
491 wxMessageBox( wxString::Format( _( "A pin map named '%s' already exists." ), newName ), _( "Rename Map" ),
492 wxOK | wxICON_ERROR, this );
493 return;
494 }
495
496 harvestGrid();
497
498 if( PIN_MAP* map = m_pinMaps.FindByName( oldName ) )
499 map->SetName( newName );
500
502 {
503 if( assoc.m_MapName == oldName )
504 assoc.m_MapName = newName;
505 }
506
507 rebuildGrid();
508}
509
510
511void PANEL_SYMBOL_PIN_MAP::applyColumnFootprint( int aCol, const wxString& aFootprintId )
512{
513 const wxString mapName = GetColumnMapName( aCol );
514
515 if( mapName.IsEmpty() )
516 return;
517
518 auto currentFootprint = [&]() -> wxString
519 {
520 for( const ASSOCIATED_FOOTPRINT& a : m_associations )
521 {
522 if( a.m_MapName == mapName )
523 return a.m_FootprintLibId.GetUniStringLibId();
524 }
525
526 return wxEmptyString;
527 };
528
529 wxString fpid = aFootprintId;
530 fpid.Trim().Trim( false );
531
532 LIB_ID fpId;
533 fpId.Parse( fpid );
534
535 if( !fpId.IsValid() )
536 {
537 wxMessageBox( _( "Invalid footprint identifier." ), _( "Assign Footprint" ), wxOK | wxICON_ERROR, this );
538 m_grid->SetCellValue( 0, aCol, currentFootprint() );
539 return;
540 }
541
542 for( const ASSOCIATED_FOOTPRINT& a : m_associations )
543 {
544 if( a.m_MapName != mapName && a.m_FootprintLibId == fpId && !fpid.IsEmpty() )
545 {
546 wxMessageBox( _( "That footprint is already assigned to another pin map." ), _( "Assign Footprint" ),
547 wxOK | wxICON_INFORMATION, this );
548 m_grid->SetCellValue( 0, aCol, currentFootprint() );
549 return;
550 }
551 }
552
553 m_associations.erase( std::remove_if( m_associations.begin(), m_associations.end(),
554 [&]( const ASSOCIATED_FOOTPRINT& a )
555 {
556 return a.m_MapName == mapName;
557 } ),
558 m_associations.end() );
559
560 if( !fpid.IsEmpty() )
561 {
563 assoc.m_FootprintLibId = fpId;
564 assoc.m_MapName = mapName;
565 m_associations.push_back( std::move( assoc ) );
566
567 m_grid->SetCellValue( 0, aCol, fpId.GetUniStringLibId() );
568 }
569 else
570 {
571 m_grid->SetCellValue( 0, aCol, wxEmptyString );
572 }
573
574 for( int row = 1; row < m_grid->GetNumberRows(); ++row )
575 ValidateCell( row, aCol );
576
577 m_grid->ForceRefresh();
578}
579
580
582{
583 if( m_grid->GetNumberCols() == 0 )
584 return;
585
586 for( int col = 0; col < FIXED_COLS; ++col )
587 m_grid->AutoSizeColumn( col, false );
588
589 int fixedWidth = 0;
590
591 for( int col = 0; col < FIXED_COLS; ++col )
592 fixedWidth += m_grid->GetColSize( col );
593
594 const int padCols = m_grid->GetNumberCols() - FIXED_COLS;
595
596 if( padCols <= 0 )
597 return;
598
599 const int remaining = m_grid->GetClientSize().GetWidth() - fixedWidth;
600
601 for( int col = FIXED_COLS; col < m_grid->GetNumberCols(); ++col )
602 m_grid->SetColSize( col, std::max( remaining / padCols, 84 ) );
603}
604
605
607{
608 // Preserve maps no footprint references so a free-standing map survives a round-trip.
609 // Associations are kept as-is and edited separately.
610 std::vector<wxString> names;
611
612 for( const PIN_MAP& map : m_pinMaps.GetAll() )
613 names.push_back( map.GetName() );
614
615 PIN_MAP_SET rebuilt;
616
617 for( size_t col = 0; col < names.size(); ++col )
618 {
619 PIN_MAP map( names[col] );
620
621 for( size_t row = 0; row < m_pinNumbers.size(); ++row )
622 {
623 const wxString pad = m_grid->GetCellValue( (int) row + 1, FIXED_COLS + (int) col );
624
625 if( !pad.IsEmpty() && pad != m_pinNumbers[row] )
626 map.SetEntry( m_pinNumbers[row], pad );
627 }
628
629 rebuilt.AddOrReplace( std::move( map ) );
630 }
631
632 m_pinMaps = std::move( rebuilt );
633}
634
635
637{
638 int suffix = 1;
639
640 while( true )
641 {
642 wxString candidate = wxString::Format( wxT( "map%d" ), suffix++ );
643
644 if( !m_pinMaps.FindByName( candidate ) )
645 return candidate;
646 }
647}
648
649
650const std::set<wxString>& PANEL_SYMBOL_PIN_MAP::padNumbersFor( const wxString& aFootprintId )
651{
652 auto it = m_footprintPads.find( aFootprintId );
653
654 if( it != m_footprintPads.end() )
655 return it->second;
656
657 std::set<wxString>& pads = m_footprintPads[aFootprintId];
658
659 if( aFootprintId.IsEmpty() )
660 return pads;
661
662 if( KIWAY_HOLDER* holder = dynamic_cast<KIWAY_HOLDER*>( wxGetTopLevelParent( this ) ) )
663 {
664 if( KIFACE* cvpcb = holder->Kiway().KiFACE( KIWAY::FACE_CVPCB ) )
665 {
666 typedef void ( *PAD_NUMBERS_FN_PTR )( const wxString&, PROJECT*, std::set<wxString>& );
667
668 if( auto fetch = (PAD_NUMBERS_FN_PTR) cvpcb->IfaceOrAddress( KIFACE_FOOTPRINT_PAD_NUMBERS ) )
669 fetch( aFootprintId, &holder->Prj(), pads );
670 }
671 }
672
673 return pads;
674}
675
676
677void PANEL_SYMBOL_PIN_MAP::OnAddMap( wxCommandEvent& aEvent )
678{
679 if( !m_grid->CommitPendingChanges() )
680 return;
681
682 harvestGrid();
683 m_pinMaps.AddOrReplace( PIN_MAP( makeUniqueMapName() ) );
684 rebuildGrid();
685}
686
687
688void PANEL_SYMBOL_PIN_MAP::OnRemoveMap( wxCommandEvent& aEvent )
689{
690 if( !m_grid->CommitPendingChanges() )
691 return;
692
693 const std::vector<PIN_MAP>& maps = m_pinMaps.GetAll();
694
695 if( maps.empty() )
696 return;
697
698 int col = m_grid->GetGridCursorCol();
699
700 if( col < FIXED_COLS )
701 {
702 if( maps.size() > 1 )
703 {
704 wxMessageBox( _( "Click a pin map column to choose which map to remove." ), _( "Remove Pin Map" ),
705 wxOK | wxICON_INFORMATION, this );
706 return;
707 }
708
709 col = FIXED_COLS;
710 }
711
712 const size_t index = (size_t) ( col - FIXED_COLS );
713
714 if( index >= maps.size() )
715 return;
716
717 const wxString mapName = maps[index].GetName();
718
719 bool hasAssociation = std::any_of( m_associations.begin(), m_associations.end(),
720 [&]( const ASSOCIATED_FOOTPRINT& a )
721 {
722 return a.m_MapName == mapName;
723 } );
724
725 if( hasAssociation
726 && !IsOK( this, wxString::Format( _( "Remove pin map '%s' and its footprint association?" ), mapName ) ) )
727 {
728 return;
729 }
730
731 harvestGrid();
732
733 m_pinMaps.Remove( mapName );
734
735 m_associations.erase( std::remove_if( m_associations.begin(), m_associations.end(),
736 [&]( const ASSOCIATED_FOOTPRINT& a )
737 {
738 return a.m_MapName == mapName;
739 } ),
740 m_associations.end() );
741
742 rebuildGrid();
743}
744
745
746void PANEL_SYMBOL_PIN_MAP::OnSizeGrid( wxSizeEvent& aEvent )
747{
749 aEvent.Skip();
750}
int index
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:106
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition dialog_shim.h:80
GRID_TRICKS(WX_GRID *aGrid)
virtual void doPopupSelection(wxCommandEvent &event)
virtual void showPopupMenu(wxMenu &menu, wxGridEvent &aEvent)
WX_GRID * m_grid
I don't own the grid, but he owns me.
A mix in class which holds the location of a wxWindow's KIWAY.
@ FACE_CVPCB
Definition kiway.h:357
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition lib_id.cpp:65
bool IsValid() const
Check if this LID_ID is valid.
Definition lib_id.h:168
wxString GetUniStringLibId() const
Definition lib_id.h:144
Define a library symbol object.
Definition lib_symbol.h:114
void SetAssociatedFootprints(std::vector< ASSOCIATED_FOOTPRINT > aList)
Definition lib_symbol.h:272
void SetPinMaps(const PIN_MAP_SET &aPinMaps)
Definition lib_symbol.h:268
PANEL_SYMBOL_PIN_MAP_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
Composed widget that edits a symbol's named pin maps and the footprint each is bound to.
static constexpr int FIXED_COLS
Number of fixed leading columns (unit, pin number, pin name).
void rebuildGrid()
Rebuild the whole grid from the working model.
void ValidateCell(int aRow, int aCol)
Re-evaluate the colour of pad cell (aRow, aCol) from its current contents.
std::vector< ASSOCIATED_FOOTPRINT > m_associations
void RenameColumn(int aCol)
Prompt for a new name for column aCol's map and update every reference to it.
void OnAddMap(wxCommandEvent &aEvent) override
const std::set< wxString > & padNumbersFor(const wxString &aFootprintId)
void onLabelDClick(wxGridEvent &aEvent)
Double-clicking a map column's header opens its rename dialog.
PANEL_SYMBOL_PIN_MAP(wxWindow *aParent)
void harvestGrid()
Read every pad cell back into the working pin maps.
void CopyColumn(int aSrcCol, int aDstCol)
Copy every pad value from column aSrcCol into column aDstCol.
void onCellChanged(wxGridEvent &aEvent)
std::vector< wxString > m_pinNumbers
void applyColumnFootprint(int aCol, const wxString &aFootprintId)
Bind (or clear, when empty) the footprint entered in column aCol's footprint cell.
void ApplyToSymbol(LIB_SYMBOL *aSymbol)
Write the edited pin maps and associations into aSymbol.
wxString makeUniqueMapName() const
bool TransferDataToWindow() override
void ResetColumnToIdentity(int aCol)
Set every cell in pad column aCol back to its row's symbol pin number (1:1).
void SetSymbol(LIB_SYMBOL *aSymbol)
Load the editable state from aSymbol.
void OnSizeGrid(wxSizeEvent &aEvent) override
std::map< wxString, std::set< wxString > > m_footprintPads
bool CommitPendingChanges()
Commit any in-progress grid cell edit;.
bool TransferDataFromWindow() override
void validateAllCells()
Re-evaluate the colour of every pad cell.
void OnRemoveMap(wxCommandEvent &aEvent) override
std::unique_ptr< PIN_MAP_GRID_TRICKS > m_gridTricks
void adjustGridColumns()
Resize the pad columns to fill the available width.
wxString GetColumnMapName(int aCol) const
std::map< int, int > m_copyFromCols
void showPopupMenu(wxMenu &menu, wxGridEvent &aEvent) override
PANEL_SYMBOL_PIN_MAP * m_panel
void doPopupSelection(wxCommandEvent &aEvent) override
PIN_MAP_GRID_TRICKS(WX_GRID *aGrid, PANEL_SYMBOL_PIN_MAP *aPanel)
A symbol-owned ordered set of named pin maps.
Definition pin_map.h:124
void AddOrReplace(PIN_MAP aMap)
Insert aMap, replacing any existing entry with the same name.
Definition pin_map.cpp:113
A named pin map.
Definition pin_map.h:65
void SetEntry(const wxString &aPinNumber, const wxString &aPadNumber)
Set the pad number for a symbol pin.
Definition pin_map.cpp:59
Container for project specific data.
Definition project.h:63
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:274
This file is part of the common library.
#define _(s)
@ GRIDTRICKS_FIRST_CLIENT_ID
Definition grid_tricks.h:44
@ KIFACE_FOOTPRINT_PAD_NUMBERS
Function pointer type: void (*)( const wxString& aFootprint, PROJECT* aProject, std::set<wxString>& a...
Definition kiface_ids.h:72
bool IsDarkTheme()
Determine if the desktop interface is currently using a dark theme or a light theme.
Definition wxgtk/ui.cpp:51
@ PIN_MAP_MENU_RENAME
@ PIN_MAP_MENU_RESET_COLUMN
@ PIN_MAP_MENU_COPY_FROM_FIRST
std::vector< wxString > ExpandStackedPinNotation(const wxString &aPinName, bool *aValid)
Expand stacked pin notation like [1,2,3], [1-4], [A1-A4], or [AA1-AA3,AB4,CD12-CD14] into individual ...
A first-class footprint choice on a LIB_SYMBOL, tied to a named pin map.
Definition pin_map.h:159
LIB_ID m_FootprintLibId
Definition pin_map.h:160
Implement a participant in the KIWAY alchemy.
Definition kiway.h:153
Logical pins: Return expanded logical pins based on stacked-pin notation.
Definition lib_symbol.h:715