1 /*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2015 CERN
5 * Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Maciej Suminski <maciej.suminski@cern.ch>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26 #include <core/kicad_algo.h>
27 #include <dialogs/dialog_track_via_properties.h>
28 #include <pcb_layer_box_selector.h>
29 #include <tools/pcb_selection_tool.h>
30 #include <board_design_settings.h>
31 #include <footprint.h>
32 #include <pad.h>
33 #include <pcb_track.h>
34 #include <pcb_edit_frame.h>
35 #include <confirm.h>
36 #include <connectivity/connectivity_data.h>
37 #include <board_commit.h>
38 #include <macros.h>
39
40 #include <wx/log.h>
41
DIALOG_TRACK_VIA_PROPERTIES(PCB_BASE_FRAME * aParent,const PCB_SELECTION & aItems,COMMIT & aCommit)42 DIALOG_TRACK_VIA_PROPERTIES::DIALOG_TRACK_VIA_PROPERTIES( PCB_BASE_FRAME* aParent,
43 const PCB_SELECTION& aItems,
44 COMMIT& aCommit ) :
45 DIALOG_TRACK_VIA_PROPERTIES_BASE( aParent ),
46 m_frame( aParent ),
47 m_items( aItems ),
48 m_commit( aCommit ),
49 m_trackStartX( aParent, m_TrackStartXLabel, m_TrackStartXCtrl, m_TrackStartXUnit ),
50 m_trackStartY( aParent, m_TrackStartYLabel, m_TrackStartYCtrl, m_TrackStartYUnit ),
51 m_trackEndX( aParent, m_TrackEndXLabel, m_TrackEndXCtrl, m_TrackEndXUnit ),
52 m_trackEndY( aParent, m_TrackEndYLabel, m_TrackEndYCtrl, m_TrackEndYUnit ),
53 m_trackWidth( aParent, m_TrackWidthLabel, m_TrackWidthCtrl, m_TrackWidthUnit ),
54 m_viaX( aParent, m_ViaXLabel, m_ViaXCtrl, m_ViaXUnit ),
55 m_viaY( aParent, m_ViaYLabel, m_ViaYCtrl, m_ViaYUnit ),
56 m_viaDiameter( aParent, m_ViaDiameterLabel, m_ViaDiameterCtrl, m_ViaDiameterUnit ),
57 m_viaDrill( aParent, m_ViaDrillLabel, m_ViaDrillCtrl, m_ViaDrillUnit ),
58 m_tracks( false ),
59 m_vias( false )
60 {
61 m_useCalculatedSize = true;
62
63 wxASSERT( !m_items.Empty() );
64
65 // Configure display origin transforms
66 m_trackStartX.SetCoordType( ORIGIN_TRANSFORMS::ABS_X_COORD );
67 m_trackStartY.SetCoordType( ORIGIN_TRANSFORMS::ABS_Y_COORD );
68 m_trackEndX.SetCoordType( ORIGIN_TRANSFORMS::ABS_X_COORD );
69 m_trackEndY.SetCoordType( ORIGIN_TRANSFORMS::ABS_Y_COORD );
70 m_viaX.SetCoordType( ORIGIN_TRANSFORMS::ABS_X_COORD );
71 m_viaY.SetCoordType( ORIGIN_TRANSFORMS::ABS_Y_COORD );
72
73 VIATYPE viaType = VIATYPE::NOT_DEFINED;
74
75 m_TrackLayerCtrl->SetLayersHotkeys( false );
76 m_TrackLayerCtrl->SetNotAllowedLayerSet( LSET::AllNonCuMask() );
77 m_TrackLayerCtrl->SetBoardFrame( aParent );
78 m_TrackLayerCtrl->Resync();
79
80 m_ViaStartLayer->SetLayersHotkeys( false );
81 m_ViaStartLayer->SetNotAllowedLayerSet( LSET::AllNonCuMask() );
82 m_ViaStartLayer->SetBoardFrame( aParent );
83 m_ViaStartLayer->Resync();
84
85 m_ViaEndLayer->SetLayersHotkeys( false );
86 m_ViaEndLayer->SetNotAllowedLayerSet( LSET::AllNonCuMask() );
87 m_ViaEndLayer->SetBoardFrame( aParent );
88 m_ViaEndLayer->Resync();
89
90 bool nets = false;
91 int net = 0;
92 bool hasLocked = false;
93 bool hasUnlocked = false;
94
95 // Start and end layers of vias
96 // if at least 2 vias do not have the same start or the same end layer
97 // the layers will be set as undefined
98 int selection_first_layer = -1;
99 int selection_last_layer = -1;
100
101 // The selection layer for tracks
102 int track_selection_layer = -1;
103
104 auto getAnnularRingSelection =
105 []( const PCB_VIA* via ) -> int
106 {
107 if( !via->GetRemoveUnconnected() )
108 return 0;
109 else if( via->GetKeepTopBottom() )
110 return 1;
111 else
112 return 2;
113 };
114
115 // Look for values that are common for every item that is selected
116 for( EDA_ITEM* item : m_items )
117 {
118 if( !nets )
119 {
120 net = static_cast<BOARD_CONNECTED_ITEM*>( item )->GetNetCode();
121 nets = true;
122 }
123 else if( net != static_cast<BOARD_CONNECTED_ITEM*>( item )->GetNetCode() )
124 {
125 net = -1;
126 }
127
128 switch( item->Type() )
129 {
130 case PCB_TRACE_T:
131 case PCB_ARC_T:
132 {
133 const PCB_TRACK* t = static_cast<const PCB_TRACK*>( item );
134
135 if( !m_tracks ) // first track in the list
136 {
137 m_trackStartX.SetValue( t->GetStart().x );
138 m_trackStartY.SetValue( t->GetStart().y );
139 m_trackEndX.SetValue( t->GetEnd().x );
140 m_trackEndY.SetValue( t->GetEnd().y );
141 m_trackWidth.SetValue( t->GetWidth() );
142 track_selection_layer = t->GetLayer();
143 m_tracks = true;
144 }
145 else // check if values are the same for every selected track
146 {
147 if( m_trackStartX.GetValue() != t->GetStart().x )
148 m_trackStartX.SetValue( INDETERMINATE_STATE );
149
150 if( m_trackStartY.GetValue() != t->GetStart().y )
151 m_trackStartY.SetValue( INDETERMINATE_STATE );
152
153 if( m_trackEndX.GetValue() != t->GetEnd().x )
154 m_trackEndX.SetValue( INDETERMINATE_STATE );
155
156 if( m_trackEndY.GetValue() != t->GetEnd().y )
157 m_trackEndY.SetValue( INDETERMINATE_STATE );
158
159 if( m_trackWidth.GetValue() != t->GetWidth() )
160 m_trackWidth.SetValue( INDETERMINATE_STATE );
161
162 if( track_selection_layer != t->GetLayer() )
163 {
164 track_selection_layer = UNDEFINED_LAYER;
165 }
166 }
167
168 if( t->IsLocked() )
169 hasLocked = true;
170 else
171 hasUnlocked = true;
172
173 break;
174 }
175
176 case PCB_VIA_T:
177 {
178 const PCB_VIA* v = static_cast<const PCB_VIA*>( item );
179
180 if( !m_vias ) // first via in the list
181 {
182 m_viaX.SetValue( v->GetPosition().x );
183 m_viaY.SetValue( v->GetPosition().y );
184 m_viaDiameter.SetValue( v->GetWidth() );
185 m_viaDrill.SetValue( v->GetDrillValue() );
186 m_vias = true;
187 viaType = v->GetViaType();
188 m_viaNotFree->SetValue( !v->GetIsFree() );
189 m_annularRingsCtrl->SetSelection( getAnnularRingSelection( v ) );
190 selection_first_layer = v->TopLayer();
191 selection_last_layer = v->BottomLayer();
192 }
193 else // check if values are the same for every selected via
194 {
195 if( m_viaX.GetValue() != v->GetPosition().x )
196 m_viaX.SetValue( INDETERMINATE_STATE );
197
198 if( m_viaY.GetValue() != v->GetPosition().y )
199 m_viaY.SetValue( INDETERMINATE_STATE );
200
201 if( m_viaDiameter.GetValue() != v->GetWidth() )
202 m_viaDiameter.SetValue( INDETERMINATE_STATE );
203
204 if( m_viaDrill.GetValue() != v->GetDrillValue() )
205 m_viaDrill.SetValue( INDETERMINATE_STATE );
206
207 if( viaType != v->GetViaType() )
208 viaType = VIATYPE::NOT_DEFINED;
209
210 if( v->GetIsFree() != !m_viaNotFree->GetValue() )
211 m_viaNotFree->Set3StateValue( wxCHK_UNDETERMINED );
212
213 if( selection_first_layer != v->TopLayer() )
214 {
215 selection_first_layer = UNDEFINED_LAYER;
216 }
217
218 if( selection_last_layer != v->BottomLayer() )
219 {
220 selection_last_layer = UNDEFINED_LAYER;
221 }
222
223 if( m_annularRingsCtrl->GetSelection() != getAnnularRingSelection( v ) )
224 {
225 if( m_annularRingsCtrl->GetStrings().size() < 4 )
226 m_annularRingsCtrl->AppendString( INDETERMINATE_STATE );
227
228 m_annularRingsCtrl->SetSelection( 3 );
229 }
230 }
231
232 if( v->IsLocked() )
233 hasLocked = true;
234 else
235 hasUnlocked = true;
236
237 break;
238 }
239
240 default:
241 {
242 wxASSERT( false );
243 break;
244 }
245 }
246 }
247
248 if( m_tracks )
249 {
250 // Set the track layer selection state:
251 if( track_selection_layer == UNDEFINED_LAYER )
252 {
253 m_TrackLayerCtrl->SetUndefinedLayerName( INDETERMINATE_STATE );
254 m_TrackLayerCtrl->Resync();
255 }
256
257 m_TrackLayerCtrl->SetLayerSelection( track_selection_layer );
258 }
259
260 // Set the vias layers selections state:
261 if( m_vias )
262 {
263 if( selection_first_layer == UNDEFINED_LAYER )
264 {
265 m_ViaStartLayer->SetUndefinedLayerName( INDETERMINATE_STATE );
266 m_ViaStartLayer->Resync();
267 }
268 m_ViaStartLayer->SetLayerSelection( selection_first_layer );
269
270 if( selection_last_layer == UNDEFINED_LAYER )
271 {
272 m_ViaEndLayer->SetUndefinedLayerName( INDETERMINATE_STATE );
273 m_ViaEndLayer->Resync();
274 }
275 m_ViaEndLayer->SetLayerSelection( selection_last_layer );
276 }
277
278 m_netSelector->SetBoard( aParent->GetBoard() );
279 m_netSelector->SetNetInfo( &aParent->GetBoard()->GetNetInfo() );
280
281 if ( net >= 0 )
282 {
283 m_netSelector->SetSelectedNetcode( net );
284 }
285 else
286 {
287 m_netSelector->SetIndeterminateString( INDETERMINATE_STATE );
288 m_netSelector->SetIndeterminate();
289 }
290
291 wxASSERT( m_tracks || m_vias );
292
293 if( m_vias )
294 {
295 if( m_viaNotFree->GetValue() )
296 {
297 m_netSelectorLabel->Disable();
298 m_netSelector->Disable();
299 }
300
301 m_DesignRuleViasUnit->SetLabel( GetAbbreviatedUnitsLabel( m_units ) );
302
303 int viaSelection = wxNOT_FOUND;
304
305 // 0 is the netclass place-holder
306 for( unsigned ii = 1; ii < aParent->GetDesignSettings().m_ViasDimensionsList.size(); ii++ )
307 {
308 VIA_DIMENSION* viaDimension = &aParent->GetDesignSettings().m_ViasDimensionsList[ii];
309 wxString msg = StringFromValue( m_units, viaDimension->m_Diameter, false )
310 + " / " + StringFromValue( m_units, viaDimension->m_Drill, false );
311 m_DesignRuleViasCtrl->Append( msg, viaDimension );
312
313 if( viaSelection == wxNOT_FOUND
314 && m_viaDiameter.GetValue() == viaDimension->m_Diameter
315 && m_viaDrill.GetValue() == viaDimension->m_Drill )
316 {
317 viaSelection = ii - 1;
318 }
319 }
320
321 m_DesignRuleViasCtrl->SetSelection( viaSelection );
322
323 m_ViaTypeChoice->Enable();
324
325 switch( viaType )
326 {
327 case VIATYPE::THROUGH: m_ViaTypeChoice->SetSelection( 0 ); break;
328 case VIATYPE::MICROVIA: m_ViaTypeChoice->SetSelection( 1 ); break;
329 case VIATYPE::BLIND_BURIED: m_ViaTypeChoice->SetSelection( 2 ); break;
330 case VIATYPE::NOT_DEFINED: m_ViaTypeChoice->SetSelection( wxNOT_FOUND ); break;
331 }
332
333 m_ViaStartLayer->Enable( viaType != VIATYPE::THROUGH );
334 m_ViaEndLayer->Enable( viaType != VIATYPE::THROUGH );
335 }
336 else
337 {
338 m_viaNotFree->Hide();
339 m_MainSizer->Hide( m_sbViaSizer, true );
340 }
341
342 if( m_tracks )
343 {
344 m_DesignRuleWidthsUnits->SetLabel( GetAbbreviatedUnitsLabel( m_units ) );
345
346 int widthSelection = wxNOT_FOUND;
347
348 // 0 is the netclass place-holder
349 for( unsigned ii = 1; ii < aParent->GetDesignSettings().m_TrackWidthList.size(); ii++ )
350 {
351 int width = aParent->GetDesignSettings().m_TrackWidthList[ii];
352 wxString msg = StringFromValue( m_units, width, false );
353 m_DesignRuleWidthsCtrl->Append( msg );
354
355 if( widthSelection == wxNOT_FOUND && m_trackWidth.GetValue() == width )
356 widthSelection = ii - 1;
357 }
358
359 m_DesignRuleWidthsCtrl->SetSelection( widthSelection );
360 }
361 else
362 {
363 m_MainSizer->Hide( m_sbTrackSizer, true );
364 }
365
366 if( hasLocked && hasUnlocked )
367 m_lockedCbox->Set3StateValue( wxCHK_UNDETERMINED );
368 else if( hasLocked )
369 m_lockedCbox->Set3StateValue( wxCHK_CHECKED );
370 else
371 m_lockedCbox->Set3StateValue( wxCHK_UNCHECKED );
372
373 if( m_tracks )
374 SetInitialFocus( m_TrackWidthCtrl );
375 else if( m_netSelector->IsEnabled() )
376 SetInitialFocus( m_netSelector );
377 else
378 SetInitialFocus( m_ViaDiameterCtrl );
379
380 m_StdButtonsOK->SetDefault();
381
382 // Now all widgets have the size fixed, call FinishDialogSettings
383 finishDialogSettings();
384 }
385
386
confirmPadChange(const std::vector<PAD * > & changingPads)387 bool DIALOG_TRACK_VIA_PROPERTIES::confirmPadChange( const std::vector<PAD*>& changingPads )
388 {
389 wxString msg;
390
391 if( changingPads.size() == 1 )
392 {
393 PAD* pad = *changingPads.begin();
394 msg.Printf( _( "Changing the net will also update %s pad %s to %s." ),
395 pad->GetParent()->GetReference(),
396 pad->GetNumber(),
397 m_netSelector->GetValue() );
398 }
399 else if( changingPads.size() == 2 )
400 {
401 PAD* pad1 = *changingPads.begin();
402 PAD* pad2 = *( ++changingPads.begin() );
403 msg.Printf( _( "Changing the net will also update %s pad %s and %s pad %s to %s." ),
404 pad1->GetParent()->GetReference(),
405 pad1->GetNumber(),
406 pad2->GetParent()->GetReference(),
407 pad2->GetNumber(),
408 m_netSelector->GetValue() );
409 }
410 else
411 {
412 msg.Printf( _( "Changing the net will also update %lu connected pads to %s." ),
413 static_cast<unsigned long>( changingPads.size() ),
414 m_netSelector->GetValue() );
415 }
416
417 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
418 dlg.SetOKCancelLabels( _( "Change Nets" ), _( "Leave Nets Unchanged" ) );
419 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
420
421 return dlg.ShowModal() == wxID_OK;
422 }
423
424
TransferDataFromWindow()425 bool DIALOG_TRACK_VIA_PROPERTIES::TransferDataFromWindow()
426 {
427 // Run validations:
428
429 if( m_vias )
430 {
431 if( !m_viaDiameter.Validate( GEOMETRY_MIN_SIZE, INT_MAX )
432 || !m_viaDrill.Validate( GEOMETRY_MIN_SIZE, INT_MAX ) )
433 return false;
434
435 if( m_ViaDiameterCtrl->IsEnabled() && !m_viaDiameter.IsIndeterminate()
436 && m_ViaDrillCtrl->IsEnabled() && !m_viaDrill.IsIndeterminate()
437 && m_viaDiameter.GetValue() <= m_viaDrill.GetValue() )
438 {
439 DisplayError( GetParent(), _( "Via hole size must be smaller than via diameter" ) );
440 m_ViaDrillCtrl->SelectAll();
441 m_ViaDrillCtrl->SetFocus();
442 return false;
443 }
444
445 if( m_ViaStartLayer->GetLayerSelection() != UNDEFINED_LAYER &&
446 m_ViaStartLayer->GetLayerSelection() == m_ViaEndLayer->GetLayerSelection() )
447 {
448 DisplayError( GetParent(), _( "Via start layer and end layer cannot be the same" ) );
449 return false;
450 }
451 }
452
453 if( m_tracks )
454 {
455 if( !m_trackWidth.Validate( GEOMETRY_MIN_SIZE, INT_MAX ) )
456 return false;
457 }
458
459 // If we survived that, then save the changes:
460 //
461 // We don't bother with updating the nets at this point as it will be useless (any connected
462 // pads will simply drive their existing nets back onto the track segments and vias).
463
464 bool changeLock = m_lockedCbox->Get3StateValue() != wxCHK_UNDETERMINED;
465 bool setLock = m_lockedCbox->Get3StateValue() == wxCHK_CHECKED;
466
467 for( EDA_ITEM* item : m_items )
468 {
469 m_commit.Modify( item );
470
471 switch( item->Type() )
472 {
473 case PCB_TRACE_T:
474 case PCB_ARC_T:
475 {
476 wxASSERT( m_tracks );
477 PCB_TRACK* t = static_cast<PCB_TRACK*>( item );
478
479 if( !m_trackStartX.IsIndeterminate() )
480 t->SetStart( wxPoint( m_trackStartX.GetValue(), t->GetStart().y ) );
481
482 if( !m_trackStartY.IsIndeterminate() )
483 t->SetStart( wxPoint( t->GetStart().x, m_trackStartY.GetValue() ) );
484
485 if( !m_trackEndX.IsIndeterminate() )
486 t->SetEnd( wxPoint( m_trackEndX.GetValue(), t->GetEnd().y ) );
487
488 if( !m_trackEndY.IsIndeterminate() )
489 t->SetEnd( wxPoint( t->GetEnd().x, m_trackEndY.GetValue() ) );
490
491 if( m_trackNetclass->IsChecked() )
492 t->SetWidth( t->GetNetClass()->GetTrackWidth() );
493 else if( !m_trackWidth.IsIndeterminate() )
494 t->SetWidth( m_trackWidth.GetValue() );
495
496 LAYER_NUM layer = m_TrackLayerCtrl->GetLayerSelection();
497
498 if( layer != UNDEFINED_LAYER )
499 t->SetLayer( (PCB_LAYER_ID) layer );
500
501 if( changeLock )
502 t->SetLocked( setLock );
503
504 break;
505 }
506
507 case PCB_VIA_T:
508 {
509 wxASSERT( m_vias );
510 PCB_VIA* v = static_cast<PCB_VIA*>( item );
511
512 if( !m_viaX.IsIndeterminate() )
513 v->SetPosition( wxPoint( m_viaX.GetValue(), v->GetPosition().y ) );
514
515 if( !m_viaY.IsIndeterminate() )
516 v->SetPosition( wxPoint( v->GetPosition().x, m_viaY.GetValue() ) );
517
518 if( m_viaNotFree->Get3StateValue() != wxCHK_UNDETERMINED )
519 v->SetIsFree( !m_viaNotFree->GetValue() );
520
521 switch( m_ViaTypeChoice->GetSelection() )
522 {
523 case 0:
524 v->SetViaType( VIATYPE::THROUGH );
525 v->SanitizeLayers();
526 break;
527 case 1:
528 v->SetViaType( VIATYPE::MICROVIA );
529 break;
530 case 2:
531 v->SetViaType( VIATYPE::BLIND_BURIED );
532 break;
533 default:
534 break;
535 }
536
537 auto startLayer = static_cast<PCB_LAYER_ID>( m_ViaStartLayer->GetLayerSelection() );
538 auto endLayer = static_cast<PCB_LAYER_ID>( m_ViaEndLayer->GetLayerSelection() );
539
540 if (startLayer != UNDEFINED_LAYER )
541 v->SetTopLayer( startLayer );
542
543 if (endLayer != UNDEFINED_LAYER )
544 v->SetBottomLayer( endLayer );
545
546 switch( m_annularRingsCtrl->GetSelection() )
547 {
548 case 0:
549 v->SetRemoveUnconnected( false );
550 break;
551 case 1:
552 v->SetRemoveUnconnected( true );
553 v->SetKeepTopBottom( true );
554 break;
555 case 2:
556 v->SetRemoveUnconnected( true );
557 v->SetKeepTopBottom( false );
558 break;
559 default:
560 break;
561 }
562
563 v->SanitizeLayers();
564
565 if( m_viaNetclass->IsChecked() )
566 {
567 switch( v->GetViaType() )
568 {
569 default:
570 wxFAIL_MSG( "Unhandled via type" );
571 KI_FALLTHROUGH;
572
573 case VIATYPE::THROUGH:
574 case VIATYPE::BLIND_BURIED:
575 v->SetWidth( v->GetNetClass()->GetViaDiameter() );
576 v->SetDrill( v->GetNetClass()->GetViaDrill() );
577 break;
578
579 case VIATYPE::MICROVIA:
580 v->SetWidth( v->GetNetClass()->GetuViaDiameter() );
581 v->SetDrill( v->GetNetClass()->GetuViaDrill() );
582 break;
583 }
584 }
585 else
586 {
587 if( !m_viaDiameter.IsIndeterminate() )
588 v->SetWidth( m_viaDiameter.GetValue() );
589
590 if( !m_viaDrill.IsIndeterminate() )
591 v->SetDrill( m_viaDrill.GetValue() );
592 }
593
594 if( changeLock )
595 v->SetLocked( setLock );
596
597 break;
598 }
599
600 default:
601 wxASSERT( false );
602 break;
603 }
604 }
605
606 m_commit.Push( _( "Edit track/via properties" ) );
607
608 // Pushing the commit will have updated the connectivity so we can now test to see if we
609 // need to update any pad nets.
610
611 auto connectivity = m_frame->GetBoard()->GetConnectivity();
612 int newNetCode = m_netSelector->GetSelectedNetcode();
613 bool updateNets = false;
614 std::vector<PAD*> changingPads;
615
616 if ( !m_netSelector->IsIndeterminate() )
617 {
618 updateNets = true;
619
620 for( EDA_ITEM* item : m_items )
621 {
622 const KICAD_T ourTypes[] = { PCB_TRACE_T, PCB_PAD_T, PCB_VIA_T, PCB_FOOTPRINT_T, EOT };
623 BOARD_CONNECTED_ITEM* boardItem = static_cast<BOARD_CONNECTED_ITEM*>( item );
624 auto connectedItems = connectivity->GetConnectedItems( boardItem, ourTypes, true );
625
626 for ( BOARD_CONNECTED_ITEM* citem : connectedItems )
627 {
628 if( citem->Type() == PCB_PAD_T )
629 {
630 PAD* pad = static_cast<PAD*>( citem );
631
632 if( pad->GetNetCode() != newNetCode && !alg::contains( changingPads, citem ) )
633 changingPads.push_back( pad );
634 }
635 }
636 }
637 }
638
639 if( changingPads.size() && !confirmPadChange( changingPads ) )
640 updateNets = false;
641
642 if( updateNets )
643 {
644 for( EDA_ITEM* item : m_items )
645 {
646 m_commit.Modify( item );
647
648 switch( item->Type() )
649 {
650 case PCB_TRACE_T:
651 case PCB_ARC_T:
652 static_cast<PCB_TRACK*>( item )->SetNetCode( newNetCode );
653 break;
654
655 case PCB_VIA_T:
656 static_cast<PCB_VIA*>( item )->SetNetCode( newNetCode );
657 break;
658
659 default:
660 wxASSERT( false );
661 break;
662 }
663 }
664
665 for( PAD* pad : changingPads )
666 {
667 m_commit.Modify( pad );
668 pad->SetNetCode( newNetCode );
669 }
670
671 m_commit.Push( _( "Updating nets" ) );
672 }
673
674 return true;
675 }
676
677
onViaNotFreeClicked(wxCommandEvent & event)678 void DIALOG_TRACK_VIA_PROPERTIES::onViaNotFreeClicked( wxCommandEvent& event )
679 {
680 m_netSelectorLabel->Enable( !m_viaNotFree->GetValue() );
681 m_netSelector->Enable( !m_viaNotFree->GetValue() );
682 }
683
684
onTrackNetclassCheck(wxCommandEvent & aEvent)685 void DIALOG_TRACK_VIA_PROPERTIES::onTrackNetclassCheck( wxCommandEvent& aEvent )
686 {
687 bool enableNC = aEvent.IsChecked();
688
689 m_DesignRuleWidths->Enable( !enableNC );
690 m_DesignRuleWidthsCtrl->Enable( !enableNC );
691 m_DesignRuleWidthsUnits->Enable( !enableNC );
692
693 m_trackWidth.Enable( !enableNC );
694 }
695
696
onWidthSelect(wxCommandEvent & aEvent)697 void DIALOG_TRACK_VIA_PROPERTIES::onWidthSelect( wxCommandEvent& aEvent )
698 {
699 m_TrackWidthCtrl->ChangeValue( m_DesignRuleWidthsCtrl->GetStringSelection() );
700 m_TrackWidthCtrl->SelectAll();
701 }
702
703
onWidthEdit(wxCommandEvent & aEvent)704 void DIALOG_TRACK_VIA_PROPERTIES::onWidthEdit( wxCommandEvent& aEvent )
705 {
706 m_DesignRuleWidthsCtrl->SetStringSelection( m_TrackWidthCtrl->GetValue() );
707 }
708
709
onViaNetclassCheck(wxCommandEvent & aEvent)710 void DIALOG_TRACK_VIA_PROPERTIES::onViaNetclassCheck( wxCommandEvent& aEvent )
711 {
712 bool enableNC = aEvent.IsChecked();
713
714 m_DesignRuleVias->Enable( !enableNC );
715 m_DesignRuleViasCtrl->Enable( !enableNC );
716 m_DesignRuleViasUnit->Enable( !enableNC );
717
718 m_viaDiameter.Enable( !enableNC );
719 m_viaDrill.Enable( !enableNC );
720 }
721
722
onViaSelect(wxCommandEvent & aEvent)723 void DIALOG_TRACK_VIA_PROPERTIES::onViaSelect( wxCommandEvent& aEvent )
724 {
725 VIA_DIMENSION* viaDimension = static_cast<VIA_DIMENSION*> ( aEvent.GetClientData() );
726
727 m_viaDiameter.ChangeValue( viaDimension->m_Diameter );
728 m_viaDrill.ChangeValue( viaDimension->m_Drill );
729 }
730
731
onViaEdit(wxCommandEvent & aEvent)732 void DIALOG_TRACK_VIA_PROPERTIES::onViaEdit( wxCommandEvent& aEvent )
733 {
734 m_DesignRuleViasCtrl->SetSelection( wxNOT_FOUND );
735
736 if( m_vias )
737 {
738 if( m_ViaTypeChoice->GetSelection() != 0 ) // check if selected type isn't through.
739 {
740 m_ViaStartLayer->Enable();
741 m_ViaEndLayer->Enable();
742 }
743 else
744 {
745 m_ViaStartLayer->SetLayerSelection( F_Cu );
746 m_ViaEndLayer->SetLayerSelection( B_Cu );
747
748 m_ViaStartLayer->Enable( false );
749 m_ViaEndLayer->Enable( false );
750 }
751 }
752 }
753