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