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 <confirm.h>
33 #include <trigo.h>
34 #include <pcb_base_frame.h>
35 #include <base_units.h>
36 #include <widgets/wx_grid.h>
37 #include <footprint.h>
38 #include <math/util.h> // for KiROUND
39 
40 #include <dialog_pad_properties.h>
41 #include <bitmaps.h>
42 #include <wx/dcclient.h>
43 
44 
46  PCB_BASE_FRAME* aFrame,
47  PCB_SHAPE* aShape ) :
49  m_shape( aShape ),
50  m_startX( aFrame, m_startXLabel, m_startXCtrl, m_startXUnits ),
51  m_startY( aFrame, m_startYLabel, m_startYCtrl, m_startYUnits ),
52  m_ctrl1X( aFrame, m_ctrl1XLabel, m_ctrl1XCtrl, m_ctrl1XUnits ),
53  m_ctrl1Y( aFrame, m_ctrl1YLabel, m_ctrl1YCtrl, m_ctrl1YUnits ),
54  m_ctrl2X( aFrame, m_ctrl2XLabel, m_ctrl2XCtrl, m_ctrl2XUnits ),
55  m_ctrl2Y( aFrame, m_ctrl2YLabel, m_ctrl2YCtrl, m_ctrl2YUnits ),
56  m_endX( aFrame, m_endXLabel, m_endXCtrl, m_endXUnits ),
57  m_endY( aFrame, m_endYLabel, m_endYCtrl, m_endYUnits ),
58  m_radius( aFrame, m_radiusLabel, m_radiusCtrl, m_radiusUnits ),
59  m_thickness( aFrame, m_thicknessLabel, m_thicknessCtrl, m_thicknessUnits )
60 {
62 
64 
65  m_sdbSizerOK->SetDefault();
66 
68 }
69 
71 {
72  if( m_shape == NULL )
73  return false;
74 
76  m_filledCtrl->SetValue( m_shape->IsFilled() );
77 
78  switch( m_shape->GetShape() )
79  {
80  case PCB_SHAPE_TYPE::SEGMENT: // Segment with rounded ends
81  SetTitle( _( "Segment" ) );
84  m_endX.SetValue( m_shape->GetEnd().x );
85  m_endY.SetValue( m_shape->GetEnd().y );
86  m_ctrl1X.Show( false, true );
87  m_ctrl1Y.Show( false, true );
88  m_ctrl2X.Show( false, true );
89  m_ctrl2Y.Show( false, true );
90  m_staticTextPosCtrl1->Show( false );
91  m_staticTextPosCtrl1->SetSize( 0, 0 );
92  m_staticTextPosCtrl2->Show( false );
93  m_staticTextPosCtrl2->SetSize( 0, 0 );
94  m_radius.Show( false );
95  m_filledCtrl->Show( false );
96  break;
97 
98  case PCB_SHAPE_TYPE::CURVE: // Bezier line
99  SetTitle( _( "Bezier" ) );
102  m_endX.SetValue( m_shape->GetEnd().x );
103  m_endY.SetValue( m_shape->GetEnd().y );
108  m_radius.Show( false );
109  m_filledCtrl->Show( false );
110  break;
111 
112  case PCB_SHAPE_TYPE::ARC: // Arc with rounded ends
113  SetTitle( _( "Arc" ) );
114  m_startX.SetValue( m_shape->GetEnd().x ); // confusingly, the start point of the arc
116  m_staticTextPosEnd->SetLabel( _( "Center" ) );
117  m_endX.SetValue( m_shape->GetStart().x ); // arc center
119  m_radiusLabel->SetLabel( _( "Angle:" ) );
122  m_ctrl1X.Show( false, true );
123  m_ctrl1Y.Show( false, true );
124  m_ctrl2X.Show( false, true );
125  m_ctrl2Y.Show( false, true );
126  m_staticTextPosCtrl1->Show( false );
127  m_staticTextPosCtrl1->SetSize( 0, 0 );
128  m_staticTextPosCtrl2->Show( false );
129  m_staticTextPosCtrl2->SetSize( 0, 0 );
130  m_filledCtrl->Show( false );
131  break;
132 
133  case PCB_SHAPE_TYPE::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  m_filledCtrl->Show( true );
158  break;
159 
160  case PCB_SHAPE_TYPE::POLYGON: // polygon
161  // polygon has a specific dialog editor. So nothing here
162  break;
163 
164  default:
165  SetTitle( "Unknown basic shape" );
166  break;
167  }
168 
169  return true;
170 }
171 
173 {
174  if( m_thickness.GetValue() == 0 && !m_filledCtrl->GetValue() )
175  {
176  DisplayError( this, _( "Line width may not be 0 for unfilled shapes." ) );
177  m_thicknessCtrl->SetFocus();
178  return false;
179  }
180 
181  // Transfer data out of the GUI.
183  m_shape->SetFilled( m_filledCtrl->GetValue() );
184 
185  switch( m_shape->GetShape() )
186  {
187  case PCB_SHAPE_TYPE::SEGMENT: // Segment with rounded ends
188  m_shape->SetStart( wxPoint( m_startX.GetValue(), m_startY.GetValue() ) );
189  m_shape->SetEnd( wxPoint( m_endX.GetValue(), m_endY.GetValue() ) );
190  break;
191 
192  case PCB_SHAPE_TYPE::CURVE: // Segment with rounded ends
193  m_shape->SetStart( wxPoint( m_startX.GetValue(), m_startY.GetValue() ) );
194  m_shape->SetEnd( wxPoint( m_endX.GetValue(), m_endY.GetValue() ) );
197  break;
198 
199  case PCB_SHAPE_TYPE::ARC: // Arc with rounded ends
200  // NB: we store the center of the arc in m_Start, and, confusingly,
201  // the start point in m_End
202  m_shape->SetStart( wxPoint( m_endX.GetValue(), m_endY.GetValue() ) );
203  m_shape->SetEnd( wxPoint( m_startX.GetValue(), m_startY.GetValue() ) );
204  // arc angle
206  break;
207 
208  case PCB_SHAPE_TYPE::CIRCLE: // ring or circle
209  m_shape->SetStart( wxPoint( m_startX.GetValue(), m_startY.GetValue() ) );
210  m_shape->SetEnd( m_shape->GetStart() + wxPoint( m_radius.GetValue(), 0 ) );
211  break;
212 
213  case PCB_SHAPE_TYPE::POLYGON: // polygon
214  // polygon has a specific dialog editor. So nothing here
215  break;
216 
217  default:
218  SetTitle( "Unknown basic shape" );
219  break;
220  }
221 
222  return true;
223 }
224 
225 
227  PCB_BASE_FRAME* aFrame,
228  PCB_SHAPE* aShape ) :
230  m_shape( aShape ),
231  m_thickness( aFrame, m_thicknessLabel, m_thicknessCtrl, m_thicknessUnits )
232 {
233  if( !m_shape->GetPolyShape().IsEmpty() )
234  {
235  for( const VECTOR2I& pt : m_shape->GetPolyShape().Outline( 0 ).CPoints() )
236  m_currPoints.emplace_back( pt );
237  }
238 
239  m_addButton->SetBitmap( KiBitmap( BITMAPS::small_plus ) );
242 
243  // Test for acceptable polygon (more than 2 corners, and not self-intersecting) and
244  // remove any redundant corners. A warning message is displayed if not OK.
245  doValidate( true );
246 
248 
249  m_sdbSizerOK->SetDefault();
250  GetSizer()->SetSizeHints( this );
251 
252  m_gridCornersList->Connect( wxEVT_GRID_CELL_CHANGING, wxGridEventHandler( DIALOG_PAD_PRIMITIVE_POLY_PROPS::onCellChanging ), NULL, this );
253 
254  // Now all widgets have the size fixed, call FinishDialogSettings
256 }
257 
258 
260 {
261  m_gridCornersList->Disconnect( wxEVT_GRID_CELL_CHANGING, wxGridEventHandler( DIALOG_PAD_PRIMITIVE_POLY_PROPS::onCellChanging ), NULL, this );
262 }
263 
264 
266 {
267  if( m_shape == NULL )
268  return false;
269 
271  m_filledCtrl->SetValue( m_shape->IsFilled() );
272 
273  // Populates the list of corners
274  int extra_rows = m_currPoints.size() - m_gridCornersList->GetNumberRows();
275 
276  if( extra_rows > 0 )
277  {
278  m_gridCornersList->AppendRows( extra_rows );
279  }
280  else if( extra_rows < 0 )
281  {
282  extra_rows = -extra_rows;
283  m_gridCornersList->DeleteRows( 0, extra_rows );
284  }
285 
286  // enter others corner coordinates
287  wxString msg;
288  for( unsigned row = 0; row < m_currPoints.size(); ++row )
289  {
290  // Row label is "Corner x"
291  msg.Printf( "Corner %d", row+1 );
292  m_gridCornersList->SetRowLabelValue( row, msg );
293 
294  msg = StringFromValue( GetUserUnits(), m_currPoints[row].x );
295  m_gridCornersList->SetCellValue( row, 0, msg );
296 
297  msg = StringFromValue( GetUserUnits(), m_currPoints[row].y );
298  m_gridCornersList->SetCellValue( row, 1, msg );
299  }
300 
301  return true;
302 }
303 
305 {
306  if( !Validate() )
307  return false;
308 
311  m_shape->SetFilled( m_filledCtrl->GetValue() );
312 
313  return true;
314 }
315 
316 
318 {
319  // Don't remove redundant corners while user is editing corner list
320  return doValidate( false );
321 }
322 
323 
324 // test for a valid polygon (a not self intersectiong polygon)
325 bool DIALOG_PAD_PRIMITIVE_POLY_PROPS::doValidate( bool aRemoveRedundantCorners )
326 {
328  return false;
329 
330  if( m_currPoints.size() < 3 )
331  {
332  m_warningText->SetLabel( _("Polygon must have at least 3 corners" ) );
333  m_warningText->Show( true );
334  m_warningIcon->Show( true );
335  return false;
336  }
337 
338  bool valid = true;
339 
340  SHAPE_LINE_CHAIN polyline( m_currPoints, true );
341 
342  // Remove redundant corners:
343  polyline.Simplify();
344 
345  if( polyline.PointCount() < 3 )
346  {
347  m_warningText->SetLabel( _( "Polygon must have at least 3 corners after simplification" ) );
348  valid = false;
349  }
350 
351  if( valid && polyline.SelfIntersecting() )
352  {
353  m_warningText->SetLabel( _( "Polygon can not be self-intersecting" ) );
354  valid = false;
355  }
356 
357  m_warningIcon->Show( !valid );
358  m_warningText->Show( !valid );
359 
360  if( aRemoveRedundantCorners )
361  {
362  if( polyline.PointCount() != (int) m_currPoints.size() )
363  { // Happens after simplification
364  m_currPoints.clear();
365 
366  for( const VECTOR2I& pt : polyline.CPoints() )
367  m_currPoints.emplace_back( pt );
368 
369  m_warningIcon->Show( true );
370  m_warningText->Show( true );
371  m_warningText->SetLabel( _( "Note: redundant corners removed" ) );
372  }
373  }
374 
375  return valid;
376 }
377 
378 
379 void DIALOG_PAD_PRIMITIVE_POLY_PROPS::OnButtonAdd( wxCommandEvent& event )
380 {
382  return;
383 
384  // Insert a new corner after the currently selected:
385  wxArrayInt selections = m_gridCornersList->GetSelectedRows();
386  int row = -1;
387 
388  if( m_gridCornersList->GetNumberRows() == 0 )
389  row = 0;
390  else if( selections.size() > 0 )
391  row = selections[ selections.size() - 1 ] + 1;
392  else
393  row = m_gridCornersList->GetGridCursorRow() + 1;
394 
395  if( row < 0 )
396  {
397  wxMessageBox( _( "Select a corner to add the new corner after." ) );
398  return;
399  }
400 
401  if( m_currPoints.size() == 0 || row >= (int) m_currPoints.size() )
402  m_currPoints.emplace_back( 0, 0 );
403  else
404  m_currPoints.insert( m_currPoints.begin() + row, wxPoint( 0, 0 ) );
405 
406  Validate();
408 
409  m_gridCornersList->ForceRefresh();
410  // Select the new row
411  m_gridCornersList->SelectRow( row, false );
412 
413  m_panelPoly->Refresh();
414 }
415 
417 {
419  return;
420 
421  wxArrayInt selections = m_gridCornersList->GetSelectedRows();
422 
423  if( m_gridCornersList->GetNumberRows() == 0 )
424  return;
425 
426  if( selections.size() == 0 && m_gridCornersList->GetGridCursorRow() >= 0 )
427  selections.push_back( m_gridCornersList->GetGridCursorRow() );
428 
429  if( selections.size() == 0 )
430  {
431  wxMessageBox( _( "Select a corner to delete." ) );
432  return;
433  }
434 
435  // remove corners:
436  std::sort( selections.begin(), selections.end() );
437 
438  for( int ii = selections.size()-1; ii >= 0 ; --ii )
439  m_currPoints.erase( m_currPoints.begin() + selections[ii] );
440 
441  Validate();
443 
444  m_gridCornersList->ForceRefresh();
445  // select the row previous to the last deleted row
446  m_gridCornersList->SelectRow( std::max( 0, selections[ 0 ] - 1 ) );
447 
448  m_panelPoly->Refresh();
449 }
450 
452 {
453  wxPaintDC dc( m_panelPoly );
454  wxSize dc_size = dc.GetSize();
455  dc.SetDeviceOrigin( dc_size.x / 2, dc_size.y / 2 );
456 
457  // Calculate a suitable scale to fit the available draw area
458  int minsize( Millimeter2iu( 0.5 ) );
459 
460  for( unsigned ii = 0; ii < m_currPoints.size(); ++ii )
461  {
462  minsize = std::max( minsize, std::abs( m_currPoints[ii].x ) );
463  minsize = std::max( minsize, std::abs( m_currPoints[ii].y ) );
464  }
465 
466  // The draw origin is the center of the window.
467  // Therefore the window size is twice the minsize just calculated
468  minsize *= 2;
469  minsize += m_thickness.GetValue();
470 
471  // Give a margin
472  double scale = std::min( double( dc_size.x ) / minsize, double( dc_size.y ) / minsize ) * 0.9;
473 
474  GRResetPenAndBrush( &dc );
475 
476  // Draw X and Y axis. This is particularly useful to show the
477  // reference position of basic shape
478  // Axis are drawn before the polygon to avoid masking segments on axis
479  GRLine( NULL, &dc, -dc_size.x, 0, dc_size.x, 0, 0, LIGHTBLUE ); // X axis
480  GRLine( NULL, &dc, 0, -dc_size.y, 0, dc_size.y, 0, LIGHTBLUE ); // Y axis
481 
482  // Draw polygon.
483  // The selected edge(s) are shown in selectcolor, the others in normalcolor.
484  EDA_COLOR_T normalcolor = WHITE;
485  EDA_COLOR_T selectcolor = RED;
486 
487  for( unsigned ii = 0; ii < m_currPoints.size(); ++ii )
488  {
489  EDA_COLOR_T color = normalcolor;
490 
491  if( m_gridCornersList->IsInSelection (ii, 0) ||
492  m_gridCornersList->IsInSelection (ii, 1) ||
493  m_gridCornersList->GetGridCursorRow() == (int)ii )
494  color = selectcolor;
495 
496  unsigned jj = ii + 1;
497 
498  if( jj >= m_currPoints.size() )
499  jj = 0;
500 
502  }
503 
504  event.Skip();
505 }
506 
508 {
509  m_panelPoly->Refresh();
510  event.Skip();
511 }
512 
513 void DIALOG_PAD_PRIMITIVE_POLY_PROPS::onGridSelect( wxGridRangeSelectEvent& event )
514 {
515  m_panelPoly->Refresh();
516 }
517 
519 {
520  int row = event.GetRow();
521  int col = event.GetCol();
522  wxString msg = event.GetString();
523 
524  if( msg.IsEmpty() )
525  return;
526 
527  if( col == 0 ) // Set the X value
528  m_currPoints[row].x = ValueFromString( GetUserUnits(), msg );
529  else // Set the Y value
530  m_currPoints[row].y = ValueFromString( GetUserUnits(), msg );
531 
532  Validate();
533 
534  m_panelPoly->Refresh();
535 }
536 
537 
538 // A dialog to apply geometry transforms to a shape or set of shapes
539 // (move, rotate around origin, scaling factor, duplication).
541  PCB_BASE_FRAME* aFrame,
542  std::vector<std::shared_ptr<PCB_SHAPE>>& aList,
543  bool aShowDuplicate ) :
545  m_list( aList ),
546  m_vectorX( aFrame, m_xLabel, m_xCtrl, m_xUnits ),
547  m_vectorY( aFrame, m_yLabel, m_yCtrl, m_yUnits ),
548  m_rotation( aFrame, m_rotationLabel, m_rotationCtrl, m_rotationUnits )
549 {
551 
552  if( !aShowDuplicate ) // means no duplicate transform
553  {
554  m_staticTextDupCnt->Show( false );
555  m_spinCtrlDuplicateCount->Show( false );
556  }
557 
558  m_sdbSizerOK->SetDefault();
559  GetSizer()->SetSizeHints( this );
560 }
561 
562 
563 // A helper function in geometry transform
564 inline void geom_transf( wxPoint& aCoord, const wxPoint& aMove, double aScale, double aRotation )
565 {
566  aCoord.x = KiROUND( aCoord.x * aScale );
567  aCoord.y = KiROUND( aCoord.y * aScale );
568  aCoord += aMove;
569  RotatePoint( &aCoord, aRotation );
570 }
571 
572 
573 void DIALOG_PAD_PRIMITIVES_TRANSFORM::Transform( std::vector<std::shared_ptr<PCB_SHAPE>>* aList,
574  int aDuplicateCount )
575 {
576  wxPoint move_vect( m_vectorX.GetValue(), m_vectorY.GetValue() );
577  double rotation = m_rotation.GetValue();
579 
580  // Avoid too small / too large scale, which could create issues:
581  if( scale < 0.01 )
582  scale = 0.01;
583 
584  if( scale > 100.0 )
585  scale = 100.0;
586 
587  // Transform shapes
588  // shapes are scaled, then moved then rotated.
589  // if aList != NULL, the initial shape will be duplicated, and transform
590  // applied to the duplicated shape
591 
592  wxPoint currMoveVect = move_vect;
593  double curr_rotation = rotation;
594 
595  do {
596  for( unsigned idx = 0; idx < m_list.size(); ++idx )
597  {
598  std::shared_ptr<PCB_SHAPE> shape;
599 
600  if( aList == NULL )
601  shape = m_list[idx];
602  else
603  {
604  aList->emplace_back( std::make_shared<PCB_SHAPE>( *m_list[idx] ) );
605  shape = aList->back();
606  }
607 
608  // Transform parameters common to all shape types (some can be unused)
609  shape->SetWidth( KiROUND( shape->GetWidth() * scale ) );
610  shape->Move( currMoveVect );
611  shape->Scale( scale );
612  shape->Rotate( wxPoint( 0, 0 ), curr_rotation );
613  }
614 
615  // Prepare new transform on duplication:
616  // Each new item is rotated (or moved) by the transform from the last duplication
617  curr_rotation += rotation;
618  currMoveVect += move_vect;
619  } while( aList && --aDuplicateCount > 0 );
620 }
621 
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:252
void GRResetPenAndBrush(wxDC *DC)
Definition: gr_basic.cpp:118
bool IsFilled() const
Definition: pcb_shape.h:96
SHAPE_POLY_SET & GetPolyShape()
Definition: pcb_shape.h:268
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
Definition: pcb_shape.h:156
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.
SHAPE_LINE_CHAIN & Simplify(bool aRemoveColinear=true)
Function Simplify()
PCB_SHAPE_TYPE GetShape() const
Definition: pcb_shape.h:130
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
int color
Definition: DXF_plotter.cpp:60
bool IsEmpty() const
int GetWidth() const
Definition: pcb_shape.h:118
DIALOG_PAD_PRIMITIVE_POLY_PROPS(wxWindow *aParent, PCB_BASE_FRAME *aFrame, PCB_SHAPE *aShape)
void OnButtonDelete(wxCommandEvent &event) override
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:228
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:98
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:120
Class DIALOG_PAD_PRIMITIVES_TRANSFORM_BASE.
DIALOG_PAD_PRIMITIVES_TRANSFORM(wxWindow *aParent, PCB_BASE_FRAME *aFrame, std::vector< std::shared_ptr< PCB_SHAPE >> &aList, bool aShowDuplicate)
polygon (not yet used for tracks, but could be in microwave apps)
void Transform(std::vector< std::shared_ptr< PCB_SHAPE >> *aList=nullptr, int aDuplicateCount=0)
Apply geometric transform (rotation, move, scale) defined in dialog aDuplicate = 1 .
bool TransferDataToWindow() override
Function TransferDataToWindow Transfer data into the GUI.
void Show(bool aShow, bool aResize=false)
Show/hide 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
long long int ValueFromString(EDA_UNITS aUnits, const wxString &aTextValue, EDA_DATA_TYPE aType)
Function ValueFromString converts aTextValue in aUnits to internal units used by the application.
Definition: base_units.cpp:402
SHAPE_LINE_CHAIN & Outline(int aIndex)
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
Definition: pcb_shape.h:145
void onPolyPanelResize(wxSizeEvent &event) override
DIALOG_PAD_PRIMITIVES_PROPERTIES(wxWindow *aParent, PCB_BASE_FRAME *aFrame, PCB_SHAPE *aShape)
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
Definition: wx_grid.cpp:182
void SetBezControl1(const wxPoint &aPoint)
Definition: pcb_shape.h:132
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:228
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:104
Definition: color4d.h:59
void onPaintPolyPanel(wxPaintEvent &event) override
void geom_transf(wxPoint &aCoord, const wxPoint &aMove, double aScale, double aRotation)
EDA_COLOR_T
Legacy color enumeration.
Definition: color4d.h:41
void OnButtonAdd(wxCommandEvent &event) override
Definition: color4d.h:48
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
const int scale
void SetStart(const wxPoint &aStart)
Definition: pcb_shape.h:148
#define _(s)
Definition: 3d_actions.cpp:33
SHAPE_LINE_CHAIN.
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
usual segment : line with rounded ends
void SetWidth(int aWidth)
Definition: pcb_shape.h:117
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
virtual long long int GetValue()
Return the current value in Internal Units.
wxString StringFromValue(EDA_UNITS aUnits, double aValue, bool aAddUnitSymbol, EDA_DATA_TYPE aType)
Convert a value to a string using double notation.
Definition: base_units.cpp:190
bool doValidate(bool aRemoveRedundantCorners)
double DoubleValueFromString(EDA_UNITS aUnits, const wxString &aTextValue, EDA_DATA_TYPE aType)
Function DoubleValueFromString converts aTextValue to a double.
Definition: base_units.cpp:293
Arcs (with rounded ends)
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:466
static constexpr int Millimeter2iu(double mm)
const wxPoint & GetBezControl1() const
Definition: pcb_shape.h:133
void SetPolyPoints(const std::vector< wxPoint > &aPoints)
Definition: pcb_shape.cpp:1076
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
std::vector< std::shared_ptr< PCB_SHAPE > > & m_list
bool TransferDataFromWindow() override
Function TransferDataFromWindow Transfer data out of the GUI.
void SetEnd(const wxPoint &aEnd)
Definition: pcb_shape.h:159
bool Validate() override
test for a valid polygon (a not self intersectiong polygon)
Class DIALOG_PAD_PRIMITIVES_PROPERTIES_BASE.