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->GetArcAngle() / 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 
224  {
225  m_startX.SetValue( m_item->GetEnd().x );
226  m_startY.SetValue( m_item->GetEnd().y );
227  }
228  else
229  {
232  }
233 
234  if( m_item->GetShape() == SHAPE_T::CIRCLE )
235  {
237  }
238  else if( m_flipStartEnd && m_item->GetShape() != SHAPE_T::ARC )
239  {
240  m_endX.SetValue( m_item->GetStart().x );
241  m_endY.SetValue( m_item->GetStart().y );
242  }
243  else
244  {
245  m_endX.SetValue( m_item->GetEnd().x );
246  m_endY.SetValue( m_item->GetEnd().y );
247  }
248 
249  // For Bezier curve:
254 
255  m_filledCtrl->SetValue( m_item->IsFilled() );
256  m_locked->SetValue( m_item->IsLocked() );
258 
260 
261  return DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::TransferDataToWindow();
262 }
263 
264 
266 {
267  if( !DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::TransferDataFromWindow() )
268  return false;
269 
270  if( !m_thickness.Validate( 0, Millimeter2iu( 1000.0 ) ) )
271  return false;
272 
273  if( m_thickness.GetValue() == 0 && !m_filledCtrl->GetValue() )
274  {
275  DisplayError( this, _( "Line width may not be 0 for unfilled shapes." ) );
276  m_thicknessCtrl->SetFocus();
277  return false;
278  }
279 
281 
282  BOARD_COMMIT commit( m_parent );
283  commit.Modify( m_item );
284 
286  {
289  }
290  else
291  {
294  }
295 
296  if( m_item->GetShape() == SHAPE_T::CIRCLE )
297  {
298  m_item->SetEnd( m_item->GetStart() + wxPoint( m_endX.GetValue(), 0 ) );
299  }
300  else if( m_flipStartEnd && m_item->GetShape() != SHAPE_T::ARC )
301  {
304  }
305  else
306  {
309  }
310 
311  // For Bezier curve: Set the two control points
312  if( m_item->GetShape() == SHAPE_T::BEZIER )
313  {
316  }
317 
318  if( m_item->GetShape() == SHAPE_T::ARC )
320 
321  if( m_fp_item )
322  {
323  // We are editing a footprint; init the item coordinates relative to the footprint anchor.
326 
327  if( m_item->GetShape() == SHAPE_T::ARC )
329 
330  if( m_item->GetShape() == SHAPE_T::BEZIER )
331  {
334  }
335  }
336 
337  bool wasLocked = m_item->IsLocked();
338 
339  m_item->SetFilled( m_filledCtrl->GetValue() );
340  m_item->SetLocked( m_locked->GetValue() );
342  m_item->SetLayer( ToLAYER_ID( layer ) );
343 
345 
346  commit.Push( _( "Modify drawing properties" ) );
347 
348  // Notify clients which treat locked and unlocked items differently (ie: POINT_EDITOR)
349  if( wasLocked != m_item->IsLocked() )
351 
353 
354  return true;
355 }
356 
357 
359 {
360  wxArrayString error_msgs;
361 
362  if( !DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::Validate() )
363  return false;
364 
365  // Type specific checks.
366  switch( m_item->GetShape() )
367  {
368  case SHAPE_T::ARC:
369  // Check angle of arc.
370  if( m_angle.GetValue() == 0 )
371  error_msgs.Add( _( "The arc angle cannot be zero." ) );
372 
374 
375  case SHAPE_T::CIRCLE:
376  // Check radius.
377  if( m_endX.GetValue() == 0 )
378  error_msgs.Add( _( "The radius cannot be zero." ) );
379  break;
380 
381  case SHAPE_T::RECT:
382  // Check for null rect.
384  error_msgs.Add( _( "The rectangle cannot be empty." ) );
385  break;
386 
387  case SHAPE_T::POLY:
388  case SHAPE_T::SEGMENT:
389  case SHAPE_T::BEZIER:
390  break;
391 
392  default:
394  break;
395  }
396 
397  if( error_msgs.GetCount() )
398  {
399  HTML_MESSAGE_BOX dlg( this, _( "Error List" ) );
400  dlg.ListSet( error_msgs );
401  dlg.ShowModal();
402  }
403 
404  return error_msgs.GetCount() == 0;
405 }
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:279
COMMIT & Modify(EDA_ITEM *aItem)
Create an undo entry for an item that has been already modified.
Definition: commit.h:103
static const TOOL_EVENT SelectedEvent
Definition: actions.h:200
int GetWidth() const
Definition: eda_shape.h:89
void SetEnd0(const wxPoint &aPoint)
Definition: fp_shape.h:114
void SetFilled(bool aFlag)
Definition: eda_shape.h:83
void SetEnd(const wxPoint &aEnd)
Definition: eda_shape.h:126
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:163
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:49
static LSET ForbiddenFootprintLayers()
Layers which are not allowed within footprint definitions.
Definition: lset.cpp:897
const wxPoint & GetStart() const
Return the starting point of the graphic.
Definition: eda_shape.h:97
void SetNotAllowedLayerSet(LSET aMask)
void SetStartY(int y)
Definition: eda_shape.h:107
double GetArcAngle() const
Definition: eda_shape.cpp:514
int LAYER_NUM
This can be replaced with int and removed.
Definition: layer_ids.h:41
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
void SetEndY(int y)
Definition: eda_shape.h:132
virtual void SetLocked(bool aLocked)
Modify the 'lock' status for of the item.
Definition: board_item.h:223
void SetBoardFrame(PCB_BASE_FRAME *aFrame)
virtual bool IsLocked() const
Definition: board_item.cpp:64
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
void SetBezierC1(const wxPoint &aPt)
Definition: eda_shape.h:144
This file contains miscellaneous commonly used macros and functions.
bool IsFilled() const
Definition: eda_shape.h:81
const wxPoint & GetBezierC1() const
Definition: eda_shape.h:145
LAYER_NUM GetLayerSelection() const
const wxPoint & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:122
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:505
void SetBezierC2_0(const wxPoint &aPoint)
Definition: fp_shape.h:120
int ShowQuasiModal()
void ListSet(const wxString &aList)
Add a list of items.
wxPoint GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition: pcb_shape.h:79
const wxPoint & GetBezierC2() const
Definition: eda_shape.h:148
#define UNIMPLEMENTED_FOR(type)
Definition: macros.h:120
#define _(s)
int SetLayerSelection(LAYER_NUM layer)
void SetWidth(int aWidth)
Definition: eda_shape.h:88
DIALOG_GRAPHIC_ITEM_PROPERTIES(PCB_BASE_EDIT_FRAME *aParent, BOARD_ITEM *aItem)
void SetCenter(const wxPoint &aCenter)
Definition: eda_shape.cpp:419
wxString SHAPE_T_asString() const
Definition: eda_shape.cpp:71
bool SetLayersHotkeys(bool value)
void SetStart0(const wxPoint &aPoint)
Definition: fp_shape.h:111
void SetEndX(int x)
Definition: eda_shape.h:138
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
void RebuildBezierToSegmentsPointsList(int aMinSegLen)
Rebuild the m_BezierPoints vertex list that approximate the Bezier curve by a list of segments.
Definition: eda_shape.cpp:366
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.
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 SetBezierC2(const wxPoint &aPt)
Definition: eda_shape.h:147
virtual long long int GetValue()
Return the current value in Internal Units.
void SetBezierC1_0(const wxPoint &aPoint)
Definition: fp_shape.h:117
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
SHAPE_T GetShape() const
Definition: eda_shape.h:92
Class DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE.
int GetRadius() const
Definition: eda_shape.cpp:466
void PostEvent(const TOOL_EVENT &aEvent)
Put an event to the event queue to be processed at the end of event processing cycle.
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:454
static constexpr int Millimeter2iu(double mm)
void SetCenter0(const wxPoint &aPt)
Definition: fp_shape.cpp:162
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:142
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:914
void SetStartX(int x)
Definition: eda_shape.h:113
void OnInitDlg(wxInitDialogEvent &event) override
virtual void UpdateMsgPanel()
Redraw the message panel.