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 The KiCad Developers, see AUTHORS.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 m_trackWidthsGrid->PushEventHandler( new GRID_TRICKS( m_trackWidthsGrid,
73 [this]( wxCommandEvent& aEvent )
74 {
75 OnAddTrackWidthsClick( aEvent );
76 } ) );
77 m_viaSizesGrid->PushEventHandler( new GRID_TRICKS( m_viaSizesGrid,
78 [this]( wxCommandEvent& aEvent )
79 {
80 OnAddViaSizesClick( aEvent );
81 } ) );
82 m_diffPairsGrid->PushEventHandler( new GRID_TRICKS( m_diffPairsGrid,
83 [this]( wxCommandEvent& aEvent )
84 {
85 OnAddDiffPairsClick( aEvent );
86 } ) );
87
88 m_trackWidthsGrid->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
89 m_viaSizesGrid->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
90 m_diffPairsGrid->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
91
95
98 m_diffPairsGrid->SetAutoEvalCols( { 0, 1, 2 } );
99
100 m_trackWidthsGrid->SetUseNativeColLabels();
101 m_viaSizesGrid->SetUseNativeColLabels();
102 m_diffPairsGrid->SetUseNativeColLabels();
103
104 // Ensure width of columns is enough to enter any reasonable value
105 WX_GRID* grid_list[] = { m_trackWidthsGrid, m_viaSizesGrid, m_diffPairsGrid, nullptr };
106 int min_linesize = m_trackWidthsGrid->GetTextExtent( wxT( "000.000000 mm " ) ).x;
107
108 for( int ii = 0; grid_list[ii]; ii++ )
109 {
110 WX_GRID* curr_grid = grid_list[ii];
111
112 for( int col = 0; col < curr_grid->GetNumberCols(); col++ )
113 {
114 int min_w = curr_grid->GetVisibleWidth( col, true, true, true );
115 int best_w = std::max( min_linesize, min_w );
116 curr_grid->SetColMinimalWidth( col, best_w );
117 curr_grid->SetColSize( col,best_w );
118 }
119 }
120
121 m_Frame->Bind( EDA_EVT_UNITS_CHANGED, &PANEL_SETUP_TRACKS_AND_VIAS::onUnitsChanged, this );
122}
123
124
126{
127 // Delete the GRID_TRICKS.
128 m_trackWidthsGrid->PopEventHandler( true );
129 m_viaSizesGrid->PopEventHandler( true );
130 m_diffPairsGrid->PopEventHandler( true );
131
132 m_Frame->Unbind( EDA_EVT_UNITS_CHANGED, &PANEL_SETUP_TRACKS_AND_VIAS::onUnitsChanged, this );
133}
134
135
137{
138 if( m_trackWidthsGrid->GetNumberRows() < 2 )
139 return;
140
141 std::vector<int> trackWidths;
142 wxString msg;
143
144 m_trackWidthsGrid->ClearSelection();
145 wxSafeYield();
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 if( m_viaSizesGrid->GetNumberRows() < 2 )
168 return;
169
170 std::vector<VIA_DIMENSION> vias;
171 wxString msg;
172
173 m_viaSizesGrid->ClearSelection();
174 wxSafeYield();
175
176 wxGridUpdateLocker lock( m_viaSizesGrid );
177
178 for( int row = 0; row < m_viaSizesGrid->GetNumberRows(); ++row )
179 {
180 msg = m_viaSizesGrid->GetCellValue( row, VIA_SIZE_COL );
181
182 if( !msg.IsEmpty() )
183 {
184 VIA_DIMENSION via_dim;
185 via_dim.m_Diameter = m_Frame->ValueFromString( msg );
186
187 msg = m_viaSizesGrid->GetCellValue( row, VIA_DRILL_COL );
188
189 if( !msg.IsEmpty() )
190 via_dim.m_Drill = m_Frame->ValueFromString( msg );
191
192 vias.push_back( via_dim );
193 }
194 }
195
196 std::sort( vias.begin(), vias.end() );
197 m_viaSizesGrid->DeleteRows( 0, m_viaSizesGrid->GetNumberRows(), false );
198
199 for( const VIA_DIMENSION& via : vias )
200 AppendViaSize( via.m_Diameter, via.m_Drill );
201}
202
203
205{
206 if( m_diffPairsGrid->GetNumberRows() < 2 )
207 return;
208
209 wxString msg;
210 std::vector<DIFF_PAIR_DIMENSION> diffPairs;
211
212 m_diffPairsGrid->ClearSelection();
213 wxSafeYield();
214
215 wxGridUpdateLocker lock( m_diffPairsGrid );
216
217 for( int row = 0; row < m_diffPairsGrid->GetNumberRows(); ++row )
218 {
219 msg = m_diffPairsGrid->GetCellValue( row, DP_WIDTH_COL );
220
221 if( !msg.IsEmpty() )
222 {
223 DIFF_PAIR_DIMENSION diffPair_dim;
224 diffPair_dim.m_Width = m_Frame->ValueFromString( msg );
225
226 msg = m_diffPairsGrid->GetCellValue( row, DP_GAP_COL );
227 diffPair_dim.m_Gap = m_Frame->ValueFromString( msg );
228
229 msg = m_diffPairsGrid->GetCellValue( row, DP_VIA_GAP_COL );
230
231 if( !msg.IsEmpty() )
232 diffPair_dim.m_ViaGap = m_Frame->ValueFromString( msg );
233
234 diffPairs.push_back( diffPair_dim );
235 }
236 }
237
238 std::sort( diffPairs.begin(), diffPairs.end() );
239 m_diffPairsGrid->DeleteRows( 0, m_diffPairsGrid->GetNumberRows(), false );
240
241 for( const DIFF_PAIR_DIMENSION& dp : diffPairs )
242 AppendDiffPairs( dp.m_Width, dp.m_Gap, dp.m_ViaGap );
243}
244
245
247{
248 BOARD_DESIGN_SETTINGS tempBDS( nullptr, "dummy" );
250
251 m_BrdSettings = &tempBDS; // No, address of stack var does not escape function
252
255
256 m_BrdSettings = saveBDS;
257
258 aEvent.Skip();
259}
260
261
263{
267
268 // Skip the first item, which is the current netclass value
269 for( unsigned ii = 1; ii < m_BrdSettings->m_TrackWidthList.size(); ii++ )
270 {
272 }
273
274 // Skip the first item, which is the current netclass value
275 for( unsigned ii = 1; ii < m_BrdSettings->m_ViasDimensionsList.size(); ii++ )
276 {
278 m_BrdSettings->m_ViasDimensionsList[ii].m_Drill );
279 }
280
281 // Skip the first item, which is the current netclass value
282 for( unsigned ii = 1; ii < m_BrdSettings->m_DiffPairDimensionsList.size(); ii++ )
283 {
287 }
288
289 return true;
290}
291
292
294{
295 if( !commitPendingChanges() )
296 return false;
297
298 std::vector<int> trackWidths;
299 std::vector<VIA_DIMENSION> vias;
300 std::vector<DIFF_PAIR_DIMENSION> diffPairs;
301
302 // Test ONLY for malformed data. Design rules and constraints are the business of DRC.
303
304 for( int row = 0; row < m_trackWidthsGrid->GetNumberRows(); ++row )
305 {
306 if( !m_trackWidthsGrid->GetCellValue( row, TR_WIDTH_COL ).IsEmpty() )
307 trackWidths.push_back( m_trackWidthsGrid->GetUnitValue( row, TR_WIDTH_COL ) );
308 }
309
310 for( int row = 0; row < m_viaSizesGrid->GetNumberRows(); ++row )
311 {
312 if( !m_viaSizesGrid->GetCellValue( row, VIA_SIZE_COL ).IsEmpty() )
313 {
314 VIA_DIMENSION via_dim;
316
317 if( !m_viaSizesGrid->GetCellValue( row, VIA_DRILL_COL ).IsEmpty() )
319
320 vias.push_back( via_dim );
321 }
322 }
323
324 for( int row = 0; row < m_diffPairsGrid->GetNumberRows(); ++row )
325 {
326 if( !m_diffPairsGrid->GetCellValue( row, DP_WIDTH_COL ).IsEmpty() )
327 {
328 DIFF_PAIR_DIMENSION diffPair_dim;
329 diffPair_dim.m_Width = m_diffPairsGrid->GetUnitValue( row, DP_WIDTH_COL );
330
331 if( !m_diffPairsGrid->GetCellValue( row, DP_GAP_COL ).IsEmpty() )
332 diffPair_dim.m_Gap = m_diffPairsGrid->GetUnitValue( row, DP_GAP_COL );
333
334 if( !m_diffPairsGrid->GetCellValue( row, DP_VIA_GAP_COL ).IsEmpty() )
335 diffPair_dim.m_ViaGap = m_diffPairsGrid->GetUnitValue( row, DP_VIA_GAP_COL );
336
337 diffPairs.push_back( diffPair_dim );
338 }
339 }
340
341 // Sort lists by increasing value
342 sort( trackWidths.begin(), trackWidths.end() );
343 sort( vias.begin(), vias.end() );
344 sort( diffPairs.begin(), diffPairs.end() );
345
346 // These are all stored in project file, not board, so no need for OnModify()
347
348 trackWidths.insert( trackWidths.begin(), 0 ); // dummy value for "use netclass"
349 m_BrdSettings->m_TrackWidthList = trackWidths;
350
351 vias.insert( vias.begin(), { 0, 0 } ); // dummy value for "use netclass"
353
354 diffPairs.insert( diffPairs.begin(), { 0, 0, 0 } ); // dummy value for "use netclass"
356
357 return true;
358}
359
360
362{
363 return m_trackWidthsGrid->CommitPendingChanges( aQuietMode )
364 && m_viaSizesGrid->CommitPendingChanges( aQuietMode )
365 && m_diffPairsGrid->CommitPendingChanges( aQuietMode );
366}
367
368
370{
371 if( !commitPendingChanges() )
372 return false;
373
374 wxString msg;
375
376 // Test vias
377 for( int row = 0; row < m_viaSizesGrid->GetNumberRows(); ++row )
378 {
379 wxString viaDia = m_viaSizesGrid->GetCellValue( row, VIA_SIZE_COL );
380 wxString viaDrill = m_viaSizesGrid->GetCellValue( row, VIA_DRILL_COL );
381
382 if( !viaDia.IsEmpty() && viaDrill.IsEmpty() )
383 {
384 msg = _( "No via hole size defined." );
386 return false;
387 }
388 }
389
390 // Test diff pairs
391 for( int row = 0; row < m_diffPairsGrid->GetNumberRows(); ++row )
392 {
393 wxString dpWidth = m_diffPairsGrid->GetCellValue( row, 0 );
394 wxString dpGap = m_diffPairsGrid->GetCellValue( row, 1 );
395
396 if( !dpWidth.IsEmpty() && dpGap.IsEmpty() )
397 {
398 msg = _( "No differential pair gap defined." );
399 PAGED_DIALOG::GetDialog( this )->SetError( msg, this, m_diffPairsGrid, row, 1 );
400 return false;
401 }
402 }
403
404 return true;
405}
406
407
409{
410 int i = m_trackWidthsGrid->GetNumberRows();
411
412 m_trackWidthsGrid->AppendRows( 1 );
413
415}
416
417
419{
420 int i = m_viaSizesGrid->GetNumberRows();
421
422 m_viaSizesGrid->AppendRows( 1 );
423
425
426 if( aDrill > 0 )
428}
429
430
431void PANEL_SETUP_TRACKS_AND_VIAS::AppendDiffPairs( int aWidth, int aGap, int aViaGap )
432{
433 int i = m_diffPairsGrid->GetNumberRows();
434
435 m_diffPairsGrid->AppendRows( 1 );
436
438
439 if( aGap > 0 )
441
442 if( aViaGap > 0 )
444}
445
446
448{
450 [&]() -> std::pair<int, int>
451 {
452 AppendTrackWidth( 0 );
453 return { m_trackWidthsGrid->GetNumberRows() - 1, TR_WIDTH_COL };
454 } );
455}
456
457
459{
461 [&]( int row )
462 {
463 m_trackWidthsGrid->DeleteRows( row, 1 );
464 } );
465}
466
467
469{
471 [&]() -> std::pair<int, int>
472 {
473 AppendViaSize( 0, 0 );
474 return { m_viaSizesGrid->GetNumberRows() - 1, VIA_SIZE_COL };
475 } );
476}
477
478
480{
482 [&]( int row )
483 {
484 m_viaSizesGrid->DeleteRows( row, 1 );
485 } );
486}
487
488
490{
492 [&]() -> std::pair<int, int>
493 {
494 AppendDiffPairs( 0, 0, 0 );
495 return { m_diffPairsGrid->GetNumberRows() - 1, DP_WIDTH_COL };
496 } );
497}
498
499
501{
503 [&]( int row )
504 {
505 m_diffPairsGrid->DeleteRows( row, 1 );
506 } );
507}
508
509
511{
512 commitPendingChanges( true );
513
514 // Note: do not change the board, as we need to get the current nets from it for
515 // netclass memberships. All the netclass definitions and dimension lists are in
516 // the BOARD_DESIGN_SETTINGS.
517
518 BOARD_DESIGN_SETTINGS* savedSettings = m_BrdSettings;
519
520 m_BrdSettings = &aBoard->GetDesignSettings();
522
523 m_BrdSettings = savedSettings;
524}
525
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
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:317
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:1024
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
bool commitPendingChanges(bool aQuietMode=false)
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)
Calculate the specified column based on the actual size of the text on screen.
Definition: wx_grid.cpp:916
void SetUnitValue(int aRow, int aCol, int aValue)
Set a unitized cell's value.
Definition: wx_grid.cpp:890
int GetUnitValue(int aRow, int aCol)
Apply standard KiCad unit and eval services to a numeric cell.
Definition: wx_grid.cpp:854
void OnDeleteRows(const std::function< void(int row)> &aDeleter)
Handles a row deletion event.
Definition: wx_grid.cpp:704
void OnAddRow(const std::function< std::pair< int, int >()> &aAdder)
Definition: wx_grid.cpp:684
void SetAutoEvalCols(const std::vector< int > &aCols)
Definition: wx_grid.h:145
void SetUnitsProvider(UNITS_PROVIDER *aProvider, int aCol=0)
Set a EUNITS_PROVIDER to enable use of unit- and eval-based Getters.
Definition: wx_grid.cpp:832
void ClearRows()
wxWidgets recently added an ASSERT which fires if the position is greater than or equal to the number...
Definition: wx_grid.h:220
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:632
#define _(s)
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...