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-2017 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 <pcbnew.h>
36 #include <trigo.h>
37 #include <macros.h>
38 #include <pcb_base_frame.h>
39 #include <base_units.h>
40 #include <widgets/wx_grid.h>
41 #include <class_board.h>
42 #include <class_module.h>
43 
44 #include <dialog_pad_properties.h>
45 #include <bitmaps.h>
46 
48  PCB_BASE_FRAME* aFrame,
49  PAD_CS_PRIMITIVE * aShape ) :
51  m_shape( aShape ),
52  m_startX( aFrame, m_startXLabel, m_startXCtrl, m_startXUnits, true ),
53  m_startY( aFrame, m_startYLabel, m_startYCtrl, m_startYUnits, true ),
54  m_endX( aFrame, m_endXLabel, m_endXCtrl, m_endXUnits, true ),
55  m_endY( aFrame, m_endYLabel, m_endYCtrl, m_endYUnits, true ),
56  m_radius( aFrame, m_radiusLabel, m_radiusCtrl, m_radiusUnits, true ),
57  m_thickness( aFrame, m_thicknessLabel, m_thicknessCtrl, m_thicknessUnits, true )
58 {
60 
61  m_sdbSizerOK->SetDefault();
62 
64 }
65 
67 {
68  if( m_shape == NULL )
69  return false;
70 
71  // Shows the text info about circle or ring only for S_CIRCLE shape
72  if( m_shape->m_Shape != S_CIRCLE )
73  m_staticTextInfo->Show( false );
74 
76 
77  switch( m_shape->m_Shape )
78  {
79  case S_SEGMENT: // Segment with rounded ends
80  SetTitle( _( "Segment" ) );
85  m_radius.Show( false );
86  break;
87 
88  case S_ARC: // Arc with rounded ends
89  SetTitle( _( "Arc" ) );
90  m_staticTextPosEnd->SetLabel( _( "Center" ) );
91  m_startX.SetValue( m_shape->m_Start.x ); // Start point of arc
93  m_endX.SetValue( m_shape->m_End.x ); // arc center
95  m_radiusLabel->SetLabel( _( "Angle:" ) );
98  break;
99 
100  case S_CIRCLE: // ring or circle
101  if( m_shape->m_Thickness )
102  SetTitle( _( "Ring" ) );
103  else
104  SetTitle( _( "Circle" ) );
105 
106  // End point does not exist for a circle or ring:
107  m_staticTextPosEnd->Show( false );
108  m_endX.Show( false );
109  m_endY.Show( false );
110 
111  // Circle center uses position controls:
112  m_staticTextPosStart->SetLabel( _( "Center:" ) );
116  break;
117 
118  case S_POLYGON: // polygon
119  // polygon has a specific dialog editor. So nothing here
120  break;
121 
122  default:
123  SetTitle( "Unknown basic shape" );
124  break;
125  }
126 
127  return true;
128 }
129 
131 {
132  // Transfer data out of the GUI.
134 
135  switch( m_shape->m_Shape )
136  {
137  case S_SEGMENT: // Segment with rounded ends
142  break;
143 
144  case S_ARC: // Arc with rounded ends
145  // Start point of arc
148  // arc center
151  // arc angle
153  break;
154 
155  case S_CIRCLE: // ring or circle
159  break;
160 
161  case S_POLYGON: // polygon
162  // polygon has a specific dialog editor. So nothing here
163  break;
164 
165  default:
166  SetTitle( "Unknown basic shape" );
167  break;
168  }
169 
170  return true;
171 }
172 
173 
175  PCB_BASE_FRAME* aFrame,
176  PAD_CS_PRIMITIVE * aShape ) :
178  m_shape( aShape ),
179  m_currshape( *m_shape ),
181 {
182  m_addButton->SetBitmap( KiBitmap( small_plus_xpm ) );
183  m_deleteButton->SetBitmap( KiBitmap( trash_xpm ) );
184  m_warningIcon->SetBitmap( KiBitmap( dialog_warning_xpm ) );
185 
186  // Test for acceptable polygon (more than 2 corners, and not self-intersecting) and
187  // remove any redundant corners. A warning message is displayed if not OK.
188  doValidate( true );
189 
191 
192  m_sdbSizerOK->SetDefault();
193  GetSizer()->SetSizeHints( this );
194 
195  // TODO: move wxEVT_GRID_CELL_CHANGING in wxFormbuilder, when it support it
196  m_gridCornersList->Connect( wxEVT_GRID_CELL_CHANGING, wxGridEventHandler( DIALOG_PAD_PRIMITIVE_POLY_PROPS::onCellChanging ), NULL, this );
197 }
198 
199 
201 {
202  m_gridCornersList->Disconnect( wxEVT_GRID_CELL_CHANGING, wxGridEventHandler( DIALOG_PAD_PRIMITIVE_POLY_PROPS::onCellChanging ), NULL, this );
203 }
204 
205 
207 {
208  if( m_shape == NULL )
209  return false;
210 
212 
213  // Populates the list of corners
214  int extra_rows = m_currshape.m_Poly.size() - m_gridCornersList->GetNumberRows();
215 
216  if( extra_rows > 0 )
217  {
218  m_gridCornersList->AppendRows( extra_rows );
219  }
220  else if( extra_rows < 0 )
221  {
222  extra_rows = -extra_rows;
223  m_gridCornersList->DeleteRows( 0, extra_rows );
224  }
225 
226  // enter others corner coordinates
227  wxString msg;
228  for( unsigned row = 0; row < m_currshape.m_Poly.size(); ++row )
229  {
230  // Row label is "Corner x"
231  msg.Printf( "Corner %d", row+1 );
232  m_gridCornersList->SetRowLabelValue( row, msg );
233 
234  msg = StringFromValue( GetUserUnits(), m_currshape.m_Poly[row].x, true, true );
235  m_gridCornersList->SetCellValue( row, 0, msg );
236 
237  msg = StringFromValue( GetUserUnits(), m_currshape.m_Poly[row].y, true, true );
238  m_gridCornersList->SetCellValue( row, 1, msg );
239  }
240 
241  return true;
242 }
243 
245 {
246  if( !Validate() )
247  return false;
248 
250 
251  *m_shape = m_currshape;
252 
253  return true;
254 }
255 
256 
258 {
259  // Don't remove redundant corners while user is editing corner list
260  return doValidate( false );
261 }
262 
263 
264 // test for a valid polygon (a not self intersectiong polygon)
265 bool DIALOG_PAD_PRIMITIVE_POLY_PROPS::doValidate( bool aRemoveRedundantCorners )
266 {
268  return false;
269 
270  if( m_currshape.m_Poly.size() < 3 )
271  {
272  m_warningText->SetLabel( _("Polygon must have at least 3 corners" ) );
273  m_warningText->Show( true );
274  m_warningIcon->Show( true );
275  return false;
276  }
277 
278  bool valid = true;
279 
280  SHAPE_LINE_CHAIN polyline;
281 
282  for( unsigned ii = 0; ii < m_currshape.m_Poly.size(); ++ii )
283  polyline.Append( m_currshape.m_Poly[ii].x, m_currshape.m_Poly[ii].y );
284 
285  // The polyline describes a polygon: close it.
286  polyline.SetClosed( true );
287 
288  // Remove redundant corners:
289  polyline.Simplify();
290 
291  if( polyline.PointCount() < 3 )
292  {
293  m_warningText->SetLabel( _("Polygon must have at least 3 corners after simplification" ) );
294  valid = false;
295  }
296 
297  if( valid && polyline.SelfIntersecting() )
298  {
299  m_warningText->SetLabel( _("Polygon may not be self-intersecting" ) );
300  valid = false;
301  }
302 
303  m_warningIcon->Show( !valid );
304  m_warningText->Show( !valid );
305 
306  if( aRemoveRedundantCorners )
307  {
308  if( polyline.PointCount() != (int)m_currshape.m_Poly.size() )
309  { // Happens after simplification
310  m_currshape.m_Poly.clear();
311 
312  for( int ii = 0; ii < polyline.PointCount(); ++ii )
313  m_currshape.m_Poly.push_back( wxPoint( polyline.CPoint( ii ).x, polyline.CPoint( ii ).y ) );
314 
315  m_warningIcon->Show( true );
316  m_warningText->Show( true );
317  m_warningText->SetLabel( _("Note: redundant corners removed" ) );
318  }
319  }
320 
321  return valid;
322 }
323 
324 
325 void DIALOG_PAD_PRIMITIVE_POLY_PROPS::OnButtonAdd( wxCommandEvent& event )
326 {
328  return;
329 
330  // Insert a new corner after the currently selected:
331  wxArrayInt selections = m_gridCornersList->GetSelectedRows();
332  int row = -1;
333 
334  if( m_gridCornersList->GetNumberRows() == 0 )
335  row = 0;
336  else if( selections.size() > 0 )
337  row = selections[ selections.size() - 1 ] + 1;
338  else
339  row = m_gridCornersList->GetGridCursorRow() + 1;
340 
341  if( row < 0 )
342  {
343  wxMessageBox( _( "Select a corner to add the new corner after." ) );
344  return;
345  }
346 
347  if( m_currshape.m_Poly.size() == 0 || row >= (int) m_currshape.m_Poly.size() )
348  m_currshape.m_Poly.push_back( wxPoint( 0, 0 ) );
349  else
350  m_currshape.m_Poly.insert( m_currshape.m_Poly.begin() + row, wxPoint( 0, 0 ) );
351 
352  Validate();
354 
355  m_gridCornersList->ForceRefresh();
356  // Select the new row
357  m_gridCornersList->SelectRow( row, false );
358 
359  m_panelPoly->Refresh();
360 }
361 
363 {
365  return;
366 
367  wxArrayInt selections = m_gridCornersList->GetSelectedRows();
368 
369  if( m_gridCornersList->GetNumberRows() == 0 )
370  return;
371 
372  if( selections.size() == 0 && m_gridCornersList->GetGridCursorRow() >= 0 )
373  selections.push_back( m_gridCornersList->GetGridCursorRow() );
374 
375  if( selections.size() == 0 )
376  {
377  wxMessageBox( _( "Select a corner to delete." ) );
378  return;
379  }
380 
381  // remove corners:
382  std::sort( selections.begin(), selections.end() );
383 
384  for( int ii = selections.size()-1; ii >= 0 ; --ii )
385  m_currshape.m_Poly.erase( m_currshape.m_Poly.begin() + selections[ii] );
386 
387  Validate();
389 
390  m_gridCornersList->ForceRefresh();
391  // select the row previous to the last deleted row
392  m_gridCornersList->SelectRow( std::max( 0, selections[ 0 ] - 1 ) );
393 
394  m_panelPoly->Refresh();
395 }
396 
398 {
399  wxPaintDC dc( m_panelPoly );
400  wxSize dc_size = dc.GetSize();
401  dc.SetDeviceOrigin( dc_size.x / 2, dc_size.y / 2 );
402 
403  // Calculate a suitable scale to fit the available draw area
404  wxSize minsize;
405 
406  for( unsigned ii = 0; ii < m_currshape.m_Poly.size(); ++ii )
407  {
408  minsize.x = std::max( minsize.x, std::abs( m_currshape.m_Poly[ii].x ) );
409  minsize.y = std::max( minsize.y, std::abs( m_currshape.m_Poly[ii].y ) );
410  }
411 
412  // The draw origin is the center of the window.
413  // Therefore the window size is twice the minsize just calculated
414  minsize.x *= 2;
415  minsize.y *= 2;
416  minsize.x += m_currshape.m_Thickness;
417  minsize.y += m_currshape.m_Thickness;
418 
419  // Avoid null or too small size:
420  int mindim = Millimeter2iu( 0.5 );
421 
422  if( minsize.x < mindim )
423  minsize.x = mindim;
424 
425  if( minsize.y < mindim )
426  minsize.y = mindim;
427 
428  double scale = std::min( (double) dc_size.x / minsize.x, (double) dc_size.y / minsize.y );
429 
430  // Give a margin
431  scale *= 0.9;
432  dc.SetUserScale( scale, scale );
433 
434  GRResetPenAndBrush( &dc );
435 
436  // Draw X and Y axis. This is particularly useful to show the
437  // reference position of basic shape
438  // Axis are drawn before the polygon to avoid masking segments on axis
439  GRLine( NULL, &dc, -int( dc_size.x/scale ), 0, int( dc_size.x/scale ), 0, 0, LIGHTBLUE ); // X axis
440  GRLine( NULL, &dc, 0, -int( dc_size.y/scale ), 0, int( dc_size.y/scale ), 0, LIGHTBLUE ); // Y axis
441 
442  // Draw polygon.
443  // The selected edge(s) are shown in selectcolor, the others in normalcolor.
444  EDA_COLOR_T normalcolor = WHITE;
445  EDA_COLOR_T selectcolor = RED;
446 
447  for( unsigned ii = 0; ii < m_currshape.m_Poly.size(); ++ii )
448  {
449  EDA_COLOR_T color = normalcolor;
450 
451  if( m_gridCornersList->IsInSelection (ii, 0) ||
452  m_gridCornersList->IsInSelection (ii, 1) ||
453  m_gridCornersList->GetGridCursorRow() == (int)ii )
454  color = selectcolor;
455 
456  unsigned jj = ii + 1;
457 
458  if( jj >= m_currshape.m_Poly.size() )
459  jj = 0;
460 
461  GRLine( NULL, &dc, m_currshape.m_Poly[ii], m_currshape.m_Poly[jj], m_currshape.m_Thickness, color );
462  }
463 
464  event.Skip();
465 }
466 
468 {
469  m_panelPoly->Refresh();
470  event.Skip();
471 }
472 
473 void DIALOG_PAD_PRIMITIVE_POLY_PROPS::onGridSelect( wxGridRangeSelectEvent& event )
474 {
475  m_panelPoly->Refresh();
476 }
477 
479 {
480  int row = event.GetRow();
481  int col = event.GetCol();
482  wxString msg = event.GetString();
483 
484  if( msg.IsEmpty() )
485  return;
486 
487  if( col == 0 ) // Set the X value
488  m_currshape.m_Poly[row].x = ValueFromString( GetUserUnits(), msg, true );
489  else // Set the Y value
490  m_currshape.m_Poly[row].y = ValueFromString( GetUserUnits(), msg, true );
491 
493 
494  Validate();
495 
496  m_panelPoly->Refresh();
497 }
498 
499 
500 // A dialog to apply geometry transforms to a shape or set of shapes
501 // (move, rotate around origin, scaling factor, duplication).
503  PCB_BASE_FRAME* aFrame,
504  std::vector<PAD_CS_PRIMITIVE*>& aList,
505  bool aShowDuplicate ) :
507  m_list( aList ),
508  m_vectorX( aFrame, m_xLabel, m_xCtrl, m_xUnits, true ),
509  m_vectorY( aFrame, m_yLabel, m_yCtrl, m_yUnits, true ),
510  m_rotation( aFrame, m_rotationLabel, m_rotationCtrl, m_rotationUnits )
511 {
513 
514  if( !aShowDuplicate ) // means no duplicate transform
515  {
516  m_staticTextDupCnt->Show( false );
517  m_spinCtrlDuplicateCount->Show( false );
518  }
519 
520  m_sdbSizerOK->SetDefault();
521  GetSizer()->SetSizeHints( this );
522 }
523 
524 
525 // A helper function in geometry transform
526 inline void geom_transf( wxPoint& aCoord, wxPoint& aMove, double aScale, double aRotation )
527 {
528  aCoord.x = KiROUND( aCoord.x * aScale );
529  aCoord.y = KiROUND( aCoord.y * aScale );
530  aCoord += aMove;
531  RotatePoint( &aCoord, aRotation );
532 }
533 
534 
535 void DIALOG_PAD_PRIMITIVES_TRANSFORM::Transform( std::vector<PAD_CS_PRIMITIVE>* aList, int aDuplicateCount )
536 {
537  wxPoint move_vect( m_vectorX.GetValue(), m_vectorY.GetValue() );
538  double rotation = m_rotation.GetValue() / 10.0;
539  double scale = DoubleValueFromString( UNSCALED_UNITS, m_scaleCtrl->GetValue() );
540 
541  // Avoid too small / too large scale, which could create issues:
542  if( scale < 0.01 )
543  scale = 0.01;
544 
545  if( scale > 100.0 )
546  scale = 100.0;
547 
548  // Transform shapes
549  // shapes are scaled, then moved then rotated.
550  // if aList != NULL, the initial shape will be duplicated, and transform
551  // applied to the duplicated shape
552 
553  wxPoint currMoveVect = move_vect;
554  double curr_rotation = rotation;
555 
556  do {
557  for( unsigned idx = 0; idx < m_list.size(); ++idx )
558  {
559  PAD_CS_PRIMITIVE* shape;
560 
561  if( aList == NULL )
562  shape = m_list[idx];
563  else
564  {
565  PAD_CS_PRIMITIVE new_shape( *m_list[idx] );
566  aList->push_back( new_shape );
567  shape = &aList->back();
568  }
569 
570  // Transform parameters common to all shape types (some can be unused)
571  shape->m_Thickness = KiROUND( shape->m_Thickness * scale );
572  geom_transf( shape->m_Start, currMoveVect, scale, curr_rotation );
573  geom_transf( shape->m_End, currMoveVect, scale, curr_rotation );
574 
575  // specific parameters:
576  switch( shape->m_Shape )
577  {
578  case S_SEGMENT: // Segment with rounded ends
579  break;
580 
581  case S_ARC: // Arc with rounded ends
582  break;
583 
584  case S_CIRCLE: // ring or circle
585  shape->m_Radius = KiROUND( shape->m_Radius * scale );
586  break;
587 
588  case S_POLYGON: // polygon
589  for( unsigned ii = 0; ii < shape->m_Poly.size(); ++ii )
590  geom_transf( shape->m_Poly[ii], currMoveVect, scale, curr_rotation );
591  break;
592 
593  default:
594  break;
595  }
596  }
597 
598  // Prepare new transform on duplication:
599  // Each new item is rotated (or moved) by the transform from the last duplication
600  curr_rotation += rotation;
601  currMoveVect += move_vect;
602  } while( aList && --aDuplicateCount > 0 );
603 }
604 
DIALOG_PAD_PRIMITIVES_PROPERTIES(wxWindow *aParent, PCB_BASE_FRAME *aFrame, PAD_CS_PRIMITIVE *aShape)
void GRResetPenAndBrush(wxDC *DC)
Definition: gr_basic.cpp:123
EDA_COLOR_T
NOTE: EDA_COLOR_T is deprecated and is kept around for compatibility with legacy canvas.
Definition: colors.h:42
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:120
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.
int PointCount() const
Function PointCount()
Class BOARD to handle a board.
wxPoint m_Start
angle of an arc, from its starting point, in 0.1 deg
Definition: class_pad.h:100
int color
Definition: DXF_plotter.cpp:62
polygon (not yet used for tracks, but could be in microwave apps)
void FinishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
usual segment : line with rounded ends
void OnButtonDelete(wxCommandEvent &event) override
virtual void SetUnits(EDA_UNITS_T aUnits, bool aUseMils=false)
Function SetUnits Normally not needed (as the UNIT_BINDER inherits from the parent frame)...
Definition: unit_binder.cpp:64
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:216
int ValueFromString(EDA_UNITS_T aUnits, const wxString &aTextValue, bool aUseMils)
Function ValueFromString converts aTextValue in aUnits to internal units used by the application...
Definition: base_units.cpp:409
void Transform(std::vector< PAD_CS_PRIMITIVE > *aList=NULL, int aDuplicateCount=0)
Apply geometric transform (rotation, move, scale) defined in dialog aDuplicate = 1 ...
const OPT< INTERSECTION > SelfIntersecting() const
Function SelfIntersecting()
#define abs(a)
Definition: auxiliary.h:84
DIALOG_PAD_PRIMITIVES_TRANSFORM(wxWindow *aParent, PCB_BASE_FRAME *aFrame, std::vector< PAD_CS_PRIMITIVE * > &aList, bool aShowDuplicate)
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:115
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
This file contains miscellaneous commonly used macros and functions.
bool TransferDataFromWindow() override
Function TransferDataFromWindow Transfer data out of the GUI.
Classes used in Pcbnew, CvPcb and GerbView.
Class DIALOG_PAD_PRIMITIVES_TRANSFORM_BASE.
virtual int GetValue()
Function GetValue Returns the current value in Internal Units.
dialog pad properties editor.
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:79
void SetClosed(bool aClosed)
Function SetClosed()
bool TransferDataToWindow() override
Function TransferDataToWindow Transfer data into the GUI.
void geom_transf(wxPoint &aCoord, wxPoint &aMove, double aScale, double aRotation)
bool TransferDataToWindow() override
Function TransferDataToWindow Transfer data into the GUI.
int m_Radius
thickness of segment or outline For filled S_CIRCLE shape, thickness = 0.
Definition: class_pad.h:98
std::vector< wxPoint > m_Poly
is also the start point of the arc
Definition: class_pad.h:102
void onGridSelect(wxGridRangeSelectEvent &event) override
double DoubleValueFromString(EDA_UNITS_T aUnits, const wxString &aTextValue, bool aUseMils)
Function DoubleValueFromString converts aTextValue to a double.
Definition: base_units.cpp:302
Arcs (with rounded ends)
Helper class to handle a primitive (basic shape: polygon, segment, circle or arc) to build a custom p...
Definition: class_pad.h:91
void Show(bool aShow)
Function Show Shows/hides the label, widget and units label.
DIALOG_PAD_PRIMITIVE_POLY_PROPS(wxWindow *aParent, PCB_BASE_FRAME *aFrame, PAD_CS_PRIMITIVE *aShape)
void onPolyPanelResize(wxSizeEvent &event) override
Definition: colors.h:60
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:156
wxPoint m_End
is also the center of the circle and arc
Definition: class_pad.h:101
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:285
STROKE_T m_Shape
Definition: class_pad.h:94
void onPaintPolyPanel(wxPaintEvent &event) override
void OnButtonAdd(wxCommandEvent &event) override
int m_Thickness
S_SEGMENT, S_ARC, S_CIRCLE, S_POLYGON only (same as DRAWSEGMENT)
Definition: class_pad.h:95
const int scale
#define max(a, b)
Definition: auxiliary.h:86
Class SHAPE_LINE_CHAIN.
virtual void SetValue(int aValue)
Function SetValue Sets new value (in Internal Units) for the text field, taking care of units convers...
std::vector< PAD_CS_PRIMITIVE * > & m_list
The common library.
Definition: colors.h:49
wxString StringFromValue(EDA_UNITS_T aUnits, int aValue, bool aAddUnitSymbol, bool aUseMils)
Function StringFromValue returns the string from aValue according to units (inch, mm ...
Definition: base_units.cpp:210
Module description (excepted pads)
bool doValidate(bool aRemoveRedundantCorners)
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
class PCB_BASE_FRAME basic PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer...
double m_ArcAngle
radius of a circle
Definition: class_pad.h:99
bool TransferDataFromWindow() override
Function TransferDataFromWindow Transfer data out of the GUI.
#define min(a, b)
Definition: auxiliary.h:85
bool Validate() override
test for a valid polygon (a not self intersectiong polygon)
Class DIALOG_PAD_PRIMITIVES_PROPERTIES_BASE.
EDA_UNITS_T GetUserUnits() const override
Definition: dialog_shim.h:132