KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_non_copper_zones_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) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2014 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright The 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_base.h>
27#include <confirm.h>
28#include <pcb_edit_frame.h>
29#include <pcbnew_settings.h>
30#include <zone_settings.h>
31#include <widgets/unit_binder.h>
32#include <wx/statbox.h>
33#include <wx/statline.h>
34#include <wx/radiobut.h>
35#include <zones.h>
36
38
39
41{
42public:
44 CONVERT_SETTINGS* aConvertSettings );
45
48
49private:
50 bool TransferDataToWindow() override;
51 bool TransferDataFromWindow() override;
52
53 void OnStyleSelection( wxCommandEvent& event ) override;
54 void OnLayerSelection( wxDataViewEvent& event ) override;
55 void OnUpdateUI( wxUpdateUIEvent& ) override;
56
57private:
60 ZONE_SETTINGS m_settings; // working copy of zone settings
68 wxStaticText* m_gapLabel;
69 wxTextCtrl* m_gapCtrl;
70 wxStaticText* m_gapUnits;
72
74 wxRadioButton* m_rbCenterline;
75 wxRadioButton* m_rbEnvelope;
77};
78
79
81 CONVERT_SETTINGS* aConvertSettings )
82{
83 DIALOG_NON_COPPER_ZONES_EDITOR dlg( aParent, aSettings, aConvertSettings );
84
85 // TODO: why does this require QuasiModal?
86 return dlg.ShowQuasiModal();
87}
88
89#define MIN_THICKNESS 10*pcbIUScale.IU_PER_MILS
90
92 ZONE_SETTINGS* aSettings,
93 CONVERT_SETTINGS* aConvertSettings ) :
101 m_cornerSmoothingType( ZONE_SETTINGS::SMOOTHING_UNDEFINED ),
103 m_convertSettings( aConvertSettings ),
104 m_rbCenterline( nullptr ),
105 m_rbEnvelope( nullptr ),
106 m_cbDeleteOriginals( nullptr )
107{
108 m_parent = aParent;
109
110 m_ptr = aSettings;
111 m_settings = *aSettings;
112
113 if( aConvertSettings )
114 {
115 wxStaticBox* bConvertBox = new wxStaticBox( this, wxID_ANY, _( "Conversion Settings" ) );
116 wxStaticBoxSizer* bConvertSizer = new wxStaticBoxSizer( bConvertBox, wxVERTICAL );
117
118 m_rbCenterline = new wxRadioButton( this, wxID_ANY, _( "Use centerlines" ) );
119 bConvertSizer->Add( m_rbCenterline, 0, wxLEFT|wxRIGHT, 5 );
120
121 bConvertSizer->AddSpacer( 2 );
122 m_rbEnvelope = new wxRadioButton( this, wxID_ANY, _( "Create bounding hull" ) );
123 bConvertSizer->Add( m_rbEnvelope, 0, wxLEFT|wxRIGHT, 5 );
124
125 m_gapLabel = new wxStaticText( this, wxID_ANY, _( "Gap:" ) );
126 m_gapCtrl = new wxTextCtrl( this, wxID_ANY );
127 m_gapUnits = new wxStaticText( this, wxID_ANY, _( "mm" ) );
129 m_gap->SetValue( m_convertSettings->m_Gap );
130
131 wxBoxSizer* hullParamsSizer = new wxBoxSizer( wxHORIZONTAL );
132 hullParamsSizer->Add( m_gapLabel, 0, wxALIGN_CENTRE_VERTICAL|wxRIGHT, 5 );
133 hullParamsSizer->Add( m_gapCtrl, 1, wxALIGN_CENTRE_VERTICAL|wxLEFT|wxRIGHT, 5 );
134 hullParamsSizer->Add( m_gapUnits, 0, wxALIGN_CENTRE_VERTICAL|wxLEFT, 5 );
135 bConvertSizer->AddSpacer( 2 );
136 bConvertSizer->Add( hullParamsSizer, 0, wxLEFT, 26 );
137
138 bConvertSizer->AddSpacer( 6 );
139 m_cbDeleteOriginals = new wxCheckBox( this, wxID_ANY,
140 _( "Delete source objects after conversion" ) );
141 bConvertSizer->Add( m_cbDeleteOriginals, 0, wxALL, 5 );
142
143 GetSizer()->Insert( 0, bConvertSizer, 0, wxALL|wxEXPAND, 10 );
144
145 wxStaticLine* line = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
146 wxLI_HORIZONTAL );
147 GetSizer()->Insert( 1, line, 0, wxLEFT|wxRIGHT|wxEXPAND, 10 );
148
149 SetTitle( _( "Convert to Non Copper Zone" ) );
150 }
151 else
152 {
153 m_gapLabel = nullptr;
154 m_gapCtrl = nullptr;
155 m_gapUnits = nullptr;
156 m_gap = nullptr;
157 }
158
160
161 m_settings.SetupLayersList( m_layers, m_parent, LSET::AllNonCuMask() );
162
164
166}
167
168
170{
171 if( m_cornerSmoothingType != m_cornerSmoothingChoice->GetSelection() )
172 {
174
176 m_cornerRadiusLabel->SetLabel( _( "Chamfer distance:" ) );
177 else
178 m_cornerRadiusLabel->SetLabel( _( "Fillet radius:" ) );
179 }
180
182
183 if( m_gap )
184 m_gap->Enable( m_rbEnvelope->GetValue() );
185}
186
187
189{
191 {
192 if( m_convertSettings->m_Strategy == BOUNDING_HULL )
193 m_rbEnvelope->SetValue( true );
194 else
195 m_rbCenterline->SetValue( true );
196
197 m_cbDeleteOriginals->SetValue( m_convertSettings->m_DeleteOriginals );
198
199 m_gap->Enable( m_rbEnvelope->GetValue() );
200 }
201
202 m_cornerSmoothingChoice->SetSelection( m_settings.GetCornerSmoothingType() );
203 m_cornerRadius.SetValue( m_settings.GetCornerRadius() );
204
205 m_minWidth.SetValue( m_settings.m_ZoneMinThickness );
206 m_cbLocked->SetValue( m_settings.m_Locked );
207
208 switch( m_settings.m_ZoneBorderDisplayStyle )
209 {
210 case ZONE_BORDER_DISPLAY_STYLE::NO_HATCH: m_OutlineDisplayCtrl->SetSelection( 0 ); break;
213 case ZONE_BORDER_DISPLAY_STYLE::INVISIBLE_BORDER: break; // Not used for standard zones
214 }
215
216 m_outlineHatchPitch.SetValue( m_settings.m_BorderHatchPitch );
217
219
220 switch( m_settings.m_FillMode )
221 {
222 case ZONE_FILL_MODE::HATCH_PATTERN: m_GridStyleCtrl->SetSelection( 1 ); break;
223 default: m_GridStyleCtrl->SetSelection( 0 ); break;
224 }
225
227 m_hatchRotation.SetAngleValue( m_settings.m_HatchOrientation );
228
229 // Gives a reasonable value to grid style parameters, if currently there are no defined
230 // parameters for grid pattern thickness and gap (if the value is 0)
231 // the grid pattern thickness default value is (arbitrary) m_ZoneMinThickness * 4
232 // or 1mm
233 // the grid pattern gap default value is (arbitrary) m_ZoneMinThickness * 6
234 // or 1.5 mm
235 int bestvalue = m_settings.m_HatchThickness;
236
237 if( bestvalue <= 0 ) // No defined value for m_hatchWidth
238 bestvalue = std::max( m_settings.m_ZoneMinThickness * 4, pcbIUScale.mmToIU( 1.0 ) );
239
240 m_hatchWidth.SetValue( std::max( bestvalue, m_settings.m_ZoneMinThickness ) );
241
242 bestvalue = m_settings.m_HatchGap;
243
244 if( bestvalue <= 0 ) // No defined value for m_hatchGap
245 bestvalue = std::max( m_settings.m_ZoneMinThickness * 6, pcbIUScale.mmToIU( 1.5 ) );
246
247 m_hatchGap.SetValue( std::max( bestvalue, m_settings.m_ZoneMinThickness ) );
248
249 m_spinCtrlSmoothLevel->SetValue( m_settings.m_HatchSmoothingLevel );
250 m_spinCtrlSmoothValue->SetValue( m_settings.m_HatchSmoothingValue );
251
252 // Enable/Disable some widgets
253 wxCommandEvent event;
254 OnStyleSelection( event );
255
256 return true;
257}
258
259
261{
262 bool enable = m_GridStyleCtrl->GetSelection() >= 1;
263 m_hatchRotation.Enable( enable );
264 m_hatchWidth.Enable( enable );
265 m_hatchGap.Enable( enable );
266 m_smoothLevelLabel->Enable( enable );
267 m_spinCtrlSmoothLevel->Enable( enable );
268 m_smoothValueLabel->Enable( enable );
269 m_spinCtrlSmoothValue->Enable( enable );
270}
271
272
274{
275 if( event.GetColumn() != 0 )
276 return;
277
278 int row = m_layers->ItemToRow( event.GetItem() );
279 bool val = m_layers->GetToggleValue( row, 0 );
280
281 wxVariant layerID;
282 m_layers->GetValue( layerID, row, 2 );
283 m_settings.m_Layers.set( ToLAYER_ID( layerID.GetInteger() ), val );
284}
285
286
288{
290 {
291 if( m_rbEnvelope->GetValue() )
292 m_convertSettings->m_Strategy = BOUNDING_HULL;
293 else
294 m_convertSettings->m_Strategy = CENTERLINE;
295
296 m_convertSettings->m_DeleteOriginals = m_cbDeleteOriginals->GetValue();
297 m_convertSettings->m_Gap = m_gap->GetIntValue();
298 }
299
300 m_settings.SetCornerSmoothingType( m_cornerSmoothingChoice->GetSelection() );
301
302 m_settings.SetCornerRadius( m_settings.GetCornerSmoothingType() == ZONE_SETTINGS::SMOOTHING_NONE
303 ? 0 : m_cornerRadius.GetValue() );
304
305 m_settings.m_ZoneMinThickness = m_minWidth.GetValue();
306
307 switch( m_OutlineDisplayCtrl->GetSelection() )
308 {
309 case 0: m_settings.m_ZoneBorderDisplayStyle = ZONE_BORDER_DISPLAY_STYLE::NO_HATCH; break;
310 case 1: m_settings.m_ZoneBorderDisplayStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE; break;
311 case 2: m_settings.m_ZoneBorderDisplayStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_FULL; break;
312 }
313
316 return false;
317
318 m_settings.m_BorderHatchPitch = m_outlineHatchPitch.GetValue();
319
320 if( m_GridStyleCtrl->GetSelection() > 0 )
322 else
324
325
326 if( m_settings.m_FillMode == ZONE_FILL_MODE::HATCH_PATTERN )
327 {
328 int minThickness = m_minWidth.GetValue();
329
330 if( !m_hatchWidth.Validate( minThickness, INT_MAX ) )
331 return false;
332
333 if( !m_hatchGap.Validate( minThickness, INT_MAX ) )
334 return false;
335 }
336
337
338 m_settings.m_HatchOrientation = m_hatchRotation.GetAngleValue();
339 m_settings.m_HatchThickness = m_hatchWidth.GetValue();
340 m_settings.m_HatchGap = m_hatchGap.GetValue();
341 m_settings.m_HatchSmoothingLevel = m_spinCtrlSmoothLevel->GetValue();
342 m_settings.m_HatchSmoothingValue = m_spinCtrlSmoothValue->GetValue();
343
344 m_settings.m_Locked = m_cbLocked->GetValue();
345
346 // Get the layer selection for this zone
347 int layer = -1;
348 for( int ii = 0; ii < m_layers->GetItemCount(); ++ii )
349 {
350 if( m_layers->GetToggleValue( (unsigned) ii, 0 ) )
351 {
352 layer = ii;
353 break;
354 }
355 }
356
357 if( layer < 0 )
358 {
359 DisplayError( this, _( "No layer selected." ) );
360 return false;
361 }
362
363 *m_ptr = m_settings;
364 return true;
365}
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:112
DIALOG_NONCOPPER_ZONES_PROPERTIES_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Non Copper Zone Properties"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxFULL_REPAINT_ON_RESIZE|wxBORDER_SUNKEN)
DIALOG_NON_COPPER_ZONES_EDITOR(PCB_BASE_FRAME *aParent, ZONE_SETTINGS *aSettings, CONVERT_SETTINGS *aConvertSettings)
void OnStyleSelection(wxCommandEvent &event) override
void OnLayerSelection(wxDataViewEvent &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:82
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...
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition lset.cpp:610
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
ZONE_SETTINGS handles zones parameters.
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.
int InvokeNonCopperZonesEditor(PCB_BASE_FRAME *aParent, ZONE_SETTINGS *aSettings, CONVERT_SETTINGS *aConvertSettings)
Function InvokeNonCopperZonesEditor invokes up a modal dialog window for non-copper zone editing.
#define _(s)
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition lset.cpp:737
KICOMMON_API wxFont GetStatusFont(wxWindow *aWindow)
@ CENTERLINE
@ BOUNDING_HULL
Class ZONE_SETTINGS used to handle zones parameters in dialogs.
#define ZONE_BORDER_HATCH_MINDIST_MM
Definition zones.h:40
#define ZONE_BORDER_HATCH_MAXDIST_MM
Definition zones.h:41