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, wxEmptyString ) );
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 =
300 pinUnits[row] > 0 ? wxString::Format( wxT( "%d" ), pinUnits[row] ) : 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
534 if( !fpid.IsEmpty() && fpId.Parse( fpid ) >= 0 )
535 {
536 wxMessageBox( _( "Invalid footprint identifier." ), _( "Assign Footprint" ), wxOK | wxICON_ERROR, this );
537 m_grid->SetCellValue( 0, aCol, currentFootprint() );
538 return;
539 }
540
541 for( const ASSOCIATED_FOOTPRINT& a : m_associations )
542 {
543 if( a.m_MapName != mapName && a.m_FootprintLibId == fpId && !fpid.IsEmpty() )
544 {
545 wxMessageBox( _( "That footprint is already assigned to another pin map." ), _( "Assign Footprint" ),
546 wxOK | wxICON_INFORMATION, this );
547 m_grid->SetCellValue( 0, aCol, currentFootprint() );
548 return;
549 }
550 }
551
552 m_associations.erase( std::remove_if( m_associations.begin(), m_associations.end(),
553 [&]( const ASSOCIATED_FOOTPRINT& a )
554 {
555 return a.m_MapName == mapName;
556 } ),
557 m_associations.end() );
558
559 if( !fpid.IsEmpty() )
560 {
562 assoc.m_FootprintLibId = fpId;
563 assoc.m_MapName = mapName;
564 m_associations.push_back( std::move( assoc ) );
565
566 m_grid->SetCellValue( 0, aCol, fpId.GetUniStringLibId() );
567 }
568 else
569 {
570 m_grid->SetCellValue( 0, aCol, wxEmptyString );
571 }
572
573 for( int row = 1; row < m_grid->GetNumberRows(); ++row )
574 ValidateCell( row, aCol );
575
576 m_grid->ForceRefresh();
577}
578
579
581{
582 if( m_grid->GetNumberCols() == 0 )
583 return;
584
585 for( int col = 0; col < FIXED_COLS; ++col )
586 m_grid->AutoSizeColumn( col, false );
587
588 int fixedWidth = 0;
589
590 for( int col = 0; col < FIXED_COLS; ++col )
591 fixedWidth += m_grid->GetColSize( col );
592
593 const int padCols = m_grid->GetNumberCols() - FIXED_COLS;
594
595 if( padCols <= 0 )
596 return;
597
598 const int remaining = std::max( m_grid->GetClientSize().GetWidth() - fixedWidth, padCols * 80 );
599
600 for( int col = FIXED_COLS; col < m_grid->GetNumberCols(); ++col )
601 m_grid->SetColSize( col, remaining / padCols );
602}
603
604
606{
607 // Preserve maps no footprint references so a free-standing map survives a round-trip.
608 // Associations are kept as-is and edited separately.
609 std::vector<wxString> names;
610
611 for( const PIN_MAP& map : m_pinMaps.GetAll() )
612 names.push_back( map.GetName() );
613
614 PIN_MAP_SET rebuilt;
615
616 for( size_t col = 0; col < names.size(); ++col )
617 {
618 PIN_MAP map( names[col] );
619
620 for( size_t row = 0; row < m_pinNumbers.size(); ++row )
621 {
622 const wxString pad = m_grid->GetCellValue( (int) row + 1, FIXED_COLS + (int) col );
623
624 if( !pad.IsEmpty() && pad != m_pinNumbers[row] )
625 map.SetEntry( m_pinNumbers[row], pad );
626 }
627
628 rebuilt.AddOrReplace( std::move( map ) );
629 }
630
631 m_pinMaps = std::move( rebuilt );
632}
633
634
636{
637 int suffix = 1;
638
639 while( true )
640 {
641 wxString candidate = wxString::Format( wxT( "map%d" ), suffix++ );
642
643 if( !m_pinMaps.FindByName( candidate ) )
644 return candidate;
645 }
646}
647
648
649const std::set<wxString>& PANEL_SYMBOL_PIN_MAP::padNumbersFor( const wxString& aFootprintId )
650{
651 auto it = m_footprintPads.find( aFootprintId );
652
653 if( it != m_footprintPads.end() )
654 return it->second;
655
656 std::set<wxString>& pads = m_footprintPads[aFootprintId];
657
658 if( aFootprintId.IsEmpty() )
659 return pads;
660
661 if( KIWAY_HOLDER* holder = dynamic_cast<KIWAY_HOLDER*>( wxGetTopLevelParent( this ) ) )
662 {
663 if( KIFACE* cvpcb = holder->Kiway().KiFACE( KIWAY::FACE_CVPCB ) )
664 {
665 typedef void ( *PAD_NUMBERS_FN_PTR )( const wxString&, PROJECT*, std::set<wxString>& );
666
667 if( auto fetch = (PAD_NUMBERS_FN_PTR) cvpcb->IfaceOrAddress( KIFACE_FOOTPRINT_PAD_NUMBERS ) )
668 fetch( aFootprintId, &holder->Prj(), pads );
669 }
670 }
671
672 return pads;
673}
674
675
676void PANEL_SYMBOL_PIN_MAP::OnAddMap( wxCommandEvent& aEvent )
677{
678 if( !m_grid->CommitPendingChanges() )
679 return;
680
681 harvestGrid();
682 m_pinMaps.AddOrReplace( PIN_MAP( makeUniqueMapName() ) );
683 rebuildGrid();
684}
685
686
687void PANEL_SYMBOL_PIN_MAP::OnRemoveMap( wxCommandEvent& aEvent )
688{
689 if( !m_grid->CommitPendingChanges() )
690 return;
691
692 const std::vector<PIN_MAP>& maps = m_pinMaps.GetAll();
693
694 if( maps.empty() )
695 return;
696
697 int col = m_grid->GetGridCursorCol();
698
699 if( col < FIXED_COLS )
700 {
701 if( maps.size() > 1 )
702 {
703 wxMessageBox( _( "Click a pin map column to choose which map to remove." ), _( "Remove Pin Map" ),
704 wxOK | wxICON_INFORMATION, this );
705 return;
706 }
707
708 col = FIXED_COLS;
709 }
710
711 const size_t index = (size_t) ( col - FIXED_COLS );
712
713 if( index >= maps.size() )
714 return;
715
716 const wxString mapName = maps[index].GetName();
717
718 bool hasAssociation = std::any_of( m_associations.begin(), m_associations.end(),
719 [&]( const ASSOCIATED_FOOTPRINT& a )
720 {
721 return a.m_MapName == mapName;
722 } );
723
724 if( hasAssociation
725 && !IsOK( this, wxString::Format( _( "Remove pin map '%s' and its footprint association?" ), mapName ) ) )
726 {
727 return;
728 }
729
730 harvestGrid();
731
732 m_pinMaps.Remove( mapName );
733
734 m_associations.erase( std::remove_if( m_associations.begin(), m_associations.end(),
735 [&]( const ASSOCIATED_FOOTPRINT& a )
736 {
737 return a.m_MapName == mapName;
738 } ),
739 m_associations.end() );
740
741 rebuildGrid();
742}
743
744
745void PANEL_SYMBOL_PIN_MAP::OnSizeGrid( wxSizeEvent& aEvent )
746{
748 aEvent.Skip();
749}
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:65
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:320
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
wxString GetUniStringLibId() const
Definition lib_id.h:144
Define a library symbol object.
Definition lib_symbol.h:80
void SetAssociatedFootprints(std::vector< ASSOCIATED_FOOTPRINT > aList)
Definition lib_symbol.h:228
void SetPinMaps(const PIN_MAP_SET &aPinMaps)
Definition lib_symbol.h:224
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:123
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:64
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:62
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:62
bool IsDarkTheme()
Determine if the desktop interface is currently using a dark theme or a light theme.
Definition wxgtk/ui.cpp:50
@ 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:158
LIB_ID m_FootprintLibId
Definition pin_map.h:159
Implement a participant in the KIWAY alchemy.
Definition kiway.h:152
Logical pins: Return expanded logical pins based on stacked-pin notation.
Definition lib_symbol.h:635