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-2021 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 
70 
72 {
73  if( m_shape == nullptr )
74  return false;
75 
77  m_filledCtrl->SetValue( m_shape->IsFilled() );
78 
79  switch( m_shape->GetShape() )
80  {
81  case SHAPE_T::SEGMENT:
82  SetTitle( _( "Segment" ) );
85  m_endX.SetValue( m_shape->GetEnd().x );
86  m_endY.SetValue( m_shape->GetEnd().y );
87  m_ctrl1X.Show( false, true );
88  m_ctrl1Y.Show( false, true );
89  m_ctrl2X.Show( false, true );
90  m_ctrl2Y.Show( false, true );
91  m_staticTextPosCtrl1->Show( false );
92  m_staticTextPosCtrl1->SetSize( 0, 0 );
93  m_staticTextPosCtrl2->Show( false );
94  m_staticTextPosCtrl2->SetSize( 0, 0 );
95  m_radius.Show( false );
96  m_filledCtrl->Show( false );
97  break;
98 
99  case SHAPE_T::BEZIER:
100  SetTitle( _( "Bezier" ) );
103  m_endX.SetValue( m_shape->GetEnd().x );
104  m_endY.SetValue( m_shape->GetEnd().y );
109  m_radius.Show( false );
110  m_filledCtrl->Show( false );
111  break;
112 
113  case SHAPE_T::ARC:
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  m_filledCtrl->Show( false );
132  break;
133 
134  case SHAPE_T::CIRCLE:
135  if( m_shape->GetWidth() )
136  SetTitle( _( "Ring" ) );
137  else
138  SetTitle( _( "Circle" ) );
139 
140  // End point does not exist for a circle or ring:
141  m_staticTextPosEnd->Show( false );
142  m_endX.Show( false );
143  m_endY.Show( false );
144 
145  // Circle center uses position controls:
146  m_staticTextPosStart->SetLabel( _( "Center:" ) );
150  m_ctrl1X.Show( false, true );
151  m_ctrl1Y.Show( false, true );
152  m_ctrl2X.Show( false, true );
153  m_ctrl2Y.Show( false, true );
154  m_staticTextPosCtrl1->Show( false );
155  m_staticTextPosCtrl1->SetSize( 0, 0 );
156  m_staticTextPosCtrl2->Show( false );
157  m_staticTextPosCtrl2->SetSize( 0, 0 );
158  m_filledCtrl->Show( true );
159  break;
160 
161  case SHAPE_T::POLY:
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 {
176  if( m_thickness.GetValue() == 0 && !m_filledCtrl->GetValue() )
177  {
178  DisplayError( this, _( "Line width may not be 0 for unfilled shapes." ) );
179  m_thicknessCtrl->SetFocus();
180  return false;
181  }
182 
183  // Transfer data out of the GUI.
185  m_shape->SetFilled( m_filledCtrl->GetValue() );
186 
187  switch( m_shape->GetShape() )
188  {
189  case SHAPE_T::SEGMENT:
190  m_shape->SetStart( wxPoint( m_startX.GetValue(), m_startY.GetValue() ) );
191  m_shape->SetEnd( wxPoint( m_endX.GetValue(), m_endY.GetValue() ) );
192  break;
193 
194  case SHAPE_T::BEZIER:
195  m_shape->SetStart( wxPoint( m_startX.GetValue(), m_startY.GetValue() ) );
196  m_shape->SetEnd( wxPoint( m_endX.GetValue(), m_endY.GetValue() ) );
199  break;
200 
201  case SHAPE_T::ARC:
202  // NB: we store the center of the arc in m_Start, and, confusingly,
203  // the start point in m_End
204  m_shape->SetStart( wxPoint( m_endX.GetValue(), m_endY.GetValue() ) );
205  m_shape->SetEnd( wxPoint( m_startX.GetValue(), m_startY.GetValue() ) );
206 
207  // arc angle
209  break;
210 
211  case SHAPE_T::CIRCLE:
212  m_shape->SetStart( wxPoint( m_startX.GetValue(), m_startY.GetValue() ) );
213  m_shape->SetEnd( m_shape->GetStart() + wxPoint( m_radius.GetValue(), 0 ) );
214  break;
215 
216  case SHAPE_T::POLY:
217  // polygon has a specific dialog editor. So nothing here
218  break;
219 
220  default:
221  SetTitle( "Unknown basic shape" );
222  break;
223  }
224 
225  return true;
226 }
227 
228 
230  PCB_BASE_FRAME* aFrame,
231  PCB_SHAPE* aShape ) :
233  m_shape( aShape ),
234  m_thickness( aFrame, m_thicknessLabel, m_thicknessCtrl, m_thicknessUnits )
235 {
236  if( !m_shape->GetPolyShape().IsEmpty() )
237  {
238  for( const VECTOR2I& pt : m_shape->GetPolyShape().Outline( 0 ).CPoints() )
239  m_currPoints.emplace_back( pt );
240  }
241 
242  m_addButton->SetBitmap( KiBitmap( BITMAPS::small_plus ) );
245 
246  // Test for acceptable polygon (more than 2 corners, and not self-intersecting) and
247  // remove any redundant corners. A warning message is displayed if not OK.
248  doValidate( true );
249 
251 
252  m_sdbSizerOK->SetDefault();
253  GetSizer()->SetSizeHints( this );
254 
255  m_gridCornersList->Connect( wxEVT_GRID_CELL_CHANGING,
257  nullptr, this );
258 
259  // Now all widgets have the size fixed, call FinishDialogSettings
261 }
262 
263 
265 {
266  m_gridCornersList->Disconnect( wxEVT_GRID_CELL_CHANGING,
268  nullptr, this );
269 }
270 
271 
273 {
274  if( m_shape == nullptr )
275  return false;
276 
278  m_filledCtrl->SetValue( m_shape->IsFilled() );
279 
280  // Populates the list of corners
281  int extra_rows = m_currPoints.size() - m_gridCornersList->GetNumberRows();
282 
283  if( extra_rows > 0 )
284  {
285  m_gridCornersList->AppendRows( extra_rows );
286  }
287  else if( extra_rows < 0 )
288  {
289  extra_rows = -extra_rows;
290  m_gridCornersList->DeleteRows( 0, extra_rows );
291  }
292 
293  // enter others corner coordinates
294  wxString msg;
295 
296  for( unsigned row = 0; row < m_currPoints.size(); ++row )
297  {
298  // Row label is "Corner x"
299  msg.Printf( "Corner %d", row+1 );
300  m_gridCornersList->SetRowLabelValue( row, msg );
301 
302  msg = StringFromValue( GetUserUnits(), m_currPoints[row].x );
303  m_gridCornersList->SetCellValue( row, 0, msg );
304 
305  msg = StringFromValue( GetUserUnits(), m_currPoints[row].y );
306  m_gridCornersList->SetCellValue( row, 1, msg );
307  }
308 
309  return true;
310 }
311 
313 {
314  if( !Validate() )
315  return false;
316 
319  m_shape->SetFilled( m_filledCtrl->GetValue() );
320 
321  return true;
322 }
323 
324 
326 {
327  // Don't remove redundant corners while user is editing corner list
328  return doValidate( false );
329 }
330 
331 
332 bool DIALOG_PAD_PRIMITIVE_POLY_PROPS::doValidate( bool aRemoveRedundantCorners )
333 {
335  return false;
336 
337  if( m_currPoints.size() < 3 )
338  {
339  m_warningText->SetLabel( _("Polygon must have at least 3 corners" ) );
340  m_warningText->Show( true );
341  m_warningIcon->Show( true );
342  return false;
343  }
344 
345  bool valid = true;
346 
347  SHAPE_LINE_CHAIN polyline( m_currPoints, true );
348 
349  // Remove redundant corners:
350  polyline.Simplify();
351 
352  if( polyline.PointCount() < 3 )
353  {
354  m_warningText->SetLabel( _( "Polygon must have at least 3 corners after simplification" ) );
355  valid = false;
356  }
357 
358  if( valid && polyline.SelfIntersecting() )
359  {
360  m_warningText->SetLabel( _( "Polygon can not be self-intersecting" ) );
361  valid = false;
362  }
363 
364  m_warningIcon->Show( !valid );
365  m_warningText->Show( !valid );
366 
367  if( aRemoveRedundantCorners )
368  {
369  if( polyline.PointCount() != (int) m_currPoints.size() )
370  { // Happens after simplification
371  m_currPoints.clear();
372 
373  for( const VECTOR2I& pt : polyline.CPoints() )
374  m_currPoints.emplace_back( pt );
375 
376  m_warningIcon->Show( true );
377  m_warningText->Show( true );
378  m_warningText->SetLabel( _( "Note: redundant corners removed" ) );
379  }
380  }
381 
382  return valid;
383 }
384 
385 
386 void DIALOG_PAD_PRIMITIVE_POLY_PROPS::OnButtonAdd( wxCommandEvent& event )
387 {
389  return;
390 
391  // Insert a new corner after the currently selected:
392  wxArrayInt selections = m_gridCornersList->GetSelectedRows();
393  int row = -1;
394 
395  if( m_gridCornersList->GetNumberRows() == 0 )
396  row = 0;
397  else if( selections.size() > 0 )
398  row = selections[ selections.size() - 1 ] + 1;
399  else
400  row = m_gridCornersList->GetGridCursorRow() + 1;
401 
402  if( row < 0 )
403  {
404  wxMessageBox( _( "Select a corner to add the new corner after." ) );
405  return;
406  }
407 
408  if( m_currPoints.size() == 0 || row >= (int) m_currPoints.size() )
409  m_currPoints.emplace_back( 0, 0 );
410  else
411  m_currPoints.insert( m_currPoints.begin() + row, wxPoint( 0, 0 ) );
412 
413  Validate();
415 
416  m_gridCornersList->ForceRefresh();
417  // Select the new row
418  m_gridCornersList->SelectRow( row, false );
419 
420  m_panelPoly->Refresh();
421 }
422 
423 
425 {
427  return;
428 
429  wxArrayInt selections = m_gridCornersList->GetSelectedRows();
430 
431  if( m_gridCornersList->GetNumberRows() == 0 )
432  return;
433 
434  if( selections.size() == 0 && m_gridCornersList->GetGridCursorRow() >= 0 )
435  selections.push_back( m_gridCornersList->GetGridCursorRow() );
436 
437  if( selections.size() == 0 )
438  {
439  wxMessageBox( _( "Select a corner to delete." ) );
440  return;
441  }
442 
443  // remove corners:
444  std::sort( selections.begin(), selections.end() );
445 
446  for( int ii = selections.size()-1; ii >= 0 ; --ii )
447  m_currPoints.erase( m_currPoints.begin() + selections[ii] );
448 
449  Validate();
451 
452  m_gridCornersList->ForceRefresh();
453 
454  // select the row previous to the last deleted row
455  m_gridCornersList->SelectRow( std::max( 0, selections[ 0 ] - 1 ) );
456 
457  m_panelPoly->Refresh();
458 }
459 
460 
462 {
463  wxPaintDC dc( m_panelPoly );
464  wxSize dc_size = dc.GetSize();
465  dc.SetDeviceOrigin( dc_size.x / 2, dc_size.y / 2 );
466 
467  // Calculate a suitable scale to fit the available draw area
468  int minsize( Millimeter2iu( 0.5 ) );
469 
470  for( unsigned ii = 0; ii < m_currPoints.size(); ++ii )
471  {
472  minsize = std::max( minsize, std::abs( m_currPoints[ii].x ) );
473  minsize = std::max( minsize, std::abs( m_currPoints[ii].y ) );
474  }
475 
476  // The draw origin is the center of the window.
477  // Therefore the window size is twice the minsize just calculated
478  minsize *= 2;
479  minsize += m_thickness.GetValue();
480 
481  // Give a margin
482  double scale = std::min( double( dc_size.x ) / minsize, double( dc_size.y ) / minsize ) * 0.9;
483 
484  GRResetPenAndBrush( &dc );
485 
486  // Draw X and Y axis. This is particularly useful to show the
487  // reference position of basic shape
488  // Axis are drawn before the polygon to avoid masking segments on axis
489  GRLine( nullptr, &dc, -dc_size.x, 0, dc_size.x, 0, 0, LIGHTBLUE ); // X axis
490  GRLine( nullptr, &dc, 0, -dc_size.y, 0, dc_size.y, 0, LIGHTBLUE ); // Y axis
491 
492  // Draw polygon.
493  // The selected edge(s) are shown in selectcolor, the others in normalcolor.
494  EDA_COLOR_T normalcolor = WHITE;
495  EDA_COLOR_T selectcolor = RED;
496 
497  for( unsigned ii = 0; ii < m_currPoints.size(); ++ii )
498  {
499  EDA_COLOR_T color = normalcolor;
500 
501  if( m_gridCornersList->IsInSelection (ii, 0) ||
502  m_gridCornersList->IsInSelection (ii, 1) ||
503  m_gridCornersList->GetGridCursorRow() == (int)ii )
504  color = selectcolor;
505 
506  unsigned jj = ii + 1;
507 
508  if( jj >= m_currPoints.size() )
509  jj = 0;
510 
511  GRLine( nullptr, &dc, m_currPoints[ii] * scale, m_currPoints[jj] * scale,
513  }
514 
515  event.Skip();
516 }
517 
518 
520 {
521  m_panelPoly->Refresh();
522  event.Skip();
523 }
524 
525 
526 void DIALOG_PAD_PRIMITIVE_POLY_PROPS::onGridSelect( wxGridRangeSelectEvent& event )
527 {
528  m_panelPoly->Refresh();
529 }
530 
531 
533 {
534  int row = event.GetRow();
535  int col = event.GetCol();
536  wxString msg = event.GetString();
537 
538  if( msg.IsEmpty() )
539  return;
540 
541  if( col == 0 ) // Set the X value
542  m_currPoints[row].x = ValueFromString( GetUserUnits(), msg );
543  else // Set the Y value
544  m_currPoints[row].y = ValueFromString( GetUserUnits(), msg );
545 
546  Validate();
547 
548  m_panelPoly->Refresh();
549 }
550 
551 
553  PCB_BASE_FRAME* aFrame,
554  std::vector<std::shared_ptr<PCB_SHAPE>>& aList,
555  bool aShowDuplicate ) :
557  m_list( aList ),
558  m_vectorX( aFrame, m_xLabel, m_xCtrl, m_xUnits ),
559  m_vectorY( aFrame, m_yLabel, m_yCtrl, m_yUnits ),
560  m_rotation( aFrame, m_rotationLabel, m_rotationCtrl, m_rotationUnits )
561 {
563 
564  if( !aShowDuplicate ) // means no duplicate transform
565  {
566  m_staticTextDupCnt->Show( false );
567  m_spinCtrlDuplicateCount->Show( false );
568  }
569 
570  m_sdbSizerOK->SetDefault();
571  GetSizer()->SetSizeHints( this );
572 }
573 
574 
575 // A helper function in geometry transform
576 inline void geom_transf( wxPoint& aCoord, const wxPoint& aMove, double aScale, double aRotation )
577 {
578  aCoord.x = KiROUND( aCoord.x * aScale );
579  aCoord.y = KiROUND( aCoord.y * aScale );
580  aCoord += aMove;
581  RotatePoint( &aCoord, aRotation );
582 }
583 
584 
585 void DIALOG_PAD_PRIMITIVES_TRANSFORM::Transform( std::vector<std::shared_ptr<PCB_SHAPE>>* aList,
586  int aDuplicateCount )
587 {
588  wxPoint move_vect( m_vectorX.GetValue(), m_vectorY.GetValue() );
589  double rotation = m_rotation.GetValue();
591 
592  // Avoid too small / too large scale, which could create issues:
593  if( scale < 0.01 )
594  scale = 0.01;
595 
596  if( scale > 100.0 )
597  scale = 100.0;
598 
599  // Transform shapes
600  // shapes are scaled, then moved then rotated.
601  // if aList != NULL, the initial shape will be duplicated, and transform
602  // applied to the duplicated shape
603 
604  wxPoint currMoveVect = move_vect;
605  double curr_rotation = rotation;
606 
607  do {
608  for( unsigned idx = 0; idx < m_list.size(); ++idx )
609  {
610  std::shared_ptr<PCB_SHAPE> shape;
611 
612  if( aList == nullptr )
613  {
614  shape = m_list[idx];
615  }
616  else
617  {
618  aList->emplace_back( std::make_shared<PCB_SHAPE>( *m_list[idx] ) );
619  shape = aList->back();
620  }
621 
622  // Transform parameters common to all shape types (some can be unused)
623  shape->SetWidth( KiROUND( shape->GetWidth() * scale ) );
624  shape->Move( currMoveVect );
625  shape->Scale( scale );
626  shape->Rotate( wxPoint( 0, 0 ), curr_rotation );
627  }
628 
629  // Prepare new transform on duplication:
630  // Each new item is rotated (or moved) by the transform from the last duplication
631  curr_rotation += rotation;
632  currMoveVect += move_vect;
633  } while( aList && --aDuplicateCount > 0 );
634 }
635 
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:119
Arcs (with rounded ends)
bool IsFilled() const
Definition: pcb_shape.h:75
Bezier Curve.
polygon (not yet used for tracks, but could be in microwave apps)
SHAPE_POLY_SET & GetPolyShape()
Definition: pcb_shape.h:240
const wxPoint & GetEnd() const
Return the ending point of the graphic.
Definition: pcb_shape.h:134
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_T GetShape() const
Definition: pcb_shape.h:110
SHAPE_LINE_CHAIN & Simplify(bool aRemoveColinear=true)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
void SetFilled(bool aFlag)
Definition: pcb_shape.h:73
int GetRadius() const
Return the radius of this item.
Definition: pcb_shape.cpp:487
int color
Definition: DXF_plotter.cpp:60
bool IsEmpty() const
int GetWidth() const
Definition: pcb_shape.h:97
const wxPoint & GetBezierC2() const
Definition: pcb_shape.h:116
usual segment : line with rounded ends
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
Return the number of points (vertices) in this line chain.
const OPT< INTERSECTION > SelfIntersecting() const
Check if the line chain is self-intersecting.
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:97
bool TransferDataFromWindow() override
Transfer data out of the GUI.
Classes used in Pcbnew, CvPcb and GerbView.
EDA_UNITS GetUserUnits() const
Definition: dialog_shim.h:119
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)
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
Transfer data into the GUI.
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:416
SHAPE_LINE_CHAIN & Outline(int aIndex)
const wxPoint & GetStart() const
Return the starting point of the graphic.
Definition: pcb_shape.h:124
const wxPoint & GetBezierC1() const
Definition: pcb_shape.h:113
void onPolyPanelResize(wxSizeEvent &event) override
#define _(s)
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:180
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:231
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:105
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:88
const int scale
void SetStart(const wxPoint &aStart)
Definition: pcb_shape.h:127
Represent a polyline (an zero-thickness chain of connected line segments).
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:107
void SetWidth(int aWidth)
Definition: pcb_shape.h:96
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:73
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:204
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:307
virtual void SetAngle(double aAngle, bool aUpdateEnd=true)
Set the angle for arcs, and normalizes it within the range 0 - 360 degrees.
Definition: pcb_shape.cpp:519
static constexpr int Millimeter2iu(double mm)
void SetPolyPoints(const std::vector< wxPoint > &aPoints)
Definition: pcb_shape.cpp:1153
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
std::vector< std::shared_ptr< PCB_SHAPE > > & m_list
bool TransferDataFromWindow() override
Transfer data out of the GUI.
void SetEnd(const wxPoint &aEnd)
Definition: pcb_shape.h:137
void SetBezierC1(const wxPoint &aPoint)
Definition: pcb_shape.h:112
bool Validate() override
Test for a valid polygon (a not self intersectiong polygon).
Class DIALOG_PAD_PRIMITIVES_PROPERTIES_BASE.