KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_track_via_properties.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) 2015 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Maciej Suminski <[email protected]>
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>
31#include <footprint.h>
32#include <pad.h>
33#include <pcb_track.h>
34#include <confirm.h>
35#include <kidialog.h>
37#include <board_commit.h>
38
39
41 const PCB_SELECTION& aItems ) :
43 m_frame( aParent ),
44 m_items( aItems ),
45 m_trackStartX( aParent, m_TrackStartXLabel, m_TrackStartXCtrl, nullptr ),
46 m_trackStartY( aParent, m_TrackStartYLabel, m_TrackStartYCtrl, m_TrackStartYUnit ),
47 m_trackEndX( aParent, m_TrackEndXLabel, m_TrackEndXCtrl, nullptr ),
48 m_trackEndY( aParent, m_TrackEndYLabel, m_TrackEndYCtrl, m_TrackEndYUnit ),
49 m_trackWidth( aParent, m_TrackWidthLabel, m_TrackWidthCtrl, m_TrackWidthUnit ),
50 m_trackMaskMargin( aParent, m_trackMaskMarginLabel, m_trackMaskMarginCtrl, m_trackMaskMarginUnit ),
51 m_viaX( aParent, m_ViaXLabel, m_ViaXCtrl, nullptr ),
52 m_viaY( aParent, m_ViaYLabel, m_ViaYCtrl, m_ViaYUnit ),
53 m_viaDiameter( aParent, m_ViaDiameterLabel, m_ViaDiameterCtrl, m_ViaDiameterUnit ),
54 m_viaDrill( aParent, m_ViaDrillLabel, m_ViaDrillCtrl, m_ViaDrillUnit ),
55 m_teardropHDPercent( aParent, m_stHDRatio, m_tcHDRatio, m_stHDRatioUnits ),
56 m_teardropLenPercent( aParent, m_stLenPercentLabel, m_tcLenPercent, nullptr ),
57 m_teardropMaxLen( aParent, m_stMaxLen, m_tcTdMaxLen, m_stMaxLenUnits ),
58 m_teardropWidthPercent( aParent, m_stWidthPercentLabel, m_tcWidthPercent, nullptr ),
59 m_teardropMaxWidth( aParent, m_stMaxWidthLabel, m_tcMaxWidth, m_stMaxWidthUnits ),
60 m_tracks( false ),
61 m_vias( false ),
62 m_editLayer( PADSTACK::ALL_LAYERS )
63{
65
66 wxASSERT( !m_items.Empty() );
67
68 m_legacyTeardropsIcon->SetBitmap( KiBitmapBundle( BITMAPS::dialog_warning ) );
70
71 m_bitmapTeardrop->SetBitmap( KiBitmapBundle( BITMAPS::teardrop_sizes ) );
72
73 m_teardropHDPercent.SetUnits( EDA_UNITS::PERCENT );
74 m_teardropLenPercent.SetUnits( EDA_UNITS::PERCENT );
75 m_teardropWidthPercent.SetUnits( EDA_UNITS::PERCENT );
76
77 m_minTrackWidthHint->SetFont( KIUI::GetInfoFont( this ).Italic() );
78
79 // Configure display origin transforms
86
87 VIATYPE viaType = VIATYPE::NOT_DEFINED;
88
93
98
101 m_ViaEndLayer->SetBoardFrame( aParent );
103
104 m_btnLinkTenting->SetBitmap( KiBitmapBundle( BITMAPS::edit_cmp_symb_links ) );
105 m_btnLinkTenting->SetValue( true );
106 m_tentingBackCtrl->Disable();
107 m_tentingBackLabel->Disable();
108
109 wxFont infoFont = KIUI::GetInfoFont( this );
110 m_techLayersLabel->SetFont( infoFont );
111
112 bool nets = false;
113 int net = 0;
114 bool hasLocked = false;
115 bool hasUnlocked = false;
116
117 // Start and end layers of vias
118 // if at least 2 vias do not have the same start or the same end layer
119 // the layers will be set as undefined
120 int selection_first_layer = -1;
121 int selection_last_layer = -1;
122
123 // The selection layer for tracks
124 int track_selection_layer = -1;
125
126 auto getAnnularRingSelection =
127 []( const PCB_VIA* via ) -> int
128 {
129 switch( via->Padstack().UnconnectedLayerMode() )
130 {
131 default:
135 }
136 };
137
138 auto getTentingSelection =
139 []( const PCB_VIA* via, PCB_LAYER_ID aLayer ) -> int
140 {
141 std::optional<bool> tentingOverride = via->Padstack().IsTented( aLayer );
142
143 if( tentingOverride.has_value() )
144 {
145 if( *tentingOverride )
146 return 1; // Tented
147
148 return 2; // Not tented
149 }
150
151 return 0; // From design rules
152 };
153
154 // Look for values that are common for every item that is selected
155 for( EDA_ITEM* item : m_items )
156 {
157 if( !nets )
158 {
159 net = static_cast<BOARD_CONNECTED_ITEM*>( item )->GetNetCode();
160 nets = true;
161 }
162 else if( net != static_cast<BOARD_CONNECTED_ITEM*>( item )->GetNetCode() )
163 {
164 net = -1;
165 }
166
167 switch( item->Type() )
168 {
169 case PCB_TRACE_T:
170 case PCB_ARC_T:
171 {
172 const PCB_TRACK* t = static_cast<const PCB_TRACK*>( item );
173
174 if( !m_tracks ) // first track in the list
175 {
181 track_selection_layer = t->GetLayer();
182 m_trackHasSolderMask->SetValue ( t->HasSolderMask() );
183
184 if( t->GetLocalSolderMaskMargin().has_value() )
186 else
187 m_trackMaskMargin.SetValue( wxEmptyString );
188
189 m_tracks = true;
190 }
191 else // check if values are the same for every selected track
192 {
193 if( m_trackStartX.GetValue() != t->GetStartX() )
195
196 if( m_trackStartY.GetValue() != t->GetStartY() )
198
199 if( m_trackEndX.GetValue() != t->GetEndX() )
201
202 if( m_trackEndY.GetValue() != t->GetEndY() )
204
205 if( m_trackWidth.GetValue() != t->GetWidth() )
207
208 if( track_selection_layer != t->GetLayer() )
209 track_selection_layer = UNDEFINED_LAYER;
210
211 if( m_trackHasSolderMask->GetValue() != t->HasSolderMask() )
212 m_trackHasSolderMask->Set3StateValue( wxCHK_UNDETERMINED );
213
216 }
217
218 if( t->IsLocked() )
219 hasLocked = true;
220 else
221 hasUnlocked = true;
222
223 break;
224 }
225
226 case PCB_VIA_T:
227 {
228 PCB_VIA* v = static_cast<PCB_VIA*>( item );
229
230 if( !m_vias ) // first via in the list
231 {
234 m_viaStack = std::make_unique<PADSTACK>( v->Padstack() );
237 m_vias = true;
238 viaType = v->GetViaType();
239 m_viaNotFree->SetValue( !v->GetIsFree() );
240 m_annularRingsCtrl->SetSelection( getAnnularRingSelection( v ) );
241
242 m_tentingFrontCtrl->SetSelection( getTentingSelection( v, F_Mask ) );
243 m_tentingBackCtrl->SetSelection( getTentingSelection( v, B_Mask ) );
244
245 bool link = m_tentingFrontCtrl->GetSelection()
246 == m_tentingBackCtrl->GetSelection();
247
248 m_btnLinkTenting->SetValue( link );
249 m_tentingBackCtrl->Enable( !link );
250 m_tentingBackLabel->Enable( !link );
251
252 selection_first_layer = v->TopLayer();
253 selection_last_layer = v->BottomLayer();
254
255 m_cbTeardrops->SetValue( v->GetTeardropParams().m_Enabled );
263 }
264 else // check if values are the same for every selected via
265 {
266 if( m_viaX.GetValue() != v->GetPosition().x )
268
269 if( m_viaY.GetValue() != v->GetPosition().y )
271
274
275 if( m_viaDrill.GetValue() != v->GetDrillValue() )
277
278 if( viaType != v->GetViaType() )
279 viaType = VIATYPE::NOT_DEFINED;
280
281 if( v->GetIsFree() != !m_viaNotFree->GetValue() )
282 m_viaNotFree->Set3StateValue( wxCHK_UNDETERMINED );
283
284 if( selection_first_layer != v->TopLayer() )
285 selection_first_layer = UNDEFINED_LAYER;
286
287 if( selection_last_layer != v->BottomLayer() )
288 selection_last_layer = UNDEFINED_LAYER;
289
290 if( m_annularRingsCtrl->GetSelection() != getAnnularRingSelection( v ) )
291 {
292 if( m_annularRingsCtrl->GetStrings().size() < 4 )
294
295 m_annularRingsCtrl->SetSelection( 3 );
296 }
297
298 if( m_cbTeardrops->GetValue() != v->GetTeardropParams().m_Enabled )
299 m_cbTeardrops->Set3StateValue( wxCHK_UNDETERMINED );
300
302 m_cbTeardropsUseNextTrack->Set3StateValue( wxCHK_UNDETERMINED );
303
306
309
312
315
318 }
319
320 if( v->IsLocked() )
321 hasLocked = true;
322 else
323 hasUnlocked = true;
324
325 break;
326 }
327
328 default:
329 {
330 wxASSERT( false );
331 break;
332 }
333 }
334 }
335
336 if( m_tracks )
337 {
338 // Set the track layer selection state:
339 if( track_selection_layer == UNDEFINED_LAYER )
340 {
343 }
344
345 m_TrackLayerCtrl->SetLayerSelection( track_selection_layer );
346 }
347
348 // Set the vias layers selections state:
349 if( m_vias )
350 {
351 if( selection_first_layer == UNDEFINED_LAYER )
352 {
355 }
356
357 m_ViaStartLayer->SetLayerSelection( selection_first_layer );
358
359 if( selection_last_layer == UNDEFINED_LAYER )
360 {
363 }
364
365 m_ViaEndLayer->SetLayerSelection( selection_last_layer );
366 }
367
368 m_netSelector->SetBoard( aParent->GetBoard() );
369 m_netSelector->SetNetInfo( &aParent->GetBoard()->GetNetInfo() );
370
371 if ( net >= 0 )
372 {
374 }
375 else
376 {
379 }
380
381 wxASSERT( m_tracks || m_vias );
382
383 if( m_vias )
384 {
385 if( m_viaNotFree->GetValue() && !m_tracks )
386 {
387 // Disable net selector to re-inforce meaning of "Automatically update via nets",
388 // but not when tracks are also selected as then things get harder if you want to
389 // update all the nets to match.
390 m_netSelectorLabel->Disable();
391 m_netSelector->Disable();
392 }
393
394 int viaSelection = wxNOT_FOUND;
395
396 // 0 is the netclass place-holder
397 for( unsigned ii = 1; ii < aParent->GetDesignSettings().m_ViasDimensionsList.size(); ii++ )
398 {
399 VIA_DIMENSION* viaDimension = &aParent->GetDesignSettings().m_ViasDimensionsList[ii];
400 wxString msg = m_frame->StringFromValue( viaDimension->m_Diameter )
401 + wxT( " / " )
402 + m_frame->StringFromValue( viaDimension->m_Drill );
403 m_predefinedViaSizesCtrl->Append( msg, viaDimension );
404
405 if( viaSelection == wxNOT_FOUND
406 && m_viaDiameter.GetValue() == viaDimension->m_Diameter
407 && m_viaDrill.GetValue() == viaDimension->m_Drill )
408 {
409 viaSelection = ii - 1;
410 }
411 }
412
413 m_predefinedViaSizesCtrl->SetSelection( viaSelection );
415
416 m_ViaTypeChoice->Enable();
417
418 switch( viaType )
419 {
420 case VIATYPE::THROUGH: m_ViaTypeChoice->SetSelection( 0 ); break;
421 case VIATYPE::MICROVIA: m_ViaTypeChoice->SetSelection( 1 ); break;
422 case VIATYPE::BLIND_BURIED: m_ViaTypeChoice->SetSelection( 2 ); break;
423 case VIATYPE::NOT_DEFINED: m_ViaTypeChoice->SetSelection( wxNOT_FOUND ); break;
424 }
425
426 m_ViaStartLayer->Enable( viaType != VIATYPE::THROUGH );
427 m_ViaEndLayer->Enable( viaType != VIATYPE::THROUGH );
428
429 m_annularRingsLabel->Show( getLayerDepth() > 1 );
430 m_annularRingsCtrl->Show( getLayerDepth() > 1 );
431
433 }
434 else
435 {
436 m_viaNotFree->Hide();
437 m_MainSizer->Hide( m_sbViaSizer, true );
438 }
439
440 if( m_tracks )
441 {
442 int widthSelection = wxNOT_FOUND;
443
444 // 0 is the netclass place-holder
445 for( unsigned ii = 1; ii < aParent->GetDesignSettings().m_TrackWidthList.size(); ii++ )
446 {
447 int width = aParent->GetDesignSettings().m_TrackWidthList[ii];
448 wxString msg = m_frame->StringFromValue( width );
449 m_predefinedTrackWidthsCtrl->Append( msg );
450
451 if( widthSelection == wxNOT_FOUND && m_trackWidth.GetValue() == width )
452 widthSelection = ii - 1;
453 }
454
455 m_predefinedTrackWidthsCtrl->SetSelection( widthSelection );
457
458 wxCommandEvent event;
459 onTrackEdit( event );
460 }
461 else
462 {
463 m_MainSizer->Hide( m_sbTrackSizer, true );
464 }
465
466 if( hasLocked && hasUnlocked )
467 m_lockedCbox->Set3StateValue( wxCHK_UNDETERMINED );
468 else if( hasLocked )
469 m_lockedCbox->Set3StateValue( wxCHK_CHECKED );
470 else
471 m_lockedCbox->Set3StateValue( wxCHK_UNCHECKED );
472
473 if( m_tracks )
475 else if( m_netSelector->IsEnabled() )
477 else
479
481
482 m_frame->Bind( EDA_EVT_UNITS_CHANGED, &DIALOG_TRACK_VIA_PROPERTIES::onUnitsChanged, this );
483 m_netSelector->Bind( FILTERED_ITEM_SELECTED, &DIALOG_TRACK_VIA_PROPERTIES::onNetSelector, this );
484
485 // Now all widgets have the size fixed, call FinishDialogSettings
487}
488
489
491{
492 m_frame->Unbind( EDA_EVT_UNITS_CHANGED, &DIALOG_TRACK_VIA_PROPERTIES::onUnitsChanged, this );
493}
494
495
497{
498 if( m_vias )
499 {
500 int viaSel = m_predefinedViaSizesCtrl->GetSelection();
501
503
504 // 0 is the netclass place-holder
505 for( unsigned ii = 1; ii < m_frame->GetDesignSettings().m_ViasDimensionsList.size(); ii++ )
506 {
508 wxString msg = m_frame->StringFromValue( viaDimension->m_Diameter )
509 + wxT( " / " )
510 + m_frame->StringFromValue( viaDimension->m_Drill );
511 m_predefinedViaSizesCtrl->Append( msg, viaDimension );
512 }
513
514 m_predefinedViaSizesCtrl->SetSelection( viaSel );
516 }
517
518 if( m_tracks )
519 {
520 int trackSel = m_predefinedTrackWidthsCtrl->GetSelection();
521
523
524 // 0 is the netclass place-holder
525 for( unsigned ii = 1; ii < m_frame->GetDesignSettings().m_TrackWidthList.size(); ii++ )
526 {
527 int width = m_frame->GetDesignSettings().m_TrackWidthList[ii];
528 wxString msg = m_frame->StringFromValue( width );
529 m_predefinedTrackWidthsCtrl->Append( msg );
530 }
531
532 m_predefinedTrackWidthsCtrl->SetSelection( trackSel );
534 }
535
536 aEvent.Skip();
537}
538
539
540bool DIALOG_TRACK_VIA_PROPERTIES::confirmPadChange( const std::vector<PAD*>& changingPads )
541{
542 wxString msg;
543
544 if( changingPads.size() == 1 )
545 {
546 PAD* pad = *changingPads.begin();
547 msg.Printf( _( "Changing the net will also update %s pad %s to %s." ),
548 pad->GetParentFootprint()->GetReference(),
549 pad->GetNumber(),
550 m_netSelector->GetValue() );
551 }
552 else if( changingPads.size() == 2 )
553 {
554 PAD* pad1 = *changingPads.begin();
555 PAD* pad2 = *( ++changingPads.begin() );
556 msg.Printf( _( "Changing the net will also update %s pad %s and %s pad %s to %s." ),
558 pad1->GetNumber(),
560 pad2->GetNumber(),
561 m_netSelector->GetValue() );
562 }
563 else
564 {
565 msg.Printf( _( "Changing the net will also update %lu connected pads to %s." ),
566 static_cast<unsigned long>( changingPads.size() ),
567 m_netSelector->GetValue() );
568 }
569
570 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
571 dlg.SetOKCancelLabels( _( "Change Nets" ), _( "Leave Nets Unchanged" ) );
572 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
573
574 return dlg.ShowModal() == wxID_OK;
575}
576
577
579{
580 // Check for malformed data ONLY; design rules and constraints are the business of DRC.
581
582 if( m_vias )
583 {
584 // TODO: This needs to move into the via class, not the dialog
585
587 || !m_viaDrill.Validate( GEOMETRY_MIN_SIZE, INT_MAX ) )
588 {
589 return false;
590 }
591
592 if( m_ViaDiameterCtrl->IsEnabled() && !m_viaDiameter.IsIndeterminate()
593 && m_ViaDrillCtrl->IsEnabled() && !m_viaDrill.IsIndeterminate()
595 {
596 DisplayError( GetParent(), _( "Via hole size must be smaller than via diameter" ) );
597 m_ViaDrillCtrl->SelectAll();
598 m_ViaDrillCtrl->SetFocus();
599 return false;
600 }
601
604 {
605 DisplayError( GetParent(), _( "Via start layer and end layer cannot be the same" ) );
606 return false;
607 }
608
610 {
611 int diameter = m_viaDiameter.GetValue();
612 m_viaStack->SetSize( { diameter, diameter }, m_editLayer );
613 }
614 }
615
616 if( m_tracks )
617 {
618 if( !m_trackWidth.Validate( GEOMETRY_MIN_SIZE, INT_MAX ) )
619 return false;
620 }
621
622 // If we survived that, then save the changes:
623 //
624 // We don't bother with updating the nets at this point as it will be useless (any connected
625 // pads will simply drive their existing nets back onto the track segments and vias).
626
627 BOARD_COMMIT commit( m_frame );
628 bool changeLock = m_lockedCbox->Get3StateValue() != wxCHK_UNDETERMINED;
629 bool setLock = m_lockedCbox->Get3StateValue() == wxCHK_CHECKED;
630
631 for( EDA_ITEM* item : m_items )
632 {
633 commit.Modify( item );
634
635 switch( item->Type() )
636 {
637 case PCB_TRACE_T:
638 case PCB_ARC_T:
639 {
640 wxASSERT( m_tracks );
641 PCB_TRACK* t = static_cast<PCB_TRACK*>( item );
642
645
648
651
654
657
658 int layer = m_TrackLayerCtrl->GetLayerSelection();
659
660 if( layer != UNDEFINED_LAYER )
661 t->SetLayer( (PCB_LAYER_ID) layer );
662
663 if ( m_trackHasSolderMask->Get3StateValue() != wxCHK_UNDETERMINED )
664 t->SetHasSolderMask( m_trackHasSolderMask->GetValue() );
665
667 {
670 else
672 }
673
674 if( changeLock )
675 t->SetLocked( setLock );
676
677 break;
678 }
679
680 case PCB_VIA_T:
681 {
682 wxASSERT( m_vias );
683 PCB_VIA* v = static_cast<PCB_VIA*>( item );
684
685 if( !m_viaX.IsIndeterminate() )
687
688 if( !m_viaY.IsIndeterminate() )
690
691 if( m_viaNotFree->Get3StateValue() != wxCHK_UNDETERMINED )
692 v->SetIsFree( !m_viaNotFree->GetValue() );
693
695 v->SetPadstack( *m_viaStack );
696
697 switch( m_ViaTypeChoice->GetSelection() )
698 {
699 case 0:
700 v->SetViaType( VIATYPE::THROUGH );
701 break;
702 case 1:
703 v->SetViaType( VIATYPE::MICROVIA );
704 break;
705 case 2:
706 v->SetViaType( VIATYPE::BLIND_BURIED );
707 break;
708 default:
709 break;
710 }
711
712 PCB_LAYER_ID startLayer = static_cast<PCB_LAYER_ID>( m_ViaStartLayer->GetLayerSelection() );
713 PCB_LAYER_ID endLayer = static_cast<PCB_LAYER_ID>( m_ViaEndLayer->GetLayerSelection() );
714
715 if( startLayer != UNDEFINED_LAYER )
716 {
717 m_viaStack->Drill().start = startLayer;
718 v->SetTopLayer( startLayer );
719 }
720
721 if( endLayer != UNDEFINED_LAYER )
722 {
723 m_viaStack->Drill().end = endLayer;
724 v->SetBottomLayer( endLayer );
725 }
726
727 v->SanitizeLayers();
728
729 switch( m_annularRingsCtrl->GetSelection() )
730 {
731 case 0:
734 break;
735 case 1:
738 break;
739 case 2:
742 break;
743 default:
744 break;
745 }
746
747 switch( m_tentingFrontCtrl->GetSelection() )
748 {
749 default:
750 case 0: v->Padstack().FrontOuterLayers().has_solder_mask.reset(); break;
751 case 1: v->Padstack().FrontOuterLayers().has_solder_mask = true; break;
752 case 2: v->Padstack().FrontOuterLayers().has_solder_mask = false; break;
753 }
754
755 switch( m_tentingBackCtrl->GetSelection() )
756 {
757 default:
758 case 0: v->Padstack().BackOuterLayers().has_solder_mask.reset(); break;
759 case 1: v->Padstack().BackOuterLayers().has_solder_mask = true; break;
760 case 2: v->Padstack().BackOuterLayers().has_solder_mask = false; break;
761 }
762
765
766 TEARDROP_PARAMETERS* targetParams = &v->GetTeardropParams();
767
768 if( m_cbTeardrops->Get3StateValue() != wxCHK_UNDETERMINED )
769 targetParams->m_Enabled = m_cbTeardrops->GetValue();
770
771 if( m_cbTeardropsUseNextTrack->Get3StateValue() != wxCHK_UNDETERMINED )
772 targetParams->m_AllowUseTwoTracks = m_cbTeardropsUseNextTrack->GetValue();
773
775 targetParams->m_TdMaxLen = m_teardropMaxLen.GetIntValue();
776
779
781 targetParams->m_BestLengthRatio = m_teardropLenPercent.GetDoubleValue() / 100.0;
782
784 targetParams->m_BestWidthRatio =
786
789
790 if( m_curvedEdges->Get3StateValue() != wxCHK_UNDETERMINED )
791 targetParams->m_CurvedEdges = m_curvedEdges->GetValue();
792
793 if( changeLock )
794 v->SetLocked( setLock );
795
796 break;
797 }
798
799 default:
800 wxASSERT( false );
801 break;
802 }
803 }
804
805 commit.Push( _( "Edit Track/Via Properties" ) );
806
807 // Pushing the commit will have updated the connectivity so we can now test to see if we
808 // need to update any pad nets.
809
810 auto connectivity = m_frame->GetBoard()->GetConnectivity();
811 int newNetCode = m_netSelector->GetSelectedNetcode();
812 bool updateNets = false;
813 std::vector<PAD*> changingPads;
814
815 if ( !m_netSelector->IsIndeterminate() )
816 {
817 updateNets = true;
818
819 for( EDA_ITEM* item : m_items )
820 {
821 BOARD_CONNECTED_ITEM* boardItem = static_cast<BOARD_CONNECTED_ITEM*>( item );
822 auto connectedItems = connectivity->GetConnectedItems( boardItem,
824
825 for ( BOARD_CONNECTED_ITEM* citem : connectedItems )
826 {
827 if( citem->Type() == PCB_PAD_T )
828 {
829 PAD* pad = static_cast<PAD*>( citem );
830
831 if( pad->GetNetCode() != newNetCode && !alg::contains( changingPads, citem ) )
832 changingPads.push_back( pad );
833 }
834 }
835 }
836 }
837
838 if( changingPads.size() && !confirmPadChange( changingPads ) )
839 updateNets = false;
840
841 if( updateNets )
842 {
843 for( EDA_ITEM* item : m_items )
844 {
845 commit.Modify( item );
846
847 switch( item->Type() )
848 {
849 case PCB_TRACE_T:
850 case PCB_ARC_T:
851 static_cast<PCB_TRACK*>( item )->SetNetCode( newNetCode );
852 break;
853
854 case PCB_VIA_T:
855 static_cast<PCB_VIA*>( item )->SetNetCode( newNetCode );
856 break;
857
858 default:
859 wxASSERT( false );
860 break;
861 }
862 }
863
864 for( PAD* pad : changingPads )
865 {
866 commit.Modify( pad );
867 pad->SetNetCode( newNetCode );
868 }
869
870 commit.Push( _( "Update Nets" ) );
871 }
872
873 return true;
874}
875
876
877void DIALOG_TRACK_VIA_PROPERTIES::onNetSelector( wxCommandEvent& aEvent )
878{
879 m_viaNotFree->SetValue( false );
880}
881
882
884{
885 if( !m_tracks )
886 {
887 m_netSelectorLabel->Enable( !m_viaNotFree->GetValue() );
888 m_netSelector->Enable( !m_viaNotFree->GetValue() );
889 }
890}
891
892
893void DIALOG_TRACK_VIA_PROPERTIES::onWidthSelect( wxCommandEvent& aEvent )
894{
895 m_TrackWidthCtrl->ChangeValue( m_predefinedTrackWidthsCtrl->GetStringSelection() );
896 m_TrackWidthCtrl->SelectAll();
897}
898
899
900void DIALOG_TRACK_VIA_PROPERTIES::onWidthEdit( wxCommandEvent& aEvent )
901{
902 m_predefinedTrackWidthsCtrl->SetStringSelection( m_TrackWidthCtrl->GetValue() );
903}
904
905
906void DIALOG_TRACK_VIA_PROPERTIES::onViaSelect( wxCommandEvent& aEvent )
907{
908 VIA_DIMENSION* viaDimension = static_cast<VIA_DIMENSION*> ( aEvent.GetClientData() );
909
910 m_viaDiameter.ChangeValue( viaDimension->m_Diameter );
911 m_viaDrill.ChangeValue( viaDimension->m_Drill );
912}
913
914
916{
917 wxCHECK_MSG( m_viaStack, /* void */, "Expected valid via stack in onPadstackModeChanged" );
918
919 switch( m_cbPadstackMode->GetSelection() )
920 {
921 default:
922 case 0: m_viaStack->SetMode( PADSTACK::MODE::NORMAL ); break;
923 case 1: m_viaStack->SetMode( PADSTACK::MODE::FRONT_INNER_BACK ); break;
924 case 2: m_viaStack->SetMode( PADSTACK::MODE::CUSTOM ); break;
925 }
926
928}
929
930
932{
933 wxCHECK_MSG( m_viaStack, /* void */, "Expected valid via stack in onEditLayerChanged" );
934
935 // Save data from the previous layer
937 {
938 int diameter = m_viaDiameter.GetValue();
939 m_viaStack->SetSize( { diameter, diameter }, m_editLayer );
940 }
941
942 switch( m_viaStack->Mode() )
943 {
944 default:
947 break;
948
950 switch( m_cbEditLayer->GetSelection() )
951 {
952 default:
953 case 0: m_editLayer = F_Cu; break;
954 case 1: m_editLayer = PADSTACK::INNER_LAYERS; break;
955 case 2: m_editLayer = B_Cu; break;
956 }
957 break;
958
960 {
961 int layer = m_cbEditLayer->GetSelection();
962
963 if( layer < 0 )
964 layer = 0;
965
966 if( m_editLayerCtrlMap.contains( layer ) )
967 m_editLayer = m_editLayerCtrlMap.at( layer );
968 else
970 }
971 }
972
973 // Load controls with the current layer
975}
976
977
979{
980 // NOTE: synchronize changes here with DIALOG_PAD_PROPERTIES::afterPadstackModeChanged
981
982 wxCHECK_MSG( m_viaStack, /* void */, "Expected valid via stack in afterPadstackModeChanged" );
983 m_cbEditLayer->Clear();
984
985 BOARD* board = m_frame->GetBoard();
986
987 switch( m_viaStack->Mode() )
988 {
990 m_cbPadstackMode->SetSelection( 0 );
991 m_cbEditLayer->Append( _( "All layers" ) );
992 m_cbEditLayer->Disable();
995 break;
996
998 {
999 m_cbPadstackMode->SetSelection( 1 );
1000 m_cbEditLayer->Enable();
1001
1002 std::vector choices = {
1003 board->GetLayerName( F_Cu ),
1004 _( "Inner Layers" ),
1005 board->GetLayerName( B_Cu )
1006 };
1007
1008 m_cbEditLayer->Append( choices );
1009
1011 { 0, F_Cu },
1013 { 2, B_Cu }
1014 };
1015
1016 if( m_editLayer != F_Cu && m_editLayer != B_Cu )
1018
1019 break;
1020 }
1021
1023 {
1024 m_cbPadstackMode->SetSelection( 2 );
1025 m_cbEditLayer->Enable();
1026 LSET layers = LSET::AllCuMask() & board->GetEnabledLayers();
1027
1028 for( PCB_LAYER_ID layer : layers.UIOrder() )
1029 {
1030 int idx = m_cbEditLayer->Append( board->GetLayerName( layer ) );
1031 m_editLayerCtrlMap[idx] = layer;
1032 }
1033
1034 break;
1035 }
1036 }
1037
1038 for( const auto& [idx, layer] : m_editLayerCtrlMap )
1039 {
1040 if( layer == m_editLayer )
1041 {
1042 m_cbEditLayer->SetSelection( idx );
1043 break;
1044 }
1045 }
1046}
1047
1048
1050{
1051 int viaType = m_ViaTypeChoice->GetSelection();
1052
1053 if( viaType <= 0 )
1054 return m_frame->GetBoard()->GetCopperLayerCount() - 1;
1055
1056 int startLayer = m_ViaStartLayer->GetLayerSelection();
1057 int endLayer = m_ViaEndLayer->GetLayerSelection();
1058
1059 if( startLayer < 0 || endLayer < 0 )
1060 return m_frame->GetBoard()->GetCopperLayerCount() - 1;
1061 else
1062 return m_frame->GetBoard()->LayerDepth( ToLAYER_ID( startLayer ), ToLAYER_ID( endLayer ) );
1063}
1064
1065
1066void DIALOG_TRACK_VIA_PROPERTIES::onViaEdit( wxCommandEvent& aEvent )
1067{
1068 m_predefinedViaSizesCtrl->SetSelection( wxNOT_FOUND );
1069
1070 if( m_vias )
1071 {
1072 if( m_ViaTypeChoice->GetSelection() != 0 ) // check if selected type isn't through.
1073 {
1074 m_ViaStartLayer->Enable();
1075 m_ViaEndLayer->Enable();
1076 }
1077 else
1078 {
1081
1082 m_ViaStartLayer->Enable( false );
1083 m_ViaEndLayer->Enable( false );
1084 }
1085
1086 m_annularRingsLabel->Show( getLayerDepth() > 1 );
1087 m_annularRingsCtrl->Show( getLayerDepth() > 1 );
1088 }
1089}
1090
1091
1093{
1094 if( m_btnLinkTenting->GetValue() )
1095 m_tentingBackCtrl->SetSelection( m_tentingFrontCtrl->GetSelection() );
1096
1097 event.Skip();
1098}
1099
1100
1102{
1103 bool link = m_btnLinkTenting->GetValue();
1104
1105 m_tentingBackCtrl->Enable( !link );
1106 m_tentingBackLabel->Enable( !link );
1107
1108 if( link )
1109 m_tentingBackCtrl->SetSelection( m_tentingFrontCtrl->GetSelection() );
1110
1111 event.Skip();
1112}
1113
1114
1115void DIALOG_TRACK_VIA_PROPERTIES::onTrackEdit( wxCommandEvent& aEvent )
1116{
1117 bool externalCuLayer = m_TrackLayerCtrl->GetLayerSelection() == F_Cu
1119
1120 m_techLayersLabel->Enable( externalCuLayer );
1121 m_trackHasSolderMask->Enable( externalCuLayer );
1122
1123 bool showMaskMargin = externalCuLayer && m_trackHasSolderMask->GetValue();
1124
1125 m_trackMaskMarginCtrl->Enable( showMaskMargin );
1126 m_trackMaskMarginLabel->Enable( showMaskMargin );
1127 m_trackMaskMarginUnit->Enable( showMaskMargin );
1128}
1129
1130
1132{
1133 event.Enable( !m_frame->GetBoard()->LegacyTeardrops() );
1134}
1135
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap)
Definition: bitmap.cpp:110
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
TEARDROP_PARAMETERS & GetTeardropParams()
std::vector< int > m_TrackWidthList
std::vector< VIA_DIMENSION > m_ViasDimensionsList
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:239
virtual void SetLocked(bool aLocked)
Definition: board_item.h:330
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:290
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:298
virtual bool IsLocked() const
Definition: board_item.cpp:75
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:295
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:879
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:820
int GetCopperLayerCount() const
Definition: board.cpp:783
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:616
int LayerDepth(PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer) const
Definition: board.cpp:808
bool LegacyTeardrops() const
Definition: board.h:1269
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Modify a given item in the model.
Definition: commit.h:108
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:102
void SetupStandardButtons(std::map< int, wxString > aLabels={})
bool m_useCalculatedSize
Definition: dialog_shim.h:234
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
Class DIALOG_TRACK_VIA_PROPERTIES_BASE.
void onWidthEdit(wxCommandEvent &aEvent) override
void onUnitsChanged(wxCommandEvent &aEvent)
void onNetSelector(wxCommandEvent &aEvent)
void onTentingLinkToggle(wxCommandEvent &event) override
void onWidthSelect(wxCommandEvent &aEvent) override
void onTeardropsUpdateUi(wxUpdateUIEvent &event) override
void onPadstackModeChanged(wxCommandEvent &aEvent) override
void onViaEdit(wxCommandEvent &aEvent) override
bool confirmPadChange(const std::vector< PAD * > &connectedPads)
std::map< int, PCB_LAYER_ID > m_editLayerCtrlMap
void onFrontTentingChanged(wxCommandEvent &event) override
PCB_LAYER_ID m_editLayer
The currently-shown copper layer of the edited via(s)
void onViaSelect(wxCommandEvent &aEvent) override
void onEditLayerChanged(wxCommandEvent &aEvent) override
void onViaNotFreeClicked(wxCommandEvent &aEvent) override
std::unique_ptr< PADSTACK > m_viaStack
Temporary padstack of the edited via(s)
DIALOG_TRACK_VIA_PROPERTIES(PCB_BASE_FRAME *aParent, const PCB_SELECTION &aItems)
void onTrackEdit(wxCommandEvent &aEvent) override
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:89
const wxString & GetReference() const
Definition: footprint.h:620
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: kidialog.h:43
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox.
Definition: kidialog.cpp:51
bool SetOKCancelLabels(const ButtonLabel &ok, const ButtonLabel &cancel) override
Definition: kidialog.h:53
int ShowModal() override
Definition: kidialog.cpp:95
int SetLayerSelection(int layer)
bool SetLayersHotkeys(bool value)
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:37
LSEQ UIOrder() const
Return the copper, technical and user layers in the order shown in layer widget.
Definition: lset.cpp:699
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition: lset.cpp:575
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:564
void SetNetInfo(const NETINFO_LIST *aNetInfoList)
void SetBoard(BOARD *aBoard)
void SetIndeterminateString(const wxString &aString)
void SetSelectedNetcode(int aNetcode)
void SetIndeterminate()
A PADSTACK defines the characteristics of a single or multi-layer pad, in the IPC sense of the word.
Definition: padstack.h:124
MASK_LAYER_PROPS & FrontOuterLayers()
Definition: padstack.h:312
void SetUnconnectedLayerMode(UNCONNECTED_LAYER_MODE aMode)
Definition: padstack.h:307
@ NORMAL
Shape is the same on all layers.
@ CUSTOM
Shapes can be defined on arbitrary layers.
@ FRONT_INNER_BACK
Up to three shapes can be defined (F_Cu, inner copper layers, B_Cu)
MASK_LAYER_PROPS & BackOuterLayers()
Definition: padstack.h:315
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition: padstack.h:144
static constexpr PCB_LAYER_ID INNER_LAYERS
! The layer identifier to use for "inner layers" on top/inner/bottom padstacks
Definition: padstack.h:147
Definition: pad.h:54
const wxString & GetNumber() const
Definition: pad.h:134
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
BOARD * GetBoard() const
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Return the BOARD_DESIGN_SETTINGS for the open project.
void SetBoardFrame(PCB_BASE_FRAME *aFrame)
void SetNotAllowedLayerSet(LSET aMask)
void SetUndefinedLayerName(const wxString &aName)
void SetEndY(int aY)
Definition: pcb_track.h:131
void SetHasSolderMask(bool aVal)
Definition: pcb_track.h:145
bool HasSolderMask() const
Definition: pcb_track.h:146
int GetStartY() const
Definition: pcb_track.h:128
int GetEndX() const
Definition: pcb_track.h:133
void SetLocalSolderMaskMargin(std::optional< int > aMargin)
Definition: pcb_track.h:148
std::optional< int > GetLocalSolderMaskMargin() const
Definition: pcb_track.h:149
int GetEndY() const
Definition: pcb_track.h:134
void SetStartX(int aX)
Definition: pcb_track.h:124
void SetStartY(int aY)
Definition: pcb_track.h:125
void SetEndX(int aX)
Definition: pcb_track.h:130
int GetStartX() const
Definition: pcb_track.h:127
virtual void SetWidth(int aWidth)
Definition: pcb_track.h:115
virtual int GetWidth() const
Definition: pcb_track.h:116
bool GetIsFree() const
Check if the via is a free via (as opposed to one created on a track by the router).
Definition: pcb_track.h:642
PCB_LAYER_ID BottomLayer() const
Definition: pcb_track.cpp:1189
VECTOR2I GetPosition() const override
Definition: pcb_track.h:493
const PADSTACK & Padstack() const
Definition: pcb_track.h:412
void SetBottomLayer(PCB_LAYER_ID aLayer)
Definition: pcb_track.cpp:1155
void SetDrill(int aDrill)
Set the drill value for vias.
Definition: pcb_track.h:608
void SetIsFree(bool aFree=true)
Definition: pcb_track.h:643
void SetTopLayer(PCB_LAYER_ID aLayer)
Definition: pcb_track.cpp:1149
void SetPosition(const VECTOR2I &aPoint) override
Definition: pcb_track.h:494
void SanitizeLayers()
Check so that the layers are correct depending on the type of via, and so that the top actually is on...
Definition: pcb_track.cpp:1195
int GetWidth() const override
Definition: pcb_track.cpp:359
void SetViaType(VIATYPE aViaType)
Definition: pcb_track.h:410
PCB_LAYER_ID TopLayer() const
Definition: pcb_track.cpp:1183
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
Definition: pcb_track.cpp:613
VIATYPE GetViaType() const
Definition: pcb_track.h:409
void SetPadstack(const PADSTACK &aPadstack)
Definition: pcb_track.h:414
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:110
TEARDROP_PARAMETARS is a helper class to handle parameters needed to build teardrops for a board thes...
double m_BestWidthRatio
The height of a teardrop as ratio between height and size of pad/via.
int m_TdMaxLen
max allowed length for teardrops in IU. <= 0 to disable
bool m_AllowUseTwoTracks
True to create teardrops using 2 track segments if the first in too small.
int m_TdMaxWidth
max allowed height for teardrops in IU. <= 0 to disable
double m_BestLengthRatio
The length of a teardrop as ratio between length and size of pad/via.
double m_WidthtoSizeFilterRatio
The ratio (H/D) between the via/pad size and the track width max value to create a teardrop 1....
bool m_Enabled
Flag to enable teardrops.
bool m_CurvedEdges
True if the teardrop should be curved.
EDA_UNITS GetUserUnits() const
wxString StringFromValue(double aValue, bool aAddUnitLabel=false, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
Converts aValue in internal units into a united string.
int GetIntValue()
Definition: unit_binder.h:129
virtual long long int GetValue()
Return the current value in Internal Units.
virtual void SetUnits(EDA_UNITS aUnits)
Normally not needed (as the UNIT_BINDER inherits from the parent frame), but can be used to set to DE...
virtual double GetDoubleValue()
Return the current value in Internal Units.
bool IsIndeterminate() const
Return true if the control holds the indeterminate value (for instance, if it represents a multiple s...
virtual void SetDoubleValue(double aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
virtual bool Validate(double aMin, double aMax, EDA_UNITS aUnits=EDA_UNITS::UNSCALED)
Validate the control against the given range, informing the user of any errors found.
virtual void ChangeValue(int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion WITHOUT trigger...
virtual void SetValue(long long int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
void SetCoordType(ORIGIN_TRANSFORMS::COORD_TYPES_T aCoordType)
Set the current origin transform mode.
Definition: unit_binder.h:200
bool IsNull() const
Return true if the control holds no value (ie: empty string, not 0).
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:170
This file is part of the common library.
#define _(s)
@ ALL_LAYERS
This file is part of the common library.
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ B_Mask
Definition: layer_ids.h:98
@ B_Cu
Definition: layer_ids.h:65
@ F_Mask
Definition: layer_ids.h:97
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
@ F_Cu
Definition: layer_ids.h:64
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:710
KICOMMON_API wxString GetLabel(EDA_UNITS aUnits, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Get the units string for a given units type.
Definition: eda_units.cpp:156
KICOMMON_API wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:155
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:100
#define GEOMETRY_MIN_SIZE
Definition: pcb_track.h:84
VIATYPE
Definition: pcb_track.h:66
std::optional< bool > has_solder_mask
True if this outer layer has mask (is not tented)
Definition: padstack.h:231
Container to handle a stock of specific vias each with unique diameter and drill sizes in the BOARD c...
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition: typeinfo.h:86
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:98
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96
#define INDETERMINATE_STATE
Used for holding indeterminate values, such as with multiple selections holding different values or c...
Definition: ui_common.h:46