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 <pcb_shape.h>
36 #include <fp_shape.h>
37 #include <confirm.h>
38 #include <widgets/unit_binder.h>
39 
41 
43 {
44 private:
48 
55 
57 
58  wxFloatingPointValidator<double> m_AngleValidator;
59  double m_AngleValue;
60 
61 public:
64 
65 private:
66  bool TransferDataToWindow() override;
67  bool TransferDataFromWindow() override;
68 
69  void OnInitDlg( wxInitDialogEvent& event ) override
70  {
71  // Call the default wxDialog handler of a wxInitDialogEvent
73 
74  // Now all widgets have the size fixed, call FinishDialogSettings
76  }
77 
78  bool Validate() override;
79 
80  void onLayer( wxCommandEvent& event ) override;
81 };
82 
84  BOARD_ITEM* aItem ):
86  m_startX( aParent, m_startXLabel, m_startXCtrl, m_startXUnits ),
87  m_startY( aParent, m_startYLabel, m_startYCtrl, m_startYUnits ),
88  m_endX( aParent, m_endXLabel, m_endXCtrl, m_endXUnits ),
89  m_endY( aParent, m_endYLabel, m_endYCtrl, m_endYUnits ),
90  m_angle( aParent, m_angleLabel, m_angleCtrl, m_angleUnits ),
91  m_thickness( aParent, m_thicknessLabel, m_thicknessCtrl, m_thicknessUnits, true ),
92  m_bezierCtrl1X( aParent, m_BezierPointC1XLabel, m_BezierC1X_Ctrl, m_BezierPointC1XUnit ),
93  m_bezierCtrl1Y( aParent, m_BezierPointC1YLabel, m_BezierC1Y_Ctrl, m_BezierPointC1YUnit ),
94  m_bezierCtrl2X( aParent, m_BezierPointC2XLabel, m_BezierC2X_Ctrl, m_BezierPointC2XUnit ),
95  m_bezierCtrl2Y( aParent, m_BezierPointC2YLabel, m_BezierC2Y_Ctrl, m_BezierPointC2YUnit ),
96  m_flipStartEnd( false ),
97  m_AngleValidator( 1, &m_AngleValue ),
98  m_AngleValue( 0.0 )
99 {
100  m_parent = aParent;
101  m_item = dynamic_cast<PCB_SHAPE*>( aItem );
102  m_fp_item = dynamic_cast<FP_SHAPE*>( aItem );
103 
104  // Configure display origin transforms
113 
115  m_AngleValidator.SetRange( -360.0, 360.0 );
116  m_angleCtrl->SetValidator( m_AngleValidator );
117  m_AngleValidator.SetWindow( m_angleCtrl );
118 
119  // Do not allow locking items in the footprint editor
120  m_locked->Show( dynamic_cast<PCB_EDIT_FRAME*>( aParent ) != nullptr );
121 
122  // Configure the layers list selector
123  if( m_fp_item )
124  {
125  LSET forbiddenLayers = LSET::ForbiddenFootprintLayers();
126 
127  // If someone went to the trouble of setting the layer in a text editor, then there's
128  // very little sense in nagging them about it.
129  forbiddenLayers.set( m_fp_item->GetLayer(), false );
130 
131  m_LayerSelectionCtrl->SetNotAllowedLayerSet( forbiddenLayers );
132  }
133 
137 
139 
140  m_StandardButtonsSizerOK->SetDefault();
141 }
142 
143 
145 {
146  wxCHECK_RET( aItem != NULL, wxT( "ShowGraphicItemPropertiesDialog() error: NULL item" ) );
147 
148  DIALOG_GRAPHIC_ITEM_PROPERTIES dlg( this, aItem );
149  dlg.ShowQuasiModal();
150 }
151 
152 
154 {
155  if( !m_item )
156  return false;
157 
158  // Only an arc has a angle parameter. So do not show this parameter for other shapes
159  if( m_item->GetShape() != S_ARC )
160  m_angle.Show( false );
161 
162  // Only a Bezeier curve has control points. So do not show these parameters for other shapes
163  if( m_item->GetShape() != S_CURVE )
164  {
165  m_bezierCtrlPt1Label->Show( false );
166  m_bezierCtrl1X.Show( false );
167  m_bezierCtrl1Y.Show( false );
168  m_bezierCtrlPt2Label->Show( false );
169  m_bezierCtrl2X.Show( false );
170  m_bezierCtrl2Y.Show( false );
171  }
172 
173  // Change texts according to the segment shape:
174  switch( m_item->GetShape() )
175  {
176  case S_CIRCLE:
177  SetTitle( _( "Circle Properties" ) );
178  m_startPointLabel->SetLabel( _( "Center" ) );
179 
180  m_endPointLabel->SetLabel( _( "Radius" ) );
181  m_endXLabel->Show( false );
183 
184  m_endY.Show( false );
185 
186  m_filledCtrl->Show( true );
187  break;
188 
189  case S_ARC:
190  SetTitle( _( "Arc Properties" ) );
191  m_AngleValue = m_item->GetAngle() / 10.0;
192 
193  m_filledCtrl->Show( false );
194  break;
195 
196  case S_POLYGON:
197  {
198  LSET graphicPolygonsLayers = LSET::AllLayersMask();
199  graphicPolygonsLayers.reset( Edge_Cuts ).reset( F_CrtYd ).reset( B_CrtYd );
200 
201  SetTitle( _( "Polygon Properties" ) );
202  m_sizerLeft->Show( false );
203 
204  m_filledCtrl->Show( true );
205  m_filledCtrl->Enable( graphicPolygonsLayers.Contains( m_item->GetLayer() ) );
206 
207  // Prevent courtyard/edge cuts from being filled
208  if( !graphicPolygonsLayers.Contains( m_item->GetLayer() ) )
209  m_filledCtrl->SetValue( false );
210 
211  break;
212  }
213  case S_RECT:
214  SetTitle( _( "Rectangle Properties" ) );
215 
216  m_filledCtrl->Show( true );
217  break;
218 
219  case S_SEGMENT:
220  if( m_item->GetStart().x == m_item->GetEnd().x )
222  else
224 
225  SetTitle( _( "Line Segment Properties" ) );
226 
227  m_filledCtrl->Show( false );
228  break;
229 
230  default:
231  break;
232  }
233 
234  if( m_item->GetShape() == S_ARC )
235  {
238  }
239  else if( m_flipStartEnd )
240  {
241  m_startX.SetValue( m_item->GetEnd().x );
242  m_startY.SetValue( m_item->GetEnd().y );
243  }
244  else
245  {
248  }
249 
250  if( m_item->GetShape() == S_CIRCLE )
251  {
253  }
254  else if( m_item->GetShape() == S_ARC )
255  {
258  }
259  else if( m_flipStartEnd )
260  {
261  m_endX.SetValue( m_item->GetStart().x );
262  m_endY.SetValue( m_item->GetStart().y );
263  }
264  else
265  {
266  m_endX.SetValue( m_item->GetEnd().x );
267  m_endY.SetValue( m_item->GetEnd().y );
268  }
269 
270  // For Bezier curve:
275 
276  m_filledCtrl->SetValue( m_item->IsFilled() );
277  m_locked->SetValue( m_item->IsLocked() );
279 
281 
282  return DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::TransferDataToWindow();
283 }
284 
285 
287 {
288  if( !DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::TransferDataFromWindow() )
289  return false;
290 
291  if( !m_thickness.Validate( 0, Millimeter2iu( 1000.0 ) ) )
292  return false;
293 
294  if( m_thickness.GetValue() == 0 && !m_filledCtrl->GetValue() )
295  {
296  DisplayError( this, _( "Line width may not be 0 for unfilled shapes." ) );
297  m_thicknessCtrl->SetFocus();
298  return false;
299  }
300 
302 
303  BOARD_COMMIT commit( m_parent );
304  commit.Modify( m_item );
305 
306  if( m_item->GetShape() == S_ARC )
307  {
308  m_item->SetArcStart( wxPoint( m_startX.GetValue(), m_startY.GetValue() ) );
309  }
310  else if( m_flipStartEnd )
311  {
314  }
315  else
316  {
319  }
320 
321  if( m_item->GetShape() == S_CIRCLE )
322  {
323  m_item->SetEnd( m_item->GetStart() + wxPoint( m_endX.GetValue(), 0 ) );
324  }
325  else if( m_item->GetShape() == S_ARC )
326  {
327  m_item->SetArcEnd( wxPoint( m_endX.GetValue(), m_endY.GetValue() ) );
328  }
329  else if( m_flipStartEnd )
330  {
333  }
334  else
335  {
338  }
339 
340  // For Bezier curve: Set the two control points
341  if( m_item->GetShape() == S_CURVE )
342  {
345  }
346 
347  if( m_item->GetShape() == S_ARC )
348  {
350  m_item->SetAngle( m_AngleValue * 10.0, false );
351  }
352 
353  if( m_fp_item )
354  {
355  // We are editing a footprint; init the item coordinates relative to the footprint anchor.
358 
359  if( m_fp_item->GetShape() == S_CURVE )
360  {
363  }
364  }
365 
366  m_item->SetFilled( m_filledCtrl->GetValue() );
367  m_item->SetLocked( m_locked->GetValue() );
369  m_item->SetLayer( ToLAYER_ID( layer ) );
370 
372 
373  commit.Push( _( "Modify drawing properties" ) );
374 
376 
377  return true;
378 }
379 
380 
381 void DIALOG_GRAPHIC_ITEM_PROPERTIES::onLayer( wxCommandEvent& event )
382 {
383  if( m_item->GetShape() == S_POLYGON )
384  {
385  LSET graphicPolygonsLayers = LSET::AllLayersMask();
386  graphicPolygonsLayers.reset( Edge_Cuts ).reset( F_CrtYd ).reset( B_CrtYd );
387 
388  m_filledCtrl->Enable( graphicPolygonsLayers.Contains(
390 
391  // Prevent courtyard/edge cuts from being filled
392  if( !graphicPolygonsLayers.Contains(
394  m_filledCtrl->SetValue( false );
395  }
396 }
397 
398 
400 {
401  wxArrayString error_msgs;
402 
403  if( !DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::Validate() )
404  return false;
405 
406  // Type specific checks.
407  switch( m_item->GetShape() )
408  {
409  case S_ARC:
410  // Check angle of arc.
411  if( m_angle.GetValue() == 0 )
412  error_msgs.Add( _( "The arc angle cannot be zero." ) );
413 
415 
416  case S_CIRCLE:
417  // Check radius.
419  error_msgs.Add( _( "The radius cannot be zero." ) );
420  break;
421 
422  case S_RECT:
423  // Check for null rect.
425  error_msgs.Add( _( "The rectangle cannot be empty." ) );
426  break;
427 
428  case S_POLYGON:
429  case S_SEGMENT:
430  case S_CURVE:
431  break;
432 
433  default:
434  wxASSERT_MSG( false, "DIALOG_GRAPHIC_ITEM_PROPERTIES::Validate not implemented for shape"
436  break;
437  }
438 
439  if( error_msgs.GetCount() )
440  {
441  HTML_MESSAGE_BOX dlg( this, _( "Error List" ) );
442  dlg.ListSet( error_msgs );
443  dlg.ShowModal();
444  }
445 
446  return error_msgs.GetCount() == 0;
447 }
void SetStartX(int x)
Definition: pcb_shape.h:150
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:253
wxPoint GetArcEnd() const
Definition: pcb_shape.cpp:373
COMMIT & Modify(EDA_ITEM *aItem)
Create an undo entry for an item that has been already modified.
Definition: commit.h:103
bool IsFilled() const
Definition: pcb_shape.h:96
void SetEnd0(const wxPoint &aPoint)
Definition: fp_shape.h:114
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
Definition: pcb_shape.h:156
void SetBezControl2(const wxPoint &aPoint)
Definition: pcb_shape.h:135
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:194
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:82
static LSET ForbiddenFootprintLayers()
Layers which are not allowed within footprint definitions.
Definition: lset.cpp:888
void SetNotAllowedLayerSet(LSET aMask)
void SetFilled(bool aFlag)
Definition: pcb_shape.h:94
int GetRadius() const
Function GetRadius returns the radius of this item Has meaning only for arc and circle.
Definition: pcb_shape.h:201
void SetBezier0_C1(const wxPoint &aPoint)
Definition: fp_shape.h:120
bool Contains(PCB_LAYER_ID aLayer)
See if the layer set contains a PCB layer.
int GetWidth() const
Definition: pcb_shape.h:118
polygon (not yet used for tracks, but could be in microwave apps)
Definition: board_item.h:54
static wxString ShowShape(PCB_SHAPE_TYPE_T aShape)
Convert the enum PCB_SHAPE_TYPE_T integer value to a wxString.
Definition: board_item.cpp:31
usual segment : line with rounded ends
Definition: board_item.h:50
Arcs (with rounded ends)
Definition: board_item.h:52
#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:257
void SetBoardFrame(PCB_BASE_FRAME *aFrame)
segment with non rounded ends
Definition: board_item.h:51
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:98
void SetBezier0_C2(const wxPoint &aPoint)
Definition: fp_shape.h:123
wxFloatingPointValidator< double > m_AngleValidator
wxPoint GetArcStart() const
Definition: pcb_shape.h:179
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.
void SetEndY(int y)
Definition: pcb_shape.h:160
#define NULL
int ShowQuasiModal()
void ListSet(const wxString &aList)
Add a list of items.
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
Definition: pcb_shape.h:145
int SetLayerSelection(LAYER_NUM layer)
static LSET AllLayersMask()
Definition: lset.cpp:787
void SetCenter(const wxPoint &aCenterPoint)
For arcs and circles:
Definition: pcb_shape.h:229
HTML_MESSAGE_BOX.
DIALOG_GRAPHIC_ITEM_PROPERTIES(PCB_BASE_EDIT_FRAME *aParent, BOARD_ITEM *aItem)
void SetBezControl1(const wxPoint &aPoint)
Definition: pcb_shape.h:132
bool SetLayersHotkeys(bool value)
void SetEndX(int x)
Definition: pcb_shape.h:161
void SetStart0(const wxPoint &aPoint)
Definition: fp_shape.h:111
int LAYER_NUM
This can be replaced with int and removed.
void onLayer(wxCommandEvent &event) override
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:81
void ShowGraphicItemPropertiesDialog(BOARD_ITEM *aItem)
virtual bool IsLocked() const
Definition: board_item.h:249
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.
#define _(s)
Definition: 3d_actions.cpp:33
const wxPoint & GetBezControl2() const
Definition: pcb_shape.h:136
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:127
void SetWidth(int aWidth)
Definition: pcb_shape.h:117
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 Has me...
Definition: pcb_shape.cpp:315
void SetArcEnd(const wxPoint &aArcEndPoint)
Initialize the end arc point.
Definition: pcb_shape.h:222
virtual long long int GetValue()
Return the current value in Internal Units.
ring
Definition: board_item.h:53
void SetStartY(int y)
Definition: pcb_shape.h:149
void SetCoordType(ORIGIN_TRANSFORMS::COORD_TYPES_T aCoordType)
Set the current origin transform mode.
Definition: unit_binder.h:173
PCB_SHAPE_TYPE_T GetShape() const
Definition: pcb_shape.h:130
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:450
virtual void SetAngle(double aAngle, bool aUpdateEnd=true)
Sets the angle for arcs, and normalizes it within the range 0 - 360 degrees.
Definition: pcb_shape.cpp:465
Bezier Curve.
Definition: board_item.h:55
static constexpr int Millimeter2iu(double mm)
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:173
const wxPoint & GetBezControl1() const
Definition: pcb_shape.h:133
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:905
void SetEnd(const wxPoint &aEnd)
Definition: pcb_shape.h:159
void SetArcStart(const wxPoint &aArcStartPoint)
Initialize the start arc point.
Definition: pcb_shape.h:213
void OnInitDlg(wxInitDialogEvent &event) override
virtual void UpdateMsgPanel()
Redraw the message panel.