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  printf("Create!\n");
65 
66  m_NetComboBox->SetBoard( aParent->GetBoard() );
67  m_NetComboBox->Enable( true );
68 
69  bool hasLocked = false;
70  bool hasUnlocked = false;
71 
72  for( auto& item : m_items )
73  {
74  int net = static_cast<BOARD_CONNECTED_ITEM*>(item)->GetNetCode();
75 
76  if( prevNet >= 0 && net != prevNet )
77  {
78  printf("prev %d net %d\n", net, prevNet );
79  m_haveUniqueNet = false;
80  break;
81  }
82 
83  prevNet = net;
84  }
85 
86  if ( m_haveUniqueNet )
87  {
88  m_NetComboBox->SetSelectedNet( prevNet );
89  }
90  else
91  {
92  m_NetComboBox->SetMultiple( true );
93  }
94 
95  // Look for values that are common for every item that is selected
96  for( auto& item : m_items )
97  {
98  switch( item->Type() )
99  {
100  case PCB_TRACE_T:
101  {
102  const TRACK* t = static_cast<const TRACK*>( item );
103 
104  if( !m_tracks ) // first track in the list
105  {
106  trackStartX = t->GetStart().x;
107  trackStartY = t->GetStart().y;
108  trackEndX = t->GetEnd().x;
109  trackEndY = t->GetEnd().y;
110  trackWidth = t->GetWidth();
111  trackLayer = t->GetLayer();
112  m_tracks = true;
113  }
114  else // check if values are the same for every selected track
115  {
116  if( trackStartX && ( *trackStartX != t->GetStart().x ) )
117  trackStartX = boost::none;
118 
119  if( trackStartY && ( *trackStartY != t->GetStart().y ) )
120  trackStartY = boost::none;
121 
122  if( trackEndX && ( *trackEndX != t->GetEnd().x ) )
123  trackEndX = boost::none;
124 
125  if( trackEndY && ( *trackEndY != t->GetEnd().y ) )
126  trackEndY = boost::none;
127 
128  if( trackWidth && ( *trackWidth != t->GetWidth() ) )
129  trackWidth = boost::none;
130 
131  if( trackLayer && ( *trackLayer != t->GetLayer() ) )
132  trackLayer = boost::none;
133  }
134 
135  if( t->IsLocked() )
136  hasLocked = true;
137  else
138  hasUnlocked = true;
139 
140  break;
141  }
142 
143  case PCB_VIA_T:
144  {
145  const VIA* v = static_cast<const VIA*>( item );
146 
147  if( !m_vias ) // first via in the list
148  {
149  viaX = v->GetPosition().x;
150  viaY = v->GetPosition().y;
151  viaDiameter = v->GetWidth();
152  viaDrill = v->GetDrillValue();
153  m_vias = true;
154  }
155  else // check if values are the same for every selected via
156  {
157  if( viaX && ( *viaX != v->GetPosition().x ) )
158  viaX = boost::none;
159 
160  if( viaY && ( *viaY != v->GetPosition().y ) )
161  viaY = boost::none;
162 
163  if( viaDiameter && ( *viaDiameter != v->GetWidth() ) )
164  viaDiameter = boost::none;
165 
166  if( viaDrill && ( *viaDrill != v->GetDrillValue() ) )
167  viaDrill = boost::none;
168  }
169 
170  if( v->IsLocked() )
171  hasLocked = true;
172  else
173  hasUnlocked = true;
174 
175  break;
176  }
177 
178  default:
179  wxASSERT( false );
180  break;
181  }
182  }
183 
184  wxASSERT( m_tracks || m_vias );
185 
186  if( m_vias )
187  {
188  setCommonVal( viaX, m_ViaXCtrl, m_viaX );
189  setCommonVal( viaY, m_ViaYCtrl, m_viaY );
191  setCommonVal( viaDrill, m_ViaDrillCtrl, m_viaDrill );
192  m_ViaDiameterCtrl->SetFocus();
193  }
194  else
195  {
196  m_MainSizer->Hide( m_sbViaSizer, true );
197  }
198 
199  if( m_tracks )
200  {
206 
209  m_TrackLayerCtrl->SetBoardFrame( aParent );
211 
212  if( trackLayer )
213  m_TrackLayerCtrl->SetLayerSelection( *trackLayer );
214 
215  m_TrackWidthCtrl->SetFocus();
216  }
217  else
218  {
219  m_MainSizer->Hide( m_sbTrackSizer, true );
220  }
221 
222  if( hasLocked && hasUnlocked )
223  {
224  m_lockedCbox->Set3StateValue( wxCHK_UNDETERMINED );
225  }
226  else if( hasLocked )
227  {
228  m_lockedCbox->Set3StateValue( wxCHK_CHECKED );
229  }
230  else
231  {
232  m_lockedCbox->Set3StateValue( wxCHK_UNCHECKED );
233  }
234 
235  m_StdButtonsOK->SetDefault();
236 
237  // Pressing ENTER when any of the text input fields is active applies changes
238  Connect( wxEVT_TEXT_ENTER, wxCommandEventHandler( DIALOG_TRACK_VIA_PROPERTIES::onOkClick ),
239  NULL, this );
240 }
241 
242 
244 {
245  if( !check() )
246  return false;
247 
248  bool changeLock = m_lockedCbox->Get3StateValue() != wxCHK_UNDETERMINED;
249  bool setLock = m_lockedCbox->Get3StateValue() == wxCHK_CHECKED;
250 
251  for( auto item : m_items )
252  {
253  aCommit.Modify( item );
254 
255  switch( item->Type() )
256  {
257  case PCB_TRACE_T:
258  {
259  wxASSERT( m_tracks );
260  TRACK* t = static_cast<TRACK*>( item );
261 
263  {
264  wxPoint start = t->GetStart();
265 
266  if( m_trackStartX.Valid() )
267  start.x = m_trackStartX.GetValue();
268 
269  if( m_trackStartY.Valid() )
270  start.y = m_trackStartY.GetValue();
271 
272  t->SetStart( start );
273  }
274 
275  if( m_trackEndX.Valid() || m_trackEndY.Valid() )
276  {
277  wxPoint end = t->GetEnd();
278 
279  if( m_trackEndX.Valid() )
280  end.x = m_trackEndX.GetValue();
281 
282  if( m_trackEndY.Valid() )
283  end.y = m_trackEndY.GetValue();
284 
285  t->SetEnd( end );
286  }
287 
288  if( m_trackNetclass->IsChecked() )
289  {
290  t->SetWidth( t->GetNetClass()->GetTrackWidth() );
291  }
292  else if( m_trackWidth.Valid() )
293  {
295  }
296 
298 
299  if( layer != UNDEFINED_LAYER )
300  t->SetLayer( (PCB_LAYER_ID) layer );
301 
302  if( changeLock )
303  t->SetLocked( setLock );
304 
306  {
307  printf("snc %d\n", m_NetComboBox->GetSelectedNet());
309  }
310 
311 
312  break;
313  }
314 
315  case PCB_VIA_T:
316  {
317  wxASSERT( m_vias );
318 
319  VIA* v = static_cast<VIA*>( item );
320 
321  if( m_viaX.Valid() || m_viaY.Valid() )
322  {
323  wxPoint pos = v->GetPosition();
324 
325  if( m_viaX.Valid() )
326  pos.x = m_viaX.GetValue();
327 
328  if( m_viaY.Valid() )
329  pos.y = m_viaY.GetValue();
330 
331  v->SetPosition( pos );
332  }
333 
334  if( m_viaNetclass->IsChecked() )
335  {
336  switch( v->GetViaType() )
337  {
338  default:
339  wxFAIL_MSG("Unhandled via type");
340  // fall through
341 
342  case VIA_THROUGH:
343  case VIA_BLIND_BURIED:
344  v->SetWidth( v->GetNetClass()->GetViaDiameter() );
345  v->SetDrill( v->GetNetClass()->GetViaDrill() );
346  break;
347 
348  case VIA_MICROVIA:
349  v->SetWidth( v->GetNetClass()->GetuViaDiameter() );
350  v->SetDrill( v->GetNetClass()->GetuViaDrill() );
351  break;
352  }
353  }
354  else
355  {
356  if( m_viaDiameter.Valid() )
358 
359  if( m_viaDrill.Valid() )
360  v->SetDrill( m_viaDrill.GetValue() );
361 
362  }
363 
365  {
366  printf("snc %d\n", m_NetComboBox->GetSelectedNet());
368  }
369 
370  if( changeLock )
371  v->SetLocked( setLock );
372 
373  break;
374  }
375 
376  default:
377  wxASSERT( false );
378  break;
379  }
380  }
381 
382  return true;
383 }
384 
385 
386 void DIALOG_TRACK_VIA_PROPERTIES::onClose( wxCloseEvent& aEvent )
387 {
388  EndModal( 0 );
389 }
390 
391 
393 {
394  bool enableNC = aEvent.IsChecked();
395 
396  m_TrackWidthLabel->Enable( !enableNC );
397  m_TrackWidthCtrl->Enable( !enableNC );
398  m_TrackWidthUnit->Enable( !enableNC );
399 }
400 
401 
403 {
404  bool enableNC = aEvent.IsChecked();
405 
406  m_ViaDiameterLabel->Enable( !enableNC );
407  m_ViaDiameterCtrl->Enable( !enableNC );
408  m_ViaDiameterUnit->Enable( !enableNC );
409 
410  m_ViaDrillLabel->Enable( !enableNC );
411  m_ViaDrillCtrl->Enable( !enableNC );
412  m_ViaDrillUnit->Enable( !enableNC );
413 }
414 
415 
416 void DIALOG_TRACK_VIA_PROPERTIES::onCancelClick( wxCommandEvent& aEvent )
417 {
418  EndModal( 0 );
419 }
420 
421 
422 void DIALOG_TRACK_VIA_PROPERTIES::onOkClick( wxCommandEvent& aEvent )
423 {
424  if( check() )
425  EndModal( 1 );
426 }
427 
428 
430 {
431  bool trackNetclass = m_trackNetclass->IsChecked();
432  bool viaNetclass = m_trackNetclass->IsChecked();
433 
434  if( m_tracks && !trackNetclass && m_trackWidth.Valid() && m_trackWidth.GetValue() <= 0 )
435  {
436  DisplayError( GetParent(), _( "Invalid track width" ) );
437  m_TrackWidthCtrl->SetFocus();
438  return false;
439  }
440 
441  if( m_vias && !viaNetclass )
442  {
443  if( m_viaDiameter.Valid() && m_viaDiameter.GetValue() <= 0 )
444  {
445  DisplayError( GetParent(), _( "Invalid via diameter" ) );
446  m_ViaDiameterCtrl->SetFocus();
447  return false;
448  }
449 
450  if( m_viaDrill.Valid() && m_viaDrill.GetValue() <= 0 )
451  {
452  DisplayError( GetParent(), _( "Invalid via drill size" ) );
453  m_ViaDrillCtrl->SetFocus();
454  return false;
455  }
456 
458  {
459  DisplayError( GetParent(), _( "Via drill size has to be smaller than via diameter" ) );
460  m_ViaDrillCtrl->SetFocus();
461  return false;
462  }
463  }
464 
465  return true;
466 }
bool IsLocked() const override
Function IsLocked.
Definition: class_track.h:136
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 setCommonVal(const boost::optional< T > &aVal, wxTextCtrl *aTxtCtrl, WX_UNIT_BINDER &aBinder)
Sets wxTextCtrl to the value stored in boost::optional or "<...>" if it is not available...
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
const SELECTION & m_items
Selected items to be modified.
bool m_tracks
Flag that determines if the dialog displays track properties.
static LSET AllNonCuMask()
Function AllNonCuMask returns a mask holding all layer minus CU layers.
Definition: lset.cpp:662
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
std::shared_ptr< NETCLASS > GetNetClass() const
Function GetNetClass returns the NETCLASS for this item.
const wxPoint & GetStart() const
Definition: class_track.h:121
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)
void SetBoard(BOARD *m_board)
bool SetLayersHotkeys(bool value)
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
void SetSelectedNet(int aNetcode)
virtual int GetValue() const
Function GetValue Returns the current value in Internal Units.
PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
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
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.