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, 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 <advanced_config.h>
27#include <kiface_base.h>
28#include <confirm.h>
29#include <board.h>
30#include <eda_group.h>
31#include <footprint.h>
32#include <pcb_edit_frame.h>
33#include <pcbnew_settings.h>
34#include <zone_settings.h>
38#include <widgets/unit_binder.h>
39#include <wx/statbox.h>
40#include <wx/statline.h>
41#include <wx/radiobut.h>
42
43#define LAYER_LIST_COLUMN_CHECK 0
44#define LAYER_LIST_COLUMN_ICON 1
45#define LAYER_LIST_COLUMN_NAME 2
46#define LAYER_LIST_ROW_ALL_INNER_LAYERS 1
47
48
50{
51public:
53 CONVERT_SETTINGS* aConvertSettings, BOARD* aBoard );
55
56private:
57 bool TransferDataToWindow() override;
58 bool TransferDataFromWindow() override;
59
60 void OnLayerSelection( wxDataViewEvent& event ) override;
61 void OnSheetNameClicked( wxCommandEvent& event );
62 void OnComponentClassClicked( wxCommandEvent& event );
63 void OnGroupClicked( wxCommandEvent& event );
64
65private:
72
74 wxRadioButton* m_rbCenterline;
75 wxRadioButton* m_rbBoundingHull;
76 wxStaticText* m_gapLabel;
77 wxTextCtrl* m_gapCtrl;
78 wxStaticText* m_gapUnits;
81
82 // The name of a rule area source that is not now found on the board (e.g. after a netlist
83 // update). This is used to re-populate the zone settings if the selection is not changed.
88
91};
92
93
94int InvokeRuleAreaEditor( PCB_BASE_FRAME* aCaller, ZONE_SETTINGS* aZoneSettings, BOARD* aBoard,
95 CONVERT_SETTINGS* aConvertSettings )
96{
97 DIALOG_RULE_AREA_PROPERTIES dlg( aCaller, aZoneSettings, aConvertSettings, aBoard );
98
99 return dlg.ShowModal();
100}
101
102
104 ZONE_SETTINGS* aSettings,
105 CONVERT_SETTINGS* aConvertSettings,
106 BOARD* aBoard ) :
108 m_board( aBoard ),
110 m_convertSettings( aConvertSettings ),
111 m_rbCenterline( nullptr ),
112 m_rbBoundingHull( nullptr ),
113 m_gapLabel( nullptr ),
114 m_gapCtrl( nullptr ),
115 m_gapUnits( nullptr ),
116 m_gap( nullptr ),
117 m_cbDeleteOriginals( nullptr ),
121{
123 m_parent = aParent;
124
125 m_ptr = aSettings;
126 m_zonesettings = *aSettings;
127
129 m_areaPropertiesNb->AddPage( m_keepoutProperties, _( "Keepouts" ), true );
130
132 m_areaPropertiesNb->AddPage( m_placementProperties, _( "Placement" ) );
133
134 m_placementProperties->m_SheetRb->Connect(
135 wxEVT_CHECKBOX,
136 wxCommandEventHandler( DIALOG_RULE_AREA_PROPERTIES::OnSheetNameClicked ), nullptr,
137 this );
138 m_placementProperties->m_ComponentsRb->Connect(
139 wxEVT_CHECKBOX,
140 wxCommandEventHandler( DIALOG_RULE_AREA_PROPERTIES::OnComponentClassClicked ), nullptr,
141 this );
142 m_placementProperties->m_GroupRb->Connect(
143 wxEVT_CHECKBOX,
144 wxCommandEventHandler( DIALOG_RULE_AREA_PROPERTIES::OnGroupClicked ), nullptr,
145 this );
146
147 if( aConvertSettings )
148 {
149 wxStaticBox* bConvertBox = new wxStaticBox( this, wxID_ANY,
150 _( "Conversion Settings" ) );
151 wxStaticBoxSizer* bConvertSizer = new wxStaticBoxSizer( bConvertBox, wxVERTICAL );
152
153 m_rbCenterline = new wxRadioButton( this, wxID_ANY, _( "Use centerlines" ) );
154 bConvertSizer->Add( m_rbCenterline, 0, wxLEFT|wxRIGHT, 5 );
155
156 bConvertSizer->AddSpacer( 2 );
157 m_rbBoundingHull = new wxRadioButton( this, wxID_ANY, _( "Create bounding hull" ) );
158 bConvertSizer->Add( m_rbBoundingHull, 0, wxLEFT|wxRIGHT, 5 );
159
160 m_gapLabel = new wxStaticText( this, wxID_ANY, _( "Gap:" ) );
161 m_gapCtrl = new wxTextCtrl( this, wxID_ANY );
162 m_gapUnits = new wxStaticText( this, wxID_ANY, _( "mm" ) );
163 m_gap = new UNIT_BINDER( aParent, m_gapLabel, m_gapCtrl, m_gapUnits );
164
165 wxBoxSizer* hullParamsSizer = new wxBoxSizer( wxHORIZONTAL );
166 hullParamsSizer->Add( m_gapLabel, 0, wxALIGN_CENTRE_VERTICAL, 5 );
167 hullParamsSizer->Add( m_gapCtrl, 1, wxALIGN_CENTRE_VERTICAL|wxLEFT|wxRIGHT, 3 );
168 hullParamsSizer->Add( m_gapUnits, 0, wxALIGN_CENTRE_VERTICAL, 5 );
169
170 bConvertSizer->AddSpacer( 2 );
171 bConvertSizer->Add( hullParamsSizer, 0, wxLEFT, 26 );
172
173 bConvertSizer->AddSpacer( 6 );
174 m_cbDeleteOriginals = new wxCheckBox( this, wxID_ANY,
175 _( "Delete source objects after conversion" ) );
176 bConvertSizer->Add( m_cbDeleteOriginals, 0, wxALL, 5 );
177
178 GetSizer()->Insert( 0, bConvertSizer, 0, wxALL|wxEXPAND, 10 );
179
180 wxStaticLine* line = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
181 wxLI_HORIZONTAL );
182 GetSizer()->Insert( 1, line, 0, wxLEFT|wxRIGHT|wxEXPAND, 10 );
183
184 SetTitle( _( "Convert to Rule Area" ) );
185 }
186
187 BOARD* board = m_parent->GetBoard();
189
190 m_zonesettings.SetupLayersList( m_layers, m_parent, layers );
191
193
195}
196
197
199{
200 m_placementProperties->m_SheetRb->Disconnect(
201 wxEVT_CHECKBOX,
202 wxCommandEventHandler( DIALOG_RULE_AREA_PROPERTIES::OnSheetNameClicked ), nullptr,
203 this );
204 m_placementProperties->m_ComponentsRb->Disconnect(
205 wxEVT_CHECKBOX,
206 wxCommandEventHandler( DIALOG_RULE_AREA_PROPERTIES::OnComponentClassClicked ), nullptr,
207 this );
208 m_placementProperties->m_GroupRb->Disconnect(
209 wxEVT_CHECKBOX,
210 wxCommandEventHandler( DIALOG_RULE_AREA_PROPERTIES::OnGroupClicked ), nullptr,
211 this );
212}
213
214
219
220
225
226
231
232
234{
236 {
237 if( m_convertSettings->m_Strategy == BOUNDING_HULL )
238 m_rbBoundingHull->SetValue( true );
239 else
240 m_rbCenterline->SetValue( true );
241
242 m_cbDeleteOriginals->SetValue( m_convertSettings->m_DeleteOriginals );
243 }
244
245 // Init keepout parameters:
246 m_keepoutProperties->m_cbTracksCtrl->SetValue( m_zonesettings.GetDoNotAllowTracks() );
247 m_keepoutProperties->m_cbViasCtrl->SetValue( m_zonesettings.GetDoNotAllowVias() );
248 m_keepoutProperties->m_cbPadsCtrl->SetValue( m_zonesettings.GetDoNotAllowPads() );
249 m_keepoutProperties->m_cbFootprintsCtrl->SetValue( m_zonesettings.GetDoNotAllowFootprints() );
250 m_keepoutProperties->m_cbCopperPourCtrl->SetValue( m_zonesettings.GetDoNotAllowZoneFills() );
251
252 // Init placement parameters:
253 m_placementProperties->m_DisabledRb->SetValue( true );
254 m_placementProperties->m_SheetRb->SetValue( false );
255 m_placementProperties->m_sheetCombo->Clear();
256
257 m_placementProperties->m_ComponentsRb->SetValue( false );
258 m_placementProperties->m_componentClassCombo->Clear();
259
260 m_placementProperties->m_GroupRb->SetValue( false );
261 m_placementProperties->m_groupCombo->Clear();
262
263 wxString curSourceName = m_zonesettings.GetPlacementAreaSource();
264
265 // Load schematic sheet and component class lists
266 if( m_board )
267 {
268 // Fetch component classes
269 std::set<wxString> classNames;
270
271 for( const wxString& className : m_board->GetComponentClassManager().GetClassNames() )
272 classNames.insert( className );
273
274 for( const wxString& sourceName : classNames )
275 m_placementProperties->m_componentClassCombo->Append( sourceName );
276
277 if( !classNames.empty() )
278 m_placementProperties->m_componentClassCombo->Select( 0 );
279
280 // Fetch sheet names and groups
281 std::set<wxString> sheetNames;
282 std::set<wxString> groupNames;
283
284 for( FOOTPRINT* fp : m_board->Footprints() )
285 {
286 sheetNames.insert( fp->GetSheetname() );
287
288 if( fp->GetParentGroup() && !fp->GetParentGroup()->GetName().IsEmpty() )
289 groupNames.insert( fp->GetParentGroup()->GetName() );
290 }
291
292 for( const wxString& sourceName : sheetNames )
293 m_placementProperties->m_sheetCombo->Append( sourceName );
294
295 for( const wxString& groupName : groupNames )
296 m_placementProperties->m_groupCombo->Append( groupName );
297
298 if( !sheetNames.empty() )
299 m_placementProperties->m_sheetCombo->Select( 0 );
300
301 if( !groupNames.empty() )
302 m_placementProperties->m_groupCombo->Select( 0 );
303 }
304
305 auto setupCurrentSourceSelection = [&]( wxComboBox* cb )
306 {
307 if( curSourceName == wxEmptyString )
308 return;
309
310 if( !cb->SetStringSelection( curSourceName ) )
311 {
313 m_notFoundPlacementSourceName = curSourceName;
314 wxString notFoundDisplayName = _( "Not found on board: " ) + curSourceName;
315 cb->Insert( notFoundDisplayName, 0 );
316 cb->Select( 0 );
317 }
318 };
319
320 if( m_zonesettings.GetPlacementAreaSourceType() == PLACEMENT_SOURCE_T::SHEETNAME )
321 {
322 if( m_zonesettings.GetPlacementAreaEnabled() )
323 m_placementProperties->m_SheetRb->SetValue( true );
324
325 setupCurrentSourceSelection( m_placementProperties->m_sheetCombo );
328 }
329 else if( m_zonesettings.GetPlacementAreaSourceType() == PLACEMENT_SOURCE_T::COMPONENT_CLASS )
330 {
331 if( m_zonesettings.GetPlacementAreaEnabled() )
332 m_placementProperties->m_ComponentsRb->SetValue( true );
333
334 setupCurrentSourceSelection( m_placementProperties->m_componentClassCombo );
337 }
338 else
339 {
340 if( m_zonesettings.GetPlacementAreaEnabled() )
341 m_placementProperties->m_GroupRb->SetValue( true );
342
343 setupCurrentSourceSelection( m_placementProperties->m_groupCombo );
346 }
347
348 // Handle most-useful notebook page selection
349 m_areaPropertiesNb->SetSelection( 0 );
350
351 if( !m_zonesettings.HasKeepoutParametersSet() && m_zonesettings.GetPlacementAreaEnabled() )
352 m_areaPropertiesNb->SetSelection( 1 );
353
354
355 m_cbLocked->SetValue( m_zonesettings.m_Locked );
356 m_tcName->SetValue( m_zonesettings.m_Name );
357
358 switch( m_zonesettings.m_ZoneBorderDisplayStyle )
359 {
360 case ZONE_BORDER_DISPLAY_STYLE::INVISIBLE_BORDER: // Not used for standard zones. Here use NO_HATCH
361 case ZONE_BORDER_DISPLAY_STYLE::NO_HATCH: m_OutlineDisplayCtrl->SetSelection( 0 ); break;
364 }
365
366 m_outlineHatchPitch.SetValue( m_zonesettings.m_BorderHatchPitch );
367
369 Layout();
370
371 return true;
372}
373
374
376{
377 if( event.GetColumn() != 0 )
378 return;
379
380 int row = m_layers->ItemToRow( event.GetItem() );
381 wxVariant layerID;
382 m_layers->GetValue( layerID, row, LAYER_LIST_COLUMN_NAME );
383 bool selected = m_layers->GetToggleValue( row, LAYER_LIST_COLUMN_CHECK );
384
385 const auto setSelectedLayer = [&]()
386 {
387 m_zonesettings.m_Layers.set( ToLAYER_ID( layerID.GetInteger() ), selected );
388 };
389
390 // In footprint editor, we may in "expand inner layer" mode, where we
391 // have only 3 possible layer selection: C_Cu, inner layers, B_Cu.
392 // So row LAYER_LIST_ROW_ALL_INNER_LAYERS selection is fp editor specific.
393 // in board editor, this row is a normal selection
395 {
396 const FOOTPRINT* fp = static_cast<FOOTPRINT*>( m_parent->GetModel() );
397
399 {
400 if( selected )
402 else
403 m_zonesettings.m_Layers &= ~LSET::InternalCuMask();
404 }
405 else
406 {
407 // We have a custom stackup footprint, so select just that one layer
408 setSelectedLayer();
409 }
410 }
411 else
412 {
413 setSelectedLayer();
414 }
415}
416
417
419{
421 {
422 if( m_rbBoundingHull->GetValue() )
423 {
424 m_convertSettings->m_Strategy = BOUNDING_HULL;
425 m_convertSettings->m_Gap = m_gap->GetIntValue();
426 }
427 else
428 {
429 m_convertSettings->m_Strategy = CENTERLINE;
430 }
431
432 m_convertSettings->m_DeleteOriginals = m_cbDeleteOriginals->GetValue();
433 }
434
435 // Set keepout parameters:
436 m_zonesettings.SetIsRuleArea( true );
437 m_zonesettings.SetDoNotAllowTracks( m_keepoutProperties->m_cbTracksCtrl->GetValue() );
438 m_zonesettings.SetDoNotAllowVias( m_keepoutProperties->m_cbViasCtrl->GetValue() );
439 m_zonesettings.SetDoNotAllowZoneFills( m_keepoutProperties->m_cbCopperPourCtrl->GetValue() );
440 m_zonesettings.SetDoNotAllowPads( m_keepoutProperties->m_cbPadsCtrl->GetValue() );
441 m_zonesettings.SetDoNotAllowFootprints( m_keepoutProperties->m_cbFootprintsCtrl->GetValue() );
442
443 // Set placement parameters
444 m_zonesettings.SetPlacementAreaEnabled( false );
445 m_zonesettings.SetPlacementAreaSource( wxEmptyString );
446
447 auto setPlacementSource =
448 [this]( PLACEMENT_SOURCE_T sourceType )
449 {
450 m_zonesettings.SetPlacementAreaSourceType( sourceType );
451
452 wxComboBox* cb;
453
454 if( sourceType == PLACEMENT_SOURCE_T::SHEETNAME )
455 cb = m_placementProperties->m_sheetCombo;
456 else if( sourceType == PLACEMENT_SOURCE_T::COMPONENT_CLASS )
457 cb = m_placementProperties->m_componentClassCombo;
458 else
459 cb = m_placementProperties->m_groupCombo;
460
461 int selectedSourceIdx = cb->GetSelection();
462
463 if( selectedSourceIdx != wxNOT_FOUND )
464 {
465 if( selectedSourceIdx == 0 && m_notFoundPlacementSource
466 && m_originalPlacementSourceType == sourceType )
467 {
468 m_zonesettings.SetPlacementAreaSource( m_notFoundPlacementSourceName );
469 }
470 else
471 {
472 m_zonesettings.SetPlacementAreaSource( cb->GetString( selectedSourceIdx ) );
473 }
474 }
475 };
476
477 if( m_placementProperties->m_SheetRb->GetValue() )
478 {
479 m_zonesettings.SetPlacementAreaEnabled( true );
480 setPlacementSource( PLACEMENT_SOURCE_T::SHEETNAME );
481 }
482 else if( m_placementProperties->m_ComponentsRb->GetValue() )
483 {
484 m_zonesettings.SetPlacementAreaEnabled( true );
485 setPlacementSource( PLACEMENT_SOURCE_T::COMPONENT_CLASS );
486 }
487 else if( m_placementProperties->m_GroupRb->GetValue() )
488 {
489 m_zonesettings.SetPlacementAreaEnabled( true );
490 setPlacementSource( PLACEMENT_SOURCE_T::GROUP_PLACEMENT );
491 }
492 else
493 {
494 setPlacementSource( m_lastPlacementSourceType );
495 }
496
497 if( m_zonesettings.m_Layers.count() == 0 )
498 {
499 DisplayError( this, _( "No layers selected." ) );
500 return false;
501 }
502
503 switch( m_OutlineDisplayCtrl->GetSelection() )
504 {
505 case 0:
506 m_zonesettings.m_ZoneBorderDisplayStyle = ZONE_BORDER_DISPLAY_STYLE::NO_HATCH;
507 break;
508 case 1:
510 break;
511 case 2:
513 break;
514 }
515
518 {
519 return false;
520 }
521
522 m_zonesettings.m_BorderHatchPitch = m_outlineHatchPitch.GetIntValue();
523
524 m_zonesettings.m_Locked = m_cbLocked->GetValue();
525 m_zonesettings.m_ZonePriority = 0; // for a keepout, this param is not used.
526
527 m_zonesettings.m_Name = m_tcName->GetValue();
528
530 return true;
531}
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:112
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:317
int GetCopperLayerCount() const
Definition board.cpp:875
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
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: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...
int ShowModal() override
FRAME_T GetFrameType() const
FOOTPRINT_STACKUP GetStackupMode() const
Definition footprint.h:318
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition lset.cpp:610
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:591
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:560
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.
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.
#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)
Function InvokeRuleAreaEditor invokes up 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:96
@ FRAME_FOOTPRINT_EDITOR
Definition frame_type.h:43
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition lset.cpp:737
@ 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:40
#define ZONE_BORDER_HATCH_MAXDIST_MM
Definition zones.h:41