KiCad PCB EDA Suite
dialog_lib_edit_pin_table.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 (C) 1992-2020 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 #include "grid_tricks.h"
26 #include "lib_pin.h"
27 #include "pin_number.h"
28 #include <bitmaps.h>
29 #include <confirm.h>
30 #include <lib_edit_frame.h>
31 #include <libedit_settings.h>
33 #include <widgets/wx_grid.h>
34 #include <pgm_base.h>
36 
37 class PIN_TABLE_DATA_MODEL : public wxGridTableBase
38 {
39 
40 private:
41  // Because the rows of the grid can either be a single pin or a group of pins, the
42  // data model is a 2D vector. If we're in the single pin case, each row's LIB_PINS
43  // contains only a single pin.
44  std::vector<LIB_PINS> m_rows;
45 
47  bool m_edited;
48 
49 public:
50  PIN_TABLE_DATA_MODEL( EDA_UNITS aUserUnits ) : m_userUnits( aUserUnits ), m_edited( false )
51  {
52  }
53 
54  int GetNumberRows() override { return (int) m_rows.size(); }
55  int GetNumberCols() override { return COL_COUNT; }
56 
57  wxString GetColLabelValue( int aCol ) override
58  {
59  switch( aCol )
60  {
61  case COL_NUMBER: return _( "Number" );
62  case COL_NAME: return _( "Name" );
63  case COL_TYPE: return _( "Electrical Type" );
64  case COL_SHAPE: return _( "Graphic Style" );
65  case COL_ORIENTATION: return _( "Orientation" );
66  case COL_NUMBER_SIZE: return _( "Number Text Size" );
67  case COL_NAME_SIZE: return _( "Name Text Size" );
68  case COL_LENGTH: return _( "Length" );
69  case COL_POSX: return _( "X Position" );
70  case COL_POSY: return _( "Y Position" );
71  default: wxFAIL; return wxEmptyString;
72  }
73  }
74 
75  bool IsEmptyCell( int row, int col ) override
76  {
77  return false; // don't allow adjacent cell overflow, even if we are actually empty
78  }
79 
80  wxString GetValue( int aRow, int aCol ) override
81  {
82  return GetValue( m_rows[ aRow ], aCol, m_userUnits );
83  }
84 
85  static wxString GetValue( const LIB_PINS& pins, int aCol, EDA_UNITS aUserUnits )
86  {
87  wxString fieldValue;
88 
89  if( pins.empty())
90  return fieldValue;
91 
92  for( LIB_PIN* pin : pins )
93  {
94  wxString val;
95 
96  switch( aCol )
97  {
98  case COL_NUMBER:
99  val = pin->GetNumber();
100  break;
101  case COL_NAME:
102  val = pin->GetName();
103  break;
104  case COL_TYPE:
105  val = PinTypeNames()[static_cast<int>( pin->GetType() )];
106  break;
107  case COL_SHAPE:
108  val = PinShapeNames()[static_cast<int>( pin->GetShape() )];
109  break;
110  case COL_ORIENTATION:
111  if( PinOrientationIndex( pin->GetOrientation() ) >= 0 )
112  val = PinOrientationNames()[ PinOrientationIndex( pin->GetOrientation() ) ];
113  break;
114  case COL_NUMBER_SIZE:
115  val = StringFromValue( aUserUnits, pin->GetNumberTextSize(), true, true );
116  break;
117  case COL_NAME_SIZE:
118  val = StringFromValue( aUserUnits, pin->GetNameTextSize(), true, true );
119  break;
120  case COL_LENGTH:
121  val = StringFromValue( aUserUnits, pin->GetLength(), true );
122  break;
123  case COL_POSX:
124  val = StringFromValue( aUserUnits, pin->GetPosition().x, true );
125  break;
126  case COL_POSY:
127  val = StringFromValue( aUserUnits, pin->GetPosition().y, true );
128  break;
129  default:
130  wxFAIL;
131  break;
132  }
133 
134  if( aCol == COL_NUMBER )
135  {
136  if( fieldValue.length() )
137  fieldValue += wxT( ", " );
138  fieldValue += val;
139  }
140  else
141  {
142  if( !fieldValue.Length() )
143  fieldValue = val;
144  else if( val != fieldValue )
145  fieldValue = INDETERMINATE_STATE;
146  }
147  }
148 
149  return fieldValue;
150  }
151 
152  void SetValue( int aRow, int aCol, const wxString &aValue ) override
153  {
154  if( aValue == INDETERMINATE_STATE )
155  return;
156 
157  LIB_PINS pins = m_rows[ aRow ];
158 
159  for( LIB_PIN* pin : pins )
160  {
161  switch( aCol )
162  {
163  case COL_NUMBER:
164  pin->SetNumber( aValue );
165  break;
166 
167  case COL_NAME:
168  pin->SetName( aValue );
169  break;
170 
171  case COL_TYPE:
172  if( PinTypeNames().Index( aValue ) != wxNOT_FOUND )
173  pin->SetType( (ELECTRICAL_PINTYPE) PinTypeNames().Index( aValue ) );
174 
175  break;
176 
177  case COL_SHAPE:
178  if( PinShapeNames().Index( aValue ) != wxNOT_FOUND )
179  pin->SetShape( (GRAPHIC_PINSHAPE) PinShapeNames().Index( aValue ) );
180 
181  break;
182 
183  case COL_ORIENTATION:
184  if( PinOrientationNames().Index( aValue ) != wxNOT_FOUND )
185  pin->SetOrientation( PinOrientationCode( PinOrientationNames().Index( aValue ) ) );
186  break;
187 
188  case COL_NUMBER_SIZE:
189  pin->SetNumberTextSize( ValueFromString( m_userUnits, aValue, true ) );
190  break;
191 
192  case COL_NAME_SIZE:
193  pin->SetNameTextSize( ValueFromString( m_userUnits, aValue, true ) );
194  break;
195 
196  case COL_LENGTH:
197  pin->SetLength( ValueFromString( m_userUnits, aValue ) );
198  break;
199 
200  case COL_POSX:
201  pin->SetPosition( wxPoint( ValueFromString( m_userUnits, aValue ),
202  pin->GetPosition().y ) );
203  break;
204 
205  case COL_POSY:
206  pin->SetPosition( wxPoint( pin->GetPosition().x,
207  ValueFromString( m_userUnits, aValue ) ) );
208  break;
209 
210  default:
211  wxFAIL;
212  break;
213  }
214  }
215 
216  m_edited = true;
217  }
218 
219  static int findRow( const std::vector<LIB_PINS>& aRowSet, const wxString& aName )
220  {
221  for( size_t i = 0; i < aRowSet.size(); ++i )
222  {
223  if( aRowSet[ i ][ 0 ] && aRowSet[ i ][ 0 ]->GetName() == aName )
224  return i;
225  }
226 
227  return -1;
228  }
229 
230  static bool compare( const LIB_PINS& lhs, const LIB_PINS& rhs, int sortCol, bool ascending,
231  EDA_UNITS units )
232  {
233  wxString lhStr = GetValue( lhs, sortCol, units );
234  wxString rhStr = GetValue( rhs, sortCol, units );
235 
236  if( lhStr == rhStr )
237  {
238  // Secondary sort key is always COL_NUMBER
239  sortCol = COL_NUMBER;
240  lhStr = GetValue( lhs, sortCol, units );
241  rhStr = GetValue( rhs, sortCol, units );
242  }
243 
244  bool res;
245 
246  // N.B. To meet the iterator sort conditions, we cannot simply invert the truth
247  // to get the opposite sort. i.e. ~(a<b) != (a>b)
248  auto cmp = [ ascending ]( const auto a, const auto b )
249  {
250  if( ascending )
251  return a < b;
252  else
253  return b < a;
254  };
255 
256  switch( sortCol )
257  {
258  case COL_NUMBER:
259  case COL_NAME:
260  res = cmp( PinNumbers::Compare( lhStr, rhStr ), 0 );
261  break;
262  case COL_NUMBER_SIZE:
263  case COL_NAME_SIZE:
264  res = cmp( ValueFromString( units, lhStr, true ),
265  ValueFromString( units, rhStr, true ) );
266  break;
267  case COL_LENGTH:
268  case COL_POSX:
269  case COL_POSY:
270  res = cmp( ValueFromString( units, lhStr ), ValueFromString( units, rhStr ) );
271  break;
272  default:
273  res = cmp( StrNumCmp( lhStr, rhStr ), 0 );
274  break;
275  }
276 
277  return res;
278  }
279 
280  void RebuildRows( LIB_PINS& aPins, bool groupByName )
281  {
282  if ( GetView() )
283  {
284  // Commit any pending in-place edits before the row gets moved out from under
285  // the editor.
286  if( auto grid = dynamic_cast<WX_GRID*>( GetView() ) )
287  grid->CommitPendingChanges( true );
288 
289  wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, 0, m_rows.size() );
290  GetView()->ProcessTableMessage( msg );
291  }
292 
293  m_rows.clear();
294 
295  for( LIB_PIN* pin : aPins )
296  {
297  int rowIndex = -1;
298 
299  if( groupByName )
300  rowIndex = findRow( m_rows, pin->GetName() );
301 
302  if( rowIndex < 0 )
303  {
304  m_rows.emplace_back( LIB_PINS() );
305  rowIndex = m_rows.size() - 1;
306  }
307 
308  m_rows[ rowIndex ].push_back( pin );
309  }
310 
311  int sortCol = 0;
312  bool ascending = true;
313 
314  if( GetView() && GetView()->GetSortingColumn() != wxNOT_FOUND )
315  {
316  sortCol = GetView()->GetSortingColumn();
317  ascending = GetView()->IsSortOrderAscending();
318  }
319 
320  for( LIB_PINS& row : m_rows )
321  SortPins( row );
322 
323  SortRows( sortCol, ascending );
324 
325  if ( GetView() )
326  {
327  wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_rows.size() );
328  GetView()->ProcessTableMessage( msg );
329  }
330  }
331 
332  void SortRows( int aSortCol, bool ascending )
333  {
334  std::sort( m_rows.begin(), m_rows.end(),
335  [ aSortCol, ascending, this ]( const LIB_PINS& lhs, const LIB_PINS& rhs ) -> bool
336  {
337  return compare( lhs, rhs, aSortCol, ascending, m_userUnits );
338  } );
339  }
340 
341  void SortPins( LIB_PINS& aRow )
342  {
343  std::sort( aRow.begin(), aRow.end(),
344  []( LIB_PIN* lhs, LIB_PIN* rhs ) -> bool
345  {
346  return PinNumbers::Compare( lhs->GetNumber(), rhs->GetNumber() ) < 0;
347  } );
348  }
349 
350  void AppendRow( LIB_PIN* aPin )
351  {
352  LIB_PINS row;
353  row.push_back( aPin );
354  m_rows.push_back( row );
355 
356  if ( GetView() )
357  {
358  wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
359  GetView()->ProcessTableMessage( msg );
360  }
361  }
362 
363  LIB_PINS RemoveRow( int aRow )
364  {
365  LIB_PINS removedRow = m_rows[ aRow ];
366 
367  m_rows.erase( m_rows.begin() + aRow );
368 
369  if ( GetView() )
370  {
371  wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, aRow, 1 );
372  GetView()->ProcessTableMessage( msg );
373  }
374 
375  return removedRow;
376  }
377 
378  bool IsEdited()
379  {
380  return m_edited;
381  }
382 };
383 
384 
387  m_editFrame( parent ),
388  m_part( aPart )
389 {
391 
392  // Save original columns widths so we can do proportional sizing.
393  for( int i = 0; i < COL_COUNT; ++i )
394  m_originalColWidths[ i ] = m_grid->GetColSize( i );
395 
396  // Give a bit more room for combobox editors
397  m_grid->SetDefaultRowSize( m_grid->GetDefaultRowSize() + 4 );
398 
400  m_grid->PushEventHandler( new GRID_TRICKS( m_grid ) );
401 
402  // Show/hide columns according to the user's preference
403  auto cfg = parent->GetSettings();
404  m_columnsShown = cfg->m_PinTableVisibleColumns;
405 
407 
408  // Set special attributes
409  wxGridCellAttr* attr;
410 
411  attr = new wxGridCellAttr;
412  wxArrayString typeNames = PinTypeNames();
413  typeNames.push_back( INDETERMINATE_STATE );
414  attr->SetRenderer( new GRID_CELL_ICON_TEXT_RENDERER( PinTypeIcons(), typeNames ) );
415  attr->SetEditor( new GRID_CELL_ICON_TEXT_POPUP( PinTypeIcons(), typeNames ) );
416  m_grid->SetColAttr( COL_TYPE, attr );
417 
418  attr = new wxGridCellAttr;
419  wxArrayString shapeNames = PinShapeNames();
420  shapeNames.push_back( INDETERMINATE_STATE );
421  attr->SetRenderer( new GRID_CELL_ICON_TEXT_RENDERER( PinShapeIcons(), shapeNames ) );
422  attr->SetEditor( new GRID_CELL_ICON_TEXT_POPUP( PinShapeIcons(), shapeNames ) );
423  m_grid->SetColAttr( COL_SHAPE, attr );
424 
425  attr = new wxGridCellAttr;
426  wxArrayString orientationNames = PinOrientationNames();
427  orientationNames.push_back( INDETERMINATE_STATE );
428  attr->SetRenderer( new GRID_CELL_ICON_TEXT_RENDERER( PinOrientationIcons(), orientationNames ) );
429  attr->SetEditor( new GRID_CELL_ICON_TEXT_POPUP( PinOrientationIcons(), orientationNames ) );
430  m_grid->SetColAttr( COL_ORIENTATION, attr );
431 
432  /* Right-aligned position values look much better, but only MSW and GTK2+
433  * currently support righ-aligned textEditCtrls, so the text jumps on all
434  * the other platforms when you edit it.
435  attr = new wxGridCellAttr;
436  attr->SetAlignment( wxALIGN_RIGHT, wxALIGN_TOP );
437  m_grid->SetColAttr( COL_POSX, attr );
438 
439  attr = new wxGridCellAttr;
440  attr->SetAlignment( wxALIGN_RIGHT, wxALIGN_TOP );
441  m_grid->SetColAttr( COL_POSY, attr );
442  */
443 
444  m_addButton->SetBitmap( KiBitmap( small_plus_xpm ) );
445  m_deleteButton->SetBitmap( KiBitmap( trash_xpm ) );
446  m_refreshButton->SetBitmap( KiBitmap( refresh_xpm ) );
447 
448  GetSizer()->SetSizeHints(this);
449  Centre();
450 
451  m_ButtonsOK->SetDefault();
452  m_initialized = true;
453  m_modified = false;
454  m_width = 0;
455 
456  // Connect Events
457  m_grid->Connect( wxEVT_GRID_COL_SORT, wxGridEventHandler( DIALOG_LIB_EDIT_PIN_TABLE::OnColSort ), nullptr, this );
458 }
459 
460 
462 {
463  auto cfg = m_editFrame->GetSettings();
464  cfg->m_PinTableVisibleColumns = m_grid->GetShownColumns().ToStdString();
465 
466  // Disconnect Events
467  m_grid->Disconnect( wxEVT_GRID_COL_SORT, wxGridEventHandler( DIALOG_LIB_EDIT_PIN_TABLE::OnColSort ), nullptr, this );
468 
469  // Prevents crash bug in wxGrid's d'tor
471 
472  // Delete the GRID_TRICKS.
473  m_grid->PopEventHandler( true );
474 
475  // This is our copy of the pins. If they were transfered to the part on an OK, then
476  // m_pins will already be empty.
477  for( auto pin : m_pins )
478  delete pin;
479 }
480 
481 
483 {
484  // Make a copy of the pins for editing
485  for( LIB_PIN* pin = m_part->GetNextPin( nullptr ); pin; pin = m_part->GetNextPin( pin ) )
486  m_pins.push_back( new LIB_PIN( *pin ) );
487 
488  m_dataModel->RebuildRows( m_pins, m_cbGroup->GetValue() );
489 
490  updateSummary();
491 
492  return true;
493 }
494 
495 
497 {
498  if( !m_grid->CommitPendingChanges() )
499  return false;
500 
501  // Delete the part's pins
502  while( LIB_PIN* pin = m_part->GetNextPin( nullptr ) )
503  m_part->RemoveDrawItem( pin );
504 
505  // Transfer our pins to the part
506  for( LIB_PIN* pin : m_pins )
507  {
508  pin->SetParent( m_part );
509  m_part->AddDrawItem( pin );
510  }
511 
512  m_pins.clear();
513 
514  return true;
515 }
516 
517 
518 void DIALOG_LIB_EDIT_PIN_TABLE::OnColSort( wxGridEvent& aEvent )
519 {
520  int sortCol = aEvent.GetCol();
521  bool ascending;
522 
523  // This is bonkers, but wxWidgets doesn't tell us ascending/descending in the
524  // event, and if we ask it will give us pre-event info.
525  if( m_grid->IsSortingBy( sortCol ) )
526  // same column; invert ascending
527  ascending = !m_grid->IsSortOrderAscending();
528  else
529  // different column; start with ascending
530  ascending = true;
531 
532  m_dataModel->SortRows( sortCol, ascending );
533 }
534 
535 
536 void DIALOG_LIB_EDIT_PIN_TABLE::OnAddRow( wxCommandEvent& event )
537 {
538  if( !m_grid->CommitPendingChanges() )
539  return;
540 
541  LIB_PIN* newPin = new LIB_PIN( nullptr );
542 
543  if( m_pins.size() > 0 )
544  {
545  LIB_PIN* last = m_pins.back();
546 
547  newPin->SetOrientation( last->GetOrientation() );
548  newPin->SetType( last->GetType() );
549  newPin->SetShape( last->GetShape() );
550 
551  wxPoint pos = last->GetPosition();
552 
553  LIBEDIT_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<LIBEDIT_SETTINGS>();
554 
555  if( last->GetOrientation() == PIN_LEFT || last->GetOrientation() == PIN_RIGHT )
556  pos.y -= cfg->m_Repeat.pin_step;
557  else
558  pos.x += cfg->m_Repeat.pin_step;
559 
560  newPin->SetPosition( pos );
561  }
562 
563  m_pins.push_back( newPin );
564 
565  m_dataModel->AppendRow( m_pins[ m_pins.size() - 1 ] );
566 
567  m_grid->MakeCellVisible( m_grid->GetNumberRows() - 1, 0 );
568  m_grid->SetGridCursor( m_grid->GetNumberRows() - 1, 0 );
569 
570  m_grid->EnableCellEditControl( true );
571  m_grid->ShowCellEditControl();
572 
573  updateSummary();
574 }
575 
576 
577 void DIALOG_LIB_EDIT_PIN_TABLE::OnDeleteRow( wxCommandEvent& event )
578 {
579  if( !m_grid->CommitPendingChanges() )
580  return;
581 
582  if( m_pins.size() == 0 ) // empty table
583  return;
584 
585  int curRow = m_grid->GetGridCursorRow();
586 
587  if( curRow < 0 )
588  return;
589 
590  LIB_PINS removedRow = m_dataModel->RemoveRow( curRow );
591 
592  for( auto pin : removedRow )
593  m_pins.erase( std::find( m_pins.begin(), m_pins.end(), pin ) );
594 
595  curRow = std::max( 0, curRow - 1 );
596  m_grid->MakeCellVisible( curRow, m_grid->GetGridCursorCol() );
597  m_grid->SetGridCursor( curRow, m_grid->GetGridCursorCol() );
598 
599  updateSummary();
600 }
601 
602 
603 void DIALOG_LIB_EDIT_PIN_TABLE::OnCellEdited( wxGridEvent& event )
604 {
605  updateSummary();
606 }
607 
608 
610 {
611  if( !m_grid->CommitPendingChanges() )
612  return;
613 
614  m_dataModel->RebuildRows( m_pins, m_cbGroup->GetValue() );
615 
616  adjustGridColumns( m_grid->GetRect().GetWidth() );
617 }
618 
619 
621 {
622  m_width = aWidth;
623 
624  // Account for scroll bars
625  aWidth -= ( m_grid->GetSize().x - m_grid->GetClientSize().x );
626 
627  wxGridUpdateLocker deferRepaintsTillLeavingScope;
628 
629  // The Number and Name columns must be at least wide enough to hold their contents, but
630  // no less wide than their original widths.
631 
632  m_grid->AutoSizeColumn( COL_NUMBER );
633 
634  if( m_grid->GetColSize( COL_NUMBER ) < m_originalColWidths[ COL_NUMBER ] )
635  m_grid->SetColSize( COL_NUMBER, m_originalColWidths[ COL_NUMBER ] );
636 
637  m_grid->AutoSizeColumn( COL_NAME );
638 
639  if( m_grid->GetColSize( COL_NAME ) < m_originalColWidths[ COL_NAME ] )
640  m_grid->SetColSize( COL_NAME, m_originalColWidths[ COL_NAME ] );
641 
642  // If the grid is still wider than the columns, then stretch the Number and Name columns
643  // to fit.
644 
645  for( int i = 0; i < COL_COUNT; ++i )
646  aWidth -= m_grid->GetColSize( i );
647 
648  if( aWidth > 0 )
649  {
650  m_grid->SetColSize( COL_NUMBER, m_grid->GetColSize( COL_NUMBER ) + aWidth / 2 );
651  m_grid->SetColSize( COL_NAME, m_grid->GetColSize( COL_NAME ) + aWidth / 2 );
652  }
653 }
654 
655 
656 void DIALOG_LIB_EDIT_PIN_TABLE::OnSize( wxSizeEvent& event )
657 {
658  auto new_size = event.GetSize().GetX();
659 
660  if( m_initialized && m_width != new_size )
661  {
662  adjustGridColumns( new_size );
663  }
664 
665  // Always propagate for a grid repaint (needed if the height changes, as well as width)
666  event.Skip();
667 }
668 
669 
670 void DIALOG_LIB_EDIT_PIN_TABLE::OnUpdateUI( wxUpdateUIEvent& event )
671 {
672  wxString columnsShown = m_grid->GetShownColumns();
673 
674  if( columnsShown != m_columnsShown )
675  {
676  m_columnsShown = columnsShown;
677 
678  if( !m_grid->IsCellEditControlShown() )
679  adjustGridColumns( m_grid->GetRect().GetWidth() );
680  }
681 }
682 
683 
684 void DIALOG_LIB_EDIT_PIN_TABLE::OnCancel( wxCommandEvent& event )
685 {
686  Close();
687 }
688 
689 
690 void DIALOG_LIB_EDIT_PIN_TABLE::OnClose( wxCloseEvent& event )
691 {
692  // This is a cancel, so commit quietly as we're going to throw the results away anyway.
693  m_grid->CommitPendingChanges( true );
694 
695  int retval = wxID_CANCEL;
696 
697  if( m_dataModel->IsEdited() )
698  {
699  if( HandleUnsavedChanges( this, _( "Save changes?" ),
700  [&]()->bool
701  {
702  if( TransferDataFromWindow() )
703  {
704  retval = wxID_OK;
705  return true;
706  }
707 
708  return false;
709  } ) )
710  {
711  if( IsQuasiModal() )
712  EndQuasiModal( retval );
713  else
714  EndModal( retval );
715 
716  return;
717  }
718  else
719  {
720  event.Veto();
721  return;
722  }
723  }
724 
725  // No change in dialog: we can close it
726  if( IsQuasiModal() )
727  EndQuasiModal( retval );
728  else
729  EndModal( retval );
730 
731  return;
732 }
733 
734 
736 {
737  PinNumbers pinNumbers;
738 
739  for( LIB_PIN* pin : m_pins )
740  {
741  if( pin->GetNumber().Length() )
742  pinNumbers.insert( pin->GetNumber() );
743  }
744 
745  m_summary->SetLabel( pinNumbers.GetSummary() );
746 }
EDA_UNITS
Definition: common.h:198
static int Compare(PinNumber const &lhs, PinNumber const &rhs)
Definition: pin_number.cpp:111
const BITMAP_OPAQUE trash_xpm[1]
Definition: trash.cpp:46
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Display a dialog with Save, Cancel and Discard Changes buttons.
Definition: confirm.cpp:201
void OnClose(wxCloseEvent &event) override
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:104
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.
Definition: string.cpp:409
void OnSize(wxSizeEvent &event) override
void SetOrientation(int aOrientation)
Definition: lib_pin.h:126
PIN_TABLE_DATA_MODEL(EDA_UNITS aUserUnits)
This file is part of the common library.
const std::vector< BITMAP_DEF > & PinOrientationIcons()
Definition: pin_type.cpp:230
int GetOrientation() const
Definition: lib_pin.h:125
DIALOG_LIB_EDIT_PIN_TABLE(LIB_EDIT_FRAME *parent, LIB_PART *aPart)
void ShowHideColumns(const wxString &shownColumns)
Show/hide the grid columns based on a tokenized string of shown column indexes.
Definition: wx_grid.cpp:127
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_item.h:55
void SetShape(GRAPHIC_PINSHAPE aShape)
Definition: lib_pin.h:129
GRAPHIC_PINSHAPE GetShape() const
Definition: lib_pin.h:128
const std::vector< BITMAP_DEF > & PinTypeIcons()
Definition: pin_type.cpp:194
void OnAddRow(wxCommandEvent &event) override
wxString GetSummary() const
Definition: pin_number.cpp:71
void OnCellEdited(wxGridEvent &event) override
GRID_TRICKS is used to add mouse and command handling (such as cut, copy, and paste) to a WX_GRID ins...
Definition: grid_tricks.h:51
int PinOrientationIndex(int code)
Definition: pin_type.cpp:149
int PinOrientationCode(int index)
Definition: pin_type.cpp:140
void SetTable(wxGridTableBase *table, bool aTakeOwnership=false)
Hide wxGrid's SetTable() method with one which doesn't mess up the grid column widths when setting th...
Definition: wx_grid.cpp:65
wxString m_PinTableVisibleColumns
GRAPHIC_PINSHAPE
Definition: pin_type.h:53
void SetPosition(const wxPoint &aPos) override
Definition: lib_pin.h:255
void insert(value_type const &v)
Definition: pin_number.h:57
const std::vector< BITMAP_DEF > & PinShapeIcons()
Definition: pin_type.cpp:212
EDA_UNITS GetUserUnits() const
Definition: dialog_shim.h:131
void AddDrawItem(LIB_ITEM *aItem)
Add a new draw aItem to the draw object list.
void DestroyTable(wxGridTableBase *aTable)
Work-around for a bug in wxGrid which crashes when deleting the table if the cell edit control was no...
Definition: wx_grid.cpp:96
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Construct a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:80
bool m_modified
true when there are unsaved changes
const wxArrayString & PinShapeNames()
Definition: pin_type.cpp:203
void SetType(ELECTRICAL_PINTYPE aType)
Definition: lib_pin.h:135
bool IsEmptyCell(int row, int col) override
void SortRows(int aSortCol, bool ascending)
void OnRebuildRows(wxCommandEvent &event) override
void OnUpdateUI(wxUpdateUIEvent &event) override
Define a library symbol object.
bool IsQuasiModal()
Definition: dialog_shim.h:123
const wxArrayString & PinTypeNames()
Definition: pin_type.cpp:185
void RebuildRows(LIB_PINS &aPins, bool groupByName)
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:180
wxString GetColLabelValue(int aCol) override
PIN_TABLE_DATA_MODEL * m_dataModel
wxString GetValue(int aRow, int aCol) override
const BITMAP_OPAQUE refresh_xpm[1]
Definition: refresh.cpp:32
static bool compare(const LIB_PINS &lhs, const LIB_PINS &rhs, int sortCol, bool ascending, EDA_UNITS units)
wxPoint GetPosition() const override
Definition: lib_pin.h:254
Class DIALOG_LIB_EDIT_PIN_TABLE_BASE.
LIB_PIN * GetNextPin(LIB_PIN *aItem=NULL)
Return the next pin object from the draw list.
const wxArrayString & PinOrientationNames()
Definition: pin_type.cpp:221
wxString GetShownColumns()
Get a tokenized string containing the shown column indexes.
Definition: wx_grid.cpp:109
const wxString & GetNumber() const
Definition: lib_pin.h:165
ELECTRICAL_PINTYPE GetType() const
Definition: lib_pin.h:134
void EndQuasiModal(int retCode)
static int findRow(const std::vector< LIB_PINS > &aRowSet, const wxString &aName)
The symbol library editor main window.
see class PGM_BASE
void OnDeleteRow(wxCommandEvent &event) override
ELECTRICAL_PINTYPE
The component library pin object electrical types used in ERC tests.
Definition: pin_type.h:34
#define _(s)
Definition: 3d_actions.cpp:33
void OnColSort(wxGridEvent &aEvent)
LIBEDIT_SETTINGS * GetSettings()
static wxString GetValue(const LIB_PINS &pins, int aCol, EDA_UNITS aUserUnits)
void SetValue(int aRow, int aCol, const wxString &aValue) override
static std::map< int, wxString > shapeNames
#define INDETERMINATE_STATE
Used for holding indeterminate values, such as with multiple selections holding different values or c...
Definition: base_units.h:48
std::vector< LIB_PINS > m_rows
void OnCancel(wxCommandEvent &event) override
const BITMAP_OPAQUE small_plus_xpm[1]
Definition: small_plus.cpp:20
wxString StringFromValue(EDA_UNITS aUnits, double aValue, bool aAddUnitSymbol, bool aUseMils, EDA_DATA_TYPE aType)
Function StringFromValue returns the string from aValue according to units (inch, mm ....
Definition: base_units.cpp:233
long long int ValueFromString(EDA_UNITS aUnits, const wxString &aTextValue, bool aUseMils, EDA_DATA_TYPE aType)
Function ValueFromString converts aTextValue in aUnits to internal units used by the application.
Definition: base_units.cpp:471
void RemoveDrawItem(LIB_ITEM *aItem)
Remove draw aItem from list.