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#include <macros.h>
40#include <optional>
41
42
43bool DIALOG_TRACK_VIA_PROPERTIES::IPC4761_CONFIGURATION::operator==( const IPC4761_CONFIGURATION& aOther ) const
44{
45 return ( tent == aOther.tent ) && ( plug == aOther.plug ) && ( cover == aOther.cover )
46 && ( cap == aOther.cap ) && ( fill == aOther.fill );
47}
48
49
51 const PCB_SELECTION& aItems ) :
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 ),
70 m_tracks( false ),
71 m_vias( false ),
73{
75
76 wxASSERT( !m_items.Empty() );
77
79 m_legacyTeardropsWarning->Show( m_frame->GetBoard()->LegacyTeardrops() );
80
82
86
87 m_minTrackWidthHint->SetFont( KIUI::GetInfoFont( this ).Italic() );
88
89 // Configure display origin transforms
96
97 m_TrackLayerCtrl->SetLayersHotkeys( false );
98 m_TrackLayerCtrl->SetNotAllowedLayerSet( LSET::AllNonCuMask() );
99 m_TrackLayerCtrl->SetBoardFrame( aParent );
100 m_TrackLayerCtrl->Resync();
101
102 m_ViaStartLayer->SetLayersHotkeys( false );
103 m_ViaStartLayer->SetNotAllowedLayerSet( LSET::AllNonCuMask() );
104 m_ViaStartLayer->SetBoardFrame( aParent );
105 m_ViaStartLayer->Resync();
106
107 m_ViaEndLayer->SetLayersHotkeys( false );
108 m_ViaEndLayer->SetNotAllowedLayerSet( LSET::AllNonCuMask() );
109 m_ViaEndLayer->SetBoardFrame( aParent );
110 m_ViaEndLayer->Resync();
111
112 wxFont infoFont = KIUI::GetSmallInfoFont( this );
113 m_techLayersLabel->SetFont( infoFont );
114
115 m_frame->Bind( EDA_EVT_UNITS_CHANGED, &DIALOG_TRACK_VIA_PROPERTIES::onUnitsChanged, this );
116 m_netSelector->Bind( FILTERED_ITEM_SELECTED, &DIALOG_TRACK_VIA_PROPERTIES::onNetSelector, this );
117
118 for( auto& preset : magic_enum::enum_values<IPC4761_PRESET>() )
119 {
120 if( preset >= IPC4761_PRESET::CUSTOM )
121 continue;
122
123 const auto& name_it = m_IPC4761Names.find( preset );
124
125 wxString name = _( "Unknown choice" );
126
127 if( name_it != m_IPC4761Names.end() )
128 name = name_it->second;
129
130 m_protectionFeatures->AppendString( name );
131 }
132
134}
135
136
142
143
145{
146 // Setting widgets states/values must be in TransferDataToWindow, not in CTor
147 // otherwise states/values are overwritten by the DIALOG_SHIM::TransferDataToWindow() config values
148 bool nets = false;
149 int net = 0;
150 bool hasLocked = false;
151 bool hasUnlocked = false;
153
154 // Start and end layers of vias
155 // if at least 2 vias do not have the same start or the same end layer
156 // the layers will be set as undefined
157 int selection_first_layer = -1;
158 int selection_last_layer = -1;
159
160 // The selection layer for tracks
161 int track_selection_layer = -1;
162
163 auto getAnnularRingSelection =
164 []( const PCB_VIA* via ) -> int
165 {
166 switch( via->Padstack().UnconnectedLayerMode() )
167 {
168 default:
173 }
174 };
175
176 // Look for values that are common for every item that is selected
177 for( EDA_ITEM* item : m_items )
178 {
179 if( !nets )
180 {
181 net = static_cast<BOARD_CONNECTED_ITEM*>( item )->GetNetCode();
182 nets = true;
183 }
184 else if( net != static_cast<BOARD_CONNECTED_ITEM*>( item )->GetNetCode() )
185 {
186 net = -1;
187 }
188
189 switch( item->Type() )
190 {
191 case PCB_TRACE_T:
192 case PCB_ARC_T:
193 {
194 const PCB_TRACK* t = static_cast<const PCB_TRACK*>( item );
195
196 if( !m_tracks ) // first track in the list
197 {
198 m_trackStartX.SetValue( t->GetStartX() );
199 m_trackStartY.SetValue( t->GetStartY() );
200 m_trackEndX.SetValue( t->GetEndX() );
201 m_trackEndY.SetValue( t->GetEndY() );
202 m_trackWidth.SetValue( t->GetWidth() );
203 track_selection_layer = t->GetLayer();
204 m_trackHasSolderMask->SetValue ( t->HasSolderMask() );
205
206 if( t->GetLocalSolderMaskMargin().has_value() )
207 m_trackMaskMargin.SetValue( t->GetLocalSolderMaskMargin().value() );
208 else
209 m_trackMaskMargin.SetValue( wxEmptyString );
210
211 m_tracks = true;
212 }
213 else // check if values are the same for every selected track
214 {
215 if( m_trackStartX.GetValue() != t->GetStartX() )
217
218 if( m_trackStartY.GetValue() != t->GetStartY() )
220
221 if( m_trackEndX.GetValue() != t->GetEndX() )
223
224 if( m_trackEndY.GetValue() != t->GetEndY() )
226
227 if( m_trackWidth.GetValue() != t->GetWidth() )
229
230 if( track_selection_layer != t->GetLayer() )
231 track_selection_layer = UNDEFINED_LAYER;
232
233 if( m_trackHasSolderMask->GetValue() != t->HasSolderMask() )
234 m_trackHasSolderMask->Set3StateValue( wxCHK_UNDETERMINED );
235
236 if( m_trackMaskMargin.GetValue() != t->GetLocalSolderMaskMargin() )
238 }
239
240 if( t->IsLocked() )
241 hasLocked = true;
242 else
243 hasUnlocked = true;
244
245 break;
246 }
247
248 case PCB_VIA_T:
249 {
250 PCB_VIA* v = static_cast<PCB_VIA*>( item );
251
252 if( !m_vias ) // first via in the list
253 {
254 m_viaX.SetValue( v->GetPosition().x );
255 m_viaY.SetValue( v->GetPosition().y );
256 m_viaStack = std::make_unique<PADSTACK>( v->Padstack() );
257 m_viaDiameter.SetValue( v->GetWidth( m_editLayer ) );
258 m_viaDrill.SetValue( v->GetDrillValue() );
259 m_vias = true;
260 viaType = v->GetViaType();
261 m_viaNotFree->SetValue( !v->GetIsFree() );
262 m_annularRingsCtrl->SetSelection( getAnnularRingSelection( v ) );
263
264 selection_first_layer = v->TopLayer();
265 selection_last_layer = v->BottomLayer();
266
267 m_cbTeardrops->SetValue( v->GetTeardropParams().m_Enabled );
271 m_teardropLenPercent.SetDoubleValue( v->GetTeardropParams().m_BestLengthRatio*100.0 );
272 m_teardropWidthPercent.SetDoubleValue( v->GetTeardropParams().m_BestWidthRatio*100.0 );
275
277
278 if( preset >= IPC4761_PRESET::CUSTOM )
280 else
281 m_protectionFeatures->SetSelection( static_cast<int>( preset ) );
282 }
283 else // check if values are the same for every selected via
284 {
285 if( m_viaX.GetValue() != v->GetPosition().x )
286 m_viaX.SetValue( INDETERMINATE_STATE );
287
288 if( m_viaY.GetValue() != v->GetPosition().y )
289 m_viaY.SetValue( INDETERMINATE_STATE );
290
291 if( m_viaDiameter.GetValue() != v->GetWidth( m_editLayer ) )
293
294 if( m_viaDrill.GetValue() != v->GetDrillValue() )
296
297 if( viaType != v->GetViaType() )
298 viaType = VIATYPE::NOT_DEFINED;
299
300 if( v->GetIsFree() != !m_viaNotFree->GetValue() )
301 m_viaNotFree->Set3StateValue( wxCHK_UNDETERMINED );
302
303 if( selection_first_layer != v->TopLayer() )
304 selection_first_layer = UNDEFINED_LAYER;
305
306 if( selection_last_layer != v->BottomLayer() )
307 selection_last_layer = UNDEFINED_LAYER;
308
309 if( m_annularRingsCtrl->GetSelection() != getAnnularRingSelection( v ) )
310 {
311 if( m_annularRingsCtrl->GetStrings().size() < 4 )
313
314 m_annularRingsCtrl->SetSelection( 3 );
315 }
316
317 if( m_cbTeardrops->GetValue() != v->GetTeardropParams().m_Enabled )
318 m_cbTeardrops->Set3StateValue( wxCHK_UNDETERMINED );
319
321 m_cbTeardropsUseNextTrack->Set3StateValue( wxCHK_UNDETERMINED );
322
323 if( m_teardropMaxLen.GetValue() != v->GetTeardropParams().m_TdMaxLen )
325
326 if( m_teardropMaxWidth.GetValue() != v->GetTeardropParams().m_TdMaxWidth )
328
329 if( m_teardropLenPercent.GetDoubleValue() != v->GetTeardropParams().m_BestLengthRatio *100.0 )
331
332 if( m_teardropWidthPercent.GetDoubleValue() != v->GetTeardropParams().m_BestWidthRatio *100.0 )
334
335 if( m_teardropHDPercent.GetDoubleValue() != v->GetTeardropParams().m_WidthtoSizeFilterRatio*100.0 )
337
338 if( static_cast<int>( getViaConfiguration( v ) ) != m_protectionFeatures->GetSelection() )
340 }
341
342 if( v->IsLocked() )
343 hasLocked = true;
344 else
345 hasUnlocked = true;
346
347 break;
348 }
349
350 default:
351 {
352 UNIMPLEMENTED_FOR( item->GetClass() );
353 break;
354 }
355 }
356 }
357
358 if( m_tracks )
359 {
360 // Set the track layer selection state:
361 if( track_selection_layer == UNDEFINED_LAYER )
362 {
363 m_TrackLayerCtrl->SetUndefinedLayerName( INDETERMINATE_STATE );
364 m_TrackLayerCtrl->Resync();
365 }
366
367 m_TrackLayerCtrl->SetLayerSelection( track_selection_layer );
368 }
369
370 // Set the vias layers selections state:
371 if( m_vias )
372 {
373 if( selection_first_layer == UNDEFINED_LAYER )
374 {
375 m_ViaStartLayer->SetUndefinedLayerName( INDETERMINATE_STATE );
376 m_ViaStartLayer->Resync();
377 }
378
379 m_ViaStartLayer->SetLayerSelection( selection_first_layer );
380
381 if( selection_last_layer == UNDEFINED_LAYER )
382 {
383 m_ViaEndLayer->SetUndefinedLayerName( INDETERMINATE_STATE );
384 m_ViaEndLayer->Resync();
385 }
386
387 m_ViaEndLayer->SetLayerSelection( selection_last_layer );
388 }
389
390 m_netSelector->SetNetInfo( &m_frame->GetBoard()->GetNetInfo() );
391
392 if ( net >= 0 )
393 {
394 m_netSelector->SetSelectedNetcode( net );
395 }
396 else
397 {
398 m_netSelector->SetIndeterminateString( INDETERMINATE_STATE );
399 m_netSelector->SetIndeterminate();
400 }
401
402 wxASSERT( m_tracks || m_vias );
403
404 if( m_vias )
405 {
406 if( m_viaNotFree->GetValue() && !m_tracks )
407 {
408 // Disable net selector to re-inforce meaning of "Automatically update via nets",
409 // but not when tracks are also selected as then things get harder if you want to
410 // update all the nets to match.
411 m_netSelectorLabel->Disable();
412 m_netSelector->Disable();
413 }
414
415 int viaSelection = wxNOT_FOUND;
416
417 // 0 is the netclass place-holder
418 for( unsigned ii = 1; ii < m_frame->GetDesignSettings().m_ViasDimensionsList.size(); ii++ )
419 {
420 VIA_DIMENSION* viaDimension = &m_frame->GetDesignSettings().m_ViasDimensionsList[ii];
421 wxString msg = m_frame->StringFromValue( viaDimension->m_Diameter )
422 + wxT( " / " )
423 + m_frame->StringFromValue( viaDimension->m_Drill );
424 m_predefinedViaSizesCtrl->Append( msg, viaDimension );
425
426 if( viaSelection == wxNOT_FOUND
427 && m_viaDiameter.GetValue() == viaDimension->m_Diameter
428 && m_viaDrill.GetValue() == viaDimension->m_Drill )
429 {
430 viaSelection = ii - 1;
431 }
432 }
433
434 m_predefinedViaSizesCtrl->SetSelection( viaSelection );
435 m_predefinedViaSizesUnits->SetLabel( EDA_UNIT_UTILS::GetLabel( m_frame->GetUserUnits() ) );
436
437 m_ViaTypeChoice->Enable();
438
439 switch( viaType )
440 {
441 case VIATYPE::THROUGH: m_ViaTypeChoice->SetSelection( 0 ); break;
442 case VIATYPE::MICROVIA: m_ViaTypeChoice->SetSelection( 1 ); break;
443 case VIATYPE::BLIND: m_ViaTypeChoice->SetSelection( 2 ); break;
444 case VIATYPE::BURIED: m_ViaTypeChoice->SetSelection( 3 ); break;
445 case VIATYPE::NOT_DEFINED: m_ViaTypeChoice->SetSelection( wxNOT_FOUND ); break;
446 }
447
448 m_ViaStartLayer->Enable( viaType != VIATYPE::THROUGH );
449 m_ViaEndLayer->Enable( viaType != VIATYPE::THROUGH );
450
451 m_annularRingsLabel->Show( getLayerDepth() > 1 );
452 m_annularRingsCtrl->Show( getLayerDepth() > 1 );
453 m_annularRingsCtrl->Enable( true );
454
456 }
457 else
458 {
459 m_viaNotFree->Hide();
460 m_MainSizer->Hide( m_sbViaSizer, true );
461 }
462
463 if( m_tracks )
464 {
465 int widthSelection = wxNOT_FOUND;
466
467 // 0 is the netclass place-holder
468 for( unsigned ii = 1; ii < m_frame->GetDesignSettings().m_TrackWidthList.size(); ii++ )
469 {
470 int width = m_frame->GetDesignSettings().m_TrackWidthList[ii];
471 wxString msg = m_frame->StringFromValue( width );
472 m_predefinedTrackWidthsCtrl->Append( msg );
473
474 if( widthSelection == wxNOT_FOUND && m_trackWidth.GetValue() == width )
475 widthSelection = ii - 1;
476 }
477
478 m_predefinedTrackWidthsCtrl->SetSelection( widthSelection );
479 m_predefinedTrackWidthsUnits->SetLabel( EDA_UNIT_UTILS::GetLabel( m_frame->GetUserUnits() ) );
480
481 wxCommandEvent event;
482 onTrackEdit( event );
483 }
484 else
485 {
486 m_MainSizer->Hide( m_sbTrackSizer, true );
487 }
488
489 if( hasLocked && hasUnlocked )
490 m_lockedCbox->Set3StateValue( wxCHK_UNDETERMINED );
491 else if( hasLocked )
492 m_lockedCbox->Set3StateValue( wxCHK_CHECKED );
493 else
494 m_lockedCbox->Set3StateValue( wxCHK_UNCHECKED );
495
496 if( m_tracks )
498 else if( m_netSelector->IsEnabled() )
500 else
502
503 // Now all widgets have the size fixed, call FinishDialogSettings
505
506 return true;
507}
508
509
511{
512 if( m_vias )
513 {
514 int viaSel = m_predefinedViaSizesCtrl->GetSelection();
515
517
518 // 0 is the netclass place-holder
519 for( unsigned ii = 1; ii < m_frame->GetDesignSettings().m_ViasDimensionsList.size(); ii++ )
520 {
521 VIA_DIMENSION* viaDimension = &m_frame->GetDesignSettings().m_ViasDimensionsList[ii];
522 wxString msg = m_frame->StringFromValue( viaDimension->m_Diameter )
523 + wxT( " / " )
524 + m_frame->StringFromValue( viaDimension->m_Drill );
525 m_predefinedViaSizesCtrl->Append( msg, viaDimension );
526 }
527
528 m_predefinedViaSizesCtrl->SetSelection( viaSel );
529 m_predefinedViaSizesUnits->SetLabel( EDA_UNIT_UTILS::GetLabel( m_frame->GetUserUnits() ) );
530 }
531
532 if( m_tracks )
533 {
534 int trackSel = m_predefinedTrackWidthsCtrl->GetSelection();
535
537
538 // 0 is the netclass place-holder
539 for( unsigned ii = 1; ii < m_frame->GetDesignSettings().m_TrackWidthList.size(); ii++ )
540 {
541 int width = m_frame->GetDesignSettings().m_TrackWidthList[ii];
542 wxString msg = m_frame->StringFromValue( width );
543 m_predefinedTrackWidthsCtrl->Append( msg );
544 }
545
546 m_predefinedTrackWidthsCtrl->SetSelection( trackSel );
547 m_predefinedTrackWidthsUnits->SetLabel( EDA_UNIT_UTILS::GetLabel( m_frame->GetUserUnits() ) );
548 }
549
550 aEvent.Skip();
551}
552
553
554bool DIALOG_TRACK_VIA_PROPERTIES::confirmShortingNets( int aNet, const std::set<int>& shortingNets )
555{
556 wxString msg;
557
558 if( shortingNets.size() == 1 )
559 {
560 msg.Printf( _( "Applying these changes will short net %s with %s." ),
561 m_netSelector->GetValue(),
562 m_frame->GetBoard()->FindNet( *shortingNets.begin() )->GetNetname() );
563 }
564 else
565 {
566 msg.Printf( _( "Applying these changes will short net %s with other nets." ),
567 m_netSelector->GetValue() );
568 }
569
570 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
571 dlg.SetOKCancelLabels( _( "Apply Anyway" ), _( "Cancel Changes" ) );
572 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
573
574 return dlg.ShowModal() == wxID_OK;
575}
576
577
578bool DIALOG_TRACK_VIA_PROPERTIES::confirmPadChange( const std::set<PAD*>& changingPads )
579{
580 wxString msg;
581
582 if( changingPads.size() == 1 )
583 {
584 PAD* pad = *changingPads.begin();
585 msg.Printf( _( "Changing the net will also update %s pad %s to %s." ),
586 pad->GetParentFootprint()->GetReference(),
587 pad->GetNumber(),
588 m_netSelector->GetValue() );
589 }
590 else if( changingPads.size() == 2 )
591 {
592 PAD* pad1 = *changingPads.begin();
593 PAD* pad2 = *( ++changingPads.begin() );
594 msg.Printf( _( "Changing the net will also update %s pad %s and %s pad %s to %s." ),
596 pad1->GetNumber(),
598 pad2->GetNumber(),
599 m_netSelector->GetValue() );
600 }
601 else
602 {
603 msg.Printf( _( "Changing the net will also update %lu connected pads to %s." ),
604 static_cast<unsigned long>( changingPads.size() ),
605 m_netSelector->GetValue() );
606 }
607
608 KIDIALOG dlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
609 dlg.SetOKCancelLabels( _( "Change Nets" ), _( "Leave Nets Unchanged" ) );
610 dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
611
612 return dlg.ShowModal() == wxID_OK;
613}
614
615
617{
618 std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_frame->GetBoard()->GetConnectivity();
619 std::vector<PCB_TRACK*> selected_tracks;
620 std::set<PCB_TRACK*> connected_tracks;
621
622 for( EDA_ITEM* item : m_items )
623 {
624 if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( item ) )
625 selected_tracks.push_back( track );
626 }
627
628 for( PCB_TRACK* selected_track : selected_tracks )
629 {
630 for( BOARD_CONNECTED_ITEM* connected_item : connectivity->GetConnectedItems( selected_track ) )
631 {
632 if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( connected_item ) )
633 connected_tracks.insert( track );
634 }
635 }
636
637 // Check for malformed data ONLY; design rules and constraints are the business of DRC.
638
639 if( m_vias )
640 {
641 // TODO: This needs to move into the via class, not the dialog
642
643 std::optional<int> viaDiameter;
644
645 if( m_ViaDiameterCtrl->IsEnabled() && !m_viaDiameter.IsIndeterminate() )
646 viaDiameter = m_viaDiameter.GetValue();
647
648 std::optional<int> viaDrill;
649
650 if( m_ViaDrillCtrl->IsEnabled() && !m_viaDrill.IsIndeterminate() )
651 viaDrill = m_viaDrill.GetValue();
652
653 std::optional<PCB_LAYER_ID> startLayer;
654
655 if( m_ViaStartLayer->GetLayerSelection() != UNDEFINED_LAYER )
656 startLayer = static_cast<PCB_LAYER_ID>( m_ViaStartLayer->GetLayerSelection() );
657
658 std::optional<PCB_LAYER_ID> endLayer;
659
660 if( m_ViaEndLayer->GetLayerSelection() != UNDEFINED_LAYER )
661 endLayer = static_cast<PCB_LAYER_ID>( m_ViaEndLayer->GetLayerSelection() );
662
663 if( std::optional<PCB_VIA::VIA_PARAMETER_ERROR> error =
664 PCB_VIA::ValidateViaParameters( viaDiameter, viaDrill, startLayer, endLayer ) )
665 {
666 DisplayError( GetParent(), error->m_Message );
667
668 if( error->m_Field == PCB_VIA::VIA_PARAMETER_ERROR::FIELD::DRILL )
669 {
670 m_ViaDrillCtrl->SelectAll();
671 m_ViaDrillCtrl->SetFocus();
672 }
673 else if( error->m_Field == PCB_VIA::VIA_PARAMETER_ERROR::FIELD::DIAMETER )
674 {
675 m_ViaDiameterCtrl->SelectAll();
676 m_ViaDiameterCtrl->SetFocus();
677 }
678
679 return false;
680 }
681
682 if( viaDiameter.has_value() )
683 {
684 int diameter = viaDiameter.value();
685 m_viaStack->SetSize( { diameter, diameter }, m_editLayer );
686 }
687 }
688
689 if( m_tracks )
690 {
691 if( !m_trackWidth.Validate( GEOMETRY_MIN_SIZE, INT_MAX ) )
692 return false;
693 }
694
695 // If we survived that, then save the changes:
696 //
697 // We don't bother with updating the nets at this point as it will be useless (any connected
698 // pads will simply drive their existing nets back onto the track segments and vias).
699
700 BOARD_COMMIT commit( m_frame );
701 bool changeLock = m_lockedCbox->Get3StateValue() != wxCHK_UNDETERMINED;
702 bool setLock = m_lockedCbox->Get3StateValue() == wxCHK_CHECKED;
703
704 for( PCB_TRACK* track : selected_tracks )
705 {
706 commit.Modify( track );
707
708 switch( track->Type() )
709 {
710 case PCB_TRACE_T:
711 case PCB_ARC_T:
712 {
713 wxASSERT( m_tracks );
714
715 if( !m_trackStartX.IsIndeterminate() )
716 track->SetStartX( m_trackStartX.GetIntValue() );
717
718 if( !m_trackStartY.IsIndeterminate() )
719 track->SetStartY( m_trackStartY.GetIntValue() );
720
721 if( !m_trackEndX.IsIndeterminate() )
722 track->SetEndX( m_trackEndX.GetIntValue() );
723
724 if( !m_trackEndY.IsIndeterminate() )
725 track->SetEndY( m_trackEndY.GetIntValue() );
726
727 if( !m_trackWidth.IsIndeterminate() )
728 track->SetWidth( m_trackWidth.GetIntValue() );
729
730 int layer = m_TrackLayerCtrl->GetLayerSelection();
731
732 if( layer != UNDEFINED_LAYER )
733 track->SetLayer( (PCB_LAYER_ID) layer );
734
735 if ( m_trackHasSolderMask->Get3StateValue() != wxCHK_UNDETERMINED )
736 track->SetHasSolderMask( m_trackHasSolderMask->GetValue() );
737
738 if( !m_trackMaskMargin.IsIndeterminate() )
739 {
740 if( m_trackMaskMargin.IsNull() )
741 track->SetLocalSolderMaskMargin( {} );
742 else
743 track->SetLocalSolderMaskMargin( m_trackMaskMargin.GetIntValue() );
744 }
745
746 if( changeLock )
747 track->SetLocked( setLock );
748
749 break;
750 }
751
752 case PCB_VIA_T:
753 {
754 wxASSERT( m_vias );
755 PCB_VIA* via = static_cast<PCB_VIA*>( track );
756
757 if( !m_viaX.IsIndeterminate() )
758 via->SetPosition( VECTOR2I( m_viaX.GetIntValue(), via->GetPosition().y ) );
759
760 if( !m_viaY.IsIndeterminate() )
761 via->SetPosition( VECTOR2I( via->GetPosition().x, m_viaY.GetIntValue() ) );
762
763 if( m_viaNotFree->Get3StateValue() != wxCHK_UNDETERMINED )
764 via->SetIsFree( !m_viaNotFree->GetValue() );
765
766 if( !m_viaDiameter.IsIndeterminate() )
767 via->SetPadstack( *m_viaStack );
768
769 switch( m_ViaTypeChoice->GetSelection() )
770 {
771 case 0: via->SetViaType( VIATYPE::THROUGH ); break;
772 case 1: via->SetViaType( VIATYPE::MICROVIA ); break;
773 case 2: via->SetViaType( VIATYPE::BLIND ); break;
774 case 3: via->SetViaType( VIATYPE::BURIED ); break;
775 default: break;
776 }
777
778 PCB_LAYER_ID startLayer = static_cast<PCB_LAYER_ID>( m_ViaStartLayer->GetLayerSelection() );
779 PCB_LAYER_ID endLayer = static_cast<PCB_LAYER_ID>( m_ViaEndLayer->GetLayerSelection() );
780
781 if( startLayer != UNDEFINED_LAYER )
782 {
783 m_viaStack->Drill().start = startLayer;
784 via->SetTopLayer( startLayer );
785 }
786
787 if( endLayer != UNDEFINED_LAYER )
788 {
789 m_viaStack->Drill().end = endLayer;
790 via->SetBottomLayer( endLayer );
791 }
792
793 via->SanitizeLayers();
794
795 switch( m_annularRingsCtrl->GetSelection() )
796 {
797 case 0:
798 via->Padstack().SetUnconnectedLayerMode(
800 break;
801 case 1:
802 via->Padstack().SetUnconnectedLayerMode(
804 break;
805 case 2:
806 via->Padstack().SetUnconnectedLayerMode(
808 break;
809 case 3:
810 via->Padstack().SetUnconnectedLayerMode(
812 break;
813 default:
814 break;
815 }
816
817
818 if( !m_viaDrill.IsIndeterminate() )
819 via->SetDrill( m_viaDrill.GetIntValue() );
820
821 TEARDROP_PARAMETERS* targetParams = &via->GetTeardropParams();
822
823 if( m_cbTeardrops->Get3StateValue() != wxCHK_UNDETERMINED )
824 targetParams->m_Enabled = m_cbTeardrops->GetValue();
825
826 if( m_cbTeardropsUseNextTrack->Get3StateValue() != wxCHK_UNDETERMINED )
827 targetParams->m_AllowUseTwoTracks = m_cbTeardropsUseNextTrack->GetValue();
828
829 if( !m_teardropMaxLen.IsIndeterminate() )
830 targetParams->m_TdMaxLen = m_teardropMaxLen.GetIntValue();
831
832 if( !m_teardropMaxWidth.IsIndeterminate() )
833 targetParams->m_TdMaxWidth = m_teardropMaxWidth.GetIntValue();
834
835 if( !m_teardropLenPercent.IsIndeterminate() )
836 targetParams->m_BestLengthRatio = m_teardropLenPercent.GetDoubleValue() / 100.0;
837
838 if( !m_teardropWidthPercent.IsIndeterminate() )
839 targetParams->m_BestWidthRatio = m_teardropWidthPercent.GetDoubleValue() / 100.0;
840
841 if( !m_teardropHDPercent.IsIndeterminate() )
842 targetParams->m_WidthtoSizeFilterRatio = m_teardropHDPercent.GetDoubleValue() / 100.0;
843
844 if( m_curvedEdges->Get3StateValue() != wxCHK_UNDETERMINED )
845 targetParams->m_CurvedEdges = m_curvedEdges->GetValue();
846
847 if( changeLock )
848 via->SetLocked( setLock );
849
850 setViaConfiguration( via, static_cast<IPC4761_PRESET>( m_protectionFeatures->GetSelection() ) );
851 break;
852 }
853
854 default:
855 UNIMPLEMENTED_FOR( track->GetClass() );
856 break;
857 }
858 }
859
860 std::set<int> shortingNets;
861 int newNetCode = m_netSelector->GetSelectedNetcode();
862 std::set<PAD*> changingPads;
863
864 // Do NOT use the connectivity code here. It will propagate through zones, and we haven't
865 // refilled those yet so it's going to pick up a whole bunch of other nets any time the track
866 // width was increased.
867 auto collide =
869 {
870 for( PCB_LAYER_ID layer : LSET( a->GetLayerSet() & b->GetLayerSet() ) )
871 {
872 if( a->GetEffectiveShape( layer )->Collide( b->GetEffectiveShape( layer ).get() ) )
873 return true;
874 }
875
876 return false;
877 };
878
879 for( PCB_TRACK* track : connected_tracks )
880 {
881 for( PCB_TRACK* other : m_frame->GetBoard()->Tracks() )
882 {
883 if( other->GetNetCode() == track->GetNetCode() || other->GetNetCode() == newNetCode )
884 continue;
885
886 if( collide( track, other ) )
887 shortingNets.insert( other->GetNetCode() );
888 }
889
890 for( FOOTPRINT* footprint : m_frame->GetBoard()->Footprints() )
891 {
892 for( PAD* pad : footprint->Pads() )
893 {
894 if( pad->GetNetCode() == newNetCode )
895 continue;
896
897 if( collide( track, pad ) )
898 {
899 if( pad->GetNetCode() == track->GetNetCode() )
900 changingPads.insert( pad );
901 else
902 shortingNets.insert( pad->GetNetCode() );
903 }
904 }
905 }
906 }
907
908 if( shortingNets.size() && !confirmShortingNets( newNetCode, shortingNets ) )
909 {
910 commit.Revert();
911 return true;
912 }
913
914 if( !m_netSelector->IsIndeterminate() )
915 {
916 if( changingPads.empty() || confirmPadChange( changingPads ) )
917 {
918 for( PCB_TRACK* track : selected_tracks )
919 track->SetNetCode( newNetCode );
920
921 for( PAD* pad : changingPads )
922 {
923 commit.Modify( pad );
924 pad->SetNetCode( newNetCode );
925 }
926 }
927 }
928
929 commit.Push( _( "Edit Track/Via Properties" ) );
930 return true;
931}
932
933
934void DIALOG_TRACK_VIA_PROPERTIES::onNetSelector( wxCommandEvent& aEvent )
935{
936 m_viaNotFree->SetValue( false );
937}
938
939
941{
942 if( !m_tracks )
943 {
944 m_netSelectorLabel->Enable( !m_viaNotFree->GetValue() );
945 m_netSelector->Enable( !m_viaNotFree->GetValue() );
946 }
947}
948
949
950void DIALOG_TRACK_VIA_PROPERTIES::onWidthSelect( wxCommandEvent& aEvent )
951{
952 m_TrackWidthCtrl->ChangeValue( m_predefinedTrackWidthsCtrl->GetStringSelection() );
953 m_TrackWidthCtrl->SelectAll();
954}
955
956
957void DIALOG_TRACK_VIA_PROPERTIES::onWidthEdit( wxCommandEvent& aEvent )
958{
959 m_predefinedTrackWidthsCtrl->SetStringSelection( m_TrackWidthCtrl->GetValue() );
960}
961
962
963void DIALOG_TRACK_VIA_PROPERTIES::onViaSelect( wxCommandEvent& aEvent )
964{
965 VIA_DIMENSION* viaDimension = static_cast<VIA_DIMENSION*> ( aEvent.GetClientData() );
966
967 m_viaDiameter.ChangeValue( viaDimension->m_Diameter );
968 m_viaDrill.ChangeValue( viaDimension->m_Drill );
969}
970
971
973{
974 wxCHECK_MSG( m_viaStack, /* void */, "Expected valid via stack in onPadstackModeChanged" );
975
976 switch( m_cbPadstackMode->GetSelection() )
977 {
978 default:
979 case 0: m_viaStack->SetMode( PADSTACK::MODE::NORMAL ); break;
980 case 1: m_viaStack->SetMode( PADSTACK::MODE::FRONT_INNER_BACK ); break;
981 case 2: m_viaStack->SetMode( PADSTACK::MODE::CUSTOM ); break;
982 }
983
985}
986
987
989{
990 wxCHECK_MSG( m_viaStack, /* void */, "Expected valid via stack in onEditLayerChanged" );
991
992 // Save data from the previous layer
993 if( !m_viaDiameter.IsIndeterminate() )
994 {
995 int diameter = m_viaDiameter.GetValue();
996 m_viaStack->SetSize( { diameter, diameter }, m_editLayer );
997 }
998
999 switch( m_viaStack->Mode() )
1000 {
1001 default:
1004 break;
1005
1007 switch( m_cbEditLayer->GetSelection() )
1008 {
1009 default:
1010 case 0: m_editLayer = F_Cu; break;
1011 case 1: m_editLayer = PADSTACK::INNER_LAYERS; break;
1012 case 2: m_editLayer = B_Cu; break;
1013 }
1014 break;
1015
1017 {
1018 int layer = m_cbEditLayer->GetSelection();
1019
1020 if( layer < 0 )
1021 layer = 0;
1022
1023 if( m_editLayerCtrlMap.contains( layer ) )
1024 m_editLayer = m_editLayerCtrlMap.at( layer );
1025 else
1026 m_editLayer = F_Cu;
1027 }
1028 }
1029
1030 // Load controls with the current layer
1031 m_viaDiameter.SetValue( m_viaStack->Size( m_editLayer ).x );
1032}
1033
1034
1036{
1037 // NOTE: synchronize changes here with DIALOG_PAD_PROPERTIES::afterPadstackModeChanged
1038
1039 wxCHECK_MSG( m_viaStack, /* void */, "Expected valid via stack in afterPadstackModeChanged" );
1040 m_cbEditLayer->Clear();
1041
1042 BOARD* board = m_frame->GetBoard();
1043
1044 switch( m_viaStack->Mode() )
1045 {
1047 m_cbPadstackMode->SetSelection( 0 );
1048 m_cbEditLayer->Append( _( "All layers" ) );
1049 m_cbEditLayer->Disable();
1052 break;
1053
1055 {
1056 m_cbPadstackMode->SetSelection( 1 );
1057 m_cbEditLayer->Enable();
1058
1059 std::vector choices = {
1060 board->GetLayerName( F_Cu ),
1061 _( "Inner Layers" ),
1062 board->GetLayerName( B_Cu )
1063 };
1064
1065 m_cbEditLayer->Append( choices );
1066
1068 { 0, F_Cu },
1070 { 2, B_Cu }
1071 };
1072
1073 if( m_editLayer != F_Cu && m_editLayer != B_Cu )
1075
1076 break;
1077 }
1078
1080 {
1081 m_cbPadstackMode->SetSelection( 2 );
1082 m_cbEditLayer->Enable();
1083 LSET layers = LSET::AllCuMask() & board->GetEnabledLayers();
1084
1085 for( PCB_LAYER_ID layer : layers.UIOrder() )
1086 {
1087 int idx = m_cbEditLayer->Append( board->GetLayerName( layer ) );
1088 m_editLayerCtrlMap[idx] = layer;
1089 }
1090
1091 break;
1092 }
1093 }
1094
1095 for( const auto& [idx, layer] : m_editLayerCtrlMap )
1096 {
1097 if( layer == m_editLayer )
1098 {
1099 m_cbEditLayer->SetSelection( idx );
1100 break;
1101 }
1102 }
1103}
1104
1105
1107{
1108 int viaType = m_ViaTypeChoice->GetSelection();
1109
1110 if( viaType <= 0 )
1111 return m_frame->GetBoard()->GetCopperLayerCount() - 1;
1112
1113 int startLayer = m_ViaStartLayer->GetLayerSelection();
1114 int endLayer = m_ViaEndLayer->GetLayerSelection();
1115
1116 if( startLayer < 0 || endLayer < 0 )
1117 return m_frame->GetBoard()->GetCopperLayerCount() - 1;
1118 else
1119 return m_frame->GetBoard()->LayerDepth( ToLAYER_ID( startLayer ), ToLAYER_ID( endLayer ) );
1120}
1121
1122
1123void DIALOG_TRACK_VIA_PROPERTIES::onViaEdit( wxCommandEvent& aEvent )
1124{
1125 m_predefinedViaSizesCtrl->SetSelection( wxNOT_FOUND );
1126
1127 if( m_vias )
1128 {
1129 if( m_ViaTypeChoice->GetSelection() != 0 ) // check if selected type isn't through.
1130 {
1131 m_ViaStartLayer->Enable();
1132 m_ViaEndLayer->Enable();
1133 }
1134 else
1135 {
1136 m_ViaStartLayer->SetLayerSelection( F_Cu );
1137 m_ViaEndLayer->SetLayerSelection( B_Cu );
1138
1139 m_ViaStartLayer->Enable( false );
1140 m_ViaEndLayer->Enable( false );
1141 }
1142
1143 m_annularRingsLabel->Show( getLayerDepth() > 1 );
1144 m_annularRingsCtrl->Show( getLayerDepth() > 1 );
1145 m_annularRingsCtrl->Enable( true );
1146 }
1147}
1148
1149
1150void DIALOG_TRACK_VIA_PROPERTIES::onTrackEdit( wxCommandEvent& aEvent )
1151{
1152 bool externalCuLayer = m_TrackLayerCtrl->GetLayerSelection() == F_Cu
1153 || m_TrackLayerCtrl->GetLayerSelection() == B_Cu;
1154
1155 m_techLayersLabel->Enable( externalCuLayer );
1156 m_trackHasSolderMask->Enable( externalCuLayer );
1157
1158 bool showMaskMargin = externalCuLayer && m_trackHasSolderMask->GetValue();
1159
1160 m_trackMaskMarginCtrl->Enable( showMaskMargin );
1161 m_trackMaskMarginLabel->Enable( showMaskMargin );
1162 m_trackMaskMarginUnit->Enable( showMaskMargin );
1163}
1164
1165
1167{
1168 event.Enable( !m_frame->GetBoard()->LegacyTeardrops() );
1169}
1170
const char * name
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()
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition board_item.h:232
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:252
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:692
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition board.cpp:924
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 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:98
const wxString & GetReference() const
Definition footprint.h:661
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
LSEQ UIOrder() const
Return the copper, technical and user layers in the order shown in layer widget.
Definition lset.cpp:726
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition lset.cpp:610
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:591
A PADSTACK defines the characteristics of a single or multi-layer pad, in the IPC sense of the word.
Definition padstack.h:125
@ NORMAL
Shape is the same on all layers.
Definition padstack.h:139
@ CUSTOM
Shapes can be defined on arbitrary layers.
Definition padstack.h:141
@ FRONT_INNER_BACK
Up to three shapes can be defined (F_Cu, inner copper layers, B_Cu)
Definition padstack.h:140
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition padstack.h:145
static constexpr PCB_LAYER_ID INNER_LAYERS
! The layer identifier to use for "inner layers" on top/inner/bottom padstacks
Definition padstack.h:148
Definition pad.h:54
const wxString & GetNumber() const
Definition pad.h:136
Common, abstract interface for edit frames.
bool HasSolderMask() const
Definition pcb_track.h:178
int GetStartY() const
Definition pcb_track.h:160
int GetEndX() const
Definition pcb_track.h:165
std::optional< int > GetLocalSolderMaskMargin() const
Definition pcb_track.h:181
int GetEndY() const
Definition pcb_track.h:166
int GetStartX() const
Definition pcb_track.h:159
virtual int GetWidth() const
Definition pcb_track.h:148
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:733
PCB_LAYER_ID BottomLayer() const
VECTOR2I GetPosition() const override
Definition pcb_track.h:586
static std::optional< VIA_PARAMETER_ERROR > ValidateViaParameters(std::optional< int > aDiameter, std::optional< int > aDrill, std::optional< PCB_LAYER_ID > aStartLayer=std::nullopt, std::optional< PCB_LAYER_ID > aEndLayer=std::nullopt)
const PADSTACK & Padstack() const
Definition pcb_track.h:463
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:455
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:169
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:737
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)
#define GEOMETRY_MIN_SIZE
Definition pcb_track.h:114
VIATYPE
Definition pcb_track.h:67
@ THROUGH
Definition pcb_track.h:68
@ NOT_DEFINED
Definition pcb_track.h:73
@ MICROVIA
Definition pcb_track.h:71
bool collide(T aObject, U aAnotherObject, int aLayer, int aMinDistance)
Used by SHAPE_INDEX to implement Query().
Definition shape_index.h:97
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