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_PCB_Frame( aPCB_FRAME ),
49 m_cornerSmoothingType( ZONE_SETTINGS::SMOOTHING_UNDEFINED ),
50 m_outlineHatchPitch( aPCB_FRAME, m_stBorderHatchPitchText, m_outlineHatchPitchCtrl,
51 m_outlineHatchUnits ),
52 m_cornerRadius( aPCB_FRAME, m_cornerRadiusLabel, m_cornerRadiusCtrl, m_cornerRadiusUnits ),
53 m_clearance( aPCB_FRAME, m_clearanceLabel, m_clearanceCtrl, m_clearanceUnits ),
54 m_minThickness( aPCB_FRAME, m_minWidthLabel, m_minWidthCtrl, m_minWidthUnits ),
55 m_antipadClearance( aPCB_FRAME, m_antipadLabel, m_antipadCtrl, m_antipadUnits ),
56 m_spokeWidth( aPCB_FRAME, m_spokeWidthLabel, m_spokeWidthCtrl, m_spokeWidthUnits ),
57 m_gridStyleRotation( aPCB_FRAME, m_staticTextGrindOrient, m_tcGridStyleOrientation,
58 m_staticTextRotUnits ),
59 m_gridStyleThickness( aPCB_FRAME, m_staticTextStyleThickness, m_tcGridStyleThickness,
60 m_GridStyleThicknessUnits ),
61 m_gridStyleGap( aPCB_FRAME, m_staticTextGridGap, m_tcGridStyleGap, m_GridStyleGapUnits ),
62 m_islandThreshold( aPCB_FRAME, m_islandThresholdLabel, m_tcIslandThreshold,
63 m_islandThresholdUnits ),
64 m_isTeardrop()
65{
66 m_cbRemoveIslands->Bind( wxEVT_CHOICE,
67 [&]( wxCommandEvent& )
68 {
69 // Area mode is index 2
70 m_islandThreshold.Enable( m_cbRemoveIslands->GetSelection() == 2 );
71 } );
72}
73
74
76{
77 if( m_settings )
79
81 m_isTeardrop = m_settings->m_TeardropType != TEARDROP_TYPE::TD_NONE;
82
84}
85
87{
89}
90
91
93{
94 if( !m_settings )
95 return false;
96
97 m_cbLocked->SetValue( m_settings->m_Locked );
98 m_cornerSmoothingChoice->SetSelection( m_settings->GetCornerSmoothingType() );
99 m_cornerRadius.SetValue( m_settings->GetCornerRadius() );
100
101 if( m_isTeardrop ) // outlines are never smoothed: they have already the right shape
102 {
103 m_cornerSmoothingChoice->SetSelection( 0 );
104 m_cornerSmoothingChoice->Enable( false );
106 m_cornerRadius.Enable( false );
107 }
108
109 switch( m_settings->m_ZoneBorderDisplayStyle )
110 {
111 case ZONE_BORDER_DISPLAY_STYLE::NO_HATCH: m_OutlineDisplayCtrl->SetSelection( 0 ); break;
112 case ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE: m_OutlineDisplayCtrl->SetSelection( 1 ); break;
113 case ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_FULL: m_OutlineDisplayCtrl->SetSelection( 2 ); break;
114 case ZONE_BORDER_DISPLAY_STYLE::INVISIBLE_BORDER: break;
115 }
116
117 m_outlineHatchPitch.SetValue( m_settings->m_BorderHatchPitch );
118
119 m_clearance.SetValue( m_settings->m_ZoneClearance );
120 m_minThickness.SetValue( m_settings->m_ZoneMinThickness );
121
122 switch( m_settings->GetPadConnection() )
123 {
124 default:
125 case ZONE_CONNECTION::THERMAL: m_PadInZoneOpt->SetSelection( 1 ); break;
126 case ZONE_CONNECTION::THT_THERMAL: m_PadInZoneOpt->SetSelection( 2 ); break;
127 case ZONE_CONNECTION::NONE: m_PadInZoneOpt->SetSelection( 3 ); break;
128 case ZONE_CONNECTION::FULL: m_PadInZoneOpt->SetSelection( 0 ); break;
129 }
130
131 if( m_isTeardrop )
132 {
133 m_PadInZoneOpt->SetSelection( 0 );
134 m_PadInZoneOpt->Enable( false );
135 }
136
137 // Do not enable/disable antipad clearance and spoke width. They might be needed if
138 // a footprint or pad overrides the zone to specify a thermal connection.
139 m_antipadClearance.SetValue( m_settings->m_ThermalReliefGap );
140 m_spokeWidth.SetValue( m_settings->m_ThermalReliefSpokeWidth );
141
142 m_islandThreshold.SetDataType( EDA_DATA_TYPE::AREA );
143 m_islandThreshold.SetDoubleValue( static_cast<double>( m_settings->GetMinIslandArea() ) );
144
145 m_cbRemoveIslands->SetSelection( static_cast<int>( m_settings->GetIslandRemovalMode() ) );
146
147 m_islandThreshold.Enable( m_settings->GetIslandRemovalMode() == ISLAND_REMOVAL_MODE::AREA );
148
149
150 if( !m_isTeardrop && m_settings->m_FillMode == ZONE_FILL_MODE::HATCH_PATTERN )
151 m_GridStyleCtrl->SetSelection( 1 );
152 else
153 m_GridStyleCtrl->SetSelection( 0 );
154
155 m_GridStyleCtrl->Enable( !m_isTeardrop );
156
157 m_gridStyleRotation.SetUnits( EDA_UNITS::DEGREES );
158 m_gridStyleRotation.SetAngleValue( m_settings->m_HatchOrientation );
159 m_gridStyleThickness.SetValue( m_settings->m_HatchThickness );
160 m_gridStyleGap.SetValue( m_settings->m_HatchGap );
161
162 m_spinCtrlSmoothLevel->SetValue( m_settings->m_HatchSmoothingLevel );
163 m_spinCtrlSmoothValue->SetValue( m_settings->m_HatchSmoothingValue );
164
165 m_tcZoneName->SetValue( m_settings->m_Name );
166
167
168 // Enable/Disable some widgets
169 wxCommandEvent aEvent;
170 OnStyleSelection( aEvent );
171 OnPadInZoneSelection( aEvent );
172 Fit();
173
174 return true;
175}
176
177
178void PANEL_ZONE_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& )
179{
180 if( m_cornerSmoothingType != m_cornerSmoothingChoice->GetSelection() )
181 {
183
185 m_cornerRadiusLabel->SetLabel( _( "Chamfer distance:" ) );
186 else
187 m_cornerRadiusLabel->SetLabel( _( "Fillet radius:" ) );
188 }
189
191}
192
193
195{
196 m_islandThreshold.Enable( m_cbRemoveIslands->GetSelection() == 2 );
197}
198
200{
201 int selection = m_PadInZoneOpt->GetSelection();
202 bool enabled = selection == 1 || selection == 2;
203 m_antipadClearance.Enable( enabled );
204 m_spokeWidth.Enable( enabled );
205}
206
207void PANEL_ZONE_PROPERTIES::OnZoneNameChanged( wxCommandEvent& aEvent )
208{
209 wxCommandEvent* evt = new wxCommandEvent( EVT_ZONE_NAME_UPDATE );
210 evt->SetString( m_tcZoneName->GetValue() );
211 wxQueueEvent( m_parent, evt );
212}
213
214
216{
217 if( !m_settings )
218 return false;
219
220 if( m_GridStyleCtrl->GetSelection() > 0 )
221 m_settings->m_FillMode = ZONE_FILL_MODE::HATCH_PATTERN;
222 else
223 m_settings->m_FillMode = ZONE_FILL_MODE::POLYGONS;
224
225 if( !AcceptOptions() )
226 return false;
227
228 m_settings->m_HatchOrientation = m_gridStyleRotation.GetAngleValue();
229 m_settings->m_HatchThickness = m_gridStyleThickness.GetIntValue();
230 m_settings->m_HatchGap = m_gridStyleGap.GetIntValue();
231 m_settings->m_HatchSmoothingLevel = m_spinCtrlSmoothLevel->GetValue();
232 m_settings->m_HatchSmoothingValue = m_spinCtrlSmoothValue->GetValue();
233
234 return true;
235}
236
237
238bool PANEL_ZONE_PROPERTIES::AcceptOptions( bool aUseExportableSetupOnly )
239{
241 return false;
242
244 return false;
245
246 if( !m_cornerRadius.Validate( 0, INT_MAX ) )
247 return false;
248
249 if( !m_spokeWidth.Validate( 0, INT_MAX ) )
250 return false;
251
253
254 if( m_settings->m_FillMode == ZONE_FILL_MODE::HATCH_PATTERN )
255 {
256 int minThickness = m_minThickness.GetIntValue();
257
258 if( !m_gridStyleThickness.Validate( minThickness, INT_MAX ) )
259 return false;
260
261 if( !m_gridStyleGap.Validate( minThickness, INT_MAX ) )
262 return false;
263 }
264
265 switch( m_PadInZoneOpt->GetSelection() )
266 {
267 case 3: m_settings->SetPadConnection( ZONE_CONNECTION::NONE ); break;
268 case 2: m_settings->SetPadConnection( ZONE_CONNECTION::THT_THERMAL ); break;
269 case 1: m_settings->SetPadConnection( ZONE_CONNECTION::THERMAL ); break;
270 case 0: m_settings->SetPadConnection( ZONE_CONNECTION::FULL ); break;
271 }
272
273 switch( m_OutlineDisplayCtrl->GetSelection() )
274 {
275 case 0: m_settings->m_ZoneBorderDisplayStyle = ZONE_BORDER_DISPLAY_STYLE::NO_HATCH; break;
276 case 1: m_settings->m_ZoneBorderDisplayStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE; break;
277 case 2: m_settings->m_ZoneBorderDisplayStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_FULL; break;
278 }
279
282 return false;
283
284 m_settings->m_BorderHatchPitch = m_outlineHatchPitch.GetIntValue();
285
286 m_settings->m_ZoneClearance = m_clearance.GetIntValue();
287 m_settings->m_ZoneMinThickness = m_minThickness.GetIntValue();
288
289 m_settings->SetCornerSmoothingType( m_cornerSmoothingChoice->GetSelection() );
290
291 if( m_settings->GetCornerSmoothingType() == ZONE_SETTINGS::SMOOTHING_NONE )
292 m_settings->SetCornerRadius( 0 );
293 else
294 m_settings->SetCornerRadius( m_cornerRadius.GetIntValue() );
295
296 m_settings->m_Locked = m_cbLocked->GetValue();
297
298 m_settings->m_ThermalReliefGap = m_antipadClearance.GetValue();
299 m_settings->m_ThermalReliefSpokeWidth = m_spokeWidth.GetValue();
300
301 if( m_settings->m_ThermalReliefSpokeWidth < m_settings->m_ZoneMinThickness )
302 {
303 DisplayErrorMessage( this, _( "Thermal spoke width cannot be smaller than the minimum width." ) );
304 return false;
305 }
306
307 m_settings->SetIslandRemovalMode( (ISLAND_REMOVAL_MODE) m_cbRemoveIslands->GetSelection() );
308 m_settings->SetMinIslandArea( m_islandThreshold.GetValue() );
309
310 // If we use only exportable to others zones parameters, exit here:
311 if( aUseExportableSetupOnly )
312 return true;
313
314 m_settings->m_Name = m_tcZoneName->GetValue();
315
316 return true;
317}
318
319
320void PANEL_ZONE_PROPERTIES::OnStyleSelection( wxCommandEvent& aEvent )
321{
322 bool enable = m_GridStyleCtrl->GetSelection() >= 1;
323 m_tcGridStyleThickness->Enable( enable );
324 m_tcGridStyleGap->Enable( enable );
325 m_tcGridStyleOrientation->Enable( enable );
326 m_spinCtrlSmoothLevel->Enable( enable );
327 m_spinCtrlSmoothValue->Enable( enable );
328}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
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:129
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:78
Handle a list of polygons defining a copper zone.
Definition: zone.h:73
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:195
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:88
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:59
#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