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