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, true ),
128  m_posY( parent, m_posYLabel, m_posYCtrl, m_posYUnits, true ),
129  m_pinLength( parent, m_pinLengthLabel, m_pinLengthCtrl, m_pinLengthUnits, true ),
130  m_nameSize( parent, m_nameSizeLabel, m_nameSizeCtrl, m_nameSizeUnits, true ),
131  m_numberSize( parent, m_numberSizeLabel, m_numberSizeCtrl, m_numberSizeUnits, true ),
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<BITMAP_DEF>& 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 components." ) );
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 
204  m_addAlternate->SetBitmap( KiBitmap( small_plus_xpm ) );
205  m_deleteAlternate->SetBitmap( KiBitmap( small_trash_xpm ) );
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 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  PART_DRAW_OPTIONS opts;
351  opts.draw_hidden_fields = true;
352 
353  RENDER_SETTINGS* renderSettings = symbolEditor->GetRenderSettings();
354  renderSettings->SetPrintDC( &dc );
355 
356  m_dummyPin->Print( renderSettings, -bBox.Centre(), (void*) &opts, DefaultTransform );
357 
358  event.Skip();
359 }
360 
361 
362 void DIALOG_PIN_PROPERTIES::OnPropertiesChange( wxCommandEvent& event )
363 {
364  if( !IsShown() ) // do nothing at init time
365  return;
366 
367  m_dummyPin->SetName( m_textPinName->GetValue() );
368  m_dummyPin->SetNumber( m_textPinNumber->GetValue() );
375  m_dummyPin->SetVisible( m_checkShow->GetValue() );
376 
377  m_panelShowPin->Refresh();
378 }
379 
380 
381 void DIALOG_PIN_PROPERTIES::OnAddAlternate( wxCommandEvent& event )
382 {
384  return;
385 
386  LIB_PIN::ALT newAlt;
387  newAlt.m_Name = wxEmptyString;
388  newAlt.m_Type = m_pin->GetType();
389  newAlt.m_Shape = m_pin->GetShape();
390 
391  m_alternatesDataModel->AppendRow( newAlt );
392 
393  m_alternatesGrid->MakeCellVisible( m_alternatesGrid->GetNumberRows() - 1, 0 );
394  m_alternatesGrid->SetGridCursor( m_alternatesGrid->GetNumberRows() - 1, 0 );
395 
396  m_alternatesGrid->EnableCellEditControl( true );
397  m_alternatesGrid->ShowCellEditControl();
398 }
399 
400 
401 void DIALOG_PIN_PROPERTIES::OnDeleteAlternate( wxCommandEvent& event )
402 {
404  return;
405 
406  if( m_alternatesDataModel->size() == 0 ) // empty table
407  return;
408 
409  int curRow = m_alternatesGrid->GetGridCursorRow();
410 
411  if( curRow < 0 )
412  return;
413 
414  m_alternatesDataModel->RemoveRow( curRow );
415 
416  curRow = std::max( 0, curRow - 1 );
417  m_alternatesGrid->MakeCellVisible( curRow, m_alternatesGrid->GetGridCursorCol() );
418  m_alternatesGrid->SetGridCursor( curRow, m_alternatesGrid->GetGridCursorCol() );
419 }
420 
421 
423 {
424  m_width = aWidth;
425 
426  // Account for margins
427  aWidth -= 30;
428 
429  wxGridUpdateLocker deferRepaintsTillLeavingScope;
430 
433 
434  m_alternatesGrid->SetColSize( COL_NAME, aWidth - m_originalColWidths[ COL_TYPE ]
436 }
437 
438 
439 void DIALOG_PIN_PROPERTIES::OnSize( wxSizeEvent& event )
440 {
441  auto new_size = event.GetSize().GetX();
442 
443  if( m_initialized && m_width != new_size )
444  adjustGridColumns( new_size );
445 
446  // Always propagate for a grid repaint (needed if the height changes, as well as width)
447  event.Skip();
448 }
449 
450 
451 void DIALOG_PIN_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
452 {
453  // Handle a delayed focus
454  if( m_delayedFocusRow >= 0 )
455  {
456  m_alternatesTurndown->Collapse( false );
457 
458  m_alternatesGrid->SetFocus();
461 
462  m_alternatesGrid->EnableCellEditControl( true );
463  m_alternatesGrid->ShowCellEditControl();
464 
465  m_delayedFocusRow = -1;
467  }
468 }
469 
470 
void SetNumberTextSize(int aSize)
Definition: lib_pin.h:178
void GRResetPenAndBrush(wxDC *DC)
Definition: gr_basic.cpp:118
Functions for manipulating tab traversal in forms and dialogs.
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:266
void SetOrientation(int aOrientation)
Definition: lib_pin.h:126
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
This file is part of the common library.
const std::vector< BITMAP_DEF > & PinOrientationIcons()
Definition: pin_type.cpp:226
bool HasConversion() const
Test if part has more than one body conversion type (DeMorgan).
int GetOrientation() const
Definition: lib_pin.h:125
void OnPropertiesChange(wxCommandEvent &event) override
LIB_PART * GetParent() const
Definition: lib_item.h:149
std::vector< wxWindow * > m_tabOrder
Definition: dialog_shim.h:219
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:190
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:114
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:145
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:136
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:222
GRAPHIC_PINSHAPE
Definition: pin_type.h:54
void OnPaintShowPanel(wxPaintEvent &event) override
void SetPosition(const wxPoint &aPos) override
Definition: lib_pin.h:259
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:98
ELECTRICAL_PINTYPE m_Type
Definition: lib_pin.h:62
bool draw_hidden_fields
Definition: lib_symbol.h:66
const std::vector< BITMAP_DEF > & PinShapeIcons()
Definition: pin_type.cpp:208
EDA_UNITS GetUserUnits() const
Definition: dialog_shim.h:120
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:97
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:82
int GetUnit() const
Definition: lib_item.h:262
SYMBOL_EDIT_FRAME * m_frame
const wxArrayString & PinShapeNames()
Definition: pin_type.cpp:199
void SetType(ELECTRICAL_PINTYPE aType)
Definition: lib_pin.h:135
ELECTRICAL_PINTYPE GetPinTypeSelection()
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:181
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:182
int GetNameTextSize() const
Definition: lib_pin.h:174
bool TransferDataFromWindow() override
int GetConvert() const
Definition: lib_item.h:265
void OnDeleteAlternate(wxCommandEvent &event) override
const BITMAP_OPAQUE small_trash_xpm[1]
Definition: small_trash.cpp:23
int GetHeight() const
Definition: eda_rect.h:115
void SetConvert(int aConvert)
Definition: lib_item.h:264
wxPoint GetPosition() const override
Definition: lib_pin.h:258
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:217
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:165
ELECTRICAL_PINTYPE GetType() const
Definition: lib_pin.h:134
void SetUnit(int aUnit)
Definition: lib_item.h:261
std::map< wxString, ALT > & GetAlternates()
Definition: lib_pin.h:180
DIALOG_PIN_PROPERTIES(SYMBOL_EDIT_FRAME *parent, LIB_PIN *aPin)
Constructor.
int GetNumberTextSize() const
Definition: lib_pin.h:177
const int scale
TRANSFORM DefaultTransform
Definition: eeschema.cpp:56
void SetName(const wxString &aName)
Definition: lib_pin.h:157
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
virtual void Print(const RENDER_SETTINGS *aSettings, const wxPoint &aOffset, void *aData, const TRANSFORM &aTransform)
Draw an item.
Definition: lib_item.cpp:137
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:60
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:297
void SetPrintDC(wxDC *aDC)
const BITMAP_OPAQUE small_plus_xpm[1]
Definition: small_plus.cpp:18
GRAPHIC_PINSHAPE m_Shape
Definition: lib_pin.h:61
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:98
The symbol library editor main window.