KiCad PCB EDA Suite
panel_setup_tracks_and_vias.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) 2018 KiCad Developers, see change_log.txt for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 
25 #include <base_units.h>
26 #include <pcb_edit_frame.h>
27 #include <board_design_settings.h>
28 #include <bitmaps.h>
29 #include <widgets/wx_grid.h>
30 #include <grid_tricks.h>
31 
33 
34 
36 {
38 };
39 
41 {
44 };
45 
47 {
51 };
52 
53 
55  PCB_EDIT_FRAME* aFrame,
56  PANEL_SETUP_FEATURE_CONSTRAINTS* aConstraintsPanel ) :
57  PANEL_SETUP_TRACKS_AND_VIAS_BASE( aParent->GetTreebook() )
58 {
59  m_Parent = aParent;
60  m_Frame = aFrame;
61  m_Pcb = m_Frame->GetBoard();
63  m_ConstraintsPanel = aConstraintsPanel;
64 
68  m_viaSizesRemoveButton->SetBitmap( KiBitmap( trash_xpm ) );
71 
72  // Membership combobox editors require a bit more room, so increase the row size of
73  // all our grids for consistency
74  m_trackWidthsGrid->SetDefaultRowSize( m_trackWidthsGrid->GetDefaultRowSize() + 4 );
75  m_viaSizesGrid->SetDefaultRowSize( m_viaSizesGrid->GetDefaultRowSize() + 4 );
76  m_diffPairsGrid->SetDefaultRowSize( m_diffPairsGrid->GetDefaultRowSize() + 4 );
77 
78  m_trackWidthsGrid->PushEventHandler( new GRID_TRICKS( m_trackWidthsGrid ) );
79  m_viaSizesGrid->PushEventHandler( new GRID_TRICKS( m_viaSizesGrid ) );
80  m_diffPairsGrid->PushEventHandler( new GRID_TRICKS( m_diffPairsGrid ) );
81 
82  m_trackWidthsGrid->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
83  m_viaSizesGrid->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
84  m_diffPairsGrid->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
85 }
86 
88 {
89  // Delete the GRID_TRICKS.
90  m_trackWidthsGrid->PopEventHandler( true );
91  m_viaSizesGrid->PopEventHandler( true );
92  m_diffPairsGrid->PopEventHandler( true );
93 }
94 
96 {
97  if( m_trackWidthsGrid->GetNumberRows() > 0 )
98  m_trackWidthsGrid->DeleteRows( 0, m_trackWidthsGrid->GetNumberRows() );
99 
100  if( m_viaSizesGrid->GetNumberRows() > 0 )
101  m_viaSizesGrid->DeleteRows( 0, m_viaSizesGrid->GetNumberRows() );
102 
103  if( m_diffPairsGrid->GetNumberRows() > 0 )
104  m_diffPairsGrid->DeleteRows( 0, m_diffPairsGrid->GetNumberRows() );
105 
106  // Skip the first item, which is the current netclass value
107  for( unsigned ii = 1; ii < m_BrdSettings->m_TrackWidthList.size(); ii++ )
108  {
110  }
111 
112  // Skip the first item, which is the current netclass value
113  for( unsigned ii = 1; ii < m_BrdSettings->m_ViasDimensionsList.size(); ii++ )
114  {
116  m_BrdSettings->m_ViasDimensionsList[ii].m_Drill );
117  }
118 
119  // Skip the first item, which is the current netclass value
120  for( unsigned ii = 1; ii < m_BrdSettings->m_DiffPairDimensionsList.size(); ii++ )
121  {
124  m_BrdSettings->m_DiffPairDimensionsList[ii].m_ViaGap );
125  }
126 
127  return true;
128 }
129 
130 
132 {
133  if( !validateData() )
134  return false;
135 
136  wxString msg;
137  std::vector<int> trackWidths;
138  std::vector<VIA_DIMENSION> vias;
139  std::vector<DIFF_PAIR_DIMENSION> diffPairs;
140 
144  {
145  return false;
146  }
147 
148  for( int row = 0; row < m_trackWidthsGrid->GetNumberRows(); ++row )
149  {
150  msg = m_trackWidthsGrid->GetCellValue( row, TR_WIDTH_COL );
151 
152  if( !msg.IsEmpty() )
153  trackWidths.push_back( ValueFromString( m_Frame->GetUserUnits(), msg ) );
154  }
155 
156  for( int row = 0; row < m_viaSizesGrid->GetNumberRows(); ++row )
157  {
158  msg = m_viaSizesGrid->GetCellValue( row, VIA_SIZE_COL );
159 
160  if( !msg.IsEmpty() )
161  {
162  VIA_DIMENSION via_dim;
163  via_dim.m_Diameter = ValueFromString( m_Frame->GetUserUnits(), msg );
164 
165  msg = m_viaSizesGrid->GetCellValue( row, VIA_DRILL_COL );
166 
167  if( !msg.IsEmpty() )
168  via_dim.m_Drill = ValueFromString( m_Frame->GetUserUnits(), msg );
169 
170  vias.push_back( via_dim );
171  }
172  }
173 
174  for( int row = 0; row < m_diffPairsGrid->GetNumberRows(); ++row )
175  {
176  msg = m_diffPairsGrid->GetCellValue( row, DP_WIDTH_COL );
177 
178  if( !msg.IsEmpty() )
179  {
180  DIFF_PAIR_DIMENSION diffPair_dim;
181  diffPair_dim.m_Width = ValueFromString( m_Frame->GetUserUnits(), msg );
182 
183  msg = m_diffPairsGrid->GetCellValue( row, DP_GAP_COL );
184  diffPair_dim.m_Gap = ValueFromString( m_Frame->GetUserUnits(), msg );
185 
186  msg = m_diffPairsGrid->GetCellValue( row, DP_VIA_GAP_COL );
187 
188  if( !msg.IsEmpty() )
189  diffPair_dim.m_ViaGap = ValueFromString( m_Frame->GetUserUnits(), msg );
190 
191  diffPairs.push_back( diffPair_dim );
192  }
193  }
194 
195  // Sort lists by increasing value
196  sort( trackWidths.begin(), trackWidths.end() );
197  sort( vias.begin(), vias.end() );
198  sort( diffPairs.begin(), diffPairs.end() );
199 
200  // These are all stored in project file, not board, so no need for OnModify()
201 
202  trackWidths.insert( trackWidths.begin(), 0 ); // dummy value for "use netclass"
203  m_BrdSettings->m_TrackWidthList = trackWidths;
204 
205  vias.insert( vias.begin(), { 0, 0 } ); // dummy value for "use netclass"
207 
208  diffPairs.insert( diffPairs.begin(), { 0, 0, 0 } ); // dummy value for "use netclass"
210 
211  return true;
212 }
213 
214 
216 {
220  {
221  return false;
222  }
223 
224  wxString msg;
225  int minViaAnnulus = m_ConstraintsPanel->m_viaMinAnnulus.GetValue();
226  int minViaDia = m_ConstraintsPanel->m_viaMinSize.GetValue();
227  int minThroughHole = m_ConstraintsPanel->m_throughHoleMin.GetValue();
228  int minTrackWidth = m_ConstraintsPanel->m_trackMinWidth.GetValue();
229  int minClearance = m_ConstraintsPanel->m_minClearance.GetValue();
230 
231  // Test tracks
232  for( int row = 0; row < m_trackWidthsGrid->GetNumberRows(); ++row )
233  {
234  wxString tvalue = m_trackWidthsGrid->GetCellValue( row, TR_WIDTH_COL );
235 
236  if( tvalue.IsEmpty() )
237  continue;
238 
239  if( ValueFromString( m_Frame->GetUserUnits(), tvalue ) < minTrackWidth )
240  {
241  msg.Printf( _( "Track width less than minimum track width (%s)." ),
242  StringFromValue( m_Frame->GetUserUnits(), minTrackWidth ) );
243  m_Parent->SetError( msg, this, m_trackWidthsGrid, row, TR_WIDTH_COL );
244  return false;
245  }
246  }
247 
248  // Test vias
249  for( int row = 0; row < m_viaSizesGrid->GetNumberRows(); ++row )
250  {
251  wxString viaDia = m_viaSizesGrid->GetCellValue( row, VIA_SIZE_COL );
252 
253  if( viaDia.IsEmpty() )
254  continue;
255 
256  if( ValueFromString( m_Frame->GetUserUnits(), viaDia ) < minViaDia )
257  {
258  msg.Printf( _( "Via diameter less than minimum via diameter (%s)." ),
259  StringFromValue( m_Frame->GetUserUnits(), minViaDia ) );
260  m_Parent->SetError( msg, this, m_viaSizesGrid, row, VIA_SIZE_COL );
261  return false;
262  }
263 
264  wxString viaDrill = m_viaSizesGrid->GetCellValue( row, VIA_DRILL_COL );
265 
266  if( viaDrill.IsEmpty() )
267  {
268  msg = _( "No via drill defined." );
269  m_Parent->SetError( msg, this, m_viaSizesGrid, row, VIA_DRILL_COL );
270  return false;
271  }
272 
273  if( ValueFromString( m_Frame->GetUserUnits(), viaDrill ) < minThroughHole )
274  {
275  msg.Printf( _( "Via drill less than minimum through hole (%s)." ),
276  StringFromValue( m_Frame->GetUserUnits(), minThroughHole ) );
277  m_Parent->SetError( msg, this, m_viaSizesGrid, row, VIA_DRILL_COL );
278  return false;
279  }
280 
281  if( ValueFromString( m_Frame->GetUserUnits(), viaDrill )
282  >= ValueFromString( m_Frame->GetUserUnits(), viaDia ) )
283  {
284  msg = _( "Via drill larger than via diameter." );
285  m_Parent->SetError( msg, this, m_viaSizesGrid, row, VIA_DRILL_COL );
286  return false;
287  }
288 
289  if( ( ValueFromString( m_Frame->GetUserUnits(), viaDia )
290  - ValueFromString( m_Frame->GetUserUnits(), viaDrill ) ) / 2 < minViaAnnulus )
291  {
292  msg.Printf( _( "Diameter and drill leave via annulus less than minimum (%s)." ),
293  StringFromValue( m_Frame->GetUserUnits(), minViaAnnulus ) );
294  m_Parent->SetError( msg, this, m_viaSizesGrid, row, VIA_SIZE_COL );
295  return false;
296  }
297  }
298 
299  // Test diff pairs
300  for( int row = 0; row < m_diffPairsGrid->GetNumberRows(); ++row )
301  {
302  wxString tvalue = m_diffPairsGrid->GetCellValue( row, 0 );
303 
304  if( tvalue.IsEmpty() )
305  continue;
306 
307  if( ValueFromString( m_Frame->GetUserUnits(), tvalue ) < minTrackWidth )
308  {
309  msg.Printf( _( "Differential pair track width less than minimum track width (%s)." ),
310  StringFromValue( m_Frame->GetUserUnits(), minTrackWidth ) );
311  m_Parent->SetError( msg, this, m_diffPairsGrid, row, 0 );
312  return false;
313  }
314 
315  wxString gap = m_diffPairsGrid->GetCellValue( row, 1 );
316 
317  if( gap.IsEmpty() )
318  {
319  msg = _( "No differential pair gap defined." );
320  m_Parent->SetError( msg, this, m_diffPairsGrid, row, 1 );
321  return false;
322  }
323 
324  if( ValueFromString( m_Frame->GetUserUnits(), gap ) < minClearance )
325  {
326  msg.Printf( _( "Differential pair gap less than minimum clearance (%s)." ),
327  StringFromValue( m_Frame->GetUserUnits(), minClearance ) );
328  m_Parent->SetError( msg, this, m_diffPairsGrid, row, 1 );
329  return false;
330  }
331 
332  wxString viaGap = m_diffPairsGrid->GetCellValue( row, 2 );
333 
334  if( viaGap.IsEmpty() )
335  continue;
336 
337  if( ValueFromString( m_Frame->GetUserUnits(), viaGap ) < minClearance )
338  {
339  msg.Printf( _( "Differential pair via gap less than minimum clearance (%s)." ),
340  StringFromValue( m_Frame->GetUserUnits(), minClearance ) );
341  m_Parent->SetError( msg, this, m_diffPairsGrid, row, 2 );
342  return false;
343  }
344  }
345 
346  return true;
347 }
348 
349 
351 {
352  int i = m_trackWidthsGrid->GetNumberRows();
353 
354  m_trackWidthsGrid->AppendRows( 1 );
355 
356  wxString val = StringFromValue( m_Frame->GetUserUnits(), aWidth );
357  m_trackWidthsGrid->SetCellValue( i, TR_WIDTH_COL, val );
358 }
359 
360 
361 void PANEL_SETUP_TRACKS_AND_VIAS::AppendViaSize( const int aSize, const int aDrill )
362 {
363  int i = m_viaSizesGrid->GetNumberRows();
364 
365  m_viaSizesGrid->AppendRows( 1 );
366 
367  wxString val = StringFromValue( m_Frame->GetUserUnits(), aSize );
368  m_viaSizesGrid->SetCellValue( i, VIA_SIZE_COL, val );
369 
370  if( aDrill > 0 )
371  {
372  val = StringFromValue( m_Frame->GetUserUnits(), aDrill );
373  m_viaSizesGrid->SetCellValue( i, VIA_DRILL_COL, val );
374  }
375 }
376 
377 
378 void PANEL_SETUP_TRACKS_AND_VIAS::AppendDiffPairs( const int aWidth, const int aGap,
379  const int aViaGap )
380 {
381  int i = m_diffPairsGrid->GetNumberRows();
382 
383  m_diffPairsGrid->AppendRows( 1 );
384 
385  wxString val = StringFromValue( m_Frame->GetUserUnits(), aWidth );
386  m_diffPairsGrid->SetCellValue( i, DP_WIDTH_COL, val );
387 
388  if( aGap > 0 )
389  {
390  val = StringFromValue( m_Frame->GetUserUnits(), aGap );
391  m_diffPairsGrid->SetCellValue( i, DP_GAP_COL, val );
392  }
393 
394  if( aViaGap > 0 )
395  {
396  val = StringFromValue( m_Frame->GetUserUnits(), aViaGap );
397  m_diffPairsGrid->SetCellValue( i, DP_VIA_GAP_COL, val );
398  }
399 }
400 
402 {
403  AppendTrackWidth( 0 );
404 
405  m_trackWidthsGrid->MakeCellVisible( m_trackWidthsGrid->GetNumberRows() - 1, TR_WIDTH_COL );
406  m_trackWidthsGrid->SetGridCursor( m_trackWidthsGrid->GetNumberRows() - 1, TR_WIDTH_COL );
407 
408  m_trackWidthsGrid->EnableCellEditControl( true );
409  m_trackWidthsGrid->ShowCellEditControl();
410 }
411 
412 
414 {
415  int curRow = m_trackWidthsGrid->GetGridCursorRow();
416 
417  if( curRow < 0 || m_trackWidthsGrid->GetNumberRows() <= curRow )
418  return;
419 
420  m_trackWidthsGrid->DeleteRows( curRow, 1 );
421 
422  curRow = std::max( 0, curRow - 1 );
423  m_trackWidthsGrid->MakeCellVisible( curRow, m_trackWidthsGrid->GetGridCursorCol() );
424  m_trackWidthsGrid->SetGridCursor( curRow, m_trackWidthsGrid->GetGridCursorCol() );
425 }
426 
427 
429 {
430  AppendViaSize( 0, 0 );
431 
432  m_viaSizesGrid->MakeCellVisible( m_viaSizesGrid->GetNumberRows() - 1, VIA_SIZE_COL );
433  m_viaSizesGrid->SetGridCursor( m_viaSizesGrid->GetNumberRows() - 1, VIA_SIZE_COL );
434 
435  m_viaSizesGrid->EnableCellEditControl( true );
436  m_viaSizesGrid->ShowCellEditControl();
437 }
438 
439 
441 {
442  int curRow = m_viaSizesGrid->GetGridCursorRow();
443 
444  if( curRow < 0 || m_viaSizesGrid->GetNumberRows() <= curRow )
445  return;
446 
447  m_viaSizesGrid->DeleteRows( curRow, 1 );
448 
449  curRow = std::max( 0, curRow - 1 );
450  m_viaSizesGrid->MakeCellVisible( curRow, m_viaSizesGrid->GetGridCursorCol() );
451  m_viaSizesGrid->SetGridCursor( curRow, m_viaSizesGrid->GetGridCursorCol() );
452 }
453 
454 
456 {
457  AppendDiffPairs( 0, 0, 0 );
458 
459  m_diffPairsGrid->MakeCellVisible( m_diffPairsGrid->GetNumberRows() - 1, DP_WIDTH_COL );
460  m_diffPairsGrid->SetGridCursor( m_diffPairsGrid->GetNumberRows() - 1, DP_WIDTH_COL );
461 
462  m_diffPairsGrid->EnableCellEditControl( true );
463  m_diffPairsGrid->ShowCellEditControl();
464 }
465 
466 
468 {
469  int curRow = m_diffPairsGrid->GetGridCursorRow();
470 
471  if( curRow < 0 || m_diffPairsGrid->GetNumberRows() <= curRow )
472  return;
473 
474  m_diffPairsGrid->DeleteRows( curRow, 1 );
475 
476  curRow = std::max( 0, curRow - 1 );
477  m_diffPairsGrid->MakeCellVisible( curRow, m_diffPairsGrid->GetGridCursorCol() );
478  m_diffPairsGrid->SetGridCursor( curRow, m_diffPairsGrid->GetGridCursorCol() );
479 }
480 
481 
483 {
487 
488  // Note: do not change the board, as we need to get the current nets from it for
489  // netclass memberships. All the netclass definitions and dimension lists are in
490  // the BOARD_DESIGN_SETTINGS.
491 
492  BOARD_DESIGN_SETTINGS* savedSettings = m_BrdSettings;
493 
494  m_BrdSettings = &aBoard->GetDesignSettings();
496 
497  m_BrdSettings = savedSettings;
498 }
499 
const BITMAP_OPAQUE trash_xpm[1]
Definition: trash.cpp:34
Struct VIA_DIMENSION is a small helper container to handle a stock of specific vias each with unique ...
void OnRemoveViaSizesClick(wxCommandEvent &event) override
Implementation of conversion functions that require both schematic and board internal units.
std::vector< int > m_TrackWidthList
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
PANEL_SETUP_FEATURE_CONSTRAINTS * m_ConstraintsPanel
GRID_TRICKS is used to add mouse and command handling (such as cut, copy, and paste) to a WX_GRID ins...
Definition: grid_tricks.h:52
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: class_board.h:558
void SetError(const wxString &aMessage, const wxString &aPageName, int aCtrlId, int aRow=-1, int aCol=-1)
Struct DIFF_PAIR_DIMENSION is a small helper container to handle a stock of specific differential pai...
void OnAddDiffPairsClick(wxCommandEvent &event) override
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Construct a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:82
long long int ValueFromString(EDA_UNITS aUnits, const wxString &aTextValue, EDA_DATA_TYPE aType)
Function ValueFromString converts aTextValue in aUnits to internal units used by the application.
Definition: base_units.cpp:444
void OnRemoveDiffPairsClick(wxCommandEvent &event) override
void OnAddViaSizesClick(wxCommandEvent &event) override
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:180
void AppendViaSize(const int aSize, const int aDrill)
PANEL_SETUP_TRACKS_AND_VIAS(PAGED_DIALOG *aParent, PCB_EDIT_FRAME *aFrame, PANEL_SETUP_FEATURE_CONSTRAINTS *aConstraintsPanel)
Information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:186
#define _(s)
Definition: 3d_actions.cpp:33
void OnAddTrackWidthsClick(wxCommandEvent &event) override
PCB_EDIT_FRAME is the main frame for Pcbnew.
std::vector< VIA_DIMENSION > m_ViasDimensionsList
virtual long long int GetValue()
Function GetValue Returns the current value in Internal Units.
wxString StringFromValue(EDA_UNITS aUnits, double aValue, bool aAddUnitSymbol, EDA_DATA_TYPE aType)
Function StringFromValue returns the string from aValue according to units (inch, mm ....
Definition: base_units.cpp:220
Class PANEL_SETUP_TRACKS_AND_VIAS_BASE.
void OnRemoveTrackWidthsClick(wxCommandEvent &event) override
BOARD * GetBoard() const
const BITMAP_OPAQUE small_plus_xpm[1]
Definition: small_plus.cpp:20
void AppendDiffPairs(const int aWidth, const int aGap, const int aViaGap)
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.