KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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-2023 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 <grid_tricks.h>
31
33
34
36{
37 TR_WIDTH_COL = 0
38};
39
41{
44};
45
47{
51};
52
53
55 PCB_EDIT_FRAME* aFrame ) :
57{
58 m_Frame = aFrame;
61
62 m_trackWidthsAddButton->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
63 m_trackWidthsSortButton->SetBitmap( KiBitmapBundle( BITMAPS::small_sort_desc ) );
64 m_trackWidthsRemoveButton->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
65 m_viaSizesAddButton->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
66 m_viaSizesSortButton->SetBitmap( KiBitmapBundle( BITMAPS::small_sort_desc ) );
67 m_viaSizesRemoveButton->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
68 m_diffPairsAddButton->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
69 m_diffPairsSortButton->SetBitmap( KiBitmapBundle( BITMAPS::small_sort_desc ) );
70 m_diffPairsRemoveButton->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
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() + FromDIP( 4 ) );
75 m_viaSizesGrid->SetDefaultRowSize( m_viaSizesGrid->GetDefaultRowSize() + FromDIP( 4 ) );
76 m_diffPairsGrid->SetDefaultRowSize( m_diffPairsGrid->GetDefaultRowSize() + FromDIP( 4 ) );
77
78 m_trackWidthsGrid->PushEventHandler( new GRID_TRICKS( m_trackWidthsGrid,
79 [this]( wxCommandEvent& aEvent )
80 {
81 OnAddTrackWidthsClick( aEvent );
82 } ) );
83 m_viaSizesGrid->PushEventHandler( new GRID_TRICKS( m_viaSizesGrid,
84 [this]( wxCommandEvent& aEvent )
85 {
86 OnAddViaSizesClick( aEvent );
87 } ) );
88 m_diffPairsGrid->PushEventHandler( new GRID_TRICKS( m_diffPairsGrid,
89 [this]( wxCommandEvent& aEvent )
90 {
91 OnAddDiffPairsClick( aEvent );
92 } ) );
93
94 m_trackWidthsGrid->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
95 m_viaSizesGrid->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
96 m_diffPairsGrid->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
97
101
103 m_viaSizesGrid->SetAutoEvalCols( { 0, 1 } );
104 m_diffPairsGrid->SetAutoEvalCols( { 0, 1, 2 } );
105
106 m_trackWidthsGrid->SetUseNativeColLabels();
107 m_viaSizesGrid->SetUseNativeColLabels();
108 m_diffPairsGrid->SetUseNativeColLabels();
109
110 // Ensure width of columns is enough to enter any reasonable value
111 WX_GRID* grid_list[] = { m_trackWidthsGrid, m_viaSizesGrid, m_diffPairsGrid, nullptr };
112 int min_linesize = m_trackWidthsGrid->GetTextExtent( wxT( "000.000000 mm " ) ).x;
113
114 for( int ii = 0; grid_list[ii]; ii++ )
115 {
116 WX_GRID* curr_grid = grid_list[ii];
117
118 for( int col = 0; col < curr_grid->GetNumberCols(); col++ )
119 {
120 int min_w = curr_grid->GetVisibleWidth( col, true, true, true );
121 int best_w = std::max( min_linesize, min_w );
122 curr_grid->SetColMinimalWidth( col, best_w );
123 curr_grid->SetColSize( col,best_w );
124 }
125 }
126
127 m_Frame->Bind( EDA_EVT_UNITS_CHANGED, &PANEL_SETUP_TRACKS_AND_VIAS::onUnitsChanged, this );
128}
129
130
132{
133 // Delete the GRID_TRICKS.
134 m_trackWidthsGrid->PopEventHandler( true );
135 m_viaSizesGrid->PopEventHandler( true );
136 m_diffPairsGrid->PopEventHandler( true );
137
138 m_Frame->Unbind( EDA_EVT_UNITS_CHANGED, &PANEL_SETUP_TRACKS_AND_VIAS::onUnitsChanged, this );
139}
140
141
143{
144 std::vector<int> trackWidths;
145 wxString msg;
146
147 wxGridUpdateLocker lock( m_trackWidthsGrid );
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( m_Frame->ValueFromString( msg ) );
155 }
156
157 std::sort( trackWidths.begin(), trackWidths.end() );
158 m_trackWidthsGrid->DeleteRows(0, m_trackWidthsGrid->GetNumberRows(), false);
159
160 for( int width : trackWidths )
161 AppendTrackWidth( width );
162}
163
164
166{
167 std::vector<VIA_DIMENSION> vias;
168 wxString msg;
169
170 wxGridUpdateLocker lock( m_viaSizesGrid );
171
172 for( int row = 0; row < m_viaSizesGrid->GetNumberRows(); ++row )
173 {
174 msg = m_viaSizesGrid->GetCellValue( row, VIA_SIZE_COL );
175
176 if( !msg.IsEmpty() )
177 {
178 VIA_DIMENSION via_dim;
179 via_dim.m_Diameter = m_Frame->ValueFromString( msg );
180
181 msg = m_viaSizesGrid->GetCellValue( row, VIA_DRILL_COL );
182
183 if( !msg.IsEmpty() )
184 via_dim.m_Drill = m_Frame->ValueFromString( msg );
185
186 vias.push_back( via_dim );
187 }
188 }
189
190 std::sort( vias.begin(), vias.end() );
191 m_viaSizesGrid->DeleteRows(0, m_viaSizesGrid->GetNumberRows(), false );
192
193 for( const VIA_DIMENSION& via : vias )
194 AppendViaSize( via.m_Diameter, via.m_Drill );
195}
196
197
199{
200 wxString msg;
201 std::vector<DIFF_PAIR_DIMENSION> diffPairs;
202
203 wxGridUpdateLocker lock( m_diffPairsGrid );
204
205 for( int row = 0; row < m_diffPairsGrid->GetNumberRows(); ++row )
206 {
207 msg = m_diffPairsGrid->GetCellValue( row, DP_WIDTH_COL );
208
209 if( !msg.IsEmpty() )
210 {
211 DIFF_PAIR_DIMENSION diffPair_dim;
212 diffPair_dim.m_Width = m_Frame->ValueFromString( msg );
213
214 msg = m_diffPairsGrid->GetCellValue( row, DP_GAP_COL );
215 diffPair_dim.m_Gap = m_Frame->ValueFromString( msg );
216
217 msg = m_diffPairsGrid->GetCellValue( row, DP_VIA_GAP_COL );
218
219 if( !msg.IsEmpty() )
220 diffPair_dim.m_ViaGap = m_Frame->ValueFromString( msg );
221
222 diffPairs.push_back( diffPair_dim );
223 }
224 }
225
226 std::sort( diffPairs.begin(), diffPairs.end() );
227 m_diffPairsGrid->DeleteRows(0, m_diffPairsGrid->GetNumberRows(), false );
228
229 for( const DIFF_PAIR_DIMENSION& dp : diffPairs )
230 AppendDiffPairs( dp.m_Width, dp.m_Gap, dp.m_ViaGap );
231}
232
233
235{
236 BOARD_DESIGN_SETTINGS tempBDS( nullptr, "dummy" );
238
239 m_BrdSettings = &tempBDS; // No, address of stack var does not escape function
240
243
244 m_BrdSettings = saveBDS;
245
246 aEvent.Skip();
247}
248
249
251{
255
256 // Skip the first item, which is the current netclass value
257 for( unsigned ii = 1; ii < m_BrdSettings->m_TrackWidthList.size(); ii++ )
258 {
260 }
261
262 // Skip the first item, which is the current netclass value
263 for( unsigned ii = 1; ii < m_BrdSettings->m_ViasDimensionsList.size(); ii++ )
264 {
266 m_BrdSettings->m_ViasDimensionsList[ii].m_Drill );
267 }
268
269 // Skip the first item, which is the current netclass value
270 for( unsigned ii = 1; ii < m_BrdSettings->m_DiffPairDimensionsList.size(); ii++ )
271 {
275 }
276
277 return true;
278}
279
280
282{
286 {
287 return false;
288 }
289
290 wxString msg;
291 std::vector<int> trackWidths;
292 std::vector<VIA_DIMENSION> vias;
293 std::vector<DIFF_PAIR_DIMENSION> diffPairs;
294
295 // Test ONLY for malformed data. Design rules and constraints are the business of DRC.
296
297 for( int row = 0; row < m_trackWidthsGrid->GetNumberRows(); ++row )
298 {
299 if( !m_trackWidthsGrid->GetCellValue( row, TR_WIDTH_COL ).IsEmpty() )
300 trackWidths.push_back( m_trackWidthsGrid->GetUnitValue( row, TR_WIDTH_COL ) );
301 }
302
303 for( int row = 0; row < m_viaSizesGrid->GetNumberRows(); ++row )
304 {
305 if( !m_viaSizesGrid->GetCellValue( row, VIA_SIZE_COL ).IsEmpty() )
306 {
307 VIA_DIMENSION via_dim;
309
310 if( !m_viaSizesGrid->GetCellValue( row, VIA_DRILL_COL ).IsEmpty() )
312
313 vias.push_back( via_dim );
314 }
315 }
316
317 for( int row = 0; row < m_diffPairsGrid->GetNumberRows(); ++row )
318 {
319 if( !m_diffPairsGrid->GetCellValue( row, DP_WIDTH_COL ).IsEmpty() )
320 {
321 DIFF_PAIR_DIMENSION diffPair_dim;
322 diffPair_dim.m_Width = m_diffPairsGrid->GetUnitValue( row, DP_WIDTH_COL );
323
324 if( !m_diffPairsGrid->GetCellValue( row, DP_GAP_COL ).IsEmpty() )
325 diffPair_dim.m_Gap = m_diffPairsGrid->GetUnitValue( row, DP_GAP_COL );
326
327 if( !m_diffPairsGrid->GetCellValue( row, DP_VIA_GAP_COL ).IsEmpty() )
328 diffPair_dim.m_ViaGap = m_diffPairsGrid->GetUnitValue( row, DP_VIA_GAP_COL );
329
330 diffPairs.push_back( diffPair_dim );
331 }
332 }
333
334 // Sort lists by increasing value
335 sort( trackWidths.begin(), trackWidths.end() );
336 sort( vias.begin(), vias.end() );
337 sort( diffPairs.begin(), diffPairs.end() );
338
339 // These are all stored in project file, not board, so no need for OnModify()
340
341 trackWidths.insert( trackWidths.begin(), 0 ); // dummy value for "use netclass"
342 m_BrdSettings->m_TrackWidthList = trackWidths;
343
344 vias.insert( vias.begin(), { 0, 0 } ); // dummy value for "use netclass"
346
347 diffPairs.insert( diffPairs.begin(), { 0, 0, 0 } ); // dummy value for "use netclass"
349
350 return true;
351}
352
353
355{
359 {
360 return false;
361 }
362
363 wxString msg;
364
365 // Test vias
366 for( int row = 0; row < m_viaSizesGrid->GetNumberRows(); ++row )
367 {
368 wxString viaDia = m_viaSizesGrid->GetCellValue( row, VIA_SIZE_COL );
369 wxString viaDrill = m_viaSizesGrid->GetCellValue( row, VIA_DRILL_COL );
370
371 if( !viaDia.IsEmpty() && viaDrill.IsEmpty() )
372 {
373 msg = _( "No via hole size defined." );
375 return false;
376 }
377 }
378
379 // Test diff pairs
380 for( int row = 0; row < m_diffPairsGrid->GetNumberRows(); ++row )
381 {
382 wxString dpWidth = m_diffPairsGrid->GetCellValue( row, 0 );
383 wxString dpGap = m_diffPairsGrid->GetCellValue( row, 1 );
384
385 if( !dpWidth.IsEmpty() && dpGap.IsEmpty() )
386 {
387 msg = _( "No differential pair gap defined." );
388 PAGED_DIALOG::GetDialog( this )->SetError( msg, this, m_diffPairsGrid, row, 1 );
389 return false;
390 }
391 }
392
393 return true;
394}
395
396
398{
399 int i = m_trackWidthsGrid->GetNumberRows();
400
401 m_trackWidthsGrid->AppendRows( 1 );
402
404}
405
406
408{
409 int i = m_viaSizesGrid->GetNumberRows();
410
411 m_viaSizesGrid->AppendRows( 1 );
412
414
415 if( aDrill > 0 )
417}
418
419
420void PANEL_SETUP_TRACKS_AND_VIAS::AppendDiffPairs( int aWidth, int aGap, int aViaGap )
421{
422 int i = m_diffPairsGrid->GetNumberRows();
423
424 m_diffPairsGrid->AppendRows( 1 );
425
427
428 if( aGap > 0 )
430
431 if( aViaGap > 0 )
433}
434
435
437{
438 wxArrayInt selectedRows = aGrid->GetSelectedRows();
439 int curRow = aGrid->GetGridCursorRow();
440
441 if( selectedRows.empty() && curRow >= 0 && curRow < aGrid->GetNumberRows() )
442 selectedRows.Add( curRow );
443
444 for( int ii = selectedRows.Count() - 1; ii >= 0; --ii )
445 {
446 int row = selectedRows.Item( ii );
447 aGrid->DeleteRows( row, 1 );
448 curRow = std::min( curRow, row );
449 }
450
451 curRow = std::max( 0, curRow - 1 );
452 aGrid->MakeCellVisible( curRow, aGrid->GetGridCursorCol() );
453 aGrid->SetGridCursor( curRow, aGrid->GetGridCursorCol() );
454}
455
456
458{
462 {
463 return;
464 }
465
466 AppendTrackWidth( 0 );
467
468 m_trackWidthsGrid->MakeCellVisible( m_trackWidthsGrid->GetNumberRows() - 1, TR_WIDTH_COL );
469 m_trackWidthsGrid->SetGridCursor( m_trackWidthsGrid->GetNumberRows() - 1, TR_WIDTH_COL );
470
471 m_trackWidthsGrid->EnableCellEditControl( true );
472 m_trackWidthsGrid->ShowCellEditControl();
473}
474
475
477{
481 {
482 return;
483 }
484
486}
487
488
490{
494 {
495 return;
496 }
497
498 AppendViaSize( 0, 0 );
499
500 m_viaSizesGrid->MakeCellVisible( m_viaSizesGrid->GetNumberRows() - 1, VIA_SIZE_COL );
501 m_viaSizesGrid->SetGridCursor( m_viaSizesGrid->GetNumberRows() - 1, VIA_SIZE_COL );
502
503 m_viaSizesGrid->EnableCellEditControl( true );
504 m_viaSizesGrid->ShowCellEditControl();
505}
506
507
509{
513 {
514 return;
515 }
516
518}
519
520
522{
526 {
527 return;
528 }
529
530 AppendDiffPairs( 0, 0, 0 );
531
532 m_diffPairsGrid->MakeCellVisible( m_diffPairsGrid->GetNumberRows() - 1, DP_WIDTH_COL );
533 m_diffPairsGrid->SetGridCursor( m_diffPairsGrid->GetNumberRows() - 1, DP_WIDTH_COL );
534
535 m_diffPairsGrid->EnableCellEditControl( true );
536 m_diffPairsGrid->ShowCellEditControl();
537}
538
539
541{
545 {
546 return;
547 }
548
550}
551
552
554{
558
559 // Note: do not change the board, as we need to get the current nets from it for
560 // netclass memberships. All the netclass definitions and dimension lists are in
561 // the BOARD_DESIGN_SETTINGS.
562
563 BOARD_DESIGN_SETTINGS* savedSettings = m_BrdSettings;
564
565 m_BrdSettings = &aBoard->GetDesignSettings();
567
568 m_BrdSettings = savedSettings;
569}
570
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap)
Definition: bitmap.cpp:110
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:290
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:892
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition: grid_tricks.h:61
static PAGED_DIALOG * GetDialog(wxWindow *aWindow)
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
PANEL_SETUP_TRACKS_AND_VIAS(wxWindow *aParentWindow, PCB_EDIT_FRAME *aFrame)
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
void AppendViaSize(int aSize, int aDrill)
BOARD * GetBoard() const
The main frame for Pcbnew.
void SetBitmap(const wxBitmapBundle &aBmp)
int ValueFromString(const wxString &aTextValue, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
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:769
void SetUnitValue(int aRow, int aCol, int aValue)
Set a unitized cell's value.
Definition: wx_grid.cpp:740
int GetUnitValue(int aRow, int aCol)
Apply standard KiCad unit and eval services to a numeric cell.
Definition: wx_grid.cpp:698
void SetAutoEvalCols(const std::vector< int > &aCols)
Definition: wx_grid.h:124
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:689
void ClearRows()
wxWidgets recently added an ASSERT which fires if the position is greater than or equal to the number...
Definition: wx_grid.h:184
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:637
#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...