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