KiCad PCB EDA Suite
dialog_track_via_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) 2015 CERN
5  * @author Maciej Suminski <maciej.suminski@cern.ch>
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 
27 #include <tools/selection_tool.h>
28 #include <class_track.h>
29 #include <wxPcbStruct.h>
30 #include <confirm.h>
31 #include <widgets/text_ctrl_eval.h>
32 
34 #include <board_commit.h>
35 
37  DIALOG_TRACK_VIA_PROPERTIES_BASE( aParent ), m_items( aItems ),
38  m_trackStartX( aParent, m_TrackStartXCtrl, m_TrackStartXUnit ),
39  m_trackStartY( aParent, m_TrackStartYCtrl, m_TrackStartYUnit ),
40  m_trackEndX( aParent, m_TrackEndXCtrl, m_TrackEndXUnit ),
41  m_trackEndY( aParent, m_TrackEndYCtrl, m_TrackEndYUnit ),
42  m_trackWidth( aParent, m_TrackWidthCtrl, m_TrackWidthUnit ),
43  m_viaX( aParent, m_ViaXCtrl, m_ViaXUnit ), m_viaY( aParent, m_ViaYCtrl, m_ViaYUnit ),
44  m_viaDiameter( aParent, m_ViaDiameterCtrl, m_ViaDiameterUnit ),
45  m_viaDrill( aParent, m_ViaDrillCtrl, m_ViaDrillUnit ),
46  m_tracks( false ), m_vias( false )
47 {
48  wxASSERT( !m_items.Empty() );
49 
50  // This is a way to trick gcc into considering these variables as initialized
51  OPT<int> trackStartX = NULLOPT;
52  OPT<int> trackStartY = NULLOPT;
53  OPT<int> trackEndX = NULLOPT;
54  OPT<int> trackEndY = NULLOPT;
55  OPT<int> trackWidth = NULLOPT;
56  OPT<PCB_LAYER_ID> trackLayer = NULLOPT;
57  OPT<int> viaX = NULLOPT;
58  OPT<int> viaY = NULLOPT;
59  OPT<int> viaDiameter = NULLOPT;
60  OPT<int> viaDrill = NULLOPT;
61 
62  m_haveUniqueNet = true;
63  int prevNet = -1;
64 
65  m_NetComboBox->SetBoard( aParent->GetBoard() );
66  m_NetComboBox->Enable( true );
67 
68  bool hasLocked = false;
69  bool hasUnlocked = false;
70 
71  for( auto& item : m_items )
72  {
73  int net = static_cast<BOARD_CONNECTED_ITEM*>(item)->GetNetCode();
74 
75  if( prevNet >= 0 && net != prevNet )
76  {
77  printf("prev %d net %d\n", net, prevNet );
78  m_haveUniqueNet = false;
79  break;
80  }
81 
82  prevNet = net;
83  }
84 
85  if ( m_haveUniqueNet )
86  {
87  m_NetComboBox->SetSelectedNet( prevNet );
88  }
89  else
90  {
91  m_NetComboBox->SetMultiple( true );
92  }
93 
94  // Look for values that are common for every item that is selected
95  for( auto& item : m_items )
96  {
97  switch( item->Type() )
98  {
99  case PCB_TRACE_T:
100  {
101  const TRACK* t = static_cast<const TRACK*>( item );
102 
103  if( !m_tracks ) // first track in the list
104  {
105  trackStartX = t->GetStart().x;
106  trackStartY = t->GetStart().y;
107  trackEndX = t->GetEnd().x;
108  trackEndY = t->GetEnd().y;
109  trackWidth = t->GetWidth();
110  trackLayer = t->GetLayer();
111  m_tracks = true;
112  }
113  else // check if values are the same for every selected track
114  {
115  if( trackStartX && ( *trackStartX != t->GetStart().x ) )
116  trackStartX = NULLOPT;
117 
118  if( trackStartY && ( *trackStartY != t->GetStart().y ) )
119  trackStartY = NULLOPT;
120 
121  if( trackEndX && ( *trackEndX != t->GetEnd().x ) )
122  trackEndX = NULLOPT;
123 
124  if( trackEndY && ( *trackEndY != t->GetEnd().y ) )
125  trackEndY = NULLOPT;
126 
127  if( trackWidth && ( *trackWidth != t->GetWidth() ) )
128  trackWidth = NULLOPT;
129 
130  if( trackLayer && ( *trackLayer != t->GetLayer() ) )
131  trackLayer = NULLOPT;
132  }
133 
134  if( t->IsLocked() )
135  hasLocked = true;
136  else
137  hasUnlocked = true;
138 
139  break;
140  }
141 
142  case PCB_VIA_T:
143  {
144  const VIA* v = static_cast<const VIA*>( item );
145 
146  if( !m_vias ) // first via in the list
147  {
148  viaX = v->GetPosition().x;
149  viaY = v->GetPosition().y;
150  viaDiameter = v->GetWidth();
151  viaDrill = v->GetDrillValue();
152  m_vias = true;
153  }
154  else // check if values are the same for every selected via
155  {
156  if( viaX && ( *viaX != v->GetPosition().x ) )
157  viaX = NULLOPT;
158 
159  if( viaY && ( *viaY != v->GetPosition().y ) )
160  viaY = NULLOPT;
161 
162  if( viaDiameter && ( *viaDiameter != v->GetWidth() ) )
163  viaDiameter = NULLOPT;
164 
165  if( viaDrill && ( *viaDrill != v->GetDrillValue() ) )
166  viaDrill = NULLOPT;
167  }
168 
169  if( v->IsLocked() )
170  hasLocked = true;
171  else
172  hasUnlocked = true;
173 
174  break;
175  }
176 
177  default:
178  wxASSERT( false );
179  break;
180  }
181  }
182 
183  wxASSERT( m_tracks || m_vias );
184 
185  if( m_vias )
186  {
187  setCommonVal( viaX, m_ViaXCtrl, m_viaX );
188  setCommonVal( viaY, m_ViaYCtrl, m_viaY );
190  setCommonVal( viaDrill, m_ViaDrillCtrl, m_viaDrill );
192 
193  int viaSelection = wxNOT_FOUND;
194 
195  for( unsigned ii = 0; ii < aParent->GetDesignSettings().m_ViasDimensionsList.size(); ii++ )
196  {
197  VIA_DIMENSION* viaDimension = &aParent->GetDesignSettings().m_ViasDimensionsList[ii];
198  wxString msg = StringFromValue( g_UserUnit, viaDimension->m_Diameter, false )
199  + " / " + StringFromValue( g_UserUnit, viaDimension->m_Drill, false );
200  m_DesignRuleViasCtrl->Append( msg, viaDimension );
201 
202  if( viaSelection == wxNOT_FOUND && viaDiameter == viaDimension->m_Diameter
203  && viaDrill == viaDimension->m_Drill )
204  {
205  viaSelection = ii;
206  }
207  }
208 
209  m_DesignRuleViasCtrl->SetSelection( viaSelection );
210 
211  m_DesignRuleViasCtrl->Connect( wxEVT_CHOICE, wxCommandEventHandler( DIALOG_TRACK_VIA_PROPERTIES::onViaSelect ), NULL, this );
212  m_ViaDiameterCtrl->Connect( wxEVT_TEXT, wxCommandEventHandler( DIALOG_TRACK_VIA_PROPERTIES::onViaEdit ), NULL, this );
213  m_ViaDrillCtrl->Connect( wxEVT_TEXT, wxCommandEventHandler( DIALOG_TRACK_VIA_PROPERTIES::onViaEdit ), NULL, this );
214 
215  m_ViaDiameterCtrl->SetFocus();
216  }
217  else
218  {
219  m_MainSizer->Hide( m_sbViaSizer, true );
220  }
221 
222  if( m_tracks )
223  {
229 
230  for( unsigned ii = 0; ii < aParent->GetDesignSettings().m_TrackWidthList.size(); ii++ )
231  {
232  int width = aParent->GetDesignSettings().m_TrackWidthList[ii];
233  wxString msg = StringFromValue( g_UserUnit, width, false );
234  m_TrackWidthCtrl->Append( msg );
235  }
236 
239  m_TrackLayerCtrl->SetBoardFrame( aParent );
241 
242  if( trackLayer )
243  m_TrackLayerCtrl->SetLayerSelection( *trackLayer );
244 
245  m_TrackWidthCtrl->SetFocus();
246  }
247  else
248  {
249  m_MainSizer->Hide( m_sbTrackSizer, true );
250  }
251 
252  if( hasLocked && hasUnlocked )
253  {
254  m_lockedCbox->Set3StateValue( wxCHK_UNDETERMINED );
255  }
256  else if( hasLocked )
257  {
258  m_lockedCbox->Set3StateValue( wxCHK_CHECKED );
259  }
260  else
261  {
262  m_lockedCbox->Set3StateValue( wxCHK_UNCHECKED );
263  }
264 
265  m_StdButtonsOK->SetDefault();
266 
267  // Pressing ENTER when any of the text input fields is active applies changes
268  Connect( wxEVT_TEXT_ENTER, wxCommandEventHandler( DIALOG_TRACK_VIA_PROPERTIES::onOkClick ),
269  NULL, this );
270 }
271 
272 
274 {
275  if( !check() )
276  return false;
277 
278  bool changeLock = m_lockedCbox->Get3StateValue() != wxCHK_UNDETERMINED;
279  bool setLock = m_lockedCbox->Get3StateValue() == wxCHK_CHECKED;
280 
281  for( auto item : m_items )
282  {
283  aCommit.Modify( item );
284 
285  switch( item->Type() )
286  {
287  case PCB_TRACE_T:
288  {
289  wxASSERT( m_tracks );
290  TRACK* t = static_cast<TRACK*>( item );
291 
293  {
294  wxPoint start = t->GetStart();
295 
296  if( m_trackStartX.Valid() )
297  start.x = m_trackStartX.GetValue();
298 
299  if( m_trackStartY.Valid() )
300  start.y = m_trackStartY.GetValue();
301 
302  t->SetStart( start );
303  }
304 
305  if( m_trackEndX.Valid() || m_trackEndY.Valid() )
306  {
307  wxPoint end = t->GetEnd();
308 
309  if( m_trackEndX.Valid() )
310  end.x = m_trackEndX.GetValue();
311 
312  if( m_trackEndY.Valid() )
313  end.y = m_trackEndY.GetValue();
314 
315  t->SetEnd( end );
316  }
317 
318  if( m_trackNetclass->IsChecked() )
319  {
320  t->SetWidth( t->GetNetClass()->GetTrackWidth() );
321  }
322  else if( m_trackWidth.Valid() )
323  {
325  }
326 
328 
329  if( layer != UNDEFINED_LAYER )
330  t->SetLayer( (PCB_LAYER_ID) layer );
331 
332  if( changeLock )
333  t->SetLocked( setLock );
334 
336  {
337  printf("snc %d\n", m_NetComboBox->GetSelectedNet());
339  }
340 
341 
342  break;
343  }
344 
345  case PCB_VIA_T:
346  {
347  wxASSERT( m_vias );
348 
349  VIA* v = static_cast<VIA*>( item );
350 
351  if( m_viaX.Valid() || m_viaY.Valid() )
352  {
353  wxPoint pos = v->GetPosition();
354 
355  if( m_viaX.Valid() )
356  pos.x = m_viaX.GetValue();
357 
358  if( m_viaY.Valid() )
359  pos.y = m_viaY.GetValue();
360 
361  v->SetPosition( pos );
362  }
363 
364  if( m_viaNetclass->IsChecked() )
365  {
366  switch( v->GetViaType() )
367  {
368  default:
369  wxFAIL_MSG("Unhandled via type");
370  // fall through
371 
372  case VIA_THROUGH:
373  case VIA_BLIND_BURIED:
374  v->SetWidth( v->GetNetClass()->GetViaDiameter() );
375  v->SetDrill( v->GetNetClass()->GetViaDrill() );
376  break;
377 
378  case VIA_MICROVIA:
379  v->SetWidth( v->GetNetClass()->GetuViaDiameter() );
380  v->SetDrill( v->GetNetClass()->GetuViaDrill() );
381  break;
382  }
383  }
384  else
385  {
386  if( m_viaDiameter.Valid() )
388 
389  if( m_viaDrill.Valid() )
390  v->SetDrill( m_viaDrill.GetValue() );
391 
392  }
393 
395  {
396  printf("snc %d\n", m_NetComboBox->GetSelectedNet());
398  }
399 
400  if( changeLock )
401  v->SetLocked( setLock );
402 
403  break;
404  }
405 
406  default:
407  wxASSERT( false );
408  break;
409  }
410  }
411 
412  return true;
413 }
414 
415 
416 void DIALOG_TRACK_VIA_PROPERTIES::onClose( wxCloseEvent& aEvent )
417 {
418  EndModal( 0 );
419 }
420 
421 
423 {
424  bool enableNC = aEvent.IsChecked();
425 
426  m_TrackWidthLabel->Enable( !enableNC );
427  m_TrackWidthCtrl->Enable( !enableNC );
428  m_TrackWidthUnit->Enable( !enableNC );
429 }
430 
431 
433 {
434  bool enableNC = aEvent.IsChecked();
435 
436  m_DesignRuleVias->Enable( !enableNC );
437  m_DesignRuleViasCtrl->Enable( !enableNC );
438  m_DesignRuleViasUnit->Enable( !enableNC );
439 
440  m_ViaDiameterLabel->Enable( !enableNC );
441  m_ViaDiameterCtrl->Enable( !enableNC );
442  m_ViaDiameterUnit->Enable( !enableNC );
443 
444  m_ViaDrillLabel->Enable( !enableNC );
445  m_ViaDrillCtrl->Enable( !enableNC );
446  m_ViaDrillUnit->Enable( !enableNC );
447 }
448 
449 
450 void DIALOG_TRACK_VIA_PROPERTIES::onCancelClick( wxCommandEvent& aEvent )
451 {
452  EndModal( 0 );
453 }
454 
455 
456 void DIALOG_TRACK_VIA_PROPERTIES::onOkClick( wxCommandEvent& aEvent )
457 {
458  if( check() )
459  EndModal( 1 );
460 }
461 
462 
463 void DIALOG_TRACK_VIA_PROPERTIES::onViaSelect( wxCommandEvent& aEvent )
464 {
465  VIA_DIMENSION* viaDimension = static_cast<VIA_DIMENSION*> ( aEvent.GetClientData() );
466 
467  wxString msg = StringFromValue( g_UserUnit, viaDimension->m_Diameter, false );
468  m_ViaDiameterCtrl->ChangeValue( msg );
469 
470  msg = StringFromValue( g_UserUnit, viaDimension->m_Drill, false );
471  m_ViaDrillCtrl->ChangeValue( msg );
472 }
473 
474 
475 void DIALOG_TRACK_VIA_PROPERTIES::onViaEdit( wxCommandEvent& aEvent )
476 {
477  m_DesignRuleViasCtrl->SetSelection( wxNOT_FOUND );
478 }
479 
480 
482 {
483  bool trackNetclass = m_trackNetclass->IsChecked();
484  bool viaNetclass = m_trackNetclass->IsChecked();
485 
486  if( m_tracks && !trackNetclass && m_trackWidth.Valid() && m_trackWidth.GetValue() <= 0 )
487  {
488  DisplayError( GetParent(), _( "Invalid track width" ) );
489  m_TrackWidthCtrl->SetFocus();
490  return false;
491  }
492 
493  if( m_vias && !viaNetclass )
494  {
495  if( m_viaDiameter.Valid() && m_viaDiameter.GetValue() <= 0 )
496  {
497  DisplayError( GetParent(), _( "Invalid via diameter" ) );
498  m_ViaDiameterCtrl->SetFocus();
499  return false;
500  }
501 
502  if( m_viaDrill.Valid() && m_viaDrill.GetValue() <= 0 )
503  {
504  DisplayError( GetParent(), _( "Invalid via drill size" ) );
505  m_ViaDrillCtrl->SetFocus();
506  return false;
507  }
508 
510  {
511  DisplayError( GetParent(), _( "Via drill size has to be smaller than via diameter" ) );
512  m_ViaDrillCtrl->SetFocus();
513  return false;
514  }
515  }
516 
517  return true;
518 }
bool IsLocked() const override
Function IsLocked.
Definition: class_track.h:138
Struct VIA_DIMENSION is a small helper container to handle a stock of specific vias each with unique ...
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:106
COMMIT & Modify(EDA_ITEM *aItem)
Modifies a given item in the model.
Definition: commit.h:103
void onTrackNetclassCheck(wxCommandEvent &aEvent) override
bool check() const
Checks if the dialog values are correct.
void SetPosition(const wxPoint &aPoint) override
Definition: class_track.h:416
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
This file is part of the common library.
void SetEnd(const wxPoint &aEnd)
Definition: class_track.h:119
std::vector< int > m_TrackWidthList
Track width list.
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
const SELECTION & m_items
Selected items to be modified.
bool m_tracks
Flag that determines if the dialog displays track properties.
wxString StringFromValue(EDA_UNITS_T aUnit, int aValue, bool aAddUnitSymbol)
Function StringFromValue returns the string from aValue according to units (inch, mm ...
Definition: base_units.cpp:204
static LSET AllNonCuMask()
Function AllNonCuMask returns a mask holding all layer minus CU layers.
Definition: lset.cpp:669
bool m_vias
Flag that determines if the dialog displays via properties.
BOARD * GetBoard() const
Class COMMIT.
Definition: commit.h:71
void SetBoardFrame(PCB_BASE_FRAME *aFrame)
Class BOARD_CONNECTED_ITEM is a base class derived from BOARD_ITEM for items that can be connected an...
virtual int GetValue() const
Function GetValue Returns the current value in Internal Units.
Definition: unit_binder.cpp:64
const wxPoint & GetEnd() const
Definition: class_track.h:120
Functions relatives to tracks, vias and segments used to fill zones.
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
void onCancelClick(wxCommandEvent &aEvent) override
void SetWidth(int aWidth)
Definition: class_track.h:116
bool IsUniqueNetSelected() const
void SetLocked(bool aLocked) override
Function SetLocked modifies 'lock' status for of the item.
Definition: class_track.h:143
PCB_LAYER_ID
A quick note on layer IDs:
const auto NULLOPT
Definition: optional.h:9
VIATYPE_T GetViaType() const
Definition: class_track.h:443
std::shared_ptr< NETCLASS > GetNetClass() const
Function GetNetClass returns the NETCLASS for this item.
const wxPoint & GetStart() const
Definition: class_track.h:123
wxString GetAbbreviatedUnitsLabel(EDA_UNITS_T aUnit)
Definition: base_units.cpp:484
bool SetNetCode(int aNetCode, bool aNoAssert=false)
Function SetNetCode sets net using a net code.
int SetLayerSelection(LAYER_NUM layer)
DIALOG_TRACK_VIA_PROPERTIES(PCB_BASE_FRAME *aParent, const SELECTION &aItems)
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings returns the BOARD_DESIGN_SETTINGS for the BOARD owned by this frame...
void SetBoard(BOARD *m_board)
bool SetLayersHotkeys(bool value)
void onViaSelect(wxCommandEvent &aEvent)
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
void SetSelectedNet(int aNetcode)
EDA_UNITS_T g_UserUnit
Global variables definitions.
Definition: common.cpp:56
void onViaEdit(wxCommandEvent &aEvent)
void onOkClick(wxCommandEvent &aEvent) override
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
void SetMultiple(bool aMultiple=true)
int GetWidth() const
Definition: class_track.h:117
void onViaNetclassCheck(wxCommandEvent &aEvent) override
void onClose(wxCloseEvent &aEvent) override
LAYER_NUM GetLayerSelection() const
void SetDrill(int aDrill)
Function SetDrill sets the drill value for vias.
Definition: class_track.h:451
const wxPoint & GetPosition() const override
Definition: class_track.h:415
void setCommonVal(const OPT< T > &aVal, wxTextEntry *aTxtEntry, UNIT_BINDER &aBinder)
Sets wxTextEntry to the value stored in OPT or "<...>" if it is not available. ...
std::vector< VIA_DIMENSION > m_ViasDimensionsList
Vias size and drill list.
boost::optional< T > OPT
Definition: optional.h:7
void SetStart(const wxPoint &aStart)
Definition: class_track.h:122
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
Class DIALOG_TRACK_VIA_PROPERTIES_BASE.
bool Valid() const
Function Valid Returns true if the text control contains a real number.
Definition: unit_binder.cpp:72
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:73
class PCB_BASE_FRAME basic PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer...
bool Apply(COMMIT &aCommit)
Applies values from the dialog to the selected items.