KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_global_edit_teardrops.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <algorithm>
25
26#include <widgets/unit_binder.h>
27#include <pcb_edit_frame.h>
28#include <board.h>
30#include <pcb_track.h>
31#include <pcb_group.h>
32#include <footprint.h>
33#include <teardrop/teardrop.h>
34#include <zone_filler.h>
37#include <tool/tool_manager.h>
40
41// Globals to remember filters during a session
42static wxString g_netclassFilter;
43static wxString g_netFilter;
44
45
47{
48public:
51
52protected:
53 void onSpecifiedValuesUpdateUi( wxUpdateUIEvent& event ) override
54 {
55 event.Enable( m_specifiedValues->GetValue() );
56 }
57 void onFilterUpdateUi( wxUpdateUIEvent& event ) override
58 {
59 event.Enable( !m_trackToTrack->GetValue() );
60 }
61
62 // Track-to-track teardrops always follow the document-wide settings (there are no teardrop
63 // properties on individual track segments as they're too ephemeral). Therefore we disable
64 // Set-to-specified-values when track-to-track is selected.
65 void onTrackToTrack( wxCommandEvent& event ) override
66 {
67 if( event.IsChecked() && m_specifiedValues->GetValue() )
68 {
69 m_specifiedValues->SetValue( false );
70 m_addTeardrops->SetValue( true );
71 }
72 }
73
74 // These just improve usability so that you don't have to click twice to enable a filter.
75 void OnNetclassFilterSelect( wxCommandEvent& event ) override
76 {
77 m_netclassFilterOpt->SetValue( true );
78 }
79 void OnLayerFilterSelect( wxCommandEvent& event ) override
80 {
81 m_layerFilterOpt->SetValue( true );
82 }
83 void OnNetFilterSelect( wxCommandEvent& event )
84 {
85 m_netFilterOpt->SetValue( true );
86 }
87
88 // Remove "add" terminology when updating only existing teardrops.
89 void OnExistingFilterSelect( wxCommandEvent& event ) override
90 {
91 if( event.IsChecked() )
92 {
93 m_addTeardrops->SetLabel( _( "Set teardrops to default values for shape" ) );
94 m_specifiedValues->SetLabel( _( "Set teardrops to specified values:" ) );
95 }
96 else
97 {
98 m_addTeardrops->SetLabel( _( "Add teardrops with default values for shape" ) );
99 m_specifiedValues->SetLabel( _( "Add teardrops with specified values:" ) );
100 }
101 }
102
103 void setSpecifiedParams( TEARDROP_PARAMETERS* targetParams );
104 void visitItem( BOARD_COMMIT* aCommit, BOARD_CONNECTED_ITEM* aItem,bool aSelectAlways );
105 void processItem( BOARD_COMMIT* aCommit, BOARD_CONNECTED_ITEM* aItem );
106
107 bool TransferDataToWindow() override;
108 bool TransferDataFromWindow() override;
109
110
111 void onShowBoardSetup( wxHyperlinkEvent& event ) override
112 {
113 m_parent->ShowBoardSetupDialog( _( "Teardrops" ) );
114 }
115
116 void buildFilterLists();
117
118private:
122
128};
129
130
138{
139 m_parent = aParent;
140 m_brd = m_parent->GetBoard();
141
143
147
148 m_minTrackWidthHint->SetFont( KIUI::GetStatusFont( this ).Italic() );
149
151
152 SetupStandardButtons( { { wxID_OK, _( "Apply and Close" ) },
153 { wxID_CANCEL, _( "Close" ) } } );
154
155 m_netFilter->Connect( FILTERED_ITEM_SELECTED,
157 nullptr, this );
158
160}
161
162
164{
165 g_netclassFilter = m_netclassFilter->GetStringSelection();
166 g_netFilter = m_netFilter->GetSelectedNetname();
167
168 m_netFilter->Disconnect( FILTERED_ITEM_SELECTED,
170 nullptr, this );
171}
172
173
175{
176 // Populate the net filter list with net names
177 m_netFilter->SetNetInfo( &m_brd->GetNetInfo() );
178
179 if( !m_brd->GetHighLightNetCodes().empty() )
180 m_netFilter->SetSelectedNetcode( *m_brd->GetHighLightNetCodes().begin() );
181
182 // Populate the netclass filter list with netclass names
183 wxArrayString netclassNames;
184 std::shared_ptr<NET_SETTINGS>& settings = m_brd->GetDesignSettings().m_NetSettings;
185
186 netclassNames.push_back( settings->GetDefaultNetclass()->GetName() );
187
188 for( const auto& [name, netclass] : settings->GetNetclasses() )
189 netclassNames.push_back( name );
190
191 m_netclassFilter->Set( netclassNames );
192 m_netclassFilter->SetStringSelection( m_brd->GetDesignSettings().GetCurrentNetClassName() );
193
194 // Populate the layer filter list
195 m_layerFilter->SetBoardFrame( m_parent );
196 m_layerFilter->SetLayersHotkeys( false );
197 m_layerFilter->SetNotAllowedLayerSet( LSET::AllNonCuMask() );
198 m_layerFilter->Resync();
199 m_layerFilter->SetLayerSelection( m_parent->GetActiveLayer() );
200}
201
202
204{
205 BOARD_DESIGN_SETTINGS& bds = m_brd->GetDesignSettings();
206
211
212 m_netclassFilter->SetStringSelection( g_netclassFilter );
213 m_netFilter->SetSelectedNet( g_netFilter );
214
215 m_cbPreferZoneConnection->Set3StateValue( wxCHK_UNDETERMINED );
216 m_cbTeardropsUseNextTrack->Set3StateValue( wxCHK_UNDETERMINED );
222 m_curvedEdges->Set3StateValue( wxCHK_UNDETERMINED );
223
224 return true;
225}
226
227
229{
230 if( m_cbPreferZoneConnection->Get3StateValue() != wxCHK_UNDETERMINED )
231 targetParams->m_TdOnPadsInZones = !m_cbPreferZoneConnection->GetValue();
232
233 if( m_cbTeardropsUseNextTrack->Get3StateValue() != wxCHK_UNDETERMINED )
234 targetParams->m_AllowUseTwoTracks = m_cbTeardropsUseNextTrack->GetValue();
235
236 if( !m_teardropHDPercent.IsIndeterminate() )
237 targetParams->m_WidthtoSizeFilterRatio = m_teardropHDPercent.GetDoubleValue() / 100.0;
238
239 if( !m_teardropLenPercent.IsIndeterminate() )
240 targetParams->m_BestLengthRatio = m_teardropLenPercent.GetDoubleValue() / 100.0;
241
242 if( !m_teardropMaxLen.IsIndeterminate() )
243 targetParams->m_TdMaxLen = m_teardropMaxLen.GetIntValue();
244
245 if( !m_teardropHeightPercent.IsIndeterminate() )
246 targetParams->m_BestWidthRatio = m_teardropHeightPercent.GetDoubleValue() / 100.0;
247
248 if( !m_teardropMaxHeight.IsIndeterminate() )
249 targetParams->m_TdMaxWidth = m_teardropMaxHeight.GetIntValue();
250
251 if( m_curvedEdges->Get3StateValue() != wxCHK_UNDETERMINED )
252 targetParams->m_CurvedEdges = m_curvedEdges->GetValue();
253}
254
255
257{
258 BOARD_DESIGN_SETTINGS& brdSettings = m_brd->GetDesignSettings();
259 TEARDROP_PARAMETERS* targetParams = nullptr;
260
261 if( aItem->Type() == PCB_PAD_T )
262 targetParams = &static_cast<PAD*>( aItem )->GetTeardropParams();
263 else if( aItem->Type() == PCB_VIA_T )
264 targetParams = &static_cast<PCB_VIA*>( aItem )->GetTeardropParams();
265 else
266 return;
267
268 aCommit->Stage( aItem, CHT_MODIFY );
269
270 if( m_removeTeardrops->GetValue() || m_removeAllTeardrops->GetValue() )
271 {
272 targetParams->m_Enabled = false;
273 }
274 else if( m_addTeardrops->GetValue() )
275 {
276 // NOTE: This ignores possible padstack shape variation.
278 *targetParams = *brdSettings.GetTeadropParamsList()->GetParameters( TARGET_ROUND );
279 else
280 *targetParams = *brdSettings.GetTeadropParamsList()->GetParameters( TARGET_RECT );
281
282 targetParams->m_Enabled = true;
283 }
284 else if( m_specifiedValues->GetValue() )
285 {
286 setSpecifiedParams( targetParams );
287
288 if( !m_existingFilter->GetValue() )
289 targetParams->m_Enabled = true;
290 }
291}
292
293
295 bool aSelectAlways )
296{
297 if( m_selectedItemsFilter->GetValue() )
298 {
299 if( !aItem->IsSelected() )
300 {
301 EDA_GROUP* group = aItem->GetParentGroup();
302
303 while( group && !group->AsEdaItem()->IsSelected() )
304 group = group->AsEdaItem()->GetParentGroup();
305
306 if( !group )
307 return;
308 }
309 }
310
311 if( aSelectAlways )
312 {
313 processItem( aCommit, aItem );
314 return;
315 }
316
317
318 if( m_netFilterOpt->GetValue() && m_netFilter->GetSelectedNetcode() >= 0 )
319 {
320 if( aItem->GetNetCode() != m_netFilter->GetSelectedNetcode() )
321 return;
322 }
323
324 if( m_netclassFilterOpt->GetValue() && !m_netclassFilter->GetStringSelection().IsEmpty() )
325 {
326 wxString filterNetclass = m_netclassFilter->GetStringSelection();
327 NETCLASS* netclass = aItem->GetEffectiveNetClass();
328
329 if( !netclass->ContainsNetclassWithName( filterNetclass ) )
330 return;
331 }
332
333 if( m_layerFilterOpt->GetValue() && m_layerFilter->GetLayerSelection() != UNDEFINED_LAYER )
334 {
335 if( aItem->GetLayer() != m_layerFilter->GetLayerSelection() )
336 return;
337 }
338
339 if( m_roundPadsFilter->GetValue() )
340 {
341 // TODO(JE) padstacks -- teardrops needs to support per-layer pad handling
343 return;
344 }
345
346 if( m_existingFilter->GetValue() )
347 {
348 if( aItem->Type() == PCB_PAD_T )
349 {
350 if( !static_cast<PAD*>( aItem )->GetTeardropParams().m_Enabled )
351 return;
352 }
353 else if( aItem->Type() == PCB_VIA_T )
354 {
355 if( !static_cast<PCB_VIA*>( aItem )->GetTeardropParams().m_Enabled )
356 return;
357 }
358 }
359
360 processItem( aCommit, aItem );
361}
362
363
365{
366 m_brd->SetLegacyTeardrops( false );
367
368 BOARD_COMMIT commit( m_parent );
369 wxBusyCursor dummy;
370
371 // Save some dialog options
372 BOARD_DESIGN_SETTINGS& bds = m_brd->GetDesignSettings();
373
374 bds.m_TeardropParamsList.m_TargetVias = m_vias->GetValue();
379
380 bool remove_all = m_removeAllTeardrops->GetValue();
381
382 if( m_vias->GetValue() || remove_all )
383 {
384 for( PCB_TRACK* track : m_brd->Tracks() )
385 {
386 if ( track->Type() == PCB_VIA_T )
387 visitItem( &commit, track, remove_all );
388 }
389 }
390
391 for( FOOTPRINT* footprint : m_brd->Footprints() )
392 {
393 for( PAD* pad : footprint->Pads() )
394 {
395 if( remove_all )
396 {
397 visitItem( &commit, pad, true );
398 continue;
399 }
400
401 if( m_pthPads->GetValue() && pad->GetAttribute() == PAD_ATTRIB::PTH )
402 {
403 visitItem( &commit, pad, false );
404 }
405 else if( m_smdPads->GetValue() && ( pad->GetAttribute() == PAD_ATTRIB::SMD
406 || pad->GetAttribute() == PAD_ATTRIB::CONN ) )
407 {
408 visitItem( &commit, pad, false );
409 }
410 }
411 }
412
413 if( m_trackToTrack->GetValue() )
414 {
415 TEARDROP_PARAMETERS_LIST* paramsList = m_brd->GetDesignSettings().GetTeadropParamsList();
416 TEARDROP_PARAMETERS* targetParams = paramsList->GetParameters( TARGET_TRACK );
417 TEARDROP_MANAGER teardropManager( m_brd, m_parent->GetToolManager() );
418
419 teardropManager.DeleteTrackToTrackTeardrops( commit );
420 teardropManager.BuildTrackCaches();
421
422 if( m_removeTeardrops->GetValue() || m_removeAllTeardrops->GetValue() )
423 {
424 targetParams->m_Enabled = false; // JEY TODO: how does this get undone/redone?
425 }
426 else if( m_addTeardrops->GetValue() )
427 {
428 targetParams->m_Enabled = true; // JEY TODO: how does this get undone/redone?
429 teardropManager.AddTeardropsOnTracks( commit, nullptr, true );
430 }
431 }
432
433 // If there are no filters then a force-full-update is equivalent, and will be faster.
434 if( !m_netFilterOpt->GetValue()
435 && !m_netclassFilterOpt->GetValue()
436 && !m_layerFilterOpt->GetValue()
437 && !m_roundPadsFilter->GetValue()
438 && !m_existingFilter->GetValue()
439 && !m_selectedItemsFilter->GetValue() )
440 {
441 commit.Push( _( "Edit Teardrops" ), SKIP_TEARDROPS );
442
443 TEARDROP_MANAGER teardropMgr( m_brd, m_parent->GetToolManager() );
444 teardropMgr.UpdateTeardrops( commit, nullptr, nullptr, true /* forceFullUpdate */ );
445 commit.Push( _( "Edit Teardrops" ), SKIP_TEARDROPS | APPEND_UNDO );
446 }
447 else
448 {
449 commit.Push( _( "Edit Teardrops" ) );
450 }
451
452 // Showing the unfilled, fully cross-hatched teardrops seems to be working fairly well, and
453 // accurate fills can then be manually generated by doing a zone fill.
454 //
455 // But here's the old code which allowed for either "draft" fills or an automatic full zone
456 // fill in case we decide the current situation isn't good enough:
457#if 0
458 if( aFillAfter )
459 {
460 ZONE_FILLER filler( m_board, aCommit );
461
462 if( m_reporter )
463 filler.SetProgressReporter( m_reporter );
464
465 filler.Fill( m_board->Zones() );
466
467 if( aCommit )
468 aCommit->Push( _( "Edit Teardrops" ), APPEND_UNDO );
469 }
470 else
471 {
472 // Fill raw teardrop shapes. This is a rough calculation, just to show a filled
473 // shape on screen without the (potentially large) performance hit of a zone refill
474 int epsilon = pcbIUScale.mmToIU( 0.001 );
475 int allowed_error = pcbIUScale.mmToIU( 0.005 );
476
477 for( ZONE* zone: m_createdTdList )
478 {
479 int half_min_width = zone->GetMinThickness() / 2;
480 int numSegs = GetArcToSegmentCount( half_min_width, allowed_error, FULL_CIRCLE );
481 SHAPE_POLY_SET filledPolys = *zone->Outline();
482
483 filledPolys.Deflate( half_min_width - epsilon, numSegs );
484
485 // Re-inflate after pruning of areas that don't meet minimum-width criteria
486 if( half_min_width - epsilon > epsilon )
487 filledPolys.Inflate( half_min_width - epsilon, numSegs );
488
489 zone->SetFilledPolysList( zone->GetFirstLayer(), filledPolys );
490 }
491 }
492#endif
493
494 m_parent->Refresh();
495 return true;
496}
497
498
500{
502 DIALOG_GLOBAL_EDIT_TEARDROPS dlg( editFrame );
503
504 dlg.ShowQuasiModal(); // QuasiModal required for NET_SELECTOR
505 return 0;
506}
507
const char * name
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:112
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:110
#define SKIP_TEARDROPS
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
COMMIT & Stage(EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE) override
Add a change of the item aItem of type aChangeType to the change list.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
virtual NETCLASS * GetEffectiveNetClass() const
Return the NETCLASS for this item.
Container for design settings for a BOARD object.
TEARDROP_PARAMETERS_LIST * GetTeadropParamsList()
TEARDROP_PARAMETERS_LIST m_TeardropParamsList
The parameters of teardrops for the different teardrop targets (via/pad, track end).
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition board_item.h:232
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:317
DIALOG_GLOBAL_EDIT_TEARDROPS_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Set Teardrops"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
void processItem(BOARD_COMMIT *aCommit, BOARD_CONNECTED_ITEM *aItem)
void visitItem(BOARD_COMMIT *aCommit, BOARD_CONNECTED_ITEM *aItem, bool aSelectAlways)
void OnNetFilterSelect(wxCommandEvent &event)
void setSpecifiedParams(TEARDROP_PARAMETERS *targetParams)
void OnNetclassFilterSelect(wxCommandEvent &event) override
DIALOG_GLOBAL_EDIT_TEARDROPS(PCB_EDIT_FRAME *aParent)
void onTrackToTrack(wxCommandEvent &event) override
void onSpecifiedValuesUpdateUi(wxUpdateUIEvent &event) override
void OnExistingFilterSelect(wxCommandEvent &event) override
void onShowBoardSetup(wxHyperlinkEvent &event) override
void onFilterUpdateUi(wxUpdateUIEvent &event) override
void OnLayerFilterSelect(wxCommandEvent &event) override
void SetupStandardButtons(std::map< int, wxString > aLabels={})
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
A set of EDA_ITEMs (i.e., without duplicates).
Definition eda_group.h:46
virtual EDA_GROUP * GetParentGroup() const
Definition eda_item.h:116
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
bool IsSelected() const
Definition eda_item.h:127
int EditTeardrops(const TOOL_EVENT &aEvent)
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition lset.cpp:610
A collection of nets and the parameters used to route or test these nets.
Definition netclass.h:45
bool ContainsNetclassWithName(const wxString &netclass) const
Determines if the given netclass name is a constituent of this (maybe aggregate) netclass.
Definition netclass.cpp:278
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition padstack.h:145
Definition pad.h:54
The main frame for Pcbnew.
Represent a set of closed polygons.
void Inflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify=false)
Perform outline inflation/deflation.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
void Deflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError)
TEARDROP_MANAGER manage and build teardrop areas A teardrop area is a polygonal area (a copper ZONE) ...
Definition teardrop.h:95
static bool IsRound(BOARD_ITEM *aItem, PCB_LAYER_ID aLayer)
void UpdateTeardrops(BOARD_COMMIT &aCommit, const std::vector< BOARD_ITEM * > *dirtyPadsAndVias, const std::set< PCB_TRACK * > *dirtyTracks, bool aForceFullUpdate=false)
Update teardrops on a list of items.
Definition teardrop.cpp:218
void AddTeardropsOnTracks(BOARD_COMMIT &aCommit, const std::set< PCB_TRACK * > *aTracks, bool aForceFullUpdate=false)
Add teardrop on tracks of different sizes connected by their end.
Definition teardrop.cpp:409
void DeleteTrackToTrackTeardrops(BOARD_COMMIT &aCommit)
Definition teardrop.cpp:357
TEARDROP_PARAMETERS_LIST is a helper class to handle the list of TEARDROP_PARAMETERS needed to build ...
bool m_UseRoundShapesOnly
True to create teardrops for round shapes only.
bool m_TargetVias
True to create teardrops for vias.
bool m_TargetPTHPads
True to create teardrops for pads with holes.
bool m_TargetTrack2Track
True to create teardrops at the end of a track connected to the end of another track having a differe...
TEARDROP_PARAMETERS * GetParameters(TARGET_TD aTdType)
bool m_TargetSMDPads
True to create teardrops for pads SMD, edge connectors,.
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_TdOnPadsInZones
A filter to exclude pads inside zone fills.
bool m_Enabled
Flag to enable teardrops.
bool m_CurvedEdges
True if the teardrop should be curved.
T * getEditFrame() const
Return the application window object, casted to requested user type.
Definition tool_base.h:186
Generic, UI-independent tool event.
Definition tool_event.h:171
void SetProgressReporter(PROGRESS_REPORTER *aReporter)
bool Fill(const std::vector< ZONE * > &aZones, bool aCheck=false, wxWindow *aParent=nullptr)
Fills the given list of zones.
Handle a list of polygons defining a copper zone.
Definition zone.h:74
@ CHT_MODIFY
Definition commit.h:44
static wxString g_netclassFilter
static wxString g_netFilter
#define _(s)
static constexpr EDA_ANGLE FULL_CIRCLE
Definition eda_angle.h:409
int GetArcToSegmentCount(int aRadius, int aErrorMax, const EDA_ANGLE &aArcAngle)
@ UNDEFINED_LAYER
Definition layer_ids.h:61
KICOMMON_API wxFont GetStatusFont(wxWindow *aWindow)
@ SMD
Smd pad, appears on the solder paste layer (default)
Definition padstack.h:83
@ PTH
Plated through hole pad.
Definition padstack.h:82
@ CONN
Like smd, does not appear on the solder paste layer (default) Note: also has a special attribute in G...
Definition padstack.h:84
Class to handle a set of BOARD_ITEMs.
const double epsilon
#define APPEND_UNDO
Definition sch_commit.h:41
std::vector< FAB_LAYER_COLOR > dummy
@ TARGET_ROUND
@ TARGET_RECT
@ TARGET_TRACK
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition typeinfo.h:97
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition typeinfo.h:87
#define INDETERMINATE_ACTION
Definition ui_common.h:47