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-2022 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 <pcb_edit_frame.h>
27#include <bitmaps.h>
28#include <widgets/wx_grid.h>
30#include <wx/treebook.h>
31#include <grid_tricks.h>
32
34
35
37{
38 TR_WIDTH_COL = 0
39};
40
42{
45};
46
48{
52};
53
54
56 PCB_EDIT_FRAME* aFrame ) :
57 PANEL_SETUP_TRACKS_AND_VIAS_BASE( aParent->GetTreebook() )
58{
59 m_Parent = aParent;
60 m_Frame = aFrame;
63
73
74 // Membership combobox editors require a bit more room, so increase the row size of
75 // all our grids for consistency
76 m_trackWidthsGrid->SetDefaultRowSize( m_trackWidthsGrid->GetDefaultRowSize() + 4 );
77 m_viaSizesGrid->SetDefaultRowSize( m_viaSizesGrid->GetDefaultRowSize() + 4 );
78 m_diffPairsGrid->SetDefaultRowSize( m_diffPairsGrid->GetDefaultRowSize() + 4 );
79
80 m_trackWidthsGrid->PushEventHandler( new GRID_TRICKS( m_trackWidthsGrid,
81 [this]( wxCommandEvent& aEvent )
82 {
83 OnAddTrackWidthsClick( aEvent );
84 } ) );
85 m_viaSizesGrid->PushEventHandler( new GRID_TRICKS( m_viaSizesGrid,
86 [this]( wxCommandEvent& aEvent )
87 {
88 OnAddViaSizesClick( aEvent );
89 } ) );
90 m_diffPairsGrid->PushEventHandler( new GRID_TRICKS( m_diffPairsGrid,
91 [this]( wxCommandEvent& aEvent )
92 {
93 OnAddDiffPairsClick( aEvent );
94 } ) );
95
96 m_trackWidthsGrid->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
97 m_viaSizesGrid->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
98 m_diffPairsGrid->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
99
103
105 m_viaSizesGrid->SetAutoEvalCols( { 0, 1 } );
106 m_diffPairsGrid->SetAutoEvalCols( { 0, 1, 2 } );
107
108 // Ensure width of columns is enough to enter any reasonable value
109 WX_GRID* grid_list[] = { m_trackWidthsGrid, m_viaSizesGrid, m_diffPairsGrid, nullptr };
110 int min_linesize = m_trackWidthsGrid->GetTextExtent( wxT( "000.000000 mm " ) ).x;
111
112 for( int ii = 0; grid_list[ii]; ii++ )
113 {
114 WX_GRID* curr_grid = grid_list[ii];
115
116 for( int col = 0; col < curr_grid->GetNumberCols(); col++ )
117 {
118 int min_w = curr_grid->GetVisibleWidth( col, true, true, true );
119 int best_w = std::max( min_linesize, min_w );
120 curr_grid->SetColMinimalWidth( col, best_w );
121 curr_grid->SetColSize( col,best_w );
122 }
123 }
124
125 m_Frame->Bind( UNITS_CHANGED, &PANEL_SETUP_TRACKS_AND_VIAS::onUnitsChanged, this );
126}
127
128
130{
131 // Delete the GRID_TRICKS.
132 m_trackWidthsGrid->PopEventHandler( true );
133 m_viaSizesGrid->PopEventHandler( true );
134 m_diffPairsGrid->PopEventHandler( true );
135
136 m_Frame->Unbind( UNITS_CHANGED, &PANEL_SETUP_TRACKS_AND_VIAS::onUnitsChanged, this );
137}
138
139
141{
142 std::vector<int> trackWidths;
143 wxString msg;
144
145 wxGridUpdateLocker lock( m_trackWidthsGrid );
146
147 for( int row = 0; row < m_trackWidthsGrid->GetNumberRows(); ++row )
148 {
149 msg = m_trackWidthsGrid->GetCellValue( row, TR_WIDTH_COL );
150
151 if( !msg.IsEmpty() )
152 trackWidths.push_back( m_Frame->ValueFromString( msg ) );
153 }
154
155 std::sort( trackWidths.begin(), trackWidths.end() );
156 m_trackWidthsGrid->DeleteRows(0, m_trackWidthsGrid->GetNumberRows(), false);
157
158 for( int width : trackWidths )
159 AppendTrackWidth( width );
160}
161
162
164{
165 std::vector<VIA_DIMENSION> vias;
166 wxString msg;
167
168 wxGridUpdateLocker lock( m_viaSizesGrid );
169
170 for( int row = 0; row < m_viaSizesGrid->GetNumberRows(); ++row )
171 {
172 msg = m_viaSizesGrid->GetCellValue( row, VIA_SIZE_COL );
173
174 if( !msg.IsEmpty() )
175 {
176 VIA_DIMENSION via_dim;
177 via_dim.m_Diameter = m_Frame->ValueFromString( msg );
178
179 msg = m_viaSizesGrid->GetCellValue( row, VIA_DRILL_COL );
180
181 if( !msg.IsEmpty() )
182 via_dim.m_Drill = m_Frame->ValueFromString( msg );
183
184 vias.push_back( via_dim );
185 }
186 }
187
188 std::sort( vias.begin(), vias.end() );
189 m_viaSizesGrid->DeleteRows(0, m_viaSizesGrid->GetNumberRows(), false );
190
191 for( const VIA_DIMENSION& via : vias )
192 AppendViaSize( via.m_Diameter, via.m_Drill );
193}
194
195
197{
198 wxString msg;
199 std::vector<DIFF_PAIR_DIMENSION> diffPairs;
200
201 wxGridUpdateLocker lock( m_diffPairsGrid );
202
203 for( int row = 0; row < m_diffPairsGrid->GetNumberRows(); ++row )
204 {
205 msg = m_diffPairsGrid->GetCellValue( row, DP_WIDTH_COL );
206
207 if( !msg.IsEmpty() )
208 {
209 DIFF_PAIR_DIMENSION diffPair_dim;
210 diffPair_dim.m_Width = m_Frame->ValueFromString( msg );
211
212 msg = m_diffPairsGrid->GetCellValue( row, DP_GAP_COL );
213 diffPair_dim.m_Gap = m_Frame->ValueFromString( msg );
214
215 msg = m_diffPairsGrid->GetCellValue( row, DP_VIA_GAP_COL );
216
217 if( !msg.IsEmpty() )
218 diffPair_dim.m_ViaGap = m_Frame->ValueFromString( msg );
219
220 diffPairs.push_back( diffPair_dim );
221 }
222 }
223
224 std::sort( diffPairs.begin(), diffPairs.end() );
225 m_diffPairsGrid->DeleteRows(0, m_diffPairsGrid->GetNumberRows(), false );
226
227 for( const DIFF_PAIR_DIMENSION& dp : diffPairs )
228 AppendDiffPairs( dp.m_Width, dp.m_Gap, dp.m_ViaGap );
229}
230
231
233{
234 BOARD_DESIGN_SETTINGS tempBDS( nullptr, "dummy" );
236
237 m_BrdSettings = &tempBDS; // No, address of stack var does not escape function
238
241
242 m_BrdSettings = saveBDS;
243
244 aEvent.Skip();
245}
246
247
249{
253
254 // Skip the first item, which is the current netclass value
255 for( unsigned ii = 1; ii < m_BrdSettings->m_TrackWidthList.size(); ii++ )
256 {
258 }
259
260 // Skip the first item, which is the current netclass value
261 for( unsigned ii = 1; ii < m_BrdSettings->m_ViasDimensionsList.size(); ii++ )
262 {
264 m_BrdSettings->m_ViasDimensionsList[ii].m_Drill );
265 }
266
267 // Skip the first item, which is the current netclass value
268 for( unsigned ii = 1; ii < m_BrdSettings->m_DiffPairDimensionsList.size(); ii++ )
269 {
273 }
274
275 return true;
276}
277
278
280{
284 {
285 return false;
286 }
287
288 wxString msg;
289 std::vector<int> trackWidths;
290 std::vector<VIA_DIMENSION> vias;
291 std::vector<DIFF_PAIR_DIMENSION> diffPairs;
292
293 // Test ONLY for malformed data. Design rules and constraints are the business of DRC.
294
295 for( int row = 0; row < m_trackWidthsGrid->GetNumberRows(); ++row )
296 {
297 if( !m_trackWidthsGrid->GetCellValue( row, TR_WIDTH_COL ).IsEmpty() )
298 trackWidths.push_back( m_trackWidthsGrid->GetUnitValue( row, TR_WIDTH_COL ) );
299 }
300
301 for( int row = 0; row < m_viaSizesGrid->GetNumberRows(); ++row )
302 {
303 if( !m_viaSizesGrid->GetCellValue( row, VIA_SIZE_COL ).IsEmpty() )
304 {
305 VIA_DIMENSION via_dim;
307
308 if( !m_viaSizesGrid->GetCellValue( row, VIA_DRILL_COL ).IsEmpty() )
310
311 vias.push_back( via_dim );
312 }
313 }
314
315 for( int row = 0; row < m_diffPairsGrid->GetNumberRows(); ++row )
316 {
317 if( !m_diffPairsGrid->GetCellValue( row, DP_WIDTH_COL ).IsEmpty() )
318 {
319 DIFF_PAIR_DIMENSION diffPair_dim;
320 diffPair_dim.m_Width = m_diffPairsGrid->GetUnitValue( row, DP_WIDTH_COL );
321
322 if( !m_diffPairsGrid->GetCellValue( row, DP_GAP_COL ).IsEmpty() )
323 diffPair_dim.m_Gap = m_diffPairsGrid->GetUnitValue( row, DP_GAP_COL );
324
325 if( !m_diffPairsGrid->GetCellValue( row, DP_VIA_GAP_COL ).IsEmpty() )
326 diffPair_dim.m_ViaGap = m_diffPairsGrid->GetUnitValue( row, DP_VIA_GAP_COL );
327
328 diffPairs.push_back( diffPair_dim );
329 }
330 }
331
332 // Sort lists by increasing value
333 sort( trackWidths.begin(), trackWidths.end() );
334 sort( vias.begin(), vias.end() );
335 sort( diffPairs.begin(), diffPairs.end() );
336
337 // These are all stored in project file, not board, so no need for OnModify()
338
339 trackWidths.insert( trackWidths.begin(), 0 ); // dummy value for "use netclass"
340 m_BrdSettings->m_TrackWidthList = trackWidths;
341
342 vias.insert( vias.begin(), { 0, 0 } ); // dummy value for "use netclass"
344
345 diffPairs.insert( diffPairs.begin(), { 0, 0, 0 } ); // dummy value for "use netclass"
347
348 return true;
349}
350
351
353{
357 {
358 return false;
359 }
360
361 wxString msg;
362
363 // Test vias
364 for( int row = 0; row < m_viaSizesGrid->GetNumberRows(); ++row )
365 {
366 wxString viaDia = m_viaSizesGrid->GetCellValue( row, VIA_SIZE_COL );
367 wxString viaDrill = m_viaSizesGrid->GetCellValue( row, VIA_DRILL_COL );
368
369 if( !viaDia.IsEmpty() && viaDrill.IsEmpty() )
370 {
371 msg = _( "No via hole size defined." );
372 m_Parent->SetError( msg, this, m_viaSizesGrid, row, VIA_DRILL_COL );
373 return false;
374 }
375 }
376
377 // Test diff pairs
378 for( int row = 0; row < m_diffPairsGrid->GetNumberRows(); ++row )
379 {
380 wxString dpWidth = m_diffPairsGrid->GetCellValue( row, 0 );
381 wxString dpGap = m_diffPairsGrid->GetCellValue( row, 1 );
382
383 if( !dpWidth.IsEmpty() && dpGap.IsEmpty() )
384 {
385 msg = _( "No differential pair gap defined." );
386 m_Parent->SetError( msg, this, m_diffPairsGrid, row, 1 );
387 return false;
388 }
389 }
390
391 return true;
392}
393
394
396{
397 int i = m_trackWidthsGrid->GetNumberRows();
398
399 m_trackWidthsGrid->AppendRows( 1 );
400
402}
403
404
406{
407 int i = m_viaSizesGrid->GetNumberRows();
408
409 m_viaSizesGrid->AppendRows( 1 );
410
412
413 if( aDrill > 0 )
415}
416
417
418void PANEL_SETUP_TRACKS_AND_VIAS::AppendDiffPairs( int aWidth, int aGap, int aViaGap )
419{
420 int i = m_diffPairsGrid->GetNumberRows();
421
422 m_diffPairsGrid->AppendRows( 1 );
423
425
426 if( aGap > 0 )
428
429 if( aViaGap > 0 )
431}
432
433
435{
436 wxArrayInt selectedRows = aGrid->GetSelectedRows();
437 int curRow = aGrid->GetGridCursorRow();
438
439 if( selectedRows.empty() && curRow >= 0 && curRow < aGrid->GetNumberRows() )
440 selectedRows.Add( curRow );
441
442 for( int ii = selectedRows.Count() - 1; ii >= 0; --ii )
443 {
444 int row = selectedRows.Item( ii );
445 aGrid->DeleteRows( row, 1 );
446 curRow = std::min( curRow, row );
447 }
448
449 curRow = std::max( 0, curRow - 1 );
450 aGrid->MakeCellVisible( curRow, aGrid->GetGridCursorCol() );
451 aGrid->SetGridCursor( curRow, aGrid->GetGridCursorCol() );
452}
453
454
456{
460 {
461 return;
462 }
463
464 AppendTrackWidth( 0 );
465
466 m_trackWidthsGrid->MakeCellVisible( m_trackWidthsGrid->GetNumberRows() - 1, TR_WIDTH_COL );
467 m_trackWidthsGrid->SetGridCursor( m_trackWidthsGrid->GetNumberRows() - 1, TR_WIDTH_COL );
468
469 m_trackWidthsGrid->EnableCellEditControl( true );
470 m_trackWidthsGrid->ShowCellEditControl();
471}
472
473
475{
479 {
480 return;
481 }
482
484}
485
486
488{
492 {
493 return;
494 }
495
496 AppendViaSize( 0, 0 );
497
498 m_viaSizesGrid->MakeCellVisible( m_viaSizesGrid->GetNumberRows() - 1, VIA_SIZE_COL );
499 m_viaSizesGrid->SetGridCursor( m_viaSizesGrid->GetNumberRows() - 1, VIA_SIZE_COL );
500
501 m_viaSizesGrid->EnableCellEditControl( true );
502 m_viaSizesGrid->ShowCellEditControl();
503}
504
505
507{
511 {
512 return;
513 }
514
516}
517
518
520{
524 {
525 return;
526 }
527
528 AppendDiffPairs( 0, 0, 0 );
529
530 m_diffPairsGrid->MakeCellVisible( m_diffPairsGrid->GetNumberRows() - 1, DP_WIDTH_COL );
531 m_diffPairsGrid->SetGridCursor( m_diffPairsGrid->GetNumberRows() - 1, DP_WIDTH_COL );
532
533 m_diffPairsGrid->EnableCellEditControl( true );
534 m_diffPairsGrid->ShowCellEditControl();
535}
536
537
539{
543 {
544 return;
545 }
546
548}
549
550
552{
556
557 // Note: do not change the board, as we need to get the current nets from it for
558 // netclass memberships. All the netclass definitions and dimension lists are in
559 // the BOARD_DESIGN_SETTINGS.
560
561 BOARD_DESIGN_SETTINGS* savedSettings = m_BrdSettings;
562
563 m_BrdSettings = &aBoard->GetDesignSettings();
565
566 m_BrdSettings = savedSettings;
567}
568
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:106
@ small_sort_desc
Container for design settings for a BOARD object.
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
std::vector< int > m_TrackWidthList
std::vector< VIA_DIMENSION > m_ViasDimensionsList
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:269
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:704
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition: grid_tricks.h:61
void SetError(const wxString &aMessage, const wxString &aPageName, int aCtrlId, int aRow=-1, int aCol=-1)
Class PANEL_SETUP_TRACKS_AND_VIAS_BASE.
void OnRemoveViaSizesClick(wxCommandEvent &event) override
void OnRemoveDiffPairsClick(wxCommandEvent &event) override
void OnSortTrackWidthsClick(wxCommandEvent &event) override
void onUnitsChanged(wxCommandEvent &aEvent)
void OnSortViaSizesClick(wxCommandEvent &event) override
void OnAddViaSizesClick(wxCommandEvent &event) override
void OnSortDiffPairsClick(wxCommandEvent &event) override
void OnRemoveTrackWidthsClick(wxCommandEvent &event) override
void OnAddDiffPairsClick(wxCommandEvent &event) override
void AppendDiffPairs(int aWidth, int aGap, int aViaGap)
void OnAddTrackWidthsClick(wxCommandEvent &event) override
PANEL_SETUP_TRACKS_AND_VIAS(PAGED_DIALOG *aParent, PCB_EDIT_FRAME *aFrame)
void AppendViaSize(int aSize, int aDrill)
BOARD * GetBoard() const
The main frame for Pcbnew.
void SetBitmap(const wxBitmap &aBmp)
int ValueFromString(const wxString &aTextValue, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Converts aTextValue in aUnits to internal units used by the frame.
int GetVisibleWidth(int aCol, bool aHeader=true, bool aContents=true, bool aKeep=false)
Calculates the specified column based on the actual size of the text on screen.
Definition: wx_grid.cpp:520
void SetUnitValue(int aRow, int aCol, int aValue)
Set a unitized cell's value.
Definition: wx_grid.cpp:502
int GetUnitValue(int aRow, int aCol)
Apply standard KiCad unit and eval services to a numeric cell.
Definition: wx_grid.cpp:481
void SetAutoEvalCols(const std::vector< int > &aCols)
Definition: wx_grid.h:96
void SetUnitsProvider(UNITS_PROVIDER *aProvider, int aCol=0)
Set a UNITS_PROVIDER to enable use of unit- and eval-based Getters.
Definition: wx_grid.cpp:472
void ClearRows()
wxWidgets recently added an ASSERT which fires if the position is greater than or equal to the number...
Definition: wx_grid.h:139
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:423
#define _(s)
void removeSelectedRows(WX_GRID *aGrid)
Container to handle a stock of specific differential pairs each with unique track width,...
Container to handle a stock of specific vias each with unique diameter and drill sizes in the BOARD c...