KiCad PCB EDA Suite
dialog_pad_properties.cpp
Go to the documentation of this file.
1 
6 /*
7  * This program source code file is part of KiCad, a free EDA CAD application.
8  *
9  * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
10  * Copyright (C) 2013 Dick Hollenbeck, dick@softplc.com
11  * Copyright (C) 2008-2013 Wayne Stambaugh <stambaughw@verizon.net>
12  * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, you may find one here:
26  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
27  * or you may search the http://www.gnu.org website for the version 2 license,
28  * or you may write to the Free Software Foundation, Inc.,
29  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
30  */
31 
32 #include <fctsys.h>
33 #include <common.h>
34 #include <gr_basic.h>
36 #include <view/view_controls.h>
37 #include <trigo.h>
38 #include <class_drawpanel.h>
39 #include <confirm.h>
40 #include <pcbnew.h>
41 #include <pcb_base_frame.h>
42 #include <base_units.h>
43 #include <unit_format.h>
44 #include <board_commit.h>
45 #include <bitmaps.h>
46 
47 #include <class_board.h>
48 #include <class_module.h>
49 #include <pcb_painter.h>
50 
51 #include <dialog_pad_properties.h>
52 #include <html_messagebox.h>
53 
54 
55 // list of pad shapes, ordered like the pad shape wxChoice in dialog.
56 static PAD_SHAPE_T code_shape[] = {
62  PAD_SHAPE_CUSTOM, // choice = CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
63  PAD_SHAPE_CUSTOM // choice = PAD_SHAPE_CUSTOM_RECT_ANCHOR
64 };
65 
66 // the ordered index of the pad shape wxChoice in dialog.
67 // keep it consistent with code_shape[] and dialog strings
76 };
77 
78 
79 
80 static PAD_ATTR_T code_type[] = {
85 };
86 
87 
88 // Default mask layers setup for pads according to the pad type
89 static const LSET std_pad_layers[] = {
90  // PAD_ATTRIB_STANDARD:
92 
93  // PAD_ATTRIB_SMD:
95 
96  // PAD_ATTRIB_CONN:
98 
99  // PAD_ATTRIB_HOLE_NOT_PLATED:
101 };
102 
103 
105 {
106  DIALOG_PAD_PROPERTIES dlg( this, aPad );
107  dlg.ShowModal();
108 }
109 
110 
112  DIALOG_PAD_PROPERTIES_BASE( aParent ),
113  m_OrientValidator( 1, &m_OrientValue )
114 {
115  m_canUpdate = false;
116  m_parent = aParent;
117  m_currentPad = aPad; // aPad can be NULL, if the dialog is called
118  // from the footprint editor to set default pad setup
119 
121 
122  m_OrientValidator.SetRange( -360.0, 360.0 );
123  m_PadOrientCtrl->SetValidator( m_OrientValidator );
124  m_OrientValidator.SetWindow( m_PadOrientCtrl );
125 
127 
129  m_dummyPad = new D_PAD( (MODULE*) NULL );
130 
131  if( aPad )
132  *m_dummyPad = *aPad;
133  else // We are editing a "master" pad, i.e. a template to create new pads
135 
136  initValues();
137 
138  // Usually, TransferDataToWindow is called by OnInitDialog
139  // calling it here fixes all widgets sizes, and FinishDialogSettings can
140  // safely fix minsizes
142 
143  // Initialize canvas to be able to display the dummy pad:
144  prepareCanvas();
145 
146  m_sdbSizerOK->SetDefault();
147  m_canUpdate = true;
148 
149  // Now all widgets have the size fixed, call FinishDialogSettings
151 }
152 
153 bool DIALOG_PAD_PROPERTIES::m_drawPadOutlineMode = false; // Stores the pad draw option during a session
154 
155 
156 void DIALOG_PAD_PROPERTIES::OnInitDialog( wxInitDialogEvent& event )
157 {
158  m_PadNumCtrl->SetFocus();
159  m_PadNumCtrl->SetSelection( -1, -1 );
160  m_selectedColor = COLOR4D( 1.0, 1.0, 1.0, 0.7 );
161 
162  // Needed on some WM to be sure the pad is redrawn according to the final size
163  // of the canvas, with the right zoom factor
164  redraw();
165 }
166 
167 
168 void DIALOG_PAD_PROPERTIES::OnCancel( wxCommandEvent& event )
169 {
170  // Mandatory to avoid m_panelShowPadGal trying to draw something
171  // in a non valid context during closing process:
172  if( m_parent->IsGalCanvasActive() )
174 
175  // Now call default handler for wxID_CANCEL command event
176  event.Skip();
177 }
178 
179 
181 {
182  // Enable or disable the widgets in page managing custom shape primitives
183  m_listCtrlPrimitives->Enable( aEnable );
184  m_buttonDel->Enable( aEnable );
185  m_buttonEditShape->Enable( aEnable );
186  m_buttonAddShape->Enable( aEnable );
187  m_buttonDup->Enable( aEnable );
188  m_buttonGeometry->Enable( aEnable );
189  m_buttonImport->Enable( aEnable );
190 }
191 
192 
194 {
195  // Initialize the canvases (legacy or gal) to display the pad
196  // Enable the suitable canvas and make some inits
197 
198  // Show the X and Y axis. It is usefull because pad shape can have an offset
199  // or be a complex shape.
200  KIGFX::COLOR4D axis_color = LIGHTBLUE;
201 
202  m_axisOrigin = new KIGFX::ORIGIN_VIEWITEM( axis_color,
204  Millimeter2iu( 0.2 ),
206  m_axisOrigin->SetDrawAtZero( true );
207 
208  if( m_parent->IsGalCanvasActive() )
209  {
213  EnableMousewheelPan( m_parent->GetCanvas()->GetEnableMousewheelPan() );
214 
215  m_panelShowPadGal->Show();
216  m_panelShowPad->Hide();
217 
219 
220  // fix the pad render mode (filled/not filled)
221  KIGFX::PCB_RENDER_SETTINGS* settings =
222  static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
223  bool filled = !m_cbShowPadOutline->IsChecked();
224  settings->SetSketchMode( LAYER_PADS_TH, !filled );
225  settings->SetSketchMode( LAYER_PAD_FR, !filled );
226  settings->SetSketchMode( LAYER_PAD_BK, !filled );
227  settings->SetSketchModeGraphicItems( !filled );
228 
229  // gives a non null grid size (0.001mm) because GAL layer does not like a 0 size grid:
230  double gridsize = 0.001 * IU_PER_MM;
231  view->GetGAL()->SetGridSize( VECTOR2D( gridsize, gridsize ) );
232  view->Add( m_dummyPad );
233  view->Add( m_axisOrigin );
234 
236  Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_PAD_PROPERTIES::OnResize ) );
237  }
238  else
239  {
240  m_panelShowPad->Show();
241  m_panelShowPadGal->Hide();
242  }
243 }
244 
245 
246 void DIALOG_PAD_PROPERTIES::OnPaintShowPanel( wxPaintEvent& event )
247 {
248  wxPaintDC dc( m_panelShowPad );
249  PAD_DRAWINFO drawInfo;
250 
252 
253  if( m_dummyPad->GetLayerSet()[F_Cu] )
254  {
256  }
257 
258  if( m_dummyPad->GetLayerSet()[B_Cu] )
259  {
260  color = color.LegacyMix( m_parent->Settings().Colors().GetItemColor( LAYER_PAD_BK ) );
261  }
262 
263  // What could happen: the pad color is *actually* black, or no
264  // copper was selected
265  if( color == BLACK )
266  color = LIGHTGRAY;
267 
268  drawInfo.m_Color = color;
269  drawInfo.m_HoleColor = DARKGRAY;
270  drawInfo.m_Offset = m_dummyPad->GetPosition();
271  drawInfo.m_Display_padnum = true;
272  drawInfo.m_Display_netname = true;
274 
276  drawInfo.m_ShowNotPlatedHole = true;
277 
278  // Shows the local pad clearance
280 
281  wxSize dc_size = dc.GetSize();
282  dc.SetDeviceOrigin( dc_size.x / 2, dc_size.y / 2 );
283 
284  // Calculate a suitable scale to fit the available draw area
285  int dim = m_dummyPad->GetBoundingRadius() *2;
286 
287  // Invalid x size. User could enter zero, or have deleted all text prior to
288  // entering a new value; this is also treated as zero. If dim is left at
289  // zero, the drawing scale is zero and we get a crash.
290  if( dim == 0 )
291  {
292  // If drill size has been set, use that. Otherwise default to 1mm.
293  dim = m_dummyPad->GetDrillSize().x;
294  if( dim == 0 )
295  dim = Millimeter2iu( 1.0 );
296  }
297 
298  if( m_dummyPad->GetLocalClearance() > 0 )
299  dim += m_dummyPad->GetLocalClearance() * 2;
300 
301  double scale = (double) dc_size.x / dim;
302 
303  // If the pad is a circle, use the x size here instead.
304  int ysize;
305 
307  ysize = m_dummyPad->GetSize().x;
308  else
309  ysize = m_dummyPad->GetSize().y;
310 
311  dim = ysize + std::abs( m_dummyPad->GetDelta().x );
312 
313  // Invalid y size. See note about x size above.
314  if( dim == 0 )
315  {
316  dim = m_dummyPad->GetDrillSize().y;
317  if( dim == 0 )
318  dim = Millimeter2iu( 0.1 );
319  }
320 
321  if( m_dummyPad->GetLocalClearance() > 0 )
322  dim += m_dummyPad->GetLocalClearance() * 2;
323 
324  double altscale = (double) dc_size.y / dim;
325  scale = std::min( scale, altscale );
326 
327  // Give a margin
328  scale *= 0.7;
329  dc.SetUserScale( scale, scale );
330 
331  GRResetPenAndBrush( &dc );
332  m_dummyPad->DrawShape( NULL, &dc, drawInfo );
333 
334  // draw selected primitives:
335  long select = m_listCtrlPrimitives->GetFirstSelected();
336  wxPoint start, end, center;
337 
338  while( select >= 0 )
339  {
340  PAD_CS_PRIMITIVE& primitive = m_primitives[select];
341 
342  // The best way to calculate parameters to draw a primitive is to
343  // use a dummy DRAWSEGMENT and use its methods
344  // Note: in legacy canvas, the pad has the 0,0 position
345  DRAWSEGMENT dummySegment;
346  primitive.ExportTo( &dummySegment );
347  dummySegment.Rotate( wxPoint( 0, 0), m_dummyPad->GetOrientation() );
348 
349  switch( primitive.m_Shape )
350  {
351  case S_SEGMENT: // usual segment : line with rounded ends
352  if( !m_drawPadOutlineMode )
353  GRFilledSegment( NULL, &dc, dummySegment.GetStart(), dummySegment.GetEnd(),
354  primitive.m_Thickness, m_selectedColor );
355  else
356  GRCSegm( NULL, &dc, dummySegment.GetStart(), dummySegment.GetEnd(),
357  primitive.m_Thickness, m_selectedColor );
358  break;
359 
360  case S_ARC: // Arc with rounded ends
361  if( !m_drawPadOutlineMode )
362  GRArc1( NULL, &dc, dummySegment.GetArcEnd(), dummySegment.GetArcStart(),
363  dummySegment.GetCenter(), primitive.m_Thickness, m_selectedColor );
364  else
365  {
366  GRArc1( NULL, &dc, dummySegment.GetArcEnd(), dummySegment.GetArcStart(),
367  dummySegment.GetCenter(), 0, m_selectedColor );
368 /* GRArc1( NULL, &dc, dummySegment.GetArcEnd(), dummySegment.GetArcStart(),
369  dummySegment.GetCenter() - primitive.m_Thickness, 0, m_selectedColor );*/
370  }
371  break;
372 
373  case S_CIRCLE: // ring or circle
374  if( primitive.m_Thickness )
375  {
376  if( !m_drawPadOutlineMode )
377  GRCircle( NULL, &dc, dummySegment.GetCenter(), primitive.m_Radius,
378  primitive.m_Thickness, m_selectedColor );
379  else
380  {
381  GRCircle( NULL, &dc, dummySegment.GetCenter(),
382  primitive.m_Radius + primitive.m_Thickness/2, 0,
383  m_selectedColor );
384  GRCircle( NULL, &dc, dummySegment.GetCenter(),
385  primitive.m_Radius - primitive.m_Thickness/2, 0,
386  m_selectedColor );
387  }
388  }
389  else
390  {
391  if( !m_drawPadOutlineMode )
392  GRFilledCircle( NULL, &dc, dummySegment.GetCenter(),
393  primitive.m_Radius, m_selectedColor );
394  else
395  GRCircle( NULL, &dc, dummySegment.GetCenter(),
396  primitive.m_Radius, 0, m_selectedColor );
397  }
398  break;
399 
400  case S_POLYGON: // polygon
401  {
402  std::vector<wxPoint> poly = dummySegment.BuildPolyPointsList();
403  GRClosedPoly( NULL, &dc, poly.size(), &poly[0],
404  m_drawPadOutlineMode ? false : true,
406  }
407  break;
408 
409  default:
410  break;
411  }
412 
413  select = m_listCtrlPrimitives->GetNextSelected( select );
414  }
415 
416  // Draw X and Y axis. This is particularly useful to show the
417  // reference position of pads with offset and no hole, or custom pad shapes
418  const int linethickness = 0;
419  GRLine( NULL, &dc, -int( dc_size.x/scale ), 0, int( dc_size.x/scale ), 0,
420  linethickness, LIGHTBLUE ); // X axis
421  GRLine( NULL, &dc, 0, -int( dc_size.y/scale ), 0, int( dc_size.y/scale ),
422  linethickness, LIGHTBLUE ); // Y axis
423 
424  event.Skip();
425 }
426 
427 
429 {
430  // Note:
431  // To avoid generating a wxEVT_TEXT event from m_tcCornerSizeRatio
432  // we use ChangeValue instead of SetValue, to set the displayed string
434  {
435  m_tcCornerSizeRatio->ChangeValue( wxString::Format( "%.1f",
439  }
440  else if( m_dummyPad->GetShape() == PAD_SHAPE_RECT )
441  {
442  m_tcCornerSizeRatio->ChangeValue( "0" );
443  m_staticTextCornerRadiusValue->SetLabel( "0" );
444  }
445  else
446  {
447  m_tcCornerSizeRatio->ChangeValue( wxEmptyString );
448  m_staticTextCornerRadiusValue->SetLabel( wxEmptyString );
449  }
450 }
451 
452 
454 {
456  return;
457 
458  wxString value = m_tcCornerSizeRatio->GetValue();
459  double rrRadiusRatioPercent;
460 
461  if( value.ToDouble( &rrRadiusRatioPercent ) )
462  {
463  // Clamp rrRadiusRatioPercent to acceptable value (0.0 to 50.0)
464  if( rrRadiusRatioPercent < 0.0 )
465  {
466  rrRadiusRatioPercent = 0.0;
467  m_tcCornerSizeRatio->ChangeValue( "0.0" );
468  }
469 
470  if( rrRadiusRatioPercent > 50.0 )
471  {
472  rrRadiusRatioPercent = 0.5;
473  m_tcCornerSizeRatio->ChangeValue( "50.0" );
474  }
475 
479  redraw();
480  }
481 }
482 
483 
485 {
486  wxString msg;
487  double angle;
488 
489  // Disable pad net name wxTextCtrl if the caller is the footprint editor
490  // because nets are living only in the board managed by the board editor
492 
493 
494  // Setup layers names from board
495  // Should be made first, before calling m_rbCopperLayersSel->SetSelection()
496  m_rbCopperLayersSel->SetString( 0, m_board->GetLayerName( F_Cu ) );
497  m_rbCopperLayersSel->SetString( 1, m_board->GetLayerName( B_Cu ) );
498 
499  m_PadLayerAdhCmp->SetLabel( m_board->GetLayerName( F_Adhes ) );
500  m_PadLayerAdhCu->SetLabel( m_board->GetLayerName( B_Adhes ) );
502  m_PadLayerPateCu->SetLabel( m_board->GetLayerName( B_Paste ) );
504  m_PadLayerSilkCu->SetLabel( m_board->GetLayerName( B_SilkS ) );
505  m_PadLayerMaskCmp->SetLabel( m_board->GetLayerName( F_Mask ) );
506  m_PadLayerMaskCu->SetLabel( m_board->GetLayerName( B_Mask ) );
507  m_PadLayerECO1->SetLabel( m_board->GetLayerName( Eco1_User ) );
508  m_PadLayerECO2->SetLabel( m_board->GetLayerName( Eco2_User ) );
510 
511  m_isFlipped = false;
512 
513  if( m_currentPad )
514  {
516 
517  if( m_isFlipped )
518  m_staticModuleSideValue->SetLabel( _( "Back side (footprint is mirrored)" ) );
519  else
520  m_staticModuleSideValue->SetLabel( _( "Front side" ) );
521 
522  // Diplay footprint rotation ( angles are in 0.1 degree )
523  MODULE* footprint = m_currentPad->GetParent();
524 
525  if( footprint )
526  msg.Printf( "%.1f", footprint->GetOrientationDegrees() );
527  else
528  msg = _("No footprint" );
529 
530  m_staticModuleRotValue->SetLabel( msg );
531  }
532 
533  if( m_isFlipped )
534  {
535  wxPoint pt = m_dummyPad->GetOffset();
536  pt.y = -pt.y;
537  m_dummyPad->SetOffset( pt );
538 
539  wxSize sz = m_dummyPad->GetDelta();
540  sz.y = -sz.y;
541  m_dummyPad->SetDelta( sz );
542 
543  // flip pad's layers
545 
546  // flip custom pad shapes
548  }
549 
551 
552  m_FlippedWarningIcon->SetBitmap( KiBitmap( dialog_warning_xpm ) );
554 
555  m_PadNumCtrl->SetValue( m_dummyPad->GetName() );
556  m_PadNetNameCtrl->SetValue( m_dummyPad->GetNetname() );
557 
558  // Set the unit name in dialog:
559  wxStaticText* unitTexts[] =
560  {
568  };
569 
570  for( unsigned ii = 0; ii < DIM( unitTexts ); ++ii )
571  unitTexts[ii]->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
572 
573  // Display current pad parameters units:
576 
579 
582 
585 
586  if( m_dummyPad->GetDelta().x )
587  {
589  m_trapDeltaDirChoice->SetSelection( 0 );
590  }
591  else
592  {
594  m_trapDeltaDirChoice->SetSelection( 1 );
595  }
596 
598 
603 
604  // These 2 parameters are usually < 0, so prepare entering a negative value, if current is 0
606 
608  m_SolderPasteMarginCtrl->SetValue( wxT( "-" ) + m_SolderPasteMarginCtrl->GetValue() );
609 
610  msg.Printf( wxT( "%f" ), m_dummyPad->GetLocalSolderPasteMarginRatio() * 100.0 );
611 
612  if( m_dummyPad->GetLocalSolderPasteMarginRatio() == 0.0 && msg[0] == '0' )
613  // Sometimes Printf adds a sign if the value is small
614  m_SolderPasteMarginRatioCtrl->SetValue( wxT( "-" ) + msg );
615  else
617 
618  switch( m_dummyPad->GetZoneConnection() )
619  {
620  default:
622  m_ZoneConnectionChoice->SetSelection( 0 );
623  m_ZoneConnectionCustom->SetSelection( 0 );
624  break;
625 
626  case PAD_ZONE_CONN_FULL:
627  m_ZoneConnectionChoice->SetSelection( 1 );
628  m_ZoneConnectionCustom->SetSelection( 1 );
629  break;
630 
632  m_ZoneConnectionChoice->SetSelection( 2 );
633  m_ZoneConnectionCustom->SetSelection( 0 );
634  break;
635 
636  case PAD_ZONE_CONN_NONE:
637  m_ZoneConnectionChoice->SetSelection( 3 );
638  m_ZoneConnectionCustom->SetSelection( 0 );
639  break;
640  }
641 
643  m_ZoneCustomPadShape->SetSelection( 1 );
644  else
645  m_ZoneCustomPadShape->SetSelection( 0 );
646 
647  if( m_currentPad )
648  {
649  angle = m_currentPad->GetOrientation();
650  MODULE* footprint = m_currentPad->GetParent();
651 
652  if( footprint )
653  angle -= footprint->GetOrientation();
654 
655  if( m_isFlipped )
656  angle = -angle;
657 
658  m_dummyPad->SetOrientation( angle );
659  }
660 
661  angle = m_dummyPad->GetOrientation();
662 
663  NORMALIZE_ANGLE_180( angle ); // ? normalizing is in D_PAD::SetOrientation()
664 
665  // Set layers used by this pad: :
667 
668  // Pad Orient
669  switch( int( angle ) )
670  {
671  case 0:
672  m_PadOrient->SetSelection( 0 );
673  break;
674 
675  case 900:
676  m_PadOrient->SetSelection( 1 );
677  break;
678 
679  case -900:
680  m_PadOrient->SetSelection( 2 );
681  break;
682 
683  case 1800:
684  case -1800:
685  m_PadOrient->SetSelection( 3 );
686  break;
687 
688  default:
689  m_PadOrient->SetSelection( 4 );
690  break;
691  }
692 
693  switch( m_dummyPad->GetShape() )
694  {
695  default:
696  case PAD_SHAPE_CIRCLE:
697  m_PadShape->SetSelection( CHOICE_SHAPE_CIRCLE );
698  break;
699 
700  case PAD_SHAPE_OVAL:
701  m_PadShape->SetSelection( CHOICE_SHAPE_OVAL );
702  break;
703 
704  case PAD_SHAPE_RECT:
705  m_PadShape->SetSelection( CHOICE_SHAPE_RECT );
706  break;
707 
708  case PAD_SHAPE_TRAPEZOID:
709  m_PadShape->SetSelection( CHOICE_SHAPE_TRAPEZOID );
710  break;
711 
712  case PAD_SHAPE_ROUNDRECT:
713  m_PadShape->SetSelection( CHOICE_SHAPE_ROUNDRECT );
714  break;
715 
716  case PAD_SHAPE_CUSTOM:
719  else
721  break;
722  }
723 
725 
726  m_OrientValue = angle / 10.0;
727 
728  // Type of pad selection
729  m_PadType->SetSelection( 0 );
730 
731  for( unsigned ii = 0; ii < DIM( code_type ); ii++ )
732  {
733  if( code_type[ii] == m_dummyPad->GetAttribute() )
734  {
735  m_PadType->SetSelection( ii );
736  break;
737  }
738  }
739 
740  // Enable/disable Pad name,and pad length die
741  // (disable for NPTH pads (mechanical pads)
743 
744  m_PadNumCtrl->Enable( enable );
745  m_PadNetNameCtrl->Enable( m_canEditNetName && enable && m_currentPad != NULL );
746  m_LengthPadToDieCtrl->Enable( enable );
747 
749  m_DrillShapeCtrl->SetSelection( 0 );
750  else
751  m_DrillShapeCtrl->SetSelection( 1 );
752 
753  // Update some dialog widgets state (Enable/disable options):
754  wxCommandEvent cmd_event;
756  OnDrillShapeSelected( cmd_event );
757  OnPadShapeSelection( cmd_event );
759 
760  // Update basic shapes list
762 }
763 
764 // A small helper function, to display coordinates:
765 static wxString formatCoord( wxPoint aCoord )
766 {
767  return wxString::Format( "(X:%s Y:%s)",
768  CoordinateToString( aCoord.x, true ),
769  CoordinateToString( aCoord.y, true ) );
770 }
771 
773 {
774  m_listCtrlPrimitives->ClearAll();
775 
776  wxListItem itemCol;
777  itemCol.SetImage(-1);
778 
779  for( int ii = 0; ii < 5; ++ii )
780  m_listCtrlPrimitives->InsertColumn(ii, itemCol);
781 
782  wxString bs_info[5];
783 
784  for( unsigned ii = 0; ii < m_primitives.size(); ++ii )
785  {
786  const PAD_CS_PRIMITIVE& primitive = m_primitives[ii];
787 
788  for( unsigned jj = 0; jj < 5; ++jj )
789  bs_info[jj].Empty();
790 
791  bs_info[4] = wxString::Format( _( "width %s" ),
792  CoordinateToString( primitive.m_Thickness, true ) );
793 
794  switch( primitive.m_Shape )
795  {
796  case S_SEGMENT: // usual segment : line with rounded ends
797  bs_info[0] = _( "Segment" );
798  bs_info[1] = _( "from " ) + formatCoord( primitive.m_Start );
799  bs_info[2] = _( "to " ) + formatCoord( primitive.m_End );
800  break;
801 
802  case S_ARC: // Arc with rounded ends
803  bs_info[0] = _( "Arc" );
804  bs_info[1] = _( "center " ) + formatCoord( primitive.m_Start ); // Center
805  bs_info[2] = _( "start " ) + formatCoord( primitive.m_End ); // Start point
806  bs_info[3] = wxString::Format( _( "angle %s" ), FMT_ANGLE( primitive.m_ArcAngle ) );
807  break;
808 
809  case S_CIRCLE: // ring or circle
810  if( primitive.m_Thickness )
811  bs_info[0] = _( "ring" );
812  else
813  bs_info[0] = _( "circle" );
814 
815  bs_info[1] = formatCoord( primitive.m_Start );
816  bs_info[2] = wxString::Format( _( "radius %s" ),
817  CoordinateToString( primitive.m_Radius, true ) );
818  break;
819 
820  case S_POLYGON: // polygon
821  bs_info[0] = "Polygon";
822  bs_info[1] = wxString::Format( _( "corners count %d" ), (int) primitive.m_Poly.size() );
823  break;
824 
825  default:
826  bs_info[0] = "Unknown primitive";
827  break;
828  }
829 
830  long tmp = m_listCtrlPrimitives->InsertItem(ii, bs_info[0]);
831  m_listCtrlPrimitives->SetItemData(tmp, ii);
832 
833  for( int jj = 0, col = 0; jj < 5; ++jj )
834  {
835  m_listCtrlPrimitives->SetItem(tmp, col++, bs_info[jj]);
836  }
837  }
838 
839  // Now columns are filled, ensure correct width of columns
840  for( unsigned ii = 0; ii < 5; ++ii )
841  m_listCtrlPrimitives->SetColumnWidth( ii, wxLIST_AUTOSIZE );
842 }
843 
844 void DIALOG_PAD_PROPERTIES::OnResize( wxSizeEvent& event )
845 {
846  redraw();
847  event.Skip();
848 }
849 
850 
851 void DIALOG_PAD_PROPERTIES::onChangePadMode( wxCommandEvent& event )
852 {
854 
855  if( m_parent->IsGalCanvasActive() )
856  {
858 
859  // fix the pad render mode (filled/not filled)
860  KIGFX::PCB_RENDER_SETTINGS* settings =
861  static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
862 
867  }
868 
869  redraw();
870 }
871 
872 
873 void DIALOG_PAD_PROPERTIES::OnPadShapeSelection( wxCommandEvent& event )
874 {
875  bool is_custom = false;
876 
877  switch( m_PadShape->GetSelection() )
878  {
879  case CHOICE_SHAPE_CIRCLE:
880  m_ShapeDelta_Ctrl->Enable( false );
881  m_trapDeltaDirChoice->Enable( false );
882  m_ShapeSize_Y_Ctrl->Enable( false );
883  m_ShapeOffset_X_Ctrl->Enable( false );
884  m_ShapeOffset_Y_Ctrl->Enable( false );
885  break;
886 
887  case CHOICE_SHAPE_OVAL:
888  m_ShapeDelta_Ctrl->Enable( false );
889  m_trapDeltaDirChoice->Enable( false );
890  m_ShapeSize_Y_Ctrl->Enable( true );
891  m_ShapeOffset_X_Ctrl->Enable( true );
892  m_ShapeOffset_Y_Ctrl->Enable( true );
893  break;
894 
895  case CHOICE_SHAPE_RECT:
896  m_ShapeDelta_Ctrl->Enable( false );
897  m_trapDeltaDirChoice->Enable( false );
898  m_ShapeSize_Y_Ctrl->Enable( true );
899  m_ShapeOffset_X_Ctrl->Enable( true );
900  m_ShapeOffset_Y_Ctrl->Enable( true );
901  break;
902 
904  m_ShapeDelta_Ctrl->Enable( true );
905  m_trapDeltaDirChoice->Enable( true );
906  m_ShapeSize_Y_Ctrl->Enable( true );
907  m_ShapeOffset_X_Ctrl->Enable( true );
908  m_ShapeOffset_Y_Ctrl->Enable( true );
909  break;
910 
912  m_ShapeDelta_Ctrl->Enable( false );
913  m_trapDeltaDirChoice->Enable( false );
914  m_ShapeSize_Y_Ctrl->Enable( true );
915  m_ShapeOffset_X_Ctrl->Enable( true );
916  m_ShapeOffset_Y_Ctrl->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_ShapeDelta_Ctrl->Enable( false );
926  m_trapDeltaDirChoice->Enable( false );
927  m_ShapeSize_Y_Ctrl->Enable(
928  m_PadShape->GetSelection() == CHOICE_SHAPE_CUSTOM_RECT_ANCHOR );
929  m_ShapeOffset_X_Ctrl->Enable( false );
930  m_ShapeOffset_Y_Ctrl->Enable( false );
931  break;
932  }
933 
934  enablePrimitivePage( is_custom );
935 
936  // A few widgets are enabled only for rounded rect pads:
937  m_tcCornerSizeRatio->Enable( m_PadShape->GetSelection() == CHOICE_SHAPE_ROUNDRECT );
938 
939  // PAD_SHAPE_CUSTOM type has constraints for zone connection and thermal shape:
940  // only not connected or solid connection is allowed to avoid destroying the shape.
941  // Enable/disable options only available for custom shaped pads
942  m_ZoneConnectionChoice->Enable( !is_custom );
943  m_ZoneConnectionCustom->Enable( is_custom );
944  m_ThermalWidthCtrl->Enable( !is_custom );
945  m_ThermalGapCtrl->Enable( !is_custom );
946 
947  m_sbSizerZonesSettings->Show( !is_custom );
948  m_sbSizerCustomShapedZonesSettings->Show( is_custom );
949 
951 
953  redraw();
954 }
955 
956 
957 void DIALOG_PAD_PROPERTIES::OnDrillShapeSelected( wxCommandEvent& event )
958 {
959  if( m_PadType->GetSelection() == 1 || m_PadType->GetSelection() == 2 )
960  {
961  // pad type = SMD or CONN: no hole allowed
962  m_PadDrill_X_Ctrl->Enable( false );
963  m_PadDrill_Y_Ctrl->Enable( false );
964  }
965  else
966  {
967  switch( m_DrillShapeCtrl->GetSelection() )
968  {
969  case 0: //CIRCLE:
970  m_PadDrill_X_Ctrl->Enable( true );
971  m_PadDrill_Y_Ctrl->Enable( false );
972  break;
973 
974  case 1: //OVALE:
975  m_PadDrill_X_Ctrl->Enable( true );
976  m_PadDrill_Y_Ctrl->Enable( true );
977  break;
978  }
979  }
980 
982  redraw();
983 }
984 
985 
986 void DIALOG_PAD_PROPERTIES::PadOrientEvent( wxCommandEvent& event )
987 {
988  switch( m_PadOrient->GetSelection() )
989  {
990  case 0:
992  break;
993 
994  case 1:
995  m_dummyPad->SetOrientation( 900 );
996  break;
997 
998  case 2:
999  m_dummyPad->SetOrientation( -900 );
1000  break;
1001 
1002  case 3:
1003  m_dummyPad->SetOrientation( 1800 );
1004  break;
1005 
1006  default:
1007  break;
1008  }
1009 
1011  m_OrientValidator.TransferToWindow();
1012 
1014  redraw();
1015 }
1016 
1017 
1018 void DIALOG_PAD_PROPERTIES::PadTypeSelected( wxCommandEvent& event )
1019 {
1020  unsigned ii = m_PadType->GetSelection();
1021 
1022  if( ii >= DIM( code_type ) ) // catches < 0 also
1023  ii = 0;
1024 
1025  LSET layer_mask = std_pad_layers[ii];
1026  setPadLayersList( layer_mask );
1027 
1028  // Enable/disable drill dialog items:
1029  event.SetId( m_DrillShapeCtrl->GetSelection() );
1030  OnDrillShapeSelected( event );
1031 
1032  if( ii == 0 || ii == DIM( code_type )-1 )
1033  m_DrillShapeCtrl->Enable( true );
1034  else
1035  m_DrillShapeCtrl->Enable( false );
1036 
1037  // Enable/disable Pad name,and pad length die
1038  // (disable for NPTH pads (mechanical pads)
1039  bool enable = ii != 3;
1040  m_PadNumCtrl->Enable( enable );
1041  m_PadNetNameCtrl->Enable( m_canEditNetName && enable && m_currentPad != NULL );
1042  m_LengthPadToDieCtrl->Enable( enable );
1043 }
1044 
1045 
1047 {
1048  LSET cu_set = layer_mask & LSET::AllCuMask();
1049 
1050  if( cu_set == LSET( F_Cu ) )
1051  m_rbCopperLayersSel->SetSelection( 0 );
1052  else if( cu_set == LSET( B_Cu ) )
1053  m_rbCopperLayersSel->SetSelection( 1 );
1054  else if( cu_set.any() )
1055  m_rbCopperLayersSel->SetSelection( 2 );
1056  else
1057  m_rbCopperLayersSel->SetSelection( 3 );
1058 
1059  m_PadLayerAdhCmp->SetValue( layer_mask[F_Adhes] );
1060  m_PadLayerAdhCu->SetValue( layer_mask[B_Adhes] );
1061 
1062  m_PadLayerPateCmp->SetValue( layer_mask[F_Paste] );
1063  m_PadLayerPateCu->SetValue( layer_mask[B_Paste] );
1064 
1065  m_PadLayerSilkCmp->SetValue( layer_mask[F_SilkS] );
1066  m_PadLayerSilkCu->SetValue( layer_mask[B_SilkS] );
1067 
1068  m_PadLayerMaskCmp->SetValue( layer_mask[F_Mask] );
1069  m_PadLayerMaskCu->SetValue( layer_mask[B_Mask] );
1070 
1071  m_PadLayerECO1->SetValue( layer_mask[Eco1_User] );
1072  m_PadLayerECO2->SetValue( layer_mask[Eco2_User] );
1073 
1074  m_PadLayerDraft->SetValue( layer_mask[Dwgs_User] );
1075 }
1076 
1077 
1078 // Called when select/deselect a layer.
1079 void DIALOG_PAD_PROPERTIES::OnSetLayers( wxCommandEvent& event )
1080 {
1082  redraw();
1083 }
1084 
1085 
1086 // test if all values are acceptable for the pad
1088 {
1089  bool error = transferDataToPad( m_dummyPad );
1090  bool skip_tstoffset = false; // the offset prm is not always tested
1091 
1092  wxArrayString error_msgs;
1093  wxString msg;
1094 
1095  // Test for incorrect values
1096  if( (m_dummyPad->GetSize().x <= 0) ||
1097  ((m_dummyPad->GetSize().y <= 0) && (m_dummyPad->GetShape() != PAD_SHAPE_CIRCLE)) )
1098  {
1099  error_msgs.Add( _( "Pad size must be greater than zero" ) );
1100  }
1101 
1102  if( (m_dummyPad->GetSize().x < m_dummyPad->GetDrillSize().x) ||
1103  (m_dummyPad->GetSize().y < m_dummyPad->GetDrillSize().y) )
1104  {
1105  error_msgs.Add( _( "Incorrect value for pad drill: pad drill bigger than pad size" ) );
1106  skip_tstoffset = true; // offset prm will be not tested because if the drill value
1107  // is incorrect the offset prm is always seen as incorrect, even if it is 0
1108  }
1109 
1110  if( m_dummyPad->GetLocalClearance() < 0 )
1111  {
1112  error_msgs.Add( _( "Pad local clearance must be zero or greater than zero" ) );
1113  }
1114 
1115  // Some pads need a negative solder mask clearance (mainly for BGA with small pads)
1116  // However the negative solder mask clearance must not create negative mask size
1117  // Therefore test for minimal acceptable negative value
1118  // Hovewer, a negative value can give strange result with custom shapes, so it is not
1119  // allowed for custom pad shape
1121  {
1123  error_msgs.Add( _( "Pad local solder mask clearance must be zero or greater than zero" ) );
1124  else
1125  {
1126  int min_smClearance = -std::min( m_dummyPad->GetSize().x, m_dummyPad->GetSize().y )/2;
1127 
1128  if( m_dummyPad->GetLocalSolderMaskMargin() <= min_smClearance )
1129  {
1130  error_msgs.Add( wxString::Format(
1131  _( "Pad local solder mask clearance must be greater than %s" ),
1132  StringFromValue( g_UserUnit, min_smClearance, true ) ) );
1133  }
1134  }
1135  }
1136 
1137  // Some pads need a positive solder paste clearance (mainly for BGA with small pads)
1138  // Hovewer, a positive value can create issues if the resulting shape is too big.
1139  // (like a solder paste creating a solder paste area on a neighbour pad or on the solder mask)
1140  // So we could ask for user to confirm the choice
1141  // Currently there are no test
1142 
1143  LSET padlayers_mask = m_dummyPad->GetLayerSet();
1144 
1145  if( padlayers_mask == 0 )
1146  error_msgs.Add( _( "Error: pad has no layer" ) );
1147 
1148  if( !padlayers_mask[F_Cu] && !padlayers_mask[B_Cu] )
1149  {
1150  if( m_dummyPad->GetDrillSize().x || m_dummyPad->GetDrillSize().y )
1151  {
1152  // Note: he message is shown in an HTML window
1153  msg = _( "Error: the pad is not on a copper layer and has a hole" );
1154 
1156  {
1157  msg += wxT( "<br><br><i>" );
1158  msg += _( "For NPTH pad, set pad size value to pad drill value,"
1159  " if you do not want this pad plotted in gerber files"
1160  );
1161  }
1162 
1163  error_msgs.Add( msg );
1164  }
1165  }
1166 
1167  if( !skip_tstoffset )
1168  {
1169  wxPoint max_size;
1170  max_size.x = std::abs( m_dummyPad->GetOffset().x );
1171  max_size.y = std::abs( m_dummyPad->GetOffset().y );
1172  max_size.x += m_dummyPad->GetDrillSize().x / 2;
1173  max_size.y += m_dummyPad->GetDrillSize().y / 2;
1174 
1175  if( ( m_dummyPad->GetSize().x / 2 < max_size.x ) ||
1176  ( m_dummyPad->GetSize().y / 2 < max_size.y ) )
1177  {
1178  error_msgs.Add( _( "Incorrect value for pad offset" ) );
1179  }
1180  }
1181 
1182  if( error )
1183  {
1184  error_msgs.Add( _( "Too large value for pad delta size" ) );
1185  }
1186 
1187  switch( m_dummyPad->GetAttribute() )
1188  {
1189  case PAD_ATTRIB_HOLE_NOT_PLATED: // Not plated, but through hole, a hole is expected
1190  case PAD_ATTRIB_STANDARD : // Pad through hole, a hole is also expected
1191  if( m_dummyPad->GetDrillSize().x <= 0 )
1192  error_msgs.Add( _( "Error: Through hole pad: drill diameter set to 0" ) );
1193  break;
1194 
1195  case PAD_ATTRIB_CONN: // Connector pads are smd pads, just they do not have solder paste.
1196  if( padlayers_mask[B_Paste] || padlayers_mask[F_Paste] )
1197  error_msgs.Add( _( "Error: Connector pads are not on the solder paste layer\n"
1198  "Use SMD pads instead" ) );
1199  // Fall trough
1200  case PAD_ATTRIB_SMD: // SMD and Connector pads (One external copper layer only)
1201  {
1202  LSET innerlayers_mask = padlayers_mask & LSET::InternalCuMask();
1203 
1204  if( ( padlayers_mask[F_Cu] && padlayers_mask[B_Cu] ) ||
1205  innerlayers_mask.count() != 0 )
1206  error_msgs.Add( _( "Error: only one external copper layer allowed for SMD or Connector pads" ) );
1207  }
1208  break;
1209  }
1210 
1211 
1213  {
1214  wxString value = m_tcCornerSizeRatio->GetValue();
1215  double rrRadiusRatioPercent;
1216 
1217  if( !value.ToDouble( &rrRadiusRatioPercent ) )
1218  error_msgs.Add( _( "Incorrect corner size value" ) );
1219  else
1220  {
1221  if( rrRadiusRatioPercent < 0.0 )
1222  error_msgs.Add( _( "Incorrect (negative) corner size value" ) );
1223  else if( rrRadiusRatioPercent > 50.0 )
1224  error_msgs.Add( _( "Corner size value must be smaller than 50%" ) );
1225  }
1226  }
1227 
1229  {
1231  error_msgs.Add(
1232  _( "Incorrect pad shape: the shape must be equivalent to only one polygon" ) );
1233  }
1234 
1235 
1236  if( error_msgs.GetCount() )
1237  {
1238  HTML_MESSAGE_BOX dlg( this, _("Pad setup errors list" ) );
1239  dlg.ListSet( error_msgs );
1240  dlg.ShowModal();
1241  }
1242 
1243  return error_msgs.GetCount() == 0;
1244 }
1245 
1246 
1248 {
1249  if( m_parent->IsGalCanvasActive() )
1250  {
1253 
1254  // The layer used to place primitive items selected when editing custom pad shapes
1255  // we use here a layer never used in a pad:
1256  #define SELECTED_ITEMS_LAYER Dwgs_User
1257 
1259  KIGFX::PCB_RENDER_SETTINGS* settings =
1260  static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
1262 
1263  view->Update( m_dummyPad );
1264 
1265  // delete previous items if highlight list
1266  while( m_highligth.size() )
1267  {
1268  delete m_highligth.back(); // the dtor also removes item from view
1269  m_highligth.pop_back();
1270  }
1271 
1272  // highlight selected primitives:
1273  long select = m_listCtrlPrimitives->GetFirstSelected();
1274 
1275  while( select >= 0 )
1276  {
1277  PAD_CS_PRIMITIVE& primitive = m_primitives[select];
1278 
1279  DRAWSEGMENT* dummySegment = new DRAWSEGMENT;
1280  dummySegment->SetLayer( SELECTED_ITEMS_LAYER );
1281  primitive.ExportTo( dummySegment );
1282  dummySegment->Rotate( wxPoint( 0, 0), m_dummyPad->GetOrientation() );
1283  dummySegment->Move( m_dummyPad->GetPosition() );
1284 
1285  // Update selected primitive (highligth selected)
1286  switch( primitive.m_Shape )
1287  {
1288  case S_SEGMENT:
1289  case S_ARC:
1290  break;
1291 
1292  case S_CIRCLE: // ring or circle
1293  if( primitive.m_Thickness == 0 ) // filled circle
1294  { // the filled circle option does not exist in a DRAWSEGMENT
1295  // but it is easy to create it with a circle having the
1296  // right radius and outline width
1297  wxPoint end = dummySegment->GetCenter();
1298  end.x += primitive.m_Radius/2;
1299  dummySegment->SetEnd( end );
1300  dummySegment->SetWidth( primitive.m_Radius );
1301  }
1302  break;
1303 
1304  case S_POLYGON:
1305  break;
1306 
1307  default:
1308  delete dummySegment;
1309  dummySegment = nullptr;
1310  break;
1311  }
1312 
1313  if( dummySegment )
1314  {
1315  view->Add( dummySegment );
1316  m_highligth.push_back( dummySegment );
1317  }
1318 
1319  select = m_listCtrlPrimitives->GetNextSelected( select );
1320  }
1321 
1322  BOX2I bbox = m_dummyPad->ViewBBox();
1323 
1324  if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
1325  {
1326  // gives a size to the full drawable area
1327  BOX2I drawbox;
1328  drawbox.Move( m_dummyPad->GetPosition() );
1329  drawbox.Inflate( bbox.GetSize().x*2, bbox.GetSize().y*2 );
1330  view->SetBoundary( drawbox );
1331 
1332  // Autozoom
1333  view->SetViewport( BOX2D( bbox.GetOrigin(), bbox.GetSize() ) );
1334 
1335  // Add a margin
1336  view->SetScale( m_panelShowPadGal->GetView()->GetScale() * 0.7 );
1337 
1340  }
1341  }
1342  else
1343  {
1344  m_panelShowPad->Refresh();
1345  }
1346 }
1347 
1348 
1350 {
1351  if( !wxDialog::TransferDataToWindow() )
1352  return false;
1353 
1354  if( !m_panelGeneral->TransferDataToWindow() )
1355  return false;
1356 
1357  if( !m_localSettingsPanel->TransferDataToWindow() )
1358  return false;
1359 
1360  return true;
1361 }
1362 
1363 
1365 {
1366  BOARD_COMMIT commit( m_parent );
1367 
1368  if( !wxDialog::TransferDataFromWindow() )
1369  return false;
1370 
1371  if( !m_panelGeneral->TransferDataFromWindow() )
1372  return false;
1373 
1374  if( !m_localSettingsPanel->TransferDataFromWindow() )
1375  return false;
1376 
1377  if( !padValuesOK() )
1378  return false;
1379 
1380  bool rastnestIsChanged = false;
1381  int isign = m_isFlipped ? -1 : 1;
1382 
1384  // m_padMaster is a pattern: ensure there is no net for this pad:
1386 
1387  if( !m_currentPad ) // Set current Pad parameters
1388  return true;
1389 
1390  commit.Modify( m_currentPad );
1391 
1392  // redraw the area where the pad was, without pad (delete pad on screen)
1396 
1397  // Update values
1400 
1402  {
1404  rastnestIsChanged = true;
1405  }
1406 
1407  wxSize size;
1408  MODULE* footprint = m_currentPad->GetParent();
1409 
1410  if( footprint )
1411  {
1412  footprint->SetLastEditTime();
1413 
1414  // compute the pos 0 value, i.e. pad position for footprint with orientation = 0
1415  // i.e. relative to footprint origin (footprint position)
1416  wxPoint pt = m_currentPad->GetPosition() - footprint->GetPosition();
1417  RotatePoint( &pt, -footprint->GetOrientation() );
1418  m_currentPad->SetPos0( pt );
1420  + footprint->GetOrientation() );
1421  }
1422 
1424 
1425  size = m_padMaster->GetDelta();
1426  size.y *= isign;
1427  m_currentPad->SetDelta( size );
1428 
1431 
1432  wxPoint offset = m_padMaster->GetOffset();
1433  offset.y *= isign;
1434  m_currentPad->SetOffset( offset );
1435 
1437 
1440 
1441 
1444 
1445  if( m_isFlipped )
1446  {
1449  }
1450 
1452  {
1453  rastnestIsChanged = true;
1455  }
1456 
1457  if( m_isFlipped )
1458  {
1460  }
1461 
1463 
1464  wxString padNetname;
1465 
1466  // For PAD_ATTRIB_HOLE_NOT_PLATED, ensure there is no net name selected
1468  padNetname = m_PadNetNameCtrl->GetValue();
1469 
1470  if( m_currentPad->GetNetname() != padNetname )
1471  {
1472  const NETINFO_ITEM* netinfo = m_board->FindNet( padNetname );
1473 
1474  if( !padNetname.IsEmpty() && netinfo == NULL )
1475  {
1476  DisplayError( NULL, _( "Unknown netname, netname not changed" ) );
1477  }
1478  else if( netinfo )
1479  {
1480  rastnestIsChanged = true;
1481  m_currentPad->SetNetCode( netinfo->GetNet() );
1482  }
1483  }
1484 
1492 
1494  {
1497  else
1499  }
1500  else
1502 
1503 
1504  // rounded rect pads with radius ratio = 0 are in fact rect pads.
1505  // So set the right shape (and perhaps issues with a radius = 0)
1508  {
1510  }
1511 
1512  // define the way the clearance area is defined in zones
1514 
1515  if( footprint )
1516  footprint->CalculateBoundingBox();
1517 
1519 
1520  // redraw the area where the pad was
1522 
1523  commit.Push( _( "Modify pad" ) );
1524 
1525  if( rastnestIsChanged ) // The net ratsnest must be recalculated
1526  m_board->m_Status_Pcb = 0;
1527 
1528  return true;
1529 }
1530 
1531 
1533 {
1534  wxString msg;
1535  int x, y;
1536 
1537  if( !Validate() )
1538  return true;
1539  if( !m_panelGeneral->Validate() )
1540  return true;
1541  if( !m_localSettingsPanel->Validate() )
1542  return true;
1543 
1544  m_OrientValidator.TransferFromWindow();
1545 
1546  aPad->SetAttribute( code_type[m_PadType->GetSelection()] );
1547  aPad->SetShape( code_shape[m_PadShape->GetSelection()] );
1550 
1551  if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
1552  aPad->SetPrimitives( m_primitives );
1553 
1554  // Read pad clearances values:
1560  double dtmp = 0.0;
1561  msg = m_SolderPasteMarginRatioCtrl->GetValue();
1562  msg.ToDouble( &dtmp );
1563 
1564  // A -50% margin ratio means no paste on a pad, the ratio must be >= -50%
1565  if( dtmp < -50.0 )
1566  dtmp = -50.0;
1567  // A margin ratio is always <= 0
1568  // 0 means use full pad copper area
1569  if( dtmp > 0.0 )
1570  dtmp = 0.0;
1571 
1572  aPad->SetLocalSolderPasteMarginRatio( dtmp / 100 );
1573 
1574  switch( m_ZoneConnectionChoice->GetSelection() )
1575  {
1576  default:
1577  case 0:
1579  break;
1580 
1581  case 1:
1583  break;
1584 
1585  case 2:
1587  break;
1588 
1589  case 3:
1591  break;
1592  }
1593 
1594  // Custom shape has only 2 options:
1595  if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
1596  {
1597  if( m_ZoneConnectionCustom->GetSelection() == 0 )
1599  else
1601  }
1602 
1603  // Read pad position:
1606 
1607  aPad->SetPosition( wxPoint( x, y ) );
1608  aPad->SetPos0( wxPoint( x, y ) );
1609 
1610  // Read pad drill:
1613 
1614  if( m_DrillShapeCtrl->GetSelection() == 0 )
1615  {
1617  y = x;
1618  }
1619  else
1621 
1622  aPad->SetDrillSize( wxSize( x, y ) );
1623 
1624  // Read pad shape size:
1627 
1628  if( aPad->GetShape() == PAD_SHAPE_CIRCLE )
1629  y = x;
1630 
1631  // for custom shped pads, the pad size is the anchor pad size:
1632  if( aPad->GetShape() == PAD_SHAPE_CUSTOM && aPad->GetAnchorPadShape() == PAD_SHAPE_CIRCLE )
1633  y = x;
1634 
1635  aPad->SetSize( wxSize( x, y ) );
1636 
1637  // Read pad length die
1639 
1640  // For a trapezoid, test delta value (be sure delta is not too large for pad size)
1641  // remember DeltaSize.x is the Y size variation
1642  bool error = false;
1643 
1644  if( aPad->GetShape() == PAD_SHAPE_TRAPEZOID )
1645  {
1646  wxSize delta;
1647 
1648  // For a trapezoid, only one of delta.x or delta.y is not 0, depending on
1649  // the direction.
1650  if( m_trapDeltaDirChoice->GetSelection() == 0 )
1651  delta.x = ValueFromTextCtrl( *m_ShapeDelta_Ctrl );
1652  else
1653  delta.y = ValueFromTextCtrl( *m_ShapeDelta_Ctrl );
1654 
1655  if( delta.x < 0 && delta.x <= -aPad->GetSize().y )
1656  {
1657  delta.x = -aPad->GetSize().y + 2;
1658  error = true;
1659  }
1660 
1661  if( delta.x > 0 && delta.x >= aPad->GetSize().y )
1662  {
1663  delta.x = aPad->GetSize().y - 2;
1664  error = true;
1665  }
1666 
1667  if( delta.y < 0 && delta.y <= -aPad->GetSize().x )
1668  {
1669  delta.y = -aPad->GetSize().x + 2;
1670  error = true;
1671  }
1672 
1673  if( delta.y > 0 && delta.y >= aPad->GetSize().x )
1674  {
1675  delta.y = aPad->GetSize().x - 2;
1676  error = true;
1677  }
1678 
1679  aPad->SetDelta( delta );
1680  }
1681 
1682  // Read pad shape offset:
1685  aPad->SetOffset( wxPoint( x, y ) );
1686 
1687  aPad->SetOrientation( m_OrientValue * 10.0 );
1688  aPad->SetName( m_PadNumCtrl->GetValue() );
1689 
1690  // Check if user has set an existing net name
1691  const NETINFO_ITEM* netinfo = m_board->FindNet( m_PadNetNameCtrl->GetValue() );
1692 
1693  if( netinfo != NULL )
1694  aPad->SetNetCode( netinfo->GetNet() );
1695  else
1697 
1698  // Clear some values, according to the pad type and shape
1699  switch( aPad->GetShape() )
1700  {
1701  case PAD_SHAPE_CIRCLE:
1702  aPad->SetOffset( wxPoint( 0, 0 ) );
1703  aPad->SetDelta( wxSize( 0, 0 ) );
1704  x = aPad->GetSize().x;
1705  aPad->SetSize( wxSize( x, x ) );
1706  break;
1707 
1708  case PAD_SHAPE_RECT:
1709  aPad->SetDelta( wxSize( 0, 0 ) );
1710  break;
1711 
1712  case PAD_SHAPE_OVAL:
1713  aPad->SetDelta( wxSize( 0, 0 ) );
1714  break;
1715 
1716  case PAD_SHAPE_TRAPEZOID:
1717  break;
1718 
1719  case PAD_SHAPE_ROUNDRECT:
1720  aPad->SetDelta( wxSize( 0, 0 ) );
1721  break;
1722 
1723  case PAD_SHAPE_CUSTOM:
1724  aPad->SetOffset( wxPoint( 0, 0 ) );
1725  aPad->SetDelta( wxSize( 0, 0 ) );
1726 
1727  // The pad custom has a "anchor pad" (a basic shape: round or rect pad)
1728  // that is the minimal area of this pad, and is usefull to ensure a hole
1729  // diameter is acceptable, and is used in Gerber files as flashed area
1730  // reference
1731  if( aPad->GetAnchorPadShape() == PAD_SHAPE_CIRCLE )
1732  {
1733  x = aPad->GetSize().x;
1734  aPad->SetSize( wxSize( x, x ) );
1735  }
1736 
1737  // define the way the clearance area is defined in zones
1738  aPad->SetCustomShapeInZoneOpt( m_ZoneCustomPadShape->GetSelection() == 0 ?
1741 
1742  break;
1743 
1744  default:
1745  ;
1746  }
1747 
1748  switch( aPad->GetAttribute() )
1749  {
1750  case PAD_ATTRIB_STANDARD:
1751  break;
1752 
1753  case PAD_ATTRIB_CONN:
1754  case PAD_ATTRIB_SMD:
1755  // SMD and PAD_ATTRIB_CONN has no hole.
1756  // basically, SMD and PAD_ATTRIB_CONN are same type of pads
1757  // PAD_ATTRIB_CONN has just a default non technical layers that differs from SMD
1758  // and are intended to be used in virtual edge board connectors
1759  // However we can accept a non null offset,
1760  // mainly to allow complex pads build from a set of basic pad shapes
1761  aPad->SetDrillSize( wxSize( 0, 0 ) );
1762  break;
1763 
1765  // Mechanical purpose only:
1766  // no offset, no net name, no pad name allowed
1767  aPad->SetOffset( wxPoint( 0, 0 ) );
1768  aPad->SetName( wxEmptyString );
1770  break;
1771 
1772  default:
1773  DisplayError( NULL, wxT( "Error: unknown pad type" ) );
1774  break;
1775  }
1776 
1777  if( aPad->GetShape() == PAD_SHAPE_ROUNDRECT )
1778  {
1779  wxString value = m_tcCornerSizeRatio->GetValue();
1780  double rrRadiusRatioPercent;
1781 
1782  if( value.ToDouble( &rrRadiusRatioPercent ) )
1783  aPad->SetRoundRectRadiusRatio( rrRadiusRatioPercent / 100.0 );
1784  }
1785 
1786  LSET padLayerMask;
1787 
1788  switch( m_rbCopperLayersSel->GetSelection() )
1789  {
1790  case 0:
1791  padLayerMask.set( F_Cu );
1792  break;
1793 
1794  case 1:
1795  padLayerMask.set( B_Cu );
1796  break;
1797 
1798  case 2:
1799  padLayerMask |= LSET::AllCuMask();
1800  break;
1801 
1802  case 3: // No copper layers
1803  break;
1804  }
1805 
1806  if( m_PadLayerAdhCmp->GetValue() )
1807  padLayerMask.set( F_Adhes );
1808 
1809  if( m_PadLayerAdhCu->GetValue() )
1810  padLayerMask.set( B_Adhes );
1811 
1812  if( m_PadLayerPateCmp->GetValue() )
1813  padLayerMask.set( F_Paste );
1814 
1815  if( m_PadLayerPateCu->GetValue() )
1816  padLayerMask.set( B_Paste );
1817 
1818  if( m_PadLayerSilkCmp->GetValue() )
1819  padLayerMask.set( F_SilkS );
1820 
1821  if( m_PadLayerSilkCu->GetValue() )
1822  padLayerMask.set( B_SilkS );
1823 
1824  if( m_PadLayerMaskCmp->GetValue() )
1825  padLayerMask.set( F_Mask );
1826 
1827  if( m_PadLayerMaskCu->GetValue() )
1828  padLayerMask.set( B_Mask );
1829 
1830  if( m_PadLayerECO1->GetValue() )
1831  padLayerMask.set( Eco1_User );
1832 
1833  if( m_PadLayerECO2->GetValue() )
1834  padLayerMask.set( Eco2_User );
1835 
1836  if( m_PadLayerDraft->GetValue() )
1837  padLayerMask.set( Dwgs_User );
1838 
1839  aPad->SetLayerSet( padLayerMask );
1840 
1841  return error;
1842 }
1843 
1844 
1845 void DIALOG_PAD_PROPERTIES::OnValuesChanged( wxCommandEvent& event )
1846 {
1847  if( m_canUpdate )
1848  {
1850  // If the pad size has changed, update the displayed values
1851  // for rounded rect pads
1853 
1854  redraw();
1855  }
1856 }
1857 
1859 {
1860  long select = m_listCtrlPrimitives->GetFirstSelected();
1861 
1862  if( select < 0 )
1863  {
1864  wxMessageBox( _( "No shape selected" ) );
1865  return;
1866  }
1867 
1868  PAD_CS_PRIMITIVE& shape = m_primitives[select];
1869 
1870  if( shape.m_Shape == S_POLYGON )
1871  {
1872  DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, &shape );
1873 
1874  if( dlg.ShowModal() != wxID_OK )
1875  return;
1876 
1877  dlg.TransferDataFromWindow();
1878  }
1879 
1880  else
1881  {
1882  DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, &shape );
1883 
1884  if( dlg.ShowModal() != wxID_OK )
1885  return;
1886 
1887  dlg.TransferDataFromWindow();
1888  }
1889 
1891 
1892  if( m_canUpdate )
1893  {
1895  redraw();
1896  }
1897 }
1898 
1899 
1901 {
1902  // Called on a double click on the basic shapes list
1903  // To Do: highligth the primitive(s) currently selected.
1904  redraw();
1905 }
1906 
1907 
1909 void DIALOG_PAD_PROPERTIES::onPrimitiveDClick( wxMouseEvent& event )
1910 {
1911  editPrimitive();
1912 }
1913 
1914 
1915 // Called on a click on basic shapes list panel button
1916 void DIALOG_PAD_PROPERTIES::onEditPrimitive( wxCommandEvent& event )
1917 {
1918  editPrimitive();
1919 }
1920 
1921 // Called on a click on basic shapes list panel button
1922 void DIALOG_PAD_PROPERTIES::onDeletePrimitive( wxCommandEvent& event )
1923 {
1924  long select = m_listCtrlPrimitives->GetFirstSelected();
1925 
1926  if( select < 0 )
1927  return;
1928 
1929  // Multiple selections are allowed. get them and remove corresponding shapes
1930  std::vector<long> indexes;
1931  indexes.push_back( select );
1932 
1933  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
1934  indexes.push_back( select );
1935 
1936  // Erase all select shapes
1937  for( unsigned ii = indexes.size(); ii > 0; --ii )
1938  m_primitives.erase( m_primitives.begin() + indexes[ii-1] );
1939 
1941 
1942  if( m_canUpdate )
1943  {
1945  redraw();
1946  }
1947 }
1948 
1949 
1950 void DIALOG_PAD_PROPERTIES::onAddPrimitive( wxCommandEvent& event )
1951 {
1952  // Ask user for shape type
1953  wxString shapelist[] =
1954  {
1955  _( "Segment" ), _( "Arc" ), _( "ring/circle" ), _( "polygon" )
1956  };
1957 
1958  int type = wxGetSingleChoiceIndex( wxEmptyString, _( "Select shape type:" ),
1959  DIM( shapelist ), shapelist, 0 );
1960 
1961  STROKE_T listtype[] =
1962  {
1964  };
1965 
1966  PAD_CS_PRIMITIVE primitive( listtype[type] );
1967 
1968  if( listtype[type] == S_POLYGON )
1969  {
1970  DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, &primitive );
1971 
1972  if( dlg.ShowModal() != wxID_OK )
1973  return;
1974  }
1975  else
1976  {
1977  DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, &primitive );
1978 
1979  if( dlg.ShowModal() != wxID_OK )
1980  return;
1981  }
1982 
1983  m_primitives.push_back( primitive );
1984 
1986 
1987  if( m_canUpdate )
1988  {
1990  redraw();
1991  }
1992 }
1993 
1994 
1995 void DIALOG_PAD_PROPERTIES::onImportPrimitives( wxCommandEvent& event )
1996 {
1997  wxMessageBox( "Not yet available" );
1998 }
1999 
2000 
2001 void DIALOG_PAD_PROPERTIES::onGeometryTransform( wxCommandEvent& event )
2002 {
2003  long select = m_listCtrlPrimitives->GetFirstSelected();
2004 
2005  if( select < 0 )
2006  {
2007  wxMessageBox( _( "No shape selected" ) );
2008  return;
2009  }
2010 
2011  // Multiple selections are allowed. Build selected shapes list
2012  std::vector<PAD_CS_PRIMITIVE*> shapeList;
2013  shapeList.push_back( &m_primitives[select] );
2014 
2015  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2016  shapeList.push_back( &m_primitives[select] );
2017 
2018  DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, shapeList, false );
2019 
2020  if( dlg.ShowModal() != wxID_OK )
2021  return;
2022 
2023  // Transfert new settings:
2024  dlg.Transform();
2025 
2027 
2028  if( m_canUpdate )
2029  {
2031  redraw();
2032  }
2033 }
2034 
2035 
2036 void DIALOG_PAD_PROPERTIES::onDuplicatePrimitive( wxCommandEvent& event )
2037 {
2038  long select = m_listCtrlPrimitives->GetFirstSelected();
2039 
2040  if( select < 0 )
2041  {
2042  wxMessageBox( _( "No shape selected" ) );
2043  return;
2044  }
2045 
2046  // Multiple selections are allowed. Build selected shapes list
2047  std::vector<PAD_CS_PRIMITIVE*> shapeList;
2048  shapeList.push_back( &m_primitives[select] );
2049 
2050  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2051  shapeList.push_back( &m_primitives[select] );
2052 
2053  DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, shapeList, true );
2054 
2055  if( dlg.ShowModal() != wxID_OK )
2056  return;
2057 
2058  // Transfer new settings
2059  // save duplicates to a separate vector to avoid m_primitives reallocation,
2060  // as shapeList contains pointers to its elements
2061  std::vector<PAD_CS_PRIMITIVE> duplicates;
2062  dlg.Transform( &duplicates, dlg.GetDuplicateCount() );
2063  std::move( duplicates.begin(), duplicates.end(), std::back_inserter( m_primitives ) );
2064 
2066 
2067  if( m_canUpdate )
2068  {
2070  redraw();
2071  }
2072 }
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:181
void Move(const Vec &aMoveVector)
Function Move moves the rectangle by the aMoveVector.
Definition: box2.h:108
wxString CoordinateToString(int aValue, bool aConvertToMils)
Function CoordinateToString is a helper to convert the integer coordinate aValue to a string in inche...
Definition: base_units.cpp:118
#define DIM(x)
of elements in an array
Definition: macros.h:98
void GRResetPenAndBrush(wxDC *DC)
Definition: gr_basic.cpp:218
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:536
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:434
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.
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:803
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.
EDA_DRAW_PANEL * GetCanvas()
Definition: draw_frame.h:351
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:408
bool transferDataToPad(D_PAD *aPad)
Copy values from dialog field to aPad&#39;s members.
Class BOARD to handle a board.
wxString StringFromValue(EDA_UNITS_T aUnit, int aValue, bool aAddUnitSymbol)
Function StringFromValue returns the string from aValue according to units (inch, mm ...
Definition: base_units.cpp:205
int GetRoundRectCornerRadius() const
Function GetRoundRectCornerRadius Has meaning only for rounded rect pads.
Definition: class_pad.h:518
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:410
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:469
wxFloatingPointValidator< double > m_OrientValidator
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:510
BOARD * GetBoard() const
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:219
void RefreshDrawingRect(const EDA_RECT &aRect, bool aEraseBackground=true)
Function RefreshDrawingRect redraws the contents of aRect in drawing units.
Definition: draw_panel.cpp:318
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:627
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:177
void GRFilledCircle(EDA_RECT *ClipBox, wxDC *DC, int x, int y, int r, int width, COLOR4D Color, COLOR4D BgColor)
Definition: gr_basic.cpp:873
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:247
smd pads, back layer
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:806
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
void SetBoundary(const BOX2I &aBoundary)
Function SetBoundary() Sets limits for view area.
Definition: view.h:275
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:57
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)
Function KiBitmap constructs a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:78
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
virtual const BOX2I ViewBBox() const override
Function ViewBBox() returns the bounding box of the item covering all its layers. ...
Definition: class_pad.cpp:1320
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:264
std::vector< wxPoint > m_Poly
is also the start point of the arc
Definition: class_pad.h:102
double GetOrientationDegrees() const
Definition: class_module.h:188
VECTOR2< double > VECTOR2D
Definition: vector2d.h:588
void OnSetLayers(wxCommandEvent &event) override
void SetZoneConnection(ZoneConnection aType)
Definition: class_pad.h:476
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Function SetMsgPanel clears the message panel and populates it with the contents of aList...
Definition: draw_frame.cpp:832
void OnPaintShowPanel(wxPaintEvent &event) override
GAL * GetGAL() const
Function GetGAL() Returns the GAL this view is using to draw graphical primitives.
Definition: view.h:177
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:593
double GetOrientation() const
Definition: class_module.h:187
void SetPos0(const wxPoint &aPos)
Definition: class_pad.h:262
PCB_GENERAL_SETTINGS & Settings()
void ListSet(const wxString &aList)
Function ListSet Add a list of items.
Arcs (with rounded ends)
wxString GetAbbreviatedUnitsLabel(EDA_UNITS_T aUnit)
Definition: base_units.cpp:485
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:650
void SetLastEditTime(timestamp_t aTime)
Definition: class_module.h:309
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
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.
Class DIALOG_PAD_PROPERTIES_BASE.
void SetDrawAtZero(bool aDrawFlag)
Function SetDrawAtZero() Set the draw at zero flag.
int GetThermalWidth() const
Definition: class_pad.cpp:661
void OnResize(wxSizeEvent &event)
void OnPadShapeSelection(wxCommandEvent &event) override
void PadTypeSelected(wxCommandEvent &event) override
int GetThermalGap() const
Definition: class_pad.cpp:672
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:479
COLOR4D m_HoleColor
Definition: class_pad.h:70
void onPrimitiveDClick(wxMouseEvent &event) override
Called on a double click on the basic shapes list.
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:217
const wxString & GetName() const
Definition: class_pad.h:190
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:887
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:416
void SetPadToDieLength(int aLength)
Definition: class_pad.h:407
PAINTER * GetPainter() const
Function GetPainter() Returns the painter object used by the view for drawing VIEW_ITEMS.
Definition: view.h:196
Class HTML_MESSAGE_BOX.
int GetNet() const
Function GetNet.
Definition: netinfo.h:227
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:1499
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:380
int ValueFromTextCtrl(const wxTextCtrl &aTextCtr)
Convert the number Value in a string according to the internal units and the selected unit (g_UserUni...
Definition: base_units.cpp:386
Like smd, does not appear on the solder paste layer (default) note also has a special attribute in Ge...
Definition: pad_shapes.h:62
void onImportPrimitives(wxCommandEvent &event) override
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:392
bool IsFlipped() const
Definition: class_pad.cpp:126
void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it bu 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:413
COLORS_DESIGN_SETTINGS & Colors()
void SetLocalClearance(int aClearance)
Definition: class_pad.h:414
a dialog to edit basic polygonal shape parameters
double GetLocalSolderPasteMarginRatio() const
Definition: class_pad.h:419
void SetLocalSolderPasteMarginRatio(double aRatio)
Definition: class_pad.h:420
EDA_UNITS_T g_UserUnit
Global variables definitions.
Definition: common.cpp:57
bool SwitchBackend(GAL_TYPE aGalType) override
Function SwitchBackend Switches method of rendering graphics.
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...
void PutValueInLocalUnits(wxTextCtrl &aTextCtr, int aValue)
Function PutValueInLocalUnits converts aValue from internal units to user units and append the units ...
Definition: base_units.cpp:267
bool TransferDataFromWindow() override
Updates the different parameters for the component being edited.
void SetLayerSet(LSET aLayerMask)
Definition: class_pad.h:401
Class NETINFO_ITEM handles the data for a net.
Definition: netinfo.h:69
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:266
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
std::vector< PAD_CS_PRIMITIVE > m_primitives
const wxString & GetNetname() const
Function GetNetname.
double GetRoundRectRadiusRatio() const
has meaning only for rounded rect pads
Definition: class_pad.h:615
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
void SetLocalSolderMaskMargin(int aMargin)
Definition: class_pad.h:411
CUST_PAD_SHAPE_IN_ZONE GetCustomShapeInZoneOpt() const
Definition: class_pad.h:232
static wxString formatCoord(wxPoint aCoord)
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:621
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:850
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
std::vector< DRAWSEGMENT * > m_highligth
NETINFO_ITEM * FindNet(int aNetcode) const
Function FindNet searches for a net with the given netcode.
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:401
double GetScale() const
Function GetScale()
Definition: view.h:265
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:265
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
Function GetGalCanvas returns a pointer to GAL-based canvas of given EDA draw frame.
Definition: draw_frame.h:895
void SetLocalSolderPasteMargin(int aMargin)
Definition: class_pad.h:417
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:334
bool IsType(FRAME_T aType) const
Module description (excepted pads)
Definition: colors.h:45
Class VIEW.
Definition: view.h:58
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.
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:185
void SetThermalGap(int aGap)
Definition: class_pad.h:482
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition: netinfo.h:461
const wxPoint GetPosition() const override
Definition: class_module.h:182
Use thermal relief for pads.
Definition: zones.h:58
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:199
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
a dialog to edit basics shapes parameters.
#define DO_NOT_DRAW
Used to disable draw function.
Definition: base_struct.h:121
bool TransferDataFromWindow() override
Function TransferDataFromWindow Transfer data out of the GUI.
void SetDelta(const wxSize &aSize)
Definition: class_pad.h:271
#define min(a, b)
Definition: auxiliary.h:85
pads are covered by copper
Definition: zones.h:59
int m_Status_Pcb
Flags used in ratsnest calculation and update.
Definition: class_board.h:237
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:894
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39
void SetWidth(int aWidth)