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-2021 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 <wx/treebook.h>
31 #include <grid_tricks.h>
32 
34 
35 
37 {
39 };
40 
42 {
45 };
46 
48 {
52 };
53 
54 
56  PCB_EDIT_FRAME* aFrame,
57  PANEL_SETUP_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 
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  // Ensure width of columns is enough to enter any reasonable value
88  WX_GRID* grid_list[] = { m_trackWidthsGrid, m_viaSizesGrid, m_diffPairsGrid, nullptr };
89  int min_linesize = m_trackWidthsGrid->GetTextExtent( "000.000000 mm " ).x;
90 
91  for( int ii = 0; grid_list[ii]; ii++ )
92  {
93  WX_GRID* curr_grid = grid_list[ii];
94 
95  for( int col = 0; col < curr_grid->GetNumberCols(); col++ )
96  {
97  int min_w = curr_grid->GetVisibleWidth( col, true, true, true );
98  int best_w = std::max( min_linesize, min_w );
99  curr_grid->SetColMinimalWidth( col, best_w );
100  curr_grid->SetColSize( col,best_w );
101  }
102  }
103 }
104 
106 {
107  // Delete the GRID_TRICKS.
108  m_trackWidthsGrid->PopEventHandler( true );
109  m_viaSizesGrid->PopEventHandler( true );
110  m_diffPairsGrid->PopEventHandler( true );
111 }
112 
114 {
118 
119  // Skip the first item, which is the current netclass value
120  for( unsigned ii = 1; ii < m_BrdSettings->m_TrackWidthList.size(); ii++ )
121  {
123  }
124 
125  // Skip the first item, which is the current netclass value
126  for( unsigned ii = 1; ii < m_BrdSettings->m_ViasDimensionsList.size(); ii++ )
127  {
129  m_BrdSettings->m_ViasDimensionsList[ii].m_Drill );
130  }
131 
132  // Skip the first item, which is the current netclass value
133  for( unsigned ii = 1; ii < m_BrdSettings->m_DiffPairDimensionsList.size(); ii++ )
134  {
137  m_BrdSettings->m_DiffPairDimensionsList[ii].m_ViaGap );
138  }
139 
140  return true;
141 }
142 
143 
145 {
149  {
150  return false;
151  }
152 
153  wxString msg;
154  std::vector<int> trackWidths;
155  std::vector<VIA_DIMENSION> vias;
156  std::vector<DIFF_PAIR_DIMENSION> diffPairs;
157 
161  {
162  return false;
163  }
164 
165  // Test ONLY for malformed data. Design rules and constraints are the business of DRC.
166 
167  for( int row = 0; row < m_trackWidthsGrid->GetNumberRows(); ++row )
168  {
169  msg = m_trackWidthsGrid->GetCellValue( row, TR_WIDTH_COL );
170 
171  if( !msg.IsEmpty() )
172  trackWidths.push_back( ValueFromString( m_Frame->GetUserUnits(), msg ) );
173  }
174 
175  for( int row = 0; row < m_viaSizesGrid->GetNumberRows(); ++row )
176  {
177  msg = m_viaSizesGrid->GetCellValue( row, VIA_SIZE_COL );
178 
179  if( !msg.IsEmpty() )
180  {
181  VIA_DIMENSION via_dim;
182  via_dim.m_Diameter = ValueFromString( m_Frame->GetUserUnits(), msg );
183 
184  msg = m_viaSizesGrid->GetCellValue( row, VIA_DRILL_COL );
185 
186  if( !msg.IsEmpty() )
187  via_dim.m_Drill = ValueFromString( m_Frame->GetUserUnits(), msg );
188 
189  vias.push_back( via_dim );
190  }
191  }
192 
193  for( int row = 0; row < m_diffPairsGrid->GetNumberRows(); ++row )
194  {
195  msg = m_diffPairsGrid->GetCellValue( row, DP_WIDTH_COL );
196 
197  if( !msg.IsEmpty() )
198  {
199  DIFF_PAIR_DIMENSION diffPair_dim;
200  diffPair_dim.m_Width = ValueFromString( m_Frame->GetUserUnits(), msg );
201 
202  msg = m_diffPairsGrid->GetCellValue( row, DP_GAP_COL );
203  diffPair_dim.m_Gap = ValueFromString( m_Frame->GetUserUnits(), msg );
204 
205  msg = m_diffPairsGrid->GetCellValue( row, DP_VIA_GAP_COL );
206 
207  if( !msg.IsEmpty() )
208  diffPair_dim.m_ViaGap = ValueFromString( m_Frame->GetUserUnits(), msg );
209 
210  diffPairs.push_back( diffPair_dim );
211  }
212  }
213 
214  // Sort lists by increasing value
215  sort( trackWidths.begin(), trackWidths.end() );
216  sort( vias.begin(), vias.end() );
217  sort( diffPairs.begin(), diffPairs.end() );
218 
219  // These are all stored in project file, not board, so no need for OnModify()
220 
221  trackWidths.insert( trackWidths.begin(), 0 ); // dummy value for "use netclass"
222  m_BrdSettings->m_TrackWidthList = trackWidths;
223 
224  vias.insert( vias.begin(), { 0, 0 } ); // dummy value for "use netclass"
226 
227  diffPairs.insert( diffPairs.begin(), { 0, 0, 0 } ); // dummy value for "use netclass"
229 
230  return true;
231 }
232 
233 
235 {
239  {
240  return false;
241  }
242 
243  wxString msg;
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  wxString viaDrill = m_viaSizesGrid->GetCellValue( row, VIA_DRILL_COL );
250 
251  if( !viaDia.IsEmpty() && viaDrill.IsEmpty() )
252  {
253  msg = _( "No via hole size defined." );
254  m_Parent->SetError( msg, this, m_viaSizesGrid, row, VIA_DRILL_COL );
255  return false;
256  }
257 
258  }
259 
260  // Test diff pairs
261  for( int row = 0; row < m_diffPairsGrid->GetNumberRows(); ++row )
262  {
263  wxString dpWidth = m_diffPairsGrid->GetCellValue( row, 0 );
264  wxString dpGap = m_diffPairsGrid->GetCellValue( row, 1 );
265 
266  if( !dpWidth.IsEmpty() && dpGap.IsEmpty() )
267  {
268  msg = _( "No differential pair gap defined." );
269  m_Parent->SetError( msg, this, m_diffPairsGrid, row, 1 );
270  return false;
271  }
272  }
273 
274  return true;
275 }
276 
277 
279 {
280  int i = m_trackWidthsGrid->GetNumberRows();
281 
282  m_trackWidthsGrid->AppendRows( 1 );
283 
284  wxString val = StringFromValue( m_Frame->GetUserUnits(), aWidth );
285  m_trackWidthsGrid->SetCellValue( i, TR_WIDTH_COL, val );
286 }
287 
288 
289 void PANEL_SETUP_TRACKS_AND_VIAS::AppendViaSize( const int aSize, const int aDrill )
290 {
291  int i = m_viaSizesGrid->GetNumberRows();
292 
293  m_viaSizesGrid->AppendRows( 1 );
294 
295  wxString val = StringFromValue( m_Frame->GetUserUnits(), aSize );
296  m_viaSizesGrid->SetCellValue( i, VIA_SIZE_COL, val );
297 
298  if( aDrill > 0 )
299  {
300  val = StringFromValue( m_Frame->GetUserUnits(), aDrill );
301  m_viaSizesGrid->SetCellValue( i, VIA_DRILL_COL, val );
302  }
303 }
304 
305 
306 void PANEL_SETUP_TRACKS_AND_VIAS::AppendDiffPairs( const int aWidth, const int aGap,
307  const int aViaGap )
308 {
309  int i = m_diffPairsGrid->GetNumberRows();
310 
311  m_diffPairsGrid->AppendRows( 1 );
312 
313  wxString val = StringFromValue( m_Frame->GetUserUnits(), aWidth );
314  m_diffPairsGrid->SetCellValue( i, DP_WIDTH_COL, val );
315 
316  if( aGap > 0 )
317  {
318  val = StringFromValue( m_Frame->GetUserUnits(), aGap );
319  m_diffPairsGrid->SetCellValue( i, DP_GAP_COL, val );
320  }
321 
322  if( aViaGap > 0 )
323  {
324  val = StringFromValue( m_Frame->GetUserUnits(), aViaGap );
325  m_diffPairsGrid->SetCellValue( i, DP_VIA_GAP_COL, val );
326  }
327 }
328 
330 {
331  AppendTrackWidth( 0 );
332 
333  m_trackWidthsGrid->MakeCellVisible( m_trackWidthsGrid->GetNumberRows() - 1, TR_WIDTH_COL );
334  m_trackWidthsGrid->SetGridCursor( m_trackWidthsGrid->GetNumberRows() - 1, TR_WIDTH_COL );
335 
336  m_trackWidthsGrid->EnableCellEditControl( true );
337  m_trackWidthsGrid->ShowCellEditControl();
338 }
339 
340 
342 {
343  int curRow = m_trackWidthsGrid->GetGridCursorRow();
344 
345  if( curRow < 0 || m_trackWidthsGrid->GetNumberRows() <= curRow )
346  return;
347 
348  m_trackWidthsGrid->DeleteRows( curRow, 1 );
349 
350  curRow = std::max( 0, curRow - 1 );
351  m_trackWidthsGrid->MakeCellVisible( curRow, m_trackWidthsGrid->GetGridCursorCol() );
352  m_trackWidthsGrid->SetGridCursor( curRow, m_trackWidthsGrid->GetGridCursorCol() );
353 }
354 
355 
357 {
358  AppendViaSize( 0, 0 );
359 
360  m_viaSizesGrid->MakeCellVisible( m_viaSizesGrid->GetNumberRows() - 1, VIA_SIZE_COL );
361  m_viaSizesGrid->SetGridCursor( m_viaSizesGrid->GetNumberRows() - 1, VIA_SIZE_COL );
362 
363  m_viaSizesGrid->EnableCellEditControl( true );
364  m_viaSizesGrid->ShowCellEditControl();
365 }
366 
367 
369 {
370  int curRow = m_viaSizesGrid->GetGridCursorRow();
371 
372  if( curRow < 0 || m_viaSizesGrid->GetNumberRows() <= curRow )
373  return;
374 
375  m_viaSizesGrid->DeleteRows( curRow, 1 );
376 
377  curRow = std::max( 0, curRow - 1 );
378  m_viaSizesGrid->MakeCellVisible( curRow, m_viaSizesGrid->GetGridCursorCol() );
379  m_viaSizesGrid->SetGridCursor( curRow, m_viaSizesGrid->GetGridCursorCol() );
380 }
381 
382 
384 {
385  AppendDiffPairs( 0, 0, 0 );
386 
387  m_diffPairsGrid->MakeCellVisible( m_diffPairsGrid->GetNumberRows() - 1, DP_WIDTH_COL );
388  m_diffPairsGrid->SetGridCursor( m_diffPairsGrid->GetNumberRows() - 1, DP_WIDTH_COL );
389 
390  m_diffPairsGrid->EnableCellEditControl( true );
391  m_diffPairsGrid->ShowCellEditControl();
392 }
393 
394 
396 {
397  int curRow = m_diffPairsGrid->GetGridCursorRow();
398 
399  if( curRow < 0 || m_diffPairsGrid->GetNumberRows() <= curRow )
400  return;
401 
402  m_diffPairsGrid->DeleteRows( curRow, 1 );
403 
404  curRow = std::max( 0, curRow - 1 );
405  m_diffPairsGrid->MakeCellVisible( curRow, m_diffPairsGrid->GetGridCursorCol() );
406  m_diffPairsGrid->SetGridCursor( curRow, m_diffPairsGrid->GetGridCursorCol() );
407 }
408 
409 
411 {
415 
416  // Note: do not change the board, as we need to get the current nets from it for
417  // netclass memberships. All the netclass definitions and dimension lists are in
418  // the BOARD_DESIGN_SETTINGS.
419 
420  BOARD_DESIGN_SETTINGS* savedSettings = m_BrdSettings;
421 
422  m_BrdSettings = &aBoard->GetDesignSettings();
424 
425  m_BrdSettings = savedSettings;
426 }
427 
Container to handle a stock of specific vias each with unique diameter and drill sizes in the BOARD c...
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
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition: grid_tricks.h:55
void SetError(const wxString &aMessage, const wxString &aPageName, int aCtrlId, int aRow=-1, int aCol=-1)
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:589
Container to handle a stock of specific differential pairs each with unique track width,...
int GetVisibleWidth(int aCol, bool aHeader=true, bool aContents=false, bool aKeep=true)
Calculates the specified column based on the actual size of the text on screen.
Definition: wx_grid.cpp:246
void OnAddDiffPairsClick(wxCommandEvent &event) override
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:416
PANEL_SETUP_TRACKS_AND_VIAS(PAGED_DIALOG *aParent, PCB_EDIT_FRAME *aFrame, PANEL_SETUP_CONSTRAINTS *aConstraintsPanel)
void OnRemoveDiffPairsClick(wxCommandEvent &event) override
void OnAddViaSizesClick(wxCommandEvent &event) override
#define _(s)
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:190
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
void AppendViaSize(const int aSize, const int aDrill)
PANEL_SETUP_CONSTRAINTS * m_ConstraintsPanel
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
void OnAddTrackWidthsClick(wxCommandEvent &event) override
The main frame for Pcbnew.
std::vector< VIA_DIMENSION > m_ViasDimensionsList
void ClearRows()
wxWidgets recently added an ASSERT which fires if the position is greater than or equal to the number...
Definition: wx_grid.h:106
wxString StringFromValue(EDA_UNITS aUnits, double aValue, bool aAddUnitSymbol, EDA_DATA_TYPE aType)
Convert a value to a string using double notation.
Definition: base_units.cpp:204
Class PANEL_SETUP_TRACKS_AND_VIAS_BASE.
void OnRemoveTrackWidthsClick(wxCommandEvent &event) override
BOARD * GetBoard() const
void AppendDiffPairs(const int aWidth, const int aGap, const int aViaGap)
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
Container for design settings for a BOARD object.