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 <pcb_track.h>
34#include <confirm.h>
35#include <kidialog.h>
37#include <board_commit.h>
38#include <magic_enum.hpp>
39
40
42 const IPC4761_CONFIGURATION& aOther ) const
43{
44 return ( tent == aOther.tent ) && ( plug == aOther.plug ) && ( cover == aOther.cover )
45 && ( cap == aOther.cap ) && ( fill == aOther.fill );
46}
47
48
50 const PCB_SELECTION& aItems ) :
52 m_frame( aParent ),
53 m_items( aItems ),
56 m_trackEndX( aParent, m_TrackEndXLabel, m_TrackEndXCtrl, nullptr ),
60 m_viaX( aParent, m_ViaXLabel, m_ViaXCtrl, nullptr ),
69 m_tracks( false ),
70 m_vias( false ),
72{
74
75 wxASSERT( !m_items.Empty() );
76
77 m_legacyTeardropsIcon->SetBitmap( KiBitmapBundle( BITMAPS::dialog_warning ) );
79
80 m_bitmapTeardrop->SetBitmap( KiBitmapBundle( BITMAPS::teardrop_sizes ) );
81
82 m_teardropHDPercent.SetUnits( EDA_UNITS::PERCENT );
83 m_teardropLenPercent.SetUnits( EDA_UNITS::PERCENT );
84 m_teardropWidthPercent.SetUnits( EDA_UNITS::PERCENT );
85
86 m_minTrackWidthHint->SetFont( KIUI::GetInfoFont( this ).Italic() );
87
88 // Configure display origin transforms
95
96 VIATYPE viaType = VIATYPE::NOT_DEFINED;
97
102
105 m_ViaStartLayer->SetBoardFrame( aParent );
107
110 m_ViaEndLayer->SetBoardFrame( aParent );
112
113 wxFont infoFont = KIUI::GetInfoFont( this );
114 m_techLayersLabel->SetFont( infoFont );
115
116 bool nets = false;
117 int net = 0;
118 bool hasLocked = false;
119 bool hasUnlocked = false;
120
121 // Start and end layers of vias
122 // if at least 2 vias do not have the same start or the same end layer
123 // the layers will be set as undefined
124 int selection_first_layer = -1;
125 int selection_last_layer = -1;
126
127 // The selection layer for tracks
128 int track_selection_layer = -1;
129
130 auto getAnnularRingSelection = []( const PCB_VIA* via ) -> int
131 {
132 switch( via->Padstack().UnconnectedLayerMode() )
133 {
134 default:
138 }
139 };
140
141 for( auto& preset : magic_enum::enum_values<IPC4761_PRESET>() )
142 {
143 if( preset >= IPC4761_PRESET::CUSTOM )
144 continue;
145
146 const auto& name_it = m_IPC4761Names.find( preset );
147
148 wxString name = _( "Unknown choice" );
149
150 if( name_it != m_IPC4761Names.end() )
151 name = name_it->second;
152
153 m_protectionFeatures->AppendString( name );
154 }
155
156 auto getProtectionSurface = []( const std::optional<bool>& front,
157 const std::optional<bool>& back ) -> IPC4761_SURFACE
158 {
160
161 if( !front.has_value() )
163 else if( front.value() )
165 else
166 value = IPC4761_SURFACE::NONE;
167
168 if( !back.has_value() )
169 {
170 if( value == IPC4761_SURFACE::FROM_RULES )
172 }
173 else if( back.value() )
174 {
175 if( value == IPC4761_SURFACE::FRONT )
177 else if( value == IPC4761_SURFACE::NONE )
179 }
180 else
181 {
182 if( value == IPC4761_SURFACE::FRONT )
184 else if( value == IPC4761_SURFACE::NONE )
186 }
187
189 };
190
191 auto getProtectionDrill = []( const std::optional<bool>& drill ) -> IPC4761_DRILL
192 {
193 if( !drill.has_value() )
195 if( drill.value() )
196 return IPC4761_DRILL::SET;
197
199 };
200
201 auto getViaConfiguration = [&]( const PCB_VIA* via ) -> IPC4761_PRESET
202 {
204 config.tent = getProtectionSurface( via->Padstack().FrontOuterLayers().has_solder_mask,
205 via->Padstack().BackOuterLayers().has_solder_mask );
206
207 config.cover = getProtectionSurface( via->Padstack().FrontOuterLayers().has_covering,
208 via->Padstack().BackOuterLayers().has_covering );
209
210 config.plug = getProtectionSurface( via->Padstack().FrontOuterLayers().has_plugging,
211 via->Padstack().BackOuterLayers().has_plugging );
212
213 config.cap = getProtectionDrill( via->Padstack().Drill().is_capped );
214
215 config.fill = getProtectionDrill( via->Padstack().Drill().is_filled );
216
217 for( const auto& [preset, configuration] : m_IPC4761Presets )
218 {
219 if( configuration == config )
220 return preset;
221 }
222
224 };
225
226 // Look for values that are common for every item that is selected
227 for( EDA_ITEM* item : m_items )
228 {
229 if( !nets )
230 {
231 net = static_cast<BOARD_CONNECTED_ITEM*>( item )->GetNetCode();
232 nets = true;
233 }
234 else if( net != static_cast<BOARD_CONNECTED_ITEM*>( item )->GetNetCode() )
235 {
236 net = -1;
237 }
238
239 switch( item->Type() )
240 {
241 case PCB_TRACE_T:
242 case PCB_ARC_T:
243 {
244 const PCB_TRACK* t = static_cast<const PCB_TRACK*>( item );
245
246 if( !m_tracks ) // first track in the list
247 {
253 track_selection_layer = t->GetLayer();
254 m_trackHasSolderMask->SetValue ( t->HasSolderMask() );
255
256 if( t->GetLocalSolderMaskMargin().has_value() )
258 else
259 m_trackMaskMargin.SetValue( wxEmptyString );
260
261 m_tracks = true;
262 }
263 else // check if values are the same for every selected track
264 {
265 if( m_trackStartX.GetValue() != t->GetStartX() )
267
268 if( m_trackStartY.GetValue() != t->GetStartY() )
270
271 if( m_trackEndX.GetValue() != t->GetEndX() )
273
274 if( m_trackEndY.GetValue() != t->GetEndY() )
276
277 if( m_trackWidth.GetValue() != t->GetWidth() )
279
280 if( track_selection_layer != t->GetLayer() )
281 track_selection_layer = UNDEFINED_LAYER;
282
283 if( m_trackHasSolderMask->GetValue() != t->HasSolderMask() )
284 m_trackHasSolderMask->Set3StateValue( wxCHK_UNDETERMINED );
285
288 }
289
290 if( t->IsLocked() )
291 hasLocked = true;
292 else
293 hasUnlocked = true;
294
295 break;
296 }
297
298 case PCB_VIA_T:
299 {
300 PCB_VIA* v = static_cast<PCB_VIA*>( item );
301
302 if( !m_vias ) // first via in the list
303 {
306 m_viaStack = std::make_unique<PADSTACK>( v->Padstack() );
309 m_vias = true;
310 viaType = v->GetViaType();
311 m_viaNotFree->SetValue( !v->GetIsFree() );
312 m_annularRingsCtrl->SetSelection( getAnnularRingSelection( v ) );
313
314 selection_first_layer = v->TopLayer();
315 selection_last_layer = v->BottomLayer();
316
317 m_cbTeardrops->SetValue( v->GetTeardropParams().m_Enabled );
325
326 IPC4761_PRESET preset = getViaConfiguration( v );
327
328 if( preset >= IPC4761_PRESET::CUSTOM )
329 {
330 m_protectionFeatures->SetSelection(
332 }
333 else
334 {
335 m_protectionFeatures->SetSelection( static_cast<int>( preset ) );
336 }
337 }
338 else // check if values are the same for every selected via
339 {
340 if( m_viaX.GetValue() != v->GetPosition().x )
342
343 if( m_viaY.GetValue() != v->GetPosition().y )
345
348
349 if( m_viaDrill.GetValue() != v->GetDrillValue() )
351
352 if( viaType != v->GetViaType() )
353 viaType = VIATYPE::NOT_DEFINED;
354
355 if( v->GetIsFree() != !m_viaNotFree->GetValue() )
356 m_viaNotFree->Set3StateValue( wxCHK_UNDETERMINED );
357
358 if( selection_first_layer != v->TopLayer() )
359 selection_first_layer = UNDEFINED_LAYER;
360
361 if( selection_last_layer != v->BottomLayer() )
362 selection_last_layer = UNDEFINED_LAYER;
363
364 if( m_annularRingsCtrl->GetSelection() != getAnnularRingSelection( v ) )
365 {
366 if( m_annularRingsCtrl->GetStrings().size() < 4 )
368
369 m_annularRingsCtrl->SetSelection( 3 );
370 }
371
372 if( m_cbTeardrops->GetValue() != v->GetTeardropParams().m_Enabled )
373 m_cbTeardrops->Set3StateValue( wxCHK_UNDETERMINED );
374
376 m_cbTeardropsUseNextTrack->Set3StateValue( wxCHK_UNDETERMINED );
377
380
383
386
389
392
393
394 if( static_cast<int>( getViaConfiguration( v ) )
395 != m_protectionFeatures->GetSelection() )
396 {
397 m_protectionFeatures->SetSelection(
399 }
400 }
401
402 if( v->IsLocked() )
403 hasLocked = true;
404 else
405 hasUnlocked = true;
406
407 break;
408 }
409
410 default:
411 {
412 wxASSERT( false );
413 break;
414 }
415 }
416 }
417
418 if( m_tracks )
419 {
420 // Set the track layer selection state:
421 if( track_selection_layer == UNDEFINED_LAYER )
422 {
425 }
426
427 m_TrackLayerCtrl->SetLayerSelection( track_selection_layer );
428 }
429
430 // Set the vias layers selections state:
431 if( m_vias )
432 {
433 if( selection_first_layer == UNDEFINED_LAYER )
434 {
437 }
438
439 m_ViaStartLayer->SetLayerSelection( selection_first_layer );
440
441 if( selection_last_layer == UNDEFINED_LAYER )
442 {
445 }
446
447 m_ViaEndLayer->SetLayerSelection( selection_last_layer );
448 }
449
450 m_netSelector->SetBoard( aParent->GetBoard() );
451 m_netSelector->SetNetInfo( &aParent->GetBoard()->GetNetInfo() );
452
453 if ( net >= 0 )
454 {
456 }
457 else
458 {
461 }
462
463 wxASSERT( m_tracks || m_vias );
464
465 if( m_vias )
466 {
467 if( m_viaNotFree->GetValue() && !m_tracks )
468 {
469 // Disable net selector to re-inforce meaning of "Automatically update via nets",
470 // but not when tracks are also selected as then things get harder if you want to
471 // update all the nets to match.
472 m_netSelectorLabel->Disable();
473 m_netSelector->Disable();
474 }
475
476 int viaSelection = wxNOT_FOUND;
477
478 // 0 is the netclass place-holder
479 for( unsigned ii = 1; ii < aParent->GetDesignSettings().m_ViasDimensionsList.size(); ii++ )
480 {
481 VIA_DIMENSION* viaDimension = &aParent->GetDesignSettings().m_ViasDimensionsList[ii];
482 wxString msg = m_frame->StringFromValue( viaDimension->m_Diameter )
483 + wxT( " / " )
484 + m_frame->StringFromValue( viaDimension->m_Drill );
485 m_predefinedViaSizesCtrl->Append( msg, viaDimension );
486
487 if( viaSelection == wxNOT_FOUND
488 && m_viaDiameter.GetValue() == viaDimension->m_Diameter
489 && m_viaDrill.GetValue() == viaDimension->m_Drill )
490 {
491 viaSelection = ii - 1;
492 }
493 }
494
495 m_predefinedViaSizesCtrl->SetSelection( viaSelection );
497
498 m_ViaTypeChoice->Enable();
499
500 switch( viaType )
501 {
502 case VIATYPE::THROUGH: m_ViaTypeChoice->SetSelection( 0 ); break;
503 case VIATYPE::MICROVIA: m_ViaTypeChoice->SetSelection( 1 ); break;
504 case VIATYPE::BLIND_BURIED: m_ViaTypeChoice->SetSelection( 2 ); break;
505 case VIATYPE::NOT_DEFINED: m_ViaTypeChoice->SetSelection( wxNOT_FOUND ); break;
506 }
507
508 m_ViaStartLayer->Enable( viaType != VIATYPE::THROUGH );
509 m_ViaEndLayer->Enable( viaType != VIATYPE::THROUGH );
510
511 m_annularRingsLabel->Show( getLayerDepth() > 1 );
512 m_annularRingsCtrl->Show( getLayerDepth() > 1 );
513
515 }
516 else
517 {
518 m_viaNotFree->Hide();
519 m_MainSizer->Hide( m_sbViaSizer, true );
520 }
521
522 if( m_tracks )
523 {
524 int widthSelection = wxNOT_FOUND;
525
526 // 0 is the netclass place-holder
527 for( unsigned ii = 1; ii < aParent->GetDesignSettings().m_TrackWidthList.size(); ii++ )
528 {
529 int width = aParent->GetDesignSettings().m_TrackWidthList[ii];
530 wxString msg = m_frame->StringFromValue( width );
531 m_predefinedTrackWidthsCtrl->Append( msg );
532
533 if( widthSelection == wxNOT_FOUND && m_trackWidth.GetValue() == width )
534 widthSelection = ii - 1;
535 }
536
537 m_predefinedTrackWidthsCtrl->SetSelection( widthSelection );
539
540 wxCommandEvent event;
541 onTrackEdit( event );
542 }
543 else
544 {
545 m_MainSizer->Hide( m_sbTrackSizer, true );
546 }
547
548 if( hasLocked && hasUnlocked )
549 m_lockedCbox->Set3StateValue( wxCHK_UNDETERMINED );
550 else if( hasLocked )
551 m_lockedCbox->Set3StateValue( wxCHK_CHECKED );
552 else
553 m_lockedCbox->Set3StateValue( wxCHK_UNCHECKED );
554
555 if( m_tracks )
557 else if( m_netSelector->IsEnabled() )
559 else
561
563
564 m_frame->Bind( EDA_EVT_UNITS_CHANGED, &DIALOG_TRACK_VIA_PROPERTIES::onUnitsChanged, this );
565 m_netSelector->Bind( FILTERED_ITEM_SELECTED, &DIALOG_TRACK_VIA_PROPERTIES::onNetSelector, this );
566
567 // Now all widgets have the size fixed, call FinishDialogSettings
569}
570
571
573{
574 m_frame->Unbind( EDA_EVT_UNITS_CHANGED, &DIALOG_TRACK_VIA_PROPERTIES::onUnitsChanged, this );
575}
576
577
579{
580 if( m_vias )
581 {
582 int viaSel = m_predefinedViaSizesCtrl->GetSelection();
583
585
586 // 0 is the netclass place-holder
587 for( unsigned ii = 1; ii < m_frame->GetDesignSettings().m_ViasDimensionsList.size(); ii++ )
588 {
590 wxString msg = m_frame->StringFromValue( viaDimension->m_Diameter )
591 + wxT( " / " )
592 + m_frame->StringFromValue( viaDimension->m_Drill );
593 m_predefinedViaSizesCtrl->Append( msg, viaDimension );
594 }
595
596 m_predefinedViaSizesCtrl->SetSelection( viaSel );
598 }
599
600 if( m_tracks )
601 {
602 int trackSel = m_predefinedTrackWidthsCtrl->GetSelection();
603
605
606 // 0 is the netclass place-holder
607 for( unsigned ii = 1; ii < m_frame->GetDesignSettings().m_TrackWidthList.size(); ii++ )
608 {
609 int width = m_frame->GetDesignSettings().m_TrackWidthList[ii];
610 wxString msg = m_frame->StringFromValue( width );
611 m_predefinedTrackWidthsCtrl->Append( msg );
612 }
613
614 m_predefinedTrackWidthsCtrl->SetSelection( trackSel );
616 }
617
618 aEvent.Skip();
619}
620
621
622bool DIALOG_TRACK_VIA_PROPERTIES::confirmShortingNets( int aNet, const std::set<int>& shortingNets )
623{
624 wxString msg;
625
626 if( shortingNets.size() == 1 )
627 {
628 msg.Printf( _( "Applying these changes will short net %s with %s." ),
629 m_netSelector->GetValue(),
630 m_frame->GetBoard()->FindNet( *shortingNets.begin() )->GetNetname() );
631 }
632 else
633 {
634 msg.Printf( _( "Applying these changes will short net %s with other nets." ),
635 m_netSelector->GetValue() );
636 }
637
638 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
639 dlg.SetOKCancelLabels( _( "Apply Anyway" ), _( "Cancel Changes" ) );
640 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
641
642 return dlg.ShowModal() == wxID_OK;
643}
644
645
646bool DIALOG_TRACK_VIA_PROPERTIES::confirmPadChange( const std::set<PAD*>& changingPads )
647{
648 wxString msg;
649
650 if( changingPads.size() == 1 )
651 {
652 PAD* pad = *changingPads.begin();
653 msg.Printf( _( "Changing the net will also update %s pad %s to %s." ),
654 pad->GetParentFootprint()->GetReference(),
655 pad->GetNumber(),
656 m_netSelector->GetValue() );
657 }
658 else if( changingPads.size() == 2 )
659 {
660 PAD* pad1 = *changingPads.begin();
661 PAD* pad2 = *( ++changingPads.begin() );
662 msg.Printf( _( "Changing the net will also update %s pad %s and %s pad %s to %s." ),
664 pad1->GetNumber(),
666 pad2->GetNumber(),
667 m_netSelector->GetValue() );
668 }
669 else
670 {
671 msg.Printf( _( "Changing the net will also update %lu connected pads to %s." ),
672 static_cast<unsigned long>( changingPads.size() ),
673 m_netSelector->GetValue() );
674 }
675
676 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
677 dlg.SetOKCancelLabels( _( "Change Nets" ), _( "Leave Nets Unchanged" ) );
678 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
679
680 return dlg.ShowModal() == wxID_OK;
681}
682
683
685{
686 std::vector<PCB_TRACK*> selected_tracks;
687
688 for( EDA_ITEM* item : m_items )
689 {
690 if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( item ) )
691 selected_tracks.push_back( track );
692 }
693
694 // Check for malformed data ONLY; design rules and constraints are the business of DRC.
695
696 if( m_vias )
697 {
698 // TODO: This needs to move into the via class, not the dialog
699
701 || !m_viaDrill.Validate( GEOMETRY_MIN_SIZE, INT_MAX ) )
702 {
703 return false;
704 }
705
706 if( m_ViaDiameterCtrl->IsEnabled() && !m_viaDiameter.IsIndeterminate()
707 && m_ViaDrillCtrl->IsEnabled() && !m_viaDrill.IsIndeterminate()
709 {
710 DisplayError( GetParent(), _( "Via hole size must be smaller than via diameter" ) );
711 m_ViaDrillCtrl->SelectAll();
712 m_ViaDrillCtrl->SetFocus();
713 return false;
714 }
715
718 {
719 DisplayError( GetParent(), _( "Via start layer and end layer cannot be the same" ) );
720 return false;
721 }
722
724 {
725 int diameter = m_viaDiameter.GetValue();
726 m_viaStack->SetSize( { diameter, diameter }, m_editLayer );
727 }
728 }
729
730 if( m_tracks )
731 {
732 if( !m_trackWidth.Validate( GEOMETRY_MIN_SIZE, INT_MAX ) )
733 return false;
734 }
735
736 // If we survived that, then save the changes:
737 //
738 // We don't bother with updating the nets at this point as it will be useless (any connected
739 // pads will simply drive their existing nets back onto the track segments and vias).
740
741 BOARD_COMMIT commit( m_frame );
742 bool changeLock = m_lockedCbox->Get3StateValue() != wxCHK_UNDETERMINED;
743 bool setLock = m_lockedCbox->Get3StateValue() == wxCHK_CHECKED;
744
745 for( PCB_TRACK* track : selected_tracks )
746 {
747 commit.Modify( track );
748
749 switch( track->Type() )
750 {
751 case PCB_TRACE_T:
752 case PCB_ARC_T:
753 {
754 wxASSERT( m_tracks );
755
757 track->SetStartX( m_trackStartX.GetIntValue() );
758
760 track->SetStartY( m_trackStartY.GetIntValue() );
761
763 track->SetEndX( m_trackEndX.GetIntValue() );
764
766 track->SetEndY( m_trackEndY.GetIntValue() );
767
769 track->SetWidth( m_trackWidth.GetIntValue() );
770
771 int layer = m_TrackLayerCtrl->GetLayerSelection();
772
773 if( layer != UNDEFINED_LAYER )
774 track->SetLayer( (PCB_LAYER_ID) layer );
775
776 if ( m_trackHasSolderMask->Get3StateValue() != wxCHK_UNDETERMINED )
777 track->SetHasSolderMask( m_trackHasSolderMask->GetValue() );
778
780 {
782 track->SetLocalSolderMaskMargin( {} );
783 else
784 track->SetLocalSolderMaskMargin( m_trackMaskMargin.GetIntValue() );
785 }
786
787 if( changeLock )
788 track->SetLocked( setLock );
789
790 break;
791 }
792
793 case PCB_VIA_T:
794 {
795 wxASSERT( m_vias );
796 PCB_VIA* via = static_cast<PCB_VIA*>( track );
797
798 if( !m_viaX.IsIndeterminate() )
799 via->SetPosition( VECTOR2I( m_viaX.GetIntValue(), via->GetPosition().y ) );
800
801 if( !m_viaY.IsIndeterminate() )
802 via->SetPosition( VECTOR2I( via->GetPosition().x, m_viaY.GetIntValue() ) );
803
804 if( m_viaNotFree->Get3StateValue() != wxCHK_UNDETERMINED )
805 via->SetIsFree( !m_viaNotFree->GetValue() );
806
808 via->SetPadstack( *m_viaStack );
809
810 switch( m_ViaTypeChoice->GetSelection() )
811 {
812 case 0:
813 via->SetViaType( VIATYPE::THROUGH );
814 break;
815 case 1:
816 via->SetViaType( VIATYPE::MICROVIA );
817 break;
818 case 2:
819 via->SetViaType( VIATYPE::BLIND_BURIED );
820 break;
821 default:
822 break;
823 }
824
825 PCB_LAYER_ID startLayer = static_cast<PCB_LAYER_ID>( m_ViaStartLayer->GetLayerSelection() );
826 PCB_LAYER_ID endLayer = static_cast<PCB_LAYER_ID>( m_ViaEndLayer->GetLayerSelection() );
827
828 if( startLayer != UNDEFINED_LAYER )
829 {
830 m_viaStack->Drill().start = startLayer;
831 via->SetTopLayer( startLayer );
832 }
833
834 if( endLayer != UNDEFINED_LAYER )
835 {
836 m_viaStack->Drill().end = endLayer;
837 via->SetBottomLayer( endLayer );
838 }
839
840 via->SanitizeLayers();
841
842 switch( m_annularRingsCtrl->GetSelection() )
843 {
844 case 0:
845 via->Padstack().SetUnconnectedLayerMode(
847 break;
848 case 1:
849 via->Padstack().SetUnconnectedLayerMode(
851 break;
852 case 2:
853 via->Padstack().SetUnconnectedLayerMode(
855 break;
856 default:
857 break;
858 }
859
860
862 via->SetDrill( m_viaDrill.GetIntValue() );
863
864 TEARDROP_PARAMETERS* targetParams = &via->GetTeardropParams();
865
866 if( m_cbTeardrops->Get3StateValue() != wxCHK_UNDETERMINED )
867 targetParams->m_Enabled = m_cbTeardrops->GetValue();
868
869 if( m_cbTeardropsUseNextTrack->Get3StateValue() != wxCHK_UNDETERMINED )
870 targetParams->m_AllowUseTwoTracks = m_cbTeardropsUseNextTrack->GetValue();
871
873 targetParams->m_TdMaxLen = m_teardropMaxLen.GetIntValue();
874
877
879 targetParams->m_BestLengthRatio = m_teardropLenPercent.GetDoubleValue() / 100.0;
880
882 targetParams->m_BestWidthRatio =
884
887
888 if( m_curvedEdges->Get3StateValue() != wxCHK_UNDETERMINED )
889 targetParams->m_CurvedEdges = m_curvedEdges->GetValue();
890
891 if( changeLock )
892 via->SetLocked( setLock );
893
894 auto setSurfaceProtection = [&]( std::optional<bool>& aFront,
895 std::optional<bool>& aBack,
896 IPC4761_SURFACE aProtection )
897 {
898 switch( aProtection )
899 {
901 aFront.reset();
902 aBack.reset();
903 break;
905 aFront = false;
906 aBack = false;
907 break;
909 aFront = true;
910 aBack = false;
911 break;
913 aFront = false;
914 aBack = true;
915 break;
917 aFront = true;
918 aBack = true;
919 break;
920 case IPC4761_SURFACE::CUSTOM: return;
921 }
922 };
923
924 auto setDrillProtection =
925 [&]( std::optional<bool>& aDrill, IPC4761_DRILL aProtection )
926 {
927 switch( aProtection )
928 {
929 case IPC4761_DRILL::FROM_RULES: aDrill.reset(); break;
930 case IPC4761_DRILL::NOT_SET: aDrill = false; break;
931 case IPC4761_DRILL::SET: aDrill = true; break;
932 }
933 };
934
935 IPC4761_PRESET selectedPreset =
936 static_cast<IPC4761_PRESET>( m_protectionFeatures->GetSelection() );
937
938 if( selectedPreset < IPC4761_PRESET::CUSTOM ) // Do not change custom feaure list.
939 {
940 const IPC4761_CONFIGURATION config = m_IPC4761Presets.at( selectedPreset );
941
942 setSurfaceProtection( via->Padstack().FrontOuterLayers().has_solder_mask,
943 via->Padstack().BackOuterLayers().has_solder_mask,
944 config.tent );
945
946 setSurfaceProtection( via->Padstack().FrontOuterLayers().has_plugging,
947 via->Padstack().BackOuterLayers().has_plugging,
948 config.plug );
949
950 setSurfaceProtection( via->Padstack().FrontOuterLayers().has_covering,
951 via->Padstack().BackOuterLayers().has_covering,
952 config.cover );
953
954 setDrillProtection( via->Padstack().Drill().is_filled, config.fill );
955
956 setDrillProtection( via->Padstack().Drill().is_capped, config.cap );
957 }
958
959
960 break;
961 }
962
963 default:
964 wxASSERT( false );
965 break;
966 }
967 }
968
969 std::set<int> shortingNets;
970 int newNetCode = m_netSelector->GetSelectedNetcode();
971 std::set<PAD*> changingPads;
972
973 // Do NOT use the connectivity code here. It will propagate through zones, and we haven't
974 // refilled those yet so it's going to pick up a whole bunch of other nets any time the track
975 // width was increased.
976 auto collide =
978 {
979 for( PCB_LAYER_ID layer : LSET( a->GetLayerSet() & b->GetLayerSet() ).Seq() )
980 {
981 if( a->GetEffectiveShape( layer )->Collide( b->GetEffectiveShape( layer ).get() ) )
982 return true;
983 }
984
985 return false;
986 };
987
988 for( PCB_TRACK* track : selected_tracks )
989 {
990 for( PCB_TRACK* other : m_frame->GetBoard()->Tracks() )
991 {
992 if( other->GetNetCode() == track->GetNetCode() || other->GetNetCode() == newNetCode )
993 continue;
994
995 if( collide( track, other ) )
996 shortingNets.insert( other->GetNetCode() );
997 }
998
999 for( FOOTPRINT* footprint : m_frame->GetBoard()->Footprints() )
1000 {
1001 for( PAD* pad : footprint->Pads() )
1002 {
1003 if( pad->GetNetCode() == newNetCode )
1004 continue;
1005
1006 if( collide( track, pad ) )
1007 {
1008 if( pad->GetNetCode() == track->GetNetCode() )
1009 changingPads.insert( pad );
1010 else
1011 shortingNets.insert( pad->GetNetCode() );
1012 }
1013 }
1014 }
1015 }
1016
1017 if( shortingNets.size() && !confirmShortingNets( newNetCode, shortingNets ) )
1018 {
1019 commit.Revert();
1020 return true;
1021 }
1022
1024 {
1025 if( changingPads.empty() || confirmPadChange( changingPads ) )
1026 {
1027 for( PCB_TRACK* track : selected_tracks )
1028 track->SetNetCode( newNetCode );
1029
1030 for( PAD* pad : changingPads )
1031 {
1032 commit.Modify( pad );
1033 pad->SetNetCode( newNetCode );
1034 }
1035 }
1036 }
1037
1038 commit.Push( _( "Edit Track/Via Properties" ) );
1039 return true;
1040}
1041
1042
1044{
1045 m_viaNotFree->SetValue( false );
1046}
1047
1048
1050{
1051 if( !m_tracks )
1052 {
1053 m_netSelectorLabel->Enable( !m_viaNotFree->GetValue() );
1054 m_netSelector->Enable( !m_viaNotFree->GetValue() );
1055 }
1056}
1057
1058
1060{
1061 m_TrackWidthCtrl->ChangeValue( m_predefinedTrackWidthsCtrl->GetStringSelection() );
1062 m_TrackWidthCtrl->SelectAll();
1063}
1064
1065
1066void DIALOG_TRACK_VIA_PROPERTIES::onWidthEdit( wxCommandEvent& aEvent )
1067{
1068 m_predefinedTrackWidthsCtrl->SetStringSelection( m_TrackWidthCtrl->GetValue() );
1069}
1070
1071
1072void DIALOG_TRACK_VIA_PROPERTIES::onViaSelect( wxCommandEvent& aEvent )
1073{
1074 VIA_DIMENSION* viaDimension = static_cast<VIA_DIMENSION*> ( aEvent.GetClientData() );
1075
1076 m_viaDiameter.ChangeValue( viaDimension->m_Diameter );
1077 m_viaDrill.ChangeValue( viaDimension->m_Drill );
1078}
1079
1080
1082{
1083 wxCHECK_MSG( m_viaStack, /* void */, "Expected valid via stack in onPadstackModeChanged" );
1084
1085 switch( m_cbPadstackMode->GetSelection() )
1086 {
1087 default:
1088 case 0: m_viaStack->SetMode( PADSTACK::MODE::NORMAL ); break;
1089 case 1: m_viaStack->SetMode( PADSTACK::MODE::FRONT_INNER_BACK ); break;
1090 case 2: m_viaStack->SetMode( PADSTACK::MODE::CUSTOM ); break;
1091 }
1092
1094}
1095
1096
1098{
1099 wxCHECK_MSG( m_viaStack, /* void */, "Expected valid via stack in onEditLayerChanged" );
1100
1101 // Save data from the previous layer
1103 {
1104 int diameter = m_viaDiameter.GetValue();
1105 m_viaStack->SetSize( { diameter, diameter }, m_editLayer );
1106 }
1107
1108 switch( m_viaStack->Mode() )
1109 {
1110 default:
1113 break;
1114
1116 switch( m_cbEditLayer->GetSelection() )
1117 {
1118 default:
1119 case 0: m_editLayer = F_Cu; break;
1120 case 1: m_editLayer = PADSTACK::INNER_LAYERS; break;
1121 case 2: m_editLayer = B_Cu; break;
1122 }
1123 break;
1124
1126 {
1127 int layer = m_cbEditLayer->GetSelection();
1128
1129 if( layer < 0 )
1130 layer = 0;
1131
1132 if( m_editLayerCtrlMap.contains( layer ) )
1133 m_editLayer = m_editLayerCtrlMap.at( layer );
1134 else
1135 m_editLayer = F_Cu;
1136 }
1137 }
1138
1139 // Load controls with the current layer
1141}
1142
1143
1145{
1146 // NOTE: synchronize changes here with DIALOG_PAD_PROPERTIES::afterPadstackModeChanged
1147
1148 wxCHECK_MSG( m_viaStack, /* void */, "Expected valid via stack in afterPadstackModeChanged" );
1149 m_cbEditLayer->Clear();
1150
1151 BOARD* board = m_frame->GetBoard();
1152
1153 switch( m_viaStack->Mode() )
1154 {
1156 m_cbPadstackMode->SetSelection( 0 );
1157 m_cbEditLayer->Append( _( "All layers" ) );
1158 m_cbEditLayer->Disable();
1161 break;
1162
1164 {
1165 m_cbPadstackMode->SetSelection( 1 );
1166 m_cbEditLayer->Enable();
1167
1168 std::vector choices = {
1169 board->GetLayerName( F_Cu ),
1170 _( "Inner Layers" ),
1171 board->GetLayerName( B_Cu )
1172 };
1173
1174 m_cbEditLayer->Append( choices );
1175
1177 { 0, F_Cu },
1179 { 2, B_Cu }
1180 };
1181
1182 if( m_editLayer != F_Cu && m_editLayer != B_Cu )
1184
1185 break;
1186 }
1187
1189 {
1190 m_cbPadstackMode->SetSelection( 2 );
1191 m_cbEditLayer->Enable();
1192 LSET layers = LSET::AllCuMask() & board->GetEnabledLayers();
1193
1194 for( PCB_LAYER_ID layer : layers.UIOrder() )
1195 {
1196 int idx = m_cbEditLayer->Append( board->GetLayerName( layer ) );
1197 m_editLayerCtrlMap[idx] = layer;
1198 }
1199
1200 break;
1201 }
1202 }
1203
1204 for( const auto& [idx, layer] : m_editLayerCtrlMap )
1205 {
1206 if( layer == m_editLayer )
1207 {
1208 m_cbEditLayer->SetSelection( idx );
1209 break;
1210 }
1211 }
1212}
1213
1214
1216{
1217 int viaType = m_ViaTypeChoice->GetSelection();
1218
1219 if( viaType <= 0 )
1220 return m_frame->GetBoard()->GetCopperLayerCount() - 1;
1221
1222 int startLayer = m_ViaStartLayer->GetLayerSelection();
1223 int endLayer = m_ViaEndLayer->GetLayerSelection();
1224
1225 if( startLayer < 0 || endLayer < 0 )
1226 return m_frame->GetBoard()->GetCopperLayerCount() - 1;
1227 else
1228 return m_frame->GetBoard()->LayerDepth( ToLAYER_ID( startLayer ), ToLAYER_ID( endLayer ) );
1229}
1230
1231
1232void DIALOG_TRACK_VIA_PROPERTIES::onViaEdit( wxCommandEvent& aEvent )
1233{
1234 m_predefinedViaSizesCtrl->SetSelection( wxNOT_FOUND );
1235
1236 if( m_vias )
1237 {
1238 if( m_ViaTypeChoice->GetSelection() != 0 ) // check if selected type isn't through.
1239 {
1240 m_ViaStartLayer->Enable();
1241 m_ViaEndLayer->Enable();
1242 }
1243 else
1244 {
1247
1248 m_ViaStartLayer->Enable( false );
1249 m_ViaEndLayer->Enable( false );
1250 }
1251
1252 m_annularRingsLabel->Show( getLayerDepth() > 1 );
1253 m_annularRingsCtrl->Show( getLayerDepth() > 1 );
1254 }
1255}
1256
1257
1258void DIALOG_TRACK_VIA_PROPERTIES::onTrackEdit( wxCommandEvent& aEvent )
1259{
1260 bool externalCuLayer = m_TrackLayerCtrl->GetLayerSelection() == F_Cu
1262
1263 m_techLayersLabel->Enable( externalCuLayer );
1264 m_trackHasSolderMask->Enable( externalCuLayer );
1265
1266 bool showMaskMargin = externalCuLayer && m_trackHasSolderMask->GetValue();
1267
1268 m_trackMaskMarginCtrl->Enable( showMaskMargin );
1269 m_trackMaskMarginLabel->Enable( showMaskMargin );
1270 m_trackMaskMarginUnit->Enable( showMaskMargin );
1271}
1272
1273
1275{
1276 event.Enable( !m_frame->GetBoard()->LegacyTeardrops() );
1277}
1278
const char * name
Definition: DXF_plotter.cpp:59
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition: bitmap.cpp:110
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,...
TEARDROP_PARAMETERS & GetTeardropParams()
std::vector< int > m_TrackWidthList
std::vector< VIA_DIMENSION > m_ViasDimensionsList
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:239
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.
Definition: board_item.cpp:278
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:298
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:259
virtual bool IsLocked() const
Definition: board_item.cpp:75
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:296
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:894
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:831
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:2005
int GetCopperLayerCount() const
Definition: board.cpp:783
const FOOTPRINTS & Footprints() const
Definition: board.h:337
const TRACKS & Tracks() const
Definition: board.h:335
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:616
int LayerDepth(PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer) const
Definition: board.cpp:819
bool LegacyTeardrops() const
Definition: board.h:1284
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Modify a given item in the model.
Definition: commit.h:108
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:66
void SetupStandardButtons(std::map< int, wxString > aLabels={})
bool m_useCalculatedSize
Definition: dialog_shim.h:198
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
Class DIALOG_TRACK_VIA_PROPERTIES_BASE.
void onWidthEdit(wxCommandEvent &aEvent) override
void onUnitsChanged(wxCommandEvent &aEvent)
void onNetSelector(wxCommandEvent &aEvent)
void onWidthSelect(wxCommandEvent &aEvent) override
bool confirmShortingNets(int aNet, const std::set< int > &shortingNets)
const std::map< IPC4761_PRESET, IPC4761_CONFIGURATION > m_IPC4761Presets
const std::map< IPC4761_PRESET, wxString > m_IPC4761Names
void onTeardropsUpdateUi(wxUpdateUIEvent &event) override
void onPadstackModeChanged(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 onEditLayerChanged(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:89
const wxString & GetReference() const
Definition: footprint.h:621
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: kidialog.h:43
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:53
int ShowModal() override
Definition: kidialog.cpp:95
int SetLayerSelection(int layer)
bool SetLayersHotkeys(bool value)
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:37
LSEQ UIOrder() const
Return the copper, technical and user layers in the order shown in layer widget.
Definition: lset.cpp:711
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition: lset.cpp:583
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:572
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:297
const wxString & GetNetname() const
Definition: netinfo.h:114
void SetNetInfo(const NETINFO_LIST *aNetInfoList)
bool IsIndeterminate()
void SetBoard(BOARD *aBoard)
int GetSelectedNetcode()
void SetIndeterminateString(const wxString &aString)
void SetSelectedNetcode(int aNetcode)
void SetIndeterminate()
A PADSTACK defines the characteristics of a single or multi-layer pad, in the IPC sense of the word.
Definition: padstack.h:124
@ NORMAL
Shape is the same on all layers.
@ CUSTOM
Shapes can be defined on arbitrary layers.
@ FRONT_INNER_BACK
Up to three shapes can be defined (F_Cu, inner copper layers, B_Cu)
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition: padstack.h:144
static constexpr PCB_LAYER_ID INNER_LAYERS
! The layer identifier to use for "inner layers" on top/inner/bottom padstacks
Definition: padstack.h:147
Definition: pad.h:54
const wxString & GetNumber() const
Definition: pad.h:134
Common, abstract interface for edit frames.
BOARD * GetBoard() const
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Return the BOARD_DESIGN_SETTINGS for the open project.
void SetBoardFrame(PCB_BASE_FRAME *aFrame)
void SetNotAllowedLayerSet(LSET aMask)
void SetUndefinedLayerName(const wxString &aName)
bool HasSolderMask() const
Definition: pcb_track.h:174
int GetStartY() const
Definition: pcb_track.h:156
int GetEndX() const
Definition: pcb_track.h:161
std::optional< int > GetLocalSolderMaskMargin() const
Definition: pcb_track.h:177
int GetEndY() const
Definition: pcb_track.h:162
int GetStartX() const
Definition: pcb_track.h:155
virtual int GetWidth() const
Definition: pcb_track.h:144
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:686
PCB_LAYER_ID BottomLayer() const
Definition: pcb_track.cpp:1328
VECTOR2I GetPosition() const override
Definition: pcb_track.h:537
const PADSTACK & Padstack() const
Definition: pcb_track.h:440
int GetWidth() const override
Definition: pcb_track.cpp:359
PCB_LAYER_ID TopLayer() const
Definition: pcb_track.cpp:1322
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
Definition: pcb_track.cpp:613
VIATYPE GetViaType() const
Definition: pcb_track.h:437
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:110
TEARDROP_PARAMETARS is a helper class to handle parameters needed to build teardrops for a board thes...
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.
EDA_UNITS GetUserUnits() const
wxString StringFromValue(double aValue, bool aAddUnitLabel=false, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
Converts aValue in internal units into a united string.
int GetIntValue()
Definition: unit_binder.h:129
virtual long long int GetValue()
Return the current value in Internal Units.
virtual void SetUnits(EDA_UNITS aUnits)
Normally not needed (as the UNIT_BINDER inherits from the parent frame), but can be used to set to DE...
virtual double GetDoubleValue()
Return the current value in Internal Units.
bool IsIndeterminate() const
Return true if the control holds the indeterminate value (for instance, if it represents a multiple s...
virtual void SetDoubleValue(double aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
virtual bool Validate(double aMin, double aMax, EDA_UNITS aUnits=EDA_UNITS::UNSCALED)
Validate the control against the given range, informing the user of any errors found.
virtual void ChangeValue(int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion WITHOUT trigger...
virtual void SetValue(long long int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
void SetCoordType(ORIGIN_TRANSFORMS::COORD_TYPES_T aCoordType)
Set the current origin transform mode.
Definition: unit_binder.h:200
bool IsNull() const
Return true if the control holds no value (ie: empty string, not 0).
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:170
This file is part of the common library.
#define _(s)
@ ALL_LAYERS
This file is part of the common library.
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ B_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:722
KICOMMON_API wxString GetLabel(EDA_UNITS aUnits, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Get the units string for a given units type.
Definition: eda_units.cpp:156
KICOMMON_API wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:155
#define GEOMETRY_MIN_SIZE
Definition: pcb_track.h:112
VIATYPE
Definition: pcb_track.h:66
bool collide(T aObject, U aAnotherObject, int aLayer, int aMinDistance)
Used by SHAPE_INDEX to implement Query().
Definition: shape_index.h:97
bool operator==(const IPC4761_CONFIGURATION &other) const
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