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) 2018 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-2018 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 <unit_format.h>
39 #include <board_commit.h>
40 #include <bitmaps.h>
41 
42 #include <class_board.h>
43 #include <class_module.h>
44 #include <pcb_painter.h>
45 #include <widgets/net_selector.h>
46 
47 #include <dialog_pad_properties.h>
48 #include <html_messagebox.h>
49 
50 
51 // list of pad shapes, ordered like the pad shape wxChoice in dialog.
53 {
59  PAD_SHAPE_CUSTOM, // choice = CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
60  PAD_SHAPE_CUSTOM // choice = PAD_SHAPE_CUSTOM_RECT_ANCHOR
61 };
62 
63 // the ordered index of the pad shape wxChoice in dialog.
64 // keep it consistent with code_shape[] and dialog strings
66 {
74 };
75 
77 {
82  PAD_ATTRIB_CONN // Aperture pad (type CONN with no copper layers)
83 };
84 
85 // Default mask layers setup for pads according to the pad type
86 static const LSET std_pad_layers[] =
87 {
88  D_PAD::StandardMask(), // PAD_ATTRIB_STANDARD:
89  D_PAD::SMDMask(), // PAD_ATTRIB_SMD:
90  D_PAD::ConnSMDMask(), // PAD_ATTRIB_CONN:
91  D_PAD::UnplatedHoleMask(), // PAD_ATTRIB_HOLE_NOT_PLATED:
93 };
94 
95 
97 {
98  DIALOG_PAD_PROPERTIES dlg( this, aPad );
99  dlg.ShowQuasiModal(); // QuasiModal required for NET_SELECTOR
100 }
101 
102 
104  DIALOG_PAD_PROPERTIES_BASE( aParent ),
105  m_parent( aParent ),
106  m_canUpdate( false ),
107  m_posX( aParent, m_posXLabel, m_posXCtrl, m_posXUnits ),
108  m_posY( aParent, m_posYLabel, m_posYCtrl, m_posYUnits ),
109  m_sizeX( aParent, m_sizeXLabel, m_sizeXCtrl, m_sizeXUnits, true ),
110  m_sizeY( aParent, m_sizeYLabel, m_sizeYCtrl, m_sizeYUnits, true ),
111  m_offsetX( aParent, m_offsetXLabel, m_offsetXCtrl, m_offsetXUnits, true ),
112  m_offsetY( aParent, m_offsetYLabel, m_offsetYCtrl, m_offsetYUnits, true ),
113  m_padToDie( aParent, m_padToDieLabel, m_padToDieCtrl, m_padToDieUnits, true ),
114  m_trapDelta( aParent, m_trapDeltaLabel, m_trapDeltaCtrl, m_trapDeltaUnits, true ),
115  m_cornerRadius( aParent, m_cornerRadiusLabel, m_tcCornerRadius, m_cornerRadiusUnits, true ),
116  m_holeX( aParent, m_holeXLabel, m_holeXCtrl, m_holeXUnits, true, 0 ),
117  m_holeY( aParent, m_holeYLabel, m_holeYCtrl, m_holeYUnits, true, 0 ),
118  m_OrientValidator( 1, &m_OrientValue ),
119  m_clearance( aParent, m_clearanceLabel, m_clearanceCtrl, m_clearanceUnits, true ),
120  m_maskClearance( aParent, m_maskClearanceLabel, m_maskClearanceCtrl, m_maskClearanceUnits, true ),
121  m_pasteClearance( aParent, m_pasteClearanceLabel, m_pasteClearanceCtrl, m_pasteClearanceUnits, true ),
122  m_spokeWidth( aParent, m_spokeWidthLabel, m_spokeWidthCtrl, m_spokeWidthUnits, true, 0 ),
123  m_thermalGap( aParent, m_thermalGapLabel, m_thermalGapCtrl, m_thermalGapUnits, true, 0 )
124 {
125  m_currentPad = aPad; // aPad can be NULL, if the dialog is called
126  // from the footprint editor to set default pad setup
127 
129 
131 
132  m_OrientValidator.SetRange( -360.0, 360.0 );
133  m_orientation->SetValidator( m_OrientValidator );
134  m_OrientValidator.SetWindow( m_orientation );
135 
136  m_cbShowPadOutline->SetValue( m_sketchPreview );
137 
138  m_FlippedWarningIcon->SetBitmap( KiBitmap( dialog_warning_xpm ) );
139  m_nonCopperWarningIcon->SetBitmap( KiBitmap( dialog_warning_xpm ) );
140 
142  m_dummyPad = new D_PAD( (MODULE*) NULL );
143 
144  if( aPad )
145  {
146  *m_dummyPad = *aPad;
148  }
149  else // We are editing a "master" pad, i.e. a template to create new pads
151 
152  initValues();
153 
154  wxFont infoFont = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
155  infoFont.SetSymbolicSize( wxFONTSIZE_SMALL );
156  m_techLayersLabel->SetFont( infoFont );
157  m_parentInfoLine1->SetFont( infoFont );
158  m_parentInfoLine2->SetFont( infoFont );
159  m_staticTextInfoNegVal->SetFont( infoFont );
160  m_staticTextInfoPosValue->SetFont( infoFont );
161  m_nonCopperNote->SetFont( infoFont );
162 
163  // Usually, TransferDataToWindow is called by OnInitDialog
164  // calling it here fixes all widget sizes so FinishDialogSettings can safely fix minsizes
166 
167  // Initialize canvas to be able to display the dummy pad:
168  prepareCanvas();
169 
171  m_sdbSizerOK->SetDefault();
172  m_canUpdate = true;
173 
174  m_PadNetSelector->Connect( NET_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ), NULL, this );
175 
176  // Now all widgets have the size fixed, call FinishDialogSettings
178 }
179 
180 
182 {
183  m_PadNetSelector->Disconnect( NET_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ), NULL, this );
184 
185  delete m_dummyPad;
186  delete m_axisOrigin;
187 }
188 
189 
190 bool DIALOG_PAD_PROPERTIES::m_sketchPreview = false; // Stores the pad draw option during a session
191 
192 
193 void DIALOG_PAD_PROPERTIES::OnInitDialog( wxInitDialogEvent& event )
194 {
195  m_selectedColor = COLOR4D( 1.0, 1.0, 1.0, 0.7 );
196 
197  // Needed on some WM to be sure the pad is redrawn according to the final size
198  // of the canvas, with the right zoom factor
199  redraw();
200 }
201 
202 
203 void DIALOG_PAD_PROPERTIES::OnCancel( wxCommandEvent& event )
204 {
205  // Mandatory to avoid m_panelShowPadGal trying to draw something
206  // in a non valid context during closing process:
207  if( m_parent->IsGalCanvasActive() )
209 
210  // Now call default handler for wxID_CANCEL command event
211  event.Skip();
212 }
213 
214 
216 {
217  // Enable or disable the widgets in page managing custom shape primitives
218  m_listCtrlPrimitives->Enable( aEnable );
219  m_buttonDel->Enable( aEnable );
220  m_buttonEditShape->Enable( aEnable );
221  m_buttonAddShape->Enable( aEnable );
222  m_buttonDup->Enable( aEnable );
223  m_buttonGeometry->Enable( aEnable );
224 }
225 
226 
228 {
229  // Initialize the canvases (legacy or gal) to display the pad
230 
231  // Show the X and Y axis. It is usefull because pad shape can have an offset
232  // or be a complex shape.
233  KIGFX::COLOR4D axis_color = LIGHTBLUE;
234 
236  Millimeter2iu( 0.2 ),
238  m_axisOrigin->SetDrawAtZero( true );
239 
240  if( m_parent->IsGalCanvasActive() )
241  {
245 
246  bool mousewheelPan = m_parent->GetCanvas()->GetEnableMousewheelPan();
248 
249  m_panelShowPadGal->Show();
250  m_panelShowPad->Hide();
251 
253 
254  // fix the pad render mode (filled/not filled)
255  auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
256  bool sketchMode = m_cbShowPadOutline->IsChecked();
257  settings->SetSketchMode( LAYER_PADS_TH, sketchMode );
258  settings->SetSketchMode( LAYER_PAD_FR, sketchMode );
259  settings->SetSketchMode( LAYER_PAD_BK, sketchMode );
260  settings->SetSketchModeGraphicItems( sketchMode );
261 
262  // gives a non null grid size (0.001mm) because GAL layer does not like a 0 size grid:
263  double gridsize = 0.001 * IU_PER_MM;
264  view->GetGAL()->SetGridSize( VECTOR2D( gridsize, gridsize ) );
265  view->Add( m_dummyPad );
266  view->Add( m_axisOrigin );
267 
269  Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_PAD_PROPERTIES::OnResize ) );
270  }
271  else
272  {
273  m_panelShowPad->Show();
274  m_panelShowPadGal->Hide();
275  }
276 }
277 
278 
279 void DIALOG_PAD_PROPERTIES::OnPaintShowPanel( wxPaintEvent& event )
280 {
281  wxPaintDC dc( m_panelShowPad );
282  PAD_DRAWINFO drawInfo;
283 
285 
286  if( m_dummyPad->GetLayerSet()[F_Cu] )
288 
289  if( m_dummyPad->GetLayerSet()[B_Cu] )
290  color = color.LegacyMix( m_parent->Settings().Colors().GetItemColor( LAYER_PAD_BK ) );
291 
292  // What could happen: the pad color is *actually* black, or no copper was selected
293  if( color == BLACK )
294  color = LIGHTGRAY;
295 
296  drawInfo.m_Color = color;
297  drawInfo.m_HoleColor = DARKGRAY;
298  drawInfo.m_Offset = m_dummyPad->GetPosition();
299  drawInfo.m_Display_padnum = true;
300  drawInfo.m_Display_netname = true;
301  drawInfo.m_ShowPadFilled = !m_sketchPreview;
302 
304  drawInfo.m_ShowNotPlatedHole = true;
305 
306  // Shows the local pad clearance
308 
309  wxSize dc_size = dc.GetSize();
310  dc.SetDeviceOrigin( dc_size.x / 2, dc_size.y / 2 );
311 
312  // Calculate a suitable scale to fit the available draw area
313  int dim = m_dummyPad->GetBoundingRadius() *2;
314 
315  // Invalid x size. User could enter zero, or have deleted all text prior to
316  // entering a new value; this is also treated as zero. If dim is left at
317  // zero, the drawing scale is zero and we get a crash.
318  if( dim == 0 )
319  {
320  // If drill size has been set, use that. Otherwise default to 1mm.
321  dim = m_dummyPad->GetDrillSize().x;
322  if( dim == 0 )
323  dim = Millimeter2iu( 1.0 );
324  }
325 
326  if( m_dummyPad->GetLocalClearance() > 0 )
327  dim += m_dummyPad->GetLocalClearance() * 2;
328 
329  double scale = (double) dc_size.x / dim;
330 
331  // If the pad is a circle, use the x size here instead.
332  int ysize;
333 
335  ysize = m_dummyPad->GetSize().x;
336  else
337  ysize = m_dummyPad->GetSize().y;
338 
339  dim = ysize + std::abs( m_dummyPad->GetDelta().x );
340 
341  // Invalid y size. See note about x size above.
342  if( dim == 0 )
343  {
344  dim = m_dummyPad->GetDrillSize().y;
345  if( dim == 0 )
346  dim = Millimeter2iu( 0.1 );
347  }
348 
349  if( m_dummyPad->GetLocalClearance() > 0 )
350  dim += m_dummyPad->GetLocalClearance() * 2;
351 
352  double altscale = (double) dc_size.y / dim;
353  scale = std::min( scale, altscale );
354 
355  // Give a margin
356  scale *= 0.7;
357  dc.SetUserScale( scale, scale );
358 
359  GRResetPenAndBrush( &dc );
360  m_dummyPad->DrawShape( NULL, &dc, drawInfo );
361 
362  // draw selected primitives:
363  long select = m_listCtrlPrimitives->GetFirstSelected();
364 
365  while( select >= 0 )
366  {
367  PAD_CS_PRIMITIVE& primitive = m_primitives[select];
368 
369  // The best way to calculate parameters to draw a primitive is to
370  // use a dummy DRAWSEGMENT and use its methods
371  // Note: in legacy canvas, the pad has the 0,0 position
372  DRAWSEGMENT dummySegment;
373  primitive.ExportTo( &dummySegment );
374  dummySegment.Rotate( wxPoint( 0, 0), m_dummyPad->GetOrientation() );
375 
376  switch( primitive.m_Shape )
377  {
378  case S_SEGMENT: // usual segment : line with rounded ends
379  if( !m_sketchPreview )
380  GRFilledSegment( NULL, &dc, dummySegment.GetStart(), dummySegment.GetEnd(),
381  primitive.m_Thickness, m_selectedColor );
382  else
383  GRCSegm( NULL, &dc, dummySegment.GetStart(), dummySegment.GetEnd(),
384  primitive.m_Thickness, m_selectedColor );
385  break;
386 
387  case S_ARC: // Arc with rounded ends
388  if( !m_sketchPreview )
389  GRArc1( NULL, &dc, dummySegment.GetArcEnd(), dummySegment.GetArcStart(),
390  dummySegment.GetCenter(), primitive.m_Thickness, m_selectedColor );
391  else
392  {
393  GRArc1( NULL, &dc, dummySegment.GetArcEnd(), dummySegment.GetArcStart(),
394  dummySegment.GetCenter(), 0, m_selectedColor );
395 /* GRArc1( NULL, &dc, dummySegment.GetArcEnd(), dummySegment.GetArcStart(),
396  dummySegment.GetCenter() - primitive.m_Thickness, 0, m_selectedColor );*/
397  }
398  break;
399 
400  case S_CIRCLE: // ring or circle
401  if( primitive.m_Thickness )
402  {
403  if( !m_sketchPreview )
404  GRCircle( nullptr, &dc, dummySegment.GetCenter(), primitive.m_Radius,
405  primitive.m_Thickness, m_selectedColor );
406  else
407  {
408  GRCircle( nullptr, &dc, dummySegment.GetCenter(),
409  primitive.m_Radius + primitive.m_Thickness/2, 0, m_selectedColor );
410  GRCircle( nullptr, &dc, dummySegment.GetCenter(),
411  primitive.m_Radius - primitive.m_Thickness/2, 0, m_selectedColor );
412  }
413  }
414  else
415  {
416  if( !m_sketchPreview )
417  GRFilledCircle( nullptr, &dc, dummySegment.GetCenter(), primitive.m_Radius,
418  m_selectedColor );
419  else
420  GRCircle( nullptr, &dc, dummySegment.GetCenter(), primitive.m_Radius, 0,
421  m_selectedColor );
422  }
423  break;
424 
425  case S_POLYGON: // polygon
426  {
427  std::vector<wxPoint> poly = dummySegment.BuildPolyPointsList();
428  GRClosedPoly( nullptr, &dc, poly.size(), &poly[0], !m_sketchPreview,
430  }
431  break;
432 
433  default:
434  break;
435  }
436 
437  select = m_listCtrlPrimitives->GetNextSelected( select );
438  }
439 
440  // Draw X and Y axis. This is particularly useful to show the
441  // reference position of pads with offset and no hole, or custom pad shapes
442  const int t = 0; // line thickness
443  GRLine( nullptr, &dc, -int( dc_size.x/scale ), 0, int( dc_size.x/scale ), 0, t, LIGHTBLUE );
444  GRLine( nullptr, &dc, 0, -int( dc_size.y/scale ), 0, int( dc_size.y/scale ), t, LIGHTBLUE );
445 
446  event.Skip();
447 }
448 
449 
451 {
452  // Note: use m_tcCornerSizeRatio->ChangeValue() to avoid generating a wxEVT_TEXT event
453 
455  {
456  auto ratio = wxString::Format( "%.1f", m_dummyPad->GetRoundRectRadiusRatio() * 100 );
457  m_tcCornerSizeRatio->ChangeValue( ratio );
459  }
460  else if( m_dummyPad->GetShape() == PAD_SHAPE_RECT )
461  {
462  m_tcCornerSizeRatio->ChangeValue( "0" );
464  }
465  else
466  {
467  m_tcCornerSizeRatio->ChangeValue( wxEmptyString );
468  m_cornerRadius.SetValue( wxEmptyString );
469  }
470 }
471 
472 
473 void DIALOG_PAD_PROPERTIES::onCornerRadiusChange( wxCommandEvent& event )
474 {
476  return;
477 
478  wxString value = m_tcCornerRadius->GetValue();
479  double rrRadius;
480 
481  if( value.ToDouble( &rrRadius ) )
482  {
483  if( rrRadius < 0.0 )
484  {
485  rrRadius = 0.0;
486  m_tcCornerRadius->ChangeValue( "0.0" );
487  }
488 
490  m_dummyPad->SetRoundRectCornerRadius( Millimeter2iu( rrRadius ) );
491 
492  auto ratio = wxString::Format( "%.1f", m_dummyPad->GetRoundRectRadiusRatio() * 100 );
493  m_tcCornerSizeRatio->ChangeValue( ratio );
494  redraw();
495  }
496 }
497 
498 
500 {
502  return;
503 
504  wxString value = m_tcCornerSizeRatio->GetValue();
505  double rrRadiusRatioPercent;
506 
507  if( value.ToDouble( &rrRadiusRatioPercent ) )
508  {
509  // Clamp rrRadiusRatioPercent to acceptable value (0.0 to 50.0)
510  if( rrRadiusRatioPercent < 0.0 )
511  {
512  rrRadiusRatioPercent = 0.0;
513  m_tcCornerSizeRatio->ChangeValue( "0.0" );
514  }
515 
516  if( rrRadiusRatioPercent > 50.0 )
517  {
518  rrRadiusRatioPercent = 0.5;
519  m_tcCornerSizeRatio->ChangeValue( "50.0" );
520  }
521 
524  redraw();
525  }
526 }
527 
528 
530 {
531  wxString msg;
532  double angle;
533 
534  // Disable pad net name wxTextCtrl if the caller is the footprint editor
535  // because nets are living only in the board managed by the board editor
537 
538 
539  // Setup layers names from board
540  // Should be made first, before calling m_rbCopperLayersSel->SetSelection()
541  m_rbCopperLayersSel->SetString( 0, m_board->GetLayerName( F_Cu ) );
542  m_rbCopperLayersSel->SetString( 1, m_board->GetLayerName( B_Cu ) );
543 
544  m_PadLayerAdhCmp->SetLabel( m_board->GetLayerName( F_Adhes ) );
545  m_PadLayerAdhCu->SetLabel( m_board->GetLayerName( B_Adhes ) );
547  m_PadLayerPateCu->SetLabel( m_board->GetLayerName( B_Paste ) );
549  m_PadLayerSilkCu->SetLabel( m_board->GetLayerName( B_SilkS ) );
550  m_PadLayerMaskCmp->SetLabel( m_board->GetLayerName( F_Mask ) );
551  m_PadLayerMaskCu->SetLabel( m_board->GetLayerName( B_Mask ) );
552  m_PadLayerECO1->SetLabel( m_board->GetLayerName( Eco1_User ) );
553  m_PadLayerECO2->SetLabel( m_board->GetLayerName( Eco2_User ) );
555 
556  m_isFlipped = false;
557 
558  if( m_currentPad )
559  {
561 
562  // Diplay parent footprint info
563  MODULE* footprint = m_currentPad->GetParent();
564  wxString msg1, msg2;
565 
566  if( footprint )
567  {
568  wxString side = footprint->IsFlipped() ? _( "back side (mirrored)" ) : _( "front side" );
569  msg1.Printf( _("Footprint %s (%s),"), footprint->GetReference(), footprint->GetValue() );
570  msg2.Printf( _("%s, rotated %.1f deg"), side, footprint->GetOrientation() / 10.0 );
571  }
572 
573  m_parentInfoLine1->SetLabel( msg1 );
574  m_parentInfoLine2->SetLabel( msg2 );
575  }
576 
577  if( m_isFlipped )
578  {
579  wxPoint pt = m_dummyPad->GetOffset();
580  pt.y = -pt.y;
581  m_dummyPad->SetOffset( pt );
582 
583  wxSize sz = m_dummyPad->GetDelta();
584  sz.y = -sz.y;
585  m_dummyPad->SetDelta( sz );
586 
587  // flip pad's layers
589 
590  // flip custom pad shapes
592  }
593 
595 
597 
598  m_PadNumCtrl->SetValue( m_dummyPad->GetName() );
600 
601  // Display current pad parameters units:
604 
607 
610 
613 
614  if( m_dummyPad->GetDelta().x )
615  {
617  m_trapAxisCtrl->SetSelection( 0 );
618  }
619  else
620  {
622  m_trapAxisCtrl->SetSelection( 1 );
623  }
624 
626 
632 
633  // Prefer "-0" to "0" for normally negative values
635  m_pasteClearanceCtrl->SetValue( wxT( "-" ) + m_pasteClearanceCtrl->GetValue() );
636 
637  msg.Printf( wxT( "%f" ), m_dummyPad->GetLocalSolderPasteMarginRatio() * 100.0 );
638 
639  if( m_dummyPad->GetLocalSolderPasteMarginRatio() == 0.0 && msg[0] == '0' )
640  // Sometimes Printf adds a sign if the value is small
641  m_SolderPasteMarginRatioCtrl->SetValue( wxT( "-" ) + msg );
642  else
644 
645  switch( m_dummyPad->GetZoneConnection() )
646  {
647  default:
649  m_ZoneConnectionChoice->SetSelection( 0 );
650  m_ZoneConnectionCustom->SetSelection( 0 );
651  break;
652 
653  case PAD_ZONE_CONN_FULL:
654  m_ZoneConnectionChoice->SetSelection( 1 );
655  m_ZoneConnectionCustom->SetSelection( 1 );
656  break;
657 
659  m_ZoneConnectionChoice->SetSelection( 2 );
660  m_ZoneConnectionCustom->SetSelection( 0 );
661  break;
662 
663  case PAD_ZONE_CONN_NONE:
664  m_ZoneConnectionChoice->SetSelection( 3 );
665  m_ZoneConnectionCustom->SetSelection( 0 );
666  break;
667  }
668 
670  m_ZoneCustomPadShape->SetSelection( 1 );
671  else
672  m_ZoneCustomPadShape->SetSelection( 0 );
673 
674  if( m_currentPad )
675  {
676  angle = m_currentPad->GetOrientation();
677  MODULE* footprint = m_currentPad->GetParent();
678 
679  if( footprint )
680  angle -= footprint->GetOrientation();
681 
682  if( m_isFlipped )
683  angle = -angle;
684 
685  m_dummyPad->SetOrientation( angle );
686  }
687 
688  angle = m_dummyPad->GetOrientation();
689 
690  NORMALIZE_ANGLE_180( angle ); // ? normalizing is in D_PAD::SetOrientation()
691 
692  // Set layers used by this pad: :
694 
695  // Pad Orient
696  // Note: use ChangeValue() instead of SetValue() so that we don't generate events
697  m_orientation->ChangeValue( StringFromValue( DEGREES, angle ) );
698 
699  switch( m_dummyPad->GetShape() )
700  {
701  default:
702  case PAD_SHAPE_CIRCLE: m_PadShape->SetSelection( CHOICE_SHAPE_CIRCLE ); break;
703  case PAD_SHAPE_OVAL: m_PadShape->SetSelection( CHOICE_SHAPE_OVAL ); break;
704  case PAD_SHAPE_RECT: m_PadShape->SetSelection( CHOICE_SHAPE_RECT ); break;
705  case PAD_SHAPE_TRAPEZOID: m_PadShape->SetSelection( CHOICE_SHAPE_TRAPEZOID ); break;
706  case PAD_SHAPE_ROUNDRECT: m_PadShape->SetSelection( CHOICE_SHAPE_ROUNDRECT ); break;
707 
708  case PAD_SHAPE_CUSTOM:
711  else
713  break;
714  }
715 
717 
718  // Type of pad selection
720  {
721  m_PadType->SetSelection( 4 );
722  }
723  else
724  {
725  switch( m_dummyPad->GetAttribute() )
726  {
727  case PAD_ATTRIB_STANDARD: m_PadType->SetSelection( 0 ); break;
728  case PAD_ATTRIB_SMD: m_PadType->SetSelection( 1 ); break;
729  case PAD_ATTRIB_CONN: m_PadType->SetSelection( 2 ); break;
730  case PAD_ATTRIB_HOLE_NOT_PLATED: m_PadType->SetSelection( 3 ); break;
731  }
732  }
733 
734  // Disable Pad name,and pad to die length for NPTH pads (mechanical pads)
736 
737  m_PadNumText->Enable( enable );
738  m_PadNumCtrl->Enable( enable );
739  m_PadNameText->Enable( enable && m_canEditNetName && m_currentPad );
740  m_PadNetSelector->Enable( enable && m_canEditNetName && m_currentPad );
741  m_padToDie.Enable( enable );
742 
744  m_holeShapeCtrl->SetSelection( 0 );
745  else
746  m_holeShapeCtrl->SetSelection( 1 );
747 
748  // Update some dialog widgets state (Enable/disable options):
749  wxCommandEvent cmd_event;
751  OnDrillShapeSelected( cmd_event );
752  OnPadShapeSelection( cmd_event );
754 
755  // Update basic shapes list
757 }
758 
759 // A small helper function, to display coordinates:
760 static wxString formatCoord( EDA_UNITS_T aUnits, wxPoint aCoord )
761 {
762  return wxString::Format( "(X:%s Y:%s)",
763  MessageTextFromValue( aUnits, aCoord.x, true ),
764  MessageTextFromValue( aUnits, aCoord.y, true ) );
765 }
766 
768 {
769  m_listCtrlPrimitives->ClearAll();
770 
771  wxListItem itemCol;
772  itemCol.SetImage(-1);
773 
774  for( int ii = 0; ii < 5; ++ii )
775  m_listCtrlPrimitives->InsertColumn(ii, itemCol);
776 
777  wxString bs_info[5];
778 
779  for( unsigned ii = 0; ii < m_primitives.size(); ++ii )
780  {
781  const PAD_CS_PRIMITIVE& primitive = m_primitives[ii];
782 
783  for( unsigned jj = 0; jj < 5; ++jj )
784  bs_info[jj].Empty();
785 
786  bs_info[4] = wxString::Format( _( "width %s" ),
787  MessageTextFromValue( m_units, primitive.m_Thickness, true ) );
788 
789  switch( primitive.m_Shape )
790  {
791  case S_SEGMENT: // usual segment : line with rounded ends
792  bs_info[0] = _( "Segment" );
793  bs_info[1] = _( "from " ) + formatCoord( m_units, primitive.m_Start );
794  bs_info[2] = _( "to " ) + formatCoord( m_units, primitive.m_End );
795  break;
796 
797  case S_ARC: // Arc with rounded ends
798  bs_info[0] = _( "Arc" );
799  bs_info[1] = _( "center " ) + formatCoord( m_units, primitive.m_Start );// Center
800  bs_info[2] = _( "start " ) + formatCoord( m_units, primitive.m_End ); // Start point
801  bs_info[3] = wxString::Format( _( "angle %s" ), FMT_ANGLE( primitive.m_ArcAngle ) );
802  break;
803 
804  case S_CIRCLE: // ring or circle
805  if( primitive.m_Thickness )
806  bs_info[0] = _( "ring" );
807  else
808  bs_info[0] = _( "circle" );
809 
810  bs_info[1] = formatCoord( m_units, primitive.m_Start );
811  bs_info[2] = wxString::Format( _( "radius %s" ),
812  MessageTextFromValue( m_units, primitive.m_Radius, true ) );
813  break;
814 
815  case S_POLYGON: // polygon
816  bs_info[0] = "Polygon";
817  bs_info[1] = wxString::Format( _( "corners count %d" ), (int) primitive.m_Poly.size() );
818  break;
819 
820  default:
821  bs_info[0] = "Unknown primitive";
822  break;
823  }
824 
825  long tmp = m_listCtrlPrimitives->InsertItem(ii, bs_info[0]);
826  m_listCtrlPrimitives->SetItemData(tmp, ii);
827 
828  for( int jj = 0, col = 0; jj < 5; ++jj )
829  {
830  m_listCtrlPrimitives->SetItem(tmp, col++, bs_info[jj]);
831  }
832  }
833 
834  // Now columns are filled, ensure correct width of columns
835  for( unsigned ii = 0; ii < 5; ++ii )
836  m_listCtrlPrimitives->SetColumnWidth( ii, wxLIST_AUTOSIZE );
837 }
838 
839 void DIALOG_PAD_PROPERTIES::OnResize( wxSizeEvent& event )
840 {
841  redraw();
842  event.Skip();
843 }
844 
845 
846 void DIALOG_PAD_PROPERTIES::onChangePadMode( wxCommandEvent& event )
847 {
848  m_sketchPreview = m_cbShowPadOutline->GetValue();
849 
850  if( m_parent->IsGalCanvasActive() )
851  {
853 
854  // fix the pad render mode (filled/not filled)
855  KIGFX::PCB_RENDER_SETTINGS* settings =
856  static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
857 
862  }
863 
864  redraw();
865 }
866 
867 
868 void DIALOG_PAD_PROPERTIES::OnPadShapeSelection( wxCommandEvent& event )
869 {
870  bool is_custom = false;
871 
872  switch( m_PadShape->GetSelection() )
873  {
874  case CHOICE_SHAPE_CIRCLE:
875  m_trapDelta.Enable( false );
876  m_trapAxisLabel->Enable( false );
877  m_trapAxisCtrl->Enable( false );
878  m_sizeY.Enable( false );
879  m_offsetX.Enable( false );
880  m_offsetY.Enable( false );
881  break;
882 
883  case CHOICE_SHAPE_OVAL:
884  m_trapDelta.Enable( false );
885  m_trapAxisLabel->Enable( false );
886  m_trapAxisCtrl->Enable( false );
887  m_sizeY.Enable( true );
888  m_offsetX.Enable( true );
889  m_offsetY.Enable( true );
890  break;
891 
892  case CHOICE_SHAPE_RECT:
893  m_trapDelta.Enable( false );
894  m_trapAxisLabel->Enable( false );
895  m_trapAxisCtrl->Enable( false );
896  m_sizeY.Enable( true );
897  m_offsetX.Enable( true );
898  m_offsetY.Enable( true );
899  break;
900 
902  m_trapDelta.Enable( true );
903  m_trapAxisLabel->Enable( true );
904  m_trapAxisCtrl->Enable( true );
905  m_sizeY.Enable( true );
906  m_offsetX.Enable( true );
907  m_offsetY.Enable( true );
908  break;
909 
911  m_trapDelta.Enable( false );
912  m_trapAxisLabel->Enable( false );
913  m_trapAxisCtrl->Enable( false );
914  m_sizeY.Enable( true );
915  m_offsetX.Enable( true );
916  m_offsetY.Enable( true );
917  // Ensure m_tcCornerSizeRatio contains the right value:
918  m_tcCornerSizeRatio->ChangeValue( wxString::Format( "%.1f",
920  break;
921 
922  case CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR: // PAD_SHAPE_CUSTOM, circular anchor
923  case CHOICE_SHAPE_CUSTOM_RECT_ANCHOR: // PAD_SHAPE_CUSTOM, rect anchor
924  is_custom = true;
925  m_trapDelta.Enable( false );
926  m_trapAxisLabel->Enable( false );
927  m_trapAxisCtrl->Enable( false );
929  m_offsetX.Enable( false );
930  m_offsetY.Enable( false );
931  break;
932  }
933 
934  enablePrimitivePage( is_custom );
935 
936  // A few widgets are enabled only for rounded rect pads:
937  m_staticTextCornerSizeRatio->Enable( m_PadShape->GetSelection() == CHOICE_SHAPE_ROUNDRECT );
938  m_tcCornerSizeRatio->Enable( m_PadShape->GetSelection() == CHOICE_SHAPE_ROUNDRECT );
941 
942  // PAD_SHAPE_CUSTOM type has constraints for zone connection and thermal shape:
943  // only not connected or solid connection is allowed to avoid destroying the shape.
944  // Enable/disable options only available for custom shaped pads
945  m_ZoneConnectionChoice->Enable( !is_custom );
946  m_ZoneConnectionCustom->Enable( is_custom );
947  m_spokeWidth.Enable( !is_custom );
948  m_thermalGap.Enable( !is_custom );
949 
950  m_sbSizerZonesSettings->Show( !is_custom );
951  m_sbSizerCustomShapedZonesSettings->Show( is_custom );
952 
954 
956  redraw();
957 }
958 
959 
960 void DIALOG_PAD_PROPERTIES::OnDrillShapeSelected( wxCommandEvent& event )
961 {
963  redraw();
964 }
965 
966 
967 void DIALOG_PAD_PROPERTIES::PadOrientEvent( wxCommandEvent& event )
968 {
970  redraw();
971 }
972 
973 
974 void DIALOG_PAD_PROPERTIES::PadTypeSelected( wxCommandEvent& event )
975 {
976  int ii = m_PadType->GetSelection();
977 
978  if( (unsigned)ii >= DIM( code_type ) ) // catches < 0 also
979  ii = 0;
980 
981  bool hasHole, hasConnection;
982 
983  switch( ii )
984  {
985  default:
986  case 0: /* PTH */ hasHole = true; hasConnection = true; break;
987  case 1: /* SMD */ hasHole = false; hasConnection = true; break;
988  case 2: /* CONN */ hasHole = false; hasConnection = true; break;
989  case 3: /* NPTH */ hasHole = true; hasConnection = false; break;
990  case 4: /* Aperture */ hasHole = false; hasConnection = false; break;
991  }
992 
993  LSET layer_mask = std_pad_layers[ii];
994  setPadLayersList( layer_mask );
995 
996  if( !hasHole )
997  {
998  m_holeX.SetValue( 0 );
999  m_holeY.SetValue( 0 );
1000  }
1001  else if ( m_holeX.GetValue() == 0 && m_currentPad )
1002  {
1005  }
1006 
1007  if( !hasConnection )
1008  {
1009  m_PadNumCtrl->SetValue( wxEmptyString );
1011  m_padToDie.SetValue( 0 );
1012  }
1013  else if( m_PadNumCtrl->GetValue().IsEmpty() && m_currentPad )
1014  {
1015  m_PadNumCtrl->SetValue( m_currentPad->GetName() );
1017  }
1018 
1020  redraw();
1021 }
1022 
1023 
1024 void DIALOG_PAD_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
1025 {
1026  int ii = m_PadType->GetSelection();
1027 
1028  if( (unsigned)ii >= DIM( code_type ) ) // catches < 0 also
1029  ii = 0;
1030 
1031  bool hasHole, hasConnection;
1032 
1033  switch( ii )
1034  {
1035  default:
1036  case 0: /* PTH */ hasHole = true; hasConnection = true; break;
1037  case 1: /* SMD */ hasHole = false; hasConnection = true; break;
1038  case 2: /* CONN */ hasHole = false; hasConnection = true; break;
1039  case 3: /* NPTH */ hasHole = true; hasConnection = false; break;
1040  case 4: /* Aperture */ hasHole = false; hasConnection = false; break;
1041  }
1042 
1043  // Enable/disable hole controls
1044  m_holeShapeLabel->Enable( hasHole );
1045  m_holeShapeCtrl->Enable( hasHole );
1046  m_holeX.Enable( hasHole );
1047  m_holeY.Enable( hasHole && m_holeShapeCtrl->GetSelection() == 1 );
1048 
1049  // Enable/disable Pad number, net and pad length-to-die
1050  m_PadNumText->Enable( hasConnection );
1051  m_PadNumCtrl->Enable( hasConnection );
1052  m_PadNameText->Enable( hasConnection );
1053  m_PadNetSelector->Enable( hasConnection && m_canEditNetName && m_currentPad );
1054  m_padToDie.Enable( hasConnection );
1055 
1056  // Enable/disable Copper Layers control
1057  m_rbCopperLayersSel->Enable( ii != 4 );
1058 }
1059 
1060 
1062 {
1063  LSET cu_set = layer_mask & LSET::AllCuMask();
1064 
1065  if( cu_set == LSET( F_Cu ) )
1066  m_rbCopperLayersSel->SetSelection( 0 );
1067  else if( cu_set == LSET( B_Cu ) )
1068  m_rbCopperLayersSel->SetSelection( 1 );
1069  else if( cu_set.any() )
1070  m_rbCopperLayersSel->SetSelection( 2 );
1071  else
1072  m_rbCopperLayersSel->SetSelection( 3 );
1073 
1074  m_PadLayerAdhCmp->SetValue( layer_mask[F_Adhes] );
1075  m_PadLayerAdhCu->SetValue( layer_mask[B_Adhes] );
1076 
1077  m_PadLayerPateCmp->SetValue( layer_mask[F_Paste] );
1078  m_PadLayerPateCu->SetValue( layer_mask[B_Paste] );
1079 
1080  m_PadLayerSilkCmp->SetValue( layer_mask[F_SilkS] );
1081  m_PadLayerSilkCu->SetValue( layer_mask[B_SilkS] );
1082 
1083  m_PadLayerMaskCmp->SetValue( layer_mask[F_Mask] );
1084  m_PadLayerMaskCu->SetValue( layer_mask[B_Mask] );
1085 
1086  m_PadLayerECO1->SetValue( layer_mask[Eco1_User] );
1087  m_PadLayerECO2->SetValue( layer_mask[Eco2_User] );
1088 
1089  m_PadLayerDraft->SetValue( layer_mask[Dwgs_User] );
1090 }
1091 
1092 
1093 // Called when select/deselect a layer.
1094 void DIALOG_PAD_PROPERTIES::OnSetLayers( wxCommandEvent& event )
1095 {
1097  redraw();
1098 }
1099 
1100 
1101 // test if all values are acceptable for the pad
1103 {
1104  bool error = transferDataToPad( m_dummyPad );
1105  bool skip_tstoffset = false; // the offset prm is not always tested
1106 
1107  wxArrayString error_msgs;
1108  wxString msg;
1109 
1110  // Test for incorrect values
1111  if( (m_dummyPad->GetSize().x <= 0) ||
1112  ((m_dummyPad->GetSize().y <= 0) && (m_dummyPad->GetShape() != PAD_SHAPE_CIRCLE)) )
1113  {
1114  error_msgs.Add( _( "Pad size must be greater than zero" ) );
1115  }
1116 
1117  if( (m_dummyPad->GetSize().x < m_dummyPad->GetDrillSize().x) ||
1118  (m_dummyPad->GetSize().y < m_dummyPad->GetDrillSize().y) )
1119  {
1120  error_msgs.Add( _( "Incorrect value for pad drill: pad drill bigger than pad size" ) );
1121  skip_tstoffset = true; // offset prm will be not tested because if the drill value
1122  // is incorrect the offset prm is always seen as incorrect, even if it is 0
1123  }
1124 
1125  if( m_dummyPad->GetLocalClearance() < 0 )
1126  {
1127  error_msgs.Add( _( "Pad local clearance must be zero or greater than zero" ) );
1128  }
1129 
1130  // Some pads need a negative solder mask clearance (mainly for BGA with small pads)
1131  // However the negative solder mask clearance must not create negative mask size
1132  // Therefore test for minimal acceptable negative value
1133  // Hovewer, a negative value can give strange result with custom shapes, so it is not
1134  // allowed for custom pad shape
1136  {
1138  error_msgs.Add( _( "Pad local solder mask clearance must be zero or greater than zero" ) );
1139  else
1140  {
1141  int min_smClearance = -std::min( m_dummyPad->GetSize().x, m_dummyPad->GetSize().y )/2;
1142 
1143  if( m_dummyPad->GetLocalSolderMaskMargin() <= min_smClearance )
1144  {
1145  error_msgs.Add( wxString::Format(
1146  _( "Pad local solder mask clearance must be greater than %s" ),
1147  StringFromValue( GetUserUnits(), min_smClearance, true, true ) ) );
1148  }
1149  }
1150  }
1151 
1152  // Some pads need a positive solder paste clearance (mainly for BGA with small pads)
1153  // Hovewer, a positive value can create issues if the resulting shape is too big.
1154  // (like a solder paste creating a solder paste area on a neighbour pad or on the solder mask)
1155  // So we could ask for user to confirm the choice
1156  // Currently there are no test
1157 
1158  LSET padlayers_mask = m_dummyPad->GetLayerSet();
1159 
1160  if( padlayers_mask == 0 )
1161  error_msgs.Add( _( "Error: pad has no layer" ) );
1162 
1163  if( !padlayers_mask[F_Cu] && !padlayers_mask[B_Cu] )
1164  {
1165  if( m_dummyPad->GetDrillSize().x || m_dummyPad->GetDrillSize().y )
1166  {
1167  // Note: he message is shown in an HTML window
1168  msg = _( "Error: the pad is not on a copper layer and has a hole" );
1169 
1171  {
1172  msg += wxT( "<br><br><i>" );
1173  msg += _( "For NPTH pad, set pad size value to pad drill value,"
1174  " if you do not want this pad plotted in gerber files" );
1175  }
1176 
1177  error_msgs.Add( msg );
1178  }
1179  }
1180 
1181  if( !skip_tstoffset )
1182  {
1183  wxPoint max_size;
1184  max_size.x = std::abs( m_dummyPad->GetOffset().x );
1185  max_size.y = std::abs( m_dummyPad->GetOffset().y );
1186  max_size.x += m_dummyPad->GetDrillSize().x / 2;
1187  max_size.y += m_dummyPad->GetDrillSize().y / 2;
1188 
1189  if( ( m_dummyPad->GetSize().x / 2 < max_size.x ) ||
1190  ( m_dummyPad->GetSize().y / 2 < max_size.y ) )
1191  {
1192  error_msgs.Add( _( "Incorrect value for pad offset" ) );
1193  }
1194  }
1195 
1196  if( error )
1197  error_msgs.Add( _( "Too large value for pad delta size" ) );
1198 
1199  switch( m_dummyPad->GetAttribute() )
1200  {
1201  case PAD_ATTRIB_HOLE_NOT_PLATED: // Not plated, but through hole, a hole is expected
1202  case PAD_ATTRIB_STANDARD : // Pad through hole, a hole is also expected
1203  if( m_dummyPad->GetDrillSize().x <= 0 ||
1205  error_msgs.Add( _( "Error: Through hole pad: drill diameter set to 0" ) );
1206  break;
1207 
1208  case PAD_ATTRIB_CONN: // Connector pads are smd pads, just they do not have solder paste.
1209  if( padlayers_mask[B_Paste] || padlayers_mask[F_Paste] )
1210  error_msgs.Add( _( "Error: Connector pads are not on the solder paste layer\n"
1211  "Use SMD pads instead" ) );
1212  // Fall trough
1213  case PAD_ATTRIB_SMD: // SMD and Connector pads (One external copper layer only)
1214  {
1215  LSET innerlayers_mask = padlayers_mask & LSET::InternalCuMask();
1216 
1217  if( ( padlayers_mask[F_Cu] && padlayers_mask[B_Cu] ) ||
1218  innerlayers_mask.count() != 0 )
1219  error_msgs.Add( _( "Error: only one external copper layer allowed for SMD or Connector pads" ) );
1220  }
1221  break;
1222  }
1223 
1224 
1226  {
1227  wxString value = m_tcCornerSizeRatio->GetValue();
1228  double rrRadiusRatioPercent;
1229 
1230  if( !value.ToDouble( &rrRadiusRatioPercent ) )
1231  error_msgs.Add( _( "Incorrect corner size value" ) );
1232  else
1233  {
1234  if( rrRadiusRatioPercent < 0.0 )
1235  error_msgs.Add( _( "Incorrect (negative) corner size value" ) );
1236  else if( rrRadiusRatioPercent > 50.0 )
1237  error_msgs.Add( _( "Corner size value must be smaller than 50%" ) );
1238  }
1239  }
1240 
1242  {
1244  error_msgs.Add( _( "Incorrect pad shape: the shape must be equivalent to only one polygon" ) );
1245  }
1246 
1247 
1248  if( error_msgs.GetCount() )
1249  {
1250  HTML_MESSAGE_BOX dlg( this, _("Pad setup errors list" ) );
1251  dlg.ListSet( error_msgs );
1252  dlg.ShowModal();
1253  }
1254 
1255  return error_msgs.GetCount() == 0;
1256 }
1257 
1258 
1260 {
1261  if( m_parent->IsGalCanvasActive() )
1262  {
1265 
1266  // The layer used to place primitive items selected when editing custom pad shapes
1267  // we use here a layer never used in a pad:
1268  #define SELECTED_ITEMS_LAYER Dwgs_User
1269 
1271  KIGFX::PCB_RENDER_SETTINGS* settings =
1272  static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
1274 
1275  view->Update( m_dummyPad );
1276 
1277  // delete previous items if highlight list
1278  while( m_highlight.size() )
1279  {
1280  delete m_highlight.back(); // the dtor also removes item from view
1281  m_highlight.pop_back();
1282  }
1283 
1284  // highlight selected primitives:
1285  long select = m_listCtrlPrimitives->GetFirstSelected();
1286 
1287  while( select >= 0 )
1288  {
1289  PAD_CS_PRIMITIVE& primitive = m_primitives[select];
1290 
1291  DRAWSEGMENT* dummySegment = new DRAWSEGMENT;
1292  dummySegment->SetLayer( SELECTED_ITEMS_LAYER );
1293  primitive.ExportTo( dummySegment );
1294  dummySegment->Rotate( wxPoint( 0, 0), m_dummyPad->GetOrientation() );
1295  dummySegment->Move( m_dummyPad->GetPosition() );
1296 
1297  // Update selected primitive (highligth selected)
1298  switch( primitive.m_Shape )
1299  {
1300  case S_SEGMENT:
1301  case S_ARC:
1302  break;
1303 
1304  case S_CIRCLE: // ring or circle
1305  if( primitive.m_Thickness == 0 ) // filled circle
1306  { // the filled circle option does not exist in a DRAWSEGMENT
1307  // but it is easy to create it with a circle having the
1308  // right radius and outline width
1309  wxPoint end = dummySegment->GetCenter();
1310  end.x += primitive.m_Radius/2;
1311  dummySegment->SetEnd( end );
1312  dummySegment->SetWidth( primitive.m_Radius );
1313  }
1314  break;
1315 
1316  case S_POLYGON:
1317  break;
1318 
1319  default:
1320  delete dummySegment;
1321  dummySegment = nullptr;
1322  break;
1323  }
1324 
1325  if( dummySegment )
1326  {
1327  view->Add( dummySegment );
1328  m_highlight.push_back( dummySegment );
1329  }
1330 
1331  select = m_listCtrlPrimitives->GetNextSelected( select );
1332  }
1333 
1334  BOX2I bbox = m_dummyPad->ViewBBox();
1335 
1336  if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
1337  {
1338  // gives a size to the full drawable area
1339  BOX2I drawbox;
1340  drawbox.Move( m_dummyPad->GetPosition() );
1341  drawbox.Inflate( bbox.GetSize().x*2, bbox.GetSize().y*2 );
1342 
1343  view->SetBoundary( drawbox );
1344 
1345  // Autozoom
1346  view->SetViewport( BOX2D( bbox.GetOrigin(), bbox.GetSize() ) );
1347 
1348  // Add a margin
1349  view->SetScale( m_panelShowPadGal->GetView()->GetScale() * 0.7 );
1350 
1353  }
1354  }
1355  else
1356  {
1357  m_panelShowPad->Refresh();
1358  }
1359 }
1360 
1361 
1363 {
1364  if( !wxDialog::TransferDataToWindow() )
1365  return false;
1366 
1367  if( !m_panelGeneral->TransferDataToWindow() )
1368  return false;
1369 
1370  if( !m_localSettingsPanel->TransferDataToWindow() )
1371  return false;
1372 
1373  return true;
1374 }
1375 
1376 
1378 {
1379  BOARD_COMMIT commit( m_parent );
1380 
1381  if( !wxDialog::TransferDataFromWindow() )
1382  return false;
1383 
1384  if( !m_panelGeneral->TransferDataFromWindow() )
1385  return false;
1386 
1387  if( !m_localSettingsPanel->TransferDataFromWindow() )
1388  return false;
1389 
1390  if( !padValuesOK() )
1391  return false;
1392 
1393  bool rastnestIsChanged = false;
1394  int isign = m_isFlipped ? -1 : 1;
1395 
1397  // m_padMaster is a pattern: ensure there is no net for this pad:
1399 
1400  if( !m_currentPad ) // Set current Pad parameters
1401  return true;
1402 
1403  commit.Modify( m_currentPad );
1404 
1405  // redraw the area where the pad was, without pad (delete pad on screen)
1409 
1410  // Update values
1413 
1415  {
1417  rastnestIsChanged = true;
1418  }
1419 
1420  wxSize size;
1421  MODULE* footprint = m_currentPad->GetParent();
1422 
1423  if( footprint )
1424  {
1425  footprint->SetLastEditTime();
1426 
1427  // compute the pos 0 value, i.e. pad position for footprint with orientation = 0
1428  // i.e. relative to footprint origin (footprint position)
1429  wxPoint pt = m_currentPad->GetPosition() - footprint->GetPosition();
1430  RotatePoint( &pt, -footprint->GetOrientation() );
1431  m_currentPad->SetPos0( pt );
1433  + footprint->GetOrientation() );
1434  }
1435 
1437 
1438  size = m_padMaster->GetDelta();
1439  size.y *= isign;
1440  m_currentPad->SetDelta( size );
1441 
1444 
1445  wxPoint offset = m_padMaster->GetOffset();
1446  offset.y *= isign;
1447  m_currentPad->SetOffset( offset );
1448 
1450 
1453 
1454 
1457 
1458  if( m_isFlipped )
1459  {
1462  }
1463 
1465  {
1466  rastnestIsChanged = true;
1468  }
1469 
1470  if( m_isFlipped )
1471  {
1473  }
1474 
1476 
1477  int padNetcode = NETINFO_LIST::UNCONNECTED;
1478 
1479  // For PAD_ATTRIB_HOLE_NOT_PLATED, ensure there is no net name selected
1481  padNetcode = m_PadNetSelector->GetSelectedNetcode();
1482 
1483  if( m_currentPad->GetNetCode() != padNetcode )
1484  {
1485  rastnestIsChanged = true;
1486  m_currentPad->SetNetCode( padNetcode );
1487  }
1488 
1496 
1498  {
1501  else
1503  }
1504  else
1506 
1507 
1508  // rounded rect pads with radius ratio = 0 are in fact rect pads.
1509  // So set the right shape (and perhaps issues with a radius = 0)
1512  {
1514  }
1515 
1516  // define the way the clearance area is defined in zones
1518 
1519  if( footprint )
1520  footprint->CalculateBoundingBox();
1521 
1523 
1524  // redraw the area where the pad was
1526 
1527  commit.Push( _( "Modify pad" ) );
1528 
1529  if( rastnestIsChanged ) // The net ratsnest must be recalculated
1530  m_board->m_Status_Pcb = 0;
1531 
1532  return true;
1533 }
1534 
1535 
1537 {
1538  wxString msg;
1539 
1540  if( !Validate() )
1541  return true;
1542  if( !m_panelGeneral->Validate() )
1543  return true;
1544  if( !m_localSettingsPanel->Validate() )
1545  return true;
1546 
1547  m_OrientValidator.TransferFromWindow();
1548 
1549  aPad->SetAttribute( code_type[m_PadType->GetSelection()] );
1550  aPad->SetShape( code_shape[m_PadShape->GetSelection()] );
1553 
1554  if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
1555  aPad->SetPrimitives( m_primitives );
1556 
1557  // Read pad clearances values:
1562  aPad->SetThermalGap( m_thermalGap.GetValue() );
1563  double dtmp = 0.0;
1564  msg = m_SolderPasteMarginRatioCtrl->GetValue();
1565  msg.ToDouble( &dtmp );
1566 
1567  // A -50% margin ratio means no paste on a pad, the ratio must be >= -50%
1568  if( dtmp < -50.0 )
1569  dtmp = -50.0;
1570  // A margin ratio is always <= 0
1571  // 0 means use full pad copper area
1572  if( dtmp > 0.0 )
1573  dtmp = 0.0;
1574 
1575  aPad->SetLocalSolderPasteMarginRatio( dtmp / 100 );
1576 
1577  switch( m_ZoneConnectionChoice->GetSelection() )
1578  {
1579  default:
1580  case 0: aPad->SetZoneConnection( PAD_ZONE_CONN_INHERITED ); break;
1581  case 1: aPad->SetZoneConnection( PAD_ZONE_CONN_FULL ); break;
1582  case 2: aPad->SetZoneConnection( PAD_ZONE_CONN_THERMAL ); break;
1583  case 3: aPad->SetZoneConnection( PAD_ZONE_CONN_NONE ); break;
1584  }
1585 
1586  // Custom shape has only 2 options:
1587  if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
1588  {
1589  if( m_ZoneConnectionCustom->GetSelection() == 0 )
1591  else
1593  }
1594 
1595  aPad->SetPosition( wxPoint( m_posX.GetValue(), m_posY.GetValue() ) );
1596  aPad->SetPos0( wxPoint( m_posX.GetValue(), m_posY.GetValue() ) );
1597 
1598  if( m_holeShapeCtrl->GetSelection() == 0 )
1599  {
1601  aPad->SetDrillSize( wxSize( m_holeX.GetValue(), m_holeX.GetValue() ) );
1602  }
1603  else
1604  {
1606  aPad->SetDrillSize( wxSize( m_holeX.GetValue(), m_holeY.GetValue() ) );
1607  }
1608 
1609  if( aPad->GetShape() == PAD_SHAPE_CIRCLE )
1610  aPad->SetSize( wxSize( m_sizeX.GetValue(), m_sizeX.GetValue() ) );
1611  else
1612  aPad->SetSize( wxSize( m_sizeX.GetValue(), m_sizeY.GetValue() ) );
1613 
1614  // Read pad length die
1616 
1617  // For a trapezoid, test delta value (be sure delta is not too large for pad size)
1618  // remember DeltaSize.x is the Y size variation
1619  bool error = false;
1620 
1621  if( aPad->GetShape() == PAD_SHAPE_TRAPEZOID )
1622  {
1623  wxSize delta;
1624 
1625  // For a trapezoid, only one of delta.x or delta.y is not 0, depending on
1626  // the direction.
1627  if( m_trapAxisCtrl->GetSelection() == 0 )
1628  delta.x = m_trapDelta.GetValue();
1629  else
1630  delta.y = m_trapDelta.GetValue();
1631 
1632  if( delta.x < 0 && delta.x <= -aPad->GetSize().y )
1633  {
1634  delta.x = -aPad->GetSize().y + 2;
1635  error = true;
1636  }
1637 
1638  if( delta.x > 0 && delta.x >= aPad->GetSize().y )
1639  {
1640  delta.x = aPad->GetSize().y - 2;
1641  error = true;
1642  }
1643 
1644  if( delta.y < 0 && delta.y <= -aPad->GetSize().x )
1645  {
1646  delta.y = -aPad->GetSize().x + 2;
1647  error = true;
1648  }
1649 
1650  if( delta.y > 0 && delta.y >= aPad->GetSize().x )
1651  {
1652  delta.y = aPad->GetSize().x - 2;
1653  error = true;
1654  }
1655 
1656  aPad->SetDelta( delta );
1657  }
1658 
1660  aPad->SetOrientation( m_OrientValue * 10.0 );
1661  aPad->SetName( m_PadNumCtrl->GetValue() );
1663 
1664  // Clear some values, according to the pad type and shape
1665  switch( aPad->GetShape() )
1666  {
1667  case PAD_SHAPE_CIRCLE:
1668  aPad->SetOffset( wxPoint( 0, 0 ) );
1669  aPad->SetDelta( wxSize( 0, 0 ) );
1670  break;
1671 
1672  case PAD_SHAPE_RECT:
1673  aPad->SetDelta( wxSize( 0, 0 ) );
1674  break;
1675 
1676  case PAD_SHAPE_OVAL:
1677  aPad->SetDelta( wxSize( 0, 0 ) );
1678  break;
1679 
1680  case PAD_SHAPE_TRAPEZOID:
1681  break;
1682 
1683  case PAD_SHAPE_ROUNDRECT:
1684  aPad->SetDelta( wxSize( 0, 0 ) );
1685  break;
1686 
1687  case PAD_SHAPE_CUSTOM:
1688  aPad->SetOffset( wxPoint( 0, 0 ) );
1689  aPad->SetDelta( wxSize( 0, 0 ) );
1690 
1691  // The pad custom has a "anchor pad" (a basic shape: round or rect pad)
1692  // that is the minimal area of this pad, and is usefull to ensure a hole
1693  // diameter is acceptable, and is used in Gerber files as flashed area
1694  // reference
1695  if( aPad->GetAnchorPadShape() == PAD_SHAPE_CIRCLE )
1696  aPad->SetSize( wxSize( m_sizeX.GetValue(), m_sizeX.GetValue() ) );
1697 
1698  // define the way the clearance area is defined in zones
1699  aPad->SetCustomShapeInZoneOpt( m_ZoneCustomPadShape->GetSelection() == 0 ?
1702  break;
1703 
1704  default:
1705  ;
1706  }
1707 
1708  switch( aPad->GetAttribute() )
1709  {
1710  case PAD_ATTRIB_STANDARD:
1711  break;
1712 
1713  case PAD_ATTRIB_CONN:
1714  case PAD_ATTRIB_SMD:
1715  // SMD and PAD_ATTRIB_CONN has no hole.
1716  // basically, SMD and PAD_ATTRIB_CONN are same type of pads
1717  // PAD_ATTRIB_CONN has just a default non technical layers that differs from SMD
1718  // and are intended to be used in virtual edge board connectors
1719  // However we can accept a non null offset,
1720  // mainly to allow complex pads build from a set of basic pad shapes
1721  aPad->SetDrillSize( wxSize( 0, 0 ) );
1722  break;
1723 
1725  // Mechanical purpose only:
1726  // no offset, no net name, no pad name allowed
1727  aPad->SetOffset( wxPoint( 0, 0 ) );
1728  aPad->SetName( wxEmptyString );
1730  break;
1731 
1732  default:
1733  DisplayError( NULL, wxT( "Error: unknown pad type" ) );
1734  break;
1735  }
1736 
1737  if( aPad->GetShape() == PAD_SHAPE_ROUNDRECT )
1738  {
1739  wxString value = m_tcCornerSizeRatio->GetValue();
1740  double rrRadiusRatioPercent;
1741 
1742  if( value.ToDouble( &rrRadiusRatioPercent ) )
1743  aPad->SetRoundRectRadiusRatio( rrRadiusRatioPercent / 100.0 );
1744  }
1745 
1746  LSET padLayerMask;
1747 
1748  switch( m_rbCopperLayersSel->GetSelection() )
1749  {
1750  case 0: padLayerMask.set( F_Cu ); break;
1751  case 1: padLayerMask.set( B_Cu ); break;
1752  case 2: padLayerMask |= LSET::AllCuMask(); break;
1753  case 3: break; // No copper layers
1754  }
1755 
1756  if( m_PadLayerAdhCmp->GetValue() )
1757  padLayerMask.set( F_Adhes );
1758 
1759  if( m_PadLayerAdhCu->GetValue() )
1760  padLayerMask.set( B_Adhes );
1761 
1762  if( m_PadLayerPateCmp->GetValue() )
1763  padLayerMask.set( F_Paste );
1764 
1765  if( m_PadLayerPateCu->GetValue() )
1766  padLayerMask.set( B_Paste );
1767 
1768  if( m_PadLayerSilkCmp->GetValue() )
1769  padLayerMask.set( F_SilkS );
1770 
1771  if( m_PadLayerSilkCu->GetValue() )
1772  padLayerMask.set( B_SilkS );
1773 
1774  if( m_PadLayerMaskCmp->GetValue() )
1775  padLayerMask.set( F_Mask );
1776 
1777  if( m_PadLayerMaskCu->GetValue() )
1778  padLayerMask.set( B_Mask );
1779 
1780  if( m_PadLayerECO1->GetValue() )
1781  padLayerMask.set( Eco1_User );
1782 
1783  if( m_PadLayerECO2->GetValue() )
1784  padLayerMask.set( Eco2_User );
1785 
1786  if( m_PadLayerDraft->GetValue() )
1787  padLayerMask.set( Dwgs_User );
1788 
1789  aPad->SetLayerSet( padLayerMask );
1790 
1791  return error;
1792 }
1793 
1794 
1795 void DIALOG_PAD_PROPERTIES::OnValuesChanged( wxCommandEvent& event )
1796 {
1797  if( m_canUpdate )
1798  {
1800  // If the pad size has changed, update the displayed values
1801  // for rounded rect pads
1803 
1804  redraw();
1805  }
1806 }
1807 
1809 {
1810  long select = m_listCtrlPrimitives->GetFirstSelected();
1811 
1812  if( select < 0 )
1813  {
1814  wxMessageBox( _( "No shape selected" ) );
1815  return;
1816  }
1817 
1818  PAD_CS_PRIMITIVE& shape = m_primitives[select];
1819 
1820  if( shape.m_Shape == S_POLYGON )
1821  {
1822  DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, m_parent, &shape );
1823 
1824  if( dlg.ShowModal() != wxID_OK )
1825  return;
1826 
1827  dlg.TransferDataFromWindow();
1828  }
1829 
1830  else
1831  {
1832  DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, m_parent, &shape );
1833 
1834  if( dlg.ShowModal() != wxID_OK )
1835  return;
1836 
1837  dlg.TransferDataFromWindow();
1838  }
1839 
1841 
1842  if( m_canUpdate )
1843  {
1845  redraw();
1846  }
1847 }
1848 
1849 
1851 {
1852  // Called on a double click on the basic shapes list
1853  // To Do: highligth the primitive(s) currently selected.
1854  redraw();
1855 }
1856 
1857 
1859 void DIALOG_PAD_PROPERTIES::onPrimitiveDClick( wxMouseEvent& event )
1860 {
1861  editPrimitive();
1862 }
1863 
1864 
1865 // Called on a click on basic shapes list panel button
1866 void DIALOG_PAD_PROPERTIES::onEditPrimitive( wxCommandEvent& event )
1867 {
1868  editPrimitive();
1869 }
1870 
1871 // Called on a click on basic shapes list panel button
1872 void DIALOG_PAD_PROPERTIES::onDeletePrimitive( wxCommandEvent& event )
1873 {
1874  long select = m_listCtrlPrimitives->GetFirstSelected();
1875 
1876  if( select < 0 )
1877  return;
1878 
1879  // Multiple selections are allowed. get them and remove corresponding shapes
1880  std::vector<long> indexes;
1881  indexes.push_back( select );
1882 
1883  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
1884  indexes.push_back( select );
1885 
1886  // Erase all select shapes
1887  for( unsigned ii = indexes.size(); ii > 0; --ii )
1888  m_primitives.erase( m_primitives.begin() + indexes[ii-1] );
1889 
1891 
1892  if( m_canUpdate )
1893  {
1895  redraw();
1896  }
1897 }
1898 
1899 
1900 void DIALOG_PAD_PROPERTIES::onAddPrimitive( wxCommandEvent& event )
1901 {
1902  // Ask user for shape type
1903  wxString shapelist[] = { _( "Segment" ), _( "Arc" ), _( "Ring/Circle" ), _( "Polygon" ) };
1904 
1905  int type = wxGetSingleChoiceIndex( _( "Shape type:" ), _( "Add Primitive" ),
1906  DIM( shapelist ), shapelist, 0, this );
1907 
1908  STROKE_T listtype[] = { S_SEGMENT, S_ARC, S_CIRCLE, S_POLYGON };
1909 
1910  PAD_CS_PRIMITIVE primitive( listtype[type] );
1911 
1912  if( listtype[type] == S_POLYGON )
1913  {
1914  DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, m_parent, &primitive );
1915 
1916  if( dlg.ShowModal() != wxID_OK )
1917  return;
1918  }
1919  else
1920  {
1921  DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, m_parent, &primitive );
1922 
1923  if( dlg.ShowModal() != wxID_OK )
1924  return;
1925  }
1926 
1927  m_primitives.push_back( primitive );
1928 
1930 
1931  if( m_canUpdate )
1932  {
1934  redraw();
1935  }
1936 }
1937 
1938 
1939 void DIALOG_PAD_PROPERTIES::onGeometryTransform( wxCommandEvent& event )
1940 {
1941  long select = m_listCtrlPrimitives->GetFirstSelected();
1942 
1943  if( select < 0 )
1944  {
1945  wxMessageBox( _( "No shape selected" ) );
1946  return;
1947  }
1948 
1949  // Multiple selections are allowed. Build selected shapes list
1950  std::vector<PAD_CS_PRIMITIVE*> shapeList;
1951  shapeList.push_back( &m_primitives[select] );
1952 
1953  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
1954  shapeList.push_back( &m_primitives[select] );
1955 
1956  DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, m_parent, shapeList, false );
1957 
1958  if( dlg.ShowModal() != wxID_OK )
1959  return;
1960 
1961  // Transfert new settings:
1962  dlg.Transform();
1963 
1965 
1966  if( m_canUpdate )
1967  {
1969  redraw();
1970  }
1971 }
1972 
1973 
1974 void DIALOG_PAD_PROPERTIES::onDuplicatePrimitive( wxCommandEvent& event )
1975 {
1976  long select = m_listCtrlPrimitives->GetFirstSelected();
1977 
1978  if( select < 0 )
1979  {
1980  wxMessageBox( _( "No shape selected" ) );
1981  return;
1982  }
1983 
1984  // Multiple selections are allowed. Build selected shapes list
1985  std::vector<PAD_CS_PRIMITIVE*> shapeList;
1986  shapeList.push_back( &m_primitives[select] );
1987 
1988  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
1989  shapeList.push_back( &m_primitives[select] );
1990 
1991  DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, m_parent, shapeList, true );
1992 
1993  if( dlg.ShowModal() != wxID_OK )
1994  return;
1995 
1996  // Transfer new settings
1997  // save duplicates to a separate vector to avoid m_primitives reallocation,
1998  // as shapeList contains pointers to its elements
1999  std::vector<PAD_CS_PRIMITIVE> duplicates;
2000  dlg.Transform( &duplicates, dlg.GetDuplicateCount() );
2001  std::move( duplicates.begin(), duplicates.end(), std::back_inserter( m_primitives ) );
2002 
2004 
2005  if( m_canUpdate )
2006  {
2008  redraw();
2009  }
2010 }
void OnInitDialog(wxInitDialogEvent &event) override
bool MergePrimitivesAsPolygon(SHAPE_POLY_SET *aMergedPolygon=NULL, int aCircleToSegmentsCount=32)
Merge all basic shapes, converted to a polygon in one polygon, in m_customShapeAsPolygon.
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:673
void OnValuesChanged(wxCommandEvent &event) override
Called when a dimension has changed.
const Vec & GetOrigin() const
Definition: box2.h:191
void Move(const Vec &aMoveVector)
Function Move moves the rectangle by the aMoveVector.
Definition: box2.h:118
#define DIM(x)
of elements in an array
Definition: macros.h:98
void GRResetPenAndBrush(wxDC *DC)
Definition: gr_basic.cpp:123
COMMIT & Modify(EDA_ITEM *aItem)
Modifies a given item in the model.
Definition: commit.h:103
PAD_SHAPE_T GetAnchorPadShape() const
Function GetAnchorPadShape.
Definition: class_pad.h:226
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint BACK and FRONT copper layers, mask, paste, solder layers are swapped internal layers are flipped only if the copper layers count is known.
Definition: lset.cpp:518
DIALOG_PAD_PROPERTIES(PCB_BASE_FRAME *aParent, D_PAD *aPad)
const std::vector< PAD_CS_PRIMITIVE > & GetPrimitives() const
Accessor to the basic shape list.
Definition: class_pad.h:336
void SetViewport(const BOX2D &aViewport)
Function SetViewport() Sets the visible area of the VIEW.
Definition: view.cpp:548
bool IsAperturePad() const
Definition: class_pad.h:409
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:99
bool m_Display_padnum
Definition: class_pad.h:75
void FlipPrimitives()
Flip the basic shapes, in custom pads.
Definition: class_pad.cpp:451
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...
virtual void Move(const wxPoint &aMoveVector) override
Function Move move this object.
virtual EDA_DRAW_PANEL * GetCanvas() const
Definition: draw_frame.h:388
PAD_ATTR_T GetAttribute() const
Definition: class_pad.h:405
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:857
like PAD_STANDARD, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:65
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:58
multilayer pads, usually with holes
GAL_TYPE GetBackend() const
Function GetBackend Returns the type of backend currently used by GAL canvas.
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:120
This file is part of the common library.
const wxPoint GetCenter() const override
Function GetCenter()
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: class_pad.cpp:106
VIEW_CONTROLS class definition.
void CalculateBoundingBox()
Function CalculateBoundingBox calculates the bounding box in board coordinates.
int GetPadToDieLength() const
Definition: class_pad.h:412
bool transferDataToPad(D_PAD *aPad)
Copy values from dialog field to aPad&#39;s members.
Class BOARD to handle a board.
int GetRoundRectCornerRadius() const
Function GetRoundRectCornerRadius Has meaning only for rounded rect pads.
Definition: class_pad.h:531
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
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,.
int GetLocalSolderMaskMargin() const
Definition: class_pad.h:414
MODULE * GetParent() const
Definition: class_pad.h:162
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:61
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
BOARD * GetBoard() const
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:219
const wxString & GetValue() const
Function GetValue.
Definition: class_module.h:497
virtual void RefreshDrawingRect(const EDA_RECT &aRect, bool aEraseBackground=true)
Function RefreshDrawingRect redraws the contents of aRect in drawing units.
int GetSelectedNetcode()
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: class_pad.h:388
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
KIGFX::VIEW * GetView() const
Function GetView() Returns a pointer to the VIEW instance used in the panel.
void NORMALIZE_ANGLE_180(T &Angle)
Definition: trigo.h:335
const wxSize & GetDrillSize() const
Definition: class_pad.h:275
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:646
void Transform(std::vector< PAD_CS_PRIMITIVE > *aList=NULL, int aDuplicateCount=0)
Apply geometric transform (rotation, move, scale) defined in dialog aDuplicate = 1 ...
const Vec & GetSize() const
Definition: box2.h:187
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
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:216
#define abs(a)
Definition: auxiliary.h:84
void SetScale(double aScale)
Function SetScale() Sets the scaling factor.
Definition: view.h:250
smd pads, back layer
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:115
void 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
bool TransferDataFromWindow() override
Function TransferDataFromWindow Transfer data out of the GUI.
const wxPoint & GetArcStart() const
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
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
COLOR4D GetItemColor(int aItemIdx) const
Function GetItemColor.
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)
virtual const BOX2I ViewBBox() const override
Function ViewBBox() returns the bounding box of the item covering all its layers. ...
Definition: class_pad.cpp:1353
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 wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
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:489
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
GAL * GetGAL() const
Function GetGAL() Returns the GAL this view is using to draw graphical primitives.
Definition: view.h:180
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
int GetBoundingRadius() const
Function GetBoundingRadius returns the radius of a minimum sized circle which fully encloses this pad...
Definition: class_pad.h:612
double GetOrientation() const
Definition: class_module.h:189
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.
bool IsFlipped() const
function IsFlipped
Definition: class_module.h:259
Arcs (with rounded ends)
Helper class to handle a primitive (basic shape: polygon, segment, circle or arc) to build a custom p...
Definition: class_pad.h:91
ZoneConnection GetZoneConnection() const
Definition: class_pad.cpp:687
void SetLastEditTime(timestamp_t aTime)
Definition: class_module.h:314
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:402
void SetSelectedNetcode(int aNetcode)
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Function GetLayerName returns the name of a layer given by aLayer.
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).
int GetThermalWidth() const
Definition: class_pad.cpp:698
void OnResize(wxSizeEvent &event)
void OnPadShapeSelection(wxCommandEvent &event) override
void PadTypeSelected(wxCommandEvent &event) override
int GetThermalGap() const
Definition: class_pad.cpp:709
static LSET InternalCuMask()
Function InternalCuMask() returns a complete set of internal copper layers, which is all Cu layers ex...
Definition: lset.cpp:633
void SetThermalWidth(int aWidth)
Definition: class_pad.h:492
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 wxSize & GetSize() const
Definition: class_pad.h:269
void SetSize(const wxSize &aSize)
Definition: class_pad.h:268
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
const wxString & GetName() const
Definition: class_pad.h:190
void SetRoundRectCornerRadius(double aRadius)
Set the rounded rectangle radius ratio based on a given radius.
Definition: class_pad.cpp:207
void OnDrillShapeSelected(wxCommandEvent &event) override
bool IsGalCanvasActive() const
Function IsGalCanvasActive is used to check which canvas (GAL-based or standard) is currently in use...
Definition: draw_frame.h:914
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings returns the BOARD_DESIGN_SETTINGS for the BOARD owned by this frame...
bool m_ShowNotPlatedHole
Definition: class_pad.h:80
int GetLocalSolderPasteMargin() const
Definition: class_pad.h:420
void SetNetInfo(NETINFO_LIST *aNetInfoList)
void SetPadToDieLength(int aLength)
Definition: class_pad.h:411
PAINTER * GetPainter() const
Function GetPainter() Returns the painter object used by the view for drawing VIEW_ITEMS.
Definition: view.h:199
Class HTML_MESSAGE_BOX.
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:1530
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:750
Like smd, does not appear on the solder paste layer (default) note also has a special attribute in Ge...
Definition: pad_shapes.h:62
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:409
bool IsFlipped() const
Definition: class_pad.cpp:134
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.
int GetLocalClearance() const
Definition: class_pad.h:417
COLORS_DESIGN_SETTINGS & Colors()
void SetLocalClearance(int aClearance)
Definition: class_pad.h:418
a dialog to edit basic polygonal shape parameters
double GetLocalSolderPasteMarginRatio() const
Definition: class_pad.h:423
void SetLocalSolderPasteMarginRatio(double aRatio)
Definition: class_pad.h:424
bool SwitchBackend(GAL_TYPE aGalType) override
Function SwitchBackend Switches method of rendering graphics.
int GetNetCode() const
Function GetNetCode.
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:401
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
double GetRoundRectRadiusRatio() const
has meaning only for rounded rect pads
Definition: class_pad.h:634
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:386
static const LSET std_pad_layers[]
void onDeletePrimitive(wxCommandEvent &event) override
Event handlers of basic shapes list panel.
void onDuplicatePrimitive(wxCommandEvent &event) override
const wxString & GetReference() const
Function GetReference.
Definition: class_module.h:463
void SetLocalSolderMaskMargin(int aMargin)
Definition: class_pad.h:415
CUST_PAD_SHAPE_IN_ZONE GetCustomShapeInZoneOpt() const
Definition: class_pad.h:232
bool GetEnableMousewheelPan() const
void SetSketchMode(int aItemLayer, bool aEnabled)
Function SetSketchMode Turns on/off sketch mode for given item layer.
Definition: pcb_painter.h:114
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 wxPoint GetArcEnd() const
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees, but soon degrees.
Definition: class_pad.h:382
D_PAD m_Pad_Master
A dummy pad to store all default parameters.
const wxSize & GetDelta() const
Definition: class_pad.h:272
Usual pad.
Definition: pad_shapes.h:60
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
#define SELECTED_ITEMS_LAYER
bool m_ShowPadFilled
Definition: class_pad.h:77
void SetEnd(const wxPoint &aEnd)
void SetOrientation(double aAngle)
Function SetOrientation sets the rotation angle of the pad.
Definition: class_pad.cpp:418
double GetScale() const
Function GetScale()
Definition: view.h:268
KIGFX::VIEW_CONTROLS * GetViewControls() const
Function GetViewControls() Returns a pointer to the VIEW_CONTROLS instance used in the panel...
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
COLOR4D m_Color
Definition: class_pad.h:68
EDA_DRAW_PANEL_GAL * GetGalCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
Definition: draw_frame.h:921
void SetLocalSolderPasteMargin(int aMargin)
Definition: class_pad.h:421
static LSET ConnSMDMask()
layer set for a SMD pad on Front layer used for edge board connectors
Definition: class_pad.cpp:113
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)
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Function Add() Adds a VIEW_ITEM to the view.
Definition: view.cpp:344
bool IsType(FRAME_T aType) const
Module description (excepted pads)
Definition: colors.h:45
static LSET ApertureMask()
layer set for an aperture pad
Definition: class_pad.cpp:127
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:172
bool m_Display_netname
Definition: class_pad.h:76
const wxPoint GetPosition() const override
Definition: class_pad.h:220
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
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:245
void SetThermalGap(int aGap)
Definition: class_pad.h:495
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:184
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...
#define FMT_ANGLE
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:216
EDA_UNITS_T
Definition: common.h:159
void StopDrawing()
Function StopDrawing() Prevents the GAL canvas from further drawing till it is recreated or StartDraw...
const wxPoint & GetOffset() const
Definition: class_pad.h:278
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.
#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
pads are covered by copper
Definition: zones.h:54
int m_Status_Pcb
Flags used in ratsnest calculation and update.
Definition: class_board.h:240
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:132
void SetWidth(int aWidth)