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 bool top = topDrill.end != UNDEFINED_LAYER && topDrill.size.x > 0;
363 bool bottom = bottomDrill.end != UNDEFINED_LAYER && bottomDrill.size.x > 0;
364
365 if( top && bottom )
366 backdrill_dir = BACKDRILL_MODE::BACKDRILL_BOTH;
367 else if( bottom )
368 backdrill_dir = BACKDRILL_MODE::BACKDRILL_BOTTOM;
369 else if( top )
370 backdrill_dir = BACKDRILL_MODE::BACKDRILL_TOP;
371 else
372 backdrill_dir = BACKDRILL_MODE::NO_BACKDRILL;
373
374 selection_first_layer = v->TopLayer();
375 selection_last_layer = v->BottomLayer();
376
377 m_cbTeardrops->SetValue( v->GetTeardropParams().m_Enabled );
381 m_teardropLenPercent.SetDoubleValue( v->GetTeardropParams().m_BestLengthRatio*100.0 );
382 m_teardropWidthPercent.SetDoubleValue( v->GetTeardropParams().m_BestWidthRatio*100.0 );
385
387
388 if( preset >= IPC4761_PRESET::CUSTOM )
390 else
391 m_protectionFeatures->SetSelection( static_cast<int>( preset ) );
392 }
393 else // check if values are the same for every selected via
394 {
395 if( m_viaX.GetValue() != v->GetPosition().x )
396 m_viaX.SetValue( INDETERMINATE_STATE );
397
398 if( m_viaY.GetValue() != v->GetPosition().y )
399 m_viaY.SetValue( INDETERMINATE_STATE );
400
401 if( m_viaDiameter.GetValue() != v->GetWidth( m_editLayer ) )
403
404 if( m_viaDrill.GetValue() != v->GetDrillValue() )
406
407 if( viaType != v->GetViaType() )
408 viaType = VIATYPE::NOT_DEFINED;
409
410 if( v->GetIsFree() != !m_viaNotFree->GetValue() )
411 m_viaNotFree->Set3StateValue( wxCHK_UNDETERMINED );
412
413 if( selection_first_layer != v->TopLayer() )
414 selection_first_layer = UNDEFINED_LAYER;
415
416 if( selection_last_layer != v->BottomLayer() )
417 selection_last_layer = UNDEFINED_LAYER;
418
419 if( m_annularRingsCtrl->GetSelection() != getAnnularRingSelection( v ) )
420 {
421 if( m_annularRingsCtrl->GetStrings().size() < 4 )
423
424 m_annularRingsCtrl->SetSelection( 3 );
425 }
426
427 if( m_cbTeardrops->GetValue() != v->GetTeardropParams().m_Enabled )
428 m_cbTeardrops->Set3StateValue( wxCHK_UNDETERMINED );
429
431 m_cbTeardropsUseNextTrack->Set3StateValue( wxCHK_UNDETERMINED );
432
433 if( m_teardropMaxLen.GetValue() != v->GetTeardropParams().m_TdMaxLen )
435
436 if( m_teardropMaxWidth.GetValue() != v->GetTeardropParams().m_TdMaxWidth )
438
439 if( m_teardropLenPercent.GetDoubleValue() != v->GetTeardropParams().m_BestLengthRatio *100.0 )
441
442 if( m_teardropWidthPercent.GetDoubleValue() != v->GetTeardropParams().m_BestWidthRatio *100.0 )
444
445 if( m_teardropHDPercent.GetDoubleValue() != v->GetTeardropParams().m_WidthtoSizeFilterRatio*100.0 )
447
448 if( static_cast<int>( getViaConfiguration( v ) ) != m_protectionFeatures->GetSelection() )
450
451 if( primary_post_machining_set )
452 {
453 if( primary_post_machining_value != v->Padstack().FrontPostMachining().mode )
454 primary_post_machining_mixed = true;
455
456 if( primary_post_machining_size != v->Padstack().FrontPostMachining().size )
457 primary_post_machining_size_mixed = true;
458
459 if( primary_post_machining_depth != v->Padstack().FrontPostMachining().depth )
460 primary_post_machining_depth_mixed = true;
461
462 if( primary_post_machining_angle != v->Padstack().FrontPostMachining().angle )
463 primary_post_machining_angle_mixed = true;
464 }
465
466 if( secondary_post_machining_set )
467 {
468 if( secondary_post_machining_value != v->Padstack().BackPostMachining().mode )
469 secondary_post_machining_mixed = true;
470
471 if( secondary_post_machining_size != v->Padstack().BackPostMachining().size )
472 secondary_post_machining_size_mixed = true;
473
474 if( secondary_post_machining_depth != v->Padstack().BackPostMachining().depth )
475 secondary_post_machining_depth_mixed = true;
476
477 if( secondary_post_machining_angle != v->Padstack().BackPostMachining().angle )
478 secondary_post_machining_angle_mixed = true;
479 }
480
481 PADSTACK::DRILL_PROPS topDrill;
482 PADSTACK::DRILL_PROPS bottomDrill;
483 getBackdrillDrills( v, topDrill, bottomDrill );
484
485 bool top = topDrill.end != UNDEFINED_LAYER && topDrill.size.x > 0;
486 bool bottom = bottomDrill.end != UNDEFINED_LAYER && bottomDrill.size.x > 0;
487
489
490 if( top && bottom )
491 new_backdrill_dir = BACKDRILL_MODE::BACKDRILL_BOTH;
492 else if( bottom )
493 new_backdrill_dir = BACKDRILL_MODE::BACKDRILL_BOTTOM;
494 else if( top )
495 new_backdrill_dir = BACKDRILL_MODE::BACKDRILL_TOP;
496 else
497 new_backdrill_dir = BACKDRILL_MODE::NO_BACKDRILL;
498
499 if( secondary_drill_end_layer != topDrill.end )
500 secondary_drill_end_layer_mixed = true;
501
502 if( tertiary_drill_end_layer != bottomDrill.end )
503 tertiary_drill_end_layer_mixed = true;
504
505 if( backdrill_dir != new_backdrill_dir )
506 backdrill_dir_mixed = true;
507
508 if( bottomDrill.size.x != tertiary_drill_size )
509 tertiary_drill_size_mixed = true;
510
511 if( topDrill.size.x != secondary_drill_size )
512 secondary_drill_size_mixed = true;
513 }
514
515 if( v->IsLocked() )
516 hasLocked = true;
517 else
518 hasUnlocked = true;
519
520 break;
521 }
522
523 default:
524 {
525 UNIMPLEMENTED_FOR( item->GetClass() );
526 break;
527 }
528 }
529 }
530
531 if( m_tracks )
532 {
533 // Set the track layer selection state:
534 if( track_selection_layer == UNDEFINED_LAYER )
535 {
536 m_TrackLayerCtrl->SetUndefinedLayerName( INDETERMINATE_STATE );
537 m_TrackLayerCtrl->Resync();
538 }
539
540 m_TrackLayerCtrl->SetLayerSelection( track_selection_layer );
541 }
542
543 // Set the vias layers selections state:
544 if( m_vias )
545 {
546 if( selection_first_layer == UNDEFINED_LAYER )
547 {
548 m_ViaStartLayer->SetUndefinedLayerName( INDETERMINATE_STATE );
549 m_ViaStartLayer->Resync();
550 }
551
552 m_ViaStartLayer->SetLayerSelection( selection_first_layer );
553
554 if( selection_last_layer == UNDEFINED_LAYER )
555 {
556 m_ViaEndLayer->SetUndefinedLayerName( INDETERMINATE_STATE );
557 m_ViaEndLayer->Resync();
558 }
559
560 m_ViaEndLayer->SetLayerSelection( selection_last_layer );
561
562 // Set backdrill controls
563
564 // Backdrill direction selector
565 if( backdrill_dir_mixed )
566 {
567 m_backdrillChoice->SetSelection( wxNOT_FOUND );
568
569 if( tertiary_drill_size_mixed )
571 else
572 m_backdrillBackSize.SetValue( tertiary_drill_size );
573
574 if( secondary_drill_size_mixed )
576 else
577 m_backdrillFrontSize.SetValue( secondary_drill_size );
578 }
579 else
580 {
581 m_backdrillChoice->SetSelection( static_cast<int>( backdrill_dir ) );
582
583 if( backdrill_dir == BACKDRILL_MODE::BACKDRILL_BOTTOM || backdrill_dir == BACKDRILL_MODE::BACKDRILL_BOTH )
584 {
585 if( tertiary_drill_size_mixed )
587 else
588 m_backdrillBackSize.SetValue( tertiary_drill_size );
589 }
590 else
591 {
592 m_backdrillBackSize.SetValue( wxEmptyString );
593 }
594
595 if( backdrill_dir == BACKDRILL_MODE::BACKDRILL_TOP || backdrill_dir == BACKDRILL_MODE::BACKDRILL_BOTH )
596 {
597 if( secondary_drill_size_mixed )
599 else
600 m_backdrillFrontSize.SetValue( secondary_drill_size );
601 }
602 else
603 {
604 m_backdrillFrontSize.SetValue( wxEmptyString );
605 }
606
607 }
608
609 // Top backdrill control
610 if( secondary_drill_end_layer_mixed )
611 {
612 m_backdrillFrontLayer->SetUndefinedLayerName( INDETERMINATE_STATE );
613 m_backdrillFrontLayer->Resync();
614 m_backdrillFrontLayer->SetLayerSelection( UNDEFINED_LAYER );
615 }
616 else
617 {
618 m_backdrillFrontLayer->SetUndefinedLayerName( _( "None" ) );
619 m_backdrillFrontLayer->Resync();
620 m_backdrillFrontLayer->SetLayerSelection( secondary_drill_end_layer );
621 }
622
623 // Bottom backdrill control
624 if( tertiary_drill_end_layer_mixed )
625 {
626 m_backdrillBackLayer->SetUndefinedLayerName( INDETERMINATE_STATE );
627 m_backdrillBackLayer->Resync();
628 m_backdrillBackLayer->SetLayerSelection( UNDEFINED_LAYER );
629 }
630 else
631 {
632 m_backdrillBackLayer->SetUndefinedLayerName( _( "None" ) );
633 m_backdrillBackLayer->Resync();
634 m_backdrillBackLayer->SetLayerSelection( tertiary_drill_end_layer );
635 }
636
637 // Post Machining
638 if( primary_post_machining_mixed )
639 {
640 m_topPostMachine->SetSelection( wxNOT_FOUND );
642 m_topPostMachineSize2.SetUnits( m_frame->GetUserUnits() );
644 }
645 else if( primary_post_machining_set && primary_post_machining_value.has_value() )
646 {
647 switch( primary_post_machining_value.value() )
648 {
650 m_topPostMachine->SetSelection( 2 );
651
652 if( primary_post_machining_size_mixed )
654 else
655 m_topPostMachineSize1.SetValue( primary_post_machining_size );
656
657 m_topPostMachineSize2.SetUnits( m_frame->GetUserUnits() );
658
659 if( primary_post_machining_depth_mixed )
661 else
662 m_topPostMachineSize2.SetValue( primary_post_machining_depth );
663
664 break;
665
667 m_topPostMachine->SetSelection( 1 );
668
669 if( primary_post_machining_size_mixed )
671 else
672 m_topPostMachineSize1.SetValue( primary_post_machining_size );
673
675
676 if( primary_post_machining_angle_mixed )
678 else
679 m_topPostMachineSize2.SetDoubleValue( primary_post_machining_angle / 10.0 );
680
681 break;
682
683 default:
684 m_topPostMachine->SetSelection( 0 );
685 m_topPostMachineSize1.SetValue( wxEmptyString );
686 m_topPostMachineSize2.SetUnits( m_frame->GetUserUnits() );
687 m_topPostMachineSize2.SetValue( wxEmptyString );
688 break;
689 }
690 }
691 else
692 {
693 m_topPostMachine->SetSelection( 0 );
694 m_topPostMachineSize1.SetValue( wxEmptyString );
695 m_topPostMachineSize2.SetUnits( m_frame->GetUserUnits() );
696 m_topPostMachineSize2.SetValue( wxEmptyString );
697 }
698
699 if( secondary_post_machining_mixed )
700 {
701 m_bottomPostMachine->SetSelection( wxNOT_FOUND );
703 m_bottomPostMachineSize2.SetUnits( m_frame->GetUserUnits() );
705 }
706 else if( secondary_post_machining_set && secondary_post_machining_value.has_value() )
707 {
708 switch( secondary_post_machining_value.value() )
709 {
711 m_bottomPostMachine->SetSelection( 2 );
712
713 if( secondary_post_machining_size_mixed )
715 else
716 m_bottomPostMachineSize1.SetValue( secondary_post_machining_size );
717
718 m_bottomPostMachineSize2.SetUnits( m_frame->GetUserUnits() );
719
720 if( secondary_post_machining_depth_mixed )
722 else
723 m_bottomPostMachineSize2.SetValue( secondary_post_machining_depth );
724
725 break;
726
728 m_bottomPostMachine->SetSelection( 1 );
729
730 if( secondary_post_machining_size_mixed )
732 else
733 m_bottomPostMachineSize1.SetValue( secondary_post_machining_size );
734
736
737 if( secondary_post_machining_angle_mixed )
739 else
740 m_bottomPostMachineSize2.SetDoubleValue( secondary_post_machining_angle / 10.0 );
741
742 break;
743
744 default:
745 m_bottomPostMachine->SetSelection( 0 );
746 m_bottomPostMachineSize1.SetValue( wxEmptyString );
747 m_bottomPostMachineSize2.SetValue( wxEmptyString );
748 m_bottomPostMachineSize2.SetUnits( m_frame->GetUserUnits() );
749 break;
750 }
751 }
752 else
753 {
754 m_bottomPostMachine->SetSelection( 0 );
755 m_bottomPostMachineSize1.SetValue( wxEmptyString );
756 m_bottomPostMachineSize2.SetUnits( m_frame->GetUserUnits() );
757 m_bottomPostMachineSize2.SetValue( wxEmptyString );
758 }
759 }
760
761 m_netSelector->SetNetInfo( &m_frame->GetBoard()->GetNetInfo() );
762
763 if ( net >= 0 )
764 {
765 m_netSelector->SetSelectedNetcode( net );
766 }
767 else
768 {
769 m_netSelector->SetIndeterminateString( INDETERMINATE_STATE );
770 m_netSelector->SetIndeterminate();
771 }
772
773 wxASSERT( m_tracks || m_vias );
774
775 if( m_vias )
776 {
777 if( m_viaNotFree->GetValue() && !m_tracks )
778 {
779 // Disable net selector to re-inforce meaning of "Automatically update via nets",
780 // but not when tracks are also selected as then things get harder if you want to
781 // update all the nets to match.
782 m_netSelectorLabel->Disable();
783 m_netSelector->Disable();
784 }
785
786 int viaSelection = wxNOT_FOUND;
787
788 // 0 is the netclass place-holder
789 for( unsigned ii = 1; ii < m_frame->GetDesignSettings().m_ViasDimensionsList.size(); ii++ )
790 {
791 VIA_DIMENSION* viaDimension = &m_frame->GetDesignSettings().m_ViasDimensionsList[ii];
792 wxString msg = m_frame->StringFromValue( viaDimension->m_Diameter )
793 + wxT( " / " )
794 + m_frame->StringFromValue( viaDimension->m_Drill );
795 m_predefinedViaSizesCtrl->Append( msg, viaDimension );
796
797 if( viaSelection == wxNOT_FOUND
798 && m_viaDiameter.GetValue() == viaDimension->m_Diameter
799 && m_viaDrill.GetValue() == viaDimension->m_Drill )
800 {
801 viaSelection = ii - 1;
802 }
803 }
804
805 m_predefinedViaSizesCtrl->SetSelection( viaSelection );
806 m_predefinedViaSizesUnits->SetLabel( EDA_UNIT_UTILS::GetLabel( m_frame->GetUserUnits() ) );
807
808 m_ViaTypeChoice->Enable();
809
810 switch( viaType )
811 {
812 case VIATYPE::THROUGH: m_ViaTypeChoice->SetSelection( 0 ); break;
813 case VIATYPE::MICROVIA: m_ViaTypeChoice->SetSelection( 1 ); break;
814 case VIATYPE::BLIND: m_ViaTypeChoice->SetSelection( 2 ); break;
815 case VIATYPE::BURIED: m_ViaTypeChoice->SetSelection( 3 ); break;
816 case VIATYPE::NOT_DEFINED: m_ViaTypeChoice->SetSelection( wxNOT_FOUND ); break;
817 }
818
819 m_ViaStartLayer->Enable( viaType != VIATYPE::THROUGH );
820 m_ViaEndLayer->Enable( viaType != VIATYPE::THROUGH );
821
822 m_annularRingsLabel->Show( getLayerDepth() > 1 );
823 m_annularRingsCtrl->Show( getLayerDepth() > 1 );
824 m_annularRingsCtrl->Enable( true );
825
827 }
828 else
829 {
830 m_viaNotFree->Hide();
831 m_MainSizer->Hide( m_sbViaSizer, true );
832 }
833
834 if( m_tracks )
835 {
836 int widthSelection = wxNOT_FOUND;
837
838 // 0 is the netclass place-holder
839 for( unsigned ii = 1; ii < m_frame->GetDesignSettings().m_TrackWidthList.size(); ii++ )
840 {
841 int width = m_frame->GetDesignSettings().m_TrackWidthList[ii];
842 wxString msg = m_frame->StringFromValue( width );
843 m_predefinedTrackWidthsCtrl->Append( msg );
844
845 if( widthSelection == wxNOT_FOUND && m_trackWidth.GetValue() == width )
846 widthSelection = ii - 1;
847 }
848
849 m_predefinedTrackWidthsCtrl->SetSelection( widthSelection );
850 m_predefinedTrackWidthsUnits->SetLabel( EDA_UNIT_UTILS::GetLabel( m_frame->GetUserUnits() ) );
851
852 wxCommandEvent event;
853 onTrackEdit( event );
854 }
855 else
856 {
857 m_MainSizer->Hide( m_sbTrackSizer, true );
858 }
859
860 if( hasLocked && hasUnlocked )
861 m_lockedCbox->Set3StateValue( wxCHK_UNDETERMINED );
862 else if( hasLocked )
863 m_lockedCbox->Set3StateValue( wxCHK_CHECKED );
864 else
865 m_lockedCbox->Set3StateValue( wxCHK_UNCHECKED );
866
867 if( m_tracks )
869 else if( m_netSelector->IsEnabled() )
871 else
873
874 wxCommandEvent dummyEvent;
875 onBackdrillChange( dummyEvent );
876 onTopPostMachineChange( dummyEvent );
877 onBottomPostMachineChange( dummyEvent );
878
879 // Now all widgets have the size fixed, call FinishDialogSettings
881
882 return true;
883}
884
885
887{
888 if( m_vias )
889 {
890 int viaSel = m_predefinedViaSizesCtrl->GetSelection();
891
893
894 // 0 is the netclass place-holder
895 for( unsigned ii = 1; ii < m_frame->GetDesignSettings().m_ViasDimensionsList.size(); ii++ )
896 {
897 VIA_DIMENSION* viaDimension = &m_frame->GetDesignSettings().m_ViasDimensionsList[ii];
898 wxString msg = m_frame->StringFromValue( viaDimension->m_Diameter )
899 + wxT( " / " )
900 + m_frame->StringFromValue( viaDimension->m_Drill );
901 m_predefinedViaSizesCtrl->Append( msg, viaDimension );
902 }
903
904 m_predefinedViaSizesCtrl->SetSelection( viaSel );
905 m_predefinedViaSizesUnits->SetLabel( EDA_UNIT_UTILS::GetLabel( m_frame->GetUserUnits() ) );
906 }
907
908 if( m_tracks )
909 {
910 int trackSel = m_predefinedTrackWidthsCtrl->GetSelection();
911
913
914 // 0 is the netclass place-holder
915 for( unsigned ii = 1; ii < m_frame->GetDesignSettings().m_TrackWidthList.size(); ii++ )
916 {
917 int width = m_frame->GetDesignSettings().m_TrackWidthList[ii];
918 wxString msg = m_frame->StringFromValue( width );
919 m_predefinedTrackWidthsCtrl->Append( msg );
920 }
921
922 m_predefinedTrackWidthsCtrl->SetSelection( trackSel );
923 m_predefinedTrackWidthsUnits->SetLabel( EDA_UNIT_UTILS::GetLabel( m_frame->GetUserUnits() ) );
924 }
925
926 aEvent.Skip();
927}
928
929
930bool DIALOG_TRACK_VIA_PROPERTIES::confirmShortingNets( int aNet, const std::set<int>& shortingNets )
931{
932 wxString msg;
933
934 if( shortingNets.size() == 1 )
935 {
936 msg.Printf( _( "Applying these changes will short net %s with %s." ),
937 m_netSelector->GetValue(),
938 m_frame->GetBoard()->FindNet( *shortingNets.begin() )->GetNetname() );
939 }
940 else
941 {
942 msg.Printf( _( "Applying these changes will short net %s with other nets." ),
943 m_netSelector->GetValue() );
944 }
945
946 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
947 dlg.SetOKCancelLabels( _( "Apply Anyway" ), _( "Cancel Changes" ) );
948 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
949
950 return dlg.ShowModal() == wxID_OK;
951}
952
953
954bool DIALOG_TRACK_VIA_PROPERTIES::confirmPadChange( const std::set<PAD*>& changingPads )
955{
956 wxString msg;
957
958 if( changingPads.size() == 1 )
959 {
960 PAD* pad = *changingPads.begin();
961 msg.Printf( _( "Changing the net will also update %s pad %s to %s." ),
962 pad->GetParentFootprint()->GetReference(),
963 pad->GetNumber(),
964 m_netSelector->GetValue() );
965 }
966 else if( changingPads.size() == 2 )
967 {
968 PAD* pad1 = *changingPads.begin();
969 PAD* pad2 = *( ++changingPads.begin() );
970 msg.Printf( _( "Changing the net will also update %s pad %s and %s pad %s to %s." ),
972 pad1->GetNumber(),
974 pad2->GetNumber(),
975 m_netSelector->GetValue() );
976 }
977 else
978 {
979 msg.Printf( _( "Changing the net will also update %lu connected pads to %s." ),
980 static_cast<unsigned long>( changingPads.size() ),
981 m_netSelector->GetValue() );
982 }
983
984 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
985 dlg.SetOKCancelLabels( _( "Change Nets" ), _( "Leave Nets Unchanged" ) );
986 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
987
988 return dlg.ShowModal() == wxID_OK;
989}
990
991
993{
994 std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_frame->GetBoard()->GetConnectivity();
995 std::vector<PCB_TRACK*> selected_tracks;
996 std::set<PCB_TRACK*> connected_tracks;
997
998 for( EDA_ITEM* item : m_items )
999 {
1000 if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( item ) )
1001 selected_tracks.push_back( track );
1002 }
1003
1004 for( PCB_TRACK* selected_track : selected_tracks )
1005 {
1006 connected_tracks.insert( selected_track );
1007
1008 // Exclude zones so we only follow direct copper, via, and pad connections. Zone
1009 // propagation would pull in unrelated same-net tracks and rewrite their net below.
1010 for( BOARD_CONNECTED_ITEM* connected_item :
1011 connectivity->GetConnectedItems( selected_track, EXCLUDE_ZONES ) )
1012 {
1013 if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( connected_item ) )
1014 connected_tracks.insert( track );
1015 }
1016 }
1017
1018 // Check for malformed data ONLY; design rules and constraints are the business of DRC.
1019
1020 if( m_vias )
1021 {
1022 // Marshal UI values into optionals; the malformed-data checks themselves live on
1023 // PCB_VIA::ValidateViaParameters so they can be reused and unit tested.
1024
1025 std::optional<int> viaDiameter;
1026
1027 if( m_ViaDiameterCtrl->IsEnabled() && !m_viaDiameter.IsIndeterminate() )
1028 viaDiameter = m_viaDiameter.GetValue();
1029
1030 std::optional<int> viaDrill;
1031
1032 if( m_ViaDrillCtrl->IsEnabled() && !m_viaDrill.IsIndeterminate() )
1033 viaDrill = m_viaDrill.GetValue();
1034
1035 std::optional<PCB_LAYER_ID> startLayer;
1036
1037 if( m_ViaStartLayer->GetLayerSelection() != UNDEFINED_LAYER )
1038 startLayer = static_cast<PCB_LAYER_ID>( m_ViaStartLayer->GetLayerSelection() );
1039
1040 std::optional<PCB_LAYER_ID> endLayer;
1041
1042 if( m_ViaEndLayer->GetLayerSelection() != UNDEFINED_LAYER )
1043 endLayer = static_cast<PCB_LAYER_ID>( m_ViaEndLayer->GetLayerSelection() );
1044
1045 std::optional<int> secondaryDrill;
1046 std::optional<int> tertiaryDrill;
1047 std::optional<PCB_LAYER_ID> secondaryStartLayer;
1048 std::optional<PCB_LAYER_ID> secondaryEndLayer;
1049 std::optional<PCB_LAYER_ID> tertiaryStartLayer;
1050 std::optional<PCB_LAYER_ID> tertiaryEndLayer;
1051
1052 if( m_backdrillChoice->GetSelection() != wxNOT_FOUND )
1053 {
1054 switch( static_cast<BACKDRILL_MODE>( m_backdrillChoice->GetSelection() ) )
1055 {
1057 break;
1058
1060 if( m_backdrillBackSize.IsIndeterminate() || m_backdrillBackSize.IsNull() )
1061 tertiaryDrill = m_viaStack->TertiaryDrill().size.x;
1062 else
1063 tertiaryDrill = m_backdrillBackSize.GetIntValue();
1064
1065 tertiaryStartLayer = B_Cu;
1066
1067 if( m_backdrillBackLayer->GetLayerSelection() != UNDEFINED_LAYER )
1068 tertiaryEndLayer = ToLAYER_ID( m_backdrillBackLayer->GetLayerSelection() );
1069
1070 if( !m_backdrillBackSize.IsIndeterminate() )
1071 tertiaryDrill = m_backdrillBackSize.GetIntValue();
1072
1073 break;
1074
1076 if( m_backdrillFrontSize.IsIndeterminate() || m_backdrillFrontSize.IsNull() )
1077 secondaryDrill = m_viaStack->SecondaryDrill().size.x;
1078 else
1079 secondaryDrill = m_backdrillFrontSize.GetIntValue();
1080
1081 secondaryStartLayer = F_Cu;
1082
1083 if( m_backdrillFrontLayer->GetLayerSelection() != UNDEFINED_LAYER )
1084 secondaryEndLayer = ToLAYER_ID( m_backdrillFrontLayer->GetLayerSelection() );
1085
1086 if( !m_backdrillFrontSize.IsIndeterminate() )
1087 secondaryDrill = m_backdrillFrontSize.GetIntValue();
1088
1089 break;
1090
1092 if( m_backdrillFrontSize.IsIndeterminate() || m_backdrillFrontSize.IsNull() )
1093 secondaryDrill = m_viaStack->SecondaryDrill().size.x;
1094 else
1095 secondaryDrill = m_backdrillFrontSize.GetIntValue();
1096
1097 secondaryStartLayer = F_Cu;
1098
1099 if( m_backdrillFrontLayer->GetLayerSelection() != UNDEFINED_LAYER )
1100 secondaryEndLayer = ToLAYER_ID( m_backdrillFrontLayer->GetLayerSelection() );
1101
1102 if( !m_backdrillFrontSize.IsIndeterminate() )
1103 secondaryDrill = m_backdrillFrontSize.GetIntValue();
1104
1105 if( m_backdrillBackSize.IsIndeterminate() || m_backdrillBackSize.IsNull() )
1106 tertiaryDrill = m_viaStack->TertiaryDrill().size.x;
1107 else
1108 tertiaryDrill = m_backdrillBackSize.GetIntValue();
1109
1110 tertiaryStartLayer = B_Cu;
1111
1112 if( m_backdrillBackLayer->GetLayerSelection() != UNDEFINED_LAYER )
1113 tertiaryEndLayer = ToLAYER_ID( m_backdrillBackLayer->GetLayerSelection() );
1114
1115 if( !m_backdrillBackSize.IsIndeterminate() )
1116 tertiaryDrill = m_backdrillBackSize.GetIntValue();
1117
1118 break;
1119 }
1120 }
1121
1122 // Post Machining
1123 std::optional<PADSTACK::POST_MACHINING_PROPS> frontPostMachining;
1124 std::optional<PADSTACK::POST_MACHINING_PROPS> backPostMachining;
1125
1126 if( m_topPostMachine->GetSelection() != wxNOT_FOUND )
1127 {
1129
1130 switch( m_topPostMachine->GetSelection() )
1131 {
1132 case 1: props.mode = PAD_DRILL_POST_MACHINING_MODE::COUNTERSINK; break;
1133 case 2: props.mode = PAD_DRILL_POST_MACHINING_MODE::COUNTERBORE; break;
1135 }
1136
1137 if( !m_topPostMachineSize1.IsIndeterminate() )
1138 props.size = m_topPostMachineSize1.GetIntValue();
1139
1140 if( !m_topPostMachineSize2.IsIndeterminate() )
1141 {
1143 props.angle = KiROUND( m_topPostMachineSize2.GetDoubleValue() * 10.0 );
1144 else
1145 props.depth = m_topPostMachineSize2.GetIntValue();
1146 }
1147
1148 frontPostMachining = props;
1149 }
1150
1151 if( m_bottomPostMachine->GetSelection() != wxNOT_FOUND )
1152 {
1154
1155 switch( m_bottomPostMachine->GetSelection() )
1156 {
1157 case 1: props.mode = PAD_DRILL_POST_MACHINING_MODE::COUNTERSINK; break;
1158 case 2: props.mode = PAD_DRILL_POST_MACHINING_MODE::COUNTERBORE; break;
1160 }
1161
1162 if( !m_bottomPostMachineSize1.IsIndeterminate() )
1163 props.size = m_bottomPostMachineSize1.GetIntValue();
1164
1165 if( !m_bottomPostMachineSize2.IsIndeterminate() )
1166 {
1168 props.angle = KiROUND( m_bottomPostMachineSize2.GetDoubleValue() * 10.0 );
1169 else
1170 props.depth = m_bottomPostMachineSize2.GetIntValue();
1171 }
1172
1173 backPostMachining = props;
1174 }
1175
1176 int copperLayerCount = m_frame->GetBoard() ? m_frame->GetBoard()->GetCopperLayerCount() : 0;
1177
1178 if( std::optional<PCB_VIA::VIA_PARAMETER_ERROR> error =
1179 PCB_VIA::ValidateViaParameters( viaDiameter, viaDrill, startLayer, endLayer,
1180 secondaryDrill, secondaryStartLayer,
1181 secondaryEndLayer, tertiaryDrill, tertiaryStartLayer,
1182 tertiaryEndLayer, copperLayerCount ) )
1183 {
1184 DisplayError( GetParent(), error->m_Message );
1185
1186 if( error->m_Field == PCB_VIA::VIA_PARAMETER_ERROR::FIELD::DRILL )
1187 {
1188 m_ViaDrillCtrl->SelectAll();
1189 m_ViaDrillCtrl->SetFocus();
1190 }
1191 else if( error->m_Field == PCB_VIA::VIA_PARAMETER_ERROR::FIELD::DIAMETER )
1192 {
1193 m_ViaDiameterCtrl->SelectAll();
1194 m_ViaDiameterCtrl->SetFocus();
1195 }
1196
1197 // Other fields might not have direct focus targets in new UI or I'd need to map them
1198 return false;
1199 }
1200
1201 }
1202
1203 if( m_tracks )
1204 {
1205 if( !m_trackWidth.Validate( GEOMETRY_MIN_SIZE, INT_MAX ) )
1206 return false;
1207 }
1208
1209 // If we survived that, then save the changes:
1210 //
1211 // We don't bother with updating the nets at this point as it will be useless (any connected
1212 // pads will simply drive their existing nets back onto the track segments and vias).
1213
1214 BOARD_COMMIT commit( m_frame );
1215 bool changeLock = m_lockedCbox->Get3StateValue() != wxCHK_UNDETERMINED;
1216 bool setLock = m_lockedCbox->Get3StateValue() == wxCHK_CHECKED;
1217
1218 for( PCB_TRACK* track : selected_tracks )
1219 {
1220 commit.Modify( track );
1221
1222 switch( track->Type() )
1223 {
1224 case PCB_TRACE_T:
1225 case PCB_ARC_T:
1226 {
1227 wxASSERT( m_tracks );
1228
1229 if( !m_trackStartX.IsIndeterminate() )
1230 track->SetStartX( m_trackStartX.GetIntValue() );
1231
1232 if( !m_trackStartY.IsIndeterminate() )
1233 track->SetStartY( m_trackStartY.GetIntValue() );
1234
1235 if( !m_trackEndX.IsIndeterminate() )
1236 track->SetEndX( m_trackEndX.GetIntValue() );
1237
1238 if( !m_trackEndY.IsIndeterminate() )
1239 track->SetEndY( m_trackEndY.GetIntValue() );
1240
1241 if( !m_trackWidth.IsIndeterminate() )
1242 track->SetWidth( m_trackWidth.GetIntValue() );
1243
1244 int layer = m_TrackLayerCtrl->GetLayerSelection();
1245
1246 if( layer != UNDEFINED_LAYER )
1247 track->SetLayer( (PCB_LAYER_ID) layer );
1248
1249 if ( m_trackHasSolderMask->Get3StateValue() != wxCHK_UNDETERMINED )
1250 track->SetHasSolderMask( m_trackHasSolderMask->GetValue() );
1251
1252 if( !m_trackMaskMargin.IsIndeterminate() )
1253 {
1254 if( m_trackMaskMargin.IsNull() )
1255 track->SetLocalSolderMaskMargin( {} );
1256 else
1257 track->SetLocalSolderMaskMargin( m_trackMaskMargin.GetIntValue() );
1258 }
1259
1260 if( changeLock )
1261 track->SetLocked( setLock );
1262
1263 break;
1264 }
1265
1266 case PCB_VIA_T:
1267 {
1268 wxASSERT( m_vias );
1269 PCB_VIA* via = static_cast<PCB_VIA*>( track );
1270 bool updatePadstack = m_padstackDirty;
1271
1272 if( !m_viaX.IsIndeterminate() )
1273 via->SetPosition( VECTOR2I( m_viaX.GetIntValue(), via->GetPosition().y ) );
1274
1275 if( !m_viaY.IsIndeterminate() )
1276 via->SetPosition( VECTOR2I( via->GetPosition().x, m_viaY.GetIntValue() ) );
1277
1278 if( m_viaNotFree->Get3StateValue() != wxCHK_UNDETERMINED )
1279 via->SetIsFree( !m_viaNotFree->GetValue() );
1280
1281 if( !m_viaDiameter.IsIndeterminate() )
1282 {
1283 int newDiameter = m_viaDiameter.GetIntValue();
1284 const VECTOR2I& currentSize = via->Padstack().Size( m_editLayer );
1285
1286 if( currentSize.x != newDiameter || currentSize.y != newDiameter )
1287 {
1288 m_viaStack->SetSize( { newDiameter, newDiameter }, m_editLayer );
1289 updatePadstack = true;
1290 }
1291 }
1292
1293 // Backdrill
1294 PADSTACK::DRILL_PROPS tertiaryDrill;
1295 PADSTACK::DRILL_PROPS secondaryDrill;
1296
1297 secondaryDrill.start = UNDEFINED_LAYER;
1298 secondaryDrill.end = UNDEFINED_LAYER;
1299 secondaryDrill.size = {0, 0};
1300 secondaryDrill.shape = PAD_DRILL_SHAPE::UNDEFINED;
1301
1302 tertiaryDrill.start = UNDEFINED_LAYER;
1303 tertiaryDrill.end = UNDEFINED_LAYER;
1304 tertiaryDrill.size = {0, 0};
1305 tertiaryDrill.shape = PAD_DRILL_SHAPE::UNDEFINED;
1306
1307 if( m_backdrillChoice->GetSelection() != wxNOT_FOUND )
1308 {
1309 switch( static_cast<BACKDRILL_MODE>( m_backdrillChoice->GetSelection() ) )
1310 {
1312 break;
1313
1315 if( m_backdrillBackSize.IsIndeterminate() || m_backdrillBackSize.IsNull() )
1316 {
1317 tertiaryDrill.size = m_viaStack->TertiaryDrill().size;
1318 }
1319 else
1320 {
1321 tertiaryDrill.size = VECTOR2I( m_backdrillBackSize.GetIntValue(),
1322 m_backdrillBackSize.GetIntValue() );
1323 }
1324
1325 tertiaryDrill.start = B_Cu;
1326 tertiaryDrill.shape = PAD_DRILL_SHAPE::CIRCLE;
1327
1328 if( m_backdrillBackLayer->GetLayerSelection() != UNDEFINED_LAYER )
1329 tertiaryDrill.end = ToLAYER_ID( m_backdrillBackLayer->GetLayerSelection() );
1330
1331 break;
1332
1334 if( m_backdrillFrontSize.IsIndeterminate() || m_backdrillFrontSize.IsNull() )
1335 {
1336 secondaryDrill.size = m_viaStack->SecondaryDrill().size;
1337 }
1338 else
1339 {
1340 secondaryDrill.size = VECTOR2I( m_backdrillFrontSize.GetIntValue(),
1341 m_backdrillFrontSize.GetIntValue() );
1342 }
1343
1344 secondaryDrill.start = F_Cu;
1345 secondaryDrill.shape = PAD_DRILL_SHAPE::CIRCLE;
1346
1347 if( m_backdrillFrontLayer->GetLayerSelection() != UNDEFINED_LAYER )
1348 secondaryDrill.end = ToLAYER_ID( m_backdrillFrontLayer->GetLayerSelection() );
1349
1350 break;
1351
1353 if( m_backdrillFrontSize.IsIndeterminate() || m_backdrillFrontSize.IsNull() )
1354 {
1355 secondaryDrill.size = m_viaStack->SecondaryDrill().size;
1356 }
1357 else
1358 {
1359 secondaryDrill.size = VECTOR2I( m_backdrillFrontSize.GetIntValue(),
1360 m_backdrillFrontSize.GetIntValue() );
1361 }
1362
1363 secondaryDrill.start = F_Cu;
1364 secondaryDrill.shape = PAD_DRILL_SHAPE::CIRCLE;
1365
1366 if( m_backdrillFrontLayer->GetLayerSelection() != UNDEFINED_LAYER )
1367 secondaryDrill.end = ToLAYER_ID( m_backdrillFrontLayer->GetLayerSelection() );
1368
1369 if( m_backdrillBackSize.IsIndeterminate() || m_backdrillBackSize.IsNull() )
1370 {
1371 tertiaryDrill.size = m_viaStack->TertiaryDrill().size;
1372 }
1373 else
1374 {
1375 tertiaryDrill.size = VECTOR2I( m_backdrillBackSize.GetIntValue(),
1376 m_backdrillBackSize.GetIntValue() );
1377 }
1378
1379 tertiaryDrill.start = B_Cu;
1380 tertiaryDrill.shape = PAD_DRILL_SHAPE::CIRCLE;
1381
1382 if( m_backdrillBackLayer->GetLayerSelection() != UNDEFINED_LAYER )
1383 tertiaryDrill.end = ToLAYER_ID( m_backdrillBackLayer->GetLayerSelection() );
1384
1385 break;
1386 }
1387
1388 if( via->Padstack().SecondaryDrill() != secondaryDrill )
1389 {
1390 m_viaStack->SecondaryDrill() = secondaryDrill;
1391 updatePadstack = true;
1392 }
1393
1394 if( via->Padstack().TertiaryDrill() != tertiaryDrill )
1395 {
1396 m_viaStack->TertiaryDrill() = tertiaryDrill;
1397 updatePadstack = true;
1398 }
1399 }
1400 else
1401 {
1402 if( !m_backdrillFrontSize.IsIndeterminate() && !m_backdrillFrontSize.IsNull() )
1403 {
1404 int frontSize = m_backdrillFrontSize.GetIntValue();
1405
1406 if( m_viaStack->SecondaryDrill().size != VECTOR2I( frontSize, frontSize ) )
1407 {
1408 m_viaStack->SecondaryDrill().size = VECTOR2I( frontSize, frontSize );
1409 updatePadstack = true;
1410 }
1411 }
1412
1413 if( !m_backdrillBackSize.IsIndeterminate() && !m_backdrillBackSize.IsNull() )
1414 {
1415 int backSize = m_backdrillBackSize.GetIntValue();
1416
1417 if( m_viaStack->TertiaryDrill().size != VECTOR2I( backSize, backSize ) )
1418 {
1419 m_viaStack->TertiaryDrill().size = VECTOR2I( backSize, backSize );
1420 updatePadstack = true;
1421 }
1422 }
1423 }
1424
1425 // Post Machining
1426 if( m_topPostMachine->GetSelection() != wxNOT_FOUND )
1427 {
1429
1430 switch( m_topPostMachine->GetSelection() )
1431 {
1432 case 1: props.mode = PAD_DRILL_POST_MACHINING_MODE::COUNTERSINK; break;
1433 case 2: props.mode = PAD_DRILL_POST_MACHINING_MODE::COUNTERBORE; break;
1435 }
1436
1437 if( !m_topPostMachineSize1.IsIndeterminate() )
1438 props.size = m_topPostMachineSize1.GetIntValue();
1439 else
1440 props.size = via->Padstack().FrontPostMachining().size;
1441
1442 if( !m_topPostMachineSize2.IsIndeterminate() )
1443 {
1445 props.angle = KiROUND( m_topPostMachineSize2.GetDoubleValue() * 10.0 );
1446 else
1447 props.depth = m_topPostMachineSize2.GetIntValue();
1448 }
1449 else
1450 {
1451 props.angle = via->Padstack().FrontPostMachining().angle;
1452 props.depth = via->Padstack().FrontPostMachining().depth;
1453 }
1454
1455 if( via->Padstack().FrontPostMachining() != props )
1456 {
1457 m_viaStack->FrontPostMachining() = props;
1458 updatePadstack = true;
1459 }
1460 }
1461
1462 if( m_bottomPostMachine->GetSelection() != wxNOT_FOUND )
1463 {
1465
1466 switch( m_bottomPostMachine->GetSelection() )
1467 {
1468 case 1: props.mode = PAD_DRILL_POST_MACHINING_MODE::COUNTERSINK; break;
1469 case 2: props.mode = PAD_DRILL_POST_MACHINING_MODE::COUNTERBORE; break;
1471 }
1472
1473 if( !m_bottomPostMachineSize1.IsIndeterminate() )
1474 props.size = m_bottomPostMachineSize1.GetIntValue();
1475 else
1476 props.size = via->Padstack().BackPostMachining().size;
1477
1478 if( !m_bottomPostMachineSize2.IsIndeterminate() )
1479 {
1481 props.angle = KiROUND( m_bottomPostMachineSize2.GetDoubleValue() * 10.0 );
1482 else
1483 props.depth = m_bottomPostMachineSize2.GetIntValue();
1484 }
1485 else
1486 {
1487 props.angle = via->Padstack().BackPostMachining().angle;
1488 props.depth = via->Padstack().BackPostMachining().depth;
1489 }
1490
1491 if( via->Padstack().BackPostMachining() != props )
1492 {
1493 m_viaStack->BackPostMachining() = props;
1494 updatePadstack = true;
1495 }
1496 }
1497
1498 switch( m_ViaTypeChoice->GetSelection() )
1499 {
1500 case 0: via->SetViaType( VIATYPE::THROUGH ); break;
1501 case 1: via->SetViaType( VIATYPE::MICROVIA ); break;
1502 case 2: via->SetViaType( VIATYPE::BLIND ); break;
1503 case 3: via->SetViaType( VIATYPE::BURIED ); break;
1504 default: break;
1505 }
1506
1507 PCB_LAYER_ID startLayer = static_cast<PCB_LAYER_ID>( m_ViaStartLayer->GetLayerSelection() );
1508 PCB_LAYER_ID endLayer = static_cast<PCB_LAYER_ID>( m_ViaEndLayer->GetLayerSelection() );
1509
1510 if( startLayer != UNDEFINED_LAYER )
1511 {
1512 if( via->Padstack().Drill().start != startLayer )
1513 {
1514 m_viaStack->Drill().start = startLayer;
1515 updatePadstack = true;
1516 }
1517
1518 via->SetTopLayer( startLayer );
1519 }
1520
1521 if( endLayer != UNDEFINED_LAYER )
1522 {
1523 if( via->Padstack().Drill().end != endLayer )
1524 {
1525 m_viaStack->Drill().end = endLayer;
1526 updatePadstack = true;
1527 }
1528
1529 via->SetBottomLayer( endLayer );
1530 }
1531
1532 if( updatePadstack )
1533 {
1534 via->SetPadstack( *m_viaStack );
1535 via->SanitizeLayers();
1536 }
1537
1538 switch( m_annularRingsCtrl->GetSelection() )
1539 {
1540 case 0:
1541 via->Padstack().SetUnconnectedLayerMode( UNCONNECTED_LAYER_MODE::KEEP_ALL );
1542 break;
1543 case 1:
1544 via->Padstack().SetUnconnectedLayerMode( UNCONNECTED_LAYER_MODE::REMOVE_EXCEPT_START_AND_END );
1545 break;
1546 case 2:
1547 via->Padstack().SetUnconnectedLayerMode( UNCONNECTED_LAYER_MODE::REMOVE_ALL );
1548 break;
1549 case 3:
1550 via->Padstack().SetUnconnectedLayerMode( UNCONNECTED_LAYER_MODE::START_END_ONLY );
1551 break;
1552 default:
1553 break;
1554 }
1555
1556
1557 if( !m_viaDrill.IsIndeterminate() )
1558 via->SetDrill( m_viaDrill.GetIntValue() );
1559
1560 TEARDROP_PARAMETERS* targetParams = &via->GetTeardropParams();
1561
1562 if( m_cbTeardrops->Get3StateValue() != wxCHK_UNDETERMINED )
1563 targetParams->m_Enabled = m_cbTeardrops->GetValue();
1564
1565 if( m_cbTeardropsUseNextTrack->Get3StateValue() != wxCHK_UNDETERMINED )
1566 targetParams->m_AllowUseTwoTracks = m_cbTeardropsUseNextTrack->GetValue();
1567
1568 if( !m_teardropMaxLen.IsIndeterminate() )
1569 targetParams->m_TdMaxLen = m_teardropMaxLen.GetIntValue();
1570
1571 if( !m_teardropMaxWidth.IsIndeterminate() )
1572 targetParams->m_TdMaxWidth = m_teardropMaxWidth.GetIntValue();
1573
1574 if( !m_teardropLenPercent.IsIndeterminate() )
1575 targetParams->m_BestLengthRatio = m_teardropLenPercent.GetDoubleValue() / 100.0;
1576
1577 if( !m_teardropWidthPercent.IsIndeterminate() )
1578 targetParams->m_BestWidthRatio = m_teardropWidthPercent.GetDoubleValue() / 100.0;
1579
1580 if( !m_teardropHDPercent.IsIndeterminate() )
1581 targetParams->m_WidthtoSizeFilterRatio = m_teardropHDPercent.GetDoubleValue() / 100.0;
1582
1583 if( m_curvedEdges->Get3StateValue() != wxCHK_UNDETERMINED )
1584 targetParams->m_CurvedEdges = m_curvedEdges->GetValue();
1585
1586 if( changeLock )
1587 via->SetLocked( setLock );
1588
1589 setViaConfiguration( via, static_cast<IPC4761_PRESET>( m_protectionFeatures->GetSelection() ) );
1590 break;
1591 }
1592
1593 default:
1594 UNIMPLEMENTED_FOR( track->GetClass() );
1595 break;
1596 }
1597 }
1598
1599 std::set<int> shortingNets;
1600 int newNetCode = m_netSelector->GetSelectedNetcode();
1601 std::set<PAD*> changingPads;
1602
1603 // Do NOT use the connectivity code here. It will propagate through zones, and we haven't
1604 // refilled those yet so it's going to pick up a whole bunch of other nets any time the track
1605 // width was increased.
1606 auto collide =
1608 {
1609 for( PCB_LAYER_ID layer : LSET( a->GetLayerSet() & b->GetLayerSet() ) )
1610 {
1611 if( a->GetEffectiveShape( layer )->Collide( b->GetEffectiveShape( layer ).get() ) )
1612 return true;
1613 }
1614
1615 return false;
1616 };
1617
1618 for( PCB_TRACK* track : connected_tracks )
1619 {
1620 for( PCB_TRACK* other : m_frame->GetBoard()->Tracks() )
1621 {
1622 if( other->GetNetCode() == track->GetNetCode() || other->GetNetCode() == newNetCode )
1623 continue;
1624
1625 if( collide( track, other ) )
1626 shortingNets.insert( other->GetNetCode() );
1627 }
1628
1629 for( FOOTPRINT* footprint : m_frame->GetBoard()->Footprints() )
1630 {
1631 for( PAD* pad : footprint->Pads() )
1632 {
1633 if( pad->GetNetCode() == newNetCode )
1634 continue;
1635
1636 if( collide( track, pad ) )
1637 {
1638 if( pad->GetNetCode() == track->GetNetCode() )
1639 changingPads.insert( pad );
1640 else
1641 shortingNets.insert( pad->GetNetCode() );
1642 }
1643 }
1644 }
1645 }
1646
1647 if( shortingNets.size() && !confirmShortingNets( newNetCode, shortingNets ) )
1648 {
1649 commit.Revert();
1650 return true;
1651 }
1652
1653 if( !m_netSelector->IsIndeterminate() )
1654 {
1655 if( changingPads.empty() || confirmPadChange( changingPads ) )
1656 {
1657 for( PCB_TRACK* track : connected_tracks )
1658 {
1659 if( !alg::contains( selected_tracks, track ) )
1660 commit.Modify( track );
1661
1662 track->SetNetCode( newNetCode );
1663 }
1664
1665 for( PAD* pad : changingPads )
1666 {
1667 commit.Modify( pad );
1668 pad->SetNetCode( newNetCode );
1669 }
1670 }
1671 }
1672
1673 commit.Push( _( "Edit Track/Via Properties" ) );
1674 return true;
1675}
1676
1677
1679{
1680 m_viaNotFree->SetValue( false );
1681}
1682
1683
1685{
1686 if( !m_tracks )
1687 {
1688 m_netSelectorLabel->Enable( !m_viaNotFree->GetValue() );
1689 m_netSelector->Enable( !m_viaNotFree->GetValue() );
1690 }
1691}
1692
1693
1695{
1696 m_TrackWidthCtrl->ChangeValue( m_predefinedTrackWidthsCtrl->GetStringSelection() );
1697 m_TrackWidthCtrl->SelectAll();
1698}
1699
1700
1701void DIALOG_TRACK_VIA_PROPERTIES::onWidthEdit( wxCommandEvent& aEvent )
1702{
1703 m_predefinedTrackWidthsCtrl->SetStringSelection( m_TrackWidthCtrl->GetValue() );
1704}
1705
1706
1707void DIALOG_TRACK_VIA_PROPERTIES::onViaSelect( wxCommandEvent& aEvent )
1708{
1709 VIA_DIMENSION* viaDimension = static_cast<VIA_DIMENSION*> ( aEvent.GetClientData() );
1710
1711 m_viaDiameter.ChangeValue( viaDimension->m_Diameter );
1712 m_viaDrill.ChangeValue( viaDimension->m_Drill );
1713}
1714
1715
1717{
1718 wxCHECK_MSG( m_viaStack, /* void */, "Expected valid via stack in onPadstackModeChanged" );
1719
1720 switch( m_cbPadstackMode->GetSelection() )
1721 {
1722 default:
1723 case 0: m_viaStack->SetMode( PADSTACK::MODE::NORMAL ); break;
1724 case 1: m_viaStack->SetMode( PADSTACK::MODE::FRONT_INNER_BACK ); break;
1725 case 2: m_viaStack->SetMode( PADSTACK::MODE::CUSTOM ); break;
1726 }
1727
1728 m_padstackDirty = true;
1729
1731}
1732
1733
1735{
1736 wxCHECK_MSG( m_viaStack, /* void */, "Expected valid via stack in onEditLayerChanged" );
1737
1738 // Save data from the previous layer
1739 if( !m_viaDiameter.IsIndeterminate() )
1740 {
1741 int diameter = m_viaDiameter.GetIntValue();
1742 m_viaStack->SetSize( { diameter, diameter }, m_editLayer );
1743 }
1744
1745 switch( m_viaStack->Mode() )
1746 {
1747 default:
1750 break;
1751
1753 switch( m_cbEditLayer->GetSelection() )
1754 {
1755 default:
1756 case 0: m_editLayer = F_Cu; break;
1757 case 1: m_editLayer = PADSTACK::INNER_LAYERS; break;
1758 case 2: m_editLayer = B_Cu; break;
1759 }
1760 break;
1761
1763 {
1764 int layer = m_cbEditLayer->GetSelection();
1765
1766 if( layer < 0 )
1767 layer = 0;
1768
1769 if( m_editLayerCtrlMap.contains( layer ) )
1770 m_editLayer = m_editLayerCtrlMap.at( layer );
1771 else
1772 m_editLayer = F_Cu;
1773 }
1774 }
1775
1776 // Load controls with the current layer
1777 m_viaDiameter.SetValue( m_viaStack->Size( m_editLayer ).x );
1778}
1779
1780
1782{
1783 // NOTE: synchronize changes here with DIALOG_PAD_PROPERTIES::afterPadstackModeChanged
1784
1785 wxCHECK_MSG( m_viaStack, /* void */, "Expected valid via stack in afterPadstackModeChanged" );
1786 m_cbEditLayer->Clear();
1787
1788 BOARD* board = m_frame->GetBoard();
1789
1790 switch( m_viaStack->Mode() )
1791 {
1793 m_cbPadstackMode->SetSelection( 0 );
1794 m_cbEditLayer->Append( _( "All layers" ) );
1795 m_cbEditLayer->Disable();
1798 break;
1799
1801 {
1802 m_cbPadstackMode->SetSelection( 1 );
1803 m_cbEditLayer->Enable();
1804
1805 std::vector choices = {
1806 board->GetLayerName( F_Cu ),
1807 _( "Inner Layers" ),
1808 board->GetLayerName( B_Cu )
1809 };
1810
1811 m_cbEditLayer->Append( choices );
1812
1814 { 0, F_Cu },
1816 { 2, B_Cu }
1817 };
1818
1819 if( m_editLayer != F_Cu && m_editLayer != B_Cu )
1821
1822 break;
1823 }
1824
1826 {
1827 m_cbPadstackMode->SetSelection( 2 );
1828 m_cbEditLayer->Enable();
1829 LSET layers = LSET::AllCuMask() & board->GetEnabledLayers();
1830
1831 for( PCB_LAYER_ID layer : layers.UIOrder() )
1832 {
1833 int idx = m_cbEditLayer->Append( board->GetLayerName( layer ) );
1834 m_editLayerCtrlMap[idx] = layer;
1835 }
1836
1837 break;
1838 }
1839 }
1840
1841 for( const auto& [idx, layer] : m_editLayerCtrlMap )
1842 {
1843 if( layer == m_editLayer )
1844 {
1845 m_cbEditLayer->SetSelection( idx );
1846 break;
1847 }
1848 }
1849}
1850
1851
1853{
1854 int viaType = m_ViaTypeChoice->GetSelection();
1855
1856 if( viaType <= 0 )
1857 return m_frame->GetBoard()->GetCopperLayerCount() - 1;
1858
1859 int startLayer = m_ViaStartLayer->GetLayerSelection();
1860 int endLayer = m_ViaEndLayer->GetLayerSelection();
1861
1862 if( startLayer < 0 || endLayer < 0 )
1863 return m_frame->GetBoard()->GetCopperLayerCount() - 1;
1864 else
1865 return m_frame->GetBoard()->LayerDepth( ToLAYER_ID( startLayer ), ToLAYER_ID( endLayer ) );
1866}
1867
1868
1869void DIALOG_TRACK_VIA_PROPERTIES::onViaEdit( wxCommandEvent& aEvent )
1870{
1871 m_predefinedViaSizesCtrl->SetSelection( wxNOT_FOUND );
1872
1873 if( m_vias )
1874 {
1875 if( m_ViaTypeChoice->GetSelection() != 0 ) // check if selected type isn't through.
1876 {
1877 m_ViaStartLayer->Enable();
1878 m_ViaEndLayer->Enable();
1879 }
1880 else
1881 {
1882 m_ViaStartLayer->SetLayerSelection( F_Cu );
1883 m_ViaEndLayer->SetLayerSelection( B_Cu );
1884
1885 m_ViaStartLayer->Enable( false );
1886 m_ViaEndLayer->Enable( false );
1887 }
1888
1889 m_annularRingsLabel->Show( getLayerDepth() > 1 );
1890 m_annularRingsCtrl->Show( getLayerDepth() > 1 );
1891 m_annularRingsCtrl->Enable( true );
1892 }
1893}
1894
1895
1896void DIALOG_TRACK_VIA_PROPERTIES::onTrackEdit( wxCommandEvent& aEvent )
1897{
1898 bool externalCuLayer = m_TrackLayerCtrl->GetLayerSelection() == F_Cu
1899 || m_TrackLayerCtrl->GetLayerSelection() == B_Cu;
1900
1901 m_techLayersLabel->Enable( externalCuLayer );
1902 m_trackHasSolderMask->Enable( externalCuLayer );
1903
1904 bool showMaskMargin = externalCuLayer && m_trackHasSolderMask->GetValue();
1905
1906 m_trackMaskMarginCtrl->Enable( showMaskMargin );
1907 m_trackMaskMarginLabel->Enable( showMaskMargin );
1908 m_trackMaskMarginUnit->Enable( showMaskMargin );
1909}
1910
1911
1913{
1914 event.Enable( !m_frame->GetBoard()->LegacyTeardrops() );
1915}
1916
1917
1919{
1920 int selection = m_backdrillChoice->GetSelection();
1921 // 0: None, 1: Bottom, 2: Top, 3: Both
1922
1923 bool enableTop = ( selection == 2 || selection == 3 );
1924 bool enableBottom = ( selection == 1 || selection == 3 );
1925
1926 m_backdrillFrontSize.Enable( enableTop );
1927 m_backdrillFrontLayer->Enable( enableTop );
1928 m_backdrillFrontLayerLabel->Enable( enableTop );
1929
1930 if( enableTop )
1931 {
1932 if( m_backdrillFrontLayer->GetLayerSelection() == UNDEFINED_LAYER )
1933 m_backdrillFrontLayer->SetLayerSelection( F_Cu );
1934
1935 if( m_backdrillFrontSize.GetIntValue() == 0 )
1936 {
1937 // Initialize backdrill slightly larger than main drill (see PADSTACK::SetBackdrillMode())
1938 m_backdrillFrontSize.SetValue( KiROUND( m_viaDrill.GetIntValue() * 1.1 ) );
1939 }
1940 }
1941
1942 m_backdrillBackSize.Enable( enableBottom );
1943 m_backdrillBackLayer->Enable( enableBottom ); // Back layer selector
1944 m_backdrillBackLayerLabel->Enable( enableBottom ); // Back layer label
1945
1946 if( enableBottom )
1947 {
1948 if( m_backdrillBackLayer->GetLayerSelection() == UNDEFINED_LAYER )
1949 m_backdrillBackLayer->SetLayerSelection( B_Cu );
1950
1951 if( m_backdrillBackSize.GetIntValue() == 0 )
1952 {
1953 // Initialize backdrill slightly larger than main drill (see PADSTACK::SetBackdrillMode())
1954 m_backdrillBackSize.SetValue( KiROUND( m_viaDrill.GetIntValue() * 1.1 ) );
1955 }
1956 }
1957}
1958
1959
1961{
1962 int selection = m_topPostMachine->GetSelection();
1963 // 0: None, 1: Countersink, 2: Counterbore
1964
1965 bool enable = ( selection != 0 );
1966 m_topPostMachineSize1.Enable( enable );
1967 m_topPostMachineSize2.Enable( enable );
1968 m_topPostMachineSize1Label->Enable( enable );
1969 m_topPostMachineSize2Label->Enable( enable );
1970
1971 if( selection == 1 ) // Countersink
1972 {
1973 m_topPostMachineSize2Label->SetLabel( _( "Angle:" ) );
1974 m_topPostMachineSize2Units->SetLabel( _( "deg" ) );
1976
1977 if( m_topPostMachineSize2.IsIndeterminate() || m_topPostMachineSize2.GetDoubleValue() == 0 )
1978 {
1979 m_topPostMachineSize2.SetDoubleValue( 82.0 );
1980 }
1981 }
1982 else if( selection == 2 ) // Counterbore
1983 {
1984 m_topPostMachineSize2Label->SetLabel( _( "Depth:" ) );
1985 m_topPostMachineSize2Units->SetLabel( EDA_UNIT_UTILS::GetLabel( m_frame->GetUserUnits() ) );
1986 m_topPostMachineSize2.SetUnits( m_frame->GetUserUnits() );
1987 }
1988 else
1989 {
1990 m_topPostMachineSize2Label->SetLabel( _( "Angle:" ) );
1991 m_topPostMachineSize2Units->SetLabel( _( "deg" ) );
1993 }
1994}
1995
1996
1998{
1999 int selection = m_bottomPostMachine->GetSelection();
2000 // 0: None, 1: Countersink, 2: Counterbore
2001
2002 bool enable = ( selection != 0 );
2003 m_bottomPostMachineSize1.Enable( enable );
2004 m_bottomPostMachineSize2.Enable( enable );
2005 m_bottomPostMachineSize1Label->Enable( enable );
2006 m_bottomPostMachineSize2Label->Enable( enable );
2007
2008 if( selection == 1 ) // Countersink
2009 {
2010 m_bottomPostMachineSize2Label->SetLabel( _( "Angle:" ) );
2011 m_bottomPostMachineSize2Units->SetLabel( _( "deg" ) );
2013
2014 if( m_bottomPostMachineSize2.IsIndeterminate() || m_bottomPostMachineSize2.GetDoubleValue() == 0 )
2015 {
2016 m_bottomPostMachineSize2.SetDoubleValue( 82.0 );
2017 }
2018 }
2019 else if( selection == 2 ) // Counterbore
2020 {
2021 m_bottomPostMachineSize2Label->SetLabel( _( "Depth:" ) );
2022 m_bottomPostMachineSize2Units->SetLabel( EDA_UNIT_UTILS::GetLabel( m_frame->GetUserUnits() ) );
2023 m_bottomPostMachineSize2.SetUnits( m_frame->GetUserUnits() );
2024 }
2025}
2026
2027
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:373
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...
KIBIS top(path, &reporter)
@ 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