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, see <https://www.gnu.org/licenses/>.
20 */
21
22#include <bitmaps.h>
23#include <core/kicad_algo.h>
28#include <footprint.h>
29#include <pad.h>
30#include <padstack.h>
31#include <pcb_track.h>
32#include <confirm.h>
33#include <kidialog.h>
35#include <board_commit.h>
36#include <magic_enum.hpp>
37#include <macros.h>
38#include <optional>
39
40
41bool DIALOG_TRACK_VIA_PROPERTIES::IPC4761_CONFIGURATION::operator==( const IPC4761_CONFIGURATION& aOther ) const
42{
43 return ( tent == aOther.tent ) && ( plug == aOther.plug ) && ( cover == aOther.cover )
44 && ( cap == aOther.cap ) && ( fill == aOther.fill );
45}
46
47
50 m_frame( aParent ),
51 m_items( aItems ),
54 m_trackEndX( aParent, m_TrackEndXLabel, m_TrackEndXCtrl, nullptr ),
58 m_viaX( aParent, m_ViaXLabel, m_ViaXCtrl, nullptr ),
77 m_tracks( false ),
78 m_vias( false ),
80 m_padstackDirty( false )
81{
82 commonInit( aParent );
83}
84
85
87 PCB_VIA* aStandaloneVia ) :
89 m_frame( aParent ),
93 m_trackEndX( aParent, m_TrackEndXLabel, m_TrackEndXCtrl, nullptr ),
97 m_viaX( aParent, m_ViaXLabel, m_ViaXCtrl, nullptr ),
116 m_tracks( false ),
117 m_vias( false ),
118 m_editLayer( F_Cu ),
119 m_padstackDirty( false )
120{
121 wxASSERT( aStandaloneVia );
122
123 m_standalone = true;
124 m_viaStandaloneSelection.Add( aStandaloneVia );
125
126 commonInit( aParent );
127}
128
129
131{
132 m_useCalculatedSize = true;
133
134 wxASSERT( !m_items.Empty() );
135
137 m_legacyTeardropsWarning->Show( m_frame->GetBoard()->LegacyTeardrops() );
138
140
144
145 m_minTrackWidthHint->SetFont( KIUI::GetInfoFont( this ).Italic() );
146
147 // Configure display origin transforms
154
155 m_TrackLayerCtrl->SetLayersHotkeys( false );
156 m_TrackLayerCtrl->SetNotAllowedLayerSet( LSET::AllNonCuMask() );
157 m_TrackLayerCtrl->SetBoardFrame( aParent );
158 m_TrackLayerCtrl->Resync();
159
160 m_ViaStartLayer->SetLayersHotkeys( false );
161 m_ViaStartLayer->SetNotAllowedLayerSet( LSET::AllNonCuMask() );
162 m_ViaStartLayer->SetBoardFrame( aParent );
163 m_ViaStartLayer->Resync();
164
165 m_ViaEndLayer->SetLayersHotkeys( false );
166 m_ViaEndLayer->SetNotAllowedLayerSet( LSET::AllNonCuMask() );
167 m_ViaEndLayer->SetBoardFrame( aParent );
168 m_ViaEndLayer->Resync();
169
170 m_backdrillFrontLayer->SetLayersHotkeys( false );
171 m_backdrillFrontLayer->SetNotAllowedLayerSet( LSET::AllNonCuMask() );
172 m_backdrillFrontLayer->SetBoardFrame( aParent );
173 m_backdrillFrontLayer->SetUndefinedLayerName( _( "None" ) );
174 m_backdrillFrontLayer->Resync();
175
176 m_backdrillBackLayer->SetLayersHotkeys( false );
177 m_backdrillBackLayer->SetNotAllowedLayerSet( LSET::AllNonCuMask() );
178 m_backdrillBackLayer->SetBoardFrame( aParent );
179 m_backdrillBackLayer->SetUndefinedLayerName( _( "None" ) );
180 m_backdrillBackLayer->Resync();
181
182 wxFont infoFont = KIUI::GetSmallInfoFont( this );
183 m_techLayersLabel->SetFont( infoFont );
184 m_postMachineSectionLabel->SetFont( infoFont );
185
186 m_frame->Bind( EDA_EVT_UNITS_CHANGED, &DIALOG_TRACK_VIA_PROPERTIES::onUnitsChanged, this );
187 m_netSelector->Bind( FILTERED_ITEM_SELECTED, &DIALOG_TRACK_VIA_PROPERTIES::onNetSelector, this );
188
189 for( auto& preset : magic_enum::enum_values<IPC4761_PRESET>() )
190 {
191 if( preset >= IPC4761_PRESET::CUSTOM )
192 continue;
193
194 const auto& name_it = m_IPC4761Names.find( preset );
195
196 wxString name = _( "Unknown choice" );
197
198 if( name_it != m_IPC4761Names.end() )
199 name = name_it->second;
200
201 m_protectionFeatures->AppendString( name );
202 }
203
205}
206
207
213
214
216{
217 // Setting widgets states/values must be in TransferDataToWindow, not in CTor
218 // otherwise states/values are overwritten by the DIALOG_SHIM::TransferDataToWindow() config values
219 bool nets = false;
220 int net = 0;
221 bool hasLocked = false;
222 bool hasUnlocked = false;
224
225 // Start and end layers of vias
226 // if at least 2 vias do not have the same start or the same end layer
227 // the layers will be set as undefined
228 int selection_first_layer = UNDEFINED_LAYER;
229 bool selection_first_layer_mixed = false;
230 int selection_last_layer = UNDEFINED_LAYER;
231 bool selection_last_layer_mixed = false;
232
233 // The selection layer for tracks
234 int track_selection_layer = UNDEFINED_LAYER;
235 bool track_selection_layer_mixed = false;
236
237 // Drill information for vias
238 int secondary_drill_end_layer = UNDEFINED_LAYER;
239 bool secondary_drill_end_layer_mixed = false;
240 int secondary_drill_size = 0;
241 bool secondary_drill_size_mixed = false;
242
243 int tertiary_drill_end_layer = UNDEFINED_LAYER;
244 bool tertiary_drill_end_layer_mixed = false;
245 int tertiary_drill_size = 0;
246 bool tertiary_drill_size_mixed = false;
247
249 bool backdrill_dir_mixed = false;
250
251 std::optional<PAD_DRILL_POST_MACHINING_MODE> primary_post_machining_value;
252 bool primary_post_machining_mixed = false;
253 int primary_post_machining_size = 0;
254 bool primary_post_machining_size_mixed = false;
255 int primary_post_machining_depth = 0;
256 bool primary_post_machining_depth_mixed = false;
257 int primary_post_machining_angle = 0;
258 bool primary_post_machining_angle_mixed = false;
259
260 std::optional<PAD_DRILL_POST_MACHINING_MODE> secondary_post_machining_value;
261 bool secondary_post_machining_mixed = false;
262 int secondary_post_machining_size = 0;
263 bool secondary_post_machining_size_mixed = false;
264 int secondary_post_machining_depth = 0;
265 bool secondary_post_machining_depth_mixed = false;
266 int secondary_post_machining_angle = 0;
267 bool secondary_post_machining_angle_mixed = false;
268
269 m_padstackDirty = false;
270
271 const int annularRingChoices = static_cast<int>( m_annularRingsCtrl->GetCount() );
272
273 auto getAnnularRingSelection =
274 []( const PCB_VIA* via ) -> int
275 {
276 switch( via->Padstack().UnconnectedLayerMode() )
277 {
278 default:
283 }
284 };
285
286 auto getBackdrillDrills =
287 []( const PCB_VIA* via, PADSTACK::DRILL_PROPS& aTop, PADSTACK::DRILL_PROPS& aBottom )
288 {
289 const PADSTACK::DRILL_PROPS& sec = via->Padstack().SecondaryDrill();
290 const PADSTACK::DRILL_PROPS& ter = via->Padstack().TertiaryDrill();
291
292 aTop = PADSTACK::DRILL_PROPS();
293 aBottom = PADSTACK::DRILL_PROPS();
294
295 if( sec.start == F_Cu )
296 aTop = sec;
297 else if( ter.start == F_Cu )
298 aTop = ter;
299
300 if( sec.start == B_Cu )
301 aBottom = sec;
302 else if( ter.start == B_Cu )
303 aBottom = ter;
304 };
305
306 // Look for values that are common for every item that is selected
307 for( EDA_ITEM* item : m_items )
308 {
309 if( !nets )
310 {
311 net = static_cast<BOARD_CONNECTED_ITEM*>( item )->GetNetCode();
312 nets = true;
313 }
314 else if( net != static_cast<BOARD_CONNECTED_ITEM*>( item )->GetNetCode() )
315 {
316 net = -1;
317 }
318
319 switch( item->Type() )
320 {
321 case PCB_TRACE_T:
322 case PCB_ARC_T:
323 {
324 const PCB_TRACK* t = static_cast<const PCB_TRACK*>( item );
325
326 if( !m_tracks ) // first track in the list
327 {
328 m_trackStartX.SetValue( t->GetStartX() );
329 m_trackStartY.SetValue( t->GetStartY() );
330 m_trackEndX.SetValue( t->GetEndX() );
331 m_trackEndY.SetValue( t->GetEndY() );
332 m_trackWidth.SetValue( t->GetWidth() );
333 track_selection_layer = t->GetLayer();
334 m_trackHasSolderMask->SetValue ( t->HasSolderMask() );
335
336 if( t->GetLocalSolderMaskMargin().has_value() )
337 m_trackMaskMargin.SetValue( t->GetLocalSolderMaskMargin().value() );
338 else
339 m_trackMaskMargin.SetValue( wxEmptyString );
340
341 m_tracks = true;
342 }
343 else // check if values are the same for every selected track
344 {
345 if( m_trackStartX.GetValue() != t->GetStartX() )
347
348 if( m_trackStartY.GetValue() != t->GetStartY() )
350
351 if( m_trackEndX.GetValue() != t->GetEndX() )
353
354 if( m_trackEndY.GetValue() != t->GetEndY() )
356
357 if( m_trackWidth.GetValue() != t->GetWidth() )
359
360 if( track_selection_layer != t->GetLayer() )
361 track_selection_layer_mixed = true;
362
363 if( m_trackHasSolderMask->GetValue() != t->HasSolderMask() )
364 m_trackHasSolderMask->Set3StateValue( wxCHK_UNDETERMINED );
365
366 if( m_trackMaskMargin.GetValue() != t->GetLocalSolderMaskMargin() )
368 }
369
370 if( t->IsLocked() )
371 hasLocked = true;
372 else
373 hasUnlocked = true;
374
375 break;
376 }
377
378 case PCB_VIA_T:
379 {
380 PCB_VIA* v = static_cast<PCB_VIA*>( item );
381
382 if( !m_vias ) // first via in the list
383 {
384 m_viaX.SetValue( v->GetPosition().x );
385 m_viaY.SetValue( v->GetPosition().y );
386 m_viaStack = std::make_unique<PADSTACK>( v->Padstack() );
387 m_viaDiameter.SetValue( v->GetWidth( m_editLayer ) );
388 m_viaDrill.SetValue( v->GetDrillValue() );
389 m_vias = true;
390 viaType = v->GetViaType();
391 m_viaNotFree->SetValue( !v->GetIsFree() );
392 m_annularRingsCtrl->SetSelection( getAnnularRingSelection( v ) );
393
394 primary_post_machining_value = v->Padstack().FrontPostMachining().mode;
395 primary_post_machining_size = v->Padstack().FrontPostMachining().size;
396 primary_post_machining_depth = v->Padstack().FrontPostMachining().depth;
397 primary_post_machining_angle = v->Padstack().FrontPostMachining().angle;
398
399 secondary_post_machining_value = v->Padstack().BackPostMachining().mode;
400 secondary_post_machining_size = v->Padstack().BackPostMachining().size;
401 secondary_post_machining_depth = v->Padstack().BackPostMachining().depth;
402 secondary_post_machining_angle = v->Padstack().BackPostMachining().angle;
403
404 PADSTACK::DRILL_PROPS topDrill;
405 PADSTACK::DRILL_PROPS bottomDrill;
406 getBackdrillDrills( v, topDrill, bottomDrill );
407
408 // secondary_* holds the top (front) backdrill, tertiary_* the bottom (back) one
409 secondary_drill_end_layer = topDrill.end;
410 tertiary_drill_end_layer = bottomDrill.end;
411
412 secondary_drill_size = topDrill.size.x;
413 tertiary_drill_size = bottomDrill.size.x;
414
415 bool top = topDrill.end != UNDEFINED_LAYER && topDrill.size.x > 0;
416 bool bottom = bottomDrill.end != UNDEFINED_LAYER && bottomDrill.size.x > 0;
417
418 if( top && bottom )
419 backdrill_dir = BACKDRILL_MODE::BACKDRILL_BOTH;
420 else if( bottom )
421 backdrill_dir = BACKDRILL_MODE::BACKDRILL_BOTTOM;
422 else if( top )
423 backdrill_dir = BACKDRILL_MODE::BACKDRILL_TOP;
424 else
425 backdrill_dir = BACKDRILL_MODE::NO_BACKDRILL;
426
427 selection_first_layer = v->TopLayer();
428 selection_last_layer = v->BottomLayer();
429
430 m_cbTeardrops->SetValue( v->GetTeardropParams().m_Enabled );
434 m_teardropLenPercent.SetDoubleValue( v->GetTeardropParams().m_BestLengthRatio*100.0 );
435 m_teardropWidthPercent.SetDoubleValue( v->GetTeardropParams().m_BestWidthRatio*100.0 );
438
440
441 if( preset >= IPC4761_PRESET::CUSTOM )
443 else
444 m_protectionFeatures->SetSelection( static_cast<int>( preset ) );
445 }
446 else // check if values are the same for every selected via
447 {
448 if( m_viaX.GetValue() != v->GetPosition().x )
449 m_viaX.SetValue( INDETERMINATE_STATE );
450
451 if( m_viaY.GetValue() != v->GetPosition().y )
452 m_viaY.SetValue( INDETERMINATE_STATE );
453
454 if( m_viaDiameter.GetValue() != v->GetWidth( m_editLayer ) )
456
457 if( m_viaDrill.GetValue() != v->GetDrillValue() )
459
460 if( viaType != v->GetViaType() )
461 viaType = VIATYPE::NOT_DEFINED;
462
463 if( v->GetIsFree() != !m_viaNotFree->GetValue() )
464 m_viaNotFree->Set3StateValue( wxCHK_UNDETERMINED );
465
466 if( selection_first_layer != v->TopLayer() )
467 selection_first_layer_mixed = true;
468
469 if( selection_last_layer != v->BottomLayer() )
470 selection_last_layer_mixed = true;
471
472 if( m_annularRingsCtrl->GetSelection() != getAnnularRingSelection( v ) )
473 {
474 if( m_annularRingsCtrl->GetSelection() != annularRingChoices )
476
477 m_annularRingsCtrl->SetSelection( annularRingChoices );
478 }
479
480 if( m_cbTeardrops->GetValue() != v->GetTeardropParams().m_Enabled )
481 m_cbTeardrops->Set3StateValue( wxCHK_UNDETERMINED );
482
484 m_cbTeardropsUseNextTrack->Set3StateValue( wxCHK_UNDETERMINED );
485
486 if( m_teardropMaxLen.GetValue() != v->GetTeardropParams().m_TdMaxLen )
488
489 if( m_teardropMaxWidth.GetValue() != v->GetTeardropParams().m_TdMaxWidth )
491
492 if( m_teardropLenPercent.GetDoubleValue() != v->GetTeardropParams().m_BestLengthRatio *100.0 )
494
495 if( m_teardropWidthPercent.GetDoubleValue() != v->GetTeardropParams().m_BestWidthRatio *100.0 )
497
498 if( m_teardropHDPercent.GetDoubleValue() != v->GetTeardropParams().m_WidthtoSizeFilterRatio*100.0 )
500
501 if( static_cast<int>( getViaConfiguration( v ) ) != m_protectionFeatures->GetSelection() )
503
504 if( primary_post_machining_value != v->Padstack().FrontPostMachining().mode )
505 primary_post_machining_mixed = true;
506
507 if( primary_post_machining_size != v->Padstack().FrontPostMachining().size )
508 primary_post_machining_size_mixed = true;
509
510 if( primary_post_machining_depth != v->Padstack().FrontPostMachining().depth )
511 primary_post_machining_depth_mixed = true;
512
513 if( primary_post_machining_angle != v->Padstack().FrontPostMachining().angle )
514 primary_post_machining_angle_mixed = true;
515
516 if( secondary_post_machining_value != v->Padstack().BackPostMachining().mode )
517 secondary_post_machining_mixed = true;
518
519 if( secondary_post_machining_size != v->Padstack().BackPostMachining().size )
520 secondary_post_machining_size_mixed = true;
521
522 if( secondary_post_machining_depth != v->Padstack().BackPostMachining().depth )
523 secondary_post_machining_depth_mixed = true;
524
525 if( secondary_post_machining_angle != v->Padstack().BackPostMachining().angle )
526 secondary_post_machining_angle_mixed = true;
527
528 PADSTACK::DRILL_PROPS topDrill;
529 PADSTACK::DRILL_PROPS bottomDrill;
530 getBackdrillDrills( v, topDrill, bottomDrill );
531
532 bool top = topDrill.end != UNDEFINED_LAYER && topDrill.size.x > 0;
533 bool bottom = bottomDrill.end != UNDEFINED_LAYER && bottomDrill.size.x > 0;
534
536
537 if( top && bottom )
538 new_backdrill_dir = BACKDRILL_MODE::BACKDRILL_BOTH;
539 else if( bottom )
540 new_backdrill_dir = BACKDRILL_MODE::BACKDRILL_BOTTOM;
541 else if( top )
542 new_backdrill_dir = BACKDRILL_MODE::BACKDRILL_TOP;
543 else
544 new_backdrill_dir = BACKDRILL_MODE::NO_BACKDRILL;
545
546 if( secondary_drill_end_layer != topDrill.end )
547 secondary_drill_end_layer_mixed = true;
548
549 if( tertiary_drill_end_layer != bottomDrill.end )
550 tertiary_drill_end_layer_mixed = true;
551
552 if( backdrill_dir != new_backdrill_dir )
553 backdrill_dir_mixed = true;
554
555 if( bottomDrill.size.x != tertiary_drill_size )
556 tertiary_drill_size_mixed = true;
557
558 if( topDrill.size.x != secondary_drill_size )
559 secondary_drill_size_mixed = true;
560 }
561
562 if( v->IsLocked() )
563 hasLocked = true;
564 else
565 hasUnlocked = true;
566
567 break;
568 }
569
570 default:
571 {
572 UNIMPLEMENTED_FOR( item->GetClass() );
573 break;
574 }
575 }
576 }
577
578 if( m_tracks )
579 {
580 // Set the track layer selection state:
581 if( track_selection_layer_mixed )
582 {
583 m_TrackLayerCtrl->SetUndefinedLayerName( INDETERMINATE_STATE );
584 m_TrackLayerCtrl->Resync();
585 m_TrackLayerCtrl->SetSelection( UNDEFINED_LAYER );
586 }
587 else
588 {
589 m_TrackLayerCtrl->SetLayerSelection( track_selection_layer );
590 }
591 }
592
593 // Set the vias layers selections state:
594 if( m_vias )
595 {
596 if( selection_first_layer_mixed )
597 {
598 m_ViaStartLayer->SetUndefinedLayerName( INDETERMINATE_STATE );
599 m_ViaStartLayer->Resync();
600 m_ViaStartLayer->SetSelection( UNDEFINED_LAYER );
601 }
602 else
603 {
604 m_ViaStartLayer->SetLayerSelection( selection_first_layer );
605 }
606
607 if( selection_last_layer_mixed )
608 {
609 m_ViaEndLayer->SetUndefinedLayerName( INDETERMINATE_STATE );
610 m_ViaEndLayer->Resync();
611 m_ViaEndLayer->SetSelection( UNDEFINED_LAYER );
612 }
613 else
614 {
615 m_ViaEndLayer->SetLayerSelection( selection_last_layer );
616 }
617
618 // Set backdrill controls
619
620 // Backdrill direction selector
621 if( backdrill_dir_mixed )
622 {
623 m_backdrillChoice->SetSelection( wxNOT_FOUND );
624
625 if( tertiary_drill_size_mixed )
627 else
628 m_backdrillBackSize.SetValue( tertiary_drill_size );
629
630 if( secondary_drill_size_mixed )
632 else
633 m_backdrillFrontSize.SetValue( secondary_drill_size );
634 }
635 else
636 {
637 m_backdrillChoice->SetSelection( static_cast<int>( backdrill_dir ) );
638
639 if( backdrill_dir == BACKDRILL_MODE::BACKDRILL_BOTTOM || backdrill_dir == BACKDRILL_MODE::BACKDRILL_BOTH )
640 {
641 if( tertiary_drill_size_mixed )
643 else
644 m_backdrillBackSize.SetValue( tertiary_drill_size );
645 }
646 else
647 {
648 m_backdrillBackSize.SetValue( wxEmptyString );
649 }
650
651 if( backdrill_dir == BACKDRILL_MODE::BACKDRILL_TOP || backdrill_dir == BACKDRILL_MODE::BACKDRILL_BOTH )
652 {
653 if( secondary_drill_size_mixed )
655 else
656 m_backdrillFrontSize.SetValue( secondary_drill_size );
657 }
658 else
659 {
660 m_backdrillFrontSize.SetValue( wxEmptyString );
661 }
662
663 }
664
665 // Top backdrill control
666 if( secondary_drill_end_layer_mixed )
667 {
668 m_backdrillFrontLayer->SetUndefinedLayerName( INDETERMINATE_STATE );
669 m_backdrillFrontLayer->Resync();
670 m_backdrillFrontLayer->SetLayerSelection( UNDEFINED_LAYER );
671 }
672 else
673 {
674 m_backdrillFrontLayer->SetUndefinedLayerName( _( "None" ) );
675 m_backdrillFrontLayer->Resync();
676 m_backdrillFrontLayer->SetLayerSelection( secondary_drill_end_layer );
677 }
678
679 // Bottom backdrill control
680 if( tertiary_drill_end_layer_mixed )
681 {
682 m_backdrillBackLayer->SetUndefinedLayerName( INDETERMINATE_STATE );
683 m_backdrillBackLayer->Resync();
684 m_backdrillBackLayer->SetLayerSelection( UNDEFINED_LAYER );
685 }
686 else
687 {
688 m_backdrillBackLayer->SetUndefinedLayerName( _( "None" ) );
689 m_backdrillBackLayer->Resync();
690 m_backdrillBackLayer->SetLayerSelection( tertiary_drill_end_layer );
691 }
692
693 // Post Machining
694 if( primary_post_machining_mixed )
695 {
696 m_topPostMachine->SetSelection( wxNOT_FOUND );
698 m_topPostMachineSize2.SetUnits( m_frame->GetUserUnits() );
700 }
701 else if( primary_post_machining_value.has_value() )
702 {
703 switch( primary_post_machining_value.value() )
704 {
706 m_topPostMachine->SetSelection( 2 );
707
708 if( primary_post_machining_size_mixed )
710 else
711 m_topPostMachineSize1.SetValue( primary_post_machining_size );
712
713 m_topPostMachineSize2.SetUnits( m_frame->GetUserUnits() );
714
715 if( primary_post_machining_depth_mixed )
717 else
718 m_topPostMachineSize2.SetValue( primary_post_machining_depth );
719
720 break;
721
723 m_topPostMachine->SetSelection( 1 );
724
725 if( primary_post_machining_size_mixed )
727 else
728 m_topPostMachineSize1.SetValue( primary_post_machining_size );
729
731
732 if( primary_post_machining_angle_mixed )
734 else
735 m_topPostMachineSize2.SetDoubleValue( primary_post_machining_angle / 10.0 );
736
737 break;
738
739 default:
740 m_topPostMachine->SetSelection( 0 );
741 m_topPostMachineSize1.SetValue( wxEmptyString );
742 m_topPostMachineSize2.SetUnits( m_frame->GetUserUnits() );
743 m_topPostMachineSize2.SetValue( wxEmptyString );
744 break;
745 }
746 }
747 else
748 {
749 m_topPostMachine->SetSelection( 0 );
750 m_topPostMachineSize1.SetValue( wxEmptyString );
751 m_topPostMachineSize2.SetUnits( m_frame->GetUserUnits() );
752 m_topPostMachineSize2.SetValue( wxEmptyString );
753 }
754
755 if( secondary_post_machining_mixed )
756 {
757 m_bottomPostMachine->SetSelection( wxNOT_FOUND );
759 m_bottomPostMachineSize2.SetUnits( m_frame->GetUserUnits() );
761 }
762 else if( secondary_post_machining_value.has_value() )
763 {
764 switch( secondary_post_machining_value.value() )
765 {
767 m_bottomPostMachine->SetSelection( 2 );
768
769 if( secondary_post_machining_size_mixed )
771 else
772 m_bottomPostMachineSize1.SetValue( secondary_post_machining_size );
773
774 m_bottomPostMachineSize2.SetUnits( m_frame->GetUserUnits() );
775
776 if( secondary_post_machining_depth_mixed )
778 else
779 m_bottomPostMachineSize2.SetValue( secondary_post_machining_depth );
780
781 break;
782
784 m_bottomPostMachine->SetSelection( 1 );
785
786 if( secondary_post_machining_size_mixed )
788 else
789 m_bottomPostMachineSize1.SetValue( secondary_post_machining_size );
790
792
793 if( secondary_post_machining_angle_mixed )
795 else
796 m_bottomPostMachineSize2.SetDoubleValue( secondary_post_machining_angle / 10.0 );
797
798 break;
799
800 default:
801 m_bottomPostMachine->SetSelection( 0 );
802 m_bottomPostMachineSize1.SetValue( wxEmptyString );
803 m_bottomPostMachineSize2.SetValue( wxEmptyString );
804 m_bottomPostMachineSize2.SetUnits( m_frame->GetUserUnits() );
805 break;
806 }
807 }
808 else
809 {
810 m_bottomPostMachine->SetSelection( 0 );
811 m_bottomPostMachineSize1.SetValue( wxEmptyString );
812 m_bottomPostMachineSize2.SetUnits( m_frame->GetUserUnits() );
813 m_bottomPostMachineSize2.SetValue( wxEmptyString );
814 }
815 }
816
817 m_netSelector->SetNetInfo( &m_frame->GetBoard()->GetNetInfo() );
818
819 if ( net >= 0 )
820 {
821 m_netSelector->SetSelectedNetcode( net );
822 }
823 else
824 {
825 m_netSelector->SetIndeterminateString( INDETERMINATE_STATE );
826 m_netSelector->SetIndeterminate();
827 }
828
829 wxASSERT( m_tracks || m_vias );
830
831 if( m_vias )
832 {
833 if( m_viaNotFree->GetValue() && !m_tracks )
834 {
835 // Disable net selector to re-inforce meaning of "Automatically update via nets",
836 // but not when tracks are also selected as then things get harder if you want to
837 // update all the nets to match.
838 m_netSelectorLabel->Disable();
839 m_netSelector->Disable();
840 }
841
842 int viaSelection = wxNOT_FOUND;
843
844 // 0 is the netclass place-holder
845 for( unsigned ii = 1; ii < m_frame->GetDesignSettings().m_ViasDimensionsList.size(); ii++ )
846 {
847 VIA_DIMENSION* viaDimension = &m_frame->GetDesignSettings().m_ViasDimensionsList[ii];
848 wxString msg = m_frame->StringFromValue( viaDimension->m_Diameter )
849 + wxT( " / " )
850 + m_frame->StringFromValue( viaDimension->m_Drill );
851 m_predefinedViaSizesCtrl->Append( msg, viaDimension );
852
853 if( viaSelection == wxNOT_FOUND
854 && m_viaDiameter.GetValue() == viaDimension->m_Diameter
855 && m_viaDrill.GetValue() == viaDimension->m_Drill )
856 {
857 viaSelection = ii - 1;
858 }
859 }
860
861 m_predefinedViaSizesCtrl->SetSelection( viaSelection );
862 m_predefinedViaSizesUnits->SetLabel( EDA_UNIT_UTILS::GetLabel( m_frame->GetUserUnits() ) );
863
864 m_ViaTypeChoice->Enable();
865
866 switch( viaType )
867 {
868 case VIATYPE::THROUGH: m_ViaTypeChoice->SetSelection( 0 ); break;
869 case VIATYPE::MICROVIA: m_ViaTypeChoice->SetSelection( 1 ); break;
870 case VIATYPE::BLIND: m_ViaTypeChoice->SetSelection( 2 ); break;
871 case VIATYPE::BURIED: m_ViaTypeChoice->SetSelection( 3 ); break;
872 case VIATYPE::NOT_DEFINED: m_ViaTypeChoice->SetSelection( wxNOT_FOUND ); break;
873 }
874
875 m_ViaStartLayer->Enable( viaType != VIATYPE::THROUGH );
876 m_ViaEndLayer->Enable( viaType != VIATYPE::THROUGH );
877
878 m_annularRingsLabel->Show( getLayerDepth() > 1 );
879 m_annularRingsCtrl->Show( getLayerDepth() > 1 );
880 m_annularRingsCtrl->Enable( true );
881
883 }
884 else
885 {
886 m_viaNotFree->Hide();
887 m_MainSizer->Hide( m_sbViaSizer, true );
888 }
889
890 if( m_tracks )
891 {
892 int widthSelection = wxNOT_FOUND;
893
894 // 0 is the netclass place-holder
895 for( unsigned ii = 1; ii < m_frame->GetDesignSettings().m_TrackWidthList.size(); ii++ )
896 {
897 int width = m_frame->GetDesignSettings().m_TrackWidthList[ii];
898 wxString msg = m_frame->StringFromValue( width );
899 m_predefinedTrackWidthsCtrl->Append( msg );
900
901 if( widthSelection == wxNOT_FOUND && m_trackWidth.GetValue() == width )
902 widthSelection = ii - 1;
903 }
904
905 m_predefinedTrackWidthsCtrl->SetSelection( widthSelection );
906 m_predefinedTrackWidthsUnits->SetLabel( EDA_UNIT_UTILS::GetLabel( m_frame->GetUserUnits() ) );
907
908 wxCommandEvent event;
909 onTrackEdit( event );
910 }
911 else
912 {
913 m_MainSizer->Hide( m_sbTrackSizer, true );
914 }
915
916 if( hasLocked && hasUnlocked )
917 m_lockedCbox->Set3StateValue( wxCHK_UNDETERMINED );
918 else if( hasLocked )
919 m_lockedCbox->Set3StateValue( wxCHK_CHECKED );
920 else
921 m_lockedCbox->Set3StateValue( wxCHK_UNCHECKED );
922
923 if( m_tracks )
925 else if( m_netSelector->IsEnabled() )
927 else
929
930 wxCommandEvent dummyEvent;
931 onBackdrillChange( dummyEvent );
932 onTopPostMachineChange( dummyEvent );
933 onBottomPostMachineChange( dummyEvent );
934
935 // Now all widgets have the size fixed, call FinishDialogSettings
937
938 return true;
939}
940
941
943{
944 if( m_vias )
945 {
946 int viaSel = m_predefinedViaSizesCtrl->GetSelection();
947
949
950 // 0 is the netclass place-holder
951 for( unsigned ii = 1; ii < m_frame->GetDesignSettings().m_ViasDimensionsList.size(); ii++ )
952 {
953 VIA_DIMENSION* viaDimension = &m_frame->GetDesignSettings().m_ViasDimensionsList[ii];
954 wxString msg = m_frame->StringFromValue( viaDimension->m_Diameter )
955 + wxT( " / " )
956 + m_frame->StringFromValue( viaDimension->m_Drill );
957 m_predefinedViaSizesCtrl->Append( msg, viaDimension );
958 }
959
960 m_predefinedViaSizesCtrl->SetSelection( viaSel );
961 m_predefinedViaSizesUnits->SetLabel( EDA_UNIT_UTILS::GetLabel( m_frame->GetUserUnits() ) );
962 }
963
964 if( m_tracks )
965 {
966 int trackSel = m_predefinedTrackWidthsCtrl->GetSelection();
967
969
970 // 0 is the netclass place-holder
971 for( unsigned ii = 1; ii < m_frame->GetDesignSettings().m_TrackWidthList.size(); ii++ )
972 {
973 int width = m_frame->GetDesignSettings().m_TrackWidthList[ii];
974 wxString msg = m_frame->StringFromValue( width );
975 m_predefinedTrackWidthsCtrl->Append( msg );
976 }
977
978 m_predefinedTrackWidthsCtrl->SetSelection( trackSel );
979 m_predefinedTrackWidthsUnits->SetLabel( EDA_UNIT_UTILS::GetLabel( m_frame->GetUserUnits() ) );
980 }
981
982 aEvent.Skip();
983}
984
985
986bool DIALOG_TRACK_VIA_PROPERTIES::confirmShortingNets( int aNet, const std::set<int>& shortingNets )
987{
988 wxString msg;
989
990 if( shortingNets.size() == 1 )
991 {
992 msg.Printf( _( "Applying these changes will short net %s with %s." ),
993 m_netSelector->GetValue(),
994 m_frame->GetBoard()->FindNet( *shortingNets.begin() )->GetNetname() );
995 }
996 else
997 {
998 msg.Printf( _( "Applying these changes will short net %s with other nets." ),
999 m_netSelector->GetValue() );
1000 }
1001
1002 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
1003 dlg.SetOKCancelLabels( _( "Apply Anyway" ), _( "Cancel Changes" ) );
1004 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1005
1006 return dlg.ShowModal() == wxID_OK;
1007}
1008
1009
1010bool DIALOG_TRACK_VIA_PROPERTIES::confirmPadChange( const std::set<PAD*>& changingPads )
1011{
1012 wxString msg;
1013
1014 if( changingPads.size() == 1 )
1015 {
1016 PAD* pad = *changingPads.begin();
1017 msg.Printf( _( "Changing the net will also update %s pad %s to %s." ),
1018 pad->GetParentFootprint()->GetReference(),
1019 pad->GetNumber(),
1020 m_netSelector->GetValue() );
1021 }
1022 else if( changingPads.size() == 2 )
1023 {
1024 PAD* pad1 = *changingPads.begin();
1025 PAD* pad2 = *( ++changingPads.begin() );
1026 msg.Printf( _( "Changing the net will also update %s pad %s and %s pad %s to %s." ),
1028 pad1->GetNumber(),
1030 pad2->GetNumber(),
1031 m_netSelector->GetValue() );
1032 }
1033 else
1034 {
1035 msg.Printf( _( "Changing the net will also update %lu connected pads to %s." ),
1036 static_cast<unsigned long>( changingPads.size() ),
1037 m_netSelector->GetValue() );
1038 }
1039
1040 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
1041 dlg.SetOKCancelLabels( _( "Change Nets" ), _( "Leave Nets Unchanged" ) );
1042 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
1043
1044 return dlg.ShowModal() == wxID_OK;
1045}
1046
1047
1049{
1050 std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_frame->GetBoard()->GetConnectivity();
1051 std::vector<PCB_TRACK*> selected_tracks;
1052 std::set<PCB_TRACK*> connected_tracks;
1053
1054 for( EDA_ITEM* item : m_items )
1055 {
1056 if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( item ) )
1057 selected_tracks.push_back( track );
1058 }
1059
1060 for( PCB_TRACK* selected_track : selected_tracks )
1061 {
1062 connected_tracks.insert( selected_track );
1063
1064 // Exclude zones so we only follow direct copper, via, and pad connections. Zone
1065 // propagation would pull in unrelated same-net tracks and rewrite their net below.
1066 for( BOARD_CONNECTED_ITEM* connected_item :
1067 connectivity->GetConnectedItems( selected_track, EXCLUDE_ZONES ) )
1068 {
1069 if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( connected_item ) )
1070 connected_tracks.insert( track );
1071 }
1072 }
1073
1074 // Check for malformed data ONLY; design rules and constraints are the business of DRC.
1075
1076 if( m_vias )
1077 {
1078 // Marshal UI values into optionals; the malformed-data checks themselves live on
1079 // PCB_VIA::ValidateViaParameters so they can be reused and unit tested.
1080
1081 std::optional<int> viaDiameter;
1082
1083 if( m_ViaDiameterCtrl->IsEnabled() && !m_viaDiameter.IsIndeterminate() )
1084 viaDiameter = m_viaDiameter.GetValue();
1085
1086 std::optional<int> viaDrill;
1087
1088 if( m_ViaDrillCtrl->IsEnabled() && !m_viaDrill.IsIndeterminate() )
1089 viaDrill = m_viaDrill.GetValue();
1090
1091 std::optional<PCB_LAYER_ID> startLayer;
1092
1093 if( m_ViaStartLayer->GetLayerSelection() != UNDEFINED_LAYER )
1094 startLayer = static_cast<PCB_LAYER_ID>( m_ViaStartLayer->GetLayerSelection() );
1095
1096 std::optional<PCB_LAYER_ID> endLayer;
1097
1098 if( m_ViaEndLayer->GetLayerSelection() != UNDEFINED_LAYER )
1099 endLayer = static_cast<PCB_LAYER_ID>( m_ViaEndLayer->GetLayerSelection() );
1100
1101 std::optional<int> secondaryDrill;
1102 std::optional<int> tertiaryDrill;
1103 std::optional<PCB_LAYER_ID> secondaryStartLayer;
1104 std::optional<PCB_LAYER_ID> secondaryEndLayer;
1105 std::optional<PCB_LAYER_ID> tertiaryStartLayer;
1106 std::optional<PCB_LAYER_ID> tertiaryEndLayer;
1107
1108 if( m_backdrillChoice->GetSelection() != wxNOT_FOUND )
1109 {
1110 switch( static_cast<BACKDRILL_MODE>( m_backdrillChoice->GetSelection() ) )
1111 {
1113 break;
1114
1116 tertiaryStartLayer = B_Cu;
1117
1118 if( m_backdrillBackLayer->GetLayerSelection() != UNDEFINED_LAYER )
1119 tertiaryEndLayer = ToLAYER_ID( m_backdrillBackLayer->GetLayerSelection() );
1120
1121 if( !m_backdrillBackSize.IsIndeterminate() && !m_backdrillBackSize.IsNull() )
1122 tertiaryDrill = m_backdrillBackSize.GetIntValue();
1123
1124 break;
1125
1127 secondaryStartLayer = F_Cu;
1128
1129 if( m_backdrillFrontLayer->GetLayerSelection() != UNDEFINED_LAYER )
1130 secondaryEndLayer = ToLAYER_ID( m_backdrillFrontLayer->GetLayerSelection() );
1131
1132 if( !m_backdrillFrontSize.IsIndeterminate() && !m_backdrillFrontSize.IsNull() )
1133 secondaryDrill = m_backdrillFrontSize.GetIntValue();
1134
1135 break;
1136
1138 secondaryStartLayer = F_Cu;
1139
1140 if( m_backdrillFrontLayer->GetLayerSelection() != UNDEFINED_LAYER )
1141 secondaryEndLayer = ToLAYER_ID( m_backdrillFrontLayer->GetLayerSelection() );
1142
1143 if( !m_backdrillFrontSize.IsIndeterminate() && !m_backdrillFrontSize.IsNull() )
1144 secondaryDrill = m_backdrillFrontSize.GetIntValue();
1145
1146 tertiaryStartLayer = B_Cu;
1147
1148 if( m_backdrillBackLayer->GetLayerSelection() != UNDEFINED_LAYER )
1149 tertiaryEndLayer = ToLAYER_ID( m_backdrillBackLayer->GetLayerSelection() );
1150
1151 if( !m_backdrillBackSize.IsIndeterminate() && !m_backdrillBackSize.IsNull() )
1152 tertiaryDrill = m_backdrillBackSize.GetIntValue();
1153
1154 break;
1155 }
1156 }
1157
1158 // Post Machining
1159 std::optional<PADSTACK::POST_MACHINING_PROPS> frontPostMachining;
1160 std::optional<PADSTACK::POST_MACHINING_PROPS> backPostMachining;
1161
1162 if( m_topPostMachine->GetSelection() != wxNOT_FOUND )
1163 {
1165
1166 switch( m_topPostMachine->GetSelection() )
1167 {
1168 case 1: props.mode = PAD_DRILL_POST_MACHINING_MODE::COUNTERSINK; break;
1169 case 2: props.mode = PAD_DRILL_POST_MACHINING_MODE::COUNTERBORE; break;
1171 }
1172
1173 if( !m_topPostMachineSize1.IsIndeterminate() )
1174 props.size = m_topPostMachineSize1.GetIntValue();
1175
1176 if( !m_topPostMachineSize2.IsIndeterminate() )
1177 {
1179 props.angle = KiROUND( m_topPostMachineSize2.GetDoubleValue() * 10.0 );
1180 else
1181 props.depth = m_topPostMachineSize2.GetIntValue();
1182 }
1183
1184 frontPostMachining = props;
1185 }
1186
1187 if( m_bottomPostMachine->GetSelection() != wxNOT_FOUND )
1188 {
1190
1191 switch( m_bottomPostMachine->GetSelection() )
1192 {
1193 case 1: props.mode = PAD_DRILL_POST_MACHINING_MODE::COUNTERSINK; break;
1194 case 2: props.mode = PAD_DRILL_POST_MACHINING_MODE::COUNTERBORE; break;
1196 }
1197
1198 if( !m_bottomPostMachineSize1.IsIndeterminate() )
1199 props.size = m_bottomPostMachineSize1.GetIntValue();
1200
1201 if( !m_bottomPostMachineSize2.IsIndeterminate() )
1202 {
1204 props.angle = KiROUND( m_bottomPostMachineSize2.GetDoubleValue() * 10.0 );
1205 else
1206 props.depth = m_bottomPostMachineSize2.GetIntValue();
1207 }
1208
1209 backPostMachining = props;
1210 }
1211
1212 int copperLayerCount = m_frame->GetBoard() ? m_frame->GetBoard()->GetCopperLayerCount() : 0;
1213
1214 if( std::optional<PCB_VIA::VIA_PARAMETER_ERROR> error =
1215 PCB_VIA::ValidateViaParameters( viaDiameter, viaDrill, startLayer, endLayer,
1216 secondaryDrill, secondaryStartLayer,
1217 secondaryEndLayer, tertiaryDrill, tertiaryStartLayer,
1218 tertiaryEndLayer, copperLayerCount ) )
1219 {
1220 DisplayError( GetParent(), error->m_Message );
1221
1222 if( error->m_Field == PCB_VIA::VIA_PARAMETER_ERROR::FIELD::DRILL )
1223 {
1224 m_ViaDrillCtrl->SelectAll();
1225 m_ViaDrillCtrl->SetFocus();
1226 }
1227 else if( error->m_Field == PCB_VIA::VIA_PARAMETER_ERROR::FIELD::DIAMETER )
1228 {
1229 m_ViaDiameterCtrl->SelectAll();
1230 m_ViaDiameterCtrl->SetFocus();
1231 }
1232
1233 // Other fields might not have direct focus targets in new UI or I'd need to map them
1234 return false;
1235 }
1236
1237 }
1238
1239 if( m_tracks )
1240 {
1241 if( !m_trackWidth.Validate( GEOMETRY_MIN_SIZE, INT_MAX ) )
1242 return false;
1243 }
1244
1245 // If we survived that, then save the changes:
1246 //
1247 // We don't bother with updating the nets at this point as it will be useless (any connected
1248 // pads will simply drive their existing nets back onto the track segments and vias).
1249
1250 BOARD_COMMIT commit( m_frame );
1251 bool changeLock = m_lockedCbox->Get3StateValue() != wxCHK_UNDETERMINED;
1252 bool setLock = m_lockedCbox->Get3StateValue() == wxCHK_CHECKED;
1253
1254 for( PCB_TRACK* track : selected_tracks )
1255 {
1256
1257 if( !m_standalone )
1258 commit.Modify( track );
1259
1260 switch( track->Type() )
1261 {
1262 case PCB_TRACE_T:
1263 case PCB_ARC_T:
1264 {
1265 wxASSERT( m_tracks );
1266
1267 if( !m_trackStartX.IsIndeterminate() )
1268 track->SetStartX( m_trackStartX.GetIntValue() );
1269
1270 if( !m_trackStartY.IsIndeterminate() )
1271 track->SetStartY( m_trackStartY.GetIntValue() );
1272
1273 if( !m_trackEndX.IsIndeterminate() )
1274 track->SetEndX( m_trackEndX.GetIntValue() );
1275
1276 if( !m_trackEndY.IsIndeterminate() )
1277 track->SetEndY( m_trackEndY.GetIntValue() );
1278
1279 if( !m_trackWidth.IsIndeterminate() )
1280 track->SetWidth( m_trackWidth.GetIntValue() );
1281
1282 if( m_TrackLayerCtrl->GetLayerSelection() != UNDEFINED_LAYER )
1283 track->SetLayer( ToLAYER_ID( m_TrackLayerCtrl->GetLayerSelection() ) );
1284
1285 if ( m_trackHasSolderMask->Get3StateValue() != wxCHK_UNDETERMINED )
1286 track->SetHasSolderMask( m_trackHasSolderMask->GetValue() );
1287
1288 if( !m_trackMaskMargin.IsIndeterminate() )
1289 {
1290 if( m_trackMaskMargin.IsNull() )
1291 track->SetLocalSolderMaskMargin( {} );
1292 else
1293 track->SetLocalSolderMaskMargin( m_trackMaskMargin.GetIntValue() );
1294 }
1295
1296 if( changeLock )
1297 track->SetLocked( setLock );
1298
1299 break;
1300 }
1301
1302 case PCB_VIA_T:
1303 {
1304 wxASSERT( m_vias );
1305 PCB_VIA* via = static_cast<PCB_VIA*>( track );
1306 bool updatePadstack = m_padstackDirty;
1307
1308 // Edit each via's own padstack. Only a mode change replaces it wholesale.
1309 PADSTACK viaStack = m_padstackDirty ? *m_viaStack : via->Padstack();
1310
1311 if( !m_viaX.IsIndeterminate() )
1312 via->SetPosition( VECTOR2I( m_viaX.GetIntValue(), via->GetPosition().y ) );
1313
1314 if( !m_viaY.IsIndeterminate() )
1315 via->SetPosition( VECTOR2I( via->GetPosition().x, m_viaY.GetIntValue() ) );
1316
1317 if( m_viaNotFree->Get3StateValue() != wxCHK_UNDETERMINED )
1318 via->SetIsFree( !m_viaNotFree->GetValue() );
1319
1320 if( !m_viaDiameter.IsIndeterminate() )
1321 {
1322 int newDiameter = m_viaDiameter.GetIntValue();
1323 const VECTOR2I& currentSize = via->Padstack().Size( m_editLayer );
1324
1325 if( currentSize.x != newDiameter || currentSize.y != newDiameter )
1326 {
1327 viaStack.SetSize( { newDiameter, newDiameter }, m_editLayer );
1328 updatePadstack = true;
1329 }
1330 }
1331
1332 // Backdrill
1333 PADSTACK::DRILL_PROPS tertiaryDrill = via->Padstack().TertiaryDrill();
1334 PADSTACK::DRILL_PROPS secondaryDrill = via->Padstack().SecondaryDrill();
1335
1336 if( m_backdrillChoice->GetSelection() != wxNOT_FOUND )
1337 {
1338 switch( static_cast<BACKDRILL_MODE>( m_backdrillChoice->GetSelection() ) )
1339 {
1341 secondaryDrill.start = UNDEFINED_LAYER;
1342 tertiaryDrill.start = UNDEFINED_LAYER;
1343 break;
1344
1346 secondaryDrill.start = UNDEFINED_LAYER;
1347 tertiaryDrill.start = B_Cu;
1348 tertiaryDrill.shape = PAD_DRILL_SHAPE::CIRCLE;
1349
1350 if( !m_backdrillBackSize.IsIndeterminate() && !m_backdrillBackSize.IsNull() )
1351 {
1352 tertiaryDrill.size = VECTOR2I( m_backdrillBackSize.GetIntValue(),
1353 m_backdrillBackSize.GetIntValue() );
1354 }
1355
1356 if( m_backdrillBackLayer->GetLayerSelection() != UNDEFINED_LAYER )
1357 tertiaryDrill.end = ToLAYER_ID( m_backdrillBackLayer->GetLayerSelection() );
1358
1359 break;
1360
1362 secondaryDrill.start = F_Cu;
1363 secondaryDrill.shape = PAD_DRILL_SHAPE::CIRCLE;
1364 tertiaryDrill.start = UNDEFINED_LAYER;
1365
1366 if( !m_backdrillFrontSize.IsIndeterminate() && !m_backdrillFrontSize.IsNull() )
1367 {
1368 secondaryDrill.size = VECTOR2I( m_backdrillFrontSize.GetIntValue(),
1369 m_backdrillFrontSize.GetIntValue() );
1370 }
1371
1372 if( m_backdrillFrontLayer->GetLayerSelection() != UNDEFINED_LAYER )
1373 secondaryDrill.end = ToLAYER_ID( m_backdrillFrontLayer->GetLayerSelection() );
1374
1375 break;
1376
1378 secondaryDrill.start = F_Cu;
1379 secondaryDrill.shape = PAD_DRILL_SHAPE::CIRCLE;
1380 tertiaryDrill.start = B_Cu;
1381 tertiaryDrill.shape = PAD_DRILL_SHAPE::CIRCLE;
1382
1383 if(! m_backdrillFrontSize.IsIndeterminate() && !m_backdrillFrontSize.IsNull() )
1384 {
1385 secondaryDrill.size = VECTOR2I( m_backdrillFrontSize.GetIntValue(),
1386 m_backdrillFrontSize.GetIntValue() );
1387 }
1388
1389 if( m_backdrillFrontLayer->GetLayerSelection() != UNDEFINED_LAYER )
1390 secondaryDrill.end = ToLAYER_ID( m_backdrillFrontLayer->GetLayerSelection() );
1391
1392 if( !m_backdrillBackSize.IsIndeterminate() && !m_backdrillBackSize.IsNull() )
1393 {
1394 tertiaryDrill.size = VECTOR2I( m_backdrillBackSize.GetIntValue(),
1395 m_backdrillBackSize.GetIntValue() );
1396 }
1397
1398 if( m_backdrillBackLayer->GetLayerSelection() != UNDEFINED_LAYER )
1399 tertiaryDrill.end = ToLAYER_ID( m_backdrillBackLayer->GetLayerSelection() );
1400
1401 break;
1402 }
1403 }
1404 else
1405 {
1406 if( !m_backdrillFrontSize.IsIndeterminate() && !m_backdrillFrontSize.IsNull() )
1407 {
1408 secondaryDrill.size = VECTOR2I( m_backdrillFrontSize.GetIntValue(),
1409 m_backdrillFrontSize.GetIntValue() );
1410 }
1411
1412 if( !m_backdrillBackSize.IsIndeterminate() && !m_backdrillBackSize.IsNull() )
1413 {
1414 tertiaryDrill.size = VECTOR2I( m_backdrillBackSize.GetIntValue(),
1415 m_backdrillBackSize.GetIntValue() );
1416 }
1417 }
1418
1419 viaStack.SecondaryDrill() = secondaryDrill;
1420
1421 if( via->Padstack().SecondaryDrill() != secondaryDrill )
1422 updatePadstack = true;
1423
1424 viaStack.TertiaryDrill() = tertiaryDrill;
1425
1426 if( via->Padstack().TertiaryDrill() != tertiaryDrill )
1427 updatePadstack = true;
1428
1429 // Post Machining
1430 if( m_topPostMachine->GetSelection() != wxNOT_FOUND )
1431 {
1432 PADSTACK::POST_MACHINING_PROPS props = via->Padstack().FrontPostMachining();
1433
1434 switch( m_topPostMachine->GetSelection() )
1435 {
1436 case 1: props.mode = PAD_DRILL_POST_MACHINING_MODE::COUNTERSINK; break;
1437 case 2: props.mode = PAD_DRILL_POST_MACHINING_MODE::COUNTERBORE; break;
1439 }
1440
1441 if( !m_topPostMachineSize1.IsIndeterminate() )
1442 props.size = m_topPostMachineSize1.GetIntValue();
1443
1444 if( !m_topPostMachineSize2.IsIndeterminate() )
1445 {
1447 props.angle = KiROUND( m_topPostMachineSize2.GetDoubleValue() * 10.0 );
1448 else
1449 props.depth = m_topPostMachineSize2.GetIntValue();
1450 }
1451
1452 viaStack.FrontPostMachining() = props;
1453
1454 if( via->Padstack().FrontPostMachining() != props )
1455 updatePadstack = true;
1456 }
1457
1458 if( m_bottomPostMachine->GetSelection() != wxNOT_FOUND )
1459 {
1460 PADSTACK::POST_MACHINING_PROPS props = via->Padstack().BackPostMachining();
1461
1462 switch( m_bottomPostMachine->GetSelection() )
1463 {
1464 case 1: props.mode = PAD_DRILL_POST_MACHINING_MODE::COUNTERSINK; break;
1465 case 2: props.mode = PAD_DRILL_POST_MACHINING_MODE::COUNTERBORE; break;
1467 }
1468
1469 if( !m_bottomPostMachineSize1.IsIndeterminate() )
1470 props.size = m_bottomPostMachineSize1.GetIntValue();
1471
1472 if( !m_bottomPostMachineSize2.IsIndeterminate() )
1473 {
1475 props.angle = KiROUND( m_bottomPostMachineSize2.GetDoubleValue() * 10.0 );
1476 else
1477 props.depth = m_bottomPostMachineSize2.GetIntValue();
1478 }
1479
1480 viaStack.BackPostMachining() = props;
1481
1482 if( via->Padstack().BackPostMachining() != props )
1483 updatePadstack = true;
1484 }
1485
1486 switch( m_ViaTypeChoice->GetSelection() )
1487 {
1488 case 0: via->SetViaType( VIATYPE::THROUGH ); break;
1489 case 1: via->SetViaType( VIATYPE::MICROVIA ); break;
1490 case 2: via->SetViaType( VIATYPE::BLIND ); break;
1491 case 3: via->SetViaType( VIATYPE::BURIED ); break;
1492 default: break;
1493 }
1494
1495 PCB_LAYER_ID startLayer = static_cast<PCB_LAYER_ID>( m_ViaStartLayer->GetLayerSelection() );
1496 PCB_LAYER_ID endLayer = static_cast<PCB_LAYER_ID>( m_ViaEndLayer->GetLayerSelection() );
1497
1498 if( startLayer != UNDEFINED_LAYER )
1499 {
1500 viaStack.Drill().start = startLayer;
1501
1502 if( via->Padstack().Drill().start != startLayer )
1503 updatePadstack = true;
1504
1505 via->SetTopLayer( startLayer );
1506 }
1507
1508 if( endLayer != UNDEFINED_LAYER )
1509 {
1510 viaStack.Drill().end = endLayer;
1511
1512 if( via->Padstack().Drill().end != endLayer )
1513 updatePadstack = true;
1514
1515 via->SetBottomLayer( endLayer );
1516 }
1517
1518 if( updatePadstack )
1519 {
1520 via->SetPadstack( viaStack );
1521 via->SanitizeLayers();
1522 }
1523
1524 switch( m_annularRingsCtrl->GetSelection() )
1525 {
1526 case 0:
1527 via->Padstack().SetUnconnectedLayerMode( UNCONNECTED_LAYER_MODE::KEEP_ALL );
1528 break;
1529 case 1:
1530 via->Padstack().SetUnconnectedLayerMode( UNCONNECTED_LAYER_MODE::REMOVE_EXCEPT_START_AND_END );
1531 break;
1532 case 2:
1533 via->Padstack().SetUnconnectedLayerMode( UNCONNECTED_LAYER_MODE::REMOVE_ALL );
1534 break;
1535 case 3:
1536 via->Padstack().SetUnconnectedLayerMode( UNCONNECTED_LAYER_MODE::START_END_ONLY );
1537 break;
1538 default:
1539 break;
1540 }
1541
1542
1543 if( !m_viaDrill.IsIndeterminate() )
1544 via->SetDrill( m_viaDrill.GetIntValue() );
1545
1546 TEARDROP_PARAMETERS* targetParams = &via->GetTeardropParams();
1547
1548 if( m_cbTeardrops->Get3StateValue() != wxCHK_UNDETERMINED )
1549 targetParams->m_Enabled = m_cbTeardrops->GetValue();
1550
1551 if( m_cbTeardropsUseNextTrack->Get3StateValue() != wxCHK_UNDETERMINED )
1552 targetParams->m_AllowUseTwoTracks = m_cbTeardropsUseNextTrack->GetValue();
1553
1554 if( !m_teardropMaxLen.IsIndeterminate() )
1555 targetParams->m_TdMaxLen = m_teardropMaxLen.GetIntValue();
1556
1557 if( !m_teardropMaxWidth.IsIndeterminate() )
1558 targetParams->m_TdMaxWidth = m_teardropMaxWidth.GetIntValue();
1559
1560 if( !m_teardropLenPercent.IsIndeterminate() )
1561 targetParams->m_BestLengthRatio = m_teardropLenPercent.GetDoubleValue() / 100.0;
1562
1563 if( !m_teardropWidthPercent.IsIndeterminate() )
1564 targetParams->m_BestWidthRatio = m_teardropWidthPercent.GetDoubleValue() / 100.0;
1565
1566 if( !m_teardropHDPercent.IsIndeterminate() )
1567 targetParams->m_WidthtoSizeFilterRatio = m_teardropHDPercent.GetDoubleValue() / 100.0;
1568
1569 if( m_curvedEdges->Get3StateValue() != wxCHK_UNDETERMINED )
1570 targetParams->m_CurvedEdges = m_curvedEdges->GetValue();
1571
1572 if( changeLock )
1573 via->SetLocked( setLock );
1574
1575 setViaConfiguration( via, static_cast<IPC4761_PRESET>( m_protectionFeatures->GetSelection() ) );
1576 break;
1577 }
1578
1579 default:
1580 UNIMPLEMENTED_FOR( track->GetClass() );
1581 break;
1582 }
1583 }
1584
1585 std::set<int> shortingNets;
1586 int newNetCode = m_netSelector->GetSelectedNetcode();
1587 std::set<PAD*> changingPads;
1588
1589 // Do NOT use the connectivity code here. It will propagate through zones, and we haven't
1590 // refilled those yet so it's going to pick up a whole bunch of other nets any time the track
1591 // width was increased.
1592 auto collide =
1594 {
1595 for( PCB_LAYER_ID layer : LSET( a->GetLayerSet() & b->GetLayerSet() ) )
1596 {
1597 if( a->GetEffectiveShape( layer )->Collide( b->GetEffectiveShape( layer ).get() ) )
1598 return true;
1599 }
1600
1601 return false;
1602 };
1603
1604 for( PCB_TRACK* track : connected_tracks )
1605 {
1606 for( PCB_TRACK* other : m_frame->GetBoard()->Tracks() )
1607 {
1608 if( other->GetNetCode() == track->GetNetCode() || other->GetNetCode() == newNetCode )
1609 continue;
1610
1611 if( collide( track, other ) )
1612 shortingNets.insert( other->GetNetCode() );
1613 }
1614
1615 for( FOOTPRINT* footprint : m_frame->GetBoard()->Footprints() )
1616 {
1617 for( PAD* pad : footprint->Pads() )
1618 {
1619 if( pad->GetNetCode() == newNetCode )
1620 continue;
1621
1622 if( collide( track, pad ) )
1623 {
1624 if( pad->GetNetCode() == track->GetNetCode() )
1625 changingPads.insert( pad );
1626 else
1627 shortingNets.insert( pad->GetNetCode() );
1628 }
1629 }
1630 }
1631 }
1632
1633 if( shortingNets.size() && !confirmShortingNets( newNetCode, shortingNets ) )
1634 {
1635 commit.Revert();
1636 return true;
1637 }
1638
1639 if( !m_netSelector->IsIndeterminate() )
1640 {
1641 if( changingPads.empty() || confirmPadChange( changingPads ) )
1642 {
1643 for( PCB_TRACK* track : connected_tracks )
1644 {
1645 if( !alg::contains( selected_tracks, track ) )
1646 commit.Modify( track );
1647
1648 track->SetNetCode( newNetCode );
1649 }
1650
1651 for( PAD* pad : changingPads )
1652 {
1653 commit.Modify( pad );
1654 pad->SetNetCode( newNetCode );
1655 }
1656 }
1657 }
1658
1659 if( !m_standalone )
1660 commit.Push( _( "Edit Track/Via Properties" ) );
1661
1662 return true;
1663}
1664
1665
1667{
1668 m_viaNotFree->SetValue( false );
1669}
1670
1671
1673{
1674 if( !m_tracks )
1675 {
1676 m_netSelectorLabel->Enable( !m_viaNotFree->GetValue() );
1677 m_netSelector->Enable( !m_viaNotFree->GetValue() );
1678 }
1679}
1680
1681
1683{
1684 m_TrackWidthCtrl->ChangeValue( m_predefinedTrackWidthsCtrl->GetStringSelection() );
1685 m_TrackWidthCtrl->SelectAll();
1686}
1687
1688
1689void DIALOG_TRACK_VIA_PROPERTIES::onWidthEdit( wxCommandEvent& aEvent )
1690{
1691 m_predefinedTrackWidthsCtrl->SetStringSelection( m_TrackWidthCtrl->GetValue() );
1692}
1693
1694
1695void DIALOG_TRACK_VIA_PROPERTIES::onViaSelect( wxCommandEvent& aEvent )
1696{
1697 VIA_DIMENSION* viaDimension = static_cast<VIA_DIMENSION*> ( aEvent.GetClientData() );
1698
1699 m_viaDiameter.ChangeValue( viaDimension->m_Diameter );
1700 m_viaDrill.ChangeValue( viaDimension->m_Drill );
1701}
1702
1703
1705{
1706 wxCHECK_MSG( m_viaStack, /* void */, "Expected valid via stack in onPadstackModeChanged" );
1707
1708 switch( m_cbPadstackMode->GetSelection() )
1709 {
1710 default:
1711 case 0: m_viaStack->SetMode( PADSTACK::MODE::NORMAL ); break;
1712 case 1: m_viaStack->SetMode( PADSTACK::MODE::FRONT_INNER_BACK ); break;
1713 case 2: m_viaStack->SetMode( PADSTACK::MODE::CUSTOM ); break;
1714 }
1715
1716 m_padstackDirty = true;
1717
1719}
1720
1721
1723{
1724 wxCHECK_MSG( m_viaStack, /* void */, "Expected valid via stack in onEditLayerChanged" );
1725
1726 // Save data from the previous layer
1727 if( !m_viaDiameter.IsIndeterminate() )
1728 {
1729 int diameter = m_viaDiameter.GetIntValue();
1730 const VECTOR2I& currentSize = m_viaStack->Size( m_editLayer );
1731
1732 if( currentSize.x != diameter || currentSize.y != diameter )
1733 {
1734 m_viaStack->SetSize( { diameter, diameter }, m_editLayer );
1735 m_padstackDirty = true;
1736 }
1737 }
1738
1739 switch( m_viaStack->Mode() )
1740 {
1741 default:
1744 break;
1745
1747 switch( m_cbEditLayer->GetSelection() )
1748 {
1749 default:
1750 case 0: m_editLayer = F_Cu; break;
1751 case 1: m_editLayer = PADSTACK::INNER_LAYERS; break;
1752 case 2: m_editLayer = B_Cu; break;
1753 }
1754 break;
1755
1757 {
1758 int layer = m_cbEditLayer->GetSelection();
1759
1760 if( layer < 0 )
1761 layer = 0;
1762
1763 if( m_editLayerCtrlMap.contains( layer ) )
1764 m_editLayer = m_editLayerCtrlMap.at( layer );
1765 else
1766 m_editLayer = F_Cu;
1767 }
1768 }
1769
1770 // Load controls with the current layer
1771 m_viaDiameter.SetValue( m_viaStack->Size( m_editLayer ).x );
1772}
1773
1774
1776{
1777 // NOTE: synchronize changes here with DIALOG_PAD_PROPERTIES::afterPadstackModeChanged
1778
1779 wxCHECK_MSG( m_viaStack, /* void */, "Expected valid via stack in afterPadstackModeChanged" );
1780 m_cbEditLayer->Clear();
1781
1782 BOARD* board = m_frame->GetBoard();
1783
1784 switch( m_viaStack->Mode() )
1785 {
1787 m_cbPadstackMode->SetSelection( 0 );
1788 m_cbEditLayer->Append( _( "All layers" ) );
1789 m_cbEditLayer->Disable();
1792 break;
1793
1795 {
1796 m_cbPadstackMode->SetSelection( 1 );
1797 m_cbEditLayer->Enable();
1798
1799 std::vector choices = {
1800 board->GetLayerName( F_Cu ),
1801 _( "Inner Layers" ),
1802 board->GetLayerName( B_Cu )
1803 };
1804
1805 m_cbEditLayer->Append( choices );
1806
1808 { 0, F_Cu },
1810 { 2, B_Cu }
1811 };
1812
1813 if( m_editLayer != F_Cu && m_editLayer != B_Cu )
1815
1816 break;
1817 }
1818
1820 {
1821 m_cbPadstackMode->SetSelection( 2 );
1822 m_cbEditLayer->Enable();
1823 LSET layers = LSET::AllCuMask() & board->GetEnabledLayers();
1824
1825 for( PCB_LAYER_ID layer : layers.UIOrder() )
1826 {
1827 int idx = m_cbEditLayer->Append( board->GetLayerName( layer ) );
1828 m_editLayerCtrlMap[idx] = layer;
1829 }
1830
1831 break;
1832 }
1833 }
1834
1835 for( const auto& [idx, layer] : m_editLayerCtrlMap )
1836 {
1837 if( layer == m_editLayer )
1838 {
1839 m_cbEditLayer->SetSelection( idx );
1840 break;
1841 }
1842 }
1843}
1844
1845
1847{
1848 int viaType = m_ViaTypeChoice->GetSelection();
1849
1850 if( viaType <= 0 )
1851 return m_frame->GetBoard()->GetCopperLayerCount() - 1;
1852
1853 int startLayer = m_ViaStartLayer->GetLayerSelection();
1854 int endLayer = m_ViaEndLayer->GetLayerSelection();
1855
1856 if( startLayer < 0 || endLayer < 0 )
1857 return m_frame->GetBoard()->GetCopperLayerCount() - 1;
1858 else
1859 return m_frame->GetBoard()->LayerDepth( ToLAYER_ID( startLayer ), ToLAYER_ID( endLayer ) );
1860}
1861
1862
1863void DIALOG_TRACK_VIA_PROPERTIES::onViaEdit( wxCommandEvent& aEvent )
1864{
1865 m_predefinedViaSizesCtrl->SetSelection( wxNOT_FOUND );
1866
1867 if( m_vias )
1868 {
1869 if( m_ViaTypeChoice->GetSelection() != 0 ) // check if selected type isn't through.
1870 {
1871 m_ViaStartLayer->Enable();
1872 m_ViaEndLayer->Enable();
1873 }
1874 else
1875 {
1876 m_ViaStartLayer->SetLayerSelection( F_Cu );
1877 m_ViaEndLayer->SetLayerSelection( B_Cu );
1878
1879 m_ViaStartLayer->Enable( false );
1880 m_ViaEndLayer->Enable( false );
1881 }
1882
1883 m_annularRingsLabel->Show( getLayerDepth() > 1 );
1884 m_annularRingsCtrl->Show( getLayerDepth() > 1 );
1885 m_annularRingsCtrl->Enable( true );
1886 }
1887}
1888
1889
1890void DIALOG_TRACK_VIA_PROPERTIES::onTrackEdit( wxCommandEvent& aEvent )
1891{
1892 bool externalCuLayer = m_TrackLayerCtrl->GetLayerSelection() == F_Cu
1893 || m_TrackLayerCtrl->GetLayerSelection() == B_Cu;
1894
1895 m_techLayersLabel->Enable( externalCuLayer );
1896 m_trackHasSolderMask->Enable( externalCuLayer );
1897
1898 bool showMaskMargin = externalCuLayer && m_trackHasSolderMask->GetValue();
1899
1900 m_trackMaskMarginCtrl->Enable( showMaskMargin );
1901 m_trackMaskMarginLabel->Enable( showMaskMargin );
1902 m_trackMaskMarginUnit->Enable( showMaskMargin );
1903}
1904
1905
1907{
1908 event.Enable( !m_frame->GetBoard()->LegacyTeardrops() );
1909}
1910
1911
1913{
1914 int selection = m_backdrillChoice->GetSelection();
1915 // 0: None, 1: Bottom, 2: Top, 3: Both
1916
1917 bool enableTop = ( selection == 2 || selection == 3 );
1918 bool enableBottom = ( selection == 1 || selection == 3 );
1919
1920 m_backdrillFrontSize.Enable( enableTop );
1921 m_backdrillFrontLayer->Enable( enableTop );
1922 m_backdrillFrontLayerLabel->Enable( enableTop );
1923
1924 m_backdrillBackSize.Enable( enableBottom );
1925 m_backdrillBackLayer->Enable( enableBottom ); // Back layer selector
1926 m_backdrillBackLayerLabel->Enable( enableBottom ); // Back layer label
1927
1928 // Initialize values if this was a user event that turned on backdrills
1929 if( aEvent.GetEventObject() )
1930 {
1931 if( enableTop )
1932 {
1933 if( m_backdrillFrontLayer->GetLayerSelection() == UNDEFINED_LAYER )
1934 m_backdrillFrontLayer->SetLayerSelection( F_Cu );
1935
1936 if( m_backdrillFrontSize.GetIntValue() == 0 )
1937 {
1938 // Initialize backdrill slightly larger than main drill (see PADSTACK::SetBackdrillMode())
1939 m_backdrillFrontSize.SetValue( KiROUND( m_viaDrill.GetIntValue() * 1.1 ) );
1940 }
1941 }
1942
1943 if( enableBottom )
1944 {
1945 if( m_backdrillBackLayer->GetLayerSelection() == UNDEFINED_LAYER )
1946 m_backdrillBackLayer->SetLayerSelection( B_Cu );
1947
1948 if( m_backdrillBackSize.GetIntValue() == 0 )
1949 {
1950 // Initialize backdrill slightly larger than main drill (see PADSTACK::SetBackdrillMode())
1951 m_backdrillBackSize.SetValue( KiROUND( m_viaDrill.GetIntValue() * 1.1 ) );
1952 }
1953 }
1954 }
1955}
1956
1957
1959{
1960 int selection = m_topPostMachine->GetSelection();
1961 // 0: None, 1: Countersink, 2: Counterbore
1962
1963 bool enable = ( selection != 0 );
1964 m_topPostMachineSize1.Enable( enable );
1965 m_topPostMachineSize2.Enable( enable );
1966 m_topPostMachineSize1Label->Enable( enable );
1967 m_topPostMachineSize2Label->Enable( enable );
1968
1969 if( selection == 1 ) // Countersink
1970 {
1971 m_topPostMachineSize2Label->SetLabel( _( "Angle:" ) );
1972 m_topPostMachineSize2Units->SetLabel( _( "deg" ) );
1974 }
1975 else if( selection == 2 ) // Counterbore
1976 {
1977 m_topPostMachineSize2Label->SetLabel( _( "Depth:" ) );
1978 m_topPostMachineSize2Units->SetLabel( EDA_UNIT_UTILS::GetLabel( m_frame->GetUserUnits() ) );
1979 m_topPostMachineSize2.SetUnits( m_frame->GetUserUnits() );
1980 }
1981 else
1982 {
1983 m_topPostMachineSize2Label->SetLabel( _( "Angle:" ) );
1984 m_topPostMachineSize2Units->SetLabel( _( "deg" ) );
1986 }
1987
1988 // Initialize values if this was a user event that turned on post machining
1989 if( aEvent.GetEventObject() )
1990 {
1991 if( selection == 1 )
1992 {
1993 if( m_topPostMachineSize2.IsIndeterminate() || m_topPostMachineSize2.GetDoubleValue() == 0 )
1994 m_topPostMachineSize2.SetDoubleValue( 82.0 );
1995 }
1996 }
1997}
1998
1999
2001{
2002 int selection = m_bottomPostMachine->GetSelection();
2003 // 0: None, 1: Countersink, 2: Counterbore
2004
2005 bool enable = ( selection != 0 );
2006 m_bottomPostMachineSize1.Enable( enable );
2007 m_bottomPostMachineSize2.Enable( enable );
2008 m_bottomPostMachineSize1Label->Enable( enable );
2009 m_bottomPostMachineSize2Label->Enable( enable );
2010
2011 if( selection == 1 ) // Countersink
2012 {
2013 m_bottomPostMachineSize2Label->SetLabel( _( "Angle:" ) );
2014 m_bottomPostMachineSize2Units->SetLabel( _( "deg" ) );
2016 }
2017 else if( selection == 2 ) // Counterbore
2018 {
2019 m_bottomPostMachineSize2Label->SetLabel( _( "Depth:" ) );
2020 m_bottomPostMachineSize2Units->SetLabel( EDA_UNIT_UTILS::GetLabel( m_frame->GetUserUnits() ) );
2021 m_bottomPostMachineSize2.SetUnits( m_frame->GetUserUnits() );
2022 }
2023
2024 // Initialize values if this was a user event that turned on post machining
2025 if( aEvent.GetEventObject() )
2026 {
2027 if( selection == 1 )
2028 {
2029 if( m_bottomPostMachineSize2.IsIndeterminate() || m_bottomPostMachineSize2.GetDoubleValue() == 0 )
2030 m_bottomPostMachineSize2.SetDoubleValue( 82.0 );
2031 }
2032 }
2033}
2034
2035
const char * name
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:106
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:982
void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
void Revert() override
Revert the commit by restoring the modified items state.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
TEARDROP_PARAMETERS & GetTeardropParams()
bool IsLocked() const override
FOOTPRINT * GetParentFootprint() const
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition board_item.h:355
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT, DRC_CONSTRAINT_T aUsage=NULL_CONSTRAINT) const
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:411
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition board.cpp:932
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition board.cpp:1174
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:102
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition dialog_shim.h:94
void SetupStandardButtons(std::map< int, wxString > aLabels={})
bool m_useCalculatedSize
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
DIALOG_TRACK_VIA_PROPERTIES_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Track & Via Properties"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxSYSTEM_MENU)
void onWidthEdit(wxCommandEvent &aEvent) override
void onUnitsChanged(wxCommandEvent &aEvent)
void onNetSelector(wxCommandEvent &aEvent)
void onWidthSelect(wxCommandEvent &aEvent) override
bool confirmShortingNets(int aNet, const std::set< int > &shortingNets)
bool m_standalone
Dialog was constructed for a standalone via (via stitching.
void onTeardropsUpdateUi(wxUpdateUIEvent &event) override
void onPadstackModeChanged(wxCommandEvent &aEvent) override
void onBackdrillChange(wxCommandEvent &aEvent) override
void onViaEdit(wxCommandEvent &aEvent) override
std::map< int, PCB_LAYER_ID > m_editLayerCtrlMap
PCB_LAYER_ID m_editLayer
The currently-shown copper layer of the edited via(s)
void onViaSelect(wxCommandEvent &aEvent) override
bool TransferDataToWindow() override
Get data from the PCB board and display it to dialog.
void onBottomPostMachineChange(wxCommandEvent &aEvent) override
void onEditLayerChanged(wxCommandEvent &aEvent) override
void onTopPostMachineChange(wxCommandEvent &aEvent) override
void onViaNotFreeClicked(wxCommandEvent &aEvent) override
void commonInit(PCB_BASE_EDIT_FRAME *aParent)
DIALOG_TRACK_VIA_PROPERTIES(PCB_BASE_EDIT_FRAME *aParent, const PCB_SELECTION &aItems)
std::unique_ptr< PADSTACK > m_viaStack
Temporary padstack of the edited via(s)
PCB_SELECTION m_viaStandaloneSelection
Used for standalone via mode to flow through the normal update logic.
bool confirmPadChange(const std::set< PAD * > &connectedPads)
void onTrackEdit(wxCommandEvent &aEvent) override
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
const wxString & GetReference() const
Definition footprint.h:793
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition kidialog.h:38
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:48
int ShowModal() override
Definition kidialog.cpp:89
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:604
LSEQ UIOrder() const
Return the copper, technical and user layers in the order shown in layer widget.
Definition lset.cpp:739
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition lset.cpp:623
A PADSTACK defines the characteristics of a single or multi-layer pad, in the IPC sense of the word.
Definition padstack.h:156
POST_MACHINING_PROPS & FrontPostMachining()
Definition padstack.h:367
DRILL_PROPS & TertiaryDrill()
Definition padstack.h:364
DRILL_PROPS & Drill()
Definition padstack.h:358
@ NORMAL
Shape is the same on all layers.
Definition padstack.h:170
@ CUSTOM
Shapes can be defined on arbitrary layers.
Definition padstack.h:172
@ FRONT_INNER_BACK
Up to three shapes can be defined (F_Cu, inner copper layers, B_Cu)
Definition padstack.h:171
DRILL_PROPS & SecondaryDrill()
Definition padstack.h:361
POST_MACHINING_PROPS & BackPostMachining()
Definition padstack.h:370
void SetSize(const VECTOR2I &aSize, PCB_LAYER_ID aLayer)
Definition padstack.cpp:856
static constexpr PCB_LAYER_ID ALL_LAYERS
! The layer identifier to use for the single defintion on normal padstacks
Definition padstack.h:179
static constexpr PCB_LAYER_ID INNER_LAYERS
! The layer identifier to use for "inner layers" on top/inner/bottom padstacks
Definition padstack.h:182
Definition pad.h:61
const wxString & GetNumber() const
Definition pad.h:143
Common, abstract interface for edit frames.
bool HasSolderMask() const
Definition pcb_track.h:122
int GetStartY() const
Definition pcb_track.h:104
int GetEndX() const
Definition pcb_track.h:109
std::optional< int > GetLocalSolderMaskMargin() const
Definition pcb_track.h:125
int GetEndY() const
Definition pcb_track.h:110
int GetStartX() const
Definition pcb_track.h:103
virtual int GetWidth() const
Definition pcb_track.h:92
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:860
PCB_LAYER_ID BottomLayer() const
VECTOR2I GetPosition() const override
Definition pcb_track.h:603
const PADSTACK & Padstack() const
Definition pcb_track.h:431
static std::optional< VIA_PARAMETER_ERROR > ValidateViaParameters(std::optional< int > aDiameter, std::optional< int > aPrimaryDrill, std::optional< PCB_LAYER_ID > aPrimaryStartLayer=std::nullopt, std::optional< PCB_LAYER_ID > aPrimaryEndLayer=std::nullopt, std::optional< int > aSecondaryDrill=std::nullopt, std::optional< PCB_LAYER_ID > aSecondaryStartLayer=std::nullopt, std::optional< PCB_LAYER_ID > aSecondaryEndLayer=std::nullopt, std::optional< int > aTertiaryDrill=std::nullopt, std::optional< PCB_LAYER_ID > aTertiaryStartLayer=std::nullopt, std::optional< PCB_LAYER_ID > aTertiaryEndLayer=std::nullopt, int aCopperLayerCount=0)
int GetWidth() const override
PCB_LAYER_ID TopLayer() const
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
VIATYPE GetViaType() const
Definition pcb_track.h:422
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const
Check if the boundary of shape (this) lies closer to the point aP than aClearance,...
Definition shape.h:181
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.
IPC4761_PRESET getViaConfiguration(const PCB_VIA *aVia)
const std::map< IPC4761_PRESET, wxString > m_IPC4761Names
void setViaConfiguration(PCB_VIA *aVia, const IPC4761_PRESET &aPreset)
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:192
This file is part of the common library.
#define EXCLUDE_ZONES
#define _(s)
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ B_Cu
Definition layer_ids.h:61
@ UNDEFINED_LAYER
Definition layer_ids.h:57
@ F_Cu
Definition layer_ids.h:60
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition lset.cpp:750
This file contains miscellaneous commonly used macros and functions.
#define UNIMPLEMENTED_FOR(type)
Definition macros.h:92
KICOMMON_API wxString GetLabel(EDA_UNITS aUnits, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Get the units string for a given units type.
KICOMMON_API wxFont GetInfoFont(wxWindow *aWindow)
KICOMMON_API wxFont GetSmallInfoFont(wxWindow *aWindow)
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition kicad_algo.h:96
BACKDRILL_MODE
Definition padstack.h:83
#define GEOMETRY_MIN_SIZE
Definition pcb_track.h:58
VIATYPE
bool collide(T aObject, U aAnotherObject, int aLayer, int aMinDistance)
Used by SHAPE_INDEX to implement Query().
The properties of a padstack drill.
Definition padstack.h:272
PCB_LAYER_ID start
Definition padstack.h:275
PCB_LAYER_ID end
Definition padstack.h:276
VECTOR2I size
Drill diameter (x == y) or slot dimensions (x != y)
Definition padstack.h:273
PAD_DRILL_SHAPE shape
Definition padstack.h:274
std::optional< PAD_DRILL_POST_MACHINING_MODE > mode
Definition padstack.h:287
Container to handle a stock of specific vias each with unique diameter and drill sizes in the BOARD c...
KIBIS top(path, &reporter)
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition typeinfo.h:89
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition typeinfo.h:90
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition typeinfo.h:88
#define INDETERMINATE_ACTION
Definition ui_common.h:48
#define INDETERMINATE_STATE
Used for holding indeterminate values, such as with multiple selections holding different values or c...
Definition ui_common.h:47
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708