KiCad PCB EDA Suite
dialog_pad_basicshapes_properties.cpp
Go to the documentation of this file.
1 
6 /*
7  * This program source code file is part of KiCad, a free EDA CAD application.
8  *
9  * Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
10  * Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, you may find one here:
24  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
25  * or you may search the http://www.gnu.org website for the version 2 license,
26  * or you may write to the Free Software Foundation, Inc.,
27  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
28  */
29 
30 #include <algorithm>
31 
32 #include <fctsys.h>
33 #include <common.h>
34 #include <confirm.h>
35 #include <trigo.h>
36 #include <pcb_base_frame.h>
37 #include <base_units.h>
38 #include <widgets/wx_grid.h>
39 #include <class_module.h>
40 #include <math/util.h> // for KiROUND
41 
42 #include <dialog_pad_properties.h>
43 #include <bitmaps.h>
44 
46  PCB_BASE_FRAME* aFrame,
47  DRAWSEGMENT* aShape ) :
49  m_shape( aShape ),
50  m_startX( aFrame, m_startXLabel, m_startXCtrl, m_startXUnits, true ),
51  m_startY( aFrame, m_startYLabel, m_startYCtrl, m_startYUnits, true ),
52  m_ctrl1X( aFrame, m_ctrl1XLabel, m_ctrl1XCtrl, m_ctrl1XUnits, true ),
53  m_ctrl1Y( aFrame, m_ctrl1YLabel, m_ctrl1YCtrl, m_ctrl1YUnits, true ),
54  m_ctrl2X( aFrame, m_ctrl2XLabel, m_ctrl2XCtrl, m_ctrl2XUnits, true ),
55  m_ctrl2Y( aFrame, m_ctrl2YLabel, m_ctrl2YCtrl, m_ctrl2YUnits, true ),
56  m_endX( aFrame, m_endXLabel, m_endXCtrl, m_endXUnits, true ),
57  m_endY( aFrame, m_endYLabel, m_endYCtrl, m_endYUnits, true ),
58  m_radius( aFrame, m_radiusLabel, m_radiusCtrl, m_radiusUnits, true ),
59  m_thickness( aFrame, m_thicknessLabel, m_thicknessCtrl, m_thicknessUnits, true )
60 {
62 
64 
65  m_sdbSizerOK->SetDefault();
66 
68 }
69 
71 {
72  if( m_shape == NULL )
73  return false;
74 
75  // Shows the text info about circle or ring only for S_CIRCLE shape
76  if( m_shape->GetShape() != S_CIRCLE )
77  m_staticTextInfo->Show( false );
78 
80 
81  switch( m_shape->GetShape() )
82  {
83  case S_SEGMENT: // Segment with rounded ends
84  SetTitle( _( "Segment" ) );
89  m_ctrl1X.Show( false, true );
90  m_ctrl1Y.Show( false, true );
91  m_ctrl2X.Show( false, true );
92  m_ctrl2Y.Show( false, true );
93  m_staticTextPosCtrl1->Show( false );
94  m_staticTextPosCtrl1->SetSize( 0, 0 );
95  m_staticTextPosCtrl2->Show( false );
96  m_staticTextPosCtrl2->SetSize( 0, 0 );
97  m_radius.Show( false );
98  break;
99 
100  case S_CURVE: // Bezier line
101  SetTitle( _( "Bezier" ) );
110  m_radius.Show( false );
111  break;
112 
113  case S_ARC: // Arc with rounded ends
114  SetTitle( _( "Arc" ) );
115  m_startX.SetValue( m_shape->GetEnd().x ); // confusingly, the start point of the arc
117  m_staticTextPosEnd->SetLabel( _( "Center" ) );
118  m_endX.SetValue( m_shape->GetStart().x ); // arc center
120  m_radiusLabel->SetLabel( _( "Angle:" ) );
123  m_ctrl1X.Show( false, true );
124  m_ctrl1Y.Show( false, true );
125  m_ctrl2X.Show( false, true );
126  m_ctrl2Y.Show( false, true );
127  m_staticTextPosCtrl1->Show( false );
128  m_staticTextPosCtrl1->SetSize( 0, 0 );
129  m_staticTextPosCtrl2->Show( false );
130  m_staticTextPosCtrl2->SetSize( 0, 0 );
131  break;
132 
133  case S_CIRCLE: // ring or circle
134  if( m_shape->GetWidth() )
135  SetTitle( _( "Ring" ) );
136  else
137  SetTitle( _( "Circle" ) );
138 
139  // End point does not exist for a circle or ring:
140  m_staticTextPosEnd->Show( false );
141  m_endX.Show( false );
142  m_endY.Show( false );
143 
144  // Circle center uses position controls:
145  m_staticTextPosStart->SetLabel( _( "Center:" ) );
149  m_ctrl1X.Show( false, true );
150  m_ctrl1Y.Show( false, true );
151  m_ctrl2X.Show( false, true );
152  m_ctrl2Y.Show( false, true );
153  m_staticTextPosCtrl1->Show( false );
154  m_staticTextPosCtrl1->SetSize( 0, 0 );
155  m_staticTextPosCtrl2->Show( false );
156  m_staticTextPosCtrl2->SetSize( 0, 0 );
157  break;
158 
159  case S_POLYGON: // polygon
160  // polygon has a specific dialog editor. So nothing here
161  break;
162 
163  default:
164  SetTitle( "Unknown basic shape" );
165  break;
166  }
167 
168  return true;
169 }
170 
172 {
173  // Transfer data out of the GUI.
175 
176  switch( m_shape->GetShape() )
177  {
178  case S_SEGMENT: // Segment with rounded ends
181  break;
182 
183  case S_CURVE: // Segment with rounded ends
188  break;
189 
190  case S_ARC: // Arc with rounded ends
191  // NB: we store the center of the arc in m_Start, and, confusingly,
192  // the start point in m_End
195  // arc angle
197  break;
198 
199  case S_CIRCLE: // ring or circle
202  break;
203 
204  case S_POLYGON: // polygon
205  // polygon has a specific dialog editor. So nothing here
206  break;
207 
208  default:
209  SetTitle( "Unknown basic shape" );
210  break;
211  }
212 
213  return true;
214 }
215 
216 
218  PCB_BASE_FRAME* aFrame,
219  DRAWSEGMENT* aShape ) :
221  m_shape( aShape ),
222  m_thickness( aFrame, m_thicknessLabel, m_thicknessCtrl, m_thicknessUnits, true )
223 {
224  if( !m_shape->GetPolyShape().IsEmpty() )
225  {
226  for( const VECTOR2I& pt : m_shape->GetPolyShape().Outline( 0 ).CPoints() )
227  m_currPoints.emplace_back( pt );
228  }
229 
230  m_addButton->SetBitmap( KiBitmap( small_plus_xpm ) );
231  m_deleteButton->SetBitmap( KiBitmap( trash_xpm ) );
232  m_warningIcon->SetBitmap( KiBitmap( dialog_warning_xpm ) );
233 
234  // Test for acceptable polygon (more than 2 corners, and not self-intersecting) and
235  // remove any redundant corners. A warning message is displayed if not OK.
236  doValidate( true );
237 
239 
240  m_sdbSizerOK->SetDefault();
241  GetSizer()->SetSizeHints( this );
242 
243  m_gridCornersList->Connect( wxEVT_GRID_CELL_CHANGING, wxGridEventHandler( DIALOG_PAD_PRIMITIVE_POLY_PROPS::onCellChanging ), NULL, this );
244 
245  // Now all widgets have the size fixed, call FinishDialogSettings
247 }
248 
249 
251 {
252  m_gridCornersList->Disconnect( wxEVT_GRID_CELL_CHANGING, wxGridEventHandler( DIALOG_PAD_PRIMITIVE_POLY_PROPS::onCellChanging ), NULL, this );
253 }
254 
255 
257 {
258  if( m_shape == NULL )
259  return false;
260 
262 
263  // Populates the list of corners
264  int extra_rows = m_currPoints.size() - m_gridCornersList->GetNumberRows();
265 
266  if( extra_rows > 0 )
267  {
268  m_gridCornersList->AppendRows( extra_rows );
269  }
270  else if( extra_rows < 0 )
271  {
272  extra_rows = -extra_rows;
273  m_gridCornersList->DeleteRows( 0, extra_rows );
274  }
275 
276  // enter others corner coordinates
277  wxString msg;
278  for( unsigned row = 0; row < m_currPoints.size(); ++row )
279  {
280  // Row label is "Corner x"
281  msg.Printf( "Corner %d", row+1 );
282  m_gridCornersList->SetRowLabelValue( row, msg );
283 
284  msg = StringFromValue( GetUserUnits(), m_currPoints[row].x, true, true );
285  m_gridCornersList->SetCellValue( row, 0, msg );
286 
287  msg = StringFromValue( GetUserUnits(), m_currPoints[row].y, true, true );
288  m_gridCornersList->SetCellValue( row, 1, msg );
289  }
290 
291  return true;
292 }
293 
295 {
296  if( !Validate() )
297  return false;
298 
301 
302  return true;
303 }
304 
305 
307 {
308  // Don't remove redundant corners while user is editing corner list
309  return doValidate( false );
310 }
311 
312 
313 // test for a valid polygon (a not self intersectiong polygon)
314 bool DIALOG_PAD_PRIMITIVE_POLY_PROPS::doValidate( bool aRemoveRedundantCorners )
315 {
317  return false;
318 
319  if( m_currPoints.size() < 3 )
320  {
321  m_warningText->SetLabel( _("Polygon must have at least 3 corners" ) );
322  m_warningText->Show( true );
323  m_warningIcon->Show( true );
324  return false;
325  }
326 
327  bool valid = true;
328 
329  SHAPE_LINE_CHAIN polyline( m_currPoints, true );
330 
331  // Remove redundant corners:
332  polyline.Simplify();
333 
334  if( polyline.PointCount() < 3 )
335  {
336  m_warningText->SetLabel( _( "Polygon must have at least 3 corners after simplification" ) );
337  valid = false;
338  }
339 
340  if( valid && polyline.SelfIntersecting() )
341  {
342  m_warningText->SetLabel( _( "Polygon can not be self-intersecting" ) );
343  valid = false;
344  }
345 
346  m_warningIcon->Show( !valid );
347  m_warningText->Show( !valid );
348 
349  if( aRemoveRedundantCorners )
350  {
351  if( polyline.PointCount() != (int) m_currPoints.size() )
352  { // Happens after simplification
353  m_currPoints.clear();
354 
355  for( const VECTOR2I& pt : polyline.CPoints() )
356  m_currPoints.emplace_back( pt );
357 
358  m_warningIcon->Show( true );
359  m_warningText->Show( true );
360  m_warningText->SetLabel( _( "Note: redundant corners removed" ) );
361  }
362  }
363 
364  return valid;
365 }
366 
367 
368 void DIALOG_PAD_PRIMITIVE_POLY_PROPS::OnButtonAdd( wxCommandEvent& event )
369 {
371  return;
372 
373  // Insert a new corner after the currently selected:
374  wxArrayInt selections = m_gridCornersList->GetSelectedRows();
375  int row = -1;
376 
377  if( m_gridCornersList->GetNumberRows() == 0 )
378  row = 0;
379  else if( selections.size() > 0 )
380  row = selections[ selections.size() - 1 ] + 1;
381  else
382  row = m_gridCornersList->GetGridCursorRow() + 1;
383 
384  if( row < 0 )
385  {
386  wxMessageBox( _( "Select a corner to add the new corner after." ) );
387  return;
388  }
389 
390  if( m_currPoints.size() == 0 || row >= (int) m_currPoints.size() )
391  m_currPoints.emplace_back( 0, 0 );
392  else
393  m_currPoints.insert( m_currPoints.begin() + row, wxPoint( 0, 0 ) );
394 
395  Validate();
397 
398  m_gridCornersList->ForceRefresh();
399  // Select the new row
400  m_gridCornersList->SelectRow( row, false );
401 
402  m_panelPoly->Refresh();
403 }
404 
406 {
408  return;
409 
410  wxArrayInt selections = m_gridCornersList->GetSelectedRows();
411 
412  if( m_gridCornersList->GetNumberRows() == 0 )
413  return;
414 
415  if( selections.size() == 0 && m_gridCornersList->GetGridCursorRow() >= 0 )
416  selections.push_back( m_gridCornersList->GetGridCursorRow() );
417 
418  if( selections.size() == 0 )
419  {
420  wxMessageBox( _( "Select a corner to delete." ) );
421  return;
422  }
423 
424  // remove corners:
425  std::sort( selections.begin(), selections.end() );
426 
427  for( int ii = selections.size()-1; ii >= 0 ; --ii )
428  m_currPoints.erase( m_currPoints.begin() + selections[ii] );
429 
430  Validate();
432 
433  m_gridCornersList->ForceRefresh();
434  // select the row previous to the last deleted row
435  m_gridCornersList->SelectRow( std::max( 0, selections[ 0 ] - 1 ) );
436 
437  m_panelPoly->Refresh();
438 }
439 
441 {
442  wxPaintDC dc( m_panelPoly );
443  wxSize dc_size = dc.GetSize();
444  dc.SetDeviceOrigin( dc_size.x / 2, dc_size.y / 2 );
445 
446  // Calculate a suitable scale to fit the available draw area
447  int minsize( Millimeter2iu( 0.5 ) );
448 
449  for( unsigned ii = 0; ii < m_currPoints.size(); ++ii )
450  {
451  minsize = std::max( minsize, std::abs( m_currPoints[ii].x ) );
452  minsize = std::max( minsize, std::abs( m_currPoints[ii].y ) );
453  }
454 
455  // The draw origin is the center of the window.
456  // Therefore the window size is twice the minsize just calculated
457  minsize *= 2;
458  minsize += m_thickness.GetValue();
459 
460  // Give a margin
461  double scale = std::min( double( dc_size.x ) / minsize, double( dc_size.y ) / minsize ) * 0.9;
462 
463  GRResetPenAndBrush( &dc );
464 
465  // Draw X and Y axis. This is particularly useful to show the
466  // reference position of basic shape
467  // Axis are drawn before the polygon to avoid masking segments on axis
468  GRLine( NULL, &dc, -dc_size.x, 0, dc_size.x, 0, 0, LIGHTBLUE ); // X axis
469  GRLine( NULL, &dc, 0, -dc_size.y, 0, dc_size.y, 0, LIGHTBLUE ); // Y axis
470 
471  // Draw polygon.
472  // The selected edge(s) are shown in selectcolor, the others in normalcolor.
473  EDA_COLOR_T normalcolor = WHITE;
474  EDA_COLOR_T selectcolor = RED;
475 
476  for( unsigned ii = 0; ii < m_currPoints.size(); ++ii )
477  {
478  EDA_COLOR_T color = normalcolor;
479 
480  if( m_gridCornersList->IsInSelection (ii, 0) ||
481  m_gridCornersList->IsInSelection (ii, 1) ||
482  m_gridCornersList->GetGridCursorRow() == (int)ii )
483  color = selectcolor;
484 
485  unsigned jj = ii + 1;
486 
487  if( jj >= m_currPoints.size() )
488  jj = 0;
489 
491  }
492 
493  event.Skip();
494 }
495 
497 {
498  m_panelPoly->Refresh();
499  event.Skip();
500 }
501 
502 void DIALOG_PAD_PRIMITIVE_POLY_PROPS::onGridSelect( wxGridRangeSelectEvent& event )
503 {
504  m_panelPoly->Refresh();
505 }
506 
508 {
509  int row = event.GetRow();
510  int col = event.GetCol();
511  wxString msg = event.GetString();
512 
513  if( msg.IsEmpty() )
514  return;
515 
516  if( col == 0 ) // Set the X value
517  m_currPoints[row].x = ValueFromString( GetUserUnits(), msg, true );
518  else // Set the Y value
519  m_currPoints[row].y = ValueFromString( GetUserUnits(), msg, true );
520 
521  Validate();
522 
523  m_panelPoly->Refresh();
524 }
525 
526 
527 // A dialog to apply geometry transforms to a shape or set of shapes
528 // (move, rotate around origin, scaling factor, duplication).
530  PCB_BASE_FRAME* aFrame,
531  std::vector<std::shared_ptr<DRAWSEGMENT>>& aList,
532  bool aShowDuplicate ) :
534  m_list( aList ),
535  m_vectorX( aFrame, m_xLabel, m_xCtrl, m_xUnits, true ),
536  m_vectorY( aFrame, m_yLabel, m_yCtrl, m_yUnits, true ),
537  m_rotation( aFrame, m_rotationLabel, m_rotationCtrl, m_rotationUnits )
538 {
540 
541  if( !aShowDuplicate ) // means no duplicate transform
542  {
543  m_staticTextDupCnt->Show( false );
544  m_spinCtrlDuplicateCount->Show( false );
545  }
546 
547  m_sdbSizerOK->SetDefault();
548  GetSizer()->SetSizeHints( this );
549 }
550 
551 
552 // A helper function in geometry transform
553 inline void geom_transf( wxPoint& aCoord, wxPoint& aMove, double aScale, double aRotation )
554 {
555  aCoord.x = KiROUND( aCoord.x * aScale );
556  aCoord.y = KiROUND( aCoord.y * aScale );
557  aCoord += aMove;
558  RotatePoint( &aCoord, aRotation );
559 }
560 
561 
562 void DIALOG_PAD_PRIMITIVES_TRANSFORM::Transform( std::vector<std::shared_ptr<DRAWSEGMENT>>* aList,
563  int aDuplicateCount )
564 {
565  wxPoint move_vect( m_vectorX.GetValue(), m_vectorY.GetValue() );
566  double rotation = m_rotation.GetValue();
568 
569  // Avoid too small / too large scale, which could create issues:
570  if( scale < 0.01 )
571  scale = 0.01;
572 
573  if( scale > 100.0 )
574  scale = 100.0;
575 
576  // Transform shapes
577  // shapes are scaled, then moved then rotated.
578  // if aList != NULL, the initial shape will be duplicated, and transform
579  // applied to the duplicated shape
580 
581  wxPoint currMoveVect = move_vect;
582  double curr_rotation = rotation;
583 
584  do {
585  for( unsigned idx = 0; idx < m_list.size(); ++idx )
586  {
587  std::shared_ptr<DRAWSEGMENT> shape;
588 
589  if( aList == NULL )
590  shape = m_list[idx];
591  else
592  {
593  aList->emplace_back( std::make_shared<DRAWSEGMENT>( *m_list[idx] ) );
594  shape = aList->back();
595  }
596 
597  // Transform parameters common to all shape types (some can be unused)
598  shape->SetWidth( KiROUND( shape->GetWidth() * scale ) );
599  shape->Move( currMoveVect );
600  shape->Scale( scale );
601  shape->Rotate( wxPoint( 0, 0 ), curr_rotation );
602  }
603 
604  // Prepare new transform on duplication:
605  // Each new item is rotated (or moved) by the transform from the last duplication
606  curr_rotation += rotation;
607  currMoveVect += move_vect;
608  } while( aList && --aDuplicateCount > 0 );
609 }
610 
const BITMAP_OPAQUE trash_xpm[1]
Definition: trash.cpp:46
void GRResetPenAndBrush(wxDC *DC)
Definition: gr_basic.cpp:122
Implementation of conversion functions that require both schematic and board internal units.
This file is part of the common library.
Class DIALOG_PAD_PRIMITIVE_POLY_PROPS_BASE.
STROKE_T GetShape() const
int color
Definition: DXF_plotter.cpp:61
polygon (not yet used for tracks, but could be in microwave apps)
bool IsEmpty() const
Returns true if the set is empty (no polygons at all)
void FinishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
double DoubleValueFromString(EDA_UNITS aUnits, const wxString &aTextValue, bool aUseMils, EDA_DATA_TYPE aType)
Function DoubleValueFromString converts aTextValue to a double.
Definition: base_units.cpp:346
usual segment : line with rounded ends
void OnButtonDelete(wxCommandEvent &event) override
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
int PointCount() const
Function PointCount()
const OPT< INTERSECTION > SelfIntersecting() const
Function SelfIntersecting()
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:114
bool TransferDataFromWindow() override
Function TransferDataFromWindow Transfer data out of the GUI.
Classes used in Pcbnew, CvPcb and GerbView.
EDA_UNITS GetUserUnits() const
Definition: dialog_shim.h:131
Class DIALOG_PAD_PRIMITIVES_TRANSFORM_BASE.
SHAPE_LINE_CHAIN & Simplify()
Function Simplify()
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Construct a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:80
DIALOG_PAD_PRIMITIVES_TRANSFORM(wxWindow *aParent, PCB_BASE_FRAME *aFrame, std::vector< std::shared_ptr< DRAWSEGMENT >> &aList, bool aShowDuplicate)
bool TransferDataToWindow() override
Function TransferDataToWindow Transfer data into the GUI.
void geom_transf(wxPoint &aCoord, wxPoint &aMove, double aScale, double aRotation)
void Show(bool aShow, bool aResize=false)
Function Show Shows/hides the label, widget and units label.
bool TransferDataToWindow() override
Function TransferDataToWindow Transfer data into the GUI.
#define NULL
void onGridSelect(wxGridRangeSelectEvent &event) override
const std::vector< VECTOR2I > & CPoints() const
const BITMAP_OPAQUE dialog_warning_xpm[1]
SHAPE_LINE_CHAIN & Outline(int aIndex)
Returns the reference to aIndex-th outline in the set
Arcs (with rounded ends)
void Transform(std::vector< std::shared_ptr< DRAWSEGMENT >> *aList=NULL, int aDuplicateCount=0)
Apply geometric transform (rotation, move, scale) defined in dialog aDuplicate = 1 .
void onPolyPanelResize(wxSizeEvent &event) override
DIALOG_PAD_PRIMITIVES_PROPERTIES(wxWindow *aParent, PCB_BASE_FRAME *aFrame, DRAWSEGMENT *aShape)
DIALOG_PAD_PRIMITIVE_POLY_PROPS(wxWindow *aParent, PCB_BASE_FRAME *aFrame, DRAWSEGMENT *aShape)
int GetRadius() const
Function GetRadius returns the radius of this item Has meaning only for arc and circle.
SHAPE_POLY_SET & GetPolyShape()
Bezier Curve.
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:174
void GRLine(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color, wxPenStyle aStyle)
Definition: gr_basic.cpp:232
Definition: color4d.h:59
void onPaintPolyPanel(wxPaintEvent &event) override
int GetWidth() const
void SetStart(const wxPoint &aStart)
EDA_COLOR_T
Legacy color enumeration.
Definition: color4d.h:41
void SetPolyPoints(const std::vector< wxPoint > &aPoints)
void OnButtonAdd(wxCommandEvent &event) override
Definition: color4d.h:48
double GetAngle() const
const int scale
#define _(s)
Definition: 3d_actions.cpp:33
SHAPE_LINE_CHAIN.
std::vector< std::shared_ptr< DRAWSEGMENT > > & m_list
virtual void SetValue(int aValue)
Function SetValue Sets new value (in Internal Units) for the text field, taking care of units convers...
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
const wxPoint & GetBezControl2() const
The common library.
virtual long long int GetValue()
Function GetValue Returns the current value in Internal Units.
void SetEnd(const wxPoint &aEnd)
void SetAngle(double aAngle)
Function SetAngle sets the angle for arcs, and normalizes it within the range 0 - 360 degrees.
const wxPoint & GetBezControl1() const
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
bool doValidate(bool aRemoveRedundantCorners)
const BITMAP_OPAQUE small_plus_xpm[1]
Definition: small_plus.cpp:20
wxString StringFromValue(EDA_UNITS aUnits, double aValue, bool aAddUnitSymbol, bool aUseMils, EDA_DATA_TYPE aType)
Function StringFromValue returns the string from aValue according to units (inch, mm ....
Definition: base_units.cpp:233
PCB_BASE_FRAME basic PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
bool TransferDataFromWindow() override
Function TransferDataFromWindow Transfer data out of the GUI.
long long int ValueFromString(EDA_UNITS aUnits, const wxString &aTextValue, bool aUseMils, EDA_DATA_TYPE aType)
Function ValueFromString converts aTextValue in aUnits to internal units used by the application.
Definition: base_units.cpp:471
virtual void SetUnits(EDA_UNITS aUnits, bool aUseMils=false)
Function SetUnits Normally not needed (as the UNIT_BINDER inherits from the parent frame),...
Definition: unit_binder.cpp:79
bool Validate() override
test for a valid polygon (a not self intersectiong polygon)
Class DIALOG_PAD_PRIMITIVES_PROPERTIES_BASE.
void SetBezControl1(const wxPoint &aPoint)
void SetWidth(int aWidth)