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 <bitmaps.h>
26 #include <sch_painter.h>
27 #include <symbol_edit_frame.h>
28 #include <lib_pin.h>
29 #include <dialog_pin_properties.h>
30 #include <confirm.h>
31 #include <widgets/tab_traversal.h>
32 #include <widgets/wx_grid.h>
33 #include <grid_tricks.h>
35 
36 class ALT_PIN_DATA_MODEL : public wxGridTableBase, public std::vector<LIB_PIN::ALT>
37 {
38 public:
40  {
41  }
42 
43  int GetNumberRows() override { return (int) size(); }
44  int GetNumberCols() override { return COL_COUNT; }
45 
46  wxString GetColLabelValue( int aCol ) override
47  {
48  switch( aCol )
49  {
50  case COL_NAME: return _( "Alternate Pin Name" );
51  case COL_TYPE: return _( "Electrical Type" );
52  case COL_SHAPE: return _( "Graphic Style" );
53  default: wxFAIL; return wxEmptyString;
54  }
55  }
56 
57  bool IsEmptyCell( int row, int col ) override
58  {
59  return false; // don't allow adjacent cell overflow, even if we are actually empty
60  }
61 
62  wxString GetValue( int aRow, int aCol ) override
63  {
64  switch( aCol )
65  {
66  case COL_NAME: return at( aRow ).m_Name;
67  case COL_TYPE: return PinTypeNames()[static_cast<int>( at( aRow ).m_Type )];
68  case COL_SHAPE: return PinShapeNames()[static_cast<int>( at( aRow ).m_Shape )];
69  default: wxFAIL; return wxEmptyString;
70  }
71  }
72 
73  void SetValue( int aRow, int aCol, const wxString &aValue ) override
74  {
75  switch( aCol )
76  {
77  case COL_NAME:
78  at( aRow ).m_Name = aValue;
79  break;
80 
81  case COL_TYPE:
82  if( PinTypeNames().Index( aValue ) != wxNOT_FOUND )
83  at( aRow ).m_Type = (ELECTRICAL_PINTYPE) PinTypeNames().Index( aValue );
84 
85  break;
86 
87  case COL_SHAPE:
88  if( PinShapeNames().Index( aValue ) != wxNOT_FOUND )
89  at( aRow ).m_Shape = (GRAPHIC_PINSHAPE) PinShapeNames().Index( aValue );
90 
91  break;
92 
93  default:
94  wxFAIL;
95  break;
96  }
97  }
98 
99  void AppendRow( const LIB_PIN::ALT& aAlt )
100  {
101  push_back( aAlt );
102 
103  if ( GetView() )
104  {
105  wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
106  GetView()->ProcessTableMessage( msg );
107  }
108  }
109 
110  void RemoveRow( int aRow )
111  {
112  erase( begin() + aRow );
113 
114  if ( GetView() )
115  {
116  wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, aRow, 1 );
117  GetView()->ProcessTableMessage( msg );
118  }
119  }
120 };
121 
122 
124  DIALOG_PIN_PROPERTIES_BASE( parent ),
125  m_frame( parent ),
126  m_pin( aPin ),
127  m_posX( parent, m_posXLabel, m_posXCtrl, m_posXUnits ),
128  m_posY( parent, m_posYLabel, m_posYCtrl, m_posYUnits ),
129  m_pinLength( parent, m_pinLengthLabel, m_pinLengthCtrl, m_pinLengthUnits ),
130  m_nameSize( parent, m_nameSizeLabel, m_nameSizeCtrl, m_nameSizeUnits ),
131  m_numberSize( parent, m_numberSizeLabel, m_numberSizeCtrl, m_numberSizeUnits ),
132  m_delayedFocusRow( -1 ),
133  m_delayedFocusColumn( -1 ),
134  m_initialized( false )
135 {
136  // Creates a dummy pin to show on a panel, inside this dialog:
137  m_dummyPin = new LIB_PIN( *m_pin );
138 
140  m_panelShowPin->SetBackgroundColour( bgColor.ToColour() );
141 
142  const wxArrayString& orientationNames = PinOrientationNames();
143  const std::vector<BITMAPS>& orientationIcons = PinOrientationIcons();
144 
145  for ( unsigned ii = 0; ii < orientationNames.GetCount(); ii++ )
146  m_choiceOrientation->Insert( orientationNames[ii], KiBitmap( orientationIcons[ii] ), ii );
147 
148  // We can't set the tab order through wxWidgets due to shortcomings in their mnemonics
149  // implementation on MSW
150  m_tabOrder = {
155  m_posXCtrl,
156  m_posYCtrl,
163  m_checkShow,
166  };
167 
168  // Default alternates turndow to whether or not alternates exist
169  m_alternatesTurndown->Collapse( m_pin->GetAlternates().size() == 0 );
170 
172 
173  // Save original columns widths so we can do proportional sizing.
174  for( int i = 0; i < COL_COUNT; ++i )
175  m_originalColWidths[ i ] = m_alternatesGrid->GetColSize( i );
176 
177  // Give a bit more room for combobox editors
178  m_alternatesGrid->SetDefaultRowSize( m_alternatesGrid->GetDefaultRowSize() + 4 );
179 
181  m_alternatesGrid->PushEventHandler( new GRID_TRICKS( m_alternatesGrid ) );
182 
183  if( aPin->GetParent()->HasConversion() )
184  {
185  m_alternatesTurndown->Collapse();
186  m_alternatesTurndown->Disable();
187  m_alternatesTurndown->SetToolTip(
188  _( "Alternate pin assignments are not available for DeMorgan symbols." ) );
189  }
190 
191  // Set special attributes
192  wxGridCellAttr* attr;
193 
194  attr = new wxGridCellAttr;
195  attr->SetRenderer( new GRID_CELL_ICON_TEXT_RENDERER( PinTypeIcons(), PinTypeNames() ) );
196  attr->SetEditor( new GRID_CELL_ICON_TEXT_POPUP( PinTypeIcons(), PinTypeNames() ) );
197  m_alternatesGrid->SetColAttr( COL_TYPE, attr );
198 
199  attr = new wxGridCellAttr;
200  attr->SetRenderer( new GRID_CELL_ICON_TEXT_RENDERER( PinShapeIcons(), PinShapeNames() ) );
201  attr->SetEditor( new GRID_CELL_ICON_TEXT_POPUP( PinShapeIcons(), PinShapeNames() ) );
202  m_alternatesGrid->SetColAttr( COL_SHAPE, attr );
203 
206 
207  m_sdbSizerButtonsOK->SetDefault();
209 
210  // Now all widgets have the size fixed, call FinishDialogSettings
212 
213  // On some window managers (Unity, XFCE) the dialog is not always raised, depending on
214  // how it is run.
215  Raise();
216 
217  m_initialized = true;
218  m_width = 0;
219 }
220 
221 
223 {
224  delete m_dummyPin;
225 
226  // Prevents crash bug in wxGrid's d'tor
228 
229  // Delete the GRID_TRICKS.
230  m_alternatesGrid->PopEventHandler( true );
231 }
232 
233 
235 {
236  if( !DIALOG_SHIM::TransferDataToWindow() )
237  return false;
238 
240 
244  m_textPinName->SetValue( m_pin->GetName() );
247  m_posY.SetValue( -m_origPos.y );
248  m_textPinNumber->SetValue( m_pin->GetNumber() );
251  m_checkApplyToAllParts->SetValue( m_pin->GetUnit() == 0 );
252  m_checkApplyToAllConversions->SetValue( m_pin->GetConvert() == 0 );
253  m_checkShow->SetValue( m_pin->IsVisible() );
254 
256 
257  for( const std::pair<const wxString, LIB_PIN::ALT>& alt : m_pin->GetAlternates() )
258  m_alternatesDataModel->AppendRow( alt.second );
259 
260  return true;
261 }
262 
263 
265 {
267  return false;
268 
269  // Check for missing alternate names.
270  for( size_t i = 0; i < m_alternatesDataModel->size(); ++i )
271  {
272  if( m_alternatesDataModel->at( i ).m_Name.IsEmpty() )
273  {
274  DisplayErrorMessage( this, _( "Alternate pin definitions must have a name." ) );
275 
277  m_delayedFocusRow = i;
278 
279  return false;
280  }
281  }
282 
283  if( !DIALOG_SHIM::TransferDataFromWindow() )
284  return false;
285 
286  wxPoint newPos( m_posX.GetValue(), -m_posY.GetValue() );
287 
288  const int acceptable_mingrid = 50;
289 
290  // Only show the warning if the position has been changed
291  if( ( m_origPos != newPos )
292  && ( ( m_posX.GetValue() % acceptable_mingrid ) || ( m_posY.GetValue() % acceptable_mingrid ) ) )
293  {
294  auto msg = wxString::Format( _( "This pin is not on a %d mils grid which will make it\n"
295  "difficult to connect to in the schematic.\n"
296  "Do you want to continue?" ),
297  acceptable_mingrid );
298  if( !IsOK( this, msg ) )
299  return false;
300  }
301 
302  m_pin->SetName( m_textPinName->GetValue() );
303  m_pin->SetNumber( m_textPinNumber->GetValue() );
308  m_pin->SetPosition( newPos );
312  m_pin->SetUnit( m_checkApplyToAllParts->GetValue() ? 0 : m_frame->GetUnit() );
313  m_pin->SetVisible( m_checkShow->GetValue() );
314 
315  std::map<wxString, LIB_PIN::ALT>& alternates = m_pin->GetAlternates();
316  alternates.clear();
317 
318  for( const LIB_PIN::ALT& alt : *m_alternatesDataModel )
319  alternates[ alt.m_Name ] = alt;
320 
321  return true;
322 }
323 
324 
325 /*
326  * Draw (on m_panelShowPin) the pin according to current settings in dialog
327  */
328 void DIALOG_PIN_PROPERTIES::OnPaintShowPanel( wxPaintEvent& event )
329 {
330  wxPaintDC dc( m_panelShowPin );
331  wxSize dc_size = dc.GetSize();
332  dc.SetDeviceOrigin( dc_size.x / 2, dc_size.y / 2 );
333 
334  // Give a parent to m_dummyPin only from draw purpose.
335  // In fact m_dummyPin should not have a parent, but draw functions need a parent
336  // to know some options, about pin texts
337  SYMBOL_EDIT_FRAME* symbolEditor = (SYMBOL_EDIT_FRAME*) GetParent();
338 
339  // Calculate a suitable scale to fit the available draw area
340  EDA_RECT bBox = m_dummyPin->GetBoundingBox( true );
341  double xscale = (double) dc_size.x / bBox.GetWidth();
342  double yscale = (double) dc_size.y / bBox.GetHeight();
343  double scale = std::min( xscale, yscale );
344 
345  // Give a 10% margin and limit to no more than 100% zoom
346  scale = std::min( scale * 0.9, 1.0 );
347  dc.SetUserScale( scale, scale );
348  GRResetPenAndBrush( &dc );
349 
350  LIB_SYMBOL_OPTIONS opts;
351  opts.draw_hidden_fields = true;
352  opts.show_connect_point = true;
353 
354  RENDER_SETTINGS* renderSettings = symbolEditor->GetRenderSettings();
355  renderSettings->SetPrintDC( &dc );
356 
357  m_dummyPin->Print( renderSettings, -bBox.Centre(), (void*) &opts, DefaultTransform );
358 
359  event.Skip();
360 }
361 
362 
363 void DIALOG_PIN_PROPERTIES::OnPropertiesChange( wxCommandEvent& event )
364 {
365  if( !IsShown() ) // do nothing at init time
366  return;
367 
368  m_dummyPin->SetName( m_textPinName->GetValue() );
369  m_dummyPin->SetNumber( m_textPinNumber->GetValue() );
376  m_dummyPin->SetVisible( m_checkShow->GetValue() );
377 
378  m_panelShowPin->Refresh();
379 }
380 
381 
382 void DIALOG_PIN_PROPERTIES::OnAddAlternate( wxCommandEvent& event )
383 {
385  return;
386 
387  LIB_PIN::ALT newAlt;
388  newAlt.m_Name = wxEmptyString;
389  newAlt.m_Type = m_pin->GetType();
390  newAlt.m_Shape = m_pin->GetShape();
391 
392  m_alternatesDataModel->AppendRow( newAlt );
393 
394  m_alternatesGrid->MakeCellVisible( m_alternatesGrid->GetNumberRows() - 1, 0 );
395  m_alternatesGrid->SetGridCursor( m_alternatesGrid->GetNumberRows() - 1, 0 );
396 
397  m_alternatesGrid->EnableCellEditControl( true );
398  m_alternatesGrid->ShowCellEditControl();
399 }
400 
401 
402 void DIALOG_PIN_PROPERTIES::OnDeleteAlternate( wxCommandEvent& event )
403 {
405  return;
406 
407  if( m_alternatesDataModel->size() == 0 ) // empty table
408  return;
409 
410  int curRow = m_alternatesGrid->GetGridCursorRow();
411 
412  if( curRow < 0 )
413  return;
414 
415  m_alternatesDataModel->RemoveRow( curRow );
416 
417  curRow = std::max( 0, curRow - 1 );
418  m_alternatesGrid->MakeCellVisible( curRow, m_alternatesGrid->GetGridCursorCol() );
419  m_alternatesGrid->SetGridCursor( curRow, m_alternatesGrid->GetGridCursorCol() );
420 }
421 
422 
424 {
425  m_width = aWidth;
426 
427  // Account for margins
428  aWidth -= 30;
429 
430  wxGridUpdateLocker deferRepaintsTillLeavingScope;
431 
434 
435  m_alternatesGrid->SetColSize( COL_NAME, aWidth - m_originalColWidths[ COL_TYPE ]
437 }
438 
439 
440 void DIALOG_PIN_PROPERTIES::OnSize( wxSizeEvent& event )
441 {
442  auto new_size = event.GetSize().GetX();
443 
444  if( m_initialized && m_width != new_size )
445  adjustGridColumns( new_size );
446 
447  // Always propagate for a grid repaint (needed if the height changes, as well as width)
448  event.Skip();
449 }
450 
451 
452 void DIALOG_PIN_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
453 {
454  // Handle a delayed focus
455  if( m_delayedFocusRow >= 0 )
456  {
457  m_alternatesTurndown->Collapse( false );
458 
459  m_alternatesGrid->SetFocus();
462 
463  m_alternatesGrid->EnableCellEditControl( true );
464  m_alternatesGrid->ShowCellEditControl();
465 
466  m_delayedFocusRow = -1;
468  }
469 }
470 
471 
void SetNumberTextSize(int aSize)
Definition: lib_pin.h:130
void GRResetPenAndBrush(wxDC *DC)
Definition: gr_basic.cpp:118
Functions for manipulating tab traversal in forms and dialogs.
void OnUpdateUI(wxUpdateUIEvent &event) override
const std::vector< BITMAPS > & PinOrientationIcons()
Definition: pin_type.cpp:228
wxString GetColLabelValue(int aCol) override
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:265
void SetOrientation(int aOrientation)
Definition: lib_pin.h:76
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
const std::vector< BITMAPS > & PinShapeIcons()
Definition: pin_type.cpp:210
This file is part of the common library.
int GetOrientation() const
Definition: lib_pin.h:75
void OnPropertiesChange(wxCommandEvent &event) override
std::vector< wxWindow * > m_tabOrder
Definition: dialog_shim.h:218
void SetShape(GRAPHIC_PINSHAPE aShape)
Definition: lib_pin.h:79
GRAPHIC_PINSHAPE GetShape() const
Definition: lib_pin.h:78
ALT_PIN_DATA_MODEL(EDA_UNITS aUserUnits)
void AppendRow(const LIB_PIN::ALT &aAlt)
void adjustGridColumns(int aWidth)
void SetSelection(GRAPHIC_PINSHAPE aShape)
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition: grid_tricks.h:52
int GetWidth() const
Definition: eda_rect.h:109
int m_originalColWidths[COL_COUNT]
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
int PinOrientationIndex(int code)
Definition: pin_type.cpp:147
void SetLength(int aLength)
Definition: lib_pin.h:82
KIGFX::SCH_RENDER_SETTINGS * GetRenderSettings()
bool TransferDataToWindow() override
int PinOrientationCode(int index)
Definition: pin_type.cpp:138
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:174
GRAPHIC_PINSHAPE
Definition: pin_type.h:55
void OnPaintShowPanel(wxPaintEvent &event) override
void SetPosition(const wxPoint &aPos) override
Definition: lib_pin.h:211
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:97
ELECTRICAL_PINTYPE m_Type
Definition: lib_pin.h:60
EDA_UNITS GetUserUnits() const
Definition: dialog_shim.h:119
void OnAddAlternate(wxCommandEvent &event) override
void SetNumber(const wxString &aNumber)
Definition: lib_pin.h:118
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:97
ALT_PIN_DATA_MODEL * m_alternatesDataModel
bool HasConversion() const
Test if symbol has more than one body conversion type (DeMorgan).
int GetUnit() const
Definition: lib_item.h:259
SYMBOL_EDIT_FRAME * m_frame
const wxArrayString & PinShapeNames()
Definition: pin_type.cpp:201
void SetType(ELECTRICAL_PINTYPE aType)
Definition: lib_pin.h:85
ELECTRICAL_PINTYPE GetPinTypeSelection()
const wxString & GetName() const
Definition: lib_pin.h:106
wxString GetValue(int aRow, int aCol) override
wxString m_Name
Definition: lib_pin.h:58
void SetVisible(bool aVisible)
Definition: lib_pin.h:98
const wxArrayString & PinTypeNames()
Definition: pin_type.cpp:183
void SetSelection(ELECTRICAL_PINTYPE aType)
#define _(s)
bool IsVisible() const
Definition: lib_pin.h:97
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:182
int GetNameTextSize() const
Definition: lib_pin.h:126
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
bool TransferDataFromWindow() override
int GetConvert() const
Definition: lib_item.h:262
void OnDeleteAlternate(wxCommandEvent &event) override
int GetHeight() const
Definition: eda_rect.h:110
void SetConvert(int aConvert)
Definition: lib_item.h:261
wxPoint GetPosition() const override
Definition: lib_pin.h:210
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
const wxArrayString & PinOrientationNames()
Definition: pin_type.cpp:219
EDA_UNITS
Definition: eda_units.h:38
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
const wxString & GetNumber() const
Definition: lib_pin.h:116
ELECTRICAL_PINTYPE GetType() const
Definition: lib_pin.h:84
LIB_SYMBOL * GetParent() const
Definition: lib_item.h:146
void SetUnit(int aUnit)
Definition: lib_item.h:258
std::map< wxString, ALT > & GetAlternates()
Definition: lib_pin.h:132
DIALOG_PIN_PROPERTIES(SYMBOL_EDIT_FRAME *parent, LIB_PIN *aPin)
int GetNumberTextSize() const
Definition: lib_pin.h:129
const int scale
TRANSFORM DefaultTransform
Definition: eeschema.cpp:56
void SetName(const wxString &aName)
Definition: lib_pin.h:108
void SetNameTextSize(int aSize)
Definition: lib_pin.h:127
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
Definition: pin_type.h:35
int GetLength() const
Definition: lib_pin.h:81
virtual void Print(const RENDER_SETTINGS *aSettings, const wxPoint &aOffset, void *aData, const TRANSFORM &aTransform)
Draw an item.
Definition: lib_item.cpp:122
void OnSize(wxSizeEvent &event) override
virtual void SetValue(int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
Class DIALOG_PIN_PROPERTIES_BASE.
Handle the component boundary box.
Definition: eda_rect.h:42
wxPoint Centre() const
Definition: eda_rect.h:55
virtual long long int GetValue()
Return 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:296
void SetPrintDC(wxDC *aDC)
GRAPHIC_PINSHAPE m_Shape
Definition: lib_pin.h:59
const std::vector< BITMAPS > & PinTypeIcons()
Definition: pin_type.cpp:192
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103
The symbol library editor main window.