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