KiCad PCB EDA Suite
Loading...
Searching...
No Matches
panel_zone_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) 2023 Ethan Chien <[email protected]>
5 * Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
6 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
7 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
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
28
29#include <wx/radiobut.h>
30#include <kiface_base.h>
31#include <confirm.h>
32#include <pcb_edit_frame.h>
33#include <pcbnew_settings.h>
34#include <wx/string.h>
35#include <widgets/unit_binder.h>
36#include <pad.h>
37#include <trigo.h>
38
40#include <string_utils.h>
41
42wxDEFINE_EVENT( EVT_ZONE_NAME_UPDATE, wxCommandEvent );
43
45 ZONES_CONTAINER& aZoneContainer ) :
47 m_ZoneContainer( aZoneContainer ),
48 m_cornerSmoothingType( ZONE_SETTINGS::SMOOTHING_UNDEFINED ),
49 m_outlineHatchPitch( aPCB_FRAME, m_stBorderHatchPitchText, m_outlineHatchPitchCtrl,
50 m_outlineHatchUnits ),
51 m_cornerRadius( aPCB_FRAME, m_cornerRadiusLabel, m_cornerRadiusCtrl, m_cornerRadiusUnits ),
52 m_clearance( aPCB_FRAME, m_clearanceLabel, m_clearanceCtrl, m_clearanceUnits ),
53 m_minThickness( aPCB_FRAME, m_minWidthLabel, m_minWidthCtrl, m_minWidthUnits ),
54 m_antipadClearance( aPCB_FRAME, m_antipadLabel, m_antipadCtrl, m_antipadUnits ),
55 m_spokeWidth( aPCB_FRAME, m_spokeWidthLabel, m_spokeWidthCtrl, m_spokeWidthUnits ),
56 m_gridStyleRotation( aPCB_FRAME, m_staticTextGrindOrient, m_tcGridStyleOrientation,
57 m_staticTextRotUnits ),
58 m_gridStyleThickness( aPCB_FRAME, m_staticTextStyleThickness, m_tcGridStyleThickness,
59 m_GridStyleThicknessUnits ),
60 m_gridStyleGap( aPCB_FRAME, m_staticTextGridGap, m_tcGridStyleGap, m_GridStyleGapUnits ),
61 m_islandThreshold( aPCB_FRAME, m_islandThresholdLabel, m_tcIslandThreshold,
62 m_islandThresholdUnits ),
63 m_isTeardrop()
64{
65 m_cbRemoveIslands->Bind( wxEVT_CHOICE,
66 [&]( wxCommandEvent& )
67 {
68 // Area mode is index 2
69 m_islandThreshold.Enable( m_cbRemoveIslands->GetSelection() == 2 );
70 } );
71}
72
73
75{
76 if( m_settings )
78
80 m_isTeardrop = m_settings->m_TeardropType != TEARDROP_TYPE::TD_NONE;
81
83}
84
86{
88}
89
90
92{
93 if( !m_settings )
94 return false;
95
96 m_cbLocked->SetValue( m_settings->m_Locked );
97 m_cornerSmoothingChoice->SetSelection( m_settings->GetCornerSmoothingType() );
98 m_cornerRadius.SetValue( m_settings->GetCornerRadius() );
99
100 if( m_isTeardrop ) // outlines are never smoothed: they have already the right shape
101 {
102 m_cornerSmoothingChoice->SetSelection( 0 );
103 m_cornerSmoothingChoice->Enable( false );
105 m_cornerRadius.Enable( false );
106 }
107
108 switch( m_settings->m_ZoneBorderDisplayStyle )
109 {
110 case ZONE_BORDER_DISPLAY_STYLE::NO_HATCH: m_OutlineDisplayCtrl->SetSelection( 0 ); break;
111 case ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE: m_OutlineDisplayCtrl->SetSelection( 1 ); break;
112 case ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_FULL: m_OutlineDisplayCtrl->SetSelection( 2 ); break;
113 case ZONE_BORDER_DISPLAY_STYLE::INVISIBLE_BORDER: break;
114 }
115
116 m_outlineHatchPitch.SetValue( m_settings->m_BorderHatchPitch );
117
118 m_clearance.SetValue( m_settings->m_ZoneClearance );
119 m_minThickness.SetValue( m_settings->m_ZoneMinThickness );
120
121 switch( m_settings->GetPadConnection() )
122 {
123 default:
124 case ZONE_CONNECTION::THERMAL: m_PadInZoneOpt->SetSelection( 1 ); break;
125 case ZONE_CONNECTION::THT_THERMAL: m_PadInZoneOpt->SetSelection( 2 ); break;
126 case ZONE_CONNECTION::NONE: m_PadInZoneOpt->SetSelection( 3 ); break;
127 case ZONE_CONNECTION::FULL: m_PadInZoneOpt->SetSelection( 0 ); break;
128 }
129
130 if( m_isTeardrop )
131 {
132 m_PadInZoneOpt->SetSelection( 0 );
133 m_PadInZoneOpt->Enable( false );
134 }
135
136 // Do not enable/disable antipad clearance and spoke width. They might be needed if
137 // a footprint or pad overrides the zone to specify a thermal connection.
138 m_antipadClearance.SetValue( m_settings->m_ThermalReliefGap );
139 m_spokeWidth.SetValue( m_settings->m_ThermalReliefSpokeWidth );
140
141 m_islandThreshold.SetDataType( EDA_DATA_TYPE::AREA );
142 m_islandThreshold.SetDoubleValue( static_cast<double>( m_settings->GetMinIslandArea() ) );
143
144 m_cbRemoveIslands->SetSelection( static_cast<int>( m_settings->GetIslandRemovalMode() ) );
145
146 m_islandThreshold.Enable( m_settings->GetIslandRemovalMode() == ISLAND_REMOVAL_MODE::AREA );
147
148
149 if( !m_isTeardrop && m_settings->m_FillMode == ZONE_FILL_MODE::HATCH_PATTERN )
150 m_GridStyleCtrl->SetSelection( 1 );
151 else
152 m_GridStyleCtrl->SetSelection( 0 );
153
154 m_GridStyleCtrl->Enable( !m_isTeardrop );
155
156 m_gridStyleRotation.SetUnits( EDA_UNITS::DEGREES );
157 m_gridStyleRotation.SetAngleValue( m_settings->m_HatchOrientation );
158 m_gridStyleThickness.SetValue( m_settings->m_HatchThickness );
159 m_gridStyleGap.SetValue( m_settings->m_HatchGap );
160
161 m_spinCtrlSmoothLevel->SetValue( m_settings->m_HatchSmoothingLevel );
162 m_spinCtrlSmoothValue->SetValue( m_settings->m_HatchSmoothingValue );
163
164 m_tcZoneName->SetValue( m_settings->m_Name );
165
166
167 // Enable/Disable some widgets
168 wxCommandEvent aEvent;
169 OnStyleSelection( aEvent );
170 OnPadInZoneSelection( aEvent );
171 Fit();
172
173 return true;
174}
175
176
177void PANEL_ZONE_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& )
178{
179 if( m_cornerSmoothingType != m_cornerSmoothingChoice->GetSelection() )
180 {
182
184 m_cornerRadiusLabel->SetLabel( _( "Chamfer distance:" ) );
185 else
186 m_cornerRadiusLabel->SetLabel( _( "Fillet radius:" ) );
187 }
188
190}
191
192
194{
195 m_islandThreshold.Enable( m_cbRemoveIslands->GetSelection() == 2 );
196}
197
199{
200 int selection = m_PadInZoneOpt->GetSelection();
201 bool enabled = selection == 1 || selection == 2;
202 m_antipadClearance.Enable( enabled );
203 m_spokeWidth.Enable( enabled );
204}
205
206void PANEL_ZONE_PROPERTIES::OnZoneNameChanged( wxCommandEvent& aEvent )
207{
208 wxCommandEvent* evt = new wxCommandEvent( EVT_ZONE_NAME_UPDATE );
209 evt->SetString( m_tcZoneName->GetValue() );
210 wxQueueEvent( m_parent, evt );
211}
212
213
215{
216 if( !m_settings )
217 return false;
218
219 if( m_GridStyleCtrl->GetSelection() > 0 )
220 m_settings->m_FillMode = ZONE_FILL_MODE::HATCH_PATTERN;
221 else
222 m_settings->m_FillMode = ZONE_FILL_MODE::POLYGONS;
223
224 if( !AcceptOptions() )
225 return false;
226
227 m_settings->m_HatchOrientation = m_gridStyleRotation.GetAngleValue();
228 m_settings->m_HatchThickness = m_gridStyleThickness.GetIntValue();
229 m_settings->m_HatchGap = m_gridStyleGap.GetIntValue();
230 m_settings->m_HatchSmoothingLevel = m_spinCtrlSmoothLevel->GetValue();
231 m_settings->m_HatchSmoothingValue = m_spinCtrlSmoothValue->GetValue();
232
233 return true;
234}
235
236
237bool PANEL_ZONE_PROPERTIES::AcceptOptions( bool aUseExportableSetupOnly )
238{
240 return false;
241
243 return false;
244
245 if( !m_cornerRadius.Validate( 0, INT_MAX ) )
246 return false;
247
248 if( !m_spokeWidth.Validate( 0, INT_MAX ) )
249 return false;
250
252
253 if( m_settings->m_FillMode == ZONE_FILL_MODE::HATCH_PATTERN )
254 {
255 int minThickness = m_minThickness.GetIntValue();
256
257 if( !m_gridStyleThickness.Validate( minThickness, INT_MAX ) )
258 return false;
259
260 if( !m_gridStyleGap.Validate( minThickness, INT_MAX ) )
261 return false;
262 }
263
264 switch( m_PadInZoneOpt->GetSelection() )
265 {
266 case 3: m_settings->SetPadConnection( ZONE_CONNECTION::NONE ); break;
267 case 2: m_settings->SetPadConnection( ZONE_CONNECTION::THT_THERMAL ); break;
268 case 1: m_settings->SetPadConnection( ZONE_CONNECTION::THERMAL ); break;
269 case 0: m_settings->SetPadConnection( ZONE_CONNECTION::FULL ); break;
270 }
271
272 switch( m_OutlineDisplayCtrl->GetSelection() )
273 {
274 case 0: m_settings->m_ZoneBorderDisplayStyle = ZONE_BORDER_DISPLAY_STYLE::NO_HATCH; break;
275 case 1: m_settings->m_ZoneBorderDisplayStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE; break;
276 case 2: m_settings->m_ZoneBorderDisplayStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_FULL; break;
277 }
278
281 return false;
282
283 m_settings->m_BorderHatchPitch = m_outlineHatchPitch.GetIntValue();
284
285 m_settings->m_ZoneClearance = m_clearance.GetIntValue();
286 m_settings->m_ZoneMinThickness = m_minThickness.GetIntValue();
287
288 m_settings->SetCornerSmoothingType( m_cornerSmoothingChoice->GetSelection() );
289
290 if( m_settings->GetCornerSmoothingType() == ZONE_SETTINGS::SMOOTHING_NONE )
291 m_settings->SetCornerRadius( 0 );
292 else
293 m_settings->SetCornerRadius( m_cornerRadius.GetIntValue() );
294
295 m_settings->m_Locked = m_cbLocked->GetValue();
296
297 m_settings->m_ThermalReliefGap = m_antipadClearance.GetValue();
298 m_settings->m_ThermalReliefSpokeWidth = m_spokeWidth.GetValue();
299
300 if( m_settings->m_ThermalReliefSpokeWidth < m_settings->m_ZoneMinThickness )
301 {
302 DisplayErrorMessage( this, _( "Thermal spoke width cannot be smaller than the minimum width." ) );
303 return false;
304 }
305
306 m_settings->SetIslandRemovalMode( (ISLAND_REMOVAL_MODE) m_cbRemoveIslands->GetSelection() );
307 m_settings->SetMinIslandArea( m_islandThreshold.GetValue() );
308
309 // If we use only exportable to others zones parameters, exit here:
310 if( aUseExportableSetupOnly )
311 return true;
312
313 m_settings->m_Name = m_tcZoneName->GetValue();
314
315 return true;
316}
317
318
319void PANEL_ZONE_PROPERTIES::OnStyleSelection( wxCommandEvent& aEvent )
320{
321 bool enable = m_GridStyleCtrl->GetSelection() >= 1;
322 m_tcGridStyleThickness->Enable( enable );
323 m_tcGridStyleGap->Enable( enable );
324 m_tcGridStyleOrientation->Enable( enable );
325 m_spinCtrlSmoothLevel->Enable( enable );
326 m_spinCtrlSmoothValue->Enable( enable );
327}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:112
Class PANEL_ZONE_PROPERTIES_BASE.
PANEL_ZONE_PROPERTIES(wxWindow *aParent, PCB_BASE_FRAME *aPcb, ZONES_CONTAINER &aZoneContainer)
ZONES_CONTAINER & m_ZoneContainer
void ActivateSelectedZone(ZONE *new_zone) override
void OnPadInZoneSelection(wxCommandEvent &event) override
void OnUserConfirmChange() override
void OnZoneNameChanged(wxCommandEvent &event) override
void OnStyleSelection(wxCommandEvent &event) override
bool AcceptOptions(bool aUseExportableSetupOnly=false)
void OnUpdateUI(wxUpdateUIEvent &) override
void OnRemoveIslandsSelection(wxCommandEvent &event) override
std::shared_ptr< ZONE_SETTINGS > m_settings
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
int GetIntValue()
Definition: unit_binder.h:134
virtual long long int GetValue()
Return the current value in Internal Units.
void Enable(bool aEnable)
Enable/disable the label, widget and units label.
virtual void SetUnits(EDA_UNITS aUnits)
Normally not needed (as the UNIT_BINDER inherits from the parent frame), but can be used to set to DE...
virtual EDA_ANGLE GetAngleValue()
void SetDataType(EDA_DATA_TYPE aDataType)
Used to override the datatype of the displayed property (default is DISTANCE)
virtual void SetAngleValue(const EDA_ANGLE &aValue)
virtual void SetDoubleValue(double aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
virtual bool Validate(double aMin, double aMax, EDA_UNITS aUnits=EDA_UNITS::UNSCALED)
Validate the control against the given range, informing the user of any errors found.
virtual void SetValue(long long int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
std::shared_ptr< ZONE_SETTINGS > GetZoneSettings(ZONE *zone)
ZONE_SETTINGS handles zones parameters.
Definition: zone_settings.h:88
Handle a list of polygons defining a copper zone.
Definition: zone.h:74
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:194
This file is part of the common library.
#define _(s)
wxDEFINE_EVENT(EVT_ZONE_NAME_UPDATE, wxCommandEvent)
constexpr int mmToIU(double mm) const
Definition: base_units.h:92
T NormalizeAngle180(T Angle)
Normalize angle to be in the -180.0 .
Definition: trigo.h:196
ISLAND_REMOVAL_MODE
Whether or not to remove isolated islands from a zone.
Definition: zone_settings.h:68
#define ZONE_CLEARANCE_MAX_VALUE_MM
Definition: zones.h:38
#define ZONE_BORDER_HATCH_MINDIST_MM
Definition: zones.h:40
#define ZONE_THICKNESS_MIN_VALUE_MM
Definition: zones.h:36
#define ZONE_BORDER_HATCH_MAXDIST_MM
Definition: zones.h:41