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 
128  m_FlippedWarningIcon->SetBitmap( KiBitmap( dialog_warning_xpm ) );
129  m_nonCopperWarningIcon->SetBitmap( KiBitmap( dialog_warning_xpm ) );
130 
132  m_dummyPad = new D_PAD( (MODULE*) NULL );
133 
134  if( aPad )
135  *m_dummyPad = *aPad;
136  else // We are editing a "master" pad, i.e. a template to create new pads
138 
139  initValues();
140 
141  wxFont infoFont = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
142  infoFont.SetSymbolicSize( wxFONTSIZE_SMALL );
143  m_staticTextInfoNegVal->SetFont( infoFont );
144  m_staticTextInfoPosValue->SetFont( infoFont );
145  m_nonCopperNote->SetFont( infoFont );
146 
147  // Usually, TransferDataToWindow is called by OnInitDialog
148  // calling it here fixes all widgets sizes, and FinishDialogSettings can
149  // safely fix minsizes
151 
152  // Initialize canvas to be able to display the dummy pad:
153  prepareCanvas();
154 
155  m_sdbSizerOK->SetDefault();
156  m_canUpdate = true;
157 
158  // Now all widgets have the size fixed, call FinishDialogSettings
160 }
161 
162 bool DIALOG_PAD_PROPERTIES::m_drawPadOutlineMode = false; // Stores the pad draw option during a session
163 
164 
165 void DIALOG_PAD_PROPERTIES::OnInitDialog( wxInitDialogEvent& event )
166 {
167  m_PadNumCtrl->SetFocus();
168  m_PadNumCtrl->SetSelection( -1, -1 );
169  m_selectedColor = COLOR4D( 1.0, 1.0, 1.0, 0.7 );
170 
171  // Needed on some WM to be sure the pad is redrawn according to the final size
172  // of the canvas, with the right zoom factor
173  redraw();
174 }
175 
176 
177 void DIALOG_PAD_PROPERTIES::OnCancel( wxCommandEvent& event )
178 {
179  // Mandatory to avoid m_panelShowPadGal trying to draw something
180  // in a non valid context during closing process:
181  if( m_parent->IsGalCanvasActive() )
183 
184  // Now call default handler for wxID_CANCEL command event
185  event.Skip();
186 }
187 
188 
190 {
191  // Enable or disable the widgets in page managing custom shape primitives
192  m_listCtrlPrimitives->Enable( aEnable );
193  m_buttonDel->Enable( aEnable );
194  m_buttonEditShape->Enable( aEnable );
195  m_buttonAddShape->Enable( aEnable );
196  m_buttonDup->Enable( aEnable );
197  m_buttonGeometry->Enable( aEnable );
198  m_buttonImport->Enable( aEnable );
199 }
200 
201 
203 {
204  // Initialize the canvases (legacy or gal) to display the pad
205  // Enable the suitable canvas and make some inits
206 
207  // Show the X and Y axis. It is usefull because pad shape can have an offset
208  // or be a complex shape.
209  KIGFX::COLOR4D axis_color = LIGHTBLUE;
210 
211  m_axisOrigin = new KIGFX::ORIGIN_VIEWITEM( axis_color,
213  Millimeter2iu( 0.2 ),
215  m_axisOrigin->SetDrawAtZero( true );
216 
217  if( m_parent->IsGalCanvasActive() )
218  {
222  EnableMousewheelPan( m_parent->GetCanvas()->GetEnableMousewheelPan() );
223 
224  m_panelShowPadGal->Show();
225  m_panelShowPad->Hide();
226 
228 
229  // fix the pad render mode (filled/not filled)
230  KIGFX::PCB_RENDER_SETTINGS* settings =
231  static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
232  bool filled = !m_cbShowPadOutline->IsChecked();
233  settings->SetSketchMode( LAYER_PADS_TH, !filled );
234  settings->SetSketchMode( LAYER_PAD_FR, !filled );
235  settings->SetSketchMode( LAYER_PAD_BK, !filled );
236  settings->SetSketchModeGraphicItems( !filled );
237 
238  // gives a non null grid size (0.001mm) because GAL layer does not like a 0 size grid:
239  double gridsize = 0.001 * IU_PER_MM;
240  view->GetGAL()->SetGridSize( VECTOR2D( gridsize, gridsize ) );
241  view->Add( m_dummyPad );
242  view->Add( m_axisOrigin );
243 
245  Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_PAD_PROPERTIES::OnResize ) );
246  }
247  else
248  {
249  m_panelShowPad->Show();
250  m_panelShowPadGal->Hide();
251  }
252 }
253 
254 
255 void DIALOG_PAD_PROPERTIES::OnPaintShowPanel( wxPaintEvent& event )
256 {
257  wxPaintDC dc( m_panelShowPad );
258  PAD_DRAWINFO drawInfo;
259 
261 
262  if( m_dummyPad->GetLayerSet()[F_Cu] )
263  {
265  }
266 
267  if( m_dummyPad->GetLayerSet()[B_Cu] )
268  {
269  color = color.LegacyMix( m_parent->Settings().Colors().GetItemColor( LAYER_PAD_BK ) );
270  }
271 
272  // What could happen: the pad color is *actually* black, or no
273  // copper was selected
274  if( color == BLACK )
275  color = LIGHTGRAY;
276 
277  drawInfo.m_Color = color;
278  drawInfo.m_HoleColor = DARKGRAY;
279  drawInfo.m_Offset = m_dummyPad->GetPosition();
280  drawInfo.m_Display_padnum = true;
281  drawInfo.m_Display_netname = true;
283 
285  drawInfo.m_ShowNotPlatedHole = true;
286 
287  // Shows the local pad clearance
289 
290  wxSize dc_size = dc.GetSize();
291  dc.SetDeviceOrigin( dc_size.x / 2, dc_size.y / 2 );
292 
293  // Calculate a suitable scale to fit the available draw area
294  int dim = m_dummyPad->GetBoundingRadius() *2;
295 
296  // Invalid x size. User could enter zero, or have deleted all text prior to
297  // entering a new value; this is also treated as zero. If dim is left at
298  // zero, the drawing scale is zero and we get a crash.
299  if( dim == 0 )
300  {
301  // If drill size has been set, use that. Otherwise default to 1mm.
302  dim = m_dummyPad->GetDrillSize().x;
303  if( dim == 0 )
304  dim = Millimeter2iu( 1.0 );
305  }
306 
307  if( m_dummyPad->GetLocalClearance() > 0 )
308  dim += m_dummyPad->GetLocalClearance() * 2;
309 
310  double scale = (double) dc_size.x / dim;
311 
312  // If the pad is a circle, use the x size here instead.
313  int ysize;
314 
316  ysize = m_dummyPad->GetSize().x;
317  else
318  ysize = m_dummyPad->GetSize().y;
319 
320  dim = ysize + std::abs( m_dummyPad->GetDelta().x );
321 
322  // Invalid y size. See note about x size above.
323  if( dim == 0 )
324  {
325  dim = m_dummyPad->GetDrillSize().y;
326  if( dim == 0 )
327  dim = Millimeter2iu( 0.1 );
328  }
329 
330  if( m_dummyPad->GetLocalClearance() > 0 )
331  dim += m_dummyPad->GetLocalClearance() * 2;
332 
333  double altscale = (double) dc_size.y / dim;
334  scale = std::min( scale, altscale );
335 
336  // Give a margin
337  scale *= 0.7;
338  dc.SetUserScale( scale, scale );
339 
340  GRResetPenAndBrush( &dc );
341  m_dummyPad->DrawShape( NULL, &dc, drawInfo );
342 
343  // draw selected primitives:
344  long select = m_listCtrlPrimitives->GetFirstSelected();
345  wxPoint start, end, center;
346 
347  while( select >= 0 )
348  {
349  PAD_CS_PRIMITIVE& primitive = m_primitives[select];
350 
351  // The best way to calculate parameters to draw a primitive is to
352  // use a dummy DRAWSEGMENT and use its methods
353  // Note: in legacy canvas, the pad has the 0,0 position
354  DRAWSEGMENT dummySegment;
355  primitive.ExportTo( &dummySegment );
356  dummySegment.Rotate( wxPoint( 0, 0), m_dummyPad->GetOrientation() );
357 
358  switch( primitive.m_Shape )
359  {
360  case S_SEGMENT: // usual segment : line with rounded ends
361  if( !m_drawPadOutlineMode )
362  GRFilledSegment( NULL, &dc, dummySegment.GetStart(), dummySegment.GetEnd(),
363  primitive.m_Thickness, m_selectedColor );
364  else
365  GRCSegm( NULL, &dc, dummySegment.GetStart(), dummySegment.GetEnd(),
366  primitive.m_Thickness, m_selectedColor );
367  break;
368 
369  case S_ARC: // Arc with rounded ends
370  if( !m_drawPadOutlineMode )
371  GRArc1( NULL, &dc, dummySegment.GetArcEnd(), dummySegment.GetArcStart(),
372  dummySegment.GetCenter(), primitive.m_Thickness, m_selectedColor );
373  else
374  {
375  GRArc1( NULL, &dc, dummySegment.GetArcEnd(), dummySegment.GetArcStart(),
376  dummySegment.GetCenter(), 0, m_selectedColor );
377 /* GRArc1( NULL, &dc, dummySegment.GetArcEnd(), dummySegment.GetArcStart(),
378  dummySegment.GetCenter() - primitive.m_Thickness, 0, m_selectedColor );*/
379  }
380  break;
381 
382  case S_CIRCLE: // ring or circle
383  if( primitive.m_Thickness )
384  {
385  if( !m_drawPadOutlineMode )
386  GRCircle( NULL, &dc, dummySegment.GetCenter(), primitive.m_Radius,
387  primitive.m_Thickness, m_selectedColor );
388  else
389  {
390  GRCircle( NULL, &dc, dummySegment.GetCenter(),
391  primitive.m_Radius + primitive.m_Thickness/2, 0,
392  m_selectedColor );
393  GRCircle( NULL, &dc, dummySegment.GetCenter(),
394  primitive.m_Radius - primitive.m_Thickness/2, 0,
395  m_selectedColor );
396  }
397  }
398  else
399  {
400  if( !m_drawPadOutlineMode )
401  GRFilledCircle( NULL, &dc, dummySegment.GetCenter(),
402  primitive.m_Radius, m_selectedColor );
403  else
404  GRCircle( NULL, &dc, dummySegment.GetCenter(),
405  primitive.m_Radius, 0, m_selectedColor );
406  }
407  break;
408 
409  case S_POLYGON: // polygon
410  {
411  std::vector<wxPoint> poly = dummySegment.BuildPolyPointsList();
412  GRClosedPoly( NULL, &dc, poly.size(), &poly[0],
413  m_drawPadOutlineMode ? false : true,
415  }
416  break;
417 
418  default:
419  break;
420  }
421 
422  select = m_listCtrlPrimitives->GetNextSelected( select );
423  }
424 
425  // Draw X and Y axis. This is particularly useful to show the
426  // reference position of pads with offset and no hole, or custom pad shapes
427  const int linethickness = 0;
428  GRLine( NULL, &dc, -int( dc_size.x/scale ), 0, int( dc_size.x/scale ), 0,
429  linethickness, LIGHTBLUE ); // X axis
430  GRLine( NULL, &dc, 0, -int( dc_size.y/scale ), 0, int( dc_size.y/scale ),
431  linethickness, LIGHTBLUE ); // Y axis
432 
433  event.Skip();
434 }
435 
436 
438 {
439  // Note:
440  // To avoid generating a wxEVT_TEXT event from m_tcCornerSizeRatio
441  // we use ChangeValue instead of SetValue, to set the displayed string
443  {
444  m_tcCornerSizeRatio->ChangeValue( wxString::Format( "%.1f",
448  }
449  else if( m_dummyPad->GetShape() == PAD_SHAPE_RECT )
450  {
451  m_tcCornerSizeRatio->ChangeValue( "0" );
452  m_staticTextCornerRadiusValue->SetLabel( "0" );
453  }
454  else
455  {
456  m_tcCornerSizeRatio->ChangeValue( wxEmptyString );
457  m_staticTextCornerRadiusValue->SetLabel( wxEmptyString );
458  }
459 }
460 
461 
463 {
465  return;
466 
467  wxString value = m_tcCornerSizeRatio->GetValue();
468  double rrRadiusRatioPercent;
469 
470  if( value.ToDouble( &rrRadiusRatioPercent ) )
471  {
472  // Clamp rrRadiusRatioPercent to acceptable value (0.0 to 50.0)
473  if( rrRadiusRatioPercent < 0.0 )
474  {
475  rrRadiusRatioPercent = 0.0;
476  m_tcCornerSizeRatio->ChangeValue( "0.0" );
477  }
478 
479  if( rrRadiusRatioPercent > 50.0 )
480  {
481  rrRadiusRatioPercent = 0.5;
482  m_tcCornerSizeRatio->ChangeValue( "50.0" );
483  }
484 
488  redraw();
489  }
490 }
491 
492 
494 {
495  wxString msg;
496  double angle;
497 
498  // Disable pad net name wxTextCtrl if the caller is the footprint editor
499  // because nets are living only in the board managed by the board editor
501 
502 
503  // Setup layers names from board
504  // Should be made first, before calling m_rbCopperLayersSel->SetSelection()
505  m_rbCopperLayersSel->SetString( 0, m_board->GetLayerName( F_Cu ) );
506  m_rbCopperLayersSel->SetString( 1, m_board->GetLayerName( B_Cu ) );
507 
508  m_PadLayerAdhCmp->SetLabel( m_board->GetLayerName( F_Adhes ) );
509  m_PadLayerAdhCu->SetLabel( m_board->GetLayerName( B_Adhes ) );
511  m_PadLayerPateCu->SetLabel( m_board->GetLayerName( B_Paste ) );
513  m_PadLayerSilkCu->SetLabel( m_board->GetLayerName( B_SilkS ) );
514  m_PadLayerMaskCmp->SetLabel( m_board->GetLayerName( F_Mask ) );
515  m_PadLayerMaskCu->SetLabel( m_board->GetLayerName( B_Mask ) );
516  m_PadLayerECO1->SetLabel( m_board->GetLayerName( Eco1_User ) );
517  m_PadLayerECO2->SetLabel( m_board->GetLayerName( Eco2_User ) );
519 
520  m_isFlipped = false;
521 
522  if( m_currentPad )
523  {
525 
526  if( m_isFlipped )
527  m_staticModuleSideValue->SetLabel( _( "Back side (footprint is mirrored)" ) );
528  else
529  m_staticModuleSideValue->SetLabel( _( "Front side" ) );
530 
531  // Diplay footprint rotation ( angles are in 0.1 degree )
532  MODULE* footprint = m_currentPad->GetParent();
533 
534  if( footprint )
535  msg.Printf( "%.1f", footprint->GetOrientationDegrees() );
536  else
537  msg = _("No footprint" );
538 
539  m_staticModuleRotValue->SetLabel( msg );
540  }
541 
542  if( m_isFlipped )
543  {
544  wxPoint pt = m_dummyPad->GetOffset();
545  pt.y = -pt.y;
546  m_dummyPad->SetOffset( pt );
547 
548  wxSize sz = m_dummyPad->GetDelta();
549  sz.y = -sz.y;
550  m_dummyPad->SetDelta( sz );
551 
552  // flip pad's layers
554 
555  // flip custom pad shapes
557  }
558 
560 
562 
563  m_PadNumCtrl->SetValue( m_dummyPad->GetName() );
564  m_PadNetNameCtrl->SetValue( m_dummyPad->GetNetname() );
565 
566  // Set the unit name in dialog:
567  wxStaticText* unitTexts[] =
568  {
576  };
577 
578  for( unsigned ii = 0; ii < DIM( unitTexts ); ++ii )
579  unitTexts[ii]->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) );
580 
581  // Display current pad parameters units:
584 
587 
590 
593 
594  if( m_dummyPad->GetDelta().x )
595  {
597  m_trapDeltaDirChoice->SetSelection( 0 );
598  }
599  else
600  {
602  m_trapDeltaDirChoice->SetSelection( 1 );
603  }
604 
606 
611 
612  // These 2 parameters are usually < 0, so prepare entering a negative value, if current is 0
614 
616  m_SolderPasteMarginCtrl->SetValue( wxT( "-" ) + m_SolderPasteMarginCtrl->GetValue() );
617 
618  msg.Printf( wxT( "%f" ), m_dummyPad->GetLocalSolderPasteMarginRatio() * 100.0 );
619 
620  if( m_dummyPad->GetLocalSolderPasteMarginRatio() == 0.0 && msg[0] == '0' )
621  // Sometimes Printf adds a sign if the value is small
622  m_SolderPasteMarginRatioCtrl->SetValue( wxT( "-" ) + msg );
623  else
625 
626  switch( m_dummyPad->GetZoneConnection() )
627  {
628  default:
630  m_ZoneConnectionChoice->SetSelection( 0 );
631  m_ZoneConnectionCustom->SetSelection( 0 );
632  break;
633 
634  case PAD_ZONE_CONN_FULL:
635  m_ZoneConnectionChoice->SetSelection( 1 );
636  m_ZoneConnectionCustom->SetSelection( 1 );
637  break;
638 
640  m_ZoneConnectionChoice->SetSelection( 2 );
641  m_ZoneConnectionCustom->SetSelection( 0 );
642  break;
643 
644  case PAD_ZONE_CONN_NONE:
645  m_ZoneConnectionChoice->SetSelection( 3 );
646  m_ZoneConnectionCustom->SetSelection( 0 );
647  break;
648  }
649 
651  m_ZoneCustomPadShape->SetSelection( 1 );
652  else
653  m_ZoneCustomPadShape->SetSelection( 0 );
654 
655  if( m_currentPad )
656  {
657  angle = m_currentPad->GetOrientation();
658  MODULE* footprint = m_currentPad->GetParent();
659 
660  if( footprint )
661  angle -= footprint->GetOrientation();
662 
663  if( m_isFlipped )
664  angle = -angle;
665 
666  m_dummyPad->SetOrientation( angle );
667  }
668 
669  angle = m_dummyPad->GetOrientation();
670 
671  NORMALIZE_ANGLE_180( angle ); // ? normalizing is in D_PAD::SetOrientation()
672 
673  // Set layers used by this pad: :
675 
676  // Pad Orient
677  switch( int( angle ) )
678  {
679  case 0:
680  m_PadOrient->SetSelection( 0 );
681  break;
682 
683  case 900:
684  m_PadOrient->SetSelection( 1 );
685  break;
686 
687  case -900:
688  m_PadOrient->SetSelection( 2 );
689  break;
690 
691  case 1800:
692  case -1800:
693  m_PadOrient->SetSelection( 3 );
694  break;
695 
696  default:
697  m_PadOrient->SetSelection( 4 );
698  break;
699  }
700 
701  switch( m_dummyPad->GetShape() )
702  {
703  default:
704  case PAD_SHAPE_CIRCLE:
705  m_PadShape->SetSelection( CHOICE_SHAPE_CIRCLE );
706  break;
707 
708  case PAD_SHAPE_OVAL:
709  m_PadShape->SetSelection( CHOICE_SHAPE_OVAL );
710  break;
711 
712  case PAD_SHAPE_RECT:
713  m_PadShape->SetSelection( CHOICE_SHAPE_RECT );
714  break;
715 
716  case PAD_SHAPE_TRAPEZOID:
717  m_PadShape->SetSelection( CHOICE_SHAPE_TRAPEZOID );
718  break;
719 
720  case PAD_SHAPE_ROUNDRECT:
721  m_PadShape->SetSelection( CHOICE_SHAPE_ROUNDRECT );
722  break;
723 
724  case PAD_SHAPE_CUSTOM:
727  else
729  break;
730  }
731 
733 
734  m_OrientValue = angle / 10.0;
735 
736  // Type of pad selection
737  m_PadType->SetSelection( 0 );
738 
739  for( unsigned ii = 0; ii < DIM( code_type ); ii++ )
740  {
741  if( code_type[ii] == m_dummyPad->GetAttribute() )
742  {
743  m_PadType->SetSelection( ii );
744  break;
745  }
746  }
747 
748  // Enable/disable Pad name,and pad length die
749  // (disable for NPTH pads (mechanical pads)
751 
752  m_PadNumCtrl->Enable( enable );
753  m_PadNetNameCtrl->Enable( m_canEditNetName && enable && m_currentPad != NULL );
754  m_LengthPadToDieCtrl->Enable( enable );
755 
757  m_DrillShapeCtrl->SetSelection( 0 );
758  else
759  m_DrillShapeCtrl->SetSelection( 1 );
760 
761  // Update some dialog widgets state (Enable/disable options):
762  wxCommandEvent cmd_event;
764  OnDrillShapeSelected( cmd_event );
765  OnPadShapeSelection( cmd_event );
767 
768  // Update basic shapes list
770 }
771 
772 // A small helper function, to display coordinates:
773 static wxString formatCoord( wxPoint aCoord )
774 {
775  return wxString::Format( "(X:%s Y:%s)",
776  CoordinateToString( aCoord.x, true ),
777  CoordinateToString( aCoord.y, true ) );
778 }
779 
781 {
782  m_listCtrlPrimitives->ClearAll();
783 
784  wxListItem itemCol;
785  itemCol.SetImage(-1);
786 
787  for( int ii = 0; ii < 5; ++ii )
788  m_listCtrlPrimitives->InsertColumn(ii, itemCol);
789 
790  wxString bs_info[5];
791 
792  for( unsigned ii = 0; ii < m_primitives.size(); ++ii )
793  {
794  const PAD_CS_PRIMITIVE& primitive = m_primitives[ii];
795 
796  for( unsigned jj = 0; jj < 5; ++jj )
797  bs_info[jj].Empty();
798 
799  bs_info[4] = wxString::Format( _( "width %s" ),
800  CoordinateToString( primitive.m_Thickness, true ) );
801 
802  switch( primitive.m_Shape )
803  {
804  case S_SEGMENT: // usual segment : line with rounded ends
805  bs_info[0] = _( "Segment" );
806  bs_info[1] = _( "from " ) + formatCoord( primitive.m_Start );
807  bs_info[2] = _( "to " ) + formatCoord( primitive.m_End );
808  break;
809 
810  case S_ARC: // Arc with rounded ends
811  bs_info[0] = _( "Arc" );
812  bs_info[1] = _( "center " ) + formatCoord( primitive.m_Start ); // Center
813  bs_info[2] = _( "start " ) + formatCoord( primitive.m_End ); // Start point
814  bs_info[3] = wxString::Format( _( "angle %s" ), FMT_ANGLE( primitive.m_ArcAngle ) );
815  break;
816 
817  case S_CIRCLE: // ring or circle
818  if( primitive.m_Thickness )
819  bs_info[0] = _( "ring" );
820  else
821  bs_info[0] = _( "circle" );
822 
823  bs_info[1] = formatCoord( primitive.m_Start );
824  bs_info[2] = wxString::Format( _( "radius %s" ),
825  CoordinateToString( primitive.m_Radius, true ) );
826  break;
827 
828  case S_POLYGON: // polygon
829  bs_info[0] = "Polygon";
830  bs_info[1] = wxString::Format( _( "corners count %d" ), (int) primitive.m_Poly.size() );
831  break;
832 
833  default:
834  bs_info[0] = "Unknown primitive";
835  break;
836  }
837 
838  long tmp = m_listCtrlPrimitives->InsertItem(ii, bs_info[0]);
839  m_listCtrlPrimitives->SetItemData(tmp, ii);
840 
841  for( int jj = 0, col = 0; jj < 5; ++jj )
842  {
843  m_listCtrlPrimitives->SetItem(tmp, col++, bs_info[jj]);
844  }
845  }
846 
847  // Now columns are filled, ensure correct width of columns
848  for( unsigned ii = 0; ii < 5; ++ii )
849  m_listCtrlPrimitives->SetColumnWidth( ii, wxLIST_AUTOSIZE );
850 }
851 
852 void DIALOG_PAD_PROPERTIES::OnResize( wxSizeEvent& event )
853 {
854  redraw();
855  event.Skip();
856 }
857 
858 
859 void DIALOG_PAD_PROPERTIES::onChangePadMode( wxCommandEvent& event )
860 {
862 
863  if( m_parent->IsGalCanvasActive() )
864  {
866 
867  // fix the pad render mode (filled/not filled)
868  KIGFX::PCB_RENDER_SETTINGS* settings =
869  static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
870 
875  }
876 
877  redraw();
878 }
879 
880 
881 void DIALOG_PAD_PROPERTIES::OnPadShapeSelection( wxCommandEvent& event )
882 {
883  bool is_custom = false;
884 
885  switch( m_PadShape->GetSelection() )
886  {
887  case CHOICE_SHAPE_CIRCLE:
888  m_ShapeDelta_Ctrl->Enable( false );
889  m_trapDeltaDirChoice->Enable( false );
890  m_ShapeSize_Y_Ctrl->Enable( false );
891  m_ShapeOffset_X_Ctrl->Enable( false );
892  m_ShapeOffset_Y_Ctrl->Enable( false );
893  break;
894 
895  case CHOICE_SHAPE_OVAL:
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 
903  case CHOICE_SHAPE_RECT:
904  m_ShapeDelta_Ctrl->Enable( false );
905  m_trapDeltaDirChoice->Enable( false );
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( true );
913  m_trapDeltaDirChoice->Enable( true );
914  m_ShapeSize_Y_Ctrl->Enable( true );
915  m_ShapeOffset_X_Ctrl->Enable( true );
916  m_ShapeOffset_Y_Ctrl->Enable( true );
917  break;
918 
920  m_ShapeDelta_Ctrl->Enable( false );
921  m_trapDeltaDirChoice->Enable( false );
922  m_ShapeSize_Y_Ctrl->Enable( true );
923  m_ShapeOffset_X_Ctrl->Enable( true );
924  m_ShapeOffset_Y_Ctrl->Enable( true );
925  // Ensure m_tcCornerSizeRatio contains the right value:
926  m_tcCornerSizeRatio->ChangeValue( wxString::Format( "%.1f",
928  break;
929 
930  case CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR: // PAD_SHAPE_CUSTOM, circular anchor
931  case CHOICE_SHAPE_CUSTOM_RECT_ANCHOR: // PAD_SHAPE_CUSTOM, rect anchor
932  is_custom = true;
933  m_ShapeDelta_Ctrl->Enable( false );
934  m_trapDeltaDirChoice->Enable( false );
935  m_ShapeSize_Y_Ctrl->Enable(
936  m_PadShape->GetSelection() == CHOICE_SHAPE_CUSTOM_RECT_ANCHOR );
937  m_ShapeOffset_X_Ctrl->Enable( false );
938  m_ShapeOffset_Y_Ctrl->Enable( false );
939  break;
940  }
941 
942  enablePrimitivePage( is_custom );
943 
944  // A few widgets are enabled only for rounded rect pads:
945  m_tcCornerSizeRatio->Enable( m_PadShape->GetSelection() == CHOICE_SHAPE_ROUNDRECT );
946 
947  // PAD_SHAPE_CUSTOM type has constraints for zone connection and thermal shape:
948  // only not connected or solid connection is allowed to avoid destroying the shape.
949  // Enable/disable options only available for custom shaped pads
950  m_ZoneConnectionChoice->Enable( !is_custom );
951  m_ZoneConnectionCustom->Enable( is_custom );
952  m_ThermalWidthCtrl->Enable( !is_custom );
953  m_ThermalGapCtrl->Enable( !is_custom );
954 
955  m_sbSizerZonesSettings->Show( !is_custom );
956  m_sbSizerCustomShapedZonesSettings->Show( is_custom );
957 
959 
961  redraw();
962 }
963 
964 
965 void DIALOG_PAD_PROPERTIES::OnDrillShapeSelected( wxCommandEvent& event )
966 {
967  if( m_PadType->GetSelection() == 1 || m_PadType->GetSelection() == 2 )
968  {
969  // pad type = SMD or CONN: no hole allowed
970  m_PadDrill_X_Ctrl->Enable( false );
971  m_PadDrill_Y_Ctrl->Enable( false );
972  }
973  else
974  {
975  switch( m_DrillShapeCtrl->GetSelection() )
976  {
977  case 0: //CIRCLE:
978  m_PadDrill_X_Ctrl->Enable( true );
979  m_PadDrill_Y_Ctrl->Enable( false );
980  break;
981 
982  case 1: //OVALE:
983  m_PadDrill_X_Ctrl->Enable( true );
984  m_PadDrill_Y_Ctrl->Enable( true );
985  break;
986  }
987  }
988 
990  redraw();
991 }
992 
993 
994 void DIALOG_PAD_PROPERTIES::PadOrientEvent( wxCommandEvent& event )
995 {
996  switch( m_PadOrient->GetSelection() )
997  {
998  case 0:
1000  break;
1001 
1002  case 1:
1003  m_dummyPad->SetOrientation( 900 );
1004  break;
1005 
1006  case 2:
1007  m_dummyPad->SetOrientation( -900 );
1008  break;
1009 
1010  case 3:
1011  m_dummyPad->SetOrientation( 1800 );
1012  break;
1013 
1014  default:
1015  break;
1016  }
1017 
1019  m_OrientValidator.TransferToWindow();
1020 
1022  redraw();
1023 }
1024 
1025 
1026 void DIALOG_PAD_PROPERTIES::PadTypeSelected( wxCommandEvent& event )
1027 {
1028  unsigned ii = m_PadType->GetSelection();
1029 
1030  if( ii >= DIM( code_type ) ) // catches < 0 also
1031  ii = 0;
1032 
1033  LSET layer_mask = std_pad_layers[ii];
1034  setPadLayersList( layer_mask );
1035 
1036  // Enable/disable drill dialog items:
1037  event.SetId( m_DrillShapeCtrl->GetSelection() );
1038  OnDrillShapeSelected( event );
1039 
1040  if( ii == 0 || ii == DIM( code_type )-1 )
1041  m_DrillShapeCtrl->Enable( true );
1042  else
1043  m_DrillShapeCtrl->Enable( false );
1044 
1045  // Enable/disable Pad name,and pad length die
1046  // (disable for NPTH pads (mechanical pads)
1047  bool enable = ii != 3;
1048  m_PadNumCtrl->Enable( enable );
1049  m_PadNetNameCtrl->Enable( m_canEditNetName && enable && m_currentPad != NULL );
1050  m_LengthPadToDieCtrl->Enable( enable );
1051 }
1052 
1053 
1055 {
1056  LSET cu_set = layer_mask & LSET::AllCuMask();
1057 
1058  if( cu_set == LSET( F_Cu ) )
1059  m_rbCopperLayersSel->SetSelection( 0 );
1060  else if( cu_set == LSET( B_Cu ) )
1061  m_rbCopperLayersSel->SetSelection( 1 );
1062  else if( cu_set.any() )
1063  m_rbCopperLayersSel->SetSelection( 2 );
1064  else
1065  m_rbCopperLayersSel->SetSelection( 3 );
1066 
1067  m_PadLayerAdhCmp->SetValue( layer_mask[F_Adhes] );
1068  m_PadLayerAdhCu->SetValue( layer_mask[B_Adhes] );
1069 
1070  m_PadLayerPateCmp->SetValue( layer_mask[F_Paste] );
1071  m_PadLayerPateCu->SetValue( layer_mask[B_Paste] );
1072 
1073  m_PadLayerSilkCmp->SetValue( layer_mask[F_SilkS] );
1074  m_PadLayerSilkCu->SetValue( layer_mask[B_SilkS] );
1075 
1076  m_PadLayerMaskCmp->SetValue( layer_mask[F_Mask] );
1077  m_PadLayerMaskCu->SetValue( layer_mask[B_Mask] );
1078 
1079  m_PadLayerECO1->SetValue( layer_mask[Eco1_User] );
1080  m_PadLayerECO2->SetValue( layer_mask[Eco2_User] );
1081 
1082  m_PadLayerDraft->SetValue( layer_mask[Dwgs_User] );
1083 }
1084 
1085 
1086 // Called when select/deselect a layer.
1087 void DIALOG_PAD_PROPERTIES::OnSetLayers( wxCommandEvent& event )
1088 {
1090  redraw();
1091 }
1092 
1093 
1094 // test if all values are acceptable for the pad
1096 {
1097  bool error = transferDataToPad( m_dummyPad );
1098  bool skip_tstoffset = false; // the offset prm is not always tested
1099 
1100  wxArrayString error_msgs;
1101  wxString msg;
1102 
1103  // Test for incorrect values
1104  if( (m_dummyPad->GetSize().x <= 0) ||
1105  ((m_dummyPad->GetSize().y <= 0) && (m_dummyPad->GetShape() != PAD_SHAPE_CIRCLE)) )
1106  {
1107  error_msgs.Add( _( "Pad size must be greater than zero" ) );
1108  }
1109 
1110  if( (m_dummyPad->GetSize().x < m_dummyPad->GetDrillSize().x) ||
1111  (m_dummyPad->GetSize().y < m_dummyPad->GetDrillSize().y) )
1112  {
1113  error_msgs.Add( _( "Incorrect value for pad drill: pad drill bigger than pad size" ) );
1114  skip_tstoffset = true; // offset prm will be not tested because if the drill value
1115  // is incorrect the offset prm is always seen as incorrect, even if it is 0
1116  }
1117 
1118  if( m_dummyPad->GetLocalClearance() < 0 )
1119  {
1120  error_msgs.Add( _( "Pad local clearance must be zero or greater than zero" ) );
1121  }
1122 
1123  // Some pads need a negative solder mask clearance (mainly for BGA with small pads)
1124  // However the negative solder mask clearance must not create negative mask size
1125  // Therefore test for minimal acceptable negative value
1126  // Hovewer, a negative value can give strange result with custom shapes, so it is not
1127  // allowed for custom pad shape
1129  {
1131  error_msgs.Add( _( "Pad local solder mask clearance must be zero or greater than zero" ) );
1132  else
1133  {
1134  int min_smClearance = -std::min( m_dummyPad->GetSize().x, m_dummyPad->GetSize().y )/2;
1135 
1136  if( m_dummyPad->GetLocalSolderMaskMargin() <= min_smClearance )
1137  {
1138  error_msgs.Add( wxString::Format(
1139  _( "Pad local solder mask clearance must be greater than %s" ),
1140  StringFromValue( g_UserUnit, min_smClearance, true ) ) );
1141  }
1142  }
1143  }
1144 
1145  // Some pads need a positive solder paste clearance (mainly for BGA with small pads)
1146  // Hovewer, a positive value can create issues if the resulting shape is too big.
1147  // (like a solder paste creating a solder paste area on a neighbour pad or on the solder mask)
1148  // So we could ask for user to confirm the choice
1149  // Currently there are no test
1150 
1151  LSET padlayers_mask = m_dummyPad->GetLayerSet();
1152 
1153  if( padlayers_mask == 0 )
1154  error_msgs.Add( _( "Error: pad has no layer" ) );
1155 
1156  if( !padlayers_mask[F_Cu] && !padlayers_mask[B_Cu] )
1157  {
1158  if( m_dummyPad->GetDrillSize().x || m_dummyPad->GetDrillSize().y )
1159  {
1160  // Note: he message is shown in an HTML window
1161  msg = _( "Error: the pad is not on a copper layer and has a hole" );
1162 
1164  {
1165  msg += wxT( "<br><br><i>" );
1166  msg += _( "For NPTH pad, set pad size value to pad drill value,"
1167  " if you do not want this pad plotted in gerber files"
1168  );
1169  }
1170 
1171  error_msgs.Add( msg );
1172  }
1173  }
1174 
1175  if( !skip_tstoffset )
1176  {
1177  wxPoint max_size;
1178  max_size.x = std::abs( m_dummyPad->GetOffset().x );
1179  max_size.y = std::abs( m_dummyPad->GetOffset().y );
1180  max_size.x += m_dummyPad->GetDrillSize().x / 2;
1181  max_size.y += m_dummyPad->GetDrillSize().y / 2;
1182 
1183  if( ( m_dummyPad->GetSize().x / 2 < max_size.x ) ||
1184  ( m_dummyPad->GetSize().y / 2 < max_size.y ) )
1185  {
1186  error_msgs.Add( _( "Incorrect value for pad offset" ) );
1187  }
1188  }
1189 
1190  if( error )
1191  {
1192  error_msgs.Add( _( "Too large value for pad delta size" ) );
1193  }
1194 
1195  switch( m_dummyPad->GetAttribute() )
1196  {
1197  case PAD_ATTRIB_HOLE_NOT_PLATED: // Not plated, but through hole, a hole is expected
1198  case PAD_ATTRIB_STANDARD : // Pad through hole, a hole is also expected
1199  if( m_dummyPad->GetDrillSize().x <= 0 ||
1201  error_msgs.Add( _( "Error: Through hole pad: drill diameter set to 0" ) );
1202  break;
1203 
1204  case PAD_ATTRIB_CONN: // Connector pads are smd pads, just they do not have solder paste.
1205  if( padlayers_mask[B_Paste] || padlayers_mask[F_Paste] )
1206  error_msgs.Add( _( "Error: Connector pads are not on the solder paste layer\n"
1207  "Use SMD pads instead" ) );
1208  // Fall trough
1209  case PAD_ATTRIB_SMD: // SMD and Connector pads (One external copper layer only)
1210  {
1211  LSET innerlayers_mask = padlayers_mask & LSET::InternalCuMask();
1212 
1213  if( ( padlayers_mask[F_Cu] && padlayers_mask[B_Cu] ) ||
1214  innerlayers_mask.count() != 0 )
1215  error_msgs.Add( _( "Error: only one external copper layer allowed for SMD or Connector pads" ) );
1216  }
1217  break;
1218  }
1219 
1220 
1222  {
1223  wxString value = m_tcCornerSizeRatio->GetValue();
1224  double rrRadiusRatioPercent;
1225 
1226  if( !value.ToDouble( &rrRadiusRatioPercent ) )
1227  error_msgs.Add( _( "Incorrect corner size value" ) );
1228  else
1229  {
1230  if( rrRadiusRatioPercent < 0.0 )
1231  error_msgs.Add( _( "Incorrect (negative) corner size value" ) );
1232  else if( rrRadiusRatioPercent > 50.0 )
1233  error_msgs.Add( _( "Corner size value must be smaller than 50%" ) );
1234  }
1235  }
1236 
1238  {
1240  error_msgs.Add(
1241  _( "Incorrect pad shape: the shape must be equivalent to only one polygon" ) );
1242  }
1243 
1244 
1245  if( error_msgs.GetCount() )
1246  {
1247  HTML_MESSAGE_BOX dlg( this, _("Pad setup errors list" ) );
1248  dlg.ListSet( error_msgs );
1249  dlg.ShowModal();
1250  }
1251 
1252  return error_msgs.GetCount() == 0;
1253 }
1254 
1255 
1257 {
1258  if( m_parent->IsGalCanvasActive() )
1259  {
1262 
1263  // The layer used to place primitive items selected when editing custom pad shapes
1264  // we use here a layer never used in a pad:
1265  #define SELECTED_ITEMS_LAYER Dwgs_User
1266 
1268  KIGFX::PCB_RENDER_SETTINGS* settings =
1269  static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
1271 
1272  view->Update( m_dummyPad );
1273 
1274  // delete previous items if highlight list
1275  while( m_highligth.size() )
1276  {
1277  delete m_highligth.back(); // the dtor also removes item from view
1278  m_highligth.pop_back();
1279  }
1280 
1281  // highlight selected primitives:
1282  long select = m_listCtrlPrimitives->GetFirstSelected();
1283 
1284  while( select >= 0 )
1285  {
1286  PAD_CS_PRIMITIVE& primitive = m_primitives[select];
1287 
1288  DRAWSEGMENT* dummySegment = new DRAWSEGMENT;
1289  dummySegment->SetLayer( SELECTED_ITEMS_LAYER );
1290  primitive.ExportTo( dummySegment );
1291  dummySegment->Rotate( wxPoint( 0, 0), m_dummyPad->GetOrientation() );
1292  dummySegment->Move( m_dummyPad->GetPosition() );
1293 
1294  // Update selected primitive (highligth selected)
1295  switch( primitive.m_Shape )
1296  {
1297  case S_SEGMENT:
1298  case S_ARC:
1299  break;
1300 
1301  case S_CIRCLE: // ring or circle
1302  if( primitive.m_Thickness == 0 ) // filled circle
1303  { // the filled circle option does not exist in a DRAWSEGMENT
1304  // but it is easy to create it with a circle having the
1305  // right radius and outline width
1306  wxPoint end = dummySegment->GetCenter();
1307  end.x += primitive.m_Radius/2;
1308  dummySegment->SetEnd( end );
1309  dummySegment->SetWidth( primitive.m_Radius );
1310  }
1311  break;
1312 
1313  case S_POLYGON:
1314  break;
1315 
1316  default:
1317  delete dummySegment;
1318  dummySegment = nullptr;
1319  break;
1320  }
1321 
1322  if( dummySegment )
1323  {
1324  view->Add( dummySegment );
1325  m_highligth.push_back( dummySegment );
1326  }
1327 
1328  select = m_listCtrlPrimitives->GetNextSelected( select );
1329  }
1330 
1331  BOX2I bbox = m_dummyPad->ViewBBox();
1332 
1333  if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
1334  {
1335  // gives a size to the full drawable area
1336  BOX2I drawbox;
1337  drawbox.Move( m_dummyPad->GetPosition() );
1338  drawbox.Inflate( bbox.GetSize().x*2, bbox.GetSize().y*2 );
1339  view->SetBoundary( drawbox );
1340 
1341  // Autozoom
1342  view->SetViewport( BOX2D( bbox.GetOrigin(), bbox.GetSize() ) );
1343 
1344  // Add a margin
1345  view->SetScale( m_panelShowPadGal->GetView()->GetScale() * 0.7 );
1346 
1349  }
1350  }
1351  else
1352  {
1353  m_panelShowPad->Refresh();
1354  }
1355 }
1356 
1357 
1359 {
1360  if( !wxDialog::TransferDataToWindow() )
1361  return false;
1362 
1363  if( !m_panelGeneral->TransferDataToWindow() )
1364  return false;
1365 
1366  if( !m_localSettingsPanel->TransferDataToWindow() )
1367  return false;
1368 
1369  return true;
1370 }
1371 
1372 
1374 {
1375  BOARD_COMMIT commit( m_parent );
1376 
1377  if( !wxDialog::TransferDataFromWindow() )
1378  return false;
1379 
1380  if( !m_panelGeneral->TransferDataFromWindow() )
1381  return false;
1382 
1383  if( !m_localSettingsPanel->TransferDataFromWindow() )
1384  return false;
1385 
1386  if( !padValuesOK() )
1387  return false;
1388 
1389  bool rastnestIsChanged = false;
1390  int isign = m_isFlipped ? -1 : 1;
1391 
1393  // m_padMaster is a pattern: ensure there is no net for this pad:
1395 
1396  if( !m_currentPad ) // Set current Pad parameters
1397  return true;
1398 
1399  commit.Modify( m_currentPad );
1400 
1401  // redraw the area where the pad was, without pad (delete pad on screen)
1405 
1406  // Update values
1409 
1411  {
1413  rastnestIsChanged = true;
1414  }
1415 
1416  wxSize size;
1417  MODULE* footprint = m_currentPad->GetParent();
1418 
1419  if( footprint )
1420  {
1421  footprint->SetLastEditTime();
1422 
1423  // compute the pos 0 value, i.e. pad position for footprint with orientation = 0
1424  // i.e. relative to footprint origin (footprint position)
1425  wxPoint pt = m_currentPad->GetPosition() - footprint->GetPosition();
1426  RotatePoint( &pt, -footprint->GetOrientation() );
1427  m_currentPad->SetPos0( pt );
1429  + footprint->GetOrientation() );
1430  }
1431 
1433 
1434  size = m_padMaster->GetDelta();
1435  size.y *= isign;
1436  m_currentPad->SetDelta( size );
1437 
1440 
1441  wxPoint offset = m_padMaster->GetOffset();
1442  offset.y *= isign;
1443  m_currentPad->SetOffset( offset );
1444 
1446 
1449 
1450 
1453 
1454  if( m_isFlipped )
1455  {
1458  }
1459 
1461  {
1462  rastnestIsChanged = true;
1464  }
1465 
1466  if( m_isFlipped )
1467  {
1469  }
1470 
1472 
1473  wxString padNetname;
1474 
1475  // For PAD_ATTRIB_HOLE_NOT_PLATED, ensure there is no net name selected
1477  padNetname = m_PadNetNameCtrl->GetValue();
1478 
1479  if( m_currentPad->GetNetname() != padNetname )
1480  {
1481  const NETINFO_ITEM* netinfo = m_board->FindNet( padNetname );
1482 
1483  if( !padNetname.IsEmpty() && netinfo == NULL )
1484  {
1485  DisplayError( NULL, _( "Unknown netname, netname not changed" ) );
1486  }
1487  else if( netinfo )
1488  {
1489  rastnestIsChanged = true;
1490  m_currentPad->SetNetCode( netinfo->GetNet() );
1491  }
1492  }
1493 
1501 
1503  {
1506  else
1508  }
1509  else
1511 
1512 
1513  // rounded rect pads with radius ratio = 0 are in fact rect pads.
1514  // So set the right shape (and perhaps issues with a radius = 0)
1517  {
1519  }
1520 
1521  // define the way the clearance area is defined in zones
1523 
1524  if( footprint )
1525  footprint->CalculateBoundingBox();
1526 
1528 
1529  // redraw the area where the pad was
1531 
1532  commit.Push( _( "Modify pad" ) );
1533 
1534  if( rastnestIsChanged ) // The net ratsnest must be recalculated
1535  m_board->m_Status_Pcb = 0;
1536 
1537  return true;
1538 }
1539 
1540 
1542 {
1543  wxString msg;
1544  int x, y;
1545 
1546  if( !Validate() )
1547  return true;
1548  if( !m_panelGeneral->Validate() )
1549  return true;
1550  if( !m_localSettingsPanel->Validate() )
1551  return true;
1552 
1553  m_OrientValidator.TransferFromWindow();
1554 
1555  aPad->SetAttribute( code_type[m_PadType->GetSelection()] );
1556  aPad->SetShape( code_shape[m_PadShape->GetSelection()] );
1559 
1560  if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
1561  aPad->SetPrimitives( m_primitives );
1562 
1563  // Read pad clearances values:
1569  double dtmp = 0.0;
1570  msg = m_SolderPasteMarginRatioCtrl->GetValue();
1571  msg.ToDouble( &dtmp );
1572 
1573  // A -50% margin ratio means no paste on a pad, the ratio must be >= -50%
1574  if( dtmp < -50.0 )
1575  dtmp = -50.0;
1576  // A margin ratio is always <= 0
1577  // 0 means use full pad copper area
1578  if( dtmp > 0.0 )
1579  dtmp = 0.0;
1580 
1581  aPad->SetLocalSolderPasteMarginRatio( dtmp / 100 );
1582 
1583  switch( m_ZoneConnectionChoice->GetSelection() )
1584  {
1585  default:
1586  case 0:
1588  break;
1589 
1590  case 1:
1592  break;
1593 
1594  case 2:
1596  break;
1597 
1598  case 3:
1600  break;
1601  }
1602 
1603  // Custom shape has only 2 options:
1604  if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
1605  {
1606  if( m_ZoneConnectionCustom->GetSelection() == 0 )
1608  else
1610  }
1611 
1612  // Read pad position:
1615 
1616  aPad->SetPosition( wxPoint( x, y ) );
1617  aPad->SetPos0( wxPoint( x, y ) );
1618 
1619  // Read pad drill:
1622 
1623  if( m_DrillShapeCtrl->GetSelection() == 0 )
1624  {
1626  y = x;
1627  }
1628  else
1630 
1631  aPad->SetDrillSize( wxSize( x, y ) );
1632 
1633  // Read pad shape size:
1636 
1637  if( aPad->GetShape() == PAD_SHAPE_CIRCLE )
1638  y = x;
1639 
1640  // for custom shped pads, the pad size is the anchor pad size:
1641  if( aPad->GetShape() == PAD_SHAPE_CUSTOM && aPad->GetAnchorPadShape() == PAD_SHAPE_CIRCLE )
1642  y = x;
1643 
1644  aPad->SetSize( wxSize( x, y ) );
1645 
1646  // Read pad length die
1648 
1649  // For a trapezoid, test delta value (be sure delta is not too large for pad size)
1650  // remember DeltaSize.x is the Y size variation
1651  bool error = false;
1652 
1653  if( aPad->GetShape() == PAD_SHAPE_TRAPEZOID )
1654  {
1655  wxSize delta;
1656 
1657  // For a trapezoid, only one of delta.x or delta.y is not 0, depending on
1658  // the direction.
1659  if( m_trapDeltaDirChoice->GetSelection() == 0 )
1660  delta.x = ValueFromTextCtrl( *m_ShapeDelta_Ctrl );
1661  else
1662  delta.y = ValueFromTextCtrl( *m_ShapeDelta_Ctrl );
1663 
1664  if( delta.x < 0 && delta.x <= -aPad->GetSize().y )
1665  {
1666  delta.x = -aPad->GetSize().y + 2;
1667  error = true;
1668  }
1669 
1670  if( delta.x > 0 && delta.x >= aPad->GetSize().y )
1671  {
1672  delta.x = aPad->GetSize().y - 2;
1673  error = true;
1674  }
1675 
1676  if( delta.y < 0 && delta.y <= -aPad->GetSize().x )
1677  {
1678  delta.y = -aPad->GetSize().x + 2;
1679  error = true;
1680  }
1681 
1682  if( delta.y > 0 && delta.y >= aPad->GetSize().x )
1683  {
1684  delta.y = aPad->GetSize().x - 2;
1685  error = true;
1686  }
1687 
1688  aPad->SetDelta( delta );
1689  }
1690 
1691  // Read pad shape offset:
1694  aPad->SetOffset( wxPoint( x, y ) );
1695 
1696  aPad->SetOrientation( m_OrientValue * 10.0 );
1697  aPad->SetName( m_PadNumCtrl->GetValue() );
1698 
1699  // Check if user has set an existing net name
1700  const NETINFO_ITEM* netinfo = m_board->FindNet( m_PadNetNameCtrl->GetValue() );
1701 
1702  if( netinfo != NULL )
1703  aPad->SetNetCode( netinfo->GetNet() );
1704  else
1706 
1707  // Clear some values, according to the pad type and shape
1708  switch( aPad->GetShape() )
1709  {
1710  case PAD_SHAPE_CIRCLE:
1711  aPad->SetOffset( wxPoint( 0, 0 ) );
1712  aPad->SetDelta( wxSize( 0, 0 ) );
1713  x = aPad->GetSize().x;
1714  aPad->SetSize( wxSize( x, x ) );
1715  break;
1716 
1717  case PAD_SHAPE_RECT:
1718  aPad->SetDelta( wxSize( 0, 0 ) );
1719  break;
1720 
1721  case PAD_SHAPE_OVAL:
1722  aPad->SetDelta( wxSize( 0, 0 ) );
1723  break;
1724 
1725  case PAD_SHAPE_TRAPEZOID:
1726  break;
1727 
1728  case PAD_SHAPE_ROUNDRECT:
1729  aPad->SetDelta( wxSize( 0, 0 ) );
1730  break;
1731 
1732  case PAD_SHAPE_CUSTOM:
1733  aPad->SetOffset( wxPoint( 0, 0 ) );
1734  aPad->SetDelta( wxSize( 0, 0 ) );
1735 
1736  // The pad custom has a "anchor pad" (a basic shape: round or rect pad)
1737  // that is the minimal area of this pad, and is usefull to ensure a hole
1738  // diameter is acceptable, and is used in Gerber files as flashed area
1739  // reference
1740  if( aPad->GetAnchorPadShape() == PAD_SHAPE_CIRCLE )
1741  {
1742  x = aPad->GetSize().x;
1743  aPad->SetSize( wxSize( x, x ) );
1744  }
1745 
1746  // define the way the clearance area is defined in zones
1747  aPad->SetCustomShapeInZoneOpt( m_ZoneCustomPadShape->GetSelection() == 0 ?
1750 
1751  break;
1752 
1753  default:
1754  ;
1755  }
1756 
1757  switch( aPad->GetAttribute() )
1758  {
1759  case PAD_ATTRIB_STANDARD:
1760  break;
1761 
1762  case PAD_ATTRIB_CONN:
1763  case PAD_ATTRIB_SMD:
1764  // SMD and PAD_ATTRIB_CONN has no hole.
1765  // basically, SMD and PAD_ATTRIB_CONN are same type of pads
1766  // PAD_ATTRIB_CONN has just a default non technical layers that differs from SMD
1767  // and are intended to be used in virtual edge board connectors
1768  // However we can accept a non null offset,
1769  // mainly to allow complex pads build from a set of basic pad shapes
1770  aPad->SetDrillSize( wxSize( 0, 0 ) );
1771  break;
1772 
1774  // Mechanical purpose only:
1775  // no offset, no net name, no pad name allowed
1776  aPad->SetOffset( wxPoint( 0, 0 ) );
1777  aPad->SetName( wxEmptyString );
1779  break;
1780 
1781  default:
1782  DisplayError( NULL, wxT( "Error: unknown pad type" ) );
1783  break;
1784  }
1785 
1786  if( aPad->GetShape() == PAD_SHAPE_ROUNDRECT )
1787  {
1788  wxString value = m_tcCornerSizeRatio->GetValue();
1789  double rrRadiusRatioPercent;
1790 
1791  if( value.ToDouble( &rrRadiusRatioPercent ) )
1792  aPad->SetRoundRectRadiusRatio( rrRadiusRatioPercent / 100.0 );
1793  }
1794 
1795  LSET padLayerMask;
1796 
1797  switch( m_rbCopperLayersSel->GetSelection() )
1798  {
1799  case 0:
1800  padLayerMask.set( F_Cu );
1801  break;
1802 
1803  case 1:
1804  padLayerMask.set( B_Cu );
1805  break;
1806 
1807  case 2:
1808  padLayerMask |= LSET::AllCuMask();
1809  break;
1810 
1811  case 3: // No copper layers
1812  break;
1813  }
1814 
1815  if( m_PadLayerAdhCmp->GetValue() )
1816  padLayerMask.set( F_Adhes );
1817 
1818  if( m_PadLayerAdhCu->GetValue() )
1819  padLayerMask.set( B_Adhes );
1820 
1821  if( m_PadLayerPateCmp->GetValue() )
1822  padLayerMask.set( F_Paste );
1823 
1824  if( m_PadLayerPateCu->GetValue() )
1825  padLayerMask.set( B_Paste );
1826 
1827  if( m_PadLayerSilkCmp->GetValue() )
1828  padLayerMask.set( F_SilkS );
1829 
1830  if( m_PadLayerSilkCu->GetValue() )
1831  padLayerMask.set( B_SilkS );
1832 
1833  if( m_PadLayerMaskCmp->GetValue() )
1834  padLayerMask.set( F_Mask );
1835 
1836  if( m_PadLayerMaskCu->GetValue() )
1837  padLayerMask.set( B_Mask );
1838 
1839  if( m_PadLayerECO1->GetValue() )
1840  padLayerMask.set( Eco1_User );
1841 
1842  if( m_PadLayerECO2->GetValue() )
1843  padLayerMask.set( Eco2_User );
1844 
1845  if( m_PadLayerDraft->GetValue() )
1846  padLayerMask.set( Dwgs_User );
1847 
1848  aPad->SetLayerSet( padLayerMask );
1849 
1850  return error;
1851 }
1852 
1853 
1854 void DIALOG_PAD_PROPERTIES::OnValuesChanged( wxCommandEvent& event )
1855 {
1856  if( m_canUpdate )
1857  {
1859  // If the pad size has changed, update the displayed values
1860  // for rounded rect pads
1862 
1863  redraw();
1864  }
1865 }
1866 
1868 {
1869  long select = m_listCtrlPrimitives->GetFirstSelected();
1870 
1871  if( select < 0 )
1872  {
1873  wxMessageBox( _( "No shape selected" ) );
1874  return;
1875  }
1876 
1877  PAD_CS_PRIMITIVE& shape = m_primitives[select];
1878 
1879  if( shape.m_Shape == S_POLYGON )
1880  {
1881  DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, &shape );
1882 
1883  if( dlg.ShowModal() != wxID_OK )
1884  return;
1885 
1886  dlg.TransferDataFromWindow();
1887  }
1888 
1889  else
1890  {
1891  DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, &shape );
1892 
1893  if( dlg.ShowModal() != wxID_OK )
1894  return;
1895 
1896  dlg.TransferDataFromWindow();
1897  }
1898 
1900 
1901  if( m_canUpdate )
1902  {
1904  redraw();
1905  }
1906 }
1907 
1908 
1910 {
1911  // Called on a double click on the basic shapes list
1912  // To Do: highligth the primitive(s) currently selected.
1913  redraw();
1914 }
1915 
1916 
1918 void DIALOG_PAD_PROPERTIES::onPrimitiveDClick( wxMouseEvent& event )
1919 {
1920  editPrimitive();
1921 }
1922 
1923 
1924 // Called on a click on basic shapes list panel button
1925 void DIALOG_PAD_PROPERTIES::onEditPrimitive( wxCommandEvent& event )
1926 {
1927  editPrimitive();
1928 }
1929 
1930 // Called on a click on basic shapes list panel button
1931 void DIALOG_PAD_PROPERTIES::onDeletePrimitive( wxCommandEvent& event )
1932 {
1933  long select = m_listCtrlPrimitives->GetFirstSelected();
1934 
1935  if( select < 0 )
1936  return;
1937 
1938  // Multiple selections are allowed. get them and remove corresponding shapes
1939  std::vector<long> indexes;
1940  indexes.push_back( select );
1941 
1942  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
1943  indexes.push_back( select );
1944 
1945  // Erase all select shapes
1946  for( unsigned ii = indexes.size(); ii > 0; --ii )
1947  m_primitives.erase( m_primitives.begin() + indexes[ii-1] );
1948 
1950 
1951  if( m_canUpdate )
1952  {
1954  redraw();
1955  }
1956 }
1957 
1958 
1959 void DIALOG_PAD_PROPERTIES::onAddPrimitive( wxCommandEvent& event )
1960 {
1961  // Ask user for shape type
1962  wxString shapelist[] =
1963  {
1964  _( "Segment" ), _( "Arc" ), _( "ring/circle" ), _( "polygon" )
1965  };
1966 
1967  int type = wxGetSingleChoiceIndex( wxEmptyString, _( "Select shape type:" ),
1968  DIM( shapelist ), shapelist, 0, this );
1969 
1970  STROKE_T listtype[] =
1971  {
1973  };
1974 
1975  PAD_CS_PRIMITIVE primitive( listtype[type] );
1976 
1977  if( listtype[type] == S_POLYGON )
1978  {
1979  DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, &primitive );
1980 
1981  if( dlg.ShowModal() != wxID_OK )
1982  return;
1983  }
1984  else
1985  {
1986  DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, &primitive );
1987 
1988  if( dlg.ShowModal() != wxID_OK )
1989  return;
1990  }
1991 
1992  m_primitives.push_back( primitive );
1993 
1995 
1996  if( m_canUpdate )
1997  {
1999  redraw();
2000  }
2001 }
2002 
2003 
2004 void DIALOG_PAD_PROPERTIES::onImportPrimitives( wxCommandEvent& event )
2005 {
2006  wxMessageBox( "Not yet available" );
2007 }
2008 
2009 
2010 void DIALOG_PAD_PROPERTIES::onGeometryTransform( wxCommandEvent& event )
2011 {
2012  long select = m_listCtrlPrimitives->GetFirstSelected();
2013 
2014  if( select < 0 )
2015  {
2016  wxMessageBox( _( "No shape selected" ) );
2017  return;
2018  }
2019 
2020  // Multiple selections are allowed. Build selected shapes list
2021  std::vector<PAD_CS_PRIMITIVE*> shapeList;
2022  shapeList.push_back( &m_primitives[select] );
2023 
2024  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2025  shapeList.push_back( &m_primitives[select] );
2026 
2027  DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, shapeList, false );
2028 
2029  if( dlg.ShowModal() != wxID_OK )
2030  return;
2031 
2032  // Transfert new settings:
2033  dlg.Transform();
2034 
2036 
2037  if( m_canUpdate )
2038  {
2040  redraw();
2041  }
2042 }
2043 
2044 
2045 void DIALOG_PAD_PROPERTIES::onDuplicatePrimitive( wxCommandEvent& event )
2046 {
2047  long select = m_listCtrlPrimitives->GetFirstSelected();
2048 
2049  if( select < 0 )
2050  {
2051  wxMessageBox( _( "No shape selected" ) );
2052  return;
2053  }
2054 
2055  // Multiple selections are allowed. Build selected shapes list
2056  std::vector<PAD_CS_PRIMITIVE*> shapeList;
2057  shapeList.push_back( &m_primitives[select] );
2058 
2059  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2060  shapeList.push_back( &m_primitives[select] );
2061 
2062  DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, shapeList, true );
2063 
2064  if( dlg.ShowModal() != wxID_OK )
2065  return;
2066 
2067  // Transfer new settings
2068  // save duplicates to a separate vector to avoid m_primitives reallocation,
2069  // as shapeList contains pointers to its elements
2070  std::vector<PAD_CS_PRIMITIVE> duplicates;
2071  dlg.Transform( &duplicates, dlg.GetDuplicateCount() );
2072  std::move( duplicates.begin(), duplicates.end(), std::back_inserter( m_primitives ) );
2073 
2075 
2076  if( m_canUpdate )
2077  {
2079  redraw();
2080  }
2081 }
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:359
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:524
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:633
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:1340
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:482
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:831
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:599
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:670
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:681
void OnResize(wxSizeEvent &event)
void OnPadShapeSelection(wxCommandEvent &event) override
void PadTypeSelected(wxCommandEvent &event) override
int GetThermalGap() const
Definition: class_pad.cpp:692
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:485
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:895
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 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: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:621
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:903
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:488
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:239
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)