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 (C) 2018-2023 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
40 const PCB_SELECTION& aItems ) :
42 m_frame( aParent ),
43 m_items( aItems ),
44 m_trackStartX( aParent, m_TrackStartXLabel, m_TrackStartXCtrl, nullptr ),
45 m_trackStartY( aParent, m_TrackStartYLabel, m_TrackStartYCtrl, m_TrackStartYUnit ),
46 m_trackEndX( aParent, m_TrackEndXLabel, m_TrackEndXCtrl, nullptr ),
47 m_trackEndY( aParent, m_TrackEndYLabel, m_TrackEndYCtrl, m_TrackEndYUnit ),
48 m_trackWidth( aParent, m_TrackWidthLabel, m_TrackWidthCtrl, m_TrackWidthUnit ),
49 m_trackMaskMargin( aParent, m_trackMaskMarginLabel, m_trackMaskMarginCtrl, m_trackMaskMarginUnit ),
50 m_viaX( aParent, m_ViaXLabel, m_ViaXCtrl, nullptr ),
51 m_viaY( aParent, m_ViaYLabel, m_ViaYCtrl, m_ViaYUnit ),
52 m_viaDiameter( aParent, m_ViaDiameterLabel, m_ViaDiameterCtrl, m_ViaDiameterUnit ),
53 m_viaDrill( aParent, m_ViaDrillLabel, m_ViaDrillCtrl, m_ViaDrillUnit ),
54 m_teardropHDPercent( aParent, m_stHDRatio, m_tcHDRatio, m_stHDRatioUnits ),
55 m_teardropLenPercent( aParent, m_stLenPercentLabel, m_tcLenPercent, nullptr ),
56 m_teardropMaxLen( aParent, m_stMaxLen, m_tcTdMaxLen, m_stMaxLenUnits ),
57 m_teardropWidthPercent( aParent, m_stWidthPercentLabel, m_tcWidthPercent, nullptr ),
58 m_teardropMaxWidth( aParent, m_stMaxWidthLabel, m_tcMaxWidth, m_stMaxWidthUnits ),
59 m_tracks( false ),
60 m_vias( false ),
61 m_editLayer( PADSTACK::ALL_LAYERS )
62{
64
65 wxASSERT( !m_items.Empty() );
66
67 m_legacyTeardropsIcon->SetBitmap( KiBitmapBundle( BITMAPS::dialog_warning ) );
69
70 m_bitmapTeardrop->SetBitmap( KiBitmapBundle( BITMAPS::teardrop_sizes ) );
71
72 m_teardropHDPercent.SetUnits( EDA_UNITS::PERCENT );
73 m_teardropLenPercent.SetUnits( EDA_UNITS::PERCENT );
74 m_teardropWidthPercent.SetUnits( EDA_UNITS::PERCENT );
75
76 m_minTrackWidthHint->SetFont( KIUI::GetInfoFont( this ).Italic() );
77
78 // Configure display origin transforms
85
86 VIATYPE viaType = VIATYPE::NOT_DEFINED;
87
92
97
100 m_ViaEndLayer->SetBoardFrame( aParent );
102
103 m_btnLinkTenting->SetBitmap( KiBitmapBundle( BITMAPS::edit_cmp_symb_links ) );
104 m_btnLinkTenting->SetValue( true );
105 m_tentingBackCtrl->Disable();
106 m_tentingBackLabel->Disable();
107
108 wxFont infoFont = KIUI::GetInfoFont( this );
109 m_techLayersLabel->SetFont( infoFont );
110
111 bool nets = false;
112 int net = 0;
113 bool hasLocked = false;
114 bool hasUnlocked = false;
115
116 // Start and end layers of vias
117 // if at least 2 vias do not have the same start or the same end layer
118 // the layers will be set as undefined
119 int selection_first_layer = -1;
120 int selection_last_layer = -1;
121
122 // The selection layer for tracks
123 int track_selection_layer = -1;
124
125 auto getAnnularRingSelection =
126 []( const PCB_VIA* via ) -> int
127 {
128 switch( via->Padstack().UnconnectedLayerMode() )
129 {
130 default:
134 }
135 };
136
137 auto getTentingSelection =
138 []( const PCB_VIA* via, PCB_LAYER_ID aLayer ) -> int
139 {
140 std::optional<bool> tentingOverride = via->Padstack().IsTented( aLayer );
141
142 if( tentingOverride.has_value() )
143 {
144 if( *tentingOverride )
145 return 1; // Tented
146
147 return 2; // Not tented
148 }
149
150 return 0; // From design rules
151 };
152
153 // Look for values that are common for every item that is selected
154 for( EDA_ITEM* item : m_items )
155 {
156 if( !nets )
157 {
158 net = static_cast<BOARD_CONNECTED_ITEM*>( item )->GetNetCode();
159 nets = true;
160 }
161 else if( net != static_cast<BOARD_CONNECTED_ITEM*>( item )->GetNetCode() )
162 {
163 net = -1;
164 }
165
166 switch( item->Type() )
167 {
168 case PCB_TRACE_T:
169 case PCB_ARC_T:
170 {
171 const PCB_TRACK* t = static_cast<const PCB_TRACK*>( item );
172
173 if( !m_tracks ) // first track in the list
174 {
180 track_selection_layer = t->GetLayer();
181 m_trackHasSolderMask->SetValue ( t->HasSolderMask() );
182
183 if( t->GetLocalSolderMaskMargin().has_value() )
185 else
186 m_trackMaskMargin.SetValue( wxEmptyString );
187
188 m_tracks = true;
189 }
190 else // check if values are the same for every selected track
191 {
192 if( m_trackStartX.GetValue() != t->GetStart().x )
194
195 if( m_trackStartY.GetValue() != t->GetStart().y )
197
198 if( m_trackEndX.GetValue() != t->GetEnd().x )
200
201 if( m_trackEndY.GetValue() != t->GetEnd().y )
203
204 if( m_trackWidth.GetValue() != t->GetWidth() )
206
207 if( track_selection_layer != t->GetLayer() )
208 track_selection_layer = UNDEFINED_LAYER;
209
210 if( m_trackHasSolderMask->GetValue() != t->HasSolderMask() )
211 m_trackHasSolderMask->Set3StateValue( wxCHK_UNDETERMINED );
212
215 }
216
217 if( t->IsLocked() )
218 hasLocked = true;
219 else
220 hasUnlocked = true;
221
222 break;
223 }
224
225 case PCB_VIA_T:
226 {
227 PCB_VIA* v = static_cast<PCB_VIA*>( item );
228
229 if( !m_vias ) // first via in the list
230 {
233 m_viaStack = std::make_unique<PADSTACK>( v->Padstack() );
236 m_vias = true;
237 viaType = v->GetViaType();
238 m_viaNotFree->SetValue( !v->GetIsFree() );
239 m_annularRingsCtrl->SetSelection( getAnnularRingSelection( v ) );
240
241 m_tentingFrontCtrl->SetSelection( getTentingSelection( v, F_Mask ) );
242 m_tentingBackCtrl->SetSelection( getTentingSelection( v, B_Mask ) );
243
244 bool link = m_tentingFrontCtrl->GetSelection()
245 == m_tentingBackCtrl->GetSelection();
246
247 m_btnLinkTenting->SetValue( link );
248 m_tentingBackCtrl->Enable( !link );
249 m_tentingBackLabel->Enable( !link );
250
251 selection_first_layer = v->TopLayer();
252 selection_last_layer = v->BottomLayer();
253
254 m_cbTeardrops->SetValue( v->GetTeardropParams().m_Enabled );
261 m_curvedEdges->SetValue( v->GetTeardropParams().IsCurved() );
262 }
263 else // check if values are the same for every selected via
264 {
265 if( m_viaX.GetValue() != v->GetPosition().x )
267
268 if( m_viaY.GetValue() != v->GetPosition().y )
270
273
274 if( m_viaDrill.GetValue() != v->GetDrillValue() )
276
277 if( viaType != v->GetViaType() )
278 viaType = VIATYPE::NOT_DEFINED;
279
280 if( v->GetIsFree() != !m_viaNotFree->GetValue() )
281 m_viaNotFree->Set3StateValue( wxCHK_UNDETERMINED );
282
283 if( selection_first_layer != v->TopLayer() )
284 selection_first_layer = UNDEFINED_LAYER;
285
286 if( selection_last_layer != v->BottomLayer() )
287 selection_last_layer = UNDEFINED_LAYER;
288
289 if( m_annularRingsCtrl->GetSelection() != getAnnularRingSelection( v ) )
290 {
291 if( m_annularRingsCtrl->GetStrings().size() < 4 )
293
294 m_annularRingsCtrl->SetSelection( 3 );
295 }
296
297 if( m_cbTeardrops->GetValue() != v->GetTeardropParams().m_Enabled )
298 m_cbTeardrops->Set3StateValue( wxCHK_UNDETERMINED );
299
301 m_cbTeardropsUseNextTrack->Set3StateValue( wxCHK_UNDETERMINED );
302
305
308
311
314
317 }
318
319 if( v->IsLocked() )
320 hasLocked = true;
321 else
322 hasUnlocked = true;
323
324 break;
325 }
326
327 default:
328 {
329 wxASSERT( false );
330 break;
331 }
332 }
333 }
334
335 if( m_tracks )
336 {
337 // Set the track layer selection state:
338 if( track_selection_layer == UNDEFINED_LAYER )
339 {
342 }
343
344 m_TrackLayerCtrl->SetLayerSelection( track_selection_layer );
345 }
346
347 // Set the vias layers selections state:
348 if( m_vias )
349 {
350 if( selection_first_layer == UNDEFINED_LAYER )
351 {
354 }
355
356 m_ViaStartLayer->SetLayerSelection( selection_first_layer );
357
358 if( selection_last_layer == UNDEFINED_LAYER )
359 {
362 }
363
364 m_ViaEndLayer->SetLayerSelection( selection_last_layer );
365 }
366
367 m_netSelector->SetBoard( aParent->GetBoard() );
368 m_netSelector->SetNetInfo( &aParent->GetBoard()->GetNetInfo() );
369
370 if ( net >= 0 )
371 {
373 }
374 else
375 {
378 }
379
380 wxASSERT( m_tracks || m_vias );
381
382 if( m_vias )
383 {
384 if( m_viaNotFree->GetValue() && !m_tracks )
385 {
386 // Disable net selector to re-inforce meaning of "Automatically update via nets",
387 // but not when tracks are also selected as then things get harder if you want to
388 // update all the nets to match.
389 m_netSelectorLabel->Disable();
390 m_netSelector->Disable();
391 }
392
393 int viaSelection = wxNOT_FOUND;
394
395 // 0 is the netclass place-holder
396 for( unsigned ii = 1; ii < aParent->GetDesignSettings().m_ViasDimensionsList.size(); ii++ )
397 {
398 VIA_DIMENSION* viaDimension = &aParent->GetDesignSettings().m_ViasDimensionsList[ii];
399 wxString msg = m_frame->StringFromValue( viaDimension->m_Diameter )
400 + wxT( " / " )
401 + m_frame->StringFromValue( viaDimension->m_Drill );
402 m_predefinedViaSizesCtrl->Append( msg, viaDimension );
403
404 if( viaSelection == wxNOT_FOUND
405 && m_viaDiameter.GetValue() == viaDimension->m_Diameter
406 && m_viaDrill.GetValue() == viaDimension->m_Drill )
407 {
408 viaSelection = ii - 1;
409 }
410 }
411
412 m_predefinedViaSizesCtrl->SetSelection( viaSelection );
414
415 m_ViaTypeChoice->Enable();
416
417 switch( viaType )
418 {
419 case VIATYPE::THROUGH: m_ViaTypeChoice->SetSelection( 0 ); break;
420 case VIATYPE::MICROVIA: m_ViaTypeChoice->SetSelection( 1 ); break;
421 case VIATYPE::BLIND_BURIED: m_ViaTypeChoice->SetSelection( 2 ); break;
422 case VIATYPE::NOT_DEFINED: m_ViaTypeChoice->SetSelection( wxNOT_FOUND ); break;
423 }
424
425 m_ViaStartLayer->Enable( viaType != VIATYPE::THROUGH );
426 m_ViaEndLayer->Enable( viaType != VIATYPE::THROUGH );
427
428 m_annularRingsLabel->Show( getLayerDepth() > 1 );
429 m_annularRingsCtrl->Show( getLayerDepth() > 1 );
430
432 }
433 else
434 {
435 m_viaNotFree->Hide();
436 m_MainSizer->Hide( m_sbViaSizer, true );
437 }
438
439 if( m_tracks )
440 {
441 int widthSelection = wxNOT_FOUND;
442
443 // 0 is the netclass place-holder
444 for( unsigned ii = 1; ii < aParent->GetDesignSettings().m_TrackWidthList.size(); ii++ )
445 {
446 int width = aParent->GetDesignSettings().m_TrackWidthList[ii];
447 wxString msg = m_frame->StringFromValue( width );
448 m_predefinedTrackWidthsCtrl->Append( msg );
449
450 if( widthSelection == wxNOT_FOUND && m_trackWidth.GetValue() == width )
451 widthSelection = ii - 1;
452 }
453
454 m_predefinedTrackWidthsCtrl->SetSelection( widthSelection );
456
457 wxCommandEvent event;
458 onTrackEdit( event );
459 }
460 else
461 {
462 m_MainSizer->Hide( m_sbTrackSizer, true );
463 }
464
465 if( hasLocked && hasUnlocked )
466 m_lockedCbox->Set3StateValue( wxCHK_UNDETERMINED );
467 else if( hasLocked )
468 m_lockedCbox->Set3StateValue( wxCHK_CHECKED );
469 else
470 m_lockedCbox->Set3StateValue( wxCHK_UNCHECKED );
471
472 if( m_tracks )
474 else if( m_netSelector->IsEnabled() )
476 else
478
480
481 m_frame->Bind( EDA_EVT_UNITS_CHANGED, &DIALOG_TRACK_VIA_PROPERTIES::onUnitsChanged, this );
482 m_netSelector->Bind( FILTERED_ITEM_SELECTED, &DIALOG_TRACK_VIA_PROPERTIES::onNetSelector, this );
483
484 // Now all widgets have the size fixed, call FinishDialogSettings
486}
487
488
490{
491 m_frame->Unbind( EDA_EVT_UNITS_CHANGED, &DIALOG_TRACK_VIA_PROPERTIES::onUnitsChanged, this );
492}
493
494
496{
497 if( m_vias )
498 {
499 int viaSel = m_predefinedViaSizesCtrl->GetSelection();
500
502
503 // 0 is the netclass place-holder
504 for( unsigned ii = 1; ii < m_frame->GetDesignSettings().m_ViasDimensionsList.size(); ii++ )
505 {
507 wxString msg = m_frame->StringFromValue( viaDimension->m_Diameter )
508 + wxT( " / " )
509 + m_frame->StringFromValue( viaDimension->m_Drill );
510 m_predefinedViaSizesCtrl->Append( msg, viaDimension );
511 }
512
513 m_predefinedViaSizesCtrl->SetSelection( viaSel );
515 }
516
517 if( m_tracks )
518 {
519 int trackSel = m_predefinedTrackWidthsCtrl->GetSelection();
520
522
523 // 0 is the netclass place-holder
524 for( unsigned ii = 1; ii < m_frame->GetDesignSettings().m_TrackWidthList.size(); ii++ )
525 {
526 int width = m_frame->GetDesignSettings().m_TrackWidthList[ii];
527 wxString msg = m_frame->StringFromValue( width );
528 m_predefinedTrackWidthsCtrl->Append( msg );
529 }
530
531 m_predefinedTrackWidthsCtrl->SetSelection( trackSel );
533 }
534
535 aEvent.Skip();
536}
537
538
539bool DIALOG_TRACK_VIA_PROPERTIES::confirmPadChange( const std::vector<PAD*>& changingPads )
540{
541 wxString msg;
542
543 if( changingPads.size() == 1 )
544 {
545 PAD* pad = *changingPads.begin();
546 msg.Printf( _( "Changing the net will also update %s pad %s to %s." ),
547 pad->GetParentFootprint()->GetReference(),
548 pad->GetNumber(),
549 m_netSelector->GetValue() );
550 }
551 else if( changingPads.size() == 2 )
552 {
553 PAD* pad1 = *changingPads.begin();
554 PAD* pad2 = *( ++changingPads.begin() );
555 msg.Printf( _( "Changing the net will also update %s pad %s and %s pad %s to %s." ),
557 pad1->GetNumber(),
559 pad2->GetNumber(),
560 m_netSelector->GetValue() );
561 }
562 else
563 {
564 msg.Printf( _( "Changing the net will also update %lu connected pads to %s." ),
565 static_cast<unsigned long>( changingPads.size() ),
566 m_netSelector->GetValue() );
567 }
568
569 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
570 dlg.SetOKCancelLabels( _( "Change Nets" ), _( "Leave Nets Unchanged" ) );
571 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
572
573 return dlg.ShowModal() == wxID_OK;
574}
575
576
578{
579 // Check for malformed data ONLY; design rules and constraints are the business of DRC.
580
581 if( m_vias )
582 {
583 // TODO: This needs to move into the via class, not the dialog
584
586 || !m_viaDrill.Validate( GEOMETRY_MIN_SIZE, INT_MAX ) )
587 {
588 return false;
589 }
590
591 if( m_ViaDiameterCtrl->IsEnabled() && !m_viaDiameter.IsIndeterminate()
592 && m_ViaDrillCtrl->IsEnabled() && !m_viaDrill.IsIndeterminate()
594 {
595 DisplayError( GetParent(), _( "Via hole size must be smaller than via diameter" ) );
596 m_ViaDrillCtrl->SelectAll();
597 m_ViaDrillCtrl->SetFocus();
598 return false;
599 }
600
603 {
604 DisplayError( GetParent(), _( "Via start layer and end layer cannot be the same" ) );
605 return false;
606 }
607
609 {
610 int diameter = m_viaDiameter.GetValue();
611 m_viaStack->SetSize( { diameter, diameter }, m_editLayer );
612 }
613 }
614
615 if( m_tracks )
616 {
617 if( !m_trackWidth.Validate( GEOMETRY_MIN_SIZE, INT_MAX ) )
618 return false;
619 }
620
621 // If we survived that, then save the changes:
622 //
623 // We don't bother with updating the nets at this point as it will be useless (any connected
624 // pads will simply drive their existing nets back onto the track segments and vias).
625
626 BOARD_COMMIT commit( m_frame );
627 bool changeLock = m_lockedCbox->Get3StateValue() != wxCHK_UNDETERMINED;
628 bool setLock = m_lockedCbox->Get3StateValue() == wxCHK_CHECKED;
629
630 for( EDA_ITEM* item : m_items )
631 {
632 commit.Modify( item );
633
634 switch( item->Type() )
635 {
636 case PCB_TRACE_T:
637 case PCB_ARC_T:
638 {
639 wxASSERT( m_tracks );
640 PCB_TRACK* t = static_cast<PCB_TRACK*>( item );
641
644
647
650
653
656
657 int layer = m_TrackLayerCtrl->GetLayerSelection();
658
659 if( layer != UNDEFINED_LAYER )
660 t->SetLayer( (PCB_LAYER_ID) layer );
661
662 if ( m_trackHasSolderMask->Get3StateValue() != wxCHK_UNDETERMINED )
663 t->SetHasSolderMask( m_trackHasSolderMask->GetValue() );
664
666 {
669 else
671 }
672
673 if( changeLock )
674 t->SetLocked( setLock );
675
676 break;
677 }
678
679 case PCB_VIA_T:
680 {
681 wxASSERT( m_vias );
682 PCB_VIA* v = static_cast<PCB_VIA*>( item );
683
684 if( !m_viaX.IsIndeterminate() )
686
687 if( !m_viaY.IsIndeterminate() )
689
690 if( m_viaNotFree->Get3StateValue() != wxCHK_UNDETERMINED )
691 v->SetIsFree( !m_viaNotFree->GetValue() );
692
693 switch( m_ViaTypeChoice->GetSelection() )
694 {
695 case 0:
696 v->SetViaType( VIATYPE::THROUGH );
697 v->SanitizeLayers();
698 break;
699 case 1:
700 v->SetViaType( VIATYPE::MICROVIA );
701 break;
702 case 2:
703 v->SetViaType( VIATYPE::BLIND_BURIED );
704 break;
705 default:
706 break;
707 }
708
709 auto startLayer = static_cast<PCB_LAYER_ID>( m_ViaStartLayer->GetLayerSelection() );
710 auto endLayer = static_cast<PCB_LAYER_ID>( m_ViaEndLayer->GetLayerSelection() );
711
712 if (startLayer != UNDEFINED_LAYER )
713 v->SetTopLayer( startLayer );
714
715 if (endLayer != UNDEFINED_LAYER )
716 v->SetBottomLayer( endLayer );
717
718 switch( m_annularRingsCtrl->GetSelection() )
719 {
720 case 0:
723 break;
724 case 1:
727 break;
728 case 2:
731 break;
732 default:
733 break;
734 }
735
736 switch( m_tentingFrontCtrl->GetSelection() )
737 {
738 default:
739 case 0: v->Padstack().FrontOuterLayers().has_solder_mask.reset(); break;
740 case 1: v->Padstack().FrontOuterLayers().has_solder_mask = true; break;
741 case 2: v->Padstack().FrontOuterLayers().has_solder_mask = false; break;
742 }
743
744 switch( m_tentingBackCtrl->GetSelection() )
745 {
746 default:
747 case 0: v->Padstack().BackOuterLayers().has_solder_mask.reset(); break;
748 case 1: v->Padstack().BackOuterLayers().has_solder_mask = true; break;
749 case 2: v->Padstack().BackOuterLayers().has_solder_mask = false; break;
750 }
751
752 v->SanitizeLayers();
753
755 v->SetPadstack( *m_viaStack );
756
759
760 TEARDROP_PARAMETERS* targetParams = &v->GetTeardropParams();
761
762 if( m_cbTeardrops->Get3StateValue() != wxCHK_UNDETERMINED )
763 targetParams->m_Enabled = m_cbTeardrops->GetValue();
764
765 if( m_cbTeardropsUseNextTrack->Get3StateValue() != wxCHK_UNDETERMINED )
766 targetParams->m_AllowUseTwoTracks = m_cbTeardropsUseNextTrack->GetValue();
767
769 targetParams->m_TdMaxLen = m_teardropMaxLen.GetIntValue();
770
773
775 targetParams->m_BestLengthRatio = m_teardropLenPercent.GetDoubleValue() / 100.0;
776
778 targetParams->m_BestWidthRatio =
780
783
784 if( m_curvedEdges->Get3StateValue() != wxCHK_UNDETERMINED )
785 {
786 if( m_curvedEdges->GetValue() )
787 targetParams->m_CurveSegCount = 1;
788 else
789 targetParams->m_CurveSegCount = 0;
790 }
791
792 if( changeLock )
793 v->SetLocked( setLock );
794
795 break;
796 }
797
798 default:
799 wxASSERT( false );
800 break;
801 }
802 }
803
804 commit.Push( _( "Edit Track/Via Properties" ) );
805
806 // Pushing the commit will have updated the connectivity so we can now test to see if we
807 // need to update any pad nets.
808
809 auto connectivity = m_frame->GetBoard()->GetConnectivity();
810 int newNetCode = m_netSelector->GetSelectedNetcode();
811 bool updateNets = false;
812 std::vector<PAD*> changingPads;
813
814 if ( !m_netSelector->IsIndeterminate() )
815 {
816 updateNets = true;
817
818 for( EDA_ITEM* item : m_items )
819 {
820 BOARD_CONNECTED_ITEM* boardItem = static_cast<BOARD_CONNECTED_ITEM*>( item );
821 auto connectedItems = connectivity->GetConnectedItems( boardItem,
823
824 for ( BOARD_CONNECTED_ITEM* citem : connectedItems )
825 {
826 if( citem->Type() == PCB_PAD_T )
827 {
828 PAD* pad = static_cast<PAD*>( citem );
829
830 if( pad->GetNetCode() != newNetCode && !alg::contains( changingPads, citem ) )
831 changingPads.push_back( pad );
832 }
833 }
834 }
835 }
836
837 if( changingPads.size() && !confirmPadChange( changingPads ) )
838 updateNets = false;
839
840 if( updateNets )
841 {
842 for( EDA_ITEM* item : m_items )
843 {
844 commit.Modify( item );
845
846 switch( item->Type() )
847 {
848 case PCB_TRACE_T:
849 case PCB_ARC_T:
850 static_cast<PCB_TRACK*>( item )->SetNetCode( newNetCode );
851 break;
852
853 case PCB_VIA_T:
854 static_cast<PCB_VIA*>( item )->SetNetCode( newNetCode );
855 break;
856
857 default:
858 wxASSERT( false );
859 break;
860 }
861 }
862
863 for( PAD* pad : changingPads )
864 {
865 commit.Modify( pad );
866 pad->SetNetCode( newNetCode );
867 }
868
869 commit.Push( _( "Update Nets" ) );
870 }
871
872 return true;
873}
874
875
876void DIALOG_TRACK_VIA_PROPERTIES::onNetSelector( wxCommandEvent& aEvent )
877{
878 m_viaNotFree->SetValue( false );
879}
880
881
883{
884 if( !m_tracks )
885 {
886 m_netSelectorLabel->Enable( !m_viaNotFree->GetValue() );
887 m_netSelector->Enable( !m_viaNotFree->GetValue() );
888 }
889}
890
891
892void DIALOG_TRACK_VIA_PROPERTIES::onWidthSelect( wxCommandEvent& aEvent )
893{
894 m_TrackWidthCtrl->ChangeValue( m_predefinedTrackWidthsCtrl->GetStringSelection() );
895 m_TrackWidthCtrl->SelectAll();
896}
897
898
899void DIALOG_TRACK_VIA_PROPERTIES::onWidthEdit( wxCommandEvent& aEvent )
900{
901 m_predefinedTrackWidthsCtrl->SetStringSelection( m_TrackWidthCtrl->GetValue() );
902}
903
904
905void DIALOG_TRACK_VIA_PROPERTIES::onViaSelect( wxCommandEvent& aEvent )
906{
907 VIA_DIMENSION* viaDimension = static_cast<VIA_DIMENSION*> ( aEvent.GetClientData() );
908
909 m_viaDiameter.ChangeValue( viaDimension->m_Diameter );
910 m_viaDrill.ChangeValue( viaDimension->m_Drill );
911}
912
913
915{
916 wxCHECK_MSG( m_viaStack, /* void */, "Expected valid via stack in onPadstackModeChanged" );
917
918 switch( m_cbPadstackMode->GetSelection() )
919 {
920 default:
921 case 0: m_viaStack->SetMode( PADSTACK::MODE::NORMAL ); break;
922 case 1: m_viaStack->SetMode( PADSTACK::MODE::FRONT_INNER_BACK ); break;
923 case 2: m_viaStack->SetMode( PADSTACK::MODE::CUSTOM ); break;
924 }
925
927}
928
929
931{
932 wxCHECK_MSG( m_viaStack, /* void */, "Expected valid via stack in onEditLayerChanged" );
933
934 // Save data from the previous layer
936 {
937 int diameter = m_viaDiameter.GetValue();
938 m_viaStack->SetSize( { diameter, diameter }, m_editLayer );
939 }
940
941 switch( m_viaStack->Mode() )
942 {
943 default:
946 break;
947
949 switch( m_cbEditLayer->GetSelection() )
950 {
951 default:
952 case 0: m_editLayer = F_Cu; break;
953 case 1: m_editLayer = PADSTACK::INNER_LAYERS; break;
954 case 2: m_editLayer = B_Cu; break;
955 }
956 break;
957
959 {
960 int layer = m_cbEditLayer->GetSelection();
961
962 if( layer < 0 )
963 layer = 0;
964
965 if( m_editLayerCtrlMap.contains( layer ) )
966 m_editLayer = m_editLayerCtrlMap.at( layer );
967 else
969 }
970 }
971
972 // Load controls with the current layer
974}
975
976
978{
979 // NOTE: synchronize changes here with DIALOG_PAD_PROPERTIES::afterPadstackModeChanged
980
981 wxCHECK_MSG( m_viaStack, /* void */, "Expected valid via stack in afterPadstackModeChanged" );
982 m_cbEditLayer->Clear();
983
984 BOARD* board = m_frame->GetBoard();
985
986 switch( m_viaStack->Mode() )
987 {
989 m_cbPadstackMode->SetSelection( 0 );
990 m_cbEditLayer->Append( _( "All layers" ) );
991 m_cbEditLayer->Disable();
994 break;
995
997 {
998 m_cbPadstackMode->SetSelection( 1 );
999 m_cbEditLayer->Enable();
1000
1001 std::vector choices = {
1002 board->GetLayerName( F_Cu ),
1003 _( "Inner Layers" ),
1004 board->GetLayerName( B_Cu )
1005 };
1006
1007 m_cbEditLayer->Append( choices );
1008
1010 { 0, F_Cu },
1012 { 2, B_Cu }
1013 };
1014
1015 if( m_editLayer != F_Cu && m_editLayer != B_Cu )
1017
1018 break;
1019 }
1020
1022 {
1023 m_cbPadstackMode->SetSelection( 2 );
1024 m_cbEditLayer->Enable();
1025 LSET layers = LSET::AllCuMask() & board->GetEnabledLayers();
1026
1027 for( PCB_LAYER_ID layer : layers.UIOrder() )
1028 {
1029 int idx = m_cbEditLayer->Append( board->GetLayerName( layer ) );
1030 m_editLayerCtrlMap[idx] = layer;
1031 }
1032
1033 break;
1034 }
1035 }
1036
1037 for( const auto& [idx, layer] : m_editLayerCtrlMap )
1038 {
1039 if( layer == m_editLayer )
1040 {
1041 m_cbEditLayer->SetSelection( idx );
1042 break;
1043 }
1044 }
1045}
1046
1047
1049{
1050 int viaType = m_ViaTypeChoice->GetSelection();
1051
1052 if( viaType <= 0 )
1053 return m_frame->GetBoard()->GetCopperLayerCount() - 1;
1054
1055 int startLayer = m_ViaStartLayer->GetLayerSelection();
1056 int endLayer = m_ViaEndLayer->GetLayerSelection();
1057
1058 if( startLayer < 0 || endLayer < 0 )
1059 return m_frame->GetBoard()->GetCopperLayerCount() - 1;
1060 else
1061 return m_frame->GetBoard()->LayerDepth( ToLAYER_ID( startLayer ), ToLAYER_ID( endLayer ) );
1062}
1063
1064
1065void DIALOG_TRACK_VIA_PROPERTIES::onViaEdit( wxCommandEvent& aEvent )
1066{
1067 m_predefinedViaSizesCtrl->SetSelection( wxNOT_FOUND );
1068
1069 if( m_vias )
1070 {
1071 if( m_ViaTypeChoice->GetSelection() != 0 ) // check if selected type isn't through.
1072 {
1073 m_ViaStartLayer->Enable();
1074 m_ViaEndLayer->Enable();
1075 }
1076 else
1077 {
1080
1081 m_ViaStartLayer->Enable( false );
1082 m_ViaEndLayer->Enable( false );
1083 }
1084
1085 m_annularRingsLabel->Show( getLayerDepth() > 1 );
1086 m_annularRingsCtrl->Show( getLayerDepth() > 1 );
1087 }
1088}
1089
1090
1092{
1093 if( m_btnLinkTenting->GetValue() )
1094 m_tentingBackCtrl->SetSelection( m_tentingFrontCtrl->GetSelection() );
1095
1096 event.Skip();
1097}
1098
1099
1101{
1102 bool link = m_btnLinkTenting->GetValue();
1103
1104 m_tentingBackCtrl->Enable( !link );
1105 m_tentingBackLabel->Enable( !link );
1106
1107 if( link )
1108 m_tentingBackCtrl->SetSelection( m_tentingFrontCtrl->GetSelection() );
1109
1110 event.Skip();
1111}
1112
1113
1114void DIALOG_TRACK_VIA_PROPERTIES::onTrackEdit( wxCommandEvent& aEvent )
1115{
1116 bool externalCuLayer = m_TrackLayerCtrl->GetLayerSelection() == F_Cu
1118
1119 m_techLayersLabel->Enable( externalCuLayer );
1120 m_trackHasSolderMask->Enable( externalCuLayer );
1121
1122 bool showMaskMargin = externalCuLayer && m_trackHasSolderMask->GetValue();
1123
1124 m_trackMaskMarginCtrl->Enable( showMaskMargin );
1125 m_trackMaskMarginLabel->Enable( showMaskMargin );
1126 m_trackMaskMarginUnit->Enable( showMaskMargin );
1127}
1128
1129
1131{
1132 event.Enable( !m_frame->GetBoard()->LegacyTeardrops() );
1133}
1134
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:237
virtual void SetLocked(bool aLocked)
Definition: board_item.h:328
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:288
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:290
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:871
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:775
int GetCopperLayerCount() const
Definition: board.cpp:738
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:579
int LayerDepth(PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer) const
Definition: board.cpp:763
bool LegacyTeardrops() const
Definition: board.h:1261
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Create an undo entry for an item that has been already modified.
Definition: commit.h:105
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:217
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:602
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: kidialog.h:43
void DoNotShowCheckbox(wxString file, int line)
Checks the 'do not show again' setting for the dialog.
Definition: kidialog.cpp:51
bool SetOKCancelLabels(const ButtonLabel &ok, const ButtonLabel &cancel) override
Shows the 'do not show again' checkbox.
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:36
LSEQ UIOrder() const
Returns the copper, technical and user layers in the order shown in layer widget.
Definition: lset.cpp:799
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition: lset.cpp:687
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:676
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
Returns the BOARD_DESIGN_SETTINGS for the open project.
void SetBoardFrame(PCB_BASE_FRAME *aFrame)
void SetNotAllowedLayerSet(LSET aMask)
void SetUndefinedLayerName(const wxString &aName)
void SetHasSolderMask(bool aVal)
Definition: pcb_track.h:139
void SetEnd(const VECTOR2I &aEnd)
Definition: pcb_track.h:118
bool HasSolderMask() const
Definition: pcb_track.h:140
void SetStart(const VECTOR2I &aStart)
Definition: pcb_track.h:121
void SetLocalSolderMaskMargin(std::optional< int > aMargin)
Definition: pcb_track.h:142
std::optional< int > GetLocalSolderMaskMargin() const
Definition: pcb_track.h:143
const VECTOR2I & GetStart() const
Definition: pcb_track.h:122
const VECTOR2I & GetEnd() const
Definition: pcb_track.h:119
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:636
PCB_LAYER_ID BottomLayer() const
Definition: pcb_track.cpp:1189
VECTOR2I GetPosition() const override
Definition: pcb_track.h:487
const PADSTACK & Padstack() const
Definition: pcb_track.h:406
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:602
void SetIsFree(bool aFree=true)
Definition: pcb_track.h:637
void SetTopLayer(PCB_LAYER_ID aLayer)
Definition: pcb_track.cpp:1149
void SetPosition(const VECTOR2I &aPoint) override
Definition: pcb_track.h:488
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:404
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:403
void SetPadstack(const PADSTACK &aPadstack)
Definition: pcb_track.h:408
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...
int m_CurveSegCount
True if the teardrop should be curved.
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.
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:199
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:810
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:155
KICOMMON_API wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:154
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