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 <fctsys.h>
26 #include <class_drawpanel.h>
27 #include <base_units.h>
28 #include <pcb_edit_frame.h>
29 #include <board_design_settings.h>
30 #include <bitmaps.h>
31 #include <widgets/wx_grid.h>
32 
34 
35 
37 {
39 };
40 
42 {
45 };
46 
48 {
52 };
53 
54 
56  PAGED_DIALOG* aParent, PCB_EDIT_FRAME* aFrame,
57  PANEL_SETUP_FEATURE_CONSTRAINTS* aConstraintsPanel ) :
58  PANEL_SETUP_TRACKS_AND_VIAS_BASE( aParent->GetTreebook() )
59 {
60  m_Parent = aParent;
61  m_Frame = aFrame;
62  m_Pcb = m_Frame->GetBoard();
64  m_ConstraintsPanel = aConstraintsPanel;
65 
66  m_trackWidthsAddButton->SetBitmap( KiBitmap( small_plus_xpm ) );
67  m_trackWidthsRemoveButton->SetBitmap( KiBitmap( trash_xpm ) );
68  m_viaSizesAddButton->SetBitmap( KiBitmap( small_plus_xpm ) );
69  m_viaSizesRemoveButton->SetBitmap( KiBitmap( trash_xpm ) );
70  m_diffPairsAddButton->SetBitmap( KiBitmap( small_plus_xpm ) );
71  m_diffPairsRemoveButton->SetBitmap( KiBitmap( trash_xpm ) );
72 
73  // Membership combobox editors require a bit more room, so increase the row size of
74  // all our grids for consistency
75  m_trackWidthsGrid->SetDefaultRowSize( m_trackWidthsGrid->GetDefaultRowSize() + 4 );
76  m_viaSizesGrid->SetDefaultRowSize( m_viaSizesGrid->GetDefaultRowSize() + 4 );
77  m_diffPairsGrid->SetDefaultRowSize( m_diffPairsGrid->GetDefaultRowSize() + 4 );
78 
79  m_trackWidthsGrid->PushEventHandler( new GRID_TRICKS( m_trackWidthsGrid ) );
80  m_viaSizesGrid->PushEventHandler( new GRID_TRICKS( m_viaSizesGrid ) );
81  m_diffPairsGrid->PushEventHandler( new GRID_TRICKS( m_diffPairsGrid ) );
82 
83  m_trackWidthsGrid->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
84  m_viaSizesGrid->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
85  m_diffPairsGrid->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
86 }
87 
89 {
90  // Delete the GRID_TRICKS.
91  m_trackWidthsGrid->PopEventHandler( true );
92  m_viaSizesGrid->PopEventHandler( true );
93  m_diffPairsGrid->PopEventHandler( true );
94 }
95 
97 {
98  if( m_trackWidthsGrid->GetNumberRows() > 0 )
99  m_trackWidthsGrid->DeleteRows( 0, m_trackWidthsGrid->GetNumberRows() );
100 
101  if( m_viaSizesGrid->GetNumberRows() > 0 )
102  m_viaSizesGrid->DeleteRows( 0, m_viaSizesGrid->GetNumberRows() );
103 
104  if( m_diffPairsGrid->GetNumberRows() > 0 )
105  m_diffPairsGrid->DeleteRows( 0, m_diffPairsGrid->GetNumberRows() );
106 
107  // Skip the first item, which is the current netclass value
108  for( unsigned ii = 1; ii < m_BrdSettings->m_TrackWidthList.size(); ii++ )
109  {
111  }
112 
113  // Skip the first item, which is the current netclass value
114  for( unsigned ii = 1; ii < m_BrdSettings->m_ViasDimensionsList.size(); ii++ )
115  {
117  m_BrdSettings->m_ViasDimensionsList[ii].m_Drill );
118  }
119 
120  // Skip the first item, which is the current netclass value
121  for( unsigned ii = 1; ii < m_BrdSettings->m_DiffPairDimensionsList.size(); ii++ )
122  {
125  m_BrdSettings->m_DiffPairDimensionsList[ii].m_ViaGap );
126  }
127 
128  return true;
129 }
130 
131 
133 {
134  if( !validateData() )
135  return false;
136 
137  wxString msg;
138  std::vector<int> trackWidths;
139  std::vector<VIA_DIMENSION> vias;
140  std::vector<DIFF_PAIR_DIMENSION> diffPairs;
141 
145  {
146  return false;
147  }
148 
149  for( int row = 0; row < m_trackWidthsGrid->GetNumberRows(); ++row )
150  {
151  msg = m_trackWidthsGrid->GetCellValue( row, TR_WIDTH_COL );
152 
153  if( !msg.IsEmpty() )
154  trackWidths.push_back( ValueFromString( m_Frame->GetUserUnits(), msg, true ) );
155  }
156 
157  for( int row = 0; row < m_viaSizesGrid->GetNumberRows(); ++row )
158  {
159  msg = m_viaSizesGrid->GetCellValue( row, VIA_SIZE_COL );
160 
161  if( !msg.IsEmpty() )
162  {
163  VIA_DIMENSION via_dim;
164  via_dim.m_Diameter = ValueFromString( m_Frame->GetUserUnits(), msg, true );
165 
166  msg = m_viaSizesGrid->GetCellValue( row, VIA_DRILL_COL );
167 
168  if( !msg.IsEmpty() )
169  via_dim.m_Drill = ValueFromString( m_Frame->GetUserUnits(), msg, true );
170 
171  vias.push_back( via_dim );
172  }
173  }
174 
175  for( int row = 0; row < m_diffPairsGrid->GetNumberRows(); ++row )
176  {
177  msg = m_diffPairsGrid->GetCellValue( row, DP_WIDTH_COL );
178 
179  if( !msg.IsEmpty() )
180  {
181  DIFF_PAIR_DIMENSION diffPair_dim;
182  diffPair_dim.m_Width = ValueFromString( m_Frame->GetUserUnits(), msg, true );
183 
184  msg = m_diffPairsGrid->GetCellValue( row, DP_GAP_COL );
185  diffPair_dim.m_Gap = ValueFromString( m_Frame->GetUserUnits(), msg, true );
186 
187  msg = m_diffPairsGrid->GetCellValue( row, DP_VIA_GAP_COL );
188 
189  if( !msg.IsEmpty() )
190  diffPair_dim.m_ViaGap = ValueFromString( m_Frame->GetUserUnits(), msg, true );
191 
192  diffPairs.push_back( diffPair_dim );
193  }
194  }
195 
196  // Sort lists by increasing value
197  sort( trackWidths.begin(), trackWidths.end() );
198  sort( vias.begin(), vias.end() );
199  sort( diffPairs.begin(), diffPairs.end() );
200 
201  trackWidths.insert( trackWidths.begin(), m_BrdSettings->m_TrackWidthList[ 0 ] );
202  m_BrdSettings->m_TrackWidthList = trackWidths;
203 
204  vias.insert( vias.begin(), m_BrdSettings->m_ViasDimensionsList[ 0 ] );
206 
207  diffPairs.insert( diffPairs.begin(), m_BrdSettings->m_DiffPairDimensionsList[ 0 ] );
209 
210  return true;
211 }
212 
213 
215 {
219  {
220  return false;
221  }
222 
223  wxString msg;
224  int minViaDia = m_ConstraintsPanel->m_viaMinSize.GetValue();
225  int minViaDrill = m_ConstraintsPanel->m_viaMinDrill.GetValue();
226  int minTrackWidth = m_ConstraintsPanel->m_trackMinWidth.GetValue();
227 
228  // Test tracks
229  for( int row = 0; row < m_trackWidthsGrid->GetNumberRows(); ++row )
230  {
231  wxString tvalue = m_trackWidthsGrid->GetCellValue( row, TR_WIDTH_COL );
232 
233  if( tvalue.IsEmpty() )
234  continue;
235 
236  if( ValueFromString( m_Frame->GetUserUnits(), tvalue ) < minTrackWidth )
237  {
238  msg.Printf( _( "Track width less than minimum track width (%s)." ),
239  StringFromValue( m_Frame->GetUserUnits(), minTrackWidth, true, true ) );
240  m_Parent->SetError( msg, this, m_trackWidthsGrid, row, TR_WIDTH_COL );
241  return false;
242  }
243  }
244 
245  // Test vias
246  for( int row = 0; row < m_viaSizesGrid->GetNumberRows(); ++row )
247  {
248  wxString viaDia = m_viaSizesGrid->GetCellValue( row, VIA_SIZE_COL );
249 
250  if( viaDia.IsEmpty() )
251  continue;
252 
253  if( ValueFromString( m_Frame->GetUserUnits(), viaDia ) < minViaDia )
254  {
255  msg.Printf( _( "Via diameter less than minimum via diameter (%s)." ),
256  StringFromValue( m_Frame->GetUserUnits(), minViaDia, true, true ) );
257  m_Parent->SetError( msg, this, m_viaSizesGrid, row, VIA_SIZE_COL );
258  return false;
259  }
260 
261  wxString viaDrill = m_viaSizesGrid->GetCellValue( row, VIA_DRILL_COL );
262 
263  if( viaDrill.IsEmpty() )
264  {
265  msg = _( "No via drill defined." );
266  m_Parent->SetError( msg, this, m_viaSizesGrid, row, VIA_DRILL_COL );
267  return false;
268  }
269 
270  if( ValueFromString( m_Frame->GetUserUnits(), viaDrill ) < minViaDrill )
271  {
272  msg.Printf( _( "Via drill less than minimum via drill (%s)." ),
273  StringFromValue( m_Frame->GetUserUnits(), minViaDrill, true, true ) );
274  m_Parent->SetError( msg, this, m_viaSizesGrid, row, VIA_DRILL_COL );
275  return false;
276  }
277 
278  if( ValueFromString( m_Frame->GetUserUnits(), viaDrill )
279  >= ValueFromString( m_Frame->GetUserUnits(), viaDia ) )
280  {
281  msg = _( "Via drill larger than via diameter." );
282  m_Parent->SetError( msg, this, m_viaSizesGrid, row, VIA_DRILL_COL );
283  return false;
284  }
285  }
286 
287  // Test diff pairs
288  for( int row = 0; row < m_diffPairsGrid->GetNumberRows(); ++row )
289  {
290  wxString tvalue = m_diffPairsGrid->GetCellValue( row, 0 );
291 
292  if( tvalue.IsEmpty() )
293  continue;
294 
295  if( ValueFromString( m_Frame->GetUserUnits(), tvalue ) < minTrackWidth )
296  {
297  msg.Printf( _( "Differential pair track width less than minimum track width (%s)." ),
298  StringFromValue( m_Frame->GetUserUnits(), minTrackWidth, true, true ) );
299  m_Parent->SetError( msg, this, m_diffPairsGrid, row, 0 );
300  return false;
301  }
302 
303  wxString gap = m_diffPairsGrid->GetCellValue( row, 1 );
304 
305  if( gap.IsEmpty() )
306  {
307  msg = _( "No differential pair gap defined." );
308  m_Parent->SetError( msg, this, m_diffPairsGrid, row, 1 );
309  return false;
310  }
311 
312  if( ValueFromString( m_Frame->GetUserUnits(), gap ) < 0 )
313  {
314  msg.Printf( _( "Differential pair gap cannot be negative." ) );
315  m_Parent->SetError( msg, this, m_diffPairsGrid, row, 1 );
316  return false;
317  }
318 
319  wxString viaGap = m_diffPairsGrid->GetCellValue( row, 2 );
320 
321  if( viaGap.IsEmpty() )
322  continue;
323 
324  if( ValueFromString( m_Frame->GetUserUnits(), viaGap ) < 0 )
325  {
326  msg.Printf( _( "Differential pair via gap cannot be negative." ) );
327  m_Parent->SetError( msg, this, m_diffPairsGrid, row, 2 );
328  return false;
329  }
330  }
331 
332  return true;
333 }
334 
335 
337 {
341 
342  // Note: do not change the board, as we need to get the current nets from it for
343  // netclass memberships. All the netclass definitions and dimension lists are in
344  // the BOARD_DESIGN_SETTINGS.
345 
346  BOARD_DESIGN_SETTINGS* savedSettings = m_BrdSettings;
347 
348  m_BrdSettings = &aBoard->GetDesignSettings();
350 
351  m_BrdSettings = savedSettings;
352 }
353 
355 {
356  int i = m_trackWidthsGrid->GetNumberRows();
357 
358  m_trackWidthsGrid->AppendRows( 1 );
359 
360  wxString val = StringFromValue( m_Frame->GetUserUnits(), aWidth, true, true );
361  m_trackWidthsGrid->SetCellValue( i, TR_WIDTH_COL, val );
362 }
363 
364 void PANEL_SETUP_TRACKS_AND_VIAS::AppendViaSize( const int aSize, const int aDrill )
365 {
366  int i = m_viaSizesGrid->GetNumberRows();
367 
368  m_viaSizesGrid->AppendRows( 1 );
369 
370  wxString val = StringFromValue( m_Frame->GetUserUnits(), aSize, true, true );
371  m_viaSizesGrid->SetCellValue( i, VIA_SIZE_COL, val );
372 
373  if( aDrill > 0 )
374  {
375  val = StringFromValue( m_Frame->GetUserUnits(), aDrill, true, true );
376  m_viaSizesGrid->SetCellValue( i, VIA_DRILL_COL, val );
377  }
378 }
379 
380 void PANEL_SETUP_TRACKS_AND_VIAS::AppendDiffPairs( const int aWidth, const int aGap,
381  const int aViaGap )
382 {
383  int i = m_diffPairsGrid->GetNumberRows();
384 
385  m_diffPairsGrid->AppendRows( 1 );
386 
387  wxString val = StringFromValue( m_Frame->GetUserUnits(), aWidth, true, true );
388  m_diffPairsGrid->SetCellValue( i, DP_WIDTH_COL, val );
389 
390  if( aGap > 0 )
391  {
392  val = StringFromValue( m_Frame->GetUserUnits(), aGap, true, true );
393  m_diffPairsGrid->SetCellValue( i, DP_GAP_COL, val );
394  }
395 
396  if( aViaGap > 0 )
397  {
398  val = StringFromValue( m_Frame->GetUserUnits(), aViaGap, true, true );
399  m_diffPairsGrid->SetCellValue( i, DP_VIA_GAP_COL, val );
400  }
401 }
402 
404 {
405  AppendTrackWidth( 0 );
406 
407  m_trackWidthsGrid->MakeCellVisible( m_trackWidthsGrid->GetNumberRows() - 1, TR_WIDTH_COL );
408  m_trackWidthsGrid->SetGridCursor( m_trackWidthsGrid->GetNumberRows() - 1, TR_WIDTH_COL );
409 
410  m_trackWidthsGrid->EnableCellEditControl( true );
411  m_trackWidthsGrid->ShowCellEditControl();
412 }
413 
415 {
416  int curRow = m_trackWidthsGrid->GetGridCursorRow();
417 
418  if( curRow < 0 || m_trackWidthsGrid->GetNumberRows() <= curRow )
419  return;
420 
421  m_trackWidthsGrid->DeleteRows( curRow, 1 );
422 
423  curRow = std::max( 0, curRow - 1 );
424  m_trackWidthsGrid->MakeCellVisible( curRow, m_trackWidthsGrid->GetGridCursorCol() );
425  m_trackWidthsGrid->SetGridCursor( curRow, m_trackWidthsGrid->GetGridCursorCol() );
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 
440 {
441  int curRow = m_viaSizesGrid->GetGridCursorRow();
442 
443  if( curRow < 0 || m_viaSizesGrid->GetNumberRows() <= curRow )
444  return;
445 
446  m_viaSizesGrid->DeleteRows( curRow, 1 );
447 
448  curRow = std::max( 0, curRow - 1 );
449  m_viaSizesGrid->MakeCellVisible( curRow, m_viaSizesGrid->GetGridCursorCol() );
450  m_viaSizesGrid->SetGridCursor( curRow, m_viaSizesGrid->GetGridCursorCol() );
451 }
452 
454 {
455  AppendDiffPairs( 0, 0, 0 );
456 
457  m_diffPairsGrid->MakeCellVisible( m_diffPairsGrid->GetNumberRows() - 1, DP_WIDTH_COL );
458  m_diffPairsGrid->SetGridCursor( m_diffPairsGrid->GetNumberRows() - 1, DP_WIDTH_COL );
459 
460  m_diffPairsGrid->EnableCellEditControl( true );
461  m_diffPairsGrid->ShowCellEditControl();
462 }
463 
465 {
466  int curRow = m_diffPairsGrid->GetGridCursorRow();
467 
468  if( curRow < 0 || m_diffPairsGrid->GetNumberRows() <= curRow )
469  return;
470 
471  m_diffPairsGrid->DeleteRows( curRow, 1 );
472 
473  curRow = std::max( 0, curRow - 1 );
474  m_diffPairsGrid->MakeCellVisible( curRow, m_diffPairsGrid->GetGridCursorCol() );
475  m_diffPairsGrid->SetGridCursor( curRow, m_diffPairsGrid->GetGridCursorCol() );
476 }
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
Class GRID_TRICKS is used to add cut, copy, and paste to an otherwise unmodied wxGrid instance...
Definition: grid_tricks.h:51
BOARD * GetBoard() const
int ValueFromString(EDA_UNITS_T aUnits, const wxString &aTextValue, bool aUseMils)
Function ValueFromString converts aTextValue in aUnits to internal units used by the application...
Definition: base_units.cpp:409
Struct DIFF_PAIR_DIMENSION is a small helper container to handle a stock of specific differential pai...
virtual int GetValue()
Function GetValue Returns the current value in Internal Units.
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:79
EDA_UNITS_T GetUserUnits() const override
Return the user units currently in use.
Definition: draw_frame.h:284
void OnRemoveDiffPairsClick(wxCommandEvent &event) override
void OnAddViaSizesClick(wxCommandEvent &event) override
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:538
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:156
void SetError(const wxString &aMessage, wxWindow *aPage, wxObject *aCtrl, int aRow=-1, int aCol=-1)
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)
#define max(a, b)
Definition: auxiliary.h:86
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:170
void OnAddTrackWidthsClick(wxCommandEvent &event) override
size_t i
Definition: json11.cpp:597
Class PCB_EDIT_FRAME is the main frame for Pcbnew.
std::vector< VIA_DIMENSION > m_ViasDimensionsList
wxString StringFromValue(EDA_UNITS_T aUnits, int aValue, bool aAddUnitSymbol, bool aUseMils)
Function StringFromValue returns the string from aValue according to units (inch, mm ...
Definition: base_units.cpp:210
Class PANEL_SETUP_TRACKS_AND_VIAS_BASE.
void OnRemoveTrackWidthsClick(wxCommandEvent &event) override
void AppendDiffPairs(const int aWidth, const int aGap, const int aViaGap)
Class BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.