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 
32 #include <board_commit.h>
33 
35  DIALOG_TRACK_VIA_PROPERTIES_BASE( aParent ), m_items( aItems ),
36  m_trackStartX( aParent, m_TrackStartXCtrl, m_TrackStartXUnit ),
37  m_trackStartY( aParent, m_TrackStartYCtrl, m_TrackStartYUnit ),
38  m_trackEndX( aParent, m_TrackEndXCtrl, m_TrackEndXUnit ),
39  m_trackEndY( aParent, m_TrackEndYCtrl, m_TrackEndYUnit ),
40  m_trackWidth( aParent, m_TrackWidthCtrl, m_TrackWidthUnit ),
41  m_viaX( aParent, m_ViaXCtrl, m_ViaXUnit ), m_viaY( aParent, m_ViaYCtrl, m_ViaYUnit ),
42  m_viaDiameter( aParent, m_ViaDiameterCtrl, m_ViaDiameterUnit ),
43  m_viaDrill( aParent, m_ViaDrillCtrl, m_ViaDrillUnit ),
44  m_tracks( false ), m_vias( false )
45 {
46  assert( !m_items.Empty() );
47 
48  // This is a way to trick gcc into considering these variables as initialized
49  boost::optional<int> trackStartX = boost::make_optional<int>( false, 0 );
50  boost::optional<int> trackStartY = boost::make_optional<int>( false, 0 );
51  boost::optional<int> trackEndX = boost::make_optional<int>( false, 0 );
52  boost::optional<int> trackEndY = boost::make_optional<int>( false, 0 );
53  boost::optional<int> trackWidth = boost::make_optional<int>( false, 0 );
54  boost::optional<PCB_LAYER_ID> trackLayer = boost::make_optional<PCB_LAYER_ID>( false, (PCB_LAYER_ID) 0 );
55  boost::optional<int> viaX, viaY, viaDiameter;
56  boost::optional<int> viaDrill = boost::make_optional<int>( false, 0 );
57 
58  bool hasLocked = false;
59  bool hasUnlocked = false;
60 
61  // Look for values that are common for every item that is selected
62  for( auto& item : m_items )
63  {
64  switch( item->Type() )
65  {
66  case PCB_TRACE_T:
67  {
68  const TRACK* t = static_cast<const TRACK*>( item );
69 
70  if( !m_tracks ) // first track in the list
71  {
72  trackStartX = t->GetStart().x;
73  trackStartY = t->GetStart().y;
74  trackEndX = t->GetEnd().x;
75  trackEndY = t->GetEnd().y;
76  trackWidth = t->GetWidth();
77  trackLayer = t->GetLayer();
78  m_tracks = true;
79  }
80  else // check if values are the same for every selected track
81  {
82  if( trackStartX && ( *trackStartX != t->GetStart().x ) )
83  trackStartX = boost::none;
84 
85  if( trackStartY && ( *trackStartY != t->GetStart().y ) )
86  trackStartY = boost::none;
87 
88  if( trackEndX && ( *trackEndX != t->GetEnd().x ) )
89  trackEndX = boost::none;
90 
91  if( trackEndY && ( *trackEndY != t->GetEnd().y ) )
92  trackEndY = boost::none;
93 
94  if( trackWidth && ( *trackWidth != t->GetWidth() ) )
95  trackWidth = boost::none;
96 
97  if( trackLayer && ( *trackLayer != t->GetLayer() ) )
98  trackLayer = boost::none;
99  }
100 
101  if( t->IsLocked() )
102  hasLocked = true;
103  else
104  hasUnlocked = true;
105 
106  break;
107  }
108 
109  case PCB_VIA_T:
110  {
111  const VIA* v = static_cast<const VIA*>( item );
112 
113  if( !m_vias ) // first via in the list
114  {
115  viaX = v->GetPosition().x;
116  viaY = v->GetPosition().y;
117  viaDiameter = v->GetWidth();
118  viaDrill = v->GetDrillValue();
119  m_vias = true;
120  }
121  else // check if values are the same for every selected via
122  {
123  if( viaX && ( *viaX != v->GetPosition().x ) )
124  viaX = boost::none;
125 
126  if( viaY && ( *viaY != v->GetPosition().y ) )
127  viaY = boost::none;
128 
129  if( viaDiameter && ( *viaDiameter != v->GetWidth() ) )
130  viaDiameter = boost::none;
131 
132  if( viaDrill && ( *viaDrill != v->GetDrillValue() ) )
133  viaDrill = boost::none;
134  }
135 
136  if( v->IsLocked() )
137  hasLocked = true;
138  else
139  hasUnlocked = true;
140 
141  break;
142  }
143 
144  default:
145  assert( false );
146  break;
147  }
148  }
149 
150  assert( m_tracks || m_vias );
151 
152  if( m_vias )
153  {
154  setCommonVal( viaX, m_ViaXCtrl, m_viaX );
155  setCommonVal( viaY, m_ViaYCtrl, m_viaY );
157  setCommonVal( viaDrill, m_ViaDrillCtrl, m_viaDrill );
158  m_ViaDiameterCtrl->SetFocus();
159  }
160  else
161  {
162  m_MainSizer->Hide( m_sbViaSizer, true );
163  }
164 
165  if( m_tracks )
166  {
172 
175  m_TrackLayerCtrl->SetBoardFrame( aParent );
177 
178  if( trackLayer )
179  m_TrackLayerCtrl->SetLayerSelection( *trackLayer );
180 
181  m_TrackWidthCtrl->SetFocus();
182  }
183  else
184  {
185  m_MainSizer->Hide( m_sbTrackSizer, true );
186  }
187 
188  if( hasLocked && hasUnlocked )
189  {
190  m_lockedCbox->Set3StateValue( wxCHK_UNDETERMINED );
191  }
192  else if( hasLocked )
193  {
194  m_lockedCbox->Set3StateValue( wxCHK_CHECKED );
195  }
196  else
197  {
198  m_lockedCbox->Set3StateValue( wxCHK_UNCHECKED );
199  }
200 
201  m_StdButtonsOK->SetDefault();
202 
203  // Pressing ENTER when any of the text input fields is active applies changes
204  Connect( wxEVT_TEXT_ENTER, wxCommandEventHandler( DIALOG_TRACK_VIA_PROPERTIES::onOkClick ), NULL, this );
205 }
206 
207 
209 {
210  if( !check() )
211  return false;
212 
213  bool changeLock = m_lockedCbox->Get3StateValue() != wxCHK_UNDETERMINED;
214  bool setLock = m_lockedCbox->Get3StateValue() == wxCHK_CHECKED;
215 
216  for( auto item : m_items )
217  {
218  aCommit.Modify( item );
219 
220  switch( item->Type() )
221  {
222  case PCB_TRACE_T:
223  {
224  assert( m_tracks );
225  TRACK* t = static_cast<TRACK*>( item );
226 
228  {
229  wxPoint start = t->GetStart();
230 
231  if( m_trackStartX.Valid() )
232  start.x = m_trackStartX.GetValue();
233 
234  if( m_trackStartY.Valid() )
235  start.y = m_trackStartY.GetValue();
236 
237  t->SetStart( start );
238  }
239 
240  if( m_trackEndX.Valid() || m_trackEndY.Valid() )
241  {
242  wxPoint end = t->GetEnd();
243 
244  if( m_trackEndX.Valid() )
245  end.x = m_trackEndX.GetValue();
246 
247  if( m_trackEndY.Valid() )
248  end.y = m_trackEndY.GetValue();
249 
250  t->SetEnd( end );
251  }
252 
253  if( m_trackNetclass->IsChecked() )
254  {
255  t->SetWidth( t->GetNetClass()->GetTrackWidth() );
256  }
257  else if( m_trackWidth.Valid() )
258  {
260  }
261 
263 
264  if( layer != UNDEFINED_LAYER )
265  t->SetLayer( (PCB_LAYER_ID) layer );
266 
267  if( changeLock )
268  t->SetLocked( setLock );
269 
270  break;
271  }
272 
273  case PCB_VIA_T:
274  {
275  assert( m_vias );
276 
277  VIA* v = static_cast<VIA*>( item );
278 
279  if( m_viaX.Valid() || m_viaY.Valid() )
280  {
281  wxPoint pos = v->GetPosition();
282 
283  if( m_viaX.Valid() )
284  pos.x = m_viaX.GetValue();
285 
286  if( m_viaY.Valid() )
287  pos.y = m_viaY.GetValue();
288 
289  v->SetPosition( pos );
290  }
291 
292  if( m_viaNetclass->IsChecked() )
293  {
294  switch( v->GetViaType() )
295  {
296  default:
297  wxFAIL_MSG("Unhandled via type");
298  // fall through
299 
300  case VIA_THROUGH:
301  case VIA_BLIND_BURIED:
302  v->SetWidth( v->GetNetClass()->GetViaDiameter() );
303  v->SetDrill( v->GetNetClass()->GetViaDrill() );
304  break;
305 
306  case VIA_MICROVIA:
307  v->SetWidth( v->GetNetClass()->GetuViaDiameter() );
308  v->SetDrill( v->GetNetClass()->GetuViaDrill() );
309  break;
310  }
311  }
312  else
313  {
314  if( m_viaDiameter.Valid() )
316 
317  if( m_viaDrill.Valid() )
318  v->SetDrill( m_viaDrill.GetValue() );
319  }
320 
321  if( changeLock )
322  v->SetLocked( setLock );
323 
324  break;
325  }
326 
327  default:
328  assert( false );
329  break;
330  }
331  }
332 
333  return true;
334 }
335 
336 
337 void DIALOG_TRACK_VIA_PROPERTIES::onClose( wxCloseEvent& aEvent )
338 {
339  EndModal( 0 );
340 }
341 
342 
344 {
345  bool enableNC = aEvent.IsChecked();
346 
347  m_TrackWidthLabel->Enable( !enableNC );
348  m_TrackWidthCtrl->Enable( !enableNC );
349  m_TrackWidthUnit->Enable( !enableNC );
350 }
351 
352 
354 {
355  bool enableNC = aEvent.IsChecked();
356 
357  m_ViaDiameterLabel->Enable( !enableNC );
358  m_ViaDiameterCtrl->Enable( !enableNC );
359  m_ViaDiameterUnit->Enable( !enableNC );
360 
361  m_ViaDrillLabel->Enable( !enableNC );
362  m_ViaDrillCtrl->Enable( !enableNC );
363  m_ViaDrillUnit->Enable( !enableNC );
364 }
365 
366 
367 void DIALOG_TRACK_VIA_PROPERTIES::onCancelClick( wxCommandEvent& aEvent )
368 {
369  EndModal( 0 );
370 }
371 
372 
373 void DIALOG_TRACK_VIA_PROPERTIES::onOkClick( wxCommandEvent& aEvent )
374 {
375  if( check() )
376  EndModal( 1 );
377 }
378 
379 
381 {
382  bool trackNetclass = m_trackNetclass->IsChecked();
383  bool viaNetclass = m_trackNetclass->IsChecked();
384 
385  if( m_tracks && !trackNetclass && m_trackWidth.Valid() && m_trackWidth.GetValue() <= 0 )
386  {
387  DisplayError( GetParent(), _( "Invalid track width" ) );
388  m_TrackWidthCtrl->SetFocus();
389  return false;
390  }
391 
392  if( m_vias && !viaNetclass )
393  {
394  if( m_viaDiameter.Valid() && m_viaDiameter.GetValue() <= 0 )
395  {
396  DisplayError( GetParent(), _( "Invalid via diameter" ) );
397  m_ViaDiameterCtrl->SetFocus();
398  return false;
399  }
400 
401  if( m_viaDrill.Valid() && m_viaDrill.GetValue() <= 0 )
402  {
403  DisplayError( GetParent(), _( "Invalid via drill size" ) );
404  m_ViaDrillCtrl->SetFocus();
405  return false;
406  }
407 
409  {
410  DisplayError( GetParent(), _( "Via drill size has to be smaller than via diameter" ) );
411  m_ViaDrillCtrl->SetFocus();
412  return false;
413  }
414  }
415 
416  return true;
417 }
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.
Class COMMIT.
Definition: commit.h:71
void SetBoardFrame(PCB_BASE_FRAME *aFrame)
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 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
int SetLayerSelection(LAYER_NUM layer)
DIALOG_TRACK_VIA_PROPERTIES(PCB_BASE_FRAME *aParent, const SELECTION &aItems)
bool SetLayersHotkeys(bool value)
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
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 ...
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:69
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.