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