KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 The 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 <widgets/wx_infobar.h>
27#include <sch_painter.h>
28#include <symbol_edit_frame.h>
29#include <sch_pin.h>
31#include <confirm.h>
32#include <kiplatform/ui.h>
34#include <widgets/wx_grid.h>
35#include <grid_tricks.h>
38#include <wx/hyperlink.h>
40
41class ALT_PIN_DATA_MODEL : public WX_GRID_TABLE_BASE, public std::vector<SCH_PIN::ALT>
42{
43public:
45 {
46 }
47
48 int GetNumberRows() override { return (int) size(); }
49 int GetNumberCols() override { return COL_COUNT; }
50
51 wxString GetColLabelValue( int aCol ) override
52 {
53 switch( aCol )
54 {
55 case COL_NAME: return _( "Alternate Pin Name" );
56 case COL_TYPE: return _( "Electrical Type" );
57 case COL_SHAPE: return _( "Graphic Style" );
58 default: wxFAIL; return wxEmptyString;
59 }
60 }
61
62 bool IsEmptyCell( int row, int col ) override
63 {
64 return false; // don't allow adjacent cell overflow, even if we are actually empty
65 }
66
67 wxString GetValue( int aRow, int aCol ) override
68 {
69 switch( aCol )
70 {
71 case COL_NAME: return at( aRow ).m_Name;
72 case COL_TYPE: return PinTypeNames()[static_cast<int>( at( aRow ).m_Type )];
73 case COL_SHAPE: return PinShapeNames()[static_cast<int>( at( aRow ).m_Shape )];
74 default: wxFAIL; return wxEmptyString;
75 }
76 }
77
78 void SetValue( int aRow, int aCol, const wxString &aValue ) override
79 {
80 switch( aCol )
81 {
82 case COL_NAME:
83 at( aRow ).m_Name = aValue;
84 break;
85
86 case COL_TYPE:
87 if( PinTypeNames().Index( aValue ) != wxNOT_FOUND )
88 at( aRow ).m_Type = (ELECTRICAL_PINTYPE) PinTypeNames().Index( aValue );
89
90 break;
91
92 case COL_SHAPE:
93 if( PinShapeNames().Index( aValue ) != wxNOT_FOUND )
94 at( aRow ).m_Shape = (GRAPHIC_PINSHAPE) PinShapeNames().Index( aValue );
95
96 break;
97
98 default:
99 wxFAIL;
100 break;
101 }
102 }
103
104 void AppendRow( const SCH_PIN::ALT& aAlt )
105 {
106 push_back( aAlt );
107
108 if ( GetView() )
109 {
110 wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
111 GetView()->ProcessTableMessage( msg );
112 }
113 }
114
115 void RemoveRow( int aRow )
116 {
117 erase( begin() + aRow );
118
119 if ( GetView() )
120 {
121 wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, aRow, 1 );
122 GetView()->ProcessTableMessage( msg );
123 }
124 }
125};
126
127
129 bool aFocusPinNumber ) :
131 m_frame( parent ),
132 m_pin( aPin ),
138 m_delayedFocusRow( -1 ),
140 m_initialized( false )
141{
142 // Create a dummy symbol with a single pin for the preview widget:
143 m_dummyParent = new LIB_SYMBOL( *static_cast<LIB_SYMBOL*>( m_pin->GetParentSymbol() ) );
144
145 // Move everything in the copied symbol to unit 1; we'll use unit 2 for the dummy pin:
146 m_dummyParent->SetUnitCount( 2, false );
147 m_dummyParent->RunOnChildren( [&]( SCH_ITEM* child )
148 {
149 child->SetUnit( 1 );
150 },
152
153 m_dummyPin = new SCH_PIN( *m_pin );
154 m_dummyPin->ClearFlags( IS_NEW ); // Needed to display the dummy pin
155 m_dummyPin->SetUnit( 2 );
156 m_dummyParent->AddDrawItem( m_dummyPin, false );
157
158 m_dummyParent->SetShowPinNames( true );
159 m_dummyParent->SetShowPinNumbers( true );
160
162 m_frame->GetCanvas()->GetBackend() );
163
164 m_previewWidget->SetLayoutDirection( wxLayout_LeftToRight );
165 m_previewWidget->DisplayPart( m_dummyParent, m_dummyPin->GetUnit(), m_dummyPin->GetBodyStyle() );
166
167 wxBoxSizer* previewSizer = new wxBoxSizer( wxHORIZONTAL );
168 previewSizer->Add( m_previewWidget, 1, wxEXPAND, 5 );
169 m_panelShowPin->SetSizer( previewSizer );
170
171 m_previewWidget->GetRenderSettings()->m_ShowHiddenPins = true;
172
173 const wxArrayString& orientationNames = PinOrientationNames();
174 const std::vector<BITMAPS>& orientationIcons = PinOrientationIcons();
175
176 for ( unsigned ii = 0; ii < orientationNames.GetCount(); ii++ )
177 m_choiceOrientation->Insert( orientationNames[ii], KiBitmapBundle( orientationIcons[ii] ), ii );
178
179 // We can't set the tab order through wxWidgets due to shortcomings in their mnemonics
180 // implementation on MSW
181 m_tabOrder = {
197 };
198
199 // Default alternates turndown to whether or not alternates exist, or if we've had it open
200 // before
201 m_alternatesTurndown->Collapse( m_pin->GetAlternates().size() == 0 && !s_alternatesTurndownOpen );
202
203 // wxwidgets doesn't call the OnCollapseChange even at init, so we update this value if
204 // the alternates pane defaults to open
205 if ( m_pin->GetAlternates().size() > 0 )
207
209
210 // Save original columns widths so we can do proportional sizing.
211 for( int i = 0; i < COL_COUNT; ++i )
212 m_originalColWidths[ i ] = m_alternatesGrid->GetColSize( i );
213
215 m_alternatesGrid->PushEventHandler( new GRID_TRICKS( m_alternatesGrid,
216 [this]( wxCommandEvent& aEvent )
217 {
218 OnAddAlternate( aEvent );
219 } ) );
220 m_alternatesGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
221
222 if( aPin->GetParentSymbol()->IsMultiBodyStyle() )
223 {
224 m_alternatesTurndown->Collapse();
225 m_alternatesTurndown->Disable();
226 m_alternatesTurndown->SetToolTip( _( "Alternate pin assignments are not available for symbols with "
227 "multiple body styles." ) );
228 }
229
230 // Set special attributes
231 wxGridCellAttr* attr;
232
233 attr = new wxGridCellAttr;
234 attr->SetRenderer( new GRID_CELL_ICON_TEXT_RENDERER( PinTypeIcons(), PinTypeNames() ) );
235 attr->SetEditor( new GRID_CELL_ICON_TEXT_POPUP( PinTypeIcons(), PinTypeNames() ) );
236 m_alternatesGrid->SetColAttr( COL_TYPE, attr );
237
238 attr = new wxGridCellAttr;
239 attr->SetRenderer( new GRID_CELL_ICON_TEXT_RENDERER( PinShapeIcons(), PinShapeNames() ) );
240 attr->SetEditor( new GRID_CELL_ICON_TEXT_POPUP( PinShapeIcons(), PinShapeNames() ) );
241 m_alternatesGrid->SetColAttr( COL_SHAPE, attr );
242
245 m_addAlternate->GetParent()->Layout();
246
248
249 SetInitialFocus( aFocusPinNumber ? m_textPinNumber : m_textPinName );
250
251 // We should call FinishDialogSettings() when all widgets have the size fixed.
252 // However m_infoBar is not yet initialized, so it will called later
253 // See TransferDataToWindow()
254
255 // On some window managers (Unity, XFCE) the dialog is not always raised, depending on
256 // how it is run.
257 Raise();
258
259 m_initialized = true;
260}
261
262
264{
265 delete m_dummyParent;
266
267 // Prevents crash bug in wxGrid's d'tor
269
270 // Delete the GRID_TRICKS.
271 m_alternatesGrid->PopEventHandler( true );
272}
273
274
276{
277 if( !DIALOG_SHIM::TransferDataToWindow() )
278 return false;
279
280 m_origPos = m_pin->GetPosition();
281
282 m_choiceOrientation->SetSelection( PinOrientationIndex( m_pin->GetOrientation() ) );
283 m_choiceStyle->SetSelection( m_pin->GetShape() );
284 m_choiceElectricalType->SetSelection( m_pin->GetType() );
285 m_textPinName->SetValue( m_pin->GetName() );
286 m_nameSize.SetValue( m_pin->GetNameTextSize() );
287 m_posX.SetValue( m_origPos.x );
288 m_posY.SetValue( m_origPos.y );
289 m_textPinNumber->SetValue( m_pin->GetNumber() );
290 m_numberSize.SetValue( m_pin->GetNumberTextSize() );
291 m_pinLength.SetValue( m_pin->GetLength() );
292 m_checkApplyToAllParts->Enable( m_pin->GetParentSymbol()->IsMultiUnit() );
293 m_checkApplyToAllParts->SetValue( m_pin->GetParentSymbol()->IsMultiUnit() && m_pin->GetUnit() == 0 );
294 m_checkApplyToAllBodyStyles->Enable( m_pin->GetParentSymbol()->IsMultiBodyStyle() );
295 m_checkApplyToAllBodyStyles->SetValue( m_pin->GetBodyStyle() == 0 );
296 m_checkShow->SetValue( m_pin->IsVisible() );
297
298 m_dummyPin->SetVisible( m_pin->IsVisible() );
299
300 wxString commonUnitsToolTip;
301
302 if( m_frame->m_SyncPinEdit )
303 {
304 wxHyperlinkCtrl* button = new wxHyperlinkCtrl( m_infoBar, wxID_ANY, _( "Exit sync pins mode" ),
305 wxEmptyString );
306
307 button->Bind( wxEVT_COMMAND_HYPERLINK,
308 std::function<void( wxHyperlinkEvent& aEvent )>(
309 [&]( wxHyperlinkEvent& aEvent )
310 {
311 m_frame->m_SyncPinEdit = false;
312 m_infoBar->Dismiss();
313 } ) );
314
315 m_infoBar->RemoveAllButtons();
316 m_infoBar->AddButton( button );
317 m_infoBar->ShowMessage( getSyncPinsMessage() );
318
319 commonUnitsToolTip = _( "Synchronized pins mode is enabled.\n"
320 "Similar pins will be edited regardless of this option." );
321 }
322 else
323 {
324 commonUnitsToolTip = _( "If checked, this pin will exist in all units." );
325 }
326
327 if( !m_pin->GetParentSymbol()->IsMultiUnit() )
328 commonUnitsToolTip = _( "This symbol only has one unit. This control has no effect." );
329
330 m_checkApplyToAllParts->SetToolTip( commonUnitsToolTip );
331
332 for( const std::pair<const wxString, SCH_PIN::ALT>& alt : m_pin->GetAlternates() )
333 m_alternatesDataModel->AppendRow( alt.second );
334
335 // We can call FinishDialogSettings() now all widgets have the size fixed.
337
338 return true;
339}
340
341
343{
344 if( !m_alternatesGrid->CommitPendingChanges() )
345 return false;
346
347 // Check for missing alternate names.
348 for( size_t i = 0; i < m_alternatesDataModel->size(); ++i )
349 {
350 if( m_alternatesDataModel->at( i ).m_Name.IsEmpty() )
351 {
352 DisplayErrorMessage( this, _( "Alternate pin definitions must have a name." ) );
353
356
357 return false;
358 }
359 }
360
361 if( !DIALOG_SHIM::TransferDataFromWindow() )
362 return false;
363
364 VECTOR2I newPos( m_posX.GetIntValue(), m_posY.GetIntValue() );
365
366 const int standard_grid = 50;
367
368 // Only show the warning if the position has been changed
369 if( ( m_origPos != newPos )
370 && ( ( m_posX.GetValue() % standard_grid ) || ( m_posY.GetValue() % standard_grid ) ) )
371 {
372 wxString msg = wxString::Format( _( "This pin is not on a %d mils grid which will make it "
373 "difficult to connect to in the schematic.\n"
374 "Do you wish to continue?" ),
375 standard_grid );
376 if( !IsOK( this, msg ) )
377 return false;
378 }
379
380 m_pin->SetName( m_textPinName->GetValue() );
381 m_pin->SetNumber( m_textPinNumber->GetValue() );
382 m_pin->SetNameTextSize( m_nameSize.GetIntValue() );
383 m_pin->SetNumberTextSize( m_numberSize.GetIntValue() );
384 m_pin->SetOrientation( PinOrientationCode( m_choiceOrientation->GetSelection() ) );
385 m_pin->SetPosition( newPos );
386 m_pin->ChangeLength( m_pinLength.GetIntValue() );
387 m_pin->SetType( m_choiceElectricalType->GetPinTypeSelection() );
388 m_pin->SetShape( m_choiceStyle->GetPinShapeSelection() );
389 m_pin->SetBodyStyle( m_checkApplyToAllBodyStyles->GetValue() ? 0 : m_frame->GetBodyStyle() );
390 m_pin->SetUnit( m_checkApplyToAllParts->GetValue() ? 0 : m_frame->GetUnit() );
391 m_pin->SetVisible( m_checkShow->GetValue() );
392
393 std::map<wxString, SCH_PIN::ALT>& alternates = m_pin->GetAlternates();
394 alternates.clear();
395
396 for( const SCH_PIN::ALT& alt : *m_alternatesDataModel )
397 alternates[ alt.m_Name ] = alt;
398
399 return true;
400}
401
402
403void DIALOG_PIN_PROPERTIES::OnPropertiesChange( wxCommandEvent& event )
404{
405 if( !IsShownOnScreen() ) // do nothing at init time
406 return;
407
408 m_dummyPin->SetName( m_textPinName->GetValue() );
409 m_dummyPin->SetNumber( m_textPinNumber->GetValue() );
410 m_dummyPin->SetNameTextSize( m_nameSize.GetIntValue() );
411 m_dummyPin->SetNumberTextSize( m_numberSize.GetIntValue() );
412 m_dummyPin->SetOrientation( PinOrientationCode( m_choiceOrientation->GetSelection() ) );
413 m_dummyPin->SetLength( m_pinLength.GetIntValue() );
414 m_dummyPin->SetType( m_choiceElectricalType->GetPinTypeSelection() );
415 m_dummyPin->SetShape( m_choiceStyle->GetPinShapeSelection() );
416 m_dummyPin->SetVisible( m_checkShow->GetValue() );
417
418 if( event.GetEventObject() == m_checkApplyToAllParts && m_frame->m_SyncPinEdit )
419 {
420 m_infoBar->ShowMessage( getSyncPinsMessage() );
421 m_infoBar->GetSizer()->Layout();
422 }
423
424 m_previewWidget->DisplayPart( m_dummyParent, m_dummyPin->GetUnit(), m_dummyPin->GetBodyStyle() );
425}
426
427
429{
430 if( m_checkApplyToAllParts->GetValue() )
431 return _( "Synchronized Pins Mode." );
432 else if( m_pin->IsNew() )
433 return _( "Synchronized Pins Mode. New pin will be added to all units." );
434 else
435 return _( "Synchronized Pins Mode. Matching pins in other units will be updated." );
436}
437
438
439void DIALOG_PIN_PROPERTIES::OnAddAlternate( wxCommandEvent& event )
440{
441 if( !m_alternatesGrid->CommitPendingChanges() )
442 return;
443
444 m_alternatesGrid->OnAddRow(
445 [&]() -> std::pair<int, int>
446 {
447 SCH_PIN::ALT newAlt;
448 newAlt.m_Name = wxEmptyString;
449 newAlt.m_Type = m_pin->GetType();
450 newAlt.m_Shape = m_pin->GetShape();
451
452 m_alternatesDataModel->AppendRow( newAlt );
453 return { m_alternatesGrid->GetNumberRows() - 1, COL_NAME };
454 } );
455}
456
457
458void DIALOG_PIN_PROPERTIES::OnDeleteAlternate( wxCommandEvent& event )
459{
460 m_alternatesGrid->OnDeleteRows(
461 [&]( int row )
462 {
463 m_alternatesDataModel->RemoveRow( row );
464 } );
465}
466
467
469{
470 // Account for scroll bars
472
473 wxGridUpdateLocker deferRepaintsTillLeavingScope;
474
477
479}
480
481
482void DIALOG_PIN_PROPERTIES::OnSize( wxSizeEvent& event )
483{
484 auto new_size = event.GetSize();
485
486 if( m_initialized && m_size != new_size )
487 {
488 m_size = new_size;
489
491 }
492
493 // Always propagate for a grid repaint (needed if the height changes, as well as width)
494 event.Skip();
495}
496
497
498void DIALOG_PIN_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
499{
500 // Handle a delayed focus
501 if( m_delayedFocusRow >= 0 )
502 {
503 m_alternatesTurndown->Collapse( false );
504
505 m_alternatesGrid->SetFocus();
508
509 m_alternatesGrid->EnableCellEditControl( true );
510 m_alternatesGrid->ShowCellEditControl();
511
514 }
515}
516
517
518void DIALOG_PIN_PROPERTIES::OnCollapsiblePaneChange( wxCollapsiblePaneEvent& event )
519{
520 if( !event.GetCollapsed() )
521 {
522 wxTopLevelWindow* tlw = dynamic_cast<wxTopLevelWindow*>( wxGetTopLevelParent( this ) );
523
524 if( tlw )
525 {
526 tlw->InvalidateBestSize();
527 wxSize bestSize = tlw->GetBestSize();
528 wxSize currentSize = tlw->GetSize();
529 tlw->SetSize( wxMax( bestSize.GetWidth(), currentSize.GetWidth() ),
530 wxMax( bestSize.GetHeight(), currentSize.GetHeight() ) );
531 }
532 }
533}
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:110
wxString GetColLabelValue(int aCol) override
void SetValue(int aRow, int aCol, const wxString &aValue) override
ALT_PIN_DATA_MODEL(EDA_UNITS aUserUnits)
wxString GetValue(int aRow, int aCol) override
void AppendRow(const SCH_PIN::ALT &aAlt)
bool IsEmptyCell(int row, int col) override
DIALOG_PIN_PROPERTIES_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Pin Properties"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
SYMBOL_EDIT_FRAME * m_frame
void OnUpdateUI(wxUpdateUIEvent &event) override
std::map< int, int > m_originalColWidths
void OnCollapsiblePaneChange(wxCollapsiblePaneEvent &event) override
void OnPropertiesChange(wxCommandEvent &event) override
void OnAddAlternate(wxCommandEvent &event) override
SYMBOL_PREVIEW_WIDGET * m_previewWidget
ALT_PIN_DATA_MODEL * m_alternatesDataModel
void OnSize(wxSizeEvent &event) override
DIALOG_PIN_PROPERTIES(SYMBOL_EDIT_FRAME *parent, SCH_PIN *aPin, bool aFocusPinNumber)
void OnDeleteAlternate(wxCommandEvent &event) override
std::vector< wxWindow * > m_tabOrder
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition dialog_shim.h:82
void SetupStandardButtons(std::map< int, wxString > aLabels={})
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
EDA_UNITS GetUserUnits() const
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition grid_tricks.h:61
Define a library symbol object.
Definition lib_symbol.h:83
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:168
const SYMBOL * GetParentSymbol() const
Definition sch_item.cpp:260
virtual void SetUnit(int aUnit)
Definition sch_item.h:238
The symbol library editor main window.
virtual bool IsMultiBodyStyle() const =0
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:259
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:202
This file is part of the common library.
#define _(s)
@ NO_RECURSE
Definition eda_item.h:53
#define IS_NEW
New item, just created.
EDA_UNITS
Definition eda_units.h:48
wxSize GetUnobscuredSize(const wxWindow *aWindow)
Tries to determine the size of the viewport of a scrollable widget (wxDataViewCtrl,...
Definition wxgtk/ui.cpp:281
const std::vector< BITMAPS > & PinTypeIcons()
Definition pin_type.cpp:162
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
Definition pin_type.h:36
const wxArrayString & PinTypeNames()
Definition pin_type.cpp:153
int PinOrientationIndex(PIN_ORIENTATION code)
Definition pin_type.cpp:70
const wxArrayString & PinShapeNames()
Definition pin_type.cpp:171
const std::vector< BITMAPS > & PinShapeIcons()
Definition pin_type.cpp:180
const wxArrayString & PinOrientationNames()
Definition pin_type.cpp:189
PIN_ORIENTATION PinOrientationCode(size_t index)
Definition pin_type.cpp:63
const std::vector< BITMAPS > & PinOrientationIcons()
Definition pin_type.cpp:198
GRAPHIC_PINSHAPE
Definition pin_type.h:84
wxString m_Name
Definition sch_pin.h:45
GRAPHIC_PINSHAPE m_Shape
Definition sch_pin.h:46
ELECTRICAL_PINTYPE m_Type
Definition sch_pin.h:47
Functions for manipulating tab traversal in forms and dialogs.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695