KiCad PCB EDA Suite
dialog_pin_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 (C) 2010 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2016 - 2020 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <fctsys.h>
26 #include <gr_basic.h>
27 #include <bitmaps.h>
28 #include <sch_painter.h>
29 #include <lib_edit_frame.h>
30 #include <class_libentry.h>
31 #include <lib_pin.h>
32 #include <dialog_pin_properties.h>
33 #include <confirm.h>
34 #include <widgets/tab_traversal.h>
35 #include <widgets/wx_grid.h>
36 #include <grid_tricks.h>
38 
39 class ALT_PIN_DATA_MODEL : public wxGridTableBase, public std::vector<LIB_PIN::ALT>
40 {
41 public:
43  {
44  }
45 
46  int GetNumberRows() override { return (int) size(); }
47  int GetNumberCols() override { return COL_COUNT; }
48 
49  wxString GetColLabelValue( int aCol ) override
50  {
51  switch( aCol )
52  {
53  case COL_NAME: return _( "Alternate Pin Name" );
54  case COL_TYPE: return _( "Electrical Type" );
55  case COL_SHAPE: return _( "Graphic Style" );
56  default: wxFAIL; return wxEmptyString;
57  }
58  }
59 
60  bool IsEmptyCell( int row, int col ) override
61  {
62  return false; // don't allow adjacent cell overflow, even if we are actually empty
63  }
64 
65  wxString GetValue( int aRow, int aCol ) override
66  {
67  switch( aCol )
68  {
69  case COL_NAME: return at( aRow ).m_Name;
70  case COL_TYPE: return PinTypeNames()[static_cast<int>( at( aRow ).m_Type )];
71  case COL_SHAPE: return PinShapeNames()[static_cast<int>( at( aRow ).m_Shape )];
72  default: wxFAIL; return wxEmptyString;
73  }
74  }
75 
76  void SetValue( int aRow, int aCol, const wxString &aValue ) override
77  {
78  switch( aCol )
79  {
80  case COL_NAME:
81  at( aRow ).m_Name = aValue;
82  break;
83 
84  case COL_TYPE:
85  if( PinTypeNames().Index( aValue ) != wxNOT_FOUND )
86  at( aRow ).m_Type = (ELECTRICAL_PINTYPE) PinTypeNames().Index( aValue );
87 
88  break;
89 
90  case COL_SHAPE:
91  if( PinShapeNames().Index( aValue ) != wxNOT_FOUND )
92  at( aRow ).m_Shape = (GRAPHIC_PINSHAPE) PinShapeNames().Index( aValue );
93 
94  break;
95 
96  default:
97  wxFAIL;
98  break;
99  }
100  }
101 
102  void AppendRow( const LIB_PIN::ALT& aAlt )
103  {
104  push_back( aAlt );
105 
106  if ( GetView() )
107  {
108  wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
109  GetView()->ProcessTableMessage( msg );
110  }
111  }
112 
113  void RemoveRow( int aRow )
114  {
115  erase( begin() + aRow );
116 
117  if ( GetView() )
118  {
119  wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, aRow, 1 );
120  GetView()->ProcessTableMessage( msg );
121  }
122  }
123 };
124 
125 
127  DIALOG_PIN_PROPERTIES_BASE( parent ),
128  m_frame( parent ),
129  m_pin( aPin ),
130  m_posX( parent, m_posXLabel, m_posXCtrl, m_posXUnits, true ),
131  m_posY( parent, m_posYLabel, m_posYCtrl, m_posYUnits, true ),
132  m_pinLength( parent, m_pinLengthLabel, m_pinLengthCtrl, m_pinLengthUnits, true ),
133  m_nameSize( parent, m_nameSizeLabel, m_nameSizeCtrl, m_nameSizeUnits, true ),
134  m_numberSize( parent, m_numberSizeLabel, m_numberSizeCtrl, m_numberSizeUnits, true ),
135  m_delayedFocusRow( -1 ),
136  m_delayedFocusColumn( -1 ),
137  m_initialized( false )
138 {
139  // Creates a dummy pin to show on a panel, inside this dialog:
140  m_dummyPin = new LIB_PIN( *m_pin );
141 
143  m_panelShowPin->SetBackgroundColour( bgColor.ToColour() );
144 
145  const wxArrayString& orientationNames = PinOrientationNames();
146  const std::vector<BITMAP_DEF>& orientationIcons = PinOrientationIcons();
147 
148  for ( unsigned ii = 0; ii < orientationNames.GetCount(); ii++ )
149  m_choiceOrientation->Insert( orientationNames[ii], KiBitmap( orientationIcons[ii] ), ii );
150 
151  // We can't set the tab order through wxWidgets due to shortcomings in their mnemonics
152  // implementation on MSW
153  m_tabOrder = {
158  m_posXCtrl,
159  m_posYCtrl,
166  m_checkShow,
169  };
170 
171  // Default alternates turndow to whether or not alternates exist
172  m_alternatesTurndown->Collapse( m_pin->GetAlternates().size() == 0 );
173 
175 
176  // Save original columns widths so we can do proportional sizing.
177  for( int i = 0; i < COL_COUNT; ++i )
178  m_originalColWidths[ i ] = m_alternatesGrid->GetColSize( i );
179 
180  // Give a bit more room for combobox editors
181  m_alternatesGrid->SetDefaultRowSize( m_alternatesGrid->GetDefaultRowSize() + 4 );
182 
184  m_alternatesGrid->PushEventHandler( new GRID_TRICKS( m_alternatesGrid ) );
185 
186  // Set special attributes
187  wxGridCellAttr* attr;
188 
189  attr = new wxGridCellAttr;
190  attr->SetRenderer( new GRID_CELL_ICON_TEXT_RENDERER( PinTypeIcons(), PinTypeNames() ) );
191  attr->SetEditor( new GRID_CELL_ICON_TEXT_POPUP( PinTypeIcons(), PinTypeNames() ) );
192  m_alternatesGrid->SetColAttr( COL_TYPE, attr );
193 
194  attr = new wxGridCellAttr;
195  attr->SetRenderer( new GRID_CELL_ICON_TEXT_RENDERER( PinShapeIcons(), PinShapeNames() ) );
196  attr->SetEditor( new GRID_CELL_ICON_TEXT_POPUP( PinShapeIcons(), PinShapeNames() ) );
197  m_alternatesGrid->SetColAttr( COL_SHAPE, attr );
198 
199  m_addAlternate->SetBitmap( KiBitmap( small_plus_xpm ) );
200  m_deleteAlternate->SetBitmap( KiBitmap( trash_xpm ) );
201 
202  m_sdbSizerButtonsOK->SetDefault();
204 
205  // Now all widgets have the size fixed, call FinishDialogSettings
207 
208  // On some window managers (Unity, XFCE) the dialog is not always raised, depending on
209  // how it is is run.
210  Raise();
211 
212  m_initialized = true;
213  m_width = 0;
214 }
215 
216 
218 {
219  delete m_dummyPin;
220 
221  // Prevents crash bug in wxGrid's d'tor
223 
224  // Delete the GRID_TRICKS.
225  m_alternatesGrid->PopEventHandler( true );
226 }
227 
228 
230 {
231  if( !DIALOG_SHIM::TransferDataToWindow() )
232  return false;
233 
235 
239  m_textPinName->SetValue( m_pin->GetName() );
243  m_textPinNumber->SetValue( m_pin->GetNumber() );
246  m_checkApplyToAllParts->SetValue( m_pin->GetUnit() == 0 );
247  m_checkApplyToAllConversions->SetValue( m_pin->GetConvert() == 0 );
248  m_checkShow->SetValue( m_pin->IsVisible() );
249 
251 
252  for( const std::pair<const wxString, LIB_PIN::ALT>& alt : m_pin->GetAlternates() )
253  m_alternatesDataModel->AppendRow( alt.second );
254 
255  return true;
256 }
257 
258 
260 {
262  return false;
263 
264  // Check for missing alternate names.
265  for( size_t i = 0; i < m_alternatesDataModel->size(); ++i )
266  {
267  if( m_alternatesDataModel->at( i ).m_Name.IsEmpty() )
268  {
269  DisplayErrorMessage( this, _( "Alternate pin definitions must have a name." ) );
270 
272  m_delayedFocusRow = i;
273 
274  return false;
275  }
276  }
277 
278  if( !DIALOG_SHIM::TransferDataFromWindow() )
279  return false;
280 
281  wxPoint newPos( m_posX.GetValue(), -m_posY.GetValue() );
282 
283  const int acceptable_mingrid = 50;
284 
285  // Only show the warning if the position has been changed
286  if( ( m_origPos != newPos )
287  && ( ( m_posX.GetValue() % acceptable_mingrid ) || ( m_posY.GetValue() % acceptable_mingrid ) ) )
288  {
289  auto msg = wxString::Format( _( "This pin is not on a %d mils grid which will make it\n"
290  "difficult to connect to in the schematic.\n"
291  "Do you want to continue?" ),
292  acceptable_mingrid );
293  if( !IsOK( this, msg ) )
294  return false;
295  }
296 
297  m_pin->SetName( m_textPinName->GetValue() );
298  m_pin->SetNumber( m_textPinNumber->GetValue() );
303  m_pin->SetPosition( newPos );
307  m_pin->SetUnit( m_checkApplyToAllParts->GetValue() ? 0 : m_frame->GetUnit() );
308  m_pin->SetVisible( m_checkShow->GetValue() );
309 
310  std::map<wxString, LIB_PIN::ALT>& alternates = m_pin->GetAlternates();
311  alternates.clear();
312 
313  for( const LIB_PIN::ALT& alt : *m_alternatesDataModel )
314  alternates[ alt.m_Name ] = alt;
315 
316  return true;
317 }
318 
319 
320 /*
321  * Draw (on m_panelShowPin) the pin according to current settings in dialog
322  */
323 void DIALOG_PIN_PROPERTIES::OnPaintShowPanel( wxPaintEvent& event )
324 {
325  wxPaintDC dc( m_panelShowPin );
326  wxSize dc_size = dc.GetSize();
327  dc.SetDeviceOrigin( dc_size.x / 2, dc_size.y / 2 );
328 
329  // Give a parent to m_dummyPin only from draw purpose.
330  // In fact m_dummyPin should not have a parent, but draw functions need a parent
331  // to know some options, about pin texts
332  LIB_EDIT_FRAME* libframe = (LIB_EDIT_FRAME*) GetParent();
333 
334  // Calculate a suitable scale to fit the available draw area
335  EDA_RECT bBox = m_dummyPin->GetBoundingBox( true );
336  double xscale = (double) dc_size.x / bBox.GetWidth();
337  double yscale = (double) dc_size.y / bBox.GetHeight();
338  double scale = std::min( xscale, yscale );
339 
340  // Give a 10% margin and limit to no more than 100% zoom
341  scale = std::min( scale * 0.9, 1.0 );
342  dc.SetUserScale( scale, scale );
343  GRResetPenAndBrush( &dc );
344 
345  PART_DRAW_OPTIONS opts;
346  opts.draw_hidden_fields = true;
347 
348  RENDER_SETTINGS* renderSettings = libframe->GetRenderSettings();
349  renderSettings->SetPrintDC( &dc );
350 
351  m_dummyPin->Print( renderSettings, -bBox.Centre(), (void*) &opts, DefaultTransform );
352 
353  event.Skip();
354 }
355 
356 
357 void DIALOG_PIN_PROPERTIES::OnPropertiesChange( wxCommandEvent& event )
358 {
359  if( !IsShown() ) // do nothing at init time
360  return;
361 
362  m_dummyPin->SetName( m_textPinName->GetValue() );
363  m_dummyPin->SetNumber( m_textPinNumber->GetValue() );
370  m_dummyPin->SetVisible( m_checkShow->GetValue() );
371 
372  m_panelShowPin->Refresh();
373 }
374 
375 
376 void DIALOG_PIN_PROPERTIES::OnAddAlternate( wxCommandEvent& event )
377 {
379  return;
380 
381  LIB_PIN::ALT newAlt;
382  newAlt.m_Name = wxEmptyString;
383  newAlt.m_Type = m_pin->GetType();
384  newAlt.m_Shape = m_pin->GetShape();
385 
386  m_alternatesDataModel->AppendRow( newAlt );
387 
388  m_alternatesGrid->MakeCellVisible( m_alternatesGrid->GetNumberRows() - 1, 0 );
389  m_alternatesGrid->SetGridCursor( m_alternatesGrid->GetNumberRows() - 1, 0 );
390 
391  m_alternatesGrid->EnableCellEditControl( true );
392  m_alternatesGrid->ShowCellEditControl();
393 }
394 
395 
396 void DIALOG_PIN_PROPERTIES::OnDeleteAlternate( wxCommandEvent& event )
397 {
399  return;
400 
401  if( m_alternatesDataModel->size() == 0 ) // empty table
402  return;
403 
404  int curRow = m_alternatesGrid->GetGridCursorRow();
405 
406  if( curRow < 0 )
407  return;
408 
409  m_alternatesDataModel->RemoveRow( curRow );
410 
411  curRow = std::max( 0, curRow - 1 );
412  m_alternatesGrid->MakeCellVisible( curRow, m_alternatesGrid->GetGridCursorCol() );
413  m_alternatesGrid->SetGridCursor( curRow, m_alternatesGrid->GetGridCursorCol() );
414 }
415 
416 
418 {
419  m_width = aWidth;
420 
421  // Account for margins
422  aWidth -= 30;
423 
424  wxGridUpdateLocker deferRepaintsTillLeavingScope;
425 
428 
429  m_alternatesGrid->SetColSize( COL_NAME, aWidth - m_originalColWidths[ COL_TYPE ]
431 }
432 
433 
434 void DIALOG_PIN_PROPERTIES::OnSize( wxSizeEvent& event )
435 {
436  auto new_size = event.GetSize().GetX();
437 
438  if( m_initialized && m_width != new_size )
439  adjustGridColumns( new_size );
440 
441  // Always propagate for a grid repaint (needed if the height changes, as well as width)
442  event.Skip();
443 }
444 
445 
446 void DIALOG_PIN_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
447 {
448  // Handle a delayed focus
449  if( m_delayedFocusRow >= 0 )
450  {
451  m_alternatesTurndown->Collapse( false );
452 
453  m_alternatesGrid->SetFocus();
456 
457  m_alternatesGrid->EnableCellEditControl( true );
458  m_alternatesGrid->ShowCellEditControl();
459 
460  m_delayedFocusRow = -1;
462  }
463 }
464 
465 
void SetNumberTextSize(int aSize)
Definition: lib_pin.h:178
EDA_UNITS
Definition: common.h:198
const BITMAP_OPAQUE trash_xpm[1]
Definition: trash.cpp:46
void GRResetPenAndBrush(wxDC *DC)
Definition: gr_basic.cpp:122
Functions for manipulating tab traversal in forms and dialogs.
DIALOG_PIN_PROPERTIES(LIB_EDIT_FRAME *parent, LIB_PIN *aPin)
Constructor.
void OnUpdateUI(wxUpdateUIEvent &event) override
wxString GetColLabelValue(int aCol) override
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:252
void SetOrientation(int aOrientation)
Definition: lib_pin.h:126
int GetConvert() const
RENDER_SETTINGS Contains all the knowledge about how graphical objects are drawn on any output surfac...
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
void OnPropertiesChange(wxCommandEvent &event) override
std::vector< wxWindow * > m_tabOrder
Definition: dialog_shim.h:213
void SetShape(GRAPHIC_PINSHAPE aShape)
Definition: lib_pin.h:129
GRAPHIC_PINSHAPE GetShape() const
Definition: lib_pin.h:128
ALT_PIN_DATA_MODEL(EDA_UNITS aUserUnits)
const std::vector< BITMAP_DEF > & PinTypeIcons()
Definition: pin_type.cpp:194
void AppendRow(const LIB_PIN::ALT &aAlt)
void adjustGridColumns(int aWidth)
void SetSelection(GRAPHIC_PINSHAPE aShape)
void FinishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
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 GetWidth() const
Definition: eda_rect.h:119
int m_originalColWidths[COL_COUNT]
const COLOR4D & GetLayerColor(int aLayer) const
Function GetLayerColor Returns the color used to draw a layer.
TRANSFORM DefaultTransform
int PinOrientationIndex(int code)
Definition: pin_type.cpp:149
void SetLength(int aLength)
Definition: lib_pin.h:132
KIGFX::SCH_RENDER_SETTINGS * GetRenderSettings()
bool TransferDataToWindow() override
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
const EDA_RECT GetBoundingBox() const override
Definition: lib_pin.h:218
GRAPHIC_PINSHAPE
Definition: pin_type.h:53
void OnPaintShowPanel(wxPaintEvent &event) override
void SetPosition(const wxPoint &aPos) override
Definition: lib_pin.h:255
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:114
ELECTRICAL_PINTYPE m_Type
Definition: lib_pin.h:62
virtual void Print(RENDER_SETTINGS *aSettings, const wxPoint &aOffset, void *aData, const TRANSFORM &aTransform)
Draw an item.
Definition: lib_item.cpp:139
const std::vector< BITMAP_DEF > & PinShapeIcons()
Definition: pin_type.cpp:212
EDA_UNITS GetUserUnits() const
Definition: dialog_shim.h:131
void OnAddAlternate(wxCommandEvent &event) override
void SetNumber(const wxString &aNumber)
Definition: lib_pin.h:166
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
ALT_PIN_DATA_MODEL * m_alternatesDataModel
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Construct a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:80
int GetUnit() const
Definition: lib_item.h:295
const wxArrayString & PinShapeNames()
Definition: pin_type.cpp:203
void SetType(ELECTRICAL_PINTYPE aType)
Definition: lib_pin.h:135
ELECTRICAL_PINTYPE GetPinTypeSelection()
int GetUnit() const
const wxString & GetName() const
Definition: lib_pin.h:156
wxString GetValue(int aRow, int aCol) override
wxString m_Name
Definition: lib_pin.h:60
void SetVisible(bool aVisible)
Definition: lib_pin.h:148
const wxArrayString & PinTypeNames()
Definition: pin_type.cpp:185
void SetSelection(ELECTRICAL_PINTYPE aType)
bool IsVisible() const
Definition: lib_pin.h:147
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:180
int GetNameTextSize() const
Definition: lib_pin.h:174
bool TransferDataFromWindow() override
int GetConvert() const
Definition: lib_item.h:298
void OnDeleteAlternate(wxCommandEvent &event) override
int GetHeight() const
Definition: eda_rect.h:120
void SetConvert(int aConvert)
Definition: lib_item.h:297
wxPoint GetPosition() const override
Definition: lib_pin.h:254
const wxArrayString & PinOrientationNames()
Definition: pin_type.cpp:221
const wxString & GetNumber() const
Definition: lib_pin.h:165
ELECTRICAL_PINTYPE GetType() const
Definition: lib_pin.h:134
void SetUnit(int aUnit)
Definition: lib_item.h:294
std::map< wxString, ALT > & GetAlternates()
Definition: lib_pin.h:180
int GetNumberTextSize() const
Definition: lib_pin.h:177
The symbol library editor main window.
const int scale
void SetName(const wxString &aName)
Definition: lib_pin.h:157
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:201
void SetNameTextSize(int aSize)
Definition: lib_pin.h:175
ELECTRICAL_PINTYPE
The component library pin object electrical types used in ERC tests.
Definition: pin_type.h:34
int GetLength() const
Definition: lib_pin.h:131
#define _(s)
Definition: 3d_actions.cpp:33
void OnSize(wxSizeEvent &event) override
virtual void SetValue(int aValue)
Function SetValue Sets new value (in Internal Units) for the text field, taking care of units convers...
Class DIALOG_PIN_PROPERTIES_BASE.
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
wxPoint Centre() const
Definition: eda_rect.h:62
virtual long long int GetValue()
Function GetValue Returns the current value in Internal Units.
void SetValue(int aRow, int aCol, const wxString &aValue) override
bool IsEmptyCell(int row, int col) override
GRAPHIC_PINSHAPE GetPinShapeSelection()
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:283
void SetPrintDC(wxDC *aDC)
const BITMAP_OPAQUE small_plus_xpm[1]
Definition: small_plus.cpp:20
GRAPHIC_PINSHAPE m_Shape
Definition: lib_pin.h:61
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:99