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-2020 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>
33 #include <pcb_layer_box_selector.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 
46 {
47 private:
51 
58 
60 
61  wxFloatingPointValidator<double> m_AngleValidator;
62  double m_AngleValue;
63 
64 public:
67 
68 private:
69  bool TransferDataToWindow() override;
70  bool TransferDataFromWindow() override;
71 
72  void OnInitDlg( wxInitDialogEvent& event ) override
73  {
74  // Call the default wxDialog handler of a wxInitDialogEvent
76 
77  // Now all widgets have the size fixed, call FinishDialogSettings
79  }
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  m_AngleValidator( 1, &m_AngleValue ),
99  m_AngleValue( 0.0 )
100 {
101  m_parent = aParent;
102  m_item = dynamic_cast<PCB_SHAPE*>( aItem );
103  m_fp_item = dynamic_cast<FP_SHAPE*>( aItem );
104 
105  // Configure display origin transforms
114 
116  m_AngleValidator.SetRange( -360.0, 360.0 );
117  m_angleCtrl->SetValidator( m_AngleValidator );
118  m_AngleValidator.SetWindow( m_angleCtrl );
119 
120  // Do not allow locking items in the footprint editor
121  m_locked->Show( dynamic_cast<PCB_EDIT_FRAME*>( aParent ) != nullptr );
122 
123  // Configure the layers list selector
124  if( m_fp_item )
125  {
126  LSET forbiddenLayers = LSET::ForbiddenFootprintLayers();
127 
128  // If someone went to the trouble of setting the layer in a text editor, then there's
129  // very little sense in nagging them about it.
130  forbiddenLayers.set( m_fp_item->GetLayer(), false );
131 
132  m_LayerSelectionCtrl->SetNotAllowedLayerSet( forbiddenLayers );
133  }
134 
138 
140 
141  m_StandardButtonsSizerOK->SetDefault();
142 }
143 
144 
146 {
147  wxCHECK_RET( aItem != NULL, wxT( "ShowGraphicItemPropertiesDialog() error: NULL item" ) );
148 
149  DIALOG_GRAPHIC_ITEM_PROPERTIES dlg( this, aItem );
150  dlg.ShowQuasiModal();
151 }
152 
153 
155 {
156  if( !m_item )
157  return false;
158 
159  // Only an arc has a angle parameter. So do not show this parameter for other shapes
160  if( m_item->GetShape() != SHAPE_T::ARC )
161  m_angle.Show( false );
162 
163  // Only a Bezeier curve has control points. So do not show these parameters for other shapes
164  if( m_item->GetShape() != SHAPE_T::BEZIER )
165  {
166  m_bezierCtrlPt1Label->Show( false );
167  m_bezierCtrl1X.Show( false );
168  m_bezierCtrl1Y.Show( false );
169  m_bezierCtrlPt2Label->Show( false );
170  m_bezierCtrl2X.Show( false );
171  m_bezierCtrl2Y.Show( false );
172  }
173 
174  // Change texts according to the segment shape:
175  switch( m_item->GetShape() )
176  {
177  case SHAPE_T::CIRCLE:
178  SetTitle( _( "Circle Properties" ) );
179  m_startPointLabel->SetLabel( _( "Center" ) );
180 
181  m_endPointLabel->SetLabel( _( "Radius" ) );
182  m_endXLabel->Show( false );
184 
185  m_endY.Show( false );
186 
187  m_filledCtrl->Show( true );
188  break;
189 
190  case SHAPE_T::ARC:
191  SetTitle( _( "Arc Properties" ) );
192  m_AngleValue = m_item->GetAngle() / 10.0;
193  m_filledCtrl->Show( false );
194  break;
195 
196  case SHAPE_T::POLY:
197  SetTitle( _( "Polygon Properties" ) );
198  m_sizerLeft->Show( false );
199  m_filledCtrl->Show( true );
200  break;
201 
202  case SHAPE_T::RECT:
203  SetTitle( _( "Rectangle Properties" ) );
204 
205  m_filledCtrl->Show( true );
206  break;
207 
208  case SHAPE_T::SEGMENT:
209  SetTitle( _( "Line Segment Properties" ) );
210 
211  if( m_item->GetStart().x == m_item->GetEnd().x )
213  else
215 
216  m_filledCtrl->Show( false );
217  break;
218 
219  default:
220  break;
221  }
222 
223  if( m_item->GetShape() == SHAPE_T::ARC )
224  {
227  }
228  else if( m_flipStartEnd )
229  {
230  m_startX.SetValue( m_item->GetEnd().x );
231  m_startY.SetValue( m_item->GetEnd().y );
232  }
233  else
234  {
237  }
238 
239  if( m_item->GetShape() == SHAPE_T::CIRCLE )
240  {
242  }
243  else if( m_item->GetShape() == SHAPE_T::ARC )
244  {
247  }
248  else if( m_flipStartEnd )
249  {
250  m_endX.SetValue( m_item->GetStart().x );
251  m_endY.SetValue( m_item->GetStart().y );
252  }
253  else
254  {
255  m_endX.SetValue( m_item->GetEnd().x );
256  m_endY.SetValue( m_item->GetEnd().y );
257  }
258 
259  // For Bezier curve:
264 
265  m_filledCtrl->SetValue( m_item->IsFilled() );
266  m_locked->SetValue( m_item->IsLocked() );
268 
270 
271  return DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::TransferDataToWindow();
272 }
273 
274 
276 {
277  if( !DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::TransferDataFromWindow() )
278  return false;
279 
280  if( !m_thickness.Validate( 0, Millimeter2iu( 1000.0 ) ) )
281  return false;
282 
283  if( m_thickness.GetValue() == 0 && !m_filledCtrl->GetValue() )
284  {
285  DisplayError( this, _( "Line width may not be 0 for unfilled shapes." ) );
286  m_thicknessCtrl->SetFocus();
287  return false;
288  }
289 
291 
292  BOARD_COMMIT commit( m_parent );
293  commit.Modify( m_item );
294 
295  if( m_item->GetShape() == SHAPE_T::ARC )
296  {
297  m_item->SetArcStart( wxPoint( m_startX.GetValue(), m_startY.GetValue() ) );
298  }
299  else if( m_flipStartEnd )
300  {
303  }
304  else
305  {
308  }
309 
310  if( m_item->GetShape() == SHAPE_T::CIRCLE )
311  {
312  m_item->SetEnd( m_item->GetStart() + wxPoint( m_endX.GetValue(), 0 ) );
313  }
314  else if( m_item->GetShape() == SHAPE_T::ARC )
315  {
316  m_item->SetArcEnd( wxPoint( m_endX.GetValue(), m_endY.GetValue() ) );
317  }
318  else if( m_flipStartEnd )
319  {
322  }
323  else
324  {
327  }
328 
329  // For Bezier curve: Set the two control points
330  if( m_item->GetShape() == SHAPE_T::BEZIER )
331  {
334  }
335 
336  if( m_item->GetShape() == SHAPE_T::ARC )
337  {
339  m_item->SetAngle( m_AngleValue * 10.0, false );
340  }
341 
342  if( m_fp_item )
343  {
344  // We are editing a footprint; init the item coordinates relative to the footprint anchor.
347 
349  {
352  }
353  }
354 
355  bool wasLocked = m_item->IsLocked();
356 
357  m_item->SetFilled( m_filledCtrl->GetValue() );
358  m_item->SetLocked( m_locked->GetValue() );
360  m_item->SetLayer( ToLAYER_ID( layer ) );
361 
363 
364  commit.Push( _( "Modify drawing properties" ) );
365 
366  // Notify clients which treat locked and unlocked items differently (ie: POINT_EDITOR)
367  if( wasLocked != m_item->IsLocked() )
369 
371 
372  return true;
373 }
374 
375 
377 {
378  wxArrayString error_msgs;
379 
380  if( !DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::Validate() )
381  return false;
382 
383  // Type specific checks.
384  switch( m_item->GetShape() )
385  {
386  case SHAPE_T::ARC:
387  // Check angle of arc.
388  if( m_angle.GetValue() == 0 )
389  error_msgs.Add( _( "The arc angle cannot be zero." ) );
390 
392 
393  case SHAPE_T::CIRCLE:
394  // Check radius.
396  error_msgs.Add( _( "The radius cannot be zero." ) );
397  break;
398 
399  case SHAPE_T::RECT:
400  // Check for null rect.
402  error_msgs.Add( _( "The rectangle cannot be empty." ) );
403  break;
404 
405  case SHAPE_T::POLY:
406  case SHAPE_T::SEGMENT:
407  case SHAPE_T::BEZIER:
408  break;
409 
410  default:
411  wxASSERT_MSG( false, "DIALOG_GRAPHIC_ITEM_PROPERTIES::Validate not implemented for shape"
413  break;
414  }
415 
416  if( error_msgs.GetCount() )
417  {
418  HTML_MESSAGE_BOX dlg( this, _( "Error List" ) );
419  dlg.ListSet( error_msgs );
420  dlg.ShowModal();
421  }
422 
423  return error_msgs.GetCount() == 0;
424 }
void SetStartX(int x)
Definition: pcb_shape.h:129
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:271
wxPoint GetArcEnd() const
Definition: pcb_shape.cpp:417
COMMIT & Modify(EDA_ITEM *aItem)
Create an undo entry for an item that has been already modified.
Definition: commit.h:103
Arcs (with rounded ends)
bool IsFilled() const
Definition: pcb_shape.h:75
static const TOOL_EVENT SelectedEvent
Definition: actions.h:199
Bezier Curve.
void SetEnd0(const wxPoint &aPoint)
Definition: fp_shape.h:114
polygon (not yet used for tracks, but could be in microwave apps)
const wxPoint & GetEnd() const
Return the ending point of the graphic.
Definition: pcb_shape.h:134
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:192
This file is part of the common library.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:80
static LSET ForbiddenFootprintLayers()
Layers which are not allowed within footprint definitions.
Definition: lset.cpp:888
SHAPE_T GetShape() const
Definition: pcb_shape.h:110
void SetNotAllowedLayerSet(LSET aMask)
void SetFilled(bool aFlag)
Definition: pcb_shape.h:73
int GetRadius() const
Return the radius of this item.
Definition: pcb_shape.cpp:487
int GetWidth() const
Definition: pcb_shape.h:97
const wxPoint & GetBezierC2() const
Definition: pcb_shape.h:116
usual segment : line with rounded ends
int LAYER_NUM
This can be replaced with int and removed.
Definition: layer_ids.h:40
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
virtual void SetLocked(bool aLocked)
Modify the 'lock' status for of the item.
Definition: board_item.h:252
void SetBoardFrame(PCB_BASE_FRAME *aFrame)
virtual bool IsLocked() const
Definition: board_item.cpp:78
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:97
wxFloatingPointValidator< double > m_AngleValidator
This file contains miscellaneous commonly used macros and functions.
wxPoint GetArcStart() const
Definition: pcb_shape.h:156
LAYER_NUM GetLayerSelection() const
void Show(bool aShow, bool aResize=false)
Show/hide the label, widget and units label.
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:502
void SetEndY(int y)
Definition: pcb_shape.h:138
#define NULL
void SetBezierC2_0(const wxPoint &aPoint)
Definition: fp_shape.h:123
int ShowQuasiModal()
void ListSet(const wxString &aList)
Add a list of items.
const wxPoint & GetStart() const
Return the starting point of the graphic.
Definition: pcb_shape.h:124
const wxPoint & GetBezierC1() const
Definition: pcb_shape.h:113
#define _(s)
int SetLayerSelection(LAYER_NUM layer)
void SetCenter(const wxPoint &aCenterPoint)
Definition: pcb_shape.h:198
DIALOG_GRAPHIC_ITEM_PROPERTIES(PCB_BASE_EDIT_FRAME *aParent, BOARD_ITEM *aItem)
bool SetLayersHotkeys(bool value)
void SetEndX(int x)
Definition: pcb_shape.h:139
void SetStart0(const wxPoint &aPoint)
Definition: fp_shape.h:111
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
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...
Definition: unit_binder.cpp:92
void ShowGraphicItemPropertiesDialog(BOARD_ITEM *aItem)
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.
Common, abstract interface for edit frames.
virtual void SetValue(int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
double GetAngle() const
Definition: pcb_shape.h:107
void SetWidth(int aWidth)
Definition: pcb_shape.h:96
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true) override
Revert the commit by restoring the modified items state.
void RebuildBezierToSegmentsPointsList(int aMinSegLen)
Rebuild the m_BezierPoints vertex list that approximate the Bezier curve by a list of segments.
Definition: pcb_shape.cpp:359
void SetArcEnd(const wxPoint &aArcEndPoint)
Initialize the end arc point.
Definition: pcb_shape.h:193
virtual long long int GetValue()
Return the current value in Internal Units.
void SetBezierC1_0(const wxPoint &aPoint)
Definition: fp_shape.h:120
void SetStartY(int y)
Definition: pcb_shape.h:128
void SetCoordType(ORIGIN_TRANSFORMS::COORD_TYPES_T aCoordType)
Set the current origin transform mode.
Definition: unit_binder.h:177
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:54
void SetBezierC2(const wxPoint &aPoint)
Definition: pcb_shape.h:115
Class DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE.
const VECTOR2I GetArcCenter(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:454
segment with non rounded ends
static wxString ShowShape(SHAPE_T aShape)
Convert the enum #PCB_SHAPE_TYPE_T integer value to a wxString.
Definition: board_item.cpp:35
virtual void SetAngle(double aAngle, bool aUpdateEnd=true)
Set the angle for arcs, and normalizes it within the range 0 - 360 degrees.
Definition: pcb_shape.cpp:519
void PostEvent(const TOOL_EVENT &aEvent)
Put an event to the event queue to be processed at the end of event processing cycle.
static constexpr int Millimeter2iu(double mm)
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:171
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:905
void SetEnd(const wxPoint &aEnd)
Definition: pcb_shape.h:137
void SetBezierC1(const wxPoint &aPoint)
Definition: pcb_shape.h:112
void SetArcStart(const wxPoint &aArcStartPoint)
Initialize the start arc point.
Definition: pcb_shape.h:183
void OnInitDlg(wxInitDialogEvent &event) override
virtual void UpdateMsgPanel()
Redraw the message panel.