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
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 );
262 m_curvedEdges->SetValue( v->GetTeardropParams().IsCurved() );
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
694 switch( m_ViaTypeChoice->GetSelection() )
695 {
696 case 0:
697 v->SetViaType( VIATYPE::THROUGH );
698 v->SanitizeLayers();
699 break;
700 case 1:
701 v->SetViaType( VIATYPE::MICROVIA );
702 break;
703 case 2:
704 v->SetViaType( VIATYPE::BLIND_BURIED );
705 break;
706 default:
707 break;
708 }
709
710 PCB_LAYER_ID startLayer = static_cast<PCB_LAYER_ID>( m_ViaStartLayer->GetLayerSelection() );
711 PCB_LAYER_ID endLayer = static_cast<PCB_LAYER_ID>( m_ViaEndLayer->GetLayerSelection() );
712
713 if (startLayer != UNDEFINED_LAYER )
714 {
715 m_viaStack->Drill().start = startLayer;
716 v->SetTopLayer( startLayer );
717 }
718
719 if (endLayer != UNDEFINED_LAYER )
720 {
721 m_viaStack->Drill().end = endLayer;
722 v->SetBottomLayer( endLayer );
723 }
724
725 switch( m_annularRingsCtrl->GetSelection() )
726 {
727 case 0:
730 break;
731 case 1:
734 break;
735 case 2:
738 break;
739 default:
740 break;
741 }
742
744 v->SetPadstack( *m_viaStack );
745
746 v->SanitizeLayers();
747
748 switch( m_tentingFrontCtrl->GetSelection() )
749 {
750 default:
751 case 0: v->Padstack().FrontOuterLayers().has_solder_mask.reset(); break;
752 case 1: v->Padstack().FrontOuterLayers().has_solder_mask = true; break;
753 case 2: v->Padstack().FrontOuterLayers().has_solder_mask = false; break;
754 }
755
756 switch( m_tentingBackCtrl->GetSelection() )
757 {
758 default:
759 case 0: v->Padstack().BackOuterLayers().has_solder_mask.reset(); break;
760 case 1: v->Padstack().BackOuterLayers().has_solder_mask = true; break;
761 case 2: v->Padstack().BackOuterLayers().has_solder_mask = false; break;
762 }
763
766
767 TEARDROP_PARAMETERS* targetParams = &v->GetTeardropParams();
768
769 if( m_cbTeardrops->Get3StateValue() != wxCHK_UNDETERMINED )
770 targetParams->m_Enabled = m_cbTeardrops->GetValue();
771
772 if( m_cbTeardropsUseNextTrack->Get3StateValue() != wxCHK_UNDETERMINED )
773 targetParams->m_AllowUseTwoTracks = m_cbTeardropsUseNextTrack->GetValue();
774
776 targetParams->m_TdMaxLen = m_teardropMaxLen.GetIntValue();
777
780
782 targetParams->m_BestLengthRatio = m_teardropLenPercent.GetDoubleValue() / 100.0;
783
785 targetParams->m_BestWidthRatio =
787
790
791 if( m_curvedEdges->Get3StateValue() != wxCHK_UNDETERMINED )
792 {
793 if( m_curvedEdges->GetValue() )
794 targetParams->m_CurveSegCount = 1;
795 else
796 targetParams->m_CurveSegCount = 0;
797 }
798
799 if( changeLock )
800 v->SetLocked( setLock );
801
802 break;
803 }
804
805 default:
806 wxASSERT( false );
807 break;
808 }
809 }
810
811 commit.Push( _( "Edit Track/Via Properties" ) );
812
813 // Pushing the commit will have updated the connectivity so we can now test to see if we
814 // need to update any pad nets.
815
816 auto connectivity = m_frame->GetBoard()->GetConnectivity();
817 int newNetCode = m_netSelector->GetSelectedNetcode();
818 bool updateNets = false;
819 std::vector<PAD*> changingPads;
820
821 if ( !m_netSelector->IsIndeterminate() )
822 {
823 updateNets = true;
824
825 for( EDA_ITEM* item : m_items )
826 {
827 BOARD_CONNECTED_ITEM* boardItem = static_cast<BOARD_CONNECTED_ITEM*>( item );
828 auto connectedItems = connectivity->GetConnectedItems( boardItem,
830
831 for ( BOARD_CONNECTED_ITEM* citem : connectedItems )
832 {
833 if( citem->Type() == PCB_PAD_T )
834 {
835 PAD* pad = static_cast<PAD*>( citem );
836
837 if( pad->GetNetCode() != newNetCode && !alg::contains( changingPads, citem ) )
838 changingPads.push_back( pad );
839 }
840 }
841 }
842 }
843
844 if( changingPads.size() && !confirmPadChange( changingPads ) )
845 updateNets = false;
846
847 if( updateNets )
848 {
849 for( EDA_ITEM* item : m_items )
850 {
851 commit.Modify( item );
852
853 switch( item->Type() )
854 {
855 case PCB_TRACE_T:
856 case PCB_ARC_T:
857 static_cast<PCB_TRACK*>( item )->SetNetCode( newNetCode );
858 break;
859
860 case PCB_VIA_T:
861 static_cast<PCB_VIA*>( item )->SetNetCode( newNetCode );
862 break;
863
864 default:
865 wxASSERT( false );
866 break;
867 }
868 }
869
870 for( PAD* pad : changingPads )
871 {
872 commit.Modify( pad );
873 pad->SetNetCode( newNetCode );
874 }
875
876 commit.Push( _( "Update Nets" ) );
877 }
878
879 return true;
880}
881
882
883void DIALOG_TRACK_VIA_PROPERTIES::onNetSelector( wxCommandEvent& aEvent )
884{
885 m_viaNotFree->SetValue( false );
886}
887
888
890{
891 if( !m_tracks )
892 {
893 m_netSelectorLabel->Enable( !m_viaNotFree->GetValue() );
894 m_netSelector->Enable( !m_viaNotFree->GetValue() );
895 }
896}
897
898
899void DIALOG_TRACK_VIA_PROPERTIES::onWidthSelect( wxCommandEvent& aEvent )
900{
901 m_TrackWidthCtrl->ChangeValue( m_predefinedTrackWidthsCtrl->GetStringSelection() );
902 m_TrackWidthCtrl->SelectAll();
903}
904
905
906void DIALOG_TRACK_VIA_PROPERTIES::onWidthEdit( wxCommandEvent& aEvent )
907{
908 m_predefinedTrackWidthsCtrl->SetStringSelection( m_TrackWidthCtrl->GetValue() );
909}
910
911
912void DIALOG_TRACK_VIA_PROPERTIES::onViaSelect( wxCommandEvent& aEvent )
913{
914 VIA_DIMENSION* viaDimension = static_cast<VIA_DIMENSION*> ( aEvent.GetClientData() );
915
916 m_viaDiameter.ChangeValue( viaDimension->m_Diameter );
917 m_viaDrill.ChangeValue( viaDimension->m_Drill );
918}
919
920
922{
923 wxCHECK_MSG( m_viaStack, /* void */, "Expected valid via stack in onPadstackModeChanged" );
924
925 switch( m_cbPadstackMode->GetSelection() )
926 {
927 default:
928 case 0: m_viaStack->SetMode( PADSTACK::MODE::NORMAL ); break;
929 case 1: m_viaStack->SetMode( PADSTACK::MODE::FRONT_INNER_BACK ); break;
930 case 2: m_viaStack->SetMode( PADSTACK::MODE::CUSTOM ); break;
931 }
932
934}
935
936
938{
939 wxCHECK_MSG( m_viaStack, /* void */, "Expected valid via stack in onEditLayerChanged" );
940
941 // Save data from the previous layer
943 {
944 int diameter = m_viaDiameter.GetValue();
945 m_viaStack->SetSize( { diameter, diameter }, m_editLayer );
946 }
947
948 switch( m_viaStack->Mode() )
949 {
950 default:
953 break;
954
956 switch( m_cbEditLayer->GetSelection() )
957 {
958 default:
959 case 0: m_editLayer = F_Cu; break;
960 case 1: m_editLayer = PADSTACK::INNER_LAYERS; break;
961 case 2: m_editLayer = B_Cu; break;
962 }
963 break;
964
966 {
967 int layer = m_cbEditLayer->GetSelection();
968
969 if( layer < 0 )
970 layer = 0;
971
972 if( m_editLayerCtrlMap.contains( layer ) )
973 m_editLayer = m_editLayerCtrlMap.at( layer );
974 else
976 }
977 }
978
979 // Load controls with the current layer
981}
982
983
985{
986 // NOTE: synchronize changes here with DIALOG_PAD_PROPERTIES::afterPadstackModeChanged
987
988 wxCHECK_MSG( m_viaStack, /* void */, "Expected valid via stack in afterPadstackModeChanged" );
989 m_cbEditLayer->Clear();
990
991 BOARD* board = m_frame->GetBoard();
992
993 switch( m_viaStack->Mode() )
994 {
996 m_cbPadstackMode->SetSelection( 0 );
997 m_cbEditLayer->Append( _( "All layers" ) );
998 m_cbEditLayer->Disable();
1001 break;
1002
1004 {
1005 m_cbPadstackMode->SetSelection( 1 );
1006 m_cbEditLayer->Enable();
1007
1008 std::vector choices = {
1009 board->GetLayerName( F_Cu ),
1010 _( "Inner Layers" ),
1011 board->GetLayerName( B_Cu )
1012 };
1013
1014 m_cbEditLayer->Append( choices );
1015
1017 { 0, F_Cu },
1019 { 2, B_Cu }
1020 };
1021
1022 if( m_editLayer != F_Cu && m_editLayer != B_Cu )
1024
1025 break;
1026 }
1027
1029 {
1030 m_cbPadstackMode->SetSelection( 2 );
1031 m_cbEditLayer->Enable();
1032 LSET layers = LSET::AllCuMask() & board->GetEnabledLayers();
1033
1034 for( PCB_LAYER_ID layer : layers.UIOrder() )
1035 {
1036 int idx = m_cbEditLayer->Append( board->GetLayerName( layer ) );
1037 m_editLayerCtrlMap[idx] = layer;
1038 }
1039
1040 break;
1041 }
1042 }
1043
1044 for( const auto& [idx, layer] : m_editLayerCtrlMap )
1045 {
1046 if( layer == m_editLayer )
1047 {
1048 m_cbEditLayer->SetSelection( idx );
1049 break;
1050 }
1051 }
1052}
1053
1054
1056{
1057 int viaType = m_ViaTypeChoice->GetSelection();
1058
1059 if( viaType <= 0 )
1060 return m_frame->GetBoard()->GetCopperLayerCount() - 1;
1061
1062 int startLayer = m_ViaStartLayer->GetLayerSelection();
1063 int endLayer = m_ViaEndLayer->GetLayerSelection();
1064
1065 if( startLayer < 0 || endLayer < 0 )
1066 return m_frame->GetBoard()->GetCopperLayerCount() - 1;
1067 else
1068 return m_frame->GetBoard()->LayerDepth( ToLAYER_ID( startLayer ), ToLAYER_ID( endLayer ) );
1069}
1070
1071
1072void DIALOG_TRACK_VIA_PROPERTIES::onViaEdit( wxCommandEvent& aEvent )
1073{
1074 m_predefinedViaSizesCtrl->SetSelection( wxNOT_FOUND );
1075
1076 if( m_vias )
1077 {
1078 if( m_ViaTypeChoice->GetSelection() != 0 ) // check if selected type isn't through.
1079 {
1080 m_ViaStartLayer->Enable();
1081 m_ViaEndLayer->Enable();
1082 }
1083 else
1084 {
1087
1088 m_ViaStartLayer->Enable( false );
1089 m_ViaEndLayer->Enable( false );
1090 }
1091
1092 m_annularRingsLabel->Show( getLayerDepth() > 1 );
1093 m_annularRingsCtrl->Show( getLayerDepth() > 1 );
1094 }
1095}
1096
1097
1099{
1100 if( m_btnLinkTenting->GetValue() )
1101 m_tentingBackCtrl->SetSelection( m_tentingFrontCtrl->GetSelection() );
1102
1103 event.Skip();
1104}
1105
1106
1108{
1109 bool link = m_btnLinkTenting->GetValue();
1110
1111 m_tentingBackCtrl->Enable( !link );
1112 m_tentingBackLabel->Enable( !link );
1113
1114 if( link )
1115 m_tentingBackCtrl->SetSelection( m_tentingFrontCtrl->GetSelection() );
1116
1117 event.Skip();
1118}
1119
1120
1121void DIALOG_TRACK_VIA_PROPERTIES::onTrackEdit( wxCommandEvent& aEvent )
1122{
1123 bool externalCuLayer = m_TrackLayerCtrl->GetLayerSelection() == F_Cu
1125
1126 m_techLayersLabel->Enable( externalCuLayer );
1127 m_trackHasSolderMask->Enable( externalCuLayer );
1128
1129 bool showMaskMargin = externalCuLayer && m_trackHasSolderMask->GetValue();
1130
1131 m_trackMaskMarginCtrl->Enable( showMaskMargin );
1132 m_trackMaskMarginLabel->Enable( showMaskMargin );
1133 m_trackMaskMarginUnit->Enable( showMaskMargin );
1134}
1135
1136
1138{
1139 event.Enable( !m_frame->GetBoard()->LegacyTeardrops() );
1140}
1141
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:778
int GetCopperLayerCount() const
Definition: board.cpp:741
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:574
int LayerDepth(PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer) const
Definition: board.cpp:766
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:226
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:622
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:809
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition: lset.cpp:697
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:686
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 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...
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:820
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