KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_rule_area_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) 2014 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, see <https://www.gnu.org/licenses/>.
20 */
21
22#include <advanced_config.h>
23#include <kiface_base.h>
24#include <confirm.h>
25#include <board.h>
27#include <eda_group.h>
28#include <footprint.h>
29#include <pcb_edit_frame.h>
30#include <pcbnew_settings.h>
31#include <zone_settings.h>
35#include <widgets/unit_binder.h>
36#include <wx/statbox.h>
37#include <wx/statline.h>
38#include <wx/radiobut.h>
39
40#define LAYER_LIST_COLUMN_CHECK 0
41#define LAYER_LIST_COLUMN_ICON 1
42#define LAYER_LIST_COLUMN_NAME 2
43#define LAYER_LIST_ROW_ALL_INNER_LAYERS 1
44
45
47{
48public:
50 CONVERT_SETTINGS* aConvertSettings, BOARD* aBoard );
52
53private:
54 bool TransferDataToWindow() override;
55 bool TransferDataFromWindow() override;
56
57 void OnLayerSelection( wxDataViewEvent& event ) override;
58 void OnSheetNameClicked( wxCommandEvent& event );
59 void OnComponentClassClicked( wxCommandEvent& event );
60 void OnGroupClicked( wxCommandEvent& event );
61
62private:
69 wxString m_originalName;
70
72 wxRadioButton* m_rbCenterline;
73 wxRadioButton* m_rbBoundingHull;
74 wxStaticText* m_gapLabel;
75 wxTextCtrl* m_gapCtrl;
76 wxStaticText* m_gapUnits;
79
80 // The name of a rule area source that is not now found on the board (e.g. after a netlist
81 // update). This is used to re-populate the zone settings if the selection is not changed.
86
89};
90
91
92int InvokeRuleAreaEditor( PCB_BASE_FRAME* aCaller, ZONE_SETTINGS* aZoneSettings, BOARD* aBoard,
93 CONVERT_SETTINGS* aConvertSettings )
94{
95 DIALOG_RULE_AREA_PROPERTIES dlg( aCaller, aZoneSettings, aConvertSettings, aBoard );
96
97 return dlg.ShowModal();
98}
99
100
102 ZONE_SETTINGS* aSettings,
103 CONVERT_SETTINGS* aConvertSettings,
104 BOARD* aBoard ) :
106 m_board( aBoard ),
108 m_convertSettings( aConvertSettings ),
109 m_rbCenterline( nullptr ),
110 m_rbBoundingHull( nullptr ),
111 m_gapLabel( nullptr ),
112 m_gapCtrl( nullptr ),
113 m_gapUnits( nullptr ),
114 m_gap( nullptr ),
115 m_cbDeleteOriginals( nullptr ),
119{
121 m_parent = aParent;
122
123 m_ptr = aSettings;
124 m_zonesettings = *aSettings;
125
127 m_areaPropertiesNb->AddPage( m_keepoutProperties, _( "Keepouts" ), true );
128
130 m_areaPropertiesNb->AddPage( m_placementProperties, _( "Placement" ) );
131
132 m_placementProperties->m_SheetRb->Connect(
133 wxEVT_CHECKBOX,
134 wxCommandEventHandler( DIALOG_RULE_AREA_PROPERTIES::OnSheetNameClicked ), nullptr,
135 this );
136 m_placementProperties->m_ComponentsRb->Connect(
137 wxEVT_CHECKBOX,
138 wxCommandEventHandler( DIALOG_RULE_AREA_PROPERTIES::OnComponentClassClicked ), nullptr,
139 this );
140 m_placementProperties->m_GroupRb->Connect(
141 wxEVT_CHECKBOX,
142 wxCommandEventHandler( DIALOG_RULE_AREA_PROPERTIES::OnGroupClicked ), nullptr,
143 this );
144
145 if( aConvertSettings )
146 {
147 wxStaticBox* bConvertBox = new wxStaticBox( this, wxID_ANY,
148 _( "Conversion Settings" ) );
149 wxStaticBoxSizer* bConvertSizer = new wxStaticBoxSizer( bConvertBox, wxVERTICAL );
150
151 m_rbCenterline = new wxRadioButton( this, wxID_ANY, _( "Use centerlines" ) );
152 bConvertSizer->Add( m_rbCenterline, 0, wxLEFT|wxRIGHT, 5 );
153
154 bConvertSizer->AddSpacer( 2 );
155 m_rbBoundingHull = new wxRadioButton( this, wxID_ANY, _( "Create bounding hull" ) );
156 bConvertSizer->Add( m_rbBoundingHull, 0, wxLEFT|wxRIGHT, 5 );
157
158 m_gapLabel = new wxStaticText( this, wxID_ANY, _( "Gap:" ) );
159 m_gapCtrl = new wxTextCtrl( this, wxID_ANY );
160 m_gapUnits = new wxStaticText( this, wxID_ANY, _( "mm" ) );
161 m_gap = new UNIT_BINDER( aParent, m_gapLabel, m_gapCtrl, m_gapUnits );
162
163 wxBoxSizer* hullParamsSizer = new wxBoxSizer( wxHORIZONTAL );
164 hullParamsSizer->Add( m_gapLabel, 0, wxALIGN_CENTRE_VERTICAL, 5 );
165 hullParamsSizer->Add( m_gapCtrl, 1, wxALIGN_CENTRE_VERTICAL|wxLEFT|wxRIGHT, 3 );
166 hullParamsSizer->Add( m_gapUnits, 0, wxALIGN_CENTRE_VERTICAL, 5 );
167
168 bConvertSizer->AddSpacer( 2 );
169 bConvertSizer->Add( hullParamsSizer, 0, wxLEFT, 26 );
170
171 bConvertSizer->AddSpacer( 6 );
172 m_cbDeleteOriginals = new wxCheckBox( this, wxID_ANY,
173 _( "Delete source objects after conversion" ) );
174 bConvertSizer->Add( m_cbDeleteOriginals, 0, wxALL, 5 );
175
176 GetSizer()->Insert( 0, bConvertSizer, 0, wxALL|wxEXPAND, 10 );
177
178 wxStaticLine* line = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
179 wxLI_HORIZONTAL );
180 GetSizer()->Insert( 1, line, 0, wxLEFT|wxRIGHT|wxEXPAND, 10 );
181
182 SetTitle( _( "Convert to Rule Area" ) );
183 }
184
185 BOARD* board = m_parent->GetBoard();
187
188 m_zonesettings.SetupLayersList( m_layers, m_parent, layers );
189
191
193}
194
195
197{
198 m_placementProperties->m_SheetRb->Disconnect(
199 wxEVT_CHECKBOX,
200 wxCommandEventHandler( DIALOG_RULE_AREA_PROPERTIES::OnSheetNameClicked ), nullptr,
201 this );
202 m_placementProperties->m_ComponentsRb->Disconnect(
203 wxEVT_CHECKBOX,
204 wxCommandEventHandler( DIALOG_RULE_AREA_PROPERTIES::OnComponentClassClicked ), nullptr,
205 this );
206 m_placementProperties->m_GroupRb->Disconnect(
207 wxEVT_CHECKBOX,
208 wxCommandEventHandler( DIALOG_RULE_AREA_PROPERTIES::OnGroupClicked ), nullptr,
209 this );
210}
211
212
217
218
223
224
229
230
232{
234 {
235 if( m_convertSettings->m_Strategy == BOUNDING_HULL )
236 m_rbBoundingHull->SetValue( true );
237 else
238 m_rbCenterline->SetValue( true );
239
240 m_cbDeleteOriginals->SetValue( m_convertSettings->m_DeleteOriginals );
241 }
242
243 // Init keepout parameters:
244 m_keepoutProperties->m_cbTracksCtrl->SetValue( m_zonesettings.GetDoNotAllowTracks() );
245 m_keepoutProperties->m_cbViasCtrl->SetValue( m_zonesettings.GetDoNotAllowVias() );
246 m_keepoutProperties->m_cbPadsCtrl->SetValue( m_zonesettings.GetDoNotAllowPads() );
247 m_keepoutProperties->m_cbFootprintsCtrl->SetValue( m_zonesettings.GetDoNotAllowFootprints() );
248 m_keepoutProperties->m_cbCopperPourCtrl->SetValue( m_zonesettings.GetDoNotAllowZoneFills() );
249
250 // Init placement parameters:
251 m_placementProperties->m_DisabledRb->SetValue( true );
252 m_placementProperties->m_SheetRb->SetValue( false );
253 m_placementProperties->m_sheetCombo->Clear();
254
255 m_placementProperties->m_ComponentsRb->SetValue( false );
256 m_placementProperties->m_componentClassCombo->Clear();
257
258 m_placementProperties->m_GroupRb->SetValue( false );
259 m_placementProperties->m_groupCombo->Clear();
260
261 wxString curSourceName = m_zonesettings.GetPlacementAreaSource();
262
263 // Load schematic sheet and component class lists
264 if( m_board )
265 {
266 // Fetch component classes
267 std::set<wxString> classNames;
268
269 for( const wxString& className : m_board->GetComponentClassManager().GetClassNames() )
270 classNames.insert( className );
271
272 for( const wxString& sourceName : classNames )
273 m_placementProperties->m_componentClassCombo->Append( sourceName );
274
275 if( !classNames.empty() )
276 m_placementProperties->m_componentClassCombo->Select( 0 );
277
278 // Fetch sheet names and groups
279 std::set<wxString> sheetNames;
280 std::set<wxString> groupNames;
281
282 for( FOOTPRINT* fp : m_board->Footprints() )
283 {
284 sheetNames.insert( fp->GetSheetname() );
285
286 for( EDA_GROUP* group = fp->GetParentGroup(); group; group = group->AsEdaItem()->GetParentGroup() )
287 {
288 if( !group->GetName().IsEmpty() )
289 groupNames.insert( group->GetName() );
290 }
291 }
292
293 for( const wxString& sourceName : sheetNames )
294 m_placementProperties->m_sheetCombo->Append( sourceName );
295
296 for( const wxString& groupName : groupNames )
297 m_placementProperties->m_groupCombo->Append( groupName );
298
299 if( !sheetNames.empty() )
300 m_placementProperties->m_sheetCombo->Select( 0 );
301
302 if( !groupNames.empty() )
303 m_placementProperties->m_groupCombo->Select( 0 );
304 }
305
306 auto setupCurrentSourceSelection = [&]( wxComboBox* cb )
307 {
308 if( curSourceName == wxEmptyString )
309 return;
310
311 if( !cb->SetStringSelection( curSourceName ) )
312 {
314 m_notFoundPlacementSourceName = curSourceName;
315 wxString notFoundDisplayName = _( "Not found on board: " ) + curSourceName;
316 cb->Insert( notFoundDisplayName, 0 );
317 cb->Select( 0 );
318 }
319 };
320
321 if( m_zonesettings.GetPlacementAreaSourceType() == PLACEMENT_SOURCE_T::SHEETNAME )
322 {
323 if( m_zonesettings.GetPlacementAreaEnabled() )
324 m_placementProperties->m_SheetRb->SetValue( true );
325
326 setupCurrentSourceSelection( m_placementProperties->m_sheetCombo );
329 }
330 else if( m_zonesettings.GetPlacementAreaSourceType() == PLACEMENT_SOURCE_T::COMPONENT_CLASS )
331 {
332 if( m_zonesettings.GetPlacementAreaEnabled() )
333 m_placementProperties->m_ComponentsRb->SetValue( true );
334
335 setupCurrentSourceSelection( m_placementProperties->m_componentClassCombo );
338 }
339 else
340 {
341 if( m_zonesettings.GetPlacementAreaEnabled() )
342 m_placementProperties->m_GroupRb->SetValue( true );
343
344 setupCurrentSourceSelection( m_placementProperties->m_groupCombo );
347 }
348
349 // Handle most-useful notebook page selection
350 m_areaPropertiesNb->SetSelection( 0 );
351
352 if( !m_zonesettings.HasKeepoutParametersSet() && m_zonesettings.GetPlacementAreaEnabled() )
353 m_areaPropertiesNb->SetSelection( 1 );
354
355
356 m_cbLocked->SetValue( m_zonesettings.m_Locked );
357 m_tcName->SetValue( m_zonesettings.m_Name );
359
360 switch( m_zonesettings.m_ZoneBorderDisplayStyle )
361 {
362 case ZONE_BORDER_DISPLAY_STYLE::INVISIBLE_BORDER: // Not used for standard zones. Here use NO_HATCH
363 case ZONE_BORDER_DISPLAY_STYLE::NO_HATCH: m_OutlineDisplayCtrl->SetSelection( 0 ); break;
366 }
367
368 m_outlineHatchPitch.SetValue( m_zonesettings.m_BorderHatchPitch );
369
371 Layout();
372
373 return true;
374}
375
376
378{
379 if( event.GetColumn() != 0 )
380 return;
381
382 int row = m_layers->ItemToRow( event.GetItem() );
383 wxVariant layerID;
384 m_layers->GetValue( layerID, row, LAYER_LIST_COLUMN_NAME );
385 bool selected = m_layers->GetToggleValue( row, LAYER_LIST_COLUMN_CHECK );
386
387 const auto setSelectedLayer = [&]()
388 {
389 m_zonesettings.m_Layers.set( ToLAYER_ID( layerID.GetInteger() ), selected );
390 };
391
392 // In footprint editor, we may in "expand inner layer" mode, where we
393 // have only 3 possible layer selection: C_Cu, inner layers, B_Cu.
394 // So row LAYER_LIST_ROW_ALL_INNER_LAYERS selection is fp editor specific.
395 // in board editor, this row is a normal selection
397 {
398 const FOOTPRINT* fp = static_cast<FOOTPRINT*>( m_parent->GetModel() );
399
401 {
402 if( selected )
404 else
405 m_zonesettings.m_Layers &= ~LSET::InternalCuMask();
406 }
407 else
408 {
409 // We have a custom stackup footprint, so select just that one layer
410 setSelectedLayer();
411 }
412 }
413 else
414 {
415 setSelectedLayer();
416 }
417}
418
419
421{
423 {
424 if( m_rbBoundingHull->GetValue() )
425 {
426 m_convertSettings->m_Strategy = BOUNDING_HULL;
427 m_convertSettings->m_Gap = m_gap->GetIntValue();
428 }
429 else
430 {
431 m_convertSettings->m_Strategy = CENTERLINE;
432 }
433
434 m_convertSettings->m_DeleteOriginals = m_cbDeleteOriginals->GetValue();
435 }
436
437 // Set keepout parameters:
438 m_zonesettings.SetIsRuleArea( true );
439 m_zonesettings.SetDoNotAllowTracks( m_keepoutProperties->m_cbTracksCtrl->GetValue() );
440 m_zonesettings.SetDoNotAllowVias( m_keepoutProperties->m_cbViasCtrl->GetValue() );
441 m_zonesettings.SetDoNotAllowZoneFills( m_keepoutProperties->m_cbCopperPourCtrl->GetValue() );
442 m_zonesettings.SetDoNotAllowPads( m_keepoutProperties->m_cbPadsCtrl->GetValue() );
443 m_zonesettings.SetDoNotAllowFootprints( m_keepoutProperties->m_cbFootprintsCtrl->GetValue() );
444
445 // Set placement parameters
446 m_zonesettings.SetPlacementAreaEnabled( false );
447 m_zonesettings.SetPlacementAreaSource( wxEmptyString );
448
449 auto setPlacementSource =
450 [this]( PLACEMENT_SOURCE_T sourceType )
451 {
452 m_zonesettings.SetPlacementAreaSourceType( sourceType );
453
454 wxComboBox* cb;
455
456 if( sourceType == PLACEMENT_SOURCE_T::SHEETNAME )
457 cb = m_placementProperties->m_sheetCombo;
458 else if( sourceType == PLACEMENT_SOURCE_T::COMPONENT_CLASS )
459 cb = m_placementProperties->m_componentClassCombo;
460 else
461 cb = m_placementProperties->m_groupCombo;
462
463 int selectedSourceIdx = cb->GetSelection();
464
465 if( selectedSourceIdx != wxNOT_FOUND )
466 {
467 if( selectedSourceIdx == 0 && m_notFoundPlacementSource
468 && m_originalPlacementSourceType == sourceType )
469 {
470 m_zonesettings.SetPlacementAreaSource( m_notFoundPlacementSourceName );
471 }
472 else
473 {
474 m_zonesettings.SetPlacementAreaSource( cb->GetString( selectedSourceIdx ) );
475 }
476 }
477 };
478
479 if( m_placementProperties->m_SheetRb->GetValue() )
480 {
481 m_zonesettings.SetPlacementAreaEnabled( true );
482 setPlacementSource( PLACEMENT_SOURCE_T::SHEETNAME );
483 }
484 else if( m_placementProperties->m_ComponentsRb->GetValue() )
485 {
486 m_zonesettings.SetPlacementAreaEnabled( true );
487 setPlacementSource( PLACEMENT_SOURCE_T::COMPONENT_CLASS );
488 }
489 else if( m_placementProperties->m_GroupRb->GetValue() )
490 {
491 m_zonesettings.SetPlacementAreaEnabled( true );
492 setPlacementSource( PLACEMENT_SOURCE_T::GROUP_PLACEMENT );
493 }
494 else
495 {
496 setPlacementSource( m_lastPlacementSourceType );
497 }
498
499 if( m_zonesettings.m_Layers.count() == 0 )
500 {
501 DisplayError( this, _( "No layers selected." ) );
502 return false;
503 }
504
505 switch( m_OutlineDisplayCtrl->GetSelection() )
506 {
507 case 0:
508 m_zonesettings.m_ZoneBorderDisplayStyle = ZONE_BORDER_DISPLAY_STYLE::NO_HATCH;
509 break;
510 case 1:
512 break;
513 case 2:
515 break;
516 }
517
520 {
521 return false;
522 }
523
524 m_zonesettings.m_BorderHatchPitch = m_outlineHatchPitch.GetIntValue();
525
526 m_zonesettings.m_Locked = m_cbLocked->GetValue();
527 m_zonesettings.m_ZonePriority = 0; // for a keepout, this param is not used.
528
529 m_zonesettings.m_Name = m_tcName->GetValue();
530
531 // Only enforce uniqueness when the user actually changed the name (issue 23131)
532 if( m_board && m_zonesettings.m_Name != m_originalName )
533 m_zonesettings.m_Name = m_board->GetUniqueZoneName( m_zonesettings.m_Name );
534
536 return true;
537}
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:128
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:410
int GetCopperLayerCount() const
Definition board.cpp:1138
DIALOG_RULE_AREA_PROPERTIES_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Rule Area Properties"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(708, 471), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxFULL_REPAINT_ON_RESIZE|wxBORDER_SUNKEN)
void OnLayerSelection(wxDataViewEvent &event) override
wxString m_originalName
name the dialog opened with, to detect edits
ZONE_SETTINGS m_zonesettings
the working copy of zone settings
void OnSheetNameClicked(wxCommandEvent &event)
PANEL_RULE_AREA_PROPERTIES_KEEPOUT_BASE * m_keepoutProperties
ZONE_SETTINGS * m_ptr
the pointer to the zone settings of the zone to edit
PANEL_RULE_AREA_PROPERTIES_PLACEMENT_BASE * m_placementProperties
void OnGroupClicked(wxCommandEvent &event)
DIALOG_RULE_AREA_PROPERTIES(PCB_BASE_FRAME *aParent, ZONE_SETTINGS *aSettings, CONVERT_SETTINGS *aConvertSettings, BOARD *aBoard)
void OnComponentClassClicked(wxCommandEvent &event)
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition dialog_shim.h:94
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...
int ShowModal() override
FRAME_T GetFrameType() const
A set of EDA_ITEMs (i.e., without duplicates).
Definition eda_group.h:43
FOOTPRINT_STACKUP GetStackupMode() const
Definition footprint.h:542
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:604
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition lset.cpp:623
static const LSET & InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
Definition lset.cpp:573
Class PANEL_RULE_AREA_PROPERTIES_KEEPOUT_BASE.
Class PANEL_RULE_AREA_PROPERTIES_PLACEMENT_BASE.
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
Handle zones parameters.
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:192
This file is part of the common library.
#define LAYER_LIST_ROW_ALL_INNER_LAYERS
#define LAYER_LIST_COLUMN_NAME
#define LAYER_LIST_COLUMN_CHECK
int InvokeRuleAreaEditor(PCB_BASE_FRAME *aCaller, ZONE_SETTINGS *aZoneSettings, BOARD *aBoard, CONVERT_SETTINGS *aConvertSettings)
Invoke a modal dialog window for copper zone editing.
#define _(s)
@ EXPAND_INNER_LAYERS
The 'normal' stackup handling, where there is a single inner layer (In1) and rule areas using it expa...
Definition footprint.h:161
@ FRAME_FOOTPRINT_EDITOR
Definition frame_type.h:39
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition lset.cpp:750
@ CENTERLINE
@ BOUNDING_HULL
Class ZONE_SETTINGS used to handle zones parameters in dialogs.
PLACEMENT_SOURCE_T
#define ZONE_BORDER_HATCH_MINDIST_MM
Definition zones.h:35
#define ZONE_BORDER_HATCH_MAXDIST_MM
Definition zones.h:36