KiCad PCB EDA Suite
dialog_copper_zones.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) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
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 <kiface_i.h>
27 #include <confirm.h>
28 #include <pcb_edit_frame.h>
29 #include <pcbnew_settings.h>
30 #include <zones.h>
31 #include <bitmaps.h>
32 #include <widgets/unit_binder.h>
33 #include <zone.h>
34 #include <board.h>
35 #include <trigo.h>
36 
38 
39 
41 {
42 public:
43  DIALOG_COPPER_ZONE( PCB_BASE_FRAME* aParent, ZONE_SETTINGS* aSettings );
44 
45 private:
47 
48  bool m_settingsExported; // settings will be written to all other zones
49 
52 
55  static wxString m_netNameShowFilter; // the filter to show nets (default * "*"). Static
56  // to keep this pattern for an entire Pcbnew session
58 
64 
69 
70  bool TransferDataToWindow() override;
71  bool TransferDataFromWindow() override;
72 
78  bool AcceptOptions( bool aUseExportableSetupOnly = false );
79 
80  void OnStyleSelection( wxCommandEvent& event ) override;
81  void OnLayerSelection( wxDataViewEvent& event ) override;
82  void OnNetSortingOptionSelected( wxCommandEvent& event ) override;
83  void ExportSetupToOtherCopperZones( wxCommandEvent& event ) override;
84  void OnRunFiltersButtonClick( wxCommandEvent& event ) override;
85  void OnUpdateUI( wxUpdateUIEvent& ) override;
86  void OnButtonCancelClick( wxCommandEvent& event ) override;
87  void OnClose( wxCloseEvent& event ) override;
88 
90 };
91 
92 
93 // Initialize static member variables
94 wxString DIALOG_COPPER_ZONE::m_netNameShowFilter( wxT( "*" ) );
95 
96 
98 {
99  DIALOG_COPPER_ZONE dlg( aCaller, aSettings );
100 
101  return dlg.ShowModal();
102 }
103 
104 #define MIN_THICKNESS ZONE_THICKNESS_MIN_VALUE_MIL*IU_PER_MILS
105 
107  DIALOG_COPPER_ZONE_BASE( aParent ),
108  m_cornerSmoothingType( ZONE_SETTINGS::SMOOTHING_UNDEFINED ),
109  m_cornerRadius( aParent, m_cornerRadiusLabel, m_cornerRadiusCtrl, m_cornerRadiusUnits, true ),
110  m_clearance( aParent, m_clearanceLabel, m_clearanceCtrl, m_clearanceUnits, true ),
111  m_minWidth( aParent, m_minWidthLabel, m_minWidthCtrl, m_minWidthUnits, true ),
112  m_antipadClearance( aParent, m_antipadLabel, m_antipadCtrl, m_antipadUnits, true ),
113  m_spokeWidth( aParent, m_spokeWidthLabel, m_spokeWidthCtrl, m_spokeWidthUnits, true ),
114  m_gridStyleRotation( aParent, m_staticTextGrindOrient, m_tcGridStyleOrientation,
115  m_staticTextRotUnits, false ),
116  m_gridStyleThickness( aParent, m_staticTextStyleThickness,
117  m_tcGridStyleThickness, m_GridStyleThicknessUnits, false ),
118  m_gridStyleGap( aParent, m_staticTextGridGap, m_tcGridStyleGap, m_GridStyleGapUnits, false ),
119  m_islandThreshold( aParent, m_islandThresholdLabel,
120  m_tcIslandThreshold, m_islandThresholdUnits, false )
121 {
122  m_Parent = aParent;
124 
125  m_ptr = aSettings;
126  m_settings = *aSettings;
128 
129  m_settingsExported = false;
130 
131  m_NetFiltering = false;
132  m_NetSortingByPadCount = true; // false = alphabetic sort, true = pad count sort
133 
134  m_sdbSizerOK->SetDefault();
135 
136  m_cbRemoveIslands->Bind( wxEVT_CHOICE,
137  [&]( wxCommandEvent& )
138  {
139  // Area mode is index 2
140  bool val = m_cbRemoveIslands->GetSelection() == 2;
141 
142  m_tcIslandThreshold->Enable( val );
143  m_islandThresholdLabel->Enable( val );
144  m_islandThresholdUnits->Enable( val );
145  } );
146 
148 }
149 
150 
152 {
157 
159  {
160  case ZONE_BORDER_DISPLAY_STYLE::NO_HATCH: m_OutlineDisplayCtrl->SetSelection( 0 ); break;
161  case ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE: m_OutlineDisplayCtrl->SetSelection( 1 ); break;
162  case ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_FULL: m_OutlineDisplayCtrl->SetSelection( 2 ); break;
163  }
164 
167 
168  switch( m_settings.GetPadConnection() )
169  {
170  default:
171  case ZONE_CONNECTION::THERMAL: m_PadInZoneOpt->SetSelection( 1 ); break;
172  case ZONE_CONNECTION::THT_THERMAL: m_PadInZoneOpt->SetSelection( 2 ); break;
173  case ZONE_CONNECTION::NONE: m_PadInZoneOpt->SetSelection( 3 ); break;
174  case ZONE_CONNECTION::FULL: m_PadInZoneOpt->SetSelection( 0 ); break;
175  }
176 
177  // Do not enable/disable antipad clearance and spoke width. They might be needed if
178  // a footprint or pad overrides the zone to specify a thermal connection.
181 
183  m_islandThreshold.SetDoubleValue( static_cast<double>( m_settings.GetMinIslandArea() ) );
184 
185  m_cbRemoveIslands->SetSelection( static_cast<int>( m_settings.GetIslandRemovalMode() ) );
186 
188 
189  m_tcIslandThreshold->Enable( val );
190  m_islandThresholdLabel->Enable( val );
191  m_islandThresholdUnits->Enable( val );
192 
193  wxString netNameDoNotShowFilter = wxT( "Net-*" );
194  m_NetFiltering = false;
195  m_NetSortingByPadCount = true;
196 
197  auto cfg = m_Parent->GetPcbNewSettings();
198 
199  int opt = cfg->m_Zones.net_sort_mode;
200  m_NetFiltering = opt >= 2;
201  m_NetSortingByPadCount = opt % 2;
202 
203  netNameDoNotShowFilter = cfg->m_Zones.net_filter;
204 
206  m_DoNotShowNetNameFilter->SetValue( netNameDoNotShowFilter );
207  m_showAllNetsOpt->SetValue( !m_NetFiltering );
209 
210  // Build list of nets:
212 
214 
215  switch( m_settings.m_FillMode )
216  {
218  m_GridStyleCtrl->SetSelection( 1 ); break;
219  default:
220  m_GridStyleCtrl->SetSelection( 0 ); break;
221  }
222 
224  m_gridStyleRotation.SetValue( m_settings.m_HatchOrientation * 10 ); // IU is decidegree
225 
226  // Gives a reasonable value to grid style parameters, if currently there are no defined
227  // parameters for grid pattern thickness and gap (if the value is 0)
228  // the grid pattern thickness default value is (arbitrary) m_ZoneMinThickness * 4
229  // or 1mm
230  // the grid pattern gap default value is (arbitrary) m_ZoneMinThickness * 6
231  // or 1.5 mm
232  int bestvalue = m_settings.m_HatchThickness;
233 
234  if( bestvalue <= 0 ) // No defined value for m_HatchThickness
235  bestvalue = std::max( m_settings.m_ZoneMinThickness * 4, Millimeter2iu( 1.0 ) );
236 
238 
239  bestvalue = m_settings.m_HatchGap;
240 
241  if( bestvalue <= 0 ) // No defined value for m_HatchGap
242  bestvalue = std::max( m_settings.m_ZoneMinThickness * 6, Millimeter2iu( 1.5 ) );
243 
244  m_gridStyleGap.SetValue( std::max( bestvalue, m_settings.m_ZoneMinThickness ) );
245 
248 
249  m_tcZoneName->SetValue( m_settings.m_Name );
250 
251  // Enable/Disable some widgets
252  wxCommandEvent event;
253  OnStyleSelection( event );
254 
255  Fit();
256 
257  return true;
258 }
259 
260 
261 void DIALOG_COPPER_ZONE::OnUpdateUI( wxUpdateUIEvent& )
262 {
263  if( m_ListNetNameSelection->GetSelection() < 0 )
264  m_ListNetNameSelection->SetSelection( 0 );
265 
266  bool noNetSelected = m_ListNetNameSelection->GetSelection() == 0;
267  bool enableSize = !noNetSelected && ( m_cbRemoveIslands->GetSelection() == 2 );
268 
269  m_bNoNetWarning->Show( noNetSelected );
270 
271  // Zones with no net never have islands removed
272  m_cbRemoveIslands->Enable( !noNetSelected );
273  m_islandThresholdLabel->Enable( enableSize );
274  m_islandThresholdUnits->Enable( enableSize );
275  m_tcIslandThreshold->Enable( enableSize );
276 
277  if( m_cornerSmoothingType != m_cornerSmoothingChoice->GetSelection() )
278  {
280 
282  m_cornerRadiusLabel->SetLabel( _( "Chamfer distance:" ) );
283  else
284  m_cornerRadiusLabel->SetLabel( _( "Fillet radius:" ) );
285  }
286 
288 }
289 
290 
291 void DIALOG_COPPER_ZONE::OnButtonCancelClick( wxCommandEvent& event )
292 {
293  // After an "Export Settings to Other Zones" cancel and close must return
294  // ZONE_EXPORT_VALUES instead of wxID_CANCEL.
295  Close( true );
296 }
297 
298 
300 {
302 
303  if( m_GridStyleCtrl->GetSelection() > 0 )
305  else
307 
308  if( !AcceptOptions() )
309  return false;
310 
311  m_settings.m_HatchOrientation = m_gridStyleRotation.GetValue() / 10.0; // value is returned in deci-degree
316 
317  *m_ptr = m_settings;
318  return true;
319 }
320 
321 
322 void DIALOG_COPPER_ZONE::OnClose( wxCloseEvent& event )
323 {
324  EndModal( m_settingsExported ? ZONE_EXPORT_VALUES : wxID_CANCEL );
325 }
326 
327 
328 bool DIALOG_COPPER_ZONE::AcceptOptions( bool aUseExportableSetupOnly )
329 {
330  if( !m_clearance.Validate( 0, Mils2iu( ZONE_CLEARANCE_MAX_VALUE_MIL ) ) )
331  return false;
332 
333  if( !m_minWidth.Validate( Mils2iu( ZONE_THICKNESS_MIN_VALUE_MIL ), INT_MAX ) )
334  return false;
335 
336  if( !m_cornerRadius.Validate( 0, INT_MAX ) )
337  return false;
338 
339  if( !m_spokeWidth.Validate( 0, INT_MAX ) )
340  return false;
341 
343 
345  {
346  int minThickness = m_minWidth.GetValue();
347 
348  if( !m_gridStyleThickness.Validate( minThickness, INT_MAX ) )
349  return false;
350 
351  if( !m_gridStyleGap.Validate( minThickness, INT_MAX ) )
352  return false;
353  }
354 
355  switch( m_PadInZoneOpt->GetSelection() )
356  {
357  case 3:
359  break;
360  case 2:
362  break;
363  case 1:
365  break;
366  case 0:
368  break;
369  }
370 
371  switch( m_OutlineDisplayCtrl->GetSelection() )
372  {
376  }
377 
378  auto cfg = m_Parent->GetPcbNewSettings();
379 
380  cfg->m_Zones.hatching_style = static_cast<int>( m_settings.m_ZoneBorderDisplayStyle );
381  cfg->m_Zones.net_filter = m_DoNotShowNetNameFilter->GetValue().ToStdString();
382 
384 
387 
389 
391  ? 0 : m_cornerRadius.GetValue() );
392 
394 
396 
399 
401  {
402  DisplayError( this, _( "Thermal spoke width cannot be smaller than the minimum width." ) );
403  return false;
404  }
405 
406  cfg->m_Zones.clearance = Iu2Mils( m_settings.m_ZoneClearance );
407  cfg->m_Zones.min_thickness = Iu2Mils( m_settings.m_ZoneMinThickness );
408  cfg->m_Zones.thermal_relief_gap = Iu2Mils( m_settings.m_ThermalReliefGap );
409  cfg->m_Zones.thermal_relief_copper_width = Iu2Mils( m_settings.m_ThermalReliefSpokeWidth );
410 
412  static_cast<ISLAND_REMOVAL_MODE>( m_cbRemoveIslands->GetSelection() ) );
414 
415  // If we use only exportable to others zones parameters, exit here:
416  if( aUseExportableSetupOnly )
417  return true;
418 
419  // Get the layer selection for this zone
420  int layers = 0;
421 
422  for( int ii = 0; ii < m_layers->GetItemCount(); ++ii )
423  {
424  if( m_layers->GetToggleValue( (unsigned) ii, 0 ) )
425  layers++;
426  }
427 
428  if( layers == 0 )
429  {
430  DisplayError( this, _( "No layer selected." ) );
431  return false;
432  }
433 
434  NETINFO_ITEM* net = nullptr;
435 
436  // Search net_code for this net, if a net was selected
437  if( m_ListNetNameSelection->GetSelection() > 0 )
438  {
439  wxString netname = m_ListNetNameSelection->GetStringSelection();
440  net = m_Parent->GetBoard()->FindNet( netname );
441  }
442 
443  m_settings.m_NetcodeSelection = net ? net->GetNet() : 0;
444 
445  m_settings.m_Name = m_tcZoneName->GetValue();
446 
447  return true;
448 }
449 
450 
451 void DIALOG_COPPER_ZONE::OnStyleSelection( wxCommandEvent& event )
452 {
453  bool enable = m_GridStyleCtrl->GetSelection() >= 1;
454  m_tcGridStyleThickness->Enable( enable );
455  m_tcGridStyleGap->Enable( enable );
456  m_tcGridStyleOrientation->Enable( enable );
457  m_spinCtrlSmoothLevel->Enable( enable );
458  m_spinCtrlSmoothValue->Enable( enable );
459 }
460 
461 
462 void DIALOG_COPPER_ZONE::OnLayerSelection( wxDataViewEvent& event )
463 {
464  if( event.GetColumn() != 0 )
465  return;
466 
467  int row = m_layers->ItemToRow( event.GetItem() );
468 
469  bool checked = m_layers->GetToggleValue( row, 0 );
470 
471  wxVariant layerID;
472  m_layers->GetValue( layerID, row, 2 );
473 
474  m_settings.m_Layers.set( ToLAYER_ID( layerID.GetInteger() ), checked );
475 }
476 
477 
479 {
480  m_NetFiltering = !m_showAllNetsOpt->GetValue();
483 
485 
486  auto cfg = m_Parent->GetPcbNewSettings();
487 
488  int configValue = m_NetFiltering ? 2 : 0;
489 
491  configValue += 1;
492 
493  cfg->m_Zones.net_sort_mode = configValue;
494  cfg->m_Zones.net_filter = m_DoNotShowNetNameFilter->GetValue().ToStdString();
495 }
496 
497 
499 {
500  if( !AcceptOptions( true ) )
501  return;
502 
503  // Export settings ( but layer and netcode ) to others copper zones
504  BOARD* pcb = m_Parent->GetBoard();
505 
506  for( ZONE* zone : pcb->Zones() )
507  {
508  // Cannot export settings from a copper zone
509  // to a zone keepout:
510  if( zone->GetIsRuleArea() )
511  continue;
512 
513  m_settings.ExportSetting( *zone, false ); // false = partial export
514  m_settingsExported = true;
515  m_Parent->OnModify();
516  }
517 }
518 
519 
520 void DIALOG_COPPER_ZONE::OnRunFiltersButtonClick( wxCommandEvent& event )
521 {
522  m_NetFiltering = true;
523  m_showAllNetsOpt->SetValue( false );
524 
526 }
527 
528 
530 {
531  wxArrayString listNetName;
532 
534 
535  if( m_NetFiltering )
536  {
537  wxString doNotShowFilter = m_DoNotShowNetNameFilter->GetValue().Lower();
538  wxString ShowFilter = m_ShowNetNameFilter->GetValue().Lower();
539 
540  for( unsigned ii = 0; ii < listNetName.GetCount(); ii++ )
541  {
542  if( listNetName[ii].Lower().Matches( doNotShowFilter ) )
543  {
544  listNetName.RemoveAt( ii );
545  ii--;
546  }
547  else if( !listNetName[ii].Lower().Matches( ShowFilter ) )
548  {
549  listNetName.RemoveAt( ii );
550  ii--;
551  }
552  }
553  }
554 
555  listNetName.Insert( wxT( "<no net>" ), 0 );
556 
557  // Ensure currently selected net for the zone is visible, regardless of filters
558  int selectedNetListNdx = 0;
559  int net_select = m_settings.m_NetcodeSelection;
560 
561  if( net_select > 0 )
562  {
563  NETINFO_ITEM* selectedNet = m_Parent->GetBoard()->FindNet( net_select );
564  if( selectedNet )
565  {
566  selectedNetListNdx = listNetName.Index( selectedNet->GetNetname() );
567 
568  if( wxNOT_FOUND == selectedNetListNdx )
569  {
570  // the currently selected net must *always* be visible.
571  // <no net> is the zero'th index, so pick next lowest
572  listNetName.Insert( selectedNet->GetNetname(), 1 );
573  selectedNetListNdx = 1;
574  }
575  }
576  }
577 
578  m_ListNetNameSelection->Clear();
579  m_ListNetNameSelection->InsertItems( listNetName, 0 );
580  m_ListNetNameSelection->SetSelection( selectedNetListNdx );
581  m_ListNetNameSelection->EnsureVisible( selectedNetListNdx );
582 }
583 
void OnRunFiltersButtonClick(wxCommandEvent &event) override
int m_HatchSmoothingLevel
Definition: zone_settings.h:87
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:240
void SetMinIslandArea(long long int aArea)
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1234
void SetIslandRemovalMode(ISLAND_REMOVAL_MODE aRemove)
ZONES & Zones()
Definition: board.h:289
void OnButtonCancelClick(wxCommandEvent &event) override
static wxString m_netNameShowFilter
This file is part of the common library.
double m_HatchSmoothingValue
Definition: zone_settings.h:89
long long int GetMinIslandArea() const
void SetCornerSmoothingType(int aType)
void OnLayerSelection(wxDataViewEvent &event) override
ZONE_BORDER_DISPLAY_STYLE m_ZoneBorderDisplayStyle
Option to show the zone area (outlines only, short hatches or full hatches.
int GetCornerSmoothingType() const
#define ZONE_CLEARANCE_MAX_VALUE_MIL
Definition: zones.h:34
void SetDataType(EDA_DATA_TYPE aDataType)
Used to override the datatype of the displayed property (default is DISTANCE)
Definition: unit_binder.cpp:86
wxString m_Name
Definition: zone_settings.h:95
#define ZONE_EXPORT_VALUES
Definition: zones.h:37
const ISLAND_REMOVAL_MODE GetIslandRemovalMode() const
PCBNEW_SETTINGS * GetPcbNewSettings()
Class DIALOG_COPPER_ZONE_BASE.
ZONE_CONNECTION GetPadConnection() const
void OnStyleSelection(wxCommandEvent &event) override
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:114
unsigned int GetCornerRadius() const
bool AcceptOptions(bool aUseExportableSetupOnly=false)
T NormalizeAngle180(T Angle)
Normalize angle to be in the -180.0 .. 180.0 range.
Definition: trigo.h:362
int m_NetcodeSelection
Definition: zone_settings.h:93
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Construct a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:82
pads are covered by copper
void SetPadConnection(ZONE_CONNECTION aPadConnection)
PCB_BASE_FRAME * m_Parent
void ExportSetting(ZONE &aTarget, bool aFullExport=true) const
Function ExportSetting copy settings to a given zone.
const BITMAP_OPAQUE dialog_warning_xpm[1]
wxSpinCtrlDouble * m_spinCtrlSmoothValue
bool TransferDataFromWindow() override
int SortedNetnamesList(wxArrayString &aNames, bool aSortbyPadsCount)
Definition: board.cpp:1305
const wxString & GetNetname() const
Function GetNetname.
Definition: netinfo.h:231
ZONE handles a list of polygons defining a copper zone.
Definition: zone.h:57
void ExportSetupToOtherCopperZones(wxCommandEvent &event) override
Thermal relief only for THT pads.
ZONE_SETTINGS handles zones parameters.
Definition: zone_settings.h:67
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
Use thermal relief for pads.
ZONE_FILL_MODE m_FillMode
Definition: zone_settings.h:81
virtual void SetUnits(EDA_UNITS aUnits)
Function SetUnits Normally not needed (as the UNIT_BINDER inherits from the parent frame),...
Definition: unit_binder.cpp:79
virtual void OnModify()
Function OnModify Must be called after a change in order to set the "modify" flag of the current scre...
NETINFO_ITEM handles the data for a net.
Definition: netinfo.h:65
#define ZONE_THICKNESS_MIN_VALUE_MIL
Definition: zones.h:32
virtual bool Validate(double aMin, double aMax, EDA_UNITS aUnits=EDA_UNITS::UNSCALED)
Function Validate Validates the control against the given range, informing the user of any errors fou...
long m_ThermalReliefSpokeWidth
int GetNet() const
Function GetNet.
Definition: netinfo.h:223
UNIT_BINDER m_gridStyleThickness
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:186
#define _(s)
Definition: 3d_actions.cpp:33
virtual void SetValue(int aValue)
Function SetValue Sets new value (in Internal Units) for the text field, taking care of units convers...
void SetCornerRadius(int aRadius)
DIALOG_COPPER_ZONE(PCB_BASE_FRAME *aParent, ZONE_SETTINGS *aSettings)
Pads are not covered.
void OnNetSortingOptionSelected(wxCommandEvent &event) override
virtual long long int GetValue()
Function GetValue Returns the current value in Internal Units.
int InvokeCopperZonesEditor(PCB_BASE_FRAME *aCaller, ZONE_SETTINGS *aSettings)
Function InvokeCopperZonesEditor invokes up a modal dialog window for copper zone editing.
void SetupLayersList(wxDataViewListCtrl *aList, PCB_BASE_FRAME *aFrame, bool aShowCopper, bool aFpEditorMode=false)
A helper routine for the various zone dialogs (copper, non-copper, keepout).
BOARD * GetBoard() const
virtual void SetDoubleValue(double aValue)
Function SetDoubleValue Sets new value (in Internal Units) for the text field, taking care of units c...
static constexpr int Millimeter2iu(double mm)
bool TransferDataToWindow() override
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:898
double m_HatchOrientation
Definition: zone_settings.h:86
PCB_BASE_FRAME basic PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
long m_ThermalReliefGap
void OnClose(wxCloseEvent &event) override
int m_ZoneMinThickness
Definition: zone_settings.h:83
void OnUpdateUI(wxUpdateUIEvent &) override