KiCad PCB EDA Suite
dialog_pad_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) 2013 Dick Hollenbeck, dick@softplc.com
6  * Copyright (C) 2008-2013 Wayne Stambaugh <stambaughw@verizon.net>
7  * Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, you may find one here:
21  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22  * or you may search the http://www.gnu.org website for the version 2 license,
23  * or you may write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26 
27 #include <fctsys.h>
28 #include <common.h>
29 #include <gr_basic.h>
31 #include <view/view_controls.h>
32 #include <trigo.h>
33 #include <class_drawpanel.h>
34 #include <confirm.h>
35 #include <pcbnew.h>
36 #include <pcb_base_frame.h>
37 #include <base_units.h>
38 #include <board_commit.h>
39 #include <bitmaps.h>
40 
41 #include <class_board.h>
42 #include <class_module.h>
43 #include <pcb_painter.h>
44 #include <widgets/net_selector.h>
45 
46 #include <dialog_pad_properties.h>
47 
48 #include <dialog_pad_properties.h>
49 #include <html_messagebox.h>
50 
51 #include <convert_basic_shapes_to_polygon.h> // for enum RECT_CHAMFER_POSITIONS definition
52 
53 
54 // list of pad shapes, ordered like the pad shape wxChoice in dialog.
56 {
63  PAD_SHAPE_CUSTOM, // choice = CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
64  PAD_SHAPE_CUSTOM // choice = PAD_SHAPE_CUSTOM_RECT_ANCHOR
65 };
66 
67 // the ordered index of the pad shape wxChoice in dialog.
68 // keep it consistent with code_shape[] and dialog strings
70 {
79 };
80 
82 {
87  PAD_ATTRIB_CONN // Aperture pad (type CONN with no copper layers)
88 };
89 
90 // Default mask layers setup for pads according to the pad type
91 static const LSET std_pad_layers[] =
92 {
93  D_PAD::StandardMask(), // PAD_ATTRIB_STANDARD:
94  D_PAD::SMDMask(), // PAD_ATTRIB_SMD:
95  D_PAD::ConnSMDMask(), // PAD_ATTRIB_CONN:
96  D_PAD::UnplatedHoleMask(), // PAD_ATTRIB_HOLE_NOT_PLATED:
98 };
99 
100 
102 {
103  DIALOG_PAD_PROPERTIES dlg( this, aPad );
104  dlg.ShowQuasiModal(); // QuasiModal required for NET_SELECTOR
105 }
106 
107 
109  DIALOG_PAD_PROPERTIES_BASE( aParent ),
110  m_parent( aParent ),
111  m_canUpdate( false ),
112  m_posX( aParent, m_posXLabel, m_posXCtrl, m_posXUnits ),
113  m_posY( aParent, m_posYLabel, m_posYCtrl, m_posYUnits ),
114  m_sizeX( aParent, m_sizeXLabel, m_sizeXCtrl, m_sizeXUnits, true ),
115  m_sizeY( aParent, m_sizeYLabel, m_sizeYCtrl, m_sizeYUnits, true ),
116  m_offsetX( aParent, m_offsetXLabel, m_offsetXCtrl, m_offsetXUnits, true ),
117  m_offsetY( aParent, m_offsetYLabel, m_offsetYCtrl, m_offsetYUnits, true ),
118  m_padToDie( aParent, m_padToDieLabel, m_padToDieCtrl, m_padToDieUnits, true ),
119  m_trapDelta( aParent, m_trapDeltaLabel, m_trapDeltaCtrl, m_trapDeltaUnits, true ),
120  m_cornerRadius( aParent, m_cornerRadiusLabel, m_tcCornerRadius, m_cornerRadiusUnits, true ),
121  m_holeX( aParent, m_holeXLabel, m_holeXCtrl, m_holeXUnits, true ),
122  m_holeY( aParent, m_holeYLabel, m_holeYCtrl, m_holeYUnits, true ),
123  m_OrientValidator( 1, &m_OrientValue ),
124  m_clearance( aParent, m_clearanceLabel, m_clearanceCtrl, m_clearanceUnits, true ),
125  m_maskClearance( aParent, m_maskClearanceLabel, m_maskClearanceCtrl, m_maskClearanceUnits, true ),
126  m_pasteClearance( aParent, m_pasteClearanceLabel, m_pasteClearanceCtrl, m_pasteClearanceUnits, true ),
127  m_spokeWidth( aParent, m_spokeWidthLabel, m_spokeWidthCtrl, m_spokeWidthUnits, true ),
128  m_thermalGap( aParent, m_thermalGapLabel, m_thermalGapCtrl, m_thermalGapUnits, true )
129 {
130  m_currentPad = aPad; // aPad can be NULL, if the dialog is called
131  // from the footprint editor to set default pad setup
132 
134 
136 
137  m_OrientValidator.SetRange( -360.0, 360.0 );
138  m_orientation->SetValidator( m_OrientValidator );
139  m_OrientValidator.SetWindow( m_orientation );
140 
141  m_cbShowPadOutline->SetValue( m_sketchPreview );
142 
143  m_FlippedWarningIcon->SetBitmap( KiBitmap( dialog_warning_xpm ) );
144  m_nonCopperWarningIcon->SetBitmap( KiBitmap( dialog_warning_xpm ) );
145 
147  m_dummyPad = new D_PAD( (MODULE*) NULL );
148 
149  if( aPad )
150  {
151  *m_dummyPad = *aPad;
153  }
154  else // We are editing a "master" pad, i.e. a template to create new pads
156 
157  initValues();
158 
159  wxFont infoFont = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
160  infoFont.SetSymbolicSize( wxFONTSIZE_SMALL );
161  m_techLayersLabel->SetFont( infoFont );
162  m_parentInfoLine1->SetFont( infoFont );
163  m_parentInfoLine2->SetFont( infoFont );
164  m_staticTextInfoNegVal->SetFont( infoFont );
165  m_staticTextInfoPosValue->SetFont( infoFont );
166  m_nonCopperNote->SetFont( infoFont );
167 
168  // Usually, TransferDataToWindow is called by OnInitDialog
169  // calling it here fixes all widget sizes so FinishDialogSettings can safely fix minsizes
171 
172  // Initialize canvas to be able to display the dummy pad:
173  prepareCanvas();
174 
176  m_sdbSizerOK->SetDefault();
177  m_canUpdate = true;
178 
179  m_PadNetSelector->Connect( NET_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ), NULL, this );
180 
181  // Now all widgets have the size fixed, call FinishDialogSettings
183 }
184 
185 
187 {
188  m_PadNetSelector->Disconnect( NET_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ), NULL, this );
189 
190  delete m_dummyPad;
191  delete m_axisOrigin;
192 }
193 
194 
195 bool DIALOG_PAD_PROPERTIES::m_sketchPreview = false; // Stores the pad draw option during a session
196 
197 
198 void DIALOG_PAD_PROPERTIES::OnInitDialog( wxInitDialogEvent& event )
199 {
200  m_selectedColor = COLOR4D( 1.0, 1.0, 1.0, 0.7 );
201 
202  // Needed on some WM to be sure the pad is redrawn according to the final size
203  // of the canvas, with the right zoom factor
204  redraw();
205 }
206 
207 
208 void DIALOG_PAD_PROPERTIES::OnCancel( wxCommandEvent& event )
209 {
210  // Mandatory to avoid m_panelShowPadGal trying to draw something
211  // in a non valid context during closing process:
212  if( m_parent->IsGalCanvasActive() )
214 
215  // Now call default handler for wxID_CANCEL command event
216  event.Skip();
217 }
218 
219 
221 {
222  // Enable or disable the widgets in page managing custom shape primitives
223  m_listCtrlPrimitives->Enable( aEnable );
224  m_buttonDel->Enable( aEnable );
225  m_buttonEditShape->Enable( aEnable );
226  m_buttonAddShape->Enable( aEnable );
227  m_buttonDup->Enable( aEnable );
228  m_buttonGeometry->Enable( aEnable );
229 }
230 
231 
233 {
234  // Initialize the canvases (legacy or gal) to display the pad
235 
236  // Show the X and Y axis. It is usefull because pad shape can have an offset
237  // or be a complex shape.
238  KIGFX::COLOR4D axis_color = LIGHTBLUE;
239 
241  Millimeter2iu( 0.2 ),
243  m_axisOrigin->SetDrawAtZero( true );
244 
245  if( m_parent->IsGalCanvasActive() )
246  {
250 
251  bool mousewheelPan = m_parent->GetCanvas()->GetEnableMousewheelPan();
253 
254  m_panelShowPadGal->Show();
255  m_panelShowPad->Hide();
256 
258 
259  // fix the pad render mode (filled/not filled)
260  auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
261  bool sketchMode = m_cbShowPadOutline->IsChecked();
262  settings->SetSketchMode( LAYER_PADS_TH, sketchMode );
263  settings->SetSketchMode( LAYER_PAD_FR, sketchMode );
264  settings->SetSketchMode( LAYER_PAD_BK, sketchMode );
265  settings->SetSketchModeGraphicItems( sketchMode );
266 
267  // gives a non null grid size (0.001mm) because GAL layer does not like a 0 size grid:
268  double gridsize = 0.001 * IU_PER_MM;
269  view->GetGAL()->SetGridSize( VECTOR2D( gridsize, gridsize ) );
270  // And do not show the grid:
271  view->GetGAL()->SetGridVisibility( false );
272  view->Add( m_dummyPad );
273  view->Add( m_axisOrigin );
274 
276  Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_PAD_PROPERTIES::OnResize ) );
277  }
278  else
279  {
280  m_panelShowPad->Show();
281  m_panelShowPadGal->Hide();
282  }
283 }
284 
285 
286 void DIALOG_PAD_PROPERTIES::OnPaintShowPanel( wxPaintEvent& event )
287 {
288  wxPaintDC dc( m_panelShowPad );
289  PAD_DRAWINFO drawInfo;
290 
292 
293  if( m_dummyPad->GetLayerSet()[F_Cu] )
295 
296  if( m_dummyPad->GetLayerSet()[B_Cu] )
298 
299  // What could happen: the pad color is *actually* black, or no copper was selected
300  if( color == BLACK )
301  color = LIGHTGRAY;
302 
303  drawInfo.m_Color = color;
304  drawInfo.m_HoleColor = DARKGRAY;
305  drawInfo.m_Offset = m_dummyPad->GetPosition();
306  drawInfo.m_Display_padnum = true;
307  drawInfo.m_Display_netname = true;
308  drawInfo.m_ShowPadFilled = !m_sketchPreview;
309 
311  drawInfo.m_ShowNotPlatedHole = true;
312 
313  // Shows the local pad clearance
315 
316  wxSize dc_size = dc.GetSize();
317  dc.SetDeviceOrigin( dc_size.x / 2, dc_size.y / 2 );
318 
319  // Calculate a suitable scale to fit the available draw area
320  int dim = m_dummyPad->GetBoundingRadius() *2;
321 
322  // Invalid x size. User could enter zero, or have deleted all text prior to
323  // entering a new value; this is also treated as zero. If dim is left at
324  // zero, the drawing scale is zero and we get a crash.
325  if( dim == 0 )
326  {
327  // If drill size has been set, use that. Otherwise default to 1mm.
328  dim = m_dummyPad->GetDrillSize().x;
329  if( dim == 0 )
330  dim = Millimeter2iu( 1.0 );
331  }
332 
333  if( m_dummyPad->GetLocalClearance() > 0 )
334  dim += m_dummyPad->GetLocalClearance() * 2;
335 
336  double scale = (double) dc_size.x / dim;
337 
338  // If the pad is a circle, use the x size here instead.
339  int ysize;
340 
342  ysize = m_dummyPad->GetSize().x;
343  else
344  ysize = m_dummyPad->GetSize().y;
345 
346  dim = ysize + std::abs( m_dummyPad->GetDelta().x );
347 
348  // Invalid y size. See note about x size above.
349  if( dim == 0 )
350  {
351  dim = m_dummyPad->GetDrillSize().y;
352  if( dim == 0 )
353  dim = Millimeter2iu( 0.1 );
354  }
355 
356  if( m_dummyPad->GetLocalClearance() > 0 )
357  dim += m_dummyPad->GetLocalClearance() * 2;
358 
359  double altscale = (double) dc_size.y / dim;
360  scale = std::min( scale, altscale );
361 
362  // Give a margin
363  scale *= 0.7;
364  dc.SetUserScale( scale, scale );
365 
366  GRResetPenAndBrush( &dc );
367  m_dummyPad->DrawShape( NULL, &dc, drawInfo );
368 
369  // draw selected primitives:
370  long select = m_listCtrlPrimitives->GetFirstSelected();
371 
372  while( select >= 0 )
373  {
374  PAD_CS_PRIMITIVE& primitive = m_primitives[select];
375 
376  // The best way to calculate parameters to draw a primitive is to
377  // use a dummy DRAWSEGMENT and use its methods
378  // Note: in legacy canvas, the pad has the 0,0 position
379  DRAWSEGMENT dummySegment;
380  primitive.ExportTo( &dummySegment );
381  dummySegment.Rotate( wxPoint( 0, 0), m_dummyPad->GetOrientation() );
382 
383  switch( primitive.m_Shape )
384  {
385  case S_SEGMENT: // usual segment : line with rounded ends
386  if( !m_sketchPreview )
387  GRFilledSegment( NULL, &dc, dummySegment.GetStart(), dummySegment.GetEnd(),
388  primitive.m_Thickness, m_selectedColor );
389  else
390  GRCSegm( NULL, &dc, dummySegment.GetStart(), dummySegment.GetEnd(),
391  primitive.m_Thickness, m_selectedColor );
392  break;
393 
394  case S_ARC: // Arc with rounded ends
395  if( !m_sketchPreview )
396  GRArc1( NULL, &dc, dummySegment.GetArcEnd(), dummySegment.GetArcStart(),
397  dummySegment.GetCenter(), primitive.m_Thickness, m_selectedColor );
398  else
399  {
400  GRArc1( NULL, &dc, dummySegment.GetArcEnd(), dummySegment.GetArcStart(),
401  dummySegment.GetCenter(), 0, m_selectedColor );
402 /* GRArc1( NULL, &dc, dummySegment.GetArcEnd(), dummySegment.GetArcStart(),
403  dummySegment.GetCenter() - primitive.m_Thickness, 0, m_selectedColor );*/
404  }
405  break;
406 
407  case S_CIRCLE: // ring or circle
408  if( primitive.m_Thickness )
409  {
410  if( !m_sketchPreview )
411  GRCircle( nullptr, &dc, dummySegment.GetCenter(), primitive.m_Radius,
412  primitive.m_Thickness, m_selectedColor );
413  else
414  {
415  GRCircle( nullptr, &dc, dummySegment.GetCenter(),
416  primitive.m_Radius + primitive.m_Thickness/2, 0, m_selectedColor );
417  GRCircle( nullptr, &dc, dummySegment.GetCenter(),
418  primitive.m_Radius - primitive.m_Thickness/2, 0, m_selectedColor );
419  }
420  }
421  else
422  {
423  if( !m_sketchPreview )
424  GRFilledCircle( nullptr, &dc, dummySegment.GetCenter(), primitive.m_Radius,
425  m_selectedColor );
426  else
427  GRCircle( nullptr, &dc, dummySegment.GetCenter(), primitive.m_Radius, 0,
428  m_selectedColor );
429  }
430  break;
431 
432  case S_POLYGON: // polygon
433  {
434  std::vector<wxPoint> poly = dummySegment.BuildPolyPointsList();
435  GRClosedPoly( nullptr, &dc, poly.size(), &poly[0], !m_sketchPreview,
437  }
438  break;
439 
440  default:
441  break;
442  }
443 
444  select = m_listCtrlPrimitives->GetNextSelected( select );
445  }
446 
447  // Draw X and Y axis. This is particularly useful to show the
448  // reference position of pads with offset and no hole, or custom pad shapes
449  const int t = 0; // line thickness
450  GRLine( nullptr, &dc, -int( dc_size.x/scale ), 0, int( dc_size.x/scale ), 0, t, LIGHTBLUE );
451  GRLine( nullptr, &dc, 0, -int( dc_size.y/scale ), 0, int( dc_size.y/scale ), t, LIGHTBLUE );
452 
453  event.Skip();
454 }
455 
456 
458 {
459  // Note: use m_tcCornerSizeRatio->ChangeValue() to avoid generating a wxEVT_TEXT event
460 
463  {
464  auto ratio = wxString::Format( "%.1f", m_dummyPad->GetRoundRectRadiusRatio() * 100 );
465  m_tcCornerSizeRatio->ChangeValue( ratio );
467 
468  ratio = wxString::Format( "%.1f", m_dummyPad->GetChamferRectRatio() * 100 );
469  m_tcChamferRatio->ChangeValue( ratio );
470  }
471  else if( m_dummyPad->GetShape() == PAD_SHAPE_RECT )
472  {
473  m_tcCornerSizeRatio->ChangeValue( "0" );
475  }
476  else
477  {
478  m_tcCornerSizeRatio->ChangeValue( wxEmptyString );
479  m_cornerRadius.SetValue( wxEmptyString );
480  }
481 }
482 
483 
484 void DIALOG_PAD_PROPERTIES::onCornerRadiusChange( wxCommandEvent& event )
485 {
488  return;
489 
490  wxString value = m_tcCornerRadius->GetValue();
491  double rrRadius;
492 
493  if( value.ToDouble( &rrRadius ) )
494  {
495  if( rrRadius < 0.0 )
496  {
497  rrRadius = 0.0;
498  m_tcCornerRadius->ChangeValue( "0.0" );
499  }
500 
502  m_dummyPad->SetRoundRectCornerRadius( Millimeter2iu( rrRadius ) );
503 
504  auto ratio = wxString::Format( "%.1f", m_dummyPad->GetRoundRectRadiusRatio() * 100 );
505  m_tcCornerSizeRatio->ChangeValue( ratio );
506  redraw();
507  }
508 }
509 
510 
512 {
515  return;
516 
517  wxString value = m_tcCornerSizeRatio->GetValue();
518  double ratioPercent;
519 
520  bool asChanged = false;
521 
522  if( value.ToDouble( &ratioPercent ) )
523  {
524  // Clamp ratioPercent to acceptable value (0.0 to 50.0)
525  if( ratioPercent < 0.0 )
526  {
527  ratioPercent = 0.0;
528  m_tcCornerSizeRatio->ChangeValue( "0.0" );
529  }
530 
531  if( ratioPercent > 50.0 )
532  {
533  ratioPercent = 0.5;
534  m_tcCornerSizeRatio->ChangeValue( "50.0" );
535  }
536 
537  asChanged = true;
538  }
539 
540  value = m_tcChamferRatio->GetValue();
541 
542  if( value.ToDouble( &ratioPercent ) )
543  {
544  // Clamp ratioPercent to acceptable value (0.0 to 50.0)
545  if( ratioPercent < 0.0 )
546  {
547  ratioPercent = 0.0;
548  m_tcChamferRatio->ChangeValue( "0.0" );
549  }
550 
551  if( ratioPercent > 50.0 )
552  {
553  ratioPercent = 0.5;
554  m_tcChamferRatio->ChangeValue( "50.0" );
555  }
556 
557  asChanged = true;
558  }
559 
560  if( asChanged )
561  {
564  redraw();
565  }
566 }
567 
568 
570 {
571  wxString msg;
572  double angle;
573 
574  // Disable pad net name wxTextCtrl if the caller is the footprint editor
575  // because nets are living only in the board managed by the board editor
577 
578 
579  // Setup layers names from board
580  // Should be made first, before calling m_rbCopperLayersSel->SetSelection()
581  m_rbCopperLayersSel->SetString( 0, m_board->GetLayerName( F_Cu ) );
582  m_rbCopperLayersSel->SetString( 1, m_board->GetLayerName( B_Cu ) );
583 
584  m_PadLayerAdhCmp->SetLabel( m_board->GetLayerName( F_Adhes ) );
585  m_PadLayerAdhCu->SetLabel( m_board->GetLayerName( B_Adhes ) );
587  m_PadLayerPateCu->SetLabel( m_board->GetLayerName( B_Paste ) );
589  m_PadLayerSilkCu->SetLabel( m_board->GetLayerName( B_SilkS ) );
590  m_PadLayerMaskCmp->SetLabel( m_board->GetLayerName( F_Mask ) );
591  m_PadLayerMaskCu->SetLabel( m_board->GetLayerName( B_Mask ) );
592  m_PadLayerECO1->SetLabel( m_board->GetLayerName( Eco1_User ) );
593  m_PadLayerECO2->SetLabel( m_board->GetLayerName( Eco2_User ) );
595 
596  m_isFlipped = false;
597 
598  if( m_currentPad )
599  {
601 
602  // Diplay parent footprint info
603  MODULE* footprint = m_currentPad->GetParent();
604  wxString msg1, msg2;
605 
606  if( footprint )
607  {
608  wxString side = footprint->IsFlipped() ? _( "back side (mirrored)" ) : _( "front side" );
609  msg1.Printf( _("Footprint %s (%s),"), footprint->GetReference(), footprint->GetValue() );
610  msg2.Printf( _("%s, rotated %.1f deg"), side, footprint->GetOrientation() / 10.0 );
611  }
612 
613  m_parentInfoLine1->SetLabel( msg1 );
614  m_parentInfoLine2->SetLabel( msg2 );
615  }
616 
617  if( m_isFlipped )
618  {
619  wxPoint pt = m_dummyPad->GetOffset();
620  pt.y = -pt.y;
621  m_dummyPad->SetOffset( pt );
622 
623  wxSize sz = m_dummyPad->GetDelta();
624  sz.y = -sz.y;
625  m_dummyPad->SetDelta( sz );
626 
627  // flip pad's layers
629 
630  // flip custom pad shapes
632  }
633 
635 
637 
638  m_PadNumCtrl->SetValue( m_dummyPad->GetName() );
640 
641  // Display current pad parameters units:
644 
647 
650 
653 
654  if( m_dummyPad->GetDelta().x )
655  {
657  m_trapAxisCtrl->SetSelection( 0 );
658  }
659  else
660  {
662  m_trapAxisCtrl->SetSelection( 1 );
663  }
664 
666 
672 
673  // Prefer "-0" to "0" for normally negative values
675  m_pasteClearanceCtrl->SetValue( wxT( "-" ) + m_pasteClearanceCtrl->GetValue() );
676 
677  msg.Printf( wxT( "%f" ), m_dummyPad->GetLocalSolderPasteMarginRatio() * 100.0 );
678 
679  if( m_dummyPad->GetLocalSolderPasteMarginRatio() == 0.0 && msg[0] == '0' )
680  // Sometimes Printf adds a sign if the value is small
681  m_SolderPasteMarginRatioCtrl->SetValue( wxT( "-" ) + msg );
682  else
684 
685  switch( m_dummyPad->GetZoneConnection() )
686  {
687  default:
689  m_ZoneConnectionChoice->SetSelection( 0 );
690  m_ZoneConnectionCustom->SetSelection( 0 );
691  break;
692 
693  case PAD_ZONE_CONN_FULL:
694  m_ZoneConnectionChoice->SetSelection( 1 );
695  m_ZoneConnectionCustom->SetSelection( 1 );
696  break;
697 
699  m_ZoneConnectionChoice->SetSelection( 2 );
700  m_ZoneConnectionCustom->SetSelection( 0 );
701  break;
702 
703  case PAD_ZONE_CONN_NONE:
704  m_ZoneConnectionChoice->SetSelection( 3 );
705  m_ZoneConnectionCustom->SetSelection( 0 );
706  break;
707  }
708 
710  m_ZoneCustomPadShape->SetSelection( 1 );
711  else
712  m_ZoneCustomPadShape->SetSelection( 0 );
713 
714  if( m_currentPad )
715  {
717  MODULE* footprint = m_currentPad->GetParent();
718 
719  if( footprint )
720  angle -= footprint->GetOrientation();
721 
722  if( m_isFlipped )
723  angle = -angle;
724 
726  }
727 
729 
730  NORMALIZE_ANGLE_180( angle ); // ? normalizing is in D_PAD::SetOrientation()
731 
732  // Set layers used by this pad: :
734 
735  // Pad Orient
736  // Note: use ChangeValue() instead of SetValue() so that we don't generate events
737  m_orientation->ChangeValue( StringFromValue( DEGREES, angle ) );
738 
739  switch( m_dummyPad->GetShape() )
740  {
741  default:
742  case PAD_SHAPE_CIRCLE: m_PadShape->SetSelection( CHOICE_SHAPE_CIRCLE ); break;
743  case PAD_SHAPE_OVAL: m_PadShape->SetSelection( CHOICE_SHAPE_OVAL ); break;
744  case PAD_SHAPE_RECT: m_PadShape->SetSelection( CHOICE_SHAPE_RECT ); break;
745  case PAD_SHAPE_TRAPEZOID: m_PadShape->SetSelection( CHOICE_SHAPE_TRAPEZOID ); break;
746  case PAD_SHAPE_ROUNDRECT: m_PadShape->SetSelection( CHOICE_SHAPE_ROUNDRECT ); break;
748 
749  case PAD_SHAPE_CUSTOM:
752  else
754  break;
755  }
756 
757 
762 
764 
765  // Type of pad selection
767  {
768  m_PadType->SetSelection( 4 );
769  }
770  else
771  {
772  switch( m_dummyPad->GetAttribute() )
773  {
774  case PAD_ATTRIB_STANDARD: m_PadType->SetSelection( 0 ); break;
775  case PAD_ATTRIB_SMD: m_PadType->SetSelection( 1 ); break;
776  case PAD_ATTRIB_CONN: m_PadType->SetSelection( 2 ); break;
777  case PAD_ATTRIB_HOLE_NOT_PLATED: m_PadType->SetSelection( 3 ); break;
778  }
779  }
780 
781  // Disable Pad name,and pad to die length for NPTH pads (mechanical pads)
783 
784  m_PadNumText->Enable( enable );
785  m_PadNumCtrl->Enable( enable );
786  m_PadNameText->Enable( enable && m_canEditNetName && m_currentPad );
787  m_PadNetSelector->Enable( enable && m_canEditNetName && m_currentPad );
788  m_padToDie.Enable( enable );
789 
791  m_holeShapeCtrl->SetSelection( 0 );
792  else
793  m_holeShapeCtrl->SetSelection( 1 );
794 
795  // Update some dialog widgets state (Enable/disable options):
796  wxCommandEvent cmd_event;
798  OnDrillShapeSelected( cmd_event );
799  OnPadShapeSelection( cmd_event );
801 
802  // Update basic shapes list
804 }
805 
806 // A small helper function, to display coordinates:
807 static wxString formatCoord( EDA_UNITS_T aUnits, wxPoint aCoord )
808 {
809  return wxString::Format( "(X:%s Y:%s)",
810  MessageTextFromValue( aUnits, aCoord.x, true ),
811  MessageTextFromValue( aUnits, aCoord.y, true ) );
812 }
813 
815 {
816  m_listCtrlPrimitives->ClearAll();
817 
818  wxListItem itemCol;
819  itemCol.SetImage(-1);
820 
821  for( int ii = 0; ii < 5; ++ii )
822  m_listCtrlPrimitives->InsertColumn(ii, itemCol);
823 
824  wxString bs_info[5];
825 
826  for( unsigned ii = 0; ii < m_primitives.size(); ++ii )
827  {
828  const PAD_CS_PRIMITIVE& primitive = m_primitives[ii];
829 
830  for( unsigned jj = 0; jj < 5; ++jj )
831  bs_info[jj].Empty();
832 
833  bs_info[4] = wxString::Format( _( "width %s" ),
834  MessageTextFromValue( m_units, primitive.m_Thickness, true ) );
835 
836  switch( primitive.m_Shape )
837  {
838  case S_SEGMENT: // usual segment : line with rounded ends
839  bs_info[0] = _( "Segment" );
840  bs_info[1] = _( "from " ) + formatCoord( m_units, primitive.m_Start );
841  bs_info[2] = _( "to " ) + formatCoord( m_units, primitive.m_End );
842  break;
843 
844  case S_ARC: // Arc with rounded ends
845  bs_info[0] = _( "Arc" );
846  bs_info[1] = _( "center " ) + formatCoord( m_units, primitive.m_Start );// Center
847  bs_info[2] = _( "start " ) + formatCoord( m_units, primitive.m_End ); // Start point
848  bs_info[3] = wxString::Format( _( "angle %s" ), FormatAngle( primitive.m_ArcAngle ) );
849  break;
850 
851  case S_CIRCLE: // ring or circle
852  if( primitive.m_Thickness )
853  bs_info[0] = _( "ring" );
854  else
855  bs_info[0] = _( "circle" );
856 
857  bs_info[1] = formatCoord( m_units, primitive.m_Start );
858  bs_info[2] = wxString::Format( _( "radius %s" ),
859  MessageTextFromValue( m_units, primitive.m_Radius, true ) );
860  break;
861 
862  case S_POLYGON: // polygon
863  bs_info[0] = "Polygon";
864  bs_info[1] = wxString::Format( _( "corners count %d" ), (int) primitive.m_Poly.size() );
865  break;
866 
867  default:
868  bs_info[0] = "Unknown primitive";
869  break;
870  }
871 
872  long tmp = m_listCtrlPrimitives->InsertItem(ii, bs_info[0]);
873  m_listCtrlPrimitives->SetItemData(tmp, ii);
874 
875  for( int jj = 0, col = 0; jj < 5; ++jj )
876  {
877  m_listCtrlPrimitives->SetItem(tmp, col++, bs_info[jj]);
878  }
879  }
880 
881  // Now columns are filled, ensure correct width of columns
882  for( unsigned ii = 0; ii < 5; ++ii )
883  m_listCtrlPrimitives->SetColumnWidth( ii, wxLIST_AUTOSIZE );
884 }
885 
886 void DIALOG_PAD_PROPERTIES::OnResize( wxSizeEvent& event )
887 {
888  redraw();
889  event.Skip();
890 }
891 
892 
893 void DIALOG_PAD_PROPERTIES::onChangePadMode( wxCommandEvent& event )
894 {
895  m_sketchPreview = m_cbShowPadOutline->GetValue();
896 
897  if( m_parent->IsGalCanvasActive() )
898  {
900 
901  // fix the pad render mode (filled/not filled)
902  KIGFX::PCB_RENDER_SETTINGS* settings =
903  static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
904 
909  }
910 
911  redraw();
912 }
913 
914 
915 
916 void DIALOG_PAD_PROPERTIES::OnPadShapeSelection( wxCommandEvent& event )
917 {
918  bool is_custom = false;
919 
920  switch( m_PadShape->GetSelection() )
921  {
922  case CHOICE_SHAPE_CIRCLE:
923  m_trapDelta.Enable( false );
924  m_trapAxisLabel->Enable( false );
925  m_trapAxisCtrl->Enable( false );
926  m_sizeY.Enable( false );
927  m_offsetX.Enable( false );
928  m_offsetY.Enable( false );
929  break;
930 
931  case CHOICE_SHAPE_OVAL:
932  m_trapDelta.Enable( false );
933  m_trapAxisLabel->Enable( false );
934  m_trapAxisCtrl->Enable( false );
935  m_sizeY.Enable( true );
936  m_offsetX.Enable( true );
937  m_offsetY.Enable( true );
938  break;
939 
940  case CHOICE_SHAPE_RECT:
941  m_trapDelta.Enable( false );
942  m_trapAxisLabel->Enable( false );
943  m_trapAxisCtrl->Enable( false );
944  m_sizeY.Enable( true );
945  m_offsetX.Enable( true );
946  m_offsetY.Enable( true );
947  break;
948 
950  m_trapDelta.Enable( true );
951  m_trapAxisLabel->Enable( true );
952  m_trapAxisCtrl->Enable( true );
953  m_sizeY.Enable( true );
954  m_offsetX.Enable( true );
955  m_offsetY.Enable( true );
956  break;
957 
960  m_trapDelta.Enable( false );
961  m_trapAxisLabel->Enable( false );
962  m_trapAxisCtrl->Enable( false );
963  m_sizeY.Enable( true );
964  m_offsetX.Enable( true );
965  m_offsetY.Enable( true );
966  // Ensure m_tcCornerSizeRatio contains the right value:
967  m_tcCornerSizeRatio->ChangeValue( wxString::Format( "%.1f",
969  break;
970 
971  case CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR: // PAD_SHAPE_CUSTOM, circular anchor
972  case CHOICE_SHAPE_CUSTOM_RECT_ANCHOR: // PAD_SHAPE_CUSTOM, rect anchor
973  is_custom = true;
974  m_trapDelta.Enable( false );
975  m_trapAxisLabel->Enable( false );
976  m_trapAxisCtrl->Enable( false );
978  m_offsetX.Enable( false );
979  m_offsetY.Enable( false );
980  break;
981  }
982 
983  enablePrimitivePage( is_custom );
984 
985  // A few widgets are enabled only for rounded rect and chamfered pads:
986  bool chamfered_rect_enable = m_PadShape->GetSelection() == CHOICE_SHAPE_CHAMFERED_RECT;
987  bool round_rect_enable = m_PadShape->GetSelection() == CHOICE_SHAPE_ROUNDRECT ||
988  chamfered_rect_enable;
989  m_staticTextCornerSizeRatio->Enable( round_rect_enable );
990  m_tcCornerSizeRatio->Enable( round_rect_enable );
991  m_staticTextCornerSizeRatioUnit->Enable( round_rect_enable );
992  m_cornerRadius.Enable( round_rect_enable );
993 
994  m_cbTopLeft->Enable( chamfered_rect_enable );
995  m_cbTopRight->Enable( chamfered_rect_enable );
996  m_cbBottomLeft->Enable( chamfered_rect_enable );
997  m_cbBottomRight->Enable( chamfered_rect_enable );
998  m_tcChamferRatio->Enable( chamfered_rect_enable );
999 
1000  // PAD_SHAPE_CUSTOM type has constraints for zone connection and thermal shape:
1001  // only not connected or solid connection is allowed to avoid destroying the shape.
1002  // Enable/disable options only available for custom shaped pads
1003  m_ZoneConnectionChoice->Enable( !is_custom );
1004  m_ZoneConnectionCustom->Enable( is_custom );
1005  m_spokeWidth.Enable( !is_custom );
1006  m_thermalGap.Enable( !is_custom );
1007 
1008  m_sbSizerZonesSettings->Show( !is_custom );
1009  m_sbSizerCustomShapedZonesSettings->Show( is_custom );
1010 
1012 
1014  redraw();
1015 }
1016 
1017 
1018 void DIALOG_PAD_PROPERTIES::OnDrillShapeSelected( wxCommandEvent& event )
1019 {
1021  redraw();
1022 }
1023 
1024 
1025 void DIALOG_PAD_PROPERTIES::PadOrientEvent( wxCommandEvent& event )
1026 {
1028  redraw();
1029 }
1030 
1031 
1032 void DIALOG_PAD_PROPERTIES::PadTypeSelected( wxCommandEvent& event )
1033 {
1034  int ii = m_PadType->GetSelection();
1035 
1036  if( (unsigned)ii >= arrayDim( code_type ) ) // catches < 0 also
1037  ii = 0;
1038 
1039  bool hasHole, hasConnection;
1040 
1041  switch( ii )
1042  {
1043  default:
1044  case 0: /* PTH */ hasHole = true; hasConnection = true; break;
1045  case 1: /* SMD */ hasHole = false; hasConnection = true; break;
1046  case 2: /* CONN */ hasHole = false; hasConnection = true; break;
1047  case 3: /* NPTH */ hasHole = true; hasConnection = false; break;
1048  case 4: /* Aperture */ hasHole = false; hasConnection = false; break;
1049  }
1050 
1051  LSET layer_mask = std_pad_layers[ii];
1052  setPadLayersList( layer_mask );
1053 
1054  if( !hasHole )
1055  {
1056  m_holeX.SetValue( 0 );
1057  m_holeY.SetValue( 0 );
1058  }
1059  else if ( m_holeX.GetValue() == 0 && m_currentPad )
1060  {
1063  }
1064 
1065  if( !hasConnection )
1066  {
1067  m_PadNumCtrl->SetValue( wxEmptyString );
1069  m_padToDie.SetValue( 0 );
1070  }
1071  else if( m_PadNumCtrl->GetValue().IsEmpty() && m_currentPad )
1072  {
1073  m_PadNumCtrl->SetValue( m_currentPad->GetName() );
1075  }
1076 
1078  redraw();
1079 }
1080 
1081 
1082 void DIALOG_PAD_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
1083 {
1084  int ii = m_PadType->GetSelection();
1085 
1086  if( (unsigned)ii >= arrayDim( code_type ) ) // catches < 0 also
1087  ii = 0;
1088 
1089  bool hasHole, hasConnection;
1090 
1091  switch( ii )
1092  {
1093  default:
1094  case 0: /* PTH */ hasHole = true; hasConnection = true; break;
1095  case 1: /* SMD */ hasHole = false; hasConnection = true; break;
1096  case 2: /* CONN */ hasHole = false; hasConnection = true; break;
1097  case 3: /* NPTH */ hasHole = true; hasConnection = false; break;
1098  case 4: /* Aperture */ hasHole = false; hasConnection = false; break;
1099  }
1100 
1101  // Enable/disable hole controls
1102  m_holeShapeLabel->Enable( hasHole );
1103  m_holeShapeCtrl->Enable( hasHole );
1104  m_holeX.Enable( hasHole );
1105  m_holeY.Enable( hasHole && m_holeShapeCtrl->GetSelection() == 1 );
1106 
1107  // Enable/disable Pad number, net and pad length-to-die
1108  m_PadNumText->Enable( hasConnection );
1109  m_PadNumCtrl->Enable( hasConnection );
1110  m_PadNameText->Enable( hasConnection );
1111  m_PadNetSelector->Enable( hasConnection && m_canEditNetName && m_currentPad );
1112  m_padToDie.Enable( hasConnection );
1113 
1114  // Enable/disable Copper Layers control
1115  m_rbCopperLayersSel->Enable( ii != 4 );
1116 }
1117 
1118 
1120 {
1121  LSET cu_set = layer_mask & LSET::AllCuMask();
1122 
1123  if( cu_set == LSET( F_Cu ) )
1124  m_rbCopperLayersSel->SetSelection( 0 );
1125  else if( cu_set == LSET( B_Cu ) )
1126  m_rbCopperLayersSel->SetSelection( 1 );
1127  else if( cu_set.any() )
1128  m_rbCopperLayersSel->SetSelection( 2 );
1129  else
1130  m_rbCopperLayersSel->SetSelection( 3 );
1131 
1132  m_PadLayerAdhCmp->SetValue( layer_mask[F_Adhes] );
1133  m_PadLayerAdhCu->SetValue( layer_mask[B_Adhes] );
1134 
1135  m_PadLayerPateCmp->SetValue( layer_mask[F_Paste] );
1136  m_PadLayerPateCu->SetValue( layer_mask[B_Paste] );
1137 
1138  m_PadLayerSilkCmp->SetValue( layer_mask[F_SilkS] );
1139  m_PadLayerSilkCu->SetValue( layer_mask[B_SilkS] );
1140 
1141  m_PadLayerMaskCmp->SetValue( layer_mask[F_Mask] );
1142  m_PadLayerMaskCu->SetValue( layer_mask[B_Mask] );
1143 
1144  m_PadLayerECO1->SetValue( layer_mask[Eco1_User] );
1145  m_PadLayerECO2->SetValue( layer_mask[Eco2_User] );
1146 
1147  m_PadLayerDraft->SetValue( layer_mask[Dwgs_User] );
1148 }
1149 
1150 
1151 // Called when select/deselect a layer.
1152 void DIALOG_PAD_PROPERTIES::OnSetLayers( wxCommandEvent& event )
1153 {
1155  redraw();
1156 }
1157 
1158 
1159 // test if all values are acceptable for the pad
1161 {
1162  bool error = transferDataToPad( m_dummyPad );
1163  bool skip_tstoffset = false; // the offset prm is not always tested
1164 
1165  wxArrayString error_msgs;
1166  wxString msg;
1167 
1168  // Test for incorrect values
1169  if( (m_dummyPad->GetSize().x <= 0) ||
1170  ((m_dummyPad->GetSize().y <= 0) && (m_dummyPad->GetShape() != PAD_SHAPE_CIRCLE)) )
1171  {
1172  error_msgs.Add( _( "Pad size must be greater than zero" ) );
1173  }
1174 
1175  if( (m_dummyPad->GetSize().x < m_dummyPad->GetDrillSize().x) ||
1176  (m_dummyPad->GetSize().y < m_dummyPad->GetDrillSize().y) )
1177  {
1178  error_msgs.Add( _( "Incorrect value for pad drill: pad drill bigger than pad size" ) );
1179  skip_tstoffset = true; // offset prm will be not tested because if the drill value
1180  // is incorrect the offset prm is always seen as incorrect, even if it is 0
1181  }
1182 
1183  if( m_dummyPad->GetLocalClearance() < 0 )
1184  {
1185  error_msgs.Add( _( "Pad local clearance must be zero or greater than zero" ) );
1186  }
1187 
1188  // Some pads need a negative solder mask clearance (mainly for BGA with small pads)
1189  // However the negative solder mask clearance must not create negative mask size
1190  // Therefore test for minimal acceptable negative value
1191  // Hovewer, a negative value can give strange result with custom shapes, so it is not
1192  // allowed for custom pad shape
1194  {
1196  error_msgs.Add( _( "Pad local solder mask clearance must be zero or greater than zero" ) );
1197  else
1198  {
1199  int min_smClearance = -std::min( m_dummyPad->GetSize().x, m_dummyPad->GetSize().y )/2;
1200 
1201  if( m_dummyPad->GetLocalSolderMaskMargin() <= min_smClearance )
1202  {
1203  error_msgs.Add( wxString::Format(
1204  _( "Pad local solder mask clearance must be greater than %s" ),
1205  StringFromValue( GetUserUnits(), min_smClearance, true, true ) ) );
1206  }
1207  }
1208  }
1209 
1210  // Some pads need a positive solder paste clearance (mainly for BGA with small pads)
1211  // Hovewer, a positive value can create issues if the resulting shape is too big.
1212  // (like a solder paste creating a solder paste area on a neighbour pad or on the solder mask)
1213  // So we could ask for user to confirm the choice
1214  // Currently there are no test
1215 
1216  LSET padlayers_mask = m_dummyPad->GetLayerSet();
1217 
1218  if( padlayers_mask == 0 )
1219  error_msgs.Add( _( "Error: pad has no layer" ) );
1220 
1221  if( !padlayers_mask[F_Cu] && !padlayers_mask[B_Cu] )
1222  {
1223  if( m_dummyPad->GetDrillSize().x || m_dummyPad->GetDrillSize().y )
1224  {
1225  // Note: he message is shown in an HTML window
1226  msg = _( "Error: the pad is not on a copper layer and has a hole" );
1227 
1229  {
1230  msg += wxT( "<br><br><i>" );
1231  msg += _( "For NPTH pad, set pad size value to pad drill value,"
1232  " if you do not want this pad plotted in gerber files" );
1233  }
1234 
1235  error_msgs.Add( msg );
1236  }
1237  }
1238 
1239  if( !skip_tstoffset )
1240  {
1241  wxPoint max_size;
1242  max_size.x = std::abs( m_dummyPad->GetOffset().x );
1243  max_size.y = std::abs( m_dummyPad->GetOffset().y );
1244  max_size.x += m_dummyPad->GetDrillSize().x / 2;
1245  max_size.y += m_dummyPad->GetDrillSize().y / 2;
1246 
1247  if( ( m_dummyPad->GetSize().x / 2 < max_size.x ) ||
1248  ( m_dummyPad->GetSize().y / 2 < max_size.y ) )
1249  {
1250  error_msgs.Add( _( "Incorrect value for pad offset" ) );
1251  }
1252  }
1253 
1254  if( error )
1255  error_msgs.Add( _( "Too large value for pad delta size" ) );
1256 
1257  switch( m_dummyPad->GetAttribute() )
1258  {
1259  case PAD_ATTRIB_HOLE_NOT_PLATED: // Not plated, but through hole, a hole is expected
1260  case PAD_ATTRIB_STANDARD : // Pad through hole, a hole is also expected
1261  if( m_dummyPad->GetDrillSize().x <= 0 ||
1263  error_msgs.Add( _( "Error: Through hole pad: drill diameter set to 0" ) );
1264  break;
1265 
1266  case PAD_ATTRIB_CONN: // Connector pads are smd pads, just they do not have solder paste.
1267  if( padlayers_mask[B_Paste] || padlayers_mask[F_Paste] )
1268  error_msgs.Add( _( "Error: Connector pads are not on the solder paste layer\n"
1269  "Use SMD pads instead" ) );
1270  // Fall trough
1271  case PAD_ATTRIB_SMD: // SMD and Connector pads (One external copper layer only)
1272  {
1273  LSET innerlayers_mask = padlayers_mask & LSET::InternalCuMask();
1274 
1275  if( ( padlayers_mask[F_Cu] && padlayers_mask[B_Cu] ) ||
1276  innerlayers_mask.count() != 0 )
1277  error_msgs.Add( _( "Error: only one external copper layer allowed for SMD or Connector pads" ) );
1278  }
1279  break;
1280  }
1281 
1282 
1285  {
1286  wxString value = m_tcCornerSizeRatio->GetValue();
1287  double rrRadiusRatioPercent;
1288 
1289  if( !value.ToDouble( &rrRadiusRatioPercent ) )
1290  error_msgs.Add( _( "Incorrect corner size value" ) );
1291  else
1292  {
1293  if( rrRadiusRatioPercent < 0.0 )
1294  error_msgs.Add( _( "Incorrect (negative) corner size value" ) );
1295  else if( rrRadiusRatioPercent > 50.0 )
1296  error_msgs.Add( _( "Corner size value must be smaller than 50%" ) );
1297  }
1298  }
1299 
1301  {
1303  error_msgs.Add( _( "Incorrect pad shape: the shape must be equivalent to only one polygon" ) );
1304  }
1305 
1306 
1307  if( error_msgs.GetCount() )
1308  {
1309  HTML_MESSAGE_BOX dlg( this, _("Pad setup errors list" ) );
1310  dlg.ListSet( error_msgs );
1311  dlg.ShowModal();
1312  }
1313 
1314  return error_msgs.GetCount() == 0;
1315 }
1316 
1317 
1319 {
1320  if( m_parent->IsGalCanvasActive() )
1321  {
1324 
1325  // The layer used to place primitive items selected when editing custom pad shapes
1326  // we use here a layer never used in a pad:
1327  #define SELECTED_ITEMS_LAYER Dwgs_User
1328 
1330  KIGFX::PCB_RENDER_SETTINGS* settings =
1331  static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
1333 
1334  view->Update( m_dummyPad );
1335 
1336  // delete previous items if highlight list
1337  while( m_highlight.size() )
1338  {
1339  delete m_highlight.back(); // the dtor also removes item from view
1340  m_highlight.pop_back();
1341  }
1342 
1343  // highlight selected primitives:
1344  long select = m_listCtrlPrimitives->GetFirstSelected();
1345 
1346  while( select >= 0 )
1347  {
1348  PAD_CS_PRIMITIVE& primitive = m_primitives[select];
1349 
1350  DRAWSEGMENT* dummySegment = new DRAWSEGMENT;
1351  dummySegment->SetLayer( SELECTED_ITEMS_LAYER );
1352  primitive.ExportTo( dummySegment );
1353  dummySegment->Rotate( wxPoint( 0, 0), m_dummyPad->GetOrientation() );
1354  dummySegment->Move( m_dummyPad->GetPosition() );
1355 
1356  // Update selected primitive (highligth selected)
1357  switch( primitive.m_Shape )
1358  {
1359  case S_SEGMENT:
1360  case S_ARC:
1361  break;
1362 
1363  case S_CIRCLE: // ring or circle
1364  if( primitive.m_Thickness == 0 ) // filled circle
1365  { // the filled circle option does not exist in a DRAWSEGMENT
1366  // but it is easy to create it with a circle having the
1367  // right radius and outline width
1368  wxPoint end = dummySegment->GetCenter();
1369  end.x += primitive.m_Radius/2;
1370  dummySegment->SetEnd( end );
1371  dummySegment->SetWidth( primitive.m_Radius );
1372  }
1373  break;
1374 
1375  case S_POLYGON:
1376  break;
1377 
1378  default:
1379  delete dummySegment;
1380  dummySegment = nullptr;
1381  break;
1382  }
1383 
1384  if( dummySegment )
1385  {
1386  view->Add( dummySegment );
1387  m_highlight.push_back( dummySegment );
1388  }
1389 
1390  select = m_listCtrlPrimitives->GetNextSelected( select );
1391  }
1392 
1393  BOX2I bbox = m_dummyPad->ViewBBox();
1394 
1395  if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
1396  {
1397  // gives a size to the full drawable area
1398  BOX2I drawbox;
1399  drawbox.Move( m_dummyPad->GetPosition() );
1400  drawbox.Inflate( bbox.GetSize().x*2, bbox.GetSize().y*2 );
1401 
1402  view->SetBoundary( drawbox );
1403 
1404  // Autozoom
1405  view->SetViewport( BOX2D( bbox.GetOrigin(), bbox.GetSize() ) );
1406 
1407  // Add a margin
1408  view->SetScale( m_panelShowPadGal->GetView()->GetScale() * 0.7 );
1409 
1412  }
1413  }
1414  else
1415  {
1416  m_panelShowPad->Refresh();
1417  }
1418 }
1419 
1420 
1422 {
1423  if( !wxDialog::TransferDataToWindow() )
1424  return false;
1425 
1426  if( !m_panelGeneral->TransferDataToWindow() )
1427  return false;
1428 
1429  if( !m_localSettingsPanel->TransferDataToWindow() )
1430  return false;
1431 
1432  return true;
1433 }
1434 
1435 
1437 {
1438  BOARD_COMMIT commit( m_parent );
1439 
1440  if( !wxDialog::TransferDataFromWindow() )
1441  return false;
1442 
1443  if( !m_panelGeneral->TransferDataFromWindow() )
1444  return false;
1445 
1446  if( !m_localSettingsPanel->TransferDataFromWindow() )
1447  return false;
1448 
1449  if( !padValuesOK() )
1450  return false;
1451 
1452  bool rastnestIsChanged = false;
1453  int isign = m_isFlipped ? -1 : 1;
1454 
1456  // m_padMaster is a pattern: ensure there is no net for this pad:
1458 
1459  if( !m_currentPad ) // Set current Pad parameters
1460  return true;
1461 
1462  commit.Modify( m_currentPad );
1463 
1464  // redraw the area where the pad was, without pad (delete pad on screen)
1468 
1469  // Update values
1472 
1474  {
1476  rastnestIsChanged = true;
1477  }
1478 
1479  wxSize size;
1480  MODULE* footprint = m_currentPad->GetParent();
1481 
1482  if( footprint )
1483  {
1484  footprint->SetLastEditTime();
1485 
1486  // compute the pos 0 value, i.e. pad position for footprint with orientation = 0
1487  // i.e. relative to footprint origin (footprint position)
1488  wxPoint pt = m_currentPad->GetPosition() - footprint->GetPosition();
1489  RotatePoint( &pt, -footprint->GetOrientation() );
1490  m_currentPad->SetPos0( pt );
1492  + footprint->GetOrientation() );
1493  }
1494 
1496 
1497  size = m_padMaster->GetDelta();
1498  size.y *= isign;
1499  m_currentPad->SetDelta( size );
1500 
1503 
1504  wxPoint offset = m_padMaster->GetOffset();
1505  offset.y *= isign;
1506  m_currentPad->SetOffset( offset );
1507 
1509 
1512 
1513 
1516 
1517  if( m_isFlipped )
1518  {
1521  }
1522 
1524  {
1525  rastnestIsChanged = true;
1527  }
1528 
1529  if( m_isFlipped )
1530  {
1532  }
1533 
1535 
1536  int padNetcode = NETINFO_LIST::UNCONNECTED;
1537 
1538  // For PAD_ATTRIB_HOLE_NOT_PLATED, ensure there is no net name selected
1540  padNetcode = m_PadNetSelector->GetSelectedNetcode();
1541 
1542  if( m_currentPad->GetNetCode() != padNetcode )
1543  {
1544  rastnestIsChanged = true;
1545  m_currentPad->SetNetCode( padNetcode );
1546  }
1547 
1557 
1559  {
1562  else
1564  }
1565  else
1567 
1568 
1569  // rounded rect pads with radius ratio = 0 are in fact rect pads.
1570  // So set the right shape (and perhaps issues with a radius = 0)
1573  {
1575  }
1576 
1577  // define the way the clearance area is defined in zones
1579 
1580  if( footprint )
1581  footprint->CalculateBoundingBox();
1582 
1584 
1585  // redraw the area where the pad was
1587 
1588  commit.Push( _( "Modify pad" ) );
1589 
1590  if( rastnestIsChanged ) // The net ratsnest must be recalculated
1591  m_board->m_Status_Pcb = 0;
1592 
1593  return true;
1594 }
1595 
1596 
1598 {
1599  wxString msg;
1600 
1601  if( !Validate() )
1602  return true;
1603  if( !m_panelGeneral->Validate() )
1604  return true;
1605  if( !m_localSettingsPanel->Validate() )
1606  return true;
1607  if( !m_spokeWidth.Validate( 0, INT_MAX ) )
1608  return false;
1609 
1610  m_OrientValidator.TransferFromWindow();
1611 
1612  aPad->SetAttribute( code_type[m_PadType->GetSelection()] );
1613  aPad->SetShape( code_shape[m_PadShape->GetSelection()] );
1616 
1617  if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
1618  aPad->SetPrimitives( m_primitives );
1619 
1620  // Read pad clearances values:
1625  aPad->SetThermalGap( m_thermalGap.GetValue() );
1626  double dtmp = 0.0;
1627  msg = m_SolderPasteMarginRatioCtrl->GetValue();
1628  msg.ToDouble( &dtmp );
1629 
1630  // A -50% margin ratio means no paste on a pad, the ratio must be >= -50%
1631  if( dtmp < -50.0 )
1632  dtmp = -50.0;
1633  // A margin ratio is always <= 0
1634  // 0 means use full pad copper area
1635  if( dtmp > 0.0 )
1636  dtmp = 0.0;
1637 
1638  aPad->SetLocalSolderPasteMarginRatio( dtmp / 100 );
1639 
1640  switch( m_ZoneConnectionChoice->GetSelection() )
1641  {
1642  default:
1643  case 0: aPad->SetZoneConnection( PAD_ZONE_CONN_INHERITED ); break;
1644  case 1: aPad->SetZoneConnection( PAD_ZONE_CONN_FULL ); break;
1645  case 2: aPad->SetZoneConnection( PAD_ZONE_CONN_THERMAL ); break;
1646  case 3: aPad->SetZoneConnection( PAD_ZONE_CONN_NONE ); break;
1647  }
1648 
1649  // Custom shape has only 2 options:
1650  if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
1651  {
1652  if( m_ZoneConnectionCustom->GetSelection() == 0 )
1654  else
1656  }
1657 
1658  aPad->SetPosition( wxPoint( m_posX.GetValue(), m_posY.GetValue() ) );
1659  aPad->SetPos0( wxPoint( m_posX.GetValue(), m_posY.GetValue() ) );
1660 
1661  if( m_holeShapeCtrl->GetSelection() == 0 )
1662  {
1664  aPad->SetDrillSize( wxSize( m_holeX.GetValue(), m_holeX.GetValue() ) );
1665  }
1666  else
1667  {
1669  aPad->SetDrillSize( wxSize( m_holeX.GetValue(), m_holeY.GetValue() ) );
1670  }
1671 
1672  if( aPad->GetShape() == PAD_SHAPE_CIRCLE )
1673  aPad->SetSize( wxSize( m_sizeX.GetValue(), m_sizeX.GetValue() ) );
1674  else
1675  aPad->SetSize( wxSize( m_sizeX.GetValue(), m_sizeY.GetValue() ) );
1676 
1677  // Read pad length die
1679 
1680  // For a trapezoid, test delta value (be sure delta is not too large for pad size)
1681  // remember DeltaSize.x is the Y size variation
1682  bool error = false;
1683 
1684  if( aPad->GetShape() == PAD_SHAPE_TRAPEZOID )
1685  {
1686  wxSize delta;
1687 
1688  // For a trapezoid, only one of delta.x or delta.y is not 0, depending on
1689  // the direction.
1690  if( m_trapAxisCtrl->GetSelection() == 0 )
1691  delta.x = m_trapDelta.GetValue();
1692  else
1693  delta.y = m_trapDelta.GetValue();
1694 
1695  if( delta.x < 0 && delta.x <= -aPad->GetSize().y )
1696  {
1697  delta.x = -aPad->GetSize().y + 2;
1698  error = true;
1699  }
1700 
1701  if( delta.x > 0 && delta.x >= aPad->GetSize().y )
1702  {
1703  delta.x = aPad->GetSize().y - 2;
1704  error = true;
1705  }
1706 
1707  if( delta.y < 0 && delta.y <= -aPad->GetSize().x )
1708  {
1709  delta.y = -aPad->GetSize().x + 2;
1710  error = true;
1711  }
1712 
1713  if( delta.y > 0 && delta.y >= aPad->GetSize().x )
1714  {
1715  delta.y = aPad->GetSize().x - 2;
1716  error = true;
1717  }
1718 
1719  aPad->SetDelta( delta );
1720  }
1721 
1722  aPad->SetOffset( wxPoint( m_offsetX.GetValue(), m_offsetY.GetValue() ) );
1723  aPad->SetOrientation( m_OrientValue * 10.0 );
1724  aPad->SetName( m_PadNumCtrl->GetValue() );
1726 
1727  int chamfers = 0;
1728 
1729  if( m_cbTopLeft->GetValue() )
1730  chamfers |= RECT_CHAMFER_TOP_LEFT;
1731 
1732  if( m_cbTopRight->GetValue() )
1733  chamfers |= RECT_CHAMFER_TOP_RIGHT;
1734 
1735  if( m_cbBottomLeft->GetValue() )
1736  chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1737 
1738  if( m_cbBottomRight->GetValue() )
1739  chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1740 
1741  aPad->SetChamferPositions( chamfers );
1742 
1743  // Clear some values, according to the pad type and shape
1744  switch( aPad->GetShape() )
1745  {
1746  case PAD_SHAPE_CIRCLE:
1747  aPad->SetOffset( wxPoint( 0, 0 ) );
1748  aPad->SetDelta( wxSize( 0, 0 ) );
1749  break;
1750 
1751  case PAD_SHAPE_RECT:
1752  aPad->SetDelta( wxSize( 0, 0 ) );
1753  break;
1754 
1755  case PAD_SHAPE_OVAL:
1756  aPad->SetDelta( wxSize( 0, 0 ) );
1757  break;
1758 
1759  case PAD_SHAPE_TRAPEZOID:
1760  break;
1761 
1762  case PAD_SHAPE_ROUNDRECT:
1764  aPad->SetDelta( wxSize( 0, 0 ) );
1765  break;
1766 
1767  case PAD_SHAPE_CUSTOM:
1768  aPad->SetOffset( wxPoint( 0, 0 ) );
1769  aPad->SetDelta( wxSize( 0, 0 ) );
1770 
1771  // The pad custom has a "anchor pad" (a basic shape: round or rect pad)
1772  // that is the minimal area of this pad, and is usefull to ensure a hole
1773  // diameter is acceptable, and is used in Gerber files as flashed area
1774  // reference
1775  if( aPad->GetAnchorPadShape() == PAD_SHAPE_CIRCLE )
1776  aPad->SetSize( wxSize( m_sizeX.GetValue(), m_sizeX.GetValue() ) );
1777 
1778  // define the way the clearance area is defined in zones
1779  aPad->SetCustomShapeInZoneOpt( m_ZoneCustomPadShape->GetSelection() == 0 ?
1782  break;
1783 
1784  default:
1785  ;
1786  }
1787 
1788  switch( aPad->GetAttribute() )
1789  {
1790  case PAD_ATTRIB_STANDARD:
1791  break;
1792 
1793  case PAD_ATTRIB_CONN:
1794  case PAD_ATTRIB_SMD:
1795  // SMD and PAD_ATTRIB_CONN has no hole.
1796  // basically, SMD and PAD_ATTRIB_CONN are same type of pads
1797  // PAD_ATTRIB_CONN has just a default non technical layers that differs from SMD
1798  // and are intended to be used in virtual edge board connectors
1799  // However we can accept a non null offset,
1800  // mainly to allow complex pads build from a set of basic pad shapes
1801  aPad->SetDrillSize( wxSize( 0, 0 ) );
1802  break;
1803 
1805  // Mechanical purpose only:
1806  // no offset, no net name, no pad name allowed
1807  aPad->SetOffset( wxPoint( 0, 0 ) );
1808  aPad->SetName( wxEmptyString );
1810  break;
1811 
1812  default:
1813  DisplayError( NULL, wxT( "Error: unknown pad type" ) );
1814  break;
1815  }
1816 
1817  if( aPad->GetShape() == PAD_SHAPE_ROUNDRECT || aPad->GetShape() == PAD_SHAPE_CHAMFERED_RECT )
1818  {
1819  wxString value = m_tcCornerSizeRatio->GetValue();
1820  double ratioPercent;
1821 
1822  if( value.ToDouble( &ratioPercent ) )
1823  aPad->SetRoundRectRadiusRatio( ratioPercent / 100.0 );
1824 
1825  value = m_tcChamferRatio->GetValue();
1826 
1827  if( value.ToDouble( &ratioPercent ) )
1828  aPad->SetChamferRectRatio( ratioPercent / 100.0 );
1829  }
1830 
1831  LSET padLayerMask;
1832 
1833  switch( m_rbCopperLayersSel->GetSelection() )
1834  {
1835  case 0: padLayerMask.set( F_Cu ); break;
1836  case 1: padLayerMask.set( B_Cu ); break;
1837  case 2: padLayerMask |= LSET::AllCuMask(); break;
1838  case 3: break; // No copper layers
1839  }
1840 
1841  if( m_PadLayerAdhCmp->GetValue() )
1842  padLayerMask.set( F_Adhes );
1843 
1844  if( m_PadLayerAdhCu->GetValue() )
1845  padLayerMask.set( B_Adhes );
1846 
1847  if( m_PadLayerPateCmp->GetValue() )
1848  padLayerMask.set( F_Paste );
1849 
1850  if( m_PadLayerPateCu->GetValue() )
1851  padLayerMask.set( B_Paste );
1852 
1853  if( m_PadLayerSilkCmp->GetValue() )
1854  padLayerMask.set( F_SilkS );
1855 
1856  if( m_PadLayerSilkCu->GetValue() )
1857  padLayerMask.set( B_SilkS );
1858 
1859  if( m_PadLayerMaskCmp->GetValue() )
1860  padLayerMask.set( F_Mask );
1861 
1862  if( m_PadLayerMaskCu->GetValue() )
1863  padLayerMask.set( B_Mask );
1864 
1865  if( m_PadLayerECO1->GetValue() )
1866  padLayerMask.set( Eco1_User );
1867 
1868  if( m_PadLayerECO2->GetValue() )
1869  padLayerMask.set( Eco2_User );
1870 
1871  if( m_PadLayerDraft->GetValue() )
1872  padLayerMask.set( Dwgs_User );
1873 
1874  aPad->SetLayerSet( padLayerMask );
1875 
1876  return error;
1877 }
1878 
1879 
1880 void DIALOG_PAD_PROPERTIES::OnValuesChanged( wxCommandEvent& event )
1881 {
1882  if( m_canUpdate )
1883  {
1885  // If the pad size has changed, update the displayed values
1886  // for rounded rect pads
1888 
1889  redraw();
1890  }
1891 }
1892 
1894 {
1895  long select = m_listCtrlPrimitives->GetFirstSelected();
1896 
1897  if( select < 0 )
1898  {
1899  wxMessageBox( _( "No shape selected" ) );
1900  return;
1901  }
1902 
1903  PAD_CS_PRIMITIVE& shape = m_primitives[select];
1904 
1905  if( shape.m_Shape == S_POLYGON )
1906  {
1907  DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, m_parent, &shape );
1908 
1909  if( dlg.ShowModal() != wxID_OK )
1910  return;
1911 
1912  dlg.TransferDataFromWindow();
1913  }
1914 
1915  else
1916  {
1917  DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, m_parent, &shape );
1918 
1919  if( dlg.ShowModal() != wxID_OK )
1920  return;
1921 
1922  dlg.TransferDataFromWindow();
1923  }
1924 
1926 
1927  if( m_canUpdate )
1928  {
1930  redraw();
1931  }
1932 }
1933 
1934 
1936 {
1937  // Called on a double click on the basic shapes list
1938  // To Do: highligth the primitive(s) currently selected.
1939  redraw();
1940 }
1941 
1942 
1944 void DIALOG_PAD_PROPERTIES::onPrimitiveDClick( wxMouseEvent& event )
1945 {
1946  editPrimitive();
1947 }
1948 
1949 
1950 // Called on a click on basic shapes list panel button
1951 void DIALOG_PAD_PROPERTIES::onEditPrimitive( wxCommandEvent& event )
1952 {
1953  editPrimitive();
1954 }
1955 
1956 // Called on a click on basic shapes list panel button
1957 void DIALOG_PAD_PROPERTIES::onDeletePrimitive( wxCommandEvent& event )
1958 {
1959  long select = m_listCtrlPrimitives->GetFirstSelected();
1960 
1961  if( select < 0 )
1962  return;
1963 
1964  // Multiple selections are allowed. get them and remove corresponding shapes
1965  std::vector<long> indexes;
1966  indexes.push_back( select );
1967 
1968  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
1969  indexes.push_back( select );
1970 
1971  // Erase all select shapes
1972  for( unsigned ii = indexes.size(); ii > 0; --ii )
1973  m_primitives.erase( m_primitives.begin() + indexes[ii-1] );
1974 
1976 
1977  if( m_canUpdate )
1978  {
1980  redraw();
1981  }
1982 }
1983 
1984 
1985 void DIALOG_PAD_PROPERTIES::onAddPrimitive( wxCommandEvent& event )
1986 {
1987  // Ask user for shape type
1988  wxString shapelist[] = { _( "Segment" ), _( "Arc" ), _( "Ring/Circle" ), _( "Polygon" ) };
1989 
1990  int type = wxGetSingleChoiceIndex( _( "Shape type:" ), _( "Add Primitive" ),
1991  arrayDim( shapelist ), shapelist, 0, this );
1992 
1993  STROKE_T listtype[] = { S_SEGMENT, S_ARC, S_CIRCLE, S_POLYGON };
1994 
1995  PAD_CS_PRIMITIVE primitive( listtype[type] );
1996 
1997  if( listtype[type] == S_POLYGON )
1998  {
1999  DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, m_parent, &primitive );
2000 
2001  if( dlg.ShowModal() != wxID_OK )
2002  return;
2003  }
2004  else
2005  {
2006  DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, m_parent, &primitive );
2007 
2008  if( dlg.ShowModal() != wxID_OK )
2009  return;
2010  }
2011 
2012  m_primitives.push_back( primitive );
2013 
2015 
2016  if( m_canUpdate )
2017  {
2019  redraw();
2020  }
2021 }
2022 
2023 
2024 void DIALOG_PAD_PROPERTIES::onGeometryTransform( wxCommandEvent& event )
2025 {
2026  long select = m_listCtrlPrimitives->GetFirstSelected();
2027 
2028  if( select < 0 )
2029  {
2030  wxMessageBox( _( "No shape selected" ) );
2031  return;
2032  }
2033 
2034  // Multiple selections are allowed. Build selected shapes list
2035  std::vector<PAD_CS_PRIMITIVE*> shapeList;
2036  shapeList.push_back( &m_primitives[select] );
2037 
2038  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2039  shapeList.push_back( &m_primitives[select] );
2040 
2041  DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, m_parent, shapeList, false );
2042 
2043  if( dlg.ShowModal() != wxID_OK )
2044  return;
2045 
2046  // Transfert new settings:
2047  dlg.Transform();
2048 
2050 
2051  if( m_canUpdate )
2052  {
2054  redraw();
2055  }
2056 }
2057 
2058 
2059 void DIALOG_PAD_PROPERTIES::onDuplicatePrimitive( wxCommandEvent& event )
2060 {
2061  long select = m_listCtrlPrimitives->GetFirstSelected();
2062 
2063  if( select < 0 )
2064  {
2065  wxMessageBox( _( "No shape selected" ) );
2066  return;
2067  }
2068 
2069  // Multiple selections are allowed. Build selected shapes list
2070  std::vector<PAD_CS_PRIMITIVE*> shapeList;
2071  shapeList.push_back( &m_primitives[select] );
2072 
2073  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2074  shapeList.push_back( &m_primitives[select] );
2075 
2076  DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, m_parent, shapeList, true );
2077 
2078  if( dlg.ShowModal() != wxID_OK )
2079  return;
2080 
2081  // Transfer new settings
2082  // save duplicates to a separate vector to avoid m_primitives reallocation,
2083  // as shapeList contains pointers to its elements
2084  std::vector<PAD_CS_PRIMITIVE> duplicates;
2085  dlg.Transform( &duplicates, dlg.GetDuplicateCount() );
2086  std::move( duplicates.begin(), duplicates.end(), std::back_inserter( m_primitives ) );
2087 
2089 
2090  if( m_canUpdate )
2091  {
2093  redraw();
2094  }
2095 }
void OnInitDialog(wxInitDialogEvent &event) override
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:676
void OnValuesChanged(wxCommandEvent &event) override
Called when a dimension has changed.
void Move(const Vec &aMoveVector)
Function Move moves the rectangle by the aMoveVector.
Definition: box2.h:118
void GRResetPenAndBrush(wxDC *DC)
Definition: gr_basic.cpp:123
int GetLocalSolderMaskMargin() const
Definition: class_pad.h:421
double GetOrientation() const
Definition: class_module.h:188
COMMIT & Modify(EDA_ITEM *aItem)
Modifies a given item in the model.
Definition: commit.h:103
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint BACK and FRONT copper layers, mask,...
Definition: lset.cpp:521
DIALOG_PAD_PROPERTIES(PCB_BASE_FRAME *aParent, D_PAD *aPad)
int GetNetCode() const
Function GetNetCode.
void SetViewport(const BOX2D &aViewport)
Function SetViewport() Sets the visible area of the VIEW.
Definition: view.cpp:550
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings returns the BOARD_DESIGN_SETTINGS for the BOARD owned by this frame.
void enablePrimitivePage(bool aEnable)
enable (or disable) the primitive page editor
static LSET StandardMask()
layer set for a through hole pad
Definition: class_pad.cpp:101
KIGFX::VIEW_CONTROLS * GetViewControls() const
Function GetViewControls() Returns a pointer to the VIEW_CONTROLS instance used in the panel.
bool m_Display_padnum
Definition: class_pad.h:75
void FlipPrimitives()
Flip the basic shapes, in custom pads.
Definition: class_pad.cpp:462
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Function GetLayerName returns the name of a layer given by aLayer.
virtual void Move(const wxPoint &aMoveVector) override
Function Move move this object.
virtual void SetTopLayer(int aLayer, bool aEnabled=true)
Function SetTopLayer() Sets given layer to be displayed on the top or sets back the default order of ...
Definition: view.cpp:859
like PAD_STANDARD, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:66
PAD_ATTR_T
Enum PAD_ATTR_T is the set of pad shapes, used with D_PAD::{Set,Get}Attribute() The double name is fo...
Definition: pad_shapes.h:59
bool IsFlipped() const
function IsFlipped
Definition: class_module.h:258
multilayer pads, usually with holes
bool MergePrimitivesAsPolygon(SHAPE_POLY_SET *aMergedPolygon=NULL, int aCircleToSegmentsCount=ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF)
Merge all basic shapes, converted to a polygon in one polygon, in m_customShapeAsPolygon.
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
Implementation of conversion functions that require both schematic and board internal units.
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
Definition: class_pad.cpp:122
This file is part of the common library.
const wxPoint GetCenter() const override
Function GetCenter()
PAD_SHAPE_T GetAnchorPadShape() const
Function GetAnchorPadShape.
Definition: class_pad.h:226
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: class_pad.cpp:108
VIEW_CONTROLS class definition.
void CalculateBoundingBox()
Function CalculateBoundingBox calculates the bounding box in board coordinates.
const wxPoint GetArcEnd() const
bool transferDataToPad(D_PAD *aPad)
Copy values from dialog field to aPad's members.
Class BOARD to handle a board.
EDA_DRAW_PANEL_GAL * GetGalCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
Definition: draw_frame.h:935
void ExportTo(DRAWSEGMENT *aTarget)
Export the PAD_CS_PRIMITIVE parameters to a DRAWSEGMENT useful to draw a primitive shape.
wxPoint m_Start
angle of an arc, from its starting point, in 0.1 deg
Definition: class_pad.h:100
virtual bool Validate(int aMin, int aMax, bool setFocusOnError=true)
Function Validate Validates the control against the given range, informing the user of any errors fou...
int color
Definition: DXF_plotter.cpp:62
polygon (not yet used for tracks, but could be in microwave apps)
void setPadLayersList(LSET layer_mask)
Function setPadLayersList updates the CheckBox states in pad layers list,.
bool IsFlipped() const
Definition: class_pad.cpp:136
int GetPadToDieLength() const
Definition: class_pad.h:419
void FinishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:62
BOX2< VECTOR2D > BOX2D
Definition: box2.h:521
wxFloatingPointValidator< double > m_OrientValidator
virtual void EnableMousewheelPan(bool aEnable)
Function EnableMousewheelPan() Enables or disables mousewheel panning.
void GRCSegm(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, int aPenSize, COLOR4D Color)
Definition: gr_basic.cpp:415
GAL * GetGAL() const
Function GetGAL() Returns the GAL this view is using to draw graphical primitives.
Definition: view.h:180
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:219
virtual void RefreshDrawingRect(const EDA_RECT &aRect, bool aEraseBackground=true)
Function RefreshDrawingRect redraws the contents of aRect in drawing units.
int GetSelectedNetcode()
void onChangePadMode(wxCommandEvent &event) override
usual segment : line with rounded ends
void SetDrillSize(const wxSize &aSize)
Definition: class_pad.h:274
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:216
void NORMALIZE_ANGLE_180(T &Angle)
Definition: trigo.h:335
void SetRoundRectRadiusRatio(double aRadiusScale)
has meaning only for rounded rect pads Set the scaling factor between the smaller Y or Y size and the...
Definition: class_pad.h:653
const std::vector< wxPoint > BuildPolyPointsList() const
Build and return the list of corners in a std::vector<wxPoint> It must be used only to convert the SH...
void Transform(std::vector< PAD_CS_PRIMITIVE > *aList=NULL, int aDuplicateCount=0)
Apply geometric transform (rotation, move, scale) defined in dialog aDuplicate = 1 .
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
int GetThermalGap() const
Definition: class_pad.cpp:759
void GRFilledCircle(EDA_RECT *ClipBox, wxDC *DC, int x, int y, int r, int width, COLOR4D Color, COLOR4D BgColor)
Definition: gr_basic.cpp:778
void onCornerSizePercentChange(wxCommandEvent &event) override
#define abs(a)
Definition: auxiliary.h:84
void SetScale(double aScale)
Function SetScale() Sets the scaling factor.
Definition: view.h:250
int GetLocalClearance() const
Definition: class_pad.h:424
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:116
void SetSketchModeGraphicItems(bool aEnabled)
Turns on/off sketch mode for graphic items (DRAWSEGMENTs, texts).
Definition: pcb_painter.h:134
void GRClosedPoly(EDA_RECT *ClipBox, wxDC *DC, int n, wxPoint Points[], bool Fill, COLOR4D Color, COLOR4D BgColor)
Function GRClosedPoly draws a closed polygon onto the drawing context aDC and optionally fills and/or...
Definition: gr_basic.cpp:711
static const int delta[8][2]
Definition: solve.cpp:112
void SetValue(const wxString &aValue) override
Set a new value in evaluator buffer, and display it in the wxTextCtrl.
PAD_SHAPE_T
Enum PAD_SHAPE_T is the set of pad shapes, used with D_PAD::{Set,Get}Shape()
Definition: pad_shapes.h:31
PAINTER * GetPainter() const
Function GetPainter() Returns the painter object used by the view for drawing VIEW_ITEMS.
Definition: view.h:199
PAD_ATTR_T GetAttribute() const
Definition: class_pad.h:412
bool TransferDataFromWindow() override
Function TransferDataFromWindow Transfer data out of the GUI.
int GetChamferPositions() const
has meaning only for chamfered rect pads
Definition: class_pad.h:690
static PAD_SHAPE_T code_shape[]
Classes used in Pcbnew, CvPcb and GerbView.
class DIALOG_PAD_PROPERTIES, derived from DIALOG_PAD_PROPERTIES_BASE, created by wxFormBuilder
Pads are not covered.
Definition: zones.h:52
COLOR4D GetItemColor(int aItemIdx) const
Function GetItemColor.
virtual int GetValue()
Function GetValue Returns the current value in Internal Units.
wxString MessageTextFromValue(EDA_UNITS_T aUnits, int aValue, bool aUseMils)
Definition: base_units.cpp:125
bool IsGalCanvasActive() const
Function IsGalCanvasActive is used to check which canvas (GAL-based or standard) is currently in use.
Definition: draw_frame.h:928
dialog pad properties editor.
KIGFX::ORIGIN_VIEWITEM * m_axisOrigin
Class PCB_RENDER_SETTINGS Stores PCB specific render settings.
Definition: pcb_painter.h:62
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Construct a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:79
#define SELECTED
Definition: base_struct.h:121
void onAddPrimitive(wxCommandEvent &event) override
static PAD_ATTR_T code_type[]
void SetAnchorPadShape(PAD_SHAPE_T aShape)
Function SetAnchorPadShape Set the shape of the anchor pad for custm shped pads.
Definition: class_pad.h:253
void OnCancel(wxCommandEvent &event) override
static wxString formatCoord(EDA_UNITS_T aUnits, wxPoint aCoord)
std::string FormatAngle(double aAngle)
Function FormatAngle converts aAngle from board units to a string appropriate for writing to file.
Definition: base_units.cpp:490
virtual const BOX2I ViewBBox() const override
Function ViewBBox() returns the bounding box of the item covering all its layers.
Definition: class_pad.cpp:1414
int m_Radius
thickness of segment or outline For filled S_CIRCLE shape, thickness = 0.
Definition: class_pad.h:98
Class LSET is a set of PCB_LAYER_IDs.
const std::vector< PAD_CS_PRIMITIVE > & GetPrimitives() const
Accessor to the basic shape list.
Definition: class_pad.h:336
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:256
std::vector< wxPoint > m_Poly
is also the start point of the arc
Definition: class_pad.h:102
VECTOR2< double > VECTOR2D
Definition: vector2d.h:586
void OnSetLayers(wxCommandEvent &event) override
void SetZoneConnection(ZoneConnection aType)
Definition: class_pad.h:496
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
void OnPaintShowPanel(wxPaintEvent &event) override
void SetName(const wxString &aName)
Set the pad name (sometimes called pad number, although it can be an array reference like AA12).
Definition: class_pad.h:182
wxStaticBoxSizer * m_sbSizerCustomShapedZonesSettings
void SetPos0(const wxPoint &aPos)
Definition: class_pad.h:262
PCB_GENERAL_SETTINGS & Settings()
int ShowQuasiModal()
void ListSet(const wxString &aList)
Function ListSet Add a list of items.
Arcs (with rounded ends)
const wxPoint & GetOffset() const
Definition: class_pad.h:278
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: class_pad.h:395
double GetChamferRectRatio() const
has meaning only for chamfered rect pads
Definition: class_pad.h:667
int GetThermalWidth() const
Definition: class_pad.cpp:748
Helper class to handle a primitive (basic shape: polygon, segment, circle or arc) to build a custom p...
Definition: class_pad.h:91
void SetLastEditTime(timestamp_t aTime)
Definition: class_module.h:313
LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
Definition: class_pad.h:409
void SetSelectedNetcode(int aNetcode)
Subclass of DIALOG_DISPLAY_HTML_TEXT_BASE, which is generated by wxFormBuilder.
void onCornerRadiusChange(wxCommandEvent &event) override
Class DIALOG_PAD_PROPERTIES_BASE.
void SetDrawAtZero(bool aDrawFlag)
Function SetDrawAtZero() Set the draw at zero flag.
void SetStealsFocus(bool aStealsFocus)
Set whether focus is taken on certain events (mouseover, keys, etc).
void OnResize(wxSizeEvent &event)
void OnPadShapeSelection(wxCommandEvent &event) override
void PadTypeSelected(wxCommandEvent &event) override
const wxString & GetReference() const
Function GetReference.
Definition: class_module.h:462
static LSET InternalCuMask()
Function InternalCuMask() returns a complete set of internal copper layers, which is all Cu layers ex...
Definition: lset.cpp:636
void SetThermalWidth(int aWidth)
Definition: class_pad.h:499
COLOR4D m_HoleColor
Definition: class_pad.h:70
void onPrimitiveDClick(wxMouseEvent &event) override
Called on a double click on the basic shapes list.
#define BRIGHTENED
item is drawn with a bright contour
Definition: base_struct.h:138
const wxString & GetName() const
Definition: class_pad.h:190
void SetSize(const wxSize &aSize)
Definition: class_pad.h:268
int GetBoundingRadius() const
Function GetBoundingRadius returns the radius of a minimum sized circle which fully encloses this pad...
Definition: class_pad.h:619
STROKE_T
Enum STROKE_T is the set of shapes for segments (graphic segments and tracks) which are often in the ...
bool SetNetCode(int aNetCode, bool aNoAssert=false)
Function SetNetCode sets net using a net code.
void SetLayerColor(int aLayer, const COLOR4D &aColor)
Function SetLayerColor Changes the color used to draw a layer.
Definition: painter.h:230
void SetRoundRectCornerRadius(double aRadius)
Set the rounded rectangle radius ratio based on a given radius.
Definition: class_pad.cpp:217
void OnDrillShapeSelected(wxCommandEvent &event) override
const wxPoint & GetArcStart() const
bool m_ShowNotPlatedHole
Definition: class_pad.h:80
void SetNetInfo(NETINFO_LIST *aNetInfoList)
virtual EDA_DRAW_PANEL * GetCanvas() const
Definition: draw_frame.h:395
void SetPadToDieLength(int aLength)
Definition: class_pad.h:418
bool GetEnableMousewheelPan() const
Class HTML_MESSAGE_BOX.
const wxSize & GetDelta() const
Definition: class_pad.h:272
void DrawShape(EDA_RECT *aClipBox, wxDC *aDC, PAD_DRAWINFO &aDrawInfo)
Function DrawShape basic function to draw a pad.
void onGeometryTransform(wxCommandEvent &event) override
wxPoint m_End
is also the center of the circle and arc
Definition: class_pad.h:101
virtual void Update(VIEW_ITEM *aItem, int aUpdateFlags)
For dynamic VIEWs, informs the associated VIEW that the graphical representation of this item has cha...
Definition: view.cpp:1539
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
NETINFO_LIST & GetNetInfo()
Definition: class_board.h:756
Like smd, does not appear on the solder paste layer (default) note also has a special attribute in Ge...
Definition: pad_shapes.h:63
STROKE_T m_Shape
Definition: class_pad.h:94
void SetGridSize(const VECTOR2D &aGridSize)
Set the grid size.
void StartDrawing()
Function StartDrawing() Begins drawing if it was stopped previously.
int m_PadClearance
Definition: class_pad.h:73
void SetAttribute(PAD_ATTR_T aAttribute)
Definition: class_pad.cpp:420
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
void UseColorScheme(const COLORS_DESIGN_SETTINGS *aSettings)
Function UseColorScheme Applies layer color settings.
COLORS_DESIGN_SETTINGS & Colors()
void SetLocalClearance(int aClearance)
Definition: class_pad.h:425
a dialog to edit basic polygonal shape parameters
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Definition: macros.h:99
MODULE * GetParent() const
Definition: class_pad.h:162
void SetLocalSolderPasteMarginRatio(double aRatio)
Definition: class_pad.h:431
bool SwitchBackend(GAL_TYPE aGalType) override
Function SwitchBackend Switches method of rendering graphics.
CUST_PAD_SHAPE_IN_ZONE GetCustomShapeInZoneOpt() const
Definition: class_pad.h:232
int m_Thickness
S_SEGMENT, S_ARC, S_CIRCLE, S_POLYGON only (same as DRAWSEGMENT)
Definition: class_pad.h:95
void OnPrimitiveSelection(wxListEvent &event) override
Called on selection/deselection of a basic shape.
void onEditPrimitive(wxCommandEvent &event) override
virtual RENDER_SETTINGS * GetSettings()=0
Function GetSettings Returns pointer to current settings that are going to be used when drawing items...
bool TransferDataFromWindow() override
Updates the different parameters for the component being edited.
void SetLayerSet(LSET aLayerMask)
Definition: class_pad.h:408
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:300
virtual void Rotate(const wxPoint &aRotCentre, double aAngle) override
Function Rotate Rotate this object.
void PadOrientEvent(wxCommandEvent &event) override
wxPoint m_Offset
Definition: class_pad.h:83
const int scale
smd pads, front layer
#define HIGHLIGHTED
item is drawn in normal colors, when the rest is darkened
Definition: base_struct.h:137
std::vector< PAD_CS_PRIMITIVE > m_primitives
bool IsType(FRAME_T aType) const
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
void SetDrillShape(PAD_DRILL_SHAPE_T aDrillShape)
Definition: class_pad.h:393
static const LSET std_pad_layers[]
void onDeletePrimitive(wxCommandEvent &event) override
Event handlers of basic shapes list panel.
void onDuplicatePrimitive(wxCommandEvent &event) override
void SetLocalSolderMaskMargin(int aMargin)
Definition: class_pad.h:422
void SetSketchMode(int aItemLayer, bool aEnabled)
Function SetSketchMode Turns on/off sketch mode for given item layer.
Definition: pcb_painter.h:114
KIGFX::VIEW * GetView() const
Function GetView() Returns a pointer to the VIEW instance used in the panel.
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees,...
Definition: class_pad.h:389
void GRFilledSegment(EDA_RECT *aClipBox, wxDC *aDC, wxPoint aStart, wxPoint aEnd, int aWidth, COLOR4D aColor)
Definition: gr_basic.cpp:526
virtual void SetValue(int aValue)
Function SetValue Sets new value (in Internal Units) for the text field, taking care of units convers...
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
void GRCircle(EDA_RECT *ClipBox, wxDC *DC, int xc, int yc, int r, int width, COLOR4D Color)
Definition: gr_basic.cpp:755
const wxSize & GetDrillSize() const
Definition: class_pad.h:275
D_PAD m_Pad_Master
A dummy pad to store all default parameters.
bool IsAperturePad() const
Definition: class_pad.h:416
The common library.
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true) override
Executes the changes.
void SetShape(PAD_SHAPE_T aShape)
Definition: class_pad.h:217
void SetGridVisibility(bool aVisibility)
Sets the visibility setting of the grid.
#define SELECTED_ITEMS_LAYER
bool m_ShowPadFilled
Definition: class_pad.h:77
void SetEnd(const wxPoint &aEnd)
int GetRoundRectCornerRadius() const
Function GetRoundRectCornerRadius Has meaning only for rounded rect pads.
Definition: class_pad.h:538
void SetOrientation(double aAngle)
Function SetOrientation sets the rotation angle of the pad.
Definition: class_pad.cpp:429
double GetRoundRectRadiusRatio() const
has meaning only for rounded rect pads
Definition: class_pad.h:641
const wxString & GetValue() const
Function GetValue.
Definition: class_module.h:487
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: base_struct.h:257
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
bool padValuesOK()
test if all values are acceptable for the pad
void SetChamferRectRatio(double aChamferScale)
has meaning only for chamfered rect pads Set the ratio between the smaller Y or Y size and the radius...
Definition: class_pad.h:678
COLOR4D m_Color
Definition: class_pad.h:68
void SetLocalSolderPasteMargin(int aMargin)
Definition: class_pad.h:428
static LSET ConnSMDMask()
layer set for a SMD pad on Front layer used for edge board connectors
Definition: class_pad.cpp:115
void SetCustomShapeInZoneOpt(CUST_PAD_SHAPE_IN_ZONE aOption)
Set the option for the custom pad shape to use as clearance area in copper zones.
Definition: class_pad.h:242
void InstallPadOptionsFrame(D_PAD *pad)
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Function Add() Adds a VIEW_ITEM to the view.
Definition: view.cpp:346
GAL_TYPE GetBackend() const
Function GetBackend Returns the type of backend currently used by GAL canvas.
const Vec & GetSize() const
Definition: box2.h:187
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:216
Module description (excepted pads)
Definition: colors.h:45
static LSET ApertureMask()
layer set for an aperture pad
Definition: class_pad.cpp:129
BOARD * GetBoard() const
const Vec & GetOrigin() const
Definition: box2.h:191
Class VIEW.
Definition: view.h:61
void SetBoundary(const BOX2D &aBoundary)
Function SetBoundary() Sets limits for view area.
Definition: view.h:278
EDA_UNITS_T m_units
Definition: dialog_shim.h:173
bool m_Display_netname
Definition: class_pad.h:76
ZoneConnection GetZoneConnection() const
Definition: class_pad.cpp:737
const wxSize & GetSize() const
Definition: class_pad.h:269
const wxPoint GetPosition() const override
Definition: class_pad.h:220
double GetScale() const
Function GetScale()
Definition: view.h:268
int GetLocalSolderPasteMargin() const
Definition: class_pad.h:427
std::vector< DRAWSEGMENT * > m_highlight
void SetOffset(const wxPoint &aOffset)
Definition: class_pad.h:277
A dialog to apply geometry transforms to a shape or set of shapes (move, rotate around origin,...
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:243
void SetThermalGap(int aGap)
Definition: class_pad.h:502
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition: netinfo.h:469
const wxPoint GetPosition() const override
Definition: class_module.h:183
Use thermal relief for pads.
Definition: zones.h:53
bool SetPrimitives(const std::vector< PAD_CS_PRIMITIVE > &aPrimitivesList)
Import to the basic shape list.
class PCB_BASE_FRAME basic PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
void DeletePrimitivesList()
clear the basic shapes list
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
Definition: class_pad.cpp:226
EDA_UNITS_T
Definition: common.h:160
void StopDrawing()
Function StopDrawing() Prevents the GAL canvas from further drawing till it is recreated or StartDraw...
double m_ArcAngle
radius of a circle
Definition: class_pad.h:99
void Enable(bool aEnable)
Function Enable Enables/diasables the label, widget and units label.
a dialog to edit basics shapes parameters.
double GetLocalSolderPasteMarginRatio() const
Definition: class_pad.h:430
#define DO_NOT_DRAW
Used to disable draw function.
Definition: base_struct.h:126
bool TransferDataFromWindow() override
Function TransferDataFromWindow Transfer data out of the GUI.
void SetDelta(const wxSize &aSize)
Definition: class_pad.h:271
virtual void OnUpdateUI(wxUpdateUIEvent &event) override
#define min(a, b)
Definition: auxiliary.h:85
void SetChamferPositions(int aChamferPositions)
has meaning only for chamfered rect pads set the position of the chamfer for a 0 orientation,...
Definition: class_pad.h:698
pads are covered by copper
Definition: zones.h:54
int m_Status_Pcb
Flags used in ratsnest calculation and update.
Definition: class_board.h:241
void GRArc1(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int xc, int yc, COLOR4D Color)
Definition: gr_basic.cpp:799
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39
virtual void ChangeValue(int aValue)
Function ChangeValue Changes the value (in Internal Units) for the text field, taking care of units c...
EDA_UNITS_T GetUserUnits() const override
Definition: dialog_shim.h:133
void SetWidth(int aWidth)