KiCad PCB EDA Suite
dialog_graphic_item_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) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25/*
26 * Edit properties of Lines, Circles, Arcs and Polygons for PCBNew and Footprint Editor
27 */
28
29#include <pcb_base_edit_frame.h>
30#include <pcb_edit_frame.h>
31#include <wx/valnum.h>
32#include <board_commit.h>
35#include <tool/tool_manager.h>
36#include <tool/actions.h>
37#include <pcb_shape.h>
38#include <fp_shape.h>
39#include <macros.h>
40#include <confirm.h>
41#include <widgets/unit_binder.h>
42
44#include <tools/drawing_tool.h>
45
47{
48private:
52
59
61
62public:
65
66private:
67 bool TransferDataToWindow() override;
68 bool TransferDataFromWindow() override;
69
70 void OnInitDlg( wxInitDialogEvent& event ) override
71 {
72 // Call the default wxDialog handler of a wxInitDialogEvent
74
75 // Now all widgets have the size fixed, call FinishDialogSettings
77 }
78
79 void onFilledCheckbox( wxCommandEvent& event ) override;
80
81 bool Validate() override;
82};
83
85 BOARD_ITEM* aItem ):
87 m_startX( aParent, m_startXLabel, m_startXCtrl, m_startXUnits ),
88 m_startY( aParent, m_startYLabel, m_startYCtrl, m_startYUnits ),
89 m_endX( aParent, m_endXLabel, m_endXCtrl, m_endXUnits ),
90 m_endY( aParent, m_endYLabel, m_endYCtrl, m_endYUnits ),
91 m_angle( aParent, m_angleLabel, m_angleCtrl, m_angleUnits ),
92 m_thickness( aParent, m_thicknessLabel, m_thicknessCtrl, m_thicknessUnits ),
93 m_bezierCtrl1X( aParent, m_BezierPointC1XLabel, m_BezierC1X_Ctrl, m_BezierPointC1XUnit ),
94 m_bezierCtrl1Y( aParent, m_BezierPointC1YLabel, m_BezierC1Y_Ctrl, m_BezierPointC1YUnit ),
95 m_bezierCtrl2X( aParent, m_BezierPointC2XLabel, m_BezierC2X_Ctrl, m_BezierPointC2XUnit ),
96 m_bezierCtrl2Y( aParent, m_BezierPointC2YLabel, m_BezierC2Y_Ctrl, m_BezierPointC2YUnit ),
97 m_flipStartEnd( false )
98{
99 m_parent = aParent;
100 m_item = dynamic_cast<PCB_SHAPE*>( aItem );
101 m_fp_item = dynamic_cast<FP_SHAPE*>( aItem );
102
103 // Configure display origin transforms
112
114
115 // Do not allow locking items in the footprint editor
116 m_locked->Show( dynamic_cast<PCB_EDIT_FRAME*>( aParent ) != nullptr );
117
118 // Configure the layers list selector
119 if( m_fp_item )
120 {
121 LSET forbiddenLayers = LSET::ForbiddenFootprintLayers();
122
123 // If someone went to the trouble of setting the layer in a text editor, then there's
124 // very little sense in nagging them about it.
125 forbiddenLayers.set( m_fp_item->GetLayer(), false );
126
128 }
129
130 for( const std::pair<const PLOT_DASH_TYPE, lineTypeStruct>& typeEntry : lineTypeNames )
131 m_lineStyleCombo->Append( typeEntry.second.name, KiBitmap( typeEntry.second.bitmap ) );
132
134
138
140
142}
143
144
146{
147 wxCHECK_RET( aItem != NULL, wxT( "ShowGraphicItemPropertiesDialog() error: NULL item" ) );
148
149 DIALOG_GRAPHIC_ITEM_PROPERTIES dlg( this, aItem );
150
151 if( dlg.ShowQuasiModal() == wxID_OK )
152 {
153 if( aItem->IsOnLayer( GetActiveLayer() ) )
154 {
156 drawingTool->SetStroke( aItem->GetStroke(), GetActiveLayer() );
157 }
158 }
159}
160
161
163{
164 if( m_filledCtrl->GetValue() )
165 {
166 m_lineStyleCombo->SetSelection( 0 );
167 m_lineStyleLabel->Enable( false );
168 m_lineStyleCombo->Enable( false );
169 }
170 else
171 {
173
174 if( style == PLOT_DASH_TYPE::DEFAULT )
175 style = PLOT_DASH_TYPE::SOLID;
176
177 if( (int) style < (int) lineTypeNames.size() )
178 m_lineStyleCombo->SetSelection( (int) style );
179
180 m_lineStyleLabel->Enable( true );
181 m_lineStyleCombo->Enable( true );
182 }
183}
184
185
187{
188 if( !m_item )
189 return false;
190
191 // Only an arc has a angle parameter. So do not show this parameter for other shapes
192 if( m_item->GetShape() != SHAPE_T::ARC )
193 m_angle.Show( false );
194
195 // Only a Bezeier curve has control points. So do not show these parameters for other shapes
197 {
198 m_bezierCtrlPt1Label->Show( false );
199 m_bezierCtrl1X.Show( false );
200 m_bezierCtrl1Y.Show( false );
201 m_bezierCtrlPt2Label->Show( false );
202 m_bezierCtrl2X.Show( false );
203 m_bezierCtrl2Y.Show( false );
204 }
205
206 // Change texts according to the segment shape:
207 switch( m_item->GetShape() )
208 {
209 case SHAPE_T::CIRCLE:
210 SetTitle( _( "Circle Properties" ) );
211 m_startPointLabel->SetLabel( _( "Center Point" ) );
212
213 m_endPointLabel->SetLabel( _( "Radius" ) );
214 m_endXLabel->Show( false );
216
217 m_endY.Show( false );
218
219 m_filledCtrl->Show( true );
220 break;
221
222 case SHAPE_T::ARC:
223 SetTitle( _( "Arc Properties" ) );
225 m_filledCtrl->Show( false );
226 break;
227
228 case SHAPE_T::POLY:
229 SetTitle( _( "Polygon Properties" ) );
230 m_sizerLeft->Show( false );
231 m_filledCtrl->Show( true );
232 break;
233
234 case SHAPE_T::RECT:
235 SetTitle( _( "Rectangle Properties" ) );
236
237 m_filledCtrl->Show( true );
238 break;
239
240 case SHAPE_T::SEGMENT:
241 SetTitle( _( "Line Segment Properties" ) );
242
243 if( m_item->GetStart().x == m_item->GetEnd().x )
245 else
247
248 m_filledCtrl->Show( false );
249 break;
250
251 case SHAPE_T::BEZIER:
252 SetTitle( _( "Curve Properties" ) );
253 m_filledCtrl->Show( true );
254 break;
255
256 default:
257 break;
258 }
259
261 {
264 }
265 else
266 {
269 }
270
272 {
274 }
275 else if( m_flipStartEnd && m_item->GetShape() != SHAPE_T::ARC )
276 {
279 }
280 else
281 {
284 }
285
286 // For Bezier curve:
291
292 m_filledCtrl->SetValue( m_item->IsFilled() );
293 m_locked->SetValue( m_item->IsLocked() );
294
296
297 int style = static_cast<int>( m_item->GetStroke().GetPlotStyle() );
298
299 if( style == -1 )
300 m_lineStyleCombo->SetStringSelection( DEFAULT_STYLE );
301 else if( style < (int) lineTypeNames.size() )
302 m_lineStyleCombo->SetSelection( style );
303 else
304 wxFAIL_MSG( "Line type not found in the type lookup map" );
305
307
308 return DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::TransferDataToWindow();
309}
310
311
313{
314 if( !DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::TransferDataFromWindow() )
315 return false;
316
317 if( !m_item )
318 return true;
319
321 BOARD_COMMIT commit( m_parent );
322
323 commit.Modify( m_item );
324
326 {
329 }
330 else
331 {
334 }
335
337 {
339 }
340 else if( m_flipStartEnd && m_item->GetShape() != SHAPE_T::ARC )
341 {
344 }
345 else
346 {
349 }
350
351 // For Bezier curve: Set the two control points
353 {
356 }
357
358 if( m_item->GetShape() == SHAPE_T::ARC )
359 {
361
362 m_item->SetCenter( c );
363 }
364
365 if( m_fp_item )
366 {
367 // We are editing a footprint; init the item coordinates relative to the footprint anchor.
370
373
375 {
378 }
379 }
380
381 bool wasLocked = m_item->IsLocked();
382
383 m_item->SetFilled( m_filledCtrl->GetValue() );
384 m_item->SetLocked( m_locked->GetValue() );
385
386 STROKE_PARAMS stroke = m_item->GetStroke();
387
388 stroke.SetWidth( m_thickness.GetValue() );
389
390 auto it = lineTypeNames.begin();
391 std::advance( it, m_lineStyleCombo->GetSelection() );
392
393 if( it == lineTypeNames.end() )
395 else
396 stroke.SetPlotStyle( it->first );
397
398 m_item->SetStroke( stroke );
399
400 m_item->SetLayer( ToLAYER_ID( layer ) );
401
403
404 commit.Push( _( "Modify drawing properties" ) );
405
406 // Notify clients which treat locked and unlocked items differently (ie: POINT_EDITOR)
407 if( wasLocked != m_item->IsLocked() )
409
411
412 return true;
413}
414
415
417{
418 wxArrayString errors;
419
420 if( !DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::Validate() )
421 return false;
422
423 // Type specific checks.
424 switch( m_item->GetShape() )
425 {
426 case SHAPE_T::ARC:
427 // Check angle of arc.
428 if( m_angle.GetAngleValue() == ANGLE_0 )
429 errors.Add( _( "Arc angle cannot be zero." ) );
430
432 {
433 errors.Add( wxString::Format( _( "Invalid Arc with radius %f and angle %f." ),
434 0.0, m_angle.GetDoubleValue() ) );
435 }
436 else
437 {
440 VECTOR2D center = CalcArcCenter( start, end, m_angle.GetAngleValue() );
441
442 double radius = ( center - start ).EuclideanNorm();
443 double max_offset = std::max( std::abs( center.x ) + radius,
444 std::abs( center.y ) + radius );
445
446 if( max_offset >= ( std::numeric_limits<VECTOR2I::coord_type>::max() / 2 )
447 || center == start || center == end )
448 {
449 errors.Add( wxString::Format( _( "Invalid Arc with radius %f and angle %f." ),
450 radius, m_angle.GetDoubleValue() ) );
451 }
452 }
453
454 if( m_thickness.GetValue() <= 0 )
455 errors.Add( _( "Line width must be greater than zero." ) );
456
457 break;
458
459 case SHAPE_T::CIRCLE:
460 // Check radius.
461 if( m_endX.GetValue() <= 0 )
462 errors.Add( _( "Radius must be greater than zero." ) );
463
464 if( !m_filledCtrl->GetValue() && m_thickness.GetValue() <= 0 )
465 errors.Add( _( "Line width must be greater than zero for an unfilled circle." ) );
466
467 break;
468
469 case SHAPE_T::RECT:
470 // Check for null rect.
472 errors.Add( _( "Rectangle cannot be empty." ) );
473
474 if( !m_filledCtrl->GetValue() && m_thickness.GetValue() <= 0 )
475 errors.Add( _( "Line width must be greater than zero for an unfilled rectangle." ) );
476
477 break;
478
479 case SHAPE_T::POLY:
480 if( !m_filledCtrl->GetValue() && m_thickness.GetValue() <= 0 )
481 errors.Add( _( "Line width must be greater than zero for an unfilled polygon." ) );
482
483 break;
484
485 case SHAPE_T::SEGMENT:
486 if( m_thickness.GetValue() <= 0 )
487 errors.Add( _( "Line width must be greater than zero." ) );
488
489 break;
490
491 case SHAPE_T::BEZIER:
492 if( !m_filledCtrl->GetValue() && m_thickness.GetValue() <= 0 )
493 errors.Add( _( "Line width must be greater than zero for an unfilled curve." ) );
494
495 break;
496
497 default:
499 break;
500 }
501
502 if( errors.GetCount() )
503 {
504 HTML_MESSAGE_BOX dlg( this, _( "Error List" ) );
505 dlg.ListSet( errors );
506 dlg.ShowModal();
507 }
508
509 return errors.GetCount() == 0;
510}
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:58
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:180
virtual STROKE_PARAMS GetStroke() const
Definition: board_item.cpp:82
virtual void SetLocked(bool aLocked)
Definition: board_item.h:254
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
Definition: board_item.h:245
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:214
virtual bool IsLocked() const
Definition: board_item.cpp:71
COMMIT & Modify(EDA_ITEM *aItem)
Create an undo entry for an item that has been already modified.
Definition: commit.h:103
Class DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE.
void onFilledCheckbox(wxCommandEvent &event) override
DIALOG_GRAPHIC_ITEM_PROPERTIES(PCB_BASE_EDIT_FRAME *aParent, BOARD_ITEM *aItem)
void OnInitDlg(wxInitDialogEvent &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:97
void SetupStandardButtons(std::map< int, wxString > aLabels={})
int ShowQuasiModal()
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
Tool responsible for drawing graphical elements like lines, arcs, circles, etc.
Definition: drawing_tool.h:51
void SetStroke(const STROKE_PARAMS &aStroke, PCB_LAYER_ID aLayer)
Definition: drawing_tool.h:212
virtual void UpdateMsgPanel()
Redraw the message panel.
EDA_ANGLE GetArcAngle() const
Definition: eda_shape.cpp:573
void SetStartX(int x)
Definition: eda_shape.h:136
const VECTOR2I & GetBezierC2() const
Definition: eda_shape.h:179
void SetBezierC2(const VECTOR2I &aPt)
Definition: eda_shape.h:178
void SetCenter(const VECTOR2I &aCenter)
Definition: eda_shape.cpp:458
void SetEndY(int y)
Definition: eda_shape.h:155
void RebuildBezierToSegmentsPointsList(int aMinSegLen)
Rebuild the m_bezierPoints vertex list that approximate the Bezier curve by a list of segments.
Definition: eda_shape.cpp:405
void SetStartY(int y)
Definition: eda_shape.h:130
bool IsFilled() const
Definition: eda_shape.h:90
void SetFilled(bool aFlag)
Definition: eda_shape.h:95
int GetRadius() const
Definition: eda_shape.cpp:511
SHAPE_T GetShape() const
Definition: eda_shape.h:113
void SetEndX(int x)
Definition: eda_shape.h:161
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:145
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition: eda_shape.h:120
int GetWidth() const
Definition: eda_shape.h:109
void SetEnd(const VECTOR2I &aEnd)
Definition: eda_shape.h:149
void SetBezierC1(const VECTOR2I &aPt)
Definition: eda_shape.h:175
wxString SHAPE_T_asString() const
Definition: eda_shape.cpp:75
const VECTOR2I & GetBezierC1() const
Definition: eda_shape.h:176
static const TOOL_EVENT SelectedEvent
Definition: actions.h:206
void SetEnd0(const VECTOR2I &aPoint)
Definition: fp_shape.h:94
void SetStart0(const VECTOR2I &aPoint)
Definition: fp_shape.h:91
void SetBezierC2_0(const VECTOR2I &aPoint)
Definition: fp_shape.h:100
void SetCenter0(const VECTOR2I &aPt)
Definition: fp_shape.cpp:161
void SetBezierC1_0(const VECTOR2I &aPoint)
Definition: fp_shape.h:97
void ListSet(const wxString &aList)
Add a list of items.
int SetLayerSelection(int layer)
bool SetLayersHotkeys(bool value)
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:530
static LSET ForbiddenFootprintLayers()
Layers which are not allowed within footprint definitions.
Definition: lset.cpp:915
Common, abstract interface for edit frames.
void ShowGraphicItemPropertiesDialog(BOARD_ITEM *aItem)
virtual PCB_LAYER_ID GetActiveLayer() const
The main frame for Pcbnew.
void SetBoardFrame(PCB_BASE_FRAME *aFrame)
void SetNotAllowedLayerSet(LSET aMask)
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition: pcb_shape.h:67
STROKE_PARAMS GetStroke() const override
Definition: pcb_shape.h:71
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition: pcb_shape.h:72
Simple container to manage line stroke parameters.
Definition: stroke_params.h:88
int GetWidth() const
Definition: stroke_params.h:98
void SetWidth(int aWidth)
Definition: stroke_params.h:99
PLOT_DASH_TYPE GetPlotStyle() const
void SetPlotStyle(PLOT_DASH_TYPE aPlotStyle)
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:170
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:54
void PostEvent(const TOOL_EVENT &aEvent)
Put an event to the event queue to be processed at the end of event processing cycle.
virtual long long int GetValue()
Return the current value in Internal Units.
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()
virtual double GetDoubleValue()
Return the current value in Internal Units.
virtual void SetAngleValue(const EDA_ANGLE &aValue)
virtual void SetValue(long long int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
void Show(bool aShow, bool aResize=false)
Show/hide the label, widget and units label.
void SetCoordType(ORIGIN_TRANSFORMS::COORD_TYPES_T aCoordType)
Set the current origin transform mode.
Definition: unit_binder.h:187
This file is part of the common library.
#define _(s)
static constexpr EDA_ANGLE & ANGLE_0
Definition: eda_angle.h:412
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:932
This file contains miscellaneous commonly used macros and functions.
#define UNIMPLEMENTED_FOR(type)
Definition: macros.h:120
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:401
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
PLOT_DASH_TYPE
Dashed line types.
Definition: stroke_params.h:48
const std::map< PLOT_DASH_TYPE, struct lineTypeStruct > lineTypeNames
Definition: stroke_params.h:70
const VECTOR2I CalcArcCenter(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Determine the center of an arc or circle given three points on its circumference.
Definition: trigo.cpp:472
double EuclideanNorm(const VECTOR2I &vector)
Definition: trigo.h:129
VECTOR2< int > VECTOR2I
Definition: vector2d.h:618