KiCad PCB EDA Suite
dialog_pad_properties.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2013 Dick Hollenbeck, [email protected]
6  * Copyright (C) 2008-2013 Wayne Stambaugh <[email protected]>
7  * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, you may find one here:
21  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22  * or you may search the http://www.gnu.org website for the version 2 license,
23  * or you may write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26 
27 #include <base_units.h>
28 #include <bitmaps.h>
29 #include <board_commit.h>
30 #include <board.h>
31 #include <board_design_settings.h>
32 #include <footprint.h>
33 #include <confirm.h>
34 #include <core/arraydim.h>
35 #include <convert_basic_shapes_to_polygon.h> // for enum RECT_CHAMFER_POSITIONS definition
36 #include <geometry/shape_segment.h>
37 #include <dialog_pad_properties.h>
40 #include <macros.h>
41 #include <pad.h>
42 #include <pcb_base_frame.h>
43 #include <footprint_edit_frame.h>
44 #include <pcb_painter.h>
45 #include <pcbnew_settings.h>
47 #include <view/view_controls.h>
48 #include <widgets/net_selector.h>
49 #include <tool/tool_manager.h>
50 #include <tools/pad_tool.h>
51 #include <advanced_config.h> // for pad property feature management
52 #include <wx/choicdlg.h>
53 
54 
55 // list of pad shapes, ordered like the pad shape wxChoice in dialog.
57 {
64  PAD_SHAPE::CHAMFERED_RECT, // choice = CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT
65  PAD_SHAPE::CUSTOM, // choice = CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
66  PAD_SHAPE::CUSTOM // choice = PAD_SHAPE::CUSTOM_RECT_ANCHOR
67 };
68 
69 
70 // the ordered index of the pad shape wxChoice in dialog.
71 // keep it consistent with code_shape[] and dialog strings
73 {
83 };
84 
85 
87 {
92  PAD_ATTRIB::SMD // Aperture pad :type SMD with no copper layers,
93  // only on tech layers (usually only on paste layer
94 };
95 
96 
97 // These define have the same value as the m_PadType wxChoice GetSelected() return value
98 #define PTH_DLG_TYPE 0
99 #define SMD_DLG_TYPE 1
100 #define CONN_DLG_TYPE 2
101 #define NPTH_DLG_TYPE 3
102 #define APERTURE_DLG_TYPE 4
103 
104 
106 {
107  DIALOG_PAD_PROPERTIES dlg( this, aPad );
108 
109  dlg.ShowQuasiModal();
110 }
111 
112 
114  DIALOG_PAD_PROPERTIES_BASE( aParent ),
115  m_parent( aParent ),
116  m_canUpdate( false ),
117  m_posX( aParent, m_posXLabel, m_posXCtrl, m_posXUnits ),
118  m_posY( aParent, m_posYLabel, m_posYCtrl, m_posYUnits ),
119  m_sizeX( aParent, m_sizeXLabel, m_sizeXCtrl, m_sizeXUnits ),
120  m_sizeY( aParent, m_sizeYLabel, m_sizeYCtrl, m_sizeYUnits ),
121  m_offsetX( aParent, m_offsetXLabel, m_offsetXCtrl, m_offsetXUnits ),
122  m_offsetY( aParent, m_offsetYLabel, m_offsetYCtrl, m_offsetYUnits ),
123  m_padToDie( aParent, m_padToDieLabel, m_padToDieCtrl, m_padToDieUnits ),
124  m_trapDelta( aParent, m_trapDeltaLabel, m_trapDeltaCtrl, m_trapDeltaUnits ),
125  m_cornerRadius( aParent, m_cornerRadiusLabel, m_cornerRadiusCtrl, m_cornerRadiusUnits ),
126  m_cornerRatio( aParent, m_cornerRatioLabel, m_cornerRatioCtrl, m_cornerRatioUnits ),
127  m_chamferRatio( aParent, m_chamferRatioLabel, m_chamferRatioCtrl, m_chamferRatioUnits ),
128  m_mixedCornerRatio( aParent, m_mixedCornerRatioLabel, m_mixedCornerRatioCtrl,
129  m_mixedCornerRatioUnits ),
130  m_mixedChamferRatio( aParent, m_mixedChamferRatioLabel, m_mixedChamferRatioCtrl,
131  m_mixedChamferRatioUnits ),
132  m_holeX( aParent, m_holeXLabel, m_holeXCtrl, m_holeXUnits ),
133  m_holeY( aParent, m_holeYLabel, m_holeYCtrl, m_holeYUnits ),
134  m_OrientValidator( 3, &m_OrientValue ),
135  m_clearance( aParent, m_clearanceLabel, m_clearanceCtrl, m_clearanceUnits ),
136  m_maskMargin( aParent, m_maskMarginLabel, m_maskMarginCtrl, m_maskMarginUnits ),
137  m_pasteMargin( aParent, m_pasteMarginLabel, m_pasteMarginCtrl, m_pasteMarginUnits ),
138  m_pasteMarginRatio( aParent, m_pasteMarginRatioLabel, m_pasteMarginRatioCtrl,
139  m_pasteMarginRatioUnits ),
140  m_spokeWidth( aParent, m_spokeWidthLabel, m_spokeWidthCtrl, m_spokeWidthUnits ),
141  m_thermalGap( aParent, m_thermalGapLabel, m_thermalGapCtrl, m_thermalGapUnits )
142 {
143  SetName( PAD_PROPERTIES_DLG_NAME );
144  m_isFpEditor = dynamic_cast<FOOTPRINT_EDIT_FRAME*>( aParent ) != nullptr;
145 
146  m_currentPad = aPad; // aPad can be NULL, if the dialog is called
147  // from the footprint editor to set default pad setup
148 
150 
151  // Configure display origin transforms
154 
157 
158  m_OrientValidator.SetRange( -360.0, 360.0 );
159  m_orientation->SetValidator( m_OrientValidator );
160  m_OrientValidator.SetWindow( m_orientation );
161 
162  m_cbShowPadOutline->SetValue( m_sketchPreview );
163 
166 
168  m_dummyPad = new PAD( (FOOTPRINT*) nullptr );
169 
170  if( aPad )
171  {
172  SetTitle( _( "Pad Properties" ) );
173 
174  *m_dummyPad = *aPad;
176  }
177  else
178  {
179  SetTitle( _( "Default Pad Properties for Add Pad Tool" ) );
180 
182  }
183 
184  if( m_isFpEditor )
185  {
186  m_padNetLabel->Show( false );
187  m_padNetSelector->Show( false );
188  }
189 
190  // Pad needs to have a parent for painting; use the parent board for its design settings
191  if( !m_dummyPad->GetParent() )
193 
198 
200 
203 
204  initValues();
205 
206  wxFont infoFont = KIUI::GetInfoFont( this );
207  m_copperLayersLabel->SetFont( infoFont );
208  m_techLayersLabel->SetFont( infoFont );
209  m_parentInfo->SetFont( infoFont );
210 
211  infoFont.SetStyle( wxFONTSTYLE_ITALIC );
212  m_nonCopperNote->SetFont( infoFont );
213  m_staticTextInfoPaste->SetFont( infoFont );
214  m_staticTextInfoNegVal->SetFont( infoFont );
215  m_staticTextInfoPosValue->SetFont( infoFont );
216  m_staticTextPrimitiveListWarning->SetFont( infoFont );
217 
218  // Do not allow locking items in the footprint editor
219  m_locked->Show( !m_isFpEditor );
220 
221  // Usually, TransferDataToWindow is called by OnInitDialog
222  // calling it here fixes all widget sizes so FinishDialogSettings can safely fix minsizes
224 
225  // Initialize canvas to be able to display the dummy pad:
226  prepareCanvas();
227 
229  m_sdbSizerOK->SetDefault();
230  m_canUpdate = true;
231 
232  m_padNetSelector->Connect( NET_SELECTED,
233  wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ),
234  nullptr, this );
235 
236  // Now all widgets have the size fixed, call FinishDialogSettings
238 
239  wxUpdateUIEvent dummy;
240  OnUpdateUI( dummy );
241 }
242 
243 
245 {
246  m_padNetSelector->Disconnect( NET_SELECTED,
247  wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ),
248  nullptr, this );
249 
250  delete m_dummyPad;
251  delete m_axisOrigin;
252 }
253 
254 
255 // Store the pad draw option during a session.
257 
258 
259 void DIALOG_PAD_PROPERTIES::OnInitDialog( wxInitDialogEvent& event )
260 {
261  m_selectedColor = COLOR4D( 1.0, 1.0, 1.0, 0.7 );
262 
263  // Needed on some WM to be sure the pad is redrawn according to the final size
264  // of the canvas, with the right zoom factor
265  redraw();
266 }
267 
268 
269 void DIALOG_PAD_PROPERTIES::OnCancel( wxCommandEvent& event )
270 {
271  // Mandatory to avoid m_panelShowPadGal trying to draw something
272  // in a non valid context during closing process:
274 
275  // Now call default handler for wxID_CANCEL command event
276  event.Skip();
277 }
278 
279 
281 {
282  // Enable or disable the widgets in page managing custom shape primitives
283  m_listCtrlPrimitives->Enable( aEnable );
284  m_buttonDel->Enable( aEnable );
285  m_buttonEditShape->Enable( aEnable );
286  m_buttonAddShape->Enable( aEnable );
287  m_buttonDup->Enable( aEnable );
288  m_buttonGeometry->Enable( aEnable );
289 }
290 
291 
293 {
294  // Initialize the canvas to display the pad
295  m_padPreviewGAL = new PCB_DRAW_PANEL_GAL( m_boardViewPanel, -1, wxDefaultPosition,
296  wxDefaultSize,
298  m_parent->GetCanvas()->GetBackend() );
299 
300  m_padPreviewSizer->Add( m_padPreviewGAL, 12, wxEXPAND | wxALL, 5 );
301 
302  // Show the X and Y axis. It is useful because pad shape can have an offset
303  // or be a complex shape.
304  KIGFX::COLOR4D axis_color = LIGHTBLUE;
305 
307  Millimeter2iu( 0.2 ),
309  m_axisOrigin->SetDrawAtZero( true );
310 
313  m_padPreviewGAL->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
314 
315  KIGFX::VIEW_CONTROLS* parentViewControls = m_parent->GetCanvas()->GetViewControls();
316  m_padPreviewGAL->GetViewControls()->ApplySettings( parentViewControls->GetSettings() );
317 
318  m_padPreviewGAL->Show();
319 
321 
322  // fix the pad render mode (filled/not filled)
323  auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
324  bool sketchMode = m_cbShowPadOutline->IsChecked();
325  settings->SetSketchMode( LAYER_PADS_TH, sketchMode );
326  settings->SetSketchMode( LAYER_PAD_FR, sketchMode );
327  settings->SetSketchMode( LAYER_PAD_BK, sketchMode );
328  settings->SetSketchModeGraphicItems( sketchMode );
329 
330  settings->SetHighContrast( false );
331  settings->SetContrastModeDisplay( HIGH_CONTRAST_MODE::NORMAL );
332 
333  // gives a non null grid size (0.001mm) because GAL layer does not like a 0 size grid:
334  double gridsize = 0.001 * IU_PER_MM;
335  view->GetGAL()->SetGridSize( VECTOR2D( gridsize, gridsize ) );
336 
337  // And do not show the grid:
338  view->GetGAL()->SetGridVisibility( false );
339  view->Add( m_dummyPad );
340  view->Add( m_axisOrigin );
341 
343  Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_PAD_PROPERTIES::OnResize ) );
344 }
345 
346 
348 {
349  // Note: use ChangeValue() to avoid generating a wxEVT_TEXT event
350 
353 
356 }
357 
358 
359 void DIALOG_PAD_PROPERTIES::onCornerRadiusChange( wxCommandEvent& event )
360 {
363  {
364  return;
365  }
366 
367  if( m_cornerRadius.GetValue() < 0 )
368  m_cornerRadiusCtrl->ChangeValue( "0" );
369 
372 
375 
376  redraw();
377 }
378 
379 
381 {
384  {
385  return;
386  }
387 
388  wxObject* ctrl = event.GetEventObject();
389  wxString value = event.GetString();
390  bool changed = false;
391 
392  if( ctrl == m_cornerRatioCtrl || ctrl == m_mixedCornerRatioCtrl )
393  {
394  double ratioPercent;
395 
396  if( value.ToDouble( &ratioPercent ) )
397  {
398  // Clamp ratioPercent to acceptable value (0.0 to 50.0)
399  if( ratioPercent < 0.0 )
400  {
403  }
404  else if( ratioPercent > 50.0 )
405  {
408  }
409 
410  if( ctrl == m_cornerRatioCtrl )
411  m_mixedCornerRatioCtrl->ChangeValue( value );
412  else
413  m_cornerRatioCtrl->ChangeValue( value );
414 
415  changed = true;
416  }
417  }
418  else if( ctrl == m_chamferRatioCtrl || ctrl == m_mixedChamferRatioCtrl )
419  {
420  double ratioPercent;
421 
422  if( value.ToDouble( &ratioPercent ) )
423  {
424  // Clamp ratioPercent to acceptable value (0.0 to 50.0)
425  if( ratioPercent < 0.0 )
426  {
429  }
430  else if( ratioPercent > 50.0 )
431  {
434  }
435 
436  if( ctrl == m_chamferRatioCtrl )
437  m_mixedChamferRatioCtrl->ChangeValue( value );
438  else
439  m_chamferRatioCtrl->ChangeValue( value );
440 
441  changed = true;
442  }
443  }
444 
445  if( changed )
446  {
449  }
450 
451  redraw();
452 }
453 
454 
456 {
457  wxString msg;
458  double angle;
459 
460  // Disable pad net name wxTextCtrl if the caller is the footprint editor
461  // because nets are living only in the board managed by the board editor
463 
464  m_PadLayerAdhCmp->SetLabel( m_board->GetLayerName( F_Adhes ) );
465  m_PadLayerAdhCu->SetLabel( m_board->GetLayerName( B_Adhes ) );
467  m_PadLayerPateCu->SetLabel( m_board->GetLayerName( B_Paste ) );
469  m_PadLayerSilkCu->SetLabel( m_board->GetLayerName( B_SilkS ) );
470  m_PadLayerMaskCmp->SetLabel( m_board->GetLayerName( F_Mask ) );
471  m_PadLayerMaskCu->SetLabel( m_board->GetLayerName( B_Mask ) );
472  m_PadLayerECO1->SetLabel( m_board->GetLayerName( Eco1_User ) );
473  m_PadLayerECO2->SetLabel( m_board->GetLayerName( Eco2_User ) );
475 
476  if( m_currentPad )
477  {
478  m_locked->SetValue( m_currentPad->IsLocked() );
480 
481  FOOTPRINT* footprint = m_currentPad->GetParent();
482 
483  if( footprint )
484  {
486  angle -= footprint->GetOrientation();
488 
489  // Display parent footprint info
490  msg.Printf( _("Footprint %s (%s), %s, rotated %g deg"),
491  footprint->Reference().GetShownText(),
492  footprint->Value().GetShownText(),
493  footprint->IsFlipped() ? _( "back side (mirrored)" ) : _( "front side" ),
494  footprint->GetOrientationDegrees() );
495  }
496 
497  m_parentInfo->SetLabel( msg );
498  }
499  else
500  {
501  m_locked->Hide();
502  m_isFlipped = false;
503  }
504 
505  if( m_isFlipped )
506  {
507  // flip pad (up/down) around its position
508  m_dummyPad->Flip( m_dummyPad->GetPosition(), false );
509  }
510 
512 
514 
515  if( m_currentPad )
516  {
517  m_padNumCtrl->SetValue( m_dummyPad->GetNumber() );
518  }
519  else
520  {
521  PAD_TOOL* padTool = m_parent->GetToolManager()->GetTool<PAD_TOOL>();
522  m_padNumCtrl->SetValue( padTool->GetLastPadNumber() );
523  }
524 
526 
527  // Display current pad parameters units:
530 
533 
536 
537  m_offsetShapeOpt->SetValue( m_dummyPad->GetOffset() != wxPoint() );
540 
541  if( m_dummyPad->GetDelta().x )
542  {
544  m_trapAxisCtrl->SetSelection( 0 );
545  }
546  else
547  {
549  m_trapAxisCtrl->SetSelection( 1 );
550  }
551 
552  m_padToDieOpt->SetValue( m_dummyPad->GetPadToDieLength() != 0 );
554 
561 
562  switch( m_dummyPad->GetZoneConnection() )
563  {
564  default:
565  case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
566  case ZONE_CONNECTION::FULL: m_ZoneConnectionChoice->SetSelection( 1 ); break;
567  case ZONE_CONNECTION::THERMAL: m_ZoneConnectionChoice->SetSelection( 2 ); break;
568  case ZONE_CONNECTION::NONE: m_ZoneConnectionChoice->SetSelection( 3 ); break;
569  }
570 
572  m_ZoneCustomPadShape->SetSelection( 1 );
573  else
574  m_ZoneCustomPadShape->SetSelection( 0 );
575 
578 
579  // Pad Orient
580  // Note: use ChangeValue() instead of SetValue() so that we don't generate events
582 
583  switch( m_dummyPad->GetShape() )
584  {
585  default:
586  case PAD_SHAPE::CIRCLE: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_CIRCLE ); break;
587  case PAD_SHAPE::OVAL: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_OVAL ); break;
588  case PAD_SHAPE::RECT: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_RECT ); break;
589  case PAD_SHAPE::TRAPEZOID: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_TRAPEZOID ); break;
590  case PAD_SHAPE::ROUNDRECT: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_ROUNDRECT ); break;
591 
593  if( m_dummyPad->GetRoundRectRadiusRatio() > 0.0 )
595  else
597  break;
598 
599  case PAD_SHAPE::CUSTOM:
602  else
604  break;
605  }
606 
615 
617 
619 
620  // Type of pad selection
621  bool aperture = m_dummyPad->GetAttribute() == PAD_ATTRIB::SMD && m_dummyPad->IsAperturePad();
622 
623  if( aperture )
624  {
625  m_padType->SetSelection( APERTURE_DLG_TYPE );
626  }
627  else
628  {
629  switch( m_dummyPad->GetAttribute() )
630  {
631  case PAD_ATTRIB::PTH: m_padType->SetSelection( PTH_DLG_TYPE ); break;
632  case PAD_ATTRIB::SMD: m_padType->SetSelection( SMD_DLG_TYPE ); break;
633  case PAD_ATTRIB::CONN: m_padType->SetSelection( CONN_DLG_TYPE ); break;
634  case PAD_ATTRIB::NPTH: m_padType->SetSelection( NPTH_DLG_TYPE ); break;
635  }
636  }
637 
638  switch( m_dummyPad->GetProperty() )
639  {
640  case PAD_PROP::NONE: m_choiceFabProperty->SetSelection( 0 ); break;
641  case PAD_PROP::BGA: m_choiceFabProperty->SetSelection( 1 ); break;
642  case PAD_PROP::FIDUCIAL_LOCAL: m_choiceFabProperty->SetSelection( 2 ); break;
643  case PAD_PROP::FIDUCIAL_GLBL: m_choiceFabProperty->SetSelection( 3 ); break;
644  case PAD_PROP::TESTPOINT: m_choiceFabProperty->SetSelection( 4 ); break;
645  case PAD_PROP::HEATSINK: m_choiceFabProperty->SetSelection( 5 ); break;
646  case PAD_PROP::CASTELLATED: m_choiceFabProperty->SetSelection( 6 ); break;
647  }
648 
649  // Ensure the pad property is compatible with the pad type
651  {
652  m_choiceFabProperty->SetSelection( 0 );
653  m_choiceFabProperty->Enable( false );
654  }
655 
657  m_holeShapeCtrl->SetSelection( 0 );
658  else
659  m_holeShapeCtrl->SetSelection( 1 );
660 
663 
664  // Update some dialog widgets state (Enable/disable options):
665  wxCommandEvent cmd_event;
666  OnPadShapeSelection( cmd_event );
667  OnOffsetCheckbox( cmd_event );
668 
669  // Update basic shapes list
671 }
672 
673 // A small helper function, to display coordinates:
674 static wxString formatCoord( EDA_UNITS aUnits, wxPoint aCoord )
675 {
676  return wxString::Format( "(X:%s Y:%s)",
677  MessageTextFromValue( aUnits, aCoord.x ),
678  MessageTextFromValue( aUnits, aCoord.y ) );
679 }
680 
682 {
683  m_listCtrlPrimitives->ClearAll();
684 
685  wxListItem itemCol;
686  itemCol.SetImage(-1);
687 
688  for( int ii = 0; ii < 5; ++ii )
689  m_listCtrlPrimitives->InsertColumn(ii, itemCol);
690 
691  wxString bs_info[5];
692 
693  for( unsigned ii = 0; ii < m_primitives.size(); ++ii )
694  {
695  const std::shared_ptr<PCB_SHAPE>& primitive = m_primitives[ii];
696 
697  for( wxString& s : bs_info )
698  s.Empty();
699 
700  bs_info[4] = _( "width" ) + wxS( " " )+ MessageTextFromValue( m_units,
701  primitive->GetWidth() );
702 
703  switch( primitive->GetShape() )
704  {
705  case SHAPE_T::SEGMENT:
706  bs_info[0] = _( "Segment" );
707  bs_info[1] = _( "from" ) + wxS( " " )+ formatCoord( m_units, primitive->GetStart() );
708  bs_info[2] = _( "to" ) + wxS( " " )+ formatCoord( m_units, primitive->GetEnd() );
709  break;
710 
711  case SHAPE_T::BEZIER:
712  bs_info[0] = _( "Bezier" );
713  bs_info[1] = _( "from" ) + wxS( " " )+ formatCoord( m_units, primitive->GetStart() );
714  bs_info[2] = _( "to" ) + wxS( " " )+ formatCoord( m_units, primitive->GetEnd() );
715  break;
716 
717  case SHAPE_T::ARC:
718  bs_info[0] = _( "Arc" );
719  bs_info[1] = _( "center" ) + wxS( " " )+ formatCoord( m_units, primitive->GetCenter() );
720  bs_info[2] = _( "start" ) + wxS( " " )+ formatCoord( m_units, primitive->GetStart() );
721  bs_info[3] = _( "angle" ) + wxS( " " )+ FormatAngle( primitive->GetArcAngle() );
722  break;
723 
724  case SHAPE_T::CIRCLE:
725  if( primitive->GetWidth() )
726  bs_info[0] = _( "ring" );
727  else
728  bs_info[0] = _( "circle" );
729 
730  bs_info[1] = formatCoord( m_units, primitive->GetStart() );
731  bs_info[2] = _( "radius" ) + wxS( " " )+ MessageTextFromValue( m_units,
732  primitive->GetRadius() );
733  break;
734 
735  case SHAPE_T::POLY:
736  bs_info[0] = "Polygon";
737  bs_info[1] = wxString::Format( _( "corners count %d" ),
738  (int) primitive->GetPolyShape().Outline( 0 ).PointCount() );
739  break;
740 
741  default:
742  bs_info[0] = "Unknown primitive";
743  break;
744  }
745 
746  long tmp = m_listCtrlPrimitives->InsertItem( ii, bs_info[0] );
747  m_listCtrlPrimitives->SetItemData( tmp, ii );
748 
749  for( int jj = 0, col = 0; jj < 5; ++jj )
750  m_listCtrlPrimitives->SetItem( tmp, col++, bs_info[jj] );
751  }
752 
753  // Now columns are filled, ensure correct width of columns
754  for( unsigned ii = 0; ii < 5; ++ii )
755  m_listCtrlPrimitives->SetColumnWidth( ii, wxLIST_AUTOSIZE );
756 }
757 
758 
759 void DIALOG_PAD_PROPERTIES::OnResize( wxSizeEvent& event )
760 {
761  redraw();
762  event.Skip();
763 }
764 
765 
766 void DIALOG_PAD_PROPERTIES::onChangePadMode( wxCommandEvent& event )
767 {
768  m_sketchPreview = m_cbShowPadOutline->GetValue();
769 
771 
772  // fix the pad render mode (filled/not filled)
773  KIGFX::PCB_RENDER_SETTINGS* settings =
774  static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
775 
780 
781  settings->SetHighContrast( false );
783 
784  redraw();
785 }
786 
787 
788 void DIALOG_PAD_PROPERTIES::OnPadShapeSelection( wxCommandEvent& event )
789 {
790  switch( m_PadShapeSelector->GetSelection() )
791  {
792  case CHOICE_SHAPE_CIRCLE:
793  case CHOICE_SHAPE_OVAL:
794  case CHOICE_SHAPE_RECT:
795  m_shapePropsBook->SetSelection( 0 );
796  break;
797 
799  m_shapePropsBook->SetSelection( 1 );
800  break;
801 
803  {
804  m_shapePropsBook->SetSelection( 2 );
805 
806  // A reasonable default (from IPC-7351C)
807  if( m_dummyPad->GetRoundRectRadiusRatio() == 0.0 )
809 
810  break;
811  }
812 
814  m_shapePropsBook->SetSelection( 3 );
815 
816  // Reasonable default
817  if( m_dummyPad->GetChamferRectRatio() == 0.0 )
819 
820  // Ensure the displayed value is up to date:
822 
823  // A reasonable default is one corner chamfered (usual for some SMD pads).
824  if( !m_cbTopLeft->GetValue() && !m_cbTopRight->GetValue()
825  && !m_cbBottomLeft->GetValue() && !m_cbBottomRight->GetValue() )
826  {
827  m_cbTopLeft->SetValue( true );
828  m_cbTopRight->SetValue( false );
829  m_cbBottomLeft->SetValue( false );
830  m_cbBottomRight->SetValue( false );
831  }
832 
833  break;
834 
836  m_shapePropsBook->SetSelection( 4 );
837 
838  // Reasonable defaults (corner radius from IPC-7351C)
839  if( m_dummyPad->GetRoundRectRadiusRatio() == 0.0
840  && m_dummyPad->GetChamferRectRatio() == 0.0 )
841  {
842  if( m_dummyPad->GetRoundRectRadiusRatio() == 0.0 )
844 
845  if( m_dummyPad->GetChamferRectRatio() == 0.0 )
847  }
848 
849  // Ensure the displayed values are up to date:
852  break;
853 
854  case CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR: // PAD_SHAPE::CUSTOM, circular anchor
855  case CHOICE_SHAPE_CUSTOM_RECT_ANCHOR: // PAD_SHAPE::CUSTOM, rect anchor
856  m_shapePropsBook->SetSelection( 0 );
857  break;
858  }
859 
860  // Readjust props book size
861  wxSize size = m_shapePropsBook->GetSize();
862  size.y = m_shapePropsBook->GetPage( m_shapePropsBook->GetSelection() )->GetBestSize().y;
863  m_shapePropsBook->SetMaxSize( size );
864 
866  && m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR );
867 
868  m_offsetShapeOpt->Enable( m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CIRCLE
870  && m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CUSTOM_RECT_ANCHOR );
871 
872  if( !m_offsetShapeOpt->IsEnabled() )
873  m_offsetShapeOpt->SetValue( false );
874 
875  // Show/hide controls depending on m_offsetShapeOpt being enabled
876  m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
877  m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
878 
879  bool is_custom = m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
881 
882  enablePrimitivePage( is_custom );
883  m_staticTextcps->Enable( is_custom );
884  m_ZoneCustomPadShape->Enable( is_custom );
885 
887 
889 
890  for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
891  m_notebook->GetPage( i )->Layout();
892 
893  // Resize the dialog if its height is too small to show all widgets:
894  if( m_MainSizer->GetSize().y < m_MainSizer->GetMinSize().y )
895  m_MainSizer->SetSizeHints( this );
896 
897  redraw();
898 }
899 
900 
901 void DIALOG_PAD_PROPERTIES::OnDrillShapeSelected( wxCommandEvent& event )
902 {
904  redraw();
905 }
906 
907 
908 void DIALOG_PAD_PROPERTIES::PadOrientEvent( wxCommandEvent& event )
909 {
911  redraw();
912 }
913 
914 
916 {
917  m_rbCopperLayersSel->Clear();
918 
919  switch( m_padType->GetSelection() )
920  {
921  case PTH_DLG_TYPE:
922  m_rbCopperLayersSel->Append( _( "All copper layers" ) );
923  m_rbCopperLayersSel->Append( wxString::Format( _( "%s, %s and connected layers" ),
925  m_board->GetLayerName( B_Cu ) ) );
926  m_rbCopperLayersSel->Append( _( "Connected layers only" ) );
927  m_rbCopperLayersSel->Append( _( "None" ) );
928  break;
929 
930  case NPTH_DLG_TYPE:
931  m_rbCopperLayersSel->Append( wxString::Format( _( "%s and %s" ),
933  m_board->GetLayerName( B_Cu ) ) );
936  m_rbCopperLayersSel->Append( _( "None" ) );
937  break;
938 
939  case SMD_DLG_TYPE:
940  case CONN_DLG_TYPE:
943  break;
944 
945  case APERTURE_DLG_TYPE:
946  m_rbCopperLayersSel->Append( _( "None" ) );
947  break;
948  }
949 }
950 
951 
952 void DIALOG_PAD_PROPERTIES::PadTypeSelected( wxCommandEvent& event )
953 {
954  bool hasHole = true;
955  bool hasConnection = true;
956  bool hasProperty = true;
957 
958  switch( m_padType->GetSelection() )
959  {
960  case PTH_DLG_TYPE: hasHole = true; hasConnection = true; hasProperty = true; break;
961  case SMD_DLG_TYPE: hasHole = false; hasConnection = true; hasProperty = true; break;
962  case CONN_DLG_TYPE: hasHole = false; hasConnection = true; hasProperty = true; break;
963  case NPTH_DLG_TYPE: hasHole = true; hasConnection = false; hasProperty = false; break;
964  case APERTURE_DLG_TYPE: hasHole = false; hasConnection = false; hasProperty = true; break;
965  }
966 
967  // Update Layers dropdown list and selects the "best" layer set for the new pad type:
969 
970  if( !hasHole )
971  {
972  m_holeX.ChangeValue( 0 );
973  m_holeY.ChangeValue( 0 );
974  }
975  else if ( m_holeX.GetValue() == 0 && m_currentPad )
976  {
979  }
980 
981  if( !hasConnection )
982  {
983  m_padNumCtrl->ChangeValue( wxEmptyString );
985  m_padToDieOpt->SetValue( false );
986  }
987  else if( m_padNumCtrl->GetValue().IsEmpty() && m_currentPad )
988  {
989  m_padNumCtrl->ChangeValue( m_currentPad->GetNumber() );
991  }
992 
993  if( !hasProperty )
994  m_choiceFabProperty->SetSelection( 0 );
995 
996  m_choiceFabProperty->Enable( hasProperty );
997 
999 
1000  redraw();
1001 }
1002 
1003 
1004 void DIALOG_PAD_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
1005 {
1006  // Enable/disable position
1007  m_posX.Enable( !m_locked->GetValue() || m_isFpEditor );
1008  m_posY.Enable( !m_locked->GetValue() || m_isFpEditor );
1009 
1010  bool hasHole = true;
1011  bool hasConnection = true;
1012 
1013  switch( m_padType->GetSelection() )
1014  {
1015  case PTH_DLG_TYPE: /* PTH */ hasHole = true; hasConnection = true; break;
1016  case SMD_DLG_TYPE: /* SMD */ hasHole = false; hasConnection = true; break;
1017  case CONN_DLG_TYPE: /* CONN */ hasHole = false; hasConnection = true; break;
1018  case NPTH_DLG_TYPE: /* NPTH */ hasHole = true; hasConnection = false; break;
1019  case APERTURE_DLG_TYPE: /* Aperture */ hasHole = false; hasConnection = false; break;
1020  }
1021 
1022  // Enable/disable hole controls
1023  m_holeShapeLabel->Enable( hasHole );
1024  m_holeShapeCtrl->Enable( hasHole );
1025  m_holeX.Enable( hasHole );
1026  m_holeY.Enable( hasHole && m_holeShapeCtrl->GetSelection() == 1 );
1027 
1028  // Enable/disable number and net
1029  m_padNumLabel->Enable( hasConnection );
1030  m_padNumCtrl->Enable( hasConnection );
1031 
1032  if( m_padNetLabel->IsShown() )
1033  {
1034  m_padNetLabel->Enable( hasConnection && m_canEditNetName && m_currentPad );
1035  m_padNetSelector->Enable( hasConnection && m_canEditNetName && m_currentPad );
1036  }
1037 
1038  // Enable/disable pad length-to-die
1039  m_padToDieOpt->Enable( hasConnection );
1040 
1041  if( !m_padToDieOpt->IsEnabled() )
1042  m_padToDieOpt->SetValue( false );
1043 
1044  // We can show/hide this here because it doesn't require the layout to be refreshed.
1045  // All the others have to be done in their event handlers because doing a layout here
1046  // causes infinite looping on MSW.
1047  m_padToDie.Show( m_padToDieOpt->GetValue() );
1048 
1049  // Enable/disable Copper Layers control
1050  m_rbCopperLayersSel->Enable( m_padType->GetSelection() != APERTURE_DLG_TYPE );
1051 
1052  LSET cu_set = m_dummyPad->GetLayerSet() & LSET::AllCuMask();
1053 
1054  switch( m_padType->GetSelection() )
1055  {
1056  case PTH_DLG_TYPE:
1057  if( !cu_set.any() )
1058  m_stackupImagesBook->SetSelection( 3 );
1059  else if( !m_dummyPad->GetRemoveUnconnected() )
1060  m_stackupImagesBook->SetSelection( 0 );
1061  else if( m_dummyPad->GetKeepTopBottom() )
1062  m_stackupImagesBook->SetSelection( 1 );
1063  else
1064  m_stackupImagesBook->SetSelection( 2 );
1065 
1066  break;
1067 
1068  case NPTH_DLG_TYPE:
1069  if( cu_set.test( F_Cu ) && cu_set.test( B_Cu ) )
1070  m_stackupImagesBook->SetSelection( 4 );
1071  else if( cu_set.test( F_Cu ) )
1072  m_stackupImagesBook->SetSelection( 5 );
1073  else if( cu_set.test( B_Cu ) )
1074  m_stackupImagesBook->SetSelection( 6 );
1075  else
1076  m_stackupImagesBook->SetSelection( 7 );
1077 
1078  break;
1079 
1080  case SMD_DLG_TYPE:
1081  case CONN_DLG_TYPE:
1082  case APERTURE_DLG_TYPE:
1083  m_stackupImagesBook->SetSelection( 3 );
1084  break;
1085  }
1086 }
1087 
1088 
1090 {
1091  bool isOnCopperLayer = ( m_dummyPad->GetLayerSet() & LSET::AllCuMask() ).any();
1092  m_nonCopperWarningBook->SetSelection( isOnCopperLayer ? 0 : 1 );
1093 }
1094 
1095 
1096 void DIALOG_PAD_PROPERTIES::updatePadLayersList( LSET layer_mask, bool remove_unconnected,
1097  bool keep_top_bottom )
1098 {
1100 
1101  switch( m_padType->GetSelection() )
1102  {
1103  case PTH_DLG_TYPE:
1104  if( !layer_mask.any() )
1105  layer_mask = PAD::PTHMask();
1106 
1107  if( !( layer_mask & LSET::AllCuMask() ).any() )
1108  m_rbCopperLayersSel->SetSelection( 3 );
1109  else if( !remove_unconnected )
1110  m_rbCopperLayersSel->SetSelection( 0 );
1111  else if( keep_top_bottom )
1112  m_rbCopperLayersSel->SetSelection( 1 );
1113  else
1114  m_rbCopperLayersSel->SetSelection( 2 );
1115 
1116  break;
1117 
1118  case SMD_DLG_TYPE:
1119  if( !layer_mask.any() )
1120  layer_mask = PAD::SMDMask();
1121 
1122  if( layer_mask.test( F_Cu ) )
1123  m_rbCopperLayersSel->SetSelection( 0 );
1124  else
1125  m_rbCopperLayersSel->SetSelection( 1 );
1126 
1127  break;
1128 
1129  case CONN_DLG_TYPE:
1130  if( !layer_mask.any() )
1131  layer_mask = PAD::ConnSMDMask();
1132 
1133  if( layer_mask.test( F_Cu ) )
1134  m_rbCopperLayersSel->SetSelection( 0 );
1135  else
1136  m_rbCopperLayersSel->SetSelection( 1 );
1137 
1138  break;
1139 
1140  case NPTH_DLG_TYPE:
1141  if( !layer_mask.any() )
1142  layer_mask = PAD::UnplatedHoleMask();
1143 
1144  if( layer_mask.test( F_Cu ) && layer_mask.test( B_Cu ) )
1145  m_rbCopperLayersSel->SetSelection( 0 );
1146  else if( layer_mask.test( F_Cu ) )
1147  m_rbCopperLayersSel->SetSelection( 1 );
1148  else if( layer_mask.test( B_Cu ) )
1149  m_rbCopperLayersSel->SetSelection( 2 );
1150  else
1151  m_rbCopperLayersSel->SetSelection( 3 );
1152 
1153  break;
1154 
1155  case APERTURE_DLG_TYPE:
1156  if( !layer_mask.any() )
1157  layer_mask = PAD::ApertureMask();
1158 
1159  m_rbCopperLayersSel->SetSelection( 0 );
1160  break;
1161  }
1162 
1163  m_PadLayerAdhCmp->SetValue( layer_mask[F_Adhes] );
1164  m_PadLayerAdhCu->SetValue( layer_mask[B_Adhes] );
1165 
1166  m_PadLayerPateCmp->SetValue( layer_mask[F_Paste] );
1167  m_PadLayerPateCu->SetValue( layer_mask[B_Paste] );
1168 
1169  m_PadLayerSilkCmp->SetValue( layer_mask[F_SilkS] );
1170  m_PadLayerSilkCu->SetValue( layer_mask[B_SilkS] );
1171 
1172  m_PadLayerMaskCmp->SetValue( layer_mask[F_Mask] );
1173  m_PadLayerMaskCu->SetValue( layer_mask[B_Mask] );
1174 
1175  m_PadLayerECO1->SetValue( layer_mask[Eco1_User] );
1176  m_PadLayerECO2->SetValue( layer_mask[Eco2_User] );
1177 
1178  m_PadLayerDraft->SetValue( layer_mask[Dwgs_User] );
1179 }
1180 
1181 
1183 {
1184  bool retVal = DIALOG_SHIM::Show( aShow );
1185 
1186  if( aShow )
1187  {
1188  // It *should* work to set the stackup bitmap in the constructor, but it doesn't.
1189  // wxWidgets needs to have these set when the panel is visible for some reason.
1190  // https://gitlab.com/kicad/code/kicad/-/issues/5534
1197  m_stackupImage7->SetBitmap( KiBitmap( BITMAPS::pads_npth ) );
1198 
1199  Layout();
1200  }
1201 
1202  return retVal;
1203 }
1204 
1205 
1206 void DIALOG_PAD_PROPERTIES::OnSetCopperLayers( wxCommandEvent& event )
1207 {
1209  redraw();
1210 }
1211 
1212 
1213 void DIALOG_PAD_PROPERTIES::OnSetLayers( wxCommandEvent& event )
1214 {
1216  redraw();
1217 }
1218 
1219 
1221 {
1222  bool error = transferDataToPad( m_dummyPad );
1223 
1224  wxArrayString error_msgs;
1225  wxArrayString warning_msgs;
1226  wxString msg;
1227  wxSize pad_size = m_dummyPad->GetSize();
1228  wxSize drill_size = m_dummyPad->GetDrillSize();
1229 
1231  {
1232  // allow 0-sized anchor pads
1233  }
1234  else if( m_dummyPad->GetShape() == PAD_SHAPE::CIRCLE )
1235  {
1236  if( pad_size.x <= 0 )
1237  warning_msgs.Add( _( "Warning: Pad size is less than zero." ) );
1238  }
1239  else
1240  {
1241  if( pad_size.x <= 0 || pad_size.y <= 0 )
1242  warning_msgs.Add( _( "Warning: Pad size is less than zero." ) );
1243  }
1244 
1245  // Test hole size against pad size
1246  if( m_dummyPad->IsOnCopperLayer() )
1247  {
1249  PCB_LAYER_ID layer = lset.Seq().at( 0 );
1250  int maxError = m_board->GetDesignSettings().m_MaxError;
1251  SHAPE_POLY_SET padOutline;
1252 
1253  m_dummyPad->TransformShapeWithClearanceToPolygon( padOutline, layer, 0, maxError,
1255 
1256  const SHAPE_SEGMENT* drillShape = m_dummyPad->GetEffectiveHoleShape();
1257  const SEG drillSeg = drillShape->GetSeg();
1258  SHAPE_POLY_SET drillOutline;
1259 
1260  TransformOvalToPolygon( drillOutline, (wxPoint) drillSeg.A, (wxPoint) drillSeg.B,
1261  drillShape->GetWidth(), maxError, ERROR_LOC::ERROR_INSIDE );
1262 
1263  drillOutline.BooleanSubtract( padOutline, SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
1264 
1265  if( drillOutline.BBox().GetWidth() > 0 || drillOutline.BBox().GetHeight() > 0 )
1266  {
1267  warning_msgs.Add( _( "Warning: Pad drill will leave no copper or drill shape and "
1268  "pad shape do not overlap." ) );
1269  }
1270  }
1271 
1272  if( m_dummyPad->GetLocalClearance() < 0 )
1273  warning_msgs.Add( _( "Warning: Negative local clearance values will have no effect." ) );
1274 
1275  // Some pads need a negative solder mask clearance (mainly for BGA with small pads)
1276  // However the negative solder mask clearance must not create negative mask size
1277  // Therefore test for minimal acceptable negative value
1279  {
1280  int absMargin = abs( m_dummyPad->GetLocalSolderMaskMargin() );
1281 
1283  {
1284  for( const std::shared_ptr<PCB_SHAPE>& shape : m_dummyPad->GetPrimitives() )
1285  {
1286  EDA_RECT shapeBBox = shape->GetBoundingBox();
1287 
1288  if( absMargin > shapeBBox.GetWidth() || absMargin > shapeBBox.GetHeight() )
1289  {
1290  warning_msgs.Add( _( "Warning: Negative solder mask clearances larger than "
1291  "some shape primitives. Results may be surprising." ) );
1292 
1293  break;
1294  }
1295  }
1296  }
1297  else if( absMargin > pad_size.x || absMargin > pad_size.y )
1298  {
1299  warning_msgs.Add( _( "Warning: Negative solder mask clearance larger than pad. No "
1300  "solder mask will be generated." ) );
1301  }
1302  }
1303 
1304  // Some pads need a positive solder paste clearance (mainly for BGA with small pads)
1305  // However, a positive value can create issues if the resulting shape is too big.
1306  // (like a solder paste creating a solder paste area on a neighbor pad or on the solder mask)
1307  // So we could ask for user to confirm the choice
1308  // For now we just check for disappearing paste
1309  wxSize paste_size;
1310  int paste_margin = m_dummyPad->GetLocalSolderPasteMargin();
1311  double paste_ratio = m_dummyPad->GetLocalSolderPasteMarginRatio();
1312 
1313  paste_size.x = pad_size.x + paste_margin + KiROUND( pad_size.x * paste_ratio );
1314  paste_size.y = pad_size.y + paste_margin + KiROUND( pad_size.y * paste_ratio );
1315 
1316  if( paste_size.x <= 0 || paste_size.y <= 0 )
1317  {
1318  warning_msgs.Add( _( "Warning: Negative solder paste margins larger than pad. No solder "
1319  "paste mask will be generated." ) );
1320  }
1321 
1322  LSET padlayers_mask = m_dummyPad->GetLayerSet();
1323 
1324  if( padlayers_mask == 0 )
1325  error_msgs.Add( _( "Error: pad has no layer." ) );
1326 
1327  if( !padlayers_mask[F_Cu] && !padlayers_mask[B_Cu] )
1328  {
1329  if( ( drill_size.x || drill_size.y ) && m_dummyPad->GetAttribute() != PAD_ATTRIB::NPTH )
1330  {
1331  warning_msgs.Add( _( "Warning: Plated through holes should normally have a copper pad "
1332  "on at least one layer." ) );
1333  }
1334  }
1335 
1336  if( error )
1337  error_msgs.Add( _( "Too large value for pad delta size." ) );
1338 
1339  switch( m_dummyPad->GetAttribute() )
1340  {
1341  case PAD_ATTRIB::NPTH: // Not plated, but through hole, a hole is expected
1342  case PAD_ATTRIB::PTH: // Pad through hole, a hole is also expected
1343  if( drill_size.x <= 0
1344  || ( drill_size.y <= 0 && m_dummyPad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ) )
1345  {
1346  warning_msgs.Add( _( "Warning: Through hole pad has no hole." ) );
1347  }
1348  break;
1349 
1350  case PAD_ATTRIB::CONN: // Connector pads are smd pads, just they do not have solder paste.
1351  if( padlayers_mask[B_Paste] || padlayers_mask[F_Paste] )
1352  {
1353  warning_msgs.Add( _( "Warning: Connector pads normally have no solder paste. Use an "
1354  "SMD pad instead." ) );
1355  }
1357 
1358  case PAD_ATTRIB::SMD: // SMD and Connector pads (One external copper layer only)
1359  {
1360  LSET innerlayers_mask = padlayers_mask & LSET::InternalCuMask();
1361 
1362  if( ( padlayers_mask[F_Cu] && padlayers_mask[B_Cu] ) || innerlayers_mask.count() != 0 )
1363  warning_msgs.Add( _( "Warning: SMD pad has no outer layers." ) );
1364  }
1365  break;
1366  }
1367 
1371  {
1372  warning_msgs.Add( _( "Warning: Fiducial property makes no sense on NPTH pads." ) );
1373  }
1374 
1377  {
1378  warning_msgs.Add( _( "Warning: Testpoint property makes no sense on NPTH pads." ) );
1379  }
1380 
1383  {
1384  warning_msgs.Add( _( "Warning: Heatsink property makes no sense of NPTH pads." ) );
1385  }
1386 
1389  {
1390  warning_msgs.Add( _( "Warning: Castellated property is for PTH pads." ) );
1391  }
1392 
1393  if( m_dummyPad->GetProperty() == PAD_PROP::BGA &&
1395  {
1396  warning_msgs.Add( _( "Warning: BGA property is for SMD pads." ) );
1397  }
1398 
1401  {
1403 
1404  if( m_cornerRatio.GetDoubleValue() < 0.0 )
1405  error_msgs.Add( _( "Error: Negative corner size." ) );
1406  else if( m_cornerRatio.GetDoubleValue() > 50.0 )
1407  warning_msgs.Add( _( "Warning: Corner size will make pad circular." ) );
1408  }
1409 
1410  // PADSTACKS TODO: this will need to check each layer in the pad...
1412  {
1413  SHAPE_POLY_SET mergedPolygon;
1414  m_dummyPad->MergePrimitivesAsPolygon( &mergedPolygon );
1415 
1416  if( mergedPolygon.OutlineCount() > 1 )
1417  error_msgs.Add( _( "Error: Custom pad shape must resolve to a single polygon." ) );
1418  }
1419 
1420 
1421  if( error_msgs.GetCount() || warning_msgs.GetCount() )
1422  {
1423  wxString title = error_msgs.GetCount() ? _( "Pad Properties Errors" )
1424  : _( "Pad Properties Warnings" );
1425  HTML_MESSAGE_BOX dlg( this, title );
1426 
1427  dlg.ListSet( error_msgs );
1428 
1429  if( warning_msgs.GetCount() )
1430  dlg.ListSet( warning_msgs );
1431 
1432  dlg.ShowModal();
1433  }
1434 
1435  return error_msgs.GetCount() == 0;
1436 }
1437 
1438 
1440 {
1441  if( !m_canUpdate )
1442  return;
1443 
1444  KIGFX::VIEW* view = m_padPreviewGAL->GetView();
1446 
1447  // The layer used to place primitive items selected when editing custom pad shapes
1448  // we use here a layer never used in a pad:
1449  #define SELECTED_ITEMS_LAYER Dwgs_User
1450 
1452  KIGFX::PCB_RENDER_SETTINGS* settings =
1453  static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
1455 
1456  view->Update( m_dummyPad );
1457 
1458  // delete previous items if highlight list
1459  while( m_highlight.size() )
1460  {
1461  delete m_highlight.back(); // the dtor also removes item from view
1462  m_highlight.pop_back();
1463  }
1464 
1465  // highlight selected primitives:
1466  long select = m_listCtrlPrimitives->GetFirstSelected();
1467 
1468  while( select >= 0 )
1469  {
1470  PCB_SHAPE* dummyShape = (PCB_SHAPE*) m_primitives[select]->Clone();
1471  dummyShape->SetLayer( SELECTED_ITEMS_LAYER );
1472  dummyShape->Rotate( wxPoint( 0, 0), m_dummyPad->GetOrientation() );
1473  dummyShape->Move( m_dummyPad->GetPosition() );
1474 
1475  view->Add( dummyShape );
1476  m_highlight.push_back( dummyShape );
1477 
1478  select = m_listCtrlPrimitives->GetNextSelected( select );
1479  }
1480 
1481  BOX2I bbox = m_dummyPad->ViewBBox();
1482 
1483  if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
1484  {
1485  // The origin always goes in the middle of the canvas; we want offsetting the pad
1486  // shape to move the pad, not the hole
1487  bbox.Move( -m_dummyPad->GetPosition() );
1488  int maxXExtent = std::max( abs( bbox.GetLeft() ), abs( bbox.GetRight() ) );
1489  int maxYExtent = std::max( abs( bbox.GetTop() ), abs( bbox.GetBottom() ) );
1490 
1491  // Don't blow up the GAL on too-large numbers
1492  if( maxXExtent > INT_MAX / 4 )
1493  maxXExtent = INT_MAX / 4;
1494 
1495  if( maxYExtent > INT_MAX / 4 )
1496  maxYExtent = INT_MAX / 4;
1497 
1498  BOX2D viewBox( m_dummyPad->GetPosition(), {0, 0} );
1499  BOX2D canvasBox( m_dummyPad->GetPosition(), {0, 0} );
1500  viewBox.Inflate( maxXExtent * 1.4, maxYExtent * 1.4 ); // add a margin
1501  canvasBox.Inflate( maxXExtent * 2.0, maxYExtent * 2.0 );
1502 
1503  view->SetBoundary( canvasBox );
1504 
1505  // Autozoom
1506  view->SetViewport( viewBox );
1507 
1510  }
1511 }
1512 
1513 
1515 {
1516  if( !wxDialog::TransferDataToWindow() )
1517  return false;
1518 
1519  if( !m_panelGeneral->TransferDataToWindow() )
1520  return false;
1521 
1522  if( !m_localSettingsPanel->TransferDataToWindow() )
1523  return false;
1524 
1525  return true;
1526 }
1527 
1528 
1530 {
1531  BOARD_COMMIT commit( m_parent );
1532 
1533  if( !wxDialog::TransferDataFromWindow() )
1534  return false;
1535 
1536  if( !m_panelGeneral->TransferDataFromWindow() )
1537  return false;
1538 
1539  if( !m_localSettingsPanel->TransferDataFromWindow() )
1540  return false;
1541 
1542  if( !padValuesOK() )
1543  return false;
1544 
1546 
1547  PAD_TOOL* padTool = m_parent->GetToolManager()->GetTool<PAD_TOOL>();
1548  padTool->SetLastPadNumber( m_padMaster->GetNumber() );
1549 
1550  // m_padMaster is a pattern: ensure there is no net for this pad:
1552 
1553  if( !m_currentPad ) // Set current Pad parameters
1554  return true;
1555 
1556  commit.Modify( m_currentPad );
1557 
1558  // redraw the area where the pad was, without pad (delete pad on screen)
1560  m_parent->GetCanvas()->Refresh();
1562 
1563  // Update values
1567 
1568  m_currentPad->SetLocked( m_locked->GetValue() );
1569 
1570  if( !m_locked->GetValue() || m_isFpEditor )
1572 
1573  wxSize size;
1574  FOOTPRINT* footprint = m_currentPad->GetParent();
1575 
1577 
1578  size = m_padMaster->GetDelta();
1579  m_currentPad->SetDelta( size );
1580 
1583 
1584  wxPoint offset = m_padMaster->GetOffset();
1585  m_currentPad->SetOffset( offset );
1586 
1588 
1591 
1594 
1598 
1600 
1601  int padNetcode = NETINFO_LIST::UNCONNECTED;
1602 
1603  // For PAD_ATTRIB::NPTH, ensure there is no net name selected
1605  padNetcode = m_padNetSelector->GetSelectedNetcode();
1606 
1607  m_currentPad->SetNetCode( padNetcode );
1618 
1619  // rounded rect pads with radius ratio = 0 are in fact rect pads.
1620  // So set the right shape (and perhaps issues with a radius = 0)
1623  {
1625  }
1626 
1627  // Set the fabrication property:
1629 
1630  // define the way the clearance area is defined in zones
1632 
1633  if( m_isFlipped )
1634  {
1635  // flip pad (up/down) around its position
1636  m_currentPad->Flip( m_currentPad->GetPosition(), false );
1637  }
1638 
1639  if( footprint )
1640  {
1641  footprint->SetLastEditTime();
1642 
1643  // compute the pos 0 value, i.e. pad position for footprint with orientation = 0
1644  // i.e. relative to footprint origin (footprint position)
1645  wxPoint pt = m_currentPad->GetPosition() - footprint->GetPosition();
1646  RotatePoint( &pt, -footprint->GetOrientation() );
1647  m_currentPad->SetPos0( pt );
1649  footprint->GetOrientation() );
1650  }
1651 
1653 
1654  // redraw the area where the pad was
1655  m_parent->GetCanvas()->Refresh();
1656 
1657  commit.Push( _( "Modify pad" ) );
1658 
1659  return true;
1660 }
1661 
1662 
1664 {
1665  PAD_PROP prop = PAD_PROP::NONE;
1666 
1667  switch( m_choiceFabProperty->GetSelection() )
1668  {
1669  case 0: prop = PAD_PROP::NONE; break;
1670  case 1: prop = PAD_PROP::BGA; break;
1671  case 2: prop = PAD_PROP::FIDUCIAL_LOCAL; break;
1672  case 3: prop = PAD_PROP::FIDUCIAL_GLBL; break;
1673  case 4: prop = PAD_PROP::TESTPOINT; break;
1674  case 5: prop = PAD_PROP::HEATSINK; break;
1675  case 6: prop = PAD_PROP::CASTELLATED; break;
1676  }
1677 
1678  return prop;
1679 }
1680 
1681 
1683 {
1684  wxString msg;
1685 
1686  if( !Validate() )
1687  return true;
1688  if( !m_panelGeneral->Validate() )
1689  return true;
1690  if( !m_localSettingsPanel->Validate() )
1691  return true;
1692  if( !m_spokeWidth.Validate( 0, INT_MAX ) )
1693  return false;
1694 
1695  m_OrientValidator.TransferFromWindow();
1696 
1697  aPad->SetAttribute( code_type[m_padType->GetSelection()] );
1698  aPad->SetShape( code_shape[m_PadShapeSelector->GetSelection()] );
1699 
1700  if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CUSTOM_RECT_ANCHOR )
1702  else
1704 
1705  if( aPad->GetShape() == PAD_SHAPE::CUSTOM )
1707 
1708  // Read pad clearances values:
1714  aPad->SetThermalGap( m_thermalGap.GetValue() );
1715 
1716  switch( m_ZoneConnectionChoice->GetSelection() )
1717  {
1718  default:
1719  case 0: aPad->SetZoneConnection( ZONE_CONNECTION::INHERITED ); break;
1720  case 1: aPad->SetZoneConnection( ZONE_CONNECTION::FULL ); break;
1721  case 2: aPad->SetZoneConnection( ZONE_CONNECTION::THERMAL ); break;
1722  case 3: aPad->SetZoneConnection( ZONE_CONNECTION::NONE ); break;
1723  }
1724 
1725  aPad->SetPosition( wxPoint( m_posX.GetValue(), m_posY.GetValue() ) );
1726 
1727  if( m_holeShapeCtrl->GetSelection() == 0 )
1728  {
1730  aPad->SetDrillSize( wxSize( m_holeX.GetValue(), m_holeX.GetValue() ) );
1731  }
1732  else
1733  {
1735  aPad->SetDrillSize( wxSize( m_holeX.GetValue(), m_holeY.GetValue() ) );
1736  }
1737 
1738  if( aPad->GetShape() == PAD_SHAPE::CIRCLE )
1739  aPad->SetSize( wxSize( m_sizeX.GetValue(), m_sizeX.GetValue() ) );
1740  else
1741  aPad->SetSize( wxSize( m_sizeX.GetValue(), m_sizeY.GetValue() ) );
1742 
1743  // For a trapezoid, test delta value (be sure delta is not too large for pad size)
1744  // remember DeltaSize.x is the Y size variation
1745  bool error = false;
1746  wxSize delta( 0, 0 );
1747 
1748  if( aPad->GetShape() == PAD_SHAPE::TRAPEZOID )
1749  {
1750  // For a trapezoid, only one of delta.x or delta.y is not 0, depending on axis.
1751  if( m_trapAxisCtrl->GetSelection() == 0 )
1752  delta.x = m_trapDelta.GetValue();
1753  else
1754  delta.y = m_trapDelta.GetValue();
1755 
1756  if( delta.x < 0 && delta.x <= -aPad->GetSize().y )
1757  {
1758  delta.x = -aPad->GetSize().y + 2;
1759  error = true;
1760  }
1761 
1762  if( delta.x > 0 && delta.x >= aPad->GetSize().y )
1763  {
1764  delta.x = aPad->GetSize().y - 2;
1765  error = true;
1766  }
1767 
1768  if( delta.y < 0 && delta.y <= -aPad->GetSize().x )
1769  {
1770  delta.y = -aPad->GetSize().x + 2;
1771  error = true;
1772  }
1773 
1774  if( delta.y > 0 && delta.y >= aPad->GetSize().x )
1775  {
1776  delta.y = aPad->GetSize().x - 2;
1777  error = true;
1778  }
1779  }
1780 
1781  aPad->SetDelta( delta );
1782 
1783  if( m_offsetShapeOpt->GetValue() )
1784  aPad->SetOffset( wxPoint( m_offsetX.GetValue(), m_offsetY.GetValue() ) );
1785  else
1786  aPad->SetOffset( wxPoint() );
1787 
1788  // Read pad length die
1789  if( m_padToDieOpt->GetValue() )
1791  else
1792  aPad->SetPadToDieLength( 0 );
1793 
1794  aPad->SetOrientation( m_OrientValue * 10.0 );
1795  aPad->SetNumber( m_padNumCtrl->GetValue() );
1797 
1798  int chamfers = 0;
1799 
1800  if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_RECT )
1801  {
1802  if( m_cbTopLeft->GetValue() )
1803  chamfers |= RECT_CHAMFER_TOP_LEFT;
1804 
1805  if( m_cbTopRight->GetValue() )
1806  chamfers |= RECT_CHAMFER_TOP_RIGHT;
1807 
1808  if( m_cbBottomLeft->GetValue() )
1809  chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1810 
1811  if( m_cbBottomRight->GetValue() )
1812  chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1813  }
1814  else if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT )
1815  {
1816  if( m_cbTopLeft1->GetValue() )
1817  chamfers |= RECT_CHAMFER_TOP_LEFT;
1818 
1819  if( m_cbTopRight1->GetValue() )
1820  chamfers |= RECT_CHAMFER_TOP_RIGHT;
1821 
1822  if( m_cbBottomLeft1->GetValue() )
1823  chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1824 
1825  if( m_cbBottomRight1->GetValue() )
1826  chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1827  }
1828  aPad->SetChamferPositions( chamfers );
1829 
1830  if( aPad->GetShape() == PAD_SHAPE::CUSTOM )
1831  {
1832  // The pad custom has a "anchor pad" (a basic shape: round or rect pad)
1833  // that is the minimal area of this pad, and is useful to ensure a hole
1834  // diameter is acceptable, and is used in Gerber files as flashed area
1835  // reference
1836  if( aPad->GetAnchorPadShape() == PAD_SHAPE::CIRCLE )
1837  aPad->SetSize( wxSize( m_sizeX.GetValue(), m_sizeX.GetValue() ) );
1838 
1839  // define the way the clearance area is defined in zones
1840  aPad->SetCustomShapeInZoneOpt( m_ZoneCustomPadShape->GetSelection() == 0 ?
1843  }
1844 
1845  switch( aPad->GetAttribute() )
1846  {
1847  case PAD_ATTRIB::PTH:
1848  break;
1849 
1850  case PAD_ATTRIB::CONN:
1851  case PAD_ATTRIB::SMD:
1852  // SMD and PAD_ATTRIB::CONN has no hole.
1853  // basically, SMD and PAD_ATTRIB::CONN are same type of pads
1854  // PAD_ATTRIB::CONN has just a default non technical layers that differs from SMD
1855  // and are intended to be used in virtual edge board connectors
1856  // However we can accept a non null offset,
1857  // mainly to allow complex pads build from a set of basic pad shapes
1858  aPad->SetDrillSize( wxSize( 0, 0 ) );
1859  break;
1860 
1861  case PAD_ATTRIB::NPTH:
1862  // Mechanical purpose only:
1863  // no net name, no pad name allowed
1864  aPad->SetNumber( wxEmptyString );
1866  break;
1867 
1868  default:
1869  wxFAIL_MSG( "DIALOG_PAD_PROPERTIES::transferDataToPad: unknown pad type" );
1870  break;
1871  }
1872 
1873  if( aPad->GetShape() == PAD_SHAPE::ROUNDRECT )
1874  {
1876  }
1877  else if( aPad->GetShape() == PAD_SHAPE::CHAMFERED_RECT )
1878  {
1880  {
1883  }
1884  else // Choice is CHOICE_SHAPE_CHAMFERED_RECT, no rounded corner
1885  {
1887  aPad->SetRoundRectRadiusRatio( 0 );
1888  }
1889  }
1890 
1891  aPad->SetProperty( getSelectedProperty() );
1892 
1893  LSET padLayerMask = LSET();
1894  int copperLayersChoice = m_rbCopperLayersSel->GetSelection();
1895 
1896  aPad->SetRemoveUnconnected( false );
1897  aPad->SetKeepTopBottom( false );
1898 
1899  switch( m_padType->GetSelection() )
1900  {
1901  case PTH_DLG_TYPE:
1902  switch( copperLayersChoice )
1903  {
1904  case 0:
1905  // All copper layers
1906  padLayerMask |= LSET::AllCuMask();
1907  break;
1908 
1909  case 1:
1910  // Front, back and connected
1911  padLayerMask |= LSET::AllCuMask();
1912  aPad->SetRemoveUnconnected( true );
1913  aPad->SetKeepTopBottom( true );
1914  break;
1915 
1916  case 2:
1917  // Connected only
1918  padLayerMask |= LSET::AllCuMask();
1919  aPad->SetRemoveUnconnected( true );
1920  break;
1921 
1922  case 3:
1923  // No copper layers
1924  break;
1925  }
1926 
1927  break;
1928 
1929  case NPTH_DLG_TYPE:
1930  switch( copperLayersChoice )
1931  {
1932  case 0: padLayerMask.set( F_Cu ).set( B_Cu ); break;
1933  case 1: padLayerMask.set( F_Cu ); break;
1934  case 2: padLayerMask.set( B_Cu ); break;
1935  default: break;
1936  }
1937 
1938  break;
1939 
1940  case SMD_DLG_TYPE:
1941  case CONN_DLG_TYPE:
1942  switch( copperLayersChoice )
1943  {
1944  case 0: padLayerMask.set( F_Cu ); break;
1945  case 1: padLayerMask.set( B_Cu ); break;
1946  }
1947 
1948  break;
1949 
1950  case APERTURE_DLG_TYPE:
1951  // no copper layers
1952  break;
1953  }
1954 
1955  if( m_PadLayerAdhCmp->GetValue() )
1956  padLayerMask.set( F_Adhes );
1957 
1958  if( m_PadLayerAdhCu->GetValue() )
1959  padLayerMask.set( B_Adhes );
1960 
1961  if( m_PadLayerPateCmp->GetValue() )
1962  padLayerMask.set( F_Paste );
1963 
1964  if( m_PadLayerPateCu->GetValue() )
1965  padLayerMask.set( B_Paste );
1966 
1967  if( m_PadLayerSilkCmp->GetValue() )
1968  padLayerMask.set( F_SilkS );
1969 
1970  if( m_PadLayerSilkCu->GetValue() )
1971  padLayerMask.set( B_SilkS );
1972 
1973  if( m_PadLayerMaskCmp->GetValue() )
1974  padLayerMask.set( F_Mask );
1975 
1976  if( m_PadLayerMaskCu->GetValue() )
1977  padLayerMask.set( B_Mask );
1978 
1979  if( m_PadLayerECO1->GetValue() )
1980  padLayerMask.set( Eco1_User );
1981 
1982  if( m_PadLayerECO2->GetValue() )
1983  padLayerMask.set( Eco2_User );
1984 
1985  if( m_PadLayerDraft->GetValue() )
1986  padLayerMask.set( Dwgs_User );
1987 
1988  aPad->SetLayerSet( padLayerMask );
1989 
1990  return error;
1991 }
1992 
1993 
1994 void DIALOG_PAD_PROPERTIES::OnOffsetCheckbox( wxCommandEvent& event )
1995 {
1996  if( m_offsetShapeOpt->GetValue() )
1997  {
2000  }
2001 
2002  // Show/hide controls depending on m_offsetShapeOpt being enabled
2003  m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
2004  m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
2005 
2006  for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
2007  m_notebook->GetPage( i )->Layout();
2008 
2009  OnValuesChanged( event );
2010 }
2011 
2012 
2013 void DIALOG_PAD_PROPERTIES::OnPadToDieCheckbox( wxCommandEvent& event )
2014 {
2015  if( m_padToDieOpt->GetValue() && m_currentPad )
2017 
2018  OnValuesChanged( event );
2019 }
2020 
2021 
2022 void DIALOG_PAD_PROPERTIES::OnValuesChanged( wxCommandEvent& event )
2023 {
2024  if( m_canUpdate )
2025  {
2027 
2028  // If the pad size has changed, update the displayed values for rounded rect pads.
2030 
2031  redraw();
2032  }
2033 }
2034 
2036 {
2037  long select = m_listCtrlPrimitives->GetFirstSelected();
2038 
2039  if( select < 0 )
2040  {
2041  wxMessageBox( _( "No shape selected" ) );
2042  return;
2043  }
2044 
2045  std::shared_ptr<PCB_SHAPE>& shape = m_primitives[select];
2046 
2047  if( shape->GetShape() == SHAPE_T::POLY )
2048  {
2049  DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, m_parent, shape.get() );
2050 
2051  if( dlg.ShowModal() != wxID_OK )
2052  return;
2053 
2054  dlg.TransferDataFromWindow();
2055  }
2056 
2057  else
2058  {
2059  DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, m_parent, shape.get() );
2060 
2061  if( dlg.ShowModal() != wxID_OK )
2062  return;
2063 
2064  dlg.TransferDataFromWindow();
2065  }
2066 
2068 
2069  if( m_canUpdate )
2070  {
2072  redraw();
2073  }
2074 }
2075 
2076 
2078 {
2079  // Called on a double click on the basic shapes list
2080  // To Do: highligth the primitive(s) currently selected.
2081  redraw();
2082 }
2083 
2084 
2085 void DIALOG_PAD_PROPERTIES::onPrimitiveDClick( wxMouseEvent& event )
2086 {
2087  editPrimitive();
2088 }
2089 
2090 
2091 void DIALOG_PAD_PROPERTIES::onEditPrimitive( wxCommandEvent& event )
2092 {
2093  editPrimitive();
2094 }
2095 
2096 
2097 void DIALOG_PAD_PROPERTIES::onDeletePrimitive( wxCommandEvent& event )
2098 {
2099  long select = m_listCtrlPrimitives->GetFirstSelected();
2100 
2101  if( select < 0 )
2102  return;
2103 
2104  // Multiple selections are allowed. get them and remove corresponding shapes
2105  std::vector<long> indexes;
2106  indexes.push_back( select );
2107 
2108  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2109  indexes.push_back( select );
2110 
2111  // Erase all select shapes
2112  for( unsigned ii = indexes.size(); ii > 0; --ii )
2113  m_primitives.erase( m_primitives.begin() + indexes[ii-1] );
2114 
2116 
2117  if( m_canUpdate )
2118  {
2120  redraw();
2121  }
2122 }
2123 
2124 
2125 void DIALOG_PAD_PROPERTIES::onAddPrimitive( wxCommandEvent& event )
2126 {
2127  // Ask user for shape type
2128  wxString shapelist[] = {
2129  _( "Segment" ),
2130  _( "Arc" ),
2131  _( "Bezier" ),
2132  _( "Ring/Circle" ),
2133  _( "Polygon" )
2134  };
2135 
2136  int type = wxGetSingleChoiceIndex( _( "Shape type:" ), _( "Add Primitive" ),
2137  arrayDim( shapelist ), shapelist, 0, this );
2138 
2139  // User pressed cancel
2140  if( type == -1 )
2141  return;
2142 
2144  SHAPE_T::POLY };
2145 
2146  PCB_SHAPE* primitive = new PCB_SHAPE();
2147  primitive->SetShape( listtype[type] );
2149  primitive->SetFilled( true );
2150 
2151  if( listtype[type] == SHAPE_T::POLY )
2152  {
2153  DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, m_parent, primitive );
2154 
2155  if( dlg.ShowModal() != wxID_OK )
2156  return;
2157  }
2158  else
2159  {
2160  DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, m_parent, primitive );
2161 
2162  if( dlg.ShowModal() != wxID_OK )
2163  return;
2164  }
2165 
2166  m_primitives.emplace_back( primitive );
2167 
2169 
2170  if( m_canUpdate )
2171  {
2173  redraw();
2174  }
2175 }
2176 
2177 
2178 void DIALOG_PAD_PROPERTIES::onGeometryTransform( wxCommandEvent& event )
2179 {
2180  long select = m_listCtrlPrimitives->GetFirstSelected();
2181 
2182  if( select < 0 )
2183  {
2184  wxMessageBox( _( "No shape selected" ) );
2185  return;
2186  }
2187 
2188  // Multiple selections are allowed. Build selected shapes list
2189  std::vector<std::shared_ptr<PCB_SHAPE>> shapeList;
2190  shapeList.emplace_back( m_primitives[select] );
2191 
2192  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2193  shapeList.emplace_back( m_primitives[select] );
2194 
2195  DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, m_parent, shapeList, false );
2196 
2197  if( dlg.ShowModal() != wxID_OK )
2198  return;
2199 
2200  dlg.Transform();
2201 
2203 
2204  if( m_canUpdate )
2205  {
2207  redraw();
2208  }
2209 }
2210 
2211 
2212 void DIALOG_PAD_PROPERTIES::onDuplicatePrimitive( wxCommandEvent& event )
2213 {
2214  long select = m_listCtrlPrimitives->GetFirstSelected();
2215 
2216  if( select < 0 )
2217  {
2218  wxMessageBox( _( "No shape selected" ) );
2219  return;
2220  }
2221 
2222  // Multiple selections are allowed. Build selected shapes list
2223  std::vector<std::shared_ptr<PCB_SHAPE>> shapeList;
2224  shapeList.emplace_back( m_primitives[select] );
2225 
2226  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2227  shapeList.emplace_back( m_primitives[select] );
2228 
2229  DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, m_parent, shapeList, true );
2230 
2231  if( dlg.ShowModal() != wxID_OK )
2232  return;
2233 
2234  // Transfer new settings
2235  // save duplicates to a separate vector to avoid m_primitives reallocation,
2236  // as shapeList contains pointers to its elements
2237  std::vector<std::shared_ptr<PCB_SHAPE>> duplicates;
2238  dlg.Transform( &duplicates, dlg.GetDuplicateCount() );
2239  std::move( duplicates.begin(), duplicates.end(), std::back_inserter( m_primitives ) );
2240 
2242 
2243  if( m_canUpdate )
2244  {
2246  redraw();
2247  }
2248 }
void OnInitDialog(wxInitDialogEvent &event) override
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:750
void OnValuesChanged(wxCommandEvent &event) override
Called when a dimension has changed.
void Move(const Vec &aMoveVector)
Move the rectangle by the aMoveVector.
Definition: box2.h:104
int GetLocalSolderMaskMargin() const
Definition: pad.h:386
wxString MessageTextFromValue(EDA_UNITS aUnits, int aValue, bool aAddUnitLabel, EDA_DATA_TYPE aType)
Convert a value to a string using double notation.
Definition: base_units.cpp:104
smd pads, front layer
Definition: layer_ids.h:198
void SetOffset(const wxPoint &aOffset)
Definition: pad.h:249
void SetLastPadNumber(const wxString &aPadNumber)
Definition: pad_tool.h:63
COMMIT & Modify(EDA_ITEM *aItem)
Create an undo entry for an item that has been already modified.
Definition: commit.h:103
#define DO_NOT_DRAW
Used to disable draw function.
static LSET ConnSMDMask()
layer set for a SMD pad on Front layer used for edge board connectors
Definition: pad.cpp:180
void SetLocalSolderPasteMarginRatio(double aRatio)
Definition: pad.h:397
void SetViewport(const BOX2D &aViewport)
Set the visible area of the VIEW.
Definition: view.cpp:522
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Returns the BOARD_DESIGN_SETTINGS for the open project.
void SetKeepTopBottom(bool aSet)
Set whether we keep the top and bottom connections even if they are not connected.
Definition: pad.h:562
void enablePrimitivePage(bool aEnable)
enable (or disable) the primitive page editor
int OutlineCount() const
Return the number of vertices in a given outline/hole.
void SetAttribute(PAD_ATTRIB aAttribute)
Definition: pad.cpp:576
KIGFX::VIEW_CONTROLS * GetViewControls() const
Return a pointer to the #VIEW_CONTROLS instance used in the panel.
virtual void SetNegativeZero()
Definition: unit_binder.h:67
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:362
int GetLocalSolderPasteMargin() const
Definition: pad.h:393
KIGFX::GAL_DISPLAY_OPTIONS & GetGalDisplayOptions()
Return a reference to the gal rendering options used by GAL for rendering.
double GetRoundRectRadiusRatio() const
Definition: pad.h:523
void SetContrastModeDisplay(HIGH_CONTRAST_MODE aMode)
Switch the contrast mode setting (HIGH_CONTRAST_MODE:NORMAL, DIMMED or HIDDEN ) to control how the no...
Definition: pcb_painter.h:163
virtual void SetTopLayer(int aLayer, bool aEnabled=true)
Set given layer to be displayed on the top or sets back the default order of layers.
Definition: view.cpp:830
void SetFilled(bool aFlag)
Definition: eda_shape.h:83
void DeletePrimitivesList()
Clear the basic shapes list.
void SetLocalClearance(int aClearance)
Definition: pad.h:391
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:161
Implementation of conversion functions that require both schematic and board internal units.
This file is part of the common library.
coord_type GetTop() const
Definition: box2.h:187
void SetThermalSpokeWidth(int aWidth)
Set the width of the thermal spokes connecting the pad to a zone.
Definition: pad.h:490
PAD_PROP GetProperty() const
Definition: pad.h:374
static constexpr double IU_PER_MM
Mock up a conversion function.
static wxString formatCoord(EDA_UNITS aUnits, wxPoint aCoord)
void ApplySettings(const VC_SETTINGS &aSettings)
Load new settings from program common settings.
void SetBoard(BOARD *aBoard)
std::vector< std::shared_ptr< PCB_SHAPE > > m_primitives
DIALOG_PAD_PROPERTIES(PCB_BASE_FRAME *aParent, PAD *aPad)
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
void OnPadToDieCheckbox(wxCommandEvent &event) override
smd pads, back layer
Definition: layer_ids.h:199
#define NPTH_DLG_TYPE
Like smd, does not appear on the solder paste layer (default)
Smd pad, appears on the solder paste layer (default)
wxFloatingPointValidator< double > m_OrientValidator
wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:144
virtual void ChangeDoubleValue(double aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion WITHOUT trigger...
int GetWidth() const
Definition: eda_rect.h:109
Tool relating to pads and pad settings.
Definition: pad_tool.h:35
bool IsLocked() const override
Definition: pad.cpp:157
double GetOrientation() const
Definition: footprint.h:190
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:153
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
coord_type GetRight() const
Definition: box2.h:182
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:190
const SHAPE_SEGMENT * GetEffectiveHoleShape() const
Return a SHAPE object representing the pad's hole.
Definition: pad.cpp:304
int GetSelectedNetcode()
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:679
void onChangePadMode(wxCommandEvent &event) override
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
void ReplacePrimitives(const std::vector< std::shared_ptr< PCB_SHAPE >> &aPrimitivesList)
Clear the current custom shape primitives list and import a new list.
virtual void SetLocked(bool aLocked)
Modify the 'lock' status for of the item.
Definition: board_item.h:221
void SetSize(const wxSize &aSize)
Definition: pad.h:232
void NORMALIZE_ANGLE_180(T &Angle)
Definition: trigo.h:398
void SetDelta(const wxSize &aSize)
Definition: pad.h:239
coord_type GetBottom() const
Definition: box2.h:183
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:229
virtual void Rotate(const wxPoint &aRotCentre, double aAngle) override
Rotate this object.
Definition: pcb_shape.cpp:109
bool IsAperturePad() const
Definition: pad.h:378
a test point pad
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:411
int GetThermalGap() const
Definition: pad.h:499
void onCornerSizePercentChange(wxCommandEvent &event) override
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:590
bool GetKeepTopBottom() const
Definition: pad.h:563
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:97
void SetSketchModeGraphicItems(bool aEnabled)
Turn on/off sketch mode for graphic items (DRAWSEGMENTs, texts).
Definition: pcb_painter.h:128
std::unique_ptr< PAD > m_Pad_Master
bool IsFlipped() const
Definition: pad.cpp:201
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:208
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:116
const SEG & GetSeg() const
const VC_SETTINGS & GetSettings() const
Apply VIEW_CONTROLS settings from an object.
Plated through hole pad.
This file contains miscellaneous commonly used macros and functions.
bool TransferDataFromWindow() override
Transfer data out of the GUI.
FP_TEXT & Value()
read/write accessors:
Definition: footprint.h:499
void SetPadToDieLength(int aLength)
Definition: pad.h:383
void SetProperty(PAD_PROP aProperty)
Definition: pad.cpp:587
Classes used in Pcbnew, CvPcb and GerbView.
FP_TEXT & Reference()
Definition: footprint.h:500
a pad used as heat sink, usually in SMD footprints
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:72
int GetLineThickness(PCB_LAYER_ID aLayer) const
Return the default graphic segment thickness from the layer class for the given layer.
ZONE_CONNECTION GetZoneConnection() const
Definition: pad.h:476
KIGFX::ORIGIN_VIEWITEM * m_axisOrigin
PCB specific render settings.
Definition: pcb_painter.h:64
virtual void Move(const wxPoint &aMoveVector) override
Move this object.
Definition: pcb_shape.cpp:97
void SetLocalSolderMaskMargin(int aMargin)
Definition: pad.h:387
PAD_SHAPE
The set of pad shapes, used with PAD::{Set,Get}Shape() DO NOT REORDER, legacy_plugin is dependent on ...
Definition: pad_shapes.h:33
void Transform(std::vector< std::shared_ptr< PCB_SHAPE >> *aList=nullptr, int aDuplicateCount=0)
Apply geometric transform (rotation, move, scale) defined in dialog aDuplicate = 1 .
void onAddPrimitive(wxCommandEvent &event) override
const wxPoint & GetOffset() const
Definition: pad.h:250
void OnCancel(wxCommandEvent &event) override
#define PAD_PROPERTIES_DLG_NAME
DIALOG_PAD_PROPERTIES, derived from DIALOG_PAD_PROPERTIES_BASE, created by wxFormBuilder.
static PAD_SHAPE code_shape[]
#define CONN_DLG_TYPE
const wxSize & GetDrillSize() const
Definition: pad.h:243
like PAD_PTH, but not plated
std::string FormatAngle(double aAngle)
Function FormatAngle converts aAngle from board units to a string appropriate for writing to file.
Definition: base_units.cpp:520
void Show(bool aShow, bool aResize=false)
Show/hide the label, widget and units label.
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:504
pads are covered by copper
int GetThermalSpokeWidth() const
Definition: pad.h:491
void updatePadLayersList(LSET layer_mask, bool remove_unconnected, bool keep_top_bottom)
Updates the CheckBox states in pad layers list, based on the layer_mask (if non-empty) or the default...
double GetOrientation() const
Return the rotation angle of the pad in a variety of units (the basic call returns tenths of degrees)...
Definition: pad.h:349
VECTOR2< double > VECTOR2D
Definition: vector2d.h:622
void SetPos0(const wxPoint &aPos)
Definition: pad.h:226
void OnSetLayers(wxCommandEvent &event) override
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
void Flip(const wxPoint &aCentre, bool aFlipLeftRight) override
Flip this object, i.e.
Definition: pad.cpp:604
void SetThermalGap(int aGap)
Definition: pad.h:498
void OnSetCopperLayers(wxCommandEvent &event) override
bool transferDataToPad(PAD *aPad)
Copy values from dialog field to aPad's members.
Represent a set of closed polygons.
SHAPE_T
Definition: eda_shape.h:40
int ShowQuasiModal()
void ListSet(const wxString &aList)
Add a list of items.
coord_type GetWidth() const
Definition: box2.h:180
void SetDrillSize(const wxSize &aSize)
Definition: pad.h:242
const wxSize & GetSize() const
Definition: pad.h:233
Inactive layers are shown normally (no high-contrast mode)
void SetSelectedNetcode(int aNetcode)
void onCornerRadiusChange(wxCommandEvent &event) override
Class DIALOG_PAD_PROPERTIES_BASE.
void SetDrawAtZero(bool aDrawFlag)
Set the draw at zero flag.
Smd pad, used in BGA footprints.
void SetStealsFocus(bool aStealsFocus)
Set whether focus is taken on certain events (mouseover, keys, etc).
virtual const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: pad.cpp:1329
void OnUpdateUINonCopperWarning(wxUpdateUIEvent &event) override
void OnResize(wxSizeEvent &event)
void OnPadShapeSelection(wxCommandEvent &event) override
void PadTypeSelected(wxCommandEvent &event) override
void SetRemoveUnconnected(bool aSet)
Set the unconnected removal property.
Definition: pad.h:556
static LSET InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
Definition: lset.cpp:710
static LSET PTHMask()
layer set for a through hole pad
Definition: pad.cpp:166
wxString GetLastPadNumber() const
Definition: pad_tool.h:62
void onPrimitiveDClick(wxMouseEvent &event) override
Called on a double click on the basic shapes list.
const wxString & GetNumber() const
Definition: pad.h:129
void SetHighContrast(bool aEnabled)
Turns on/off high contrast display mode.
An interface for classes handling user events controlling the view behavior such as zooming,...
PAD_SHAPE GetShape() const
Definition: pad.h:170
a fiducial (usually a smd) local to the parent footprint
#define _(s)
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
void SetLayerColor(int aLayer, const COLOR4D &aColor)
Change the color used to draw a layer.
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:154
#define SELECTED
void OnDrillShapeSelected(wxCommandEvent &event) override
void SetWidth(int aWidth)
Definition: eda_shape.h:88
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pad.h:368
void SetZoneConnection(ZONE_CONNECTION aType)
Definition: pad.h:475
void SetNetInfo(NETINFO_LIST *aNetInfoList)
void onGeometryTransform(wxCommandEvent &event) override
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: pad.h:198
bool IsOnCopperLayer() const override
Definition: pad.h:218
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
void SetRoundRectRadiusRatio(double aRadiusScale)
Has meaning only for rounded rectangle pads.
Definition: pad.cpp:270
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
PAD_ATTRIB
The set of pad shapes, used with PAD::{Set,Get}Attribute().
Definition: pad_shapes.h:79
void SetGridSize(const VECTOR2D &aGridSize)
Set the grid size.
int GetLocalClearance(wxString *aSource) const override
Return any local clearances set in the "classic" (ie: pre-rule) system.
Definition: pad.cpp:700
void StartDrawing()
Begin drawing if it was stopped previously.
int GetHeight() const
Definition: eda_rect.h:110
void SetDrillShape(PAD_DRILL_SHAPE_T aShape)
Definition: pad.h:353
bool Show(bool show) override
void UpdateColors()
Update the color settings in the painter and GAL.
A dialog to edit basic polygonal shape parameters.
double GetLocalSolderPasteMarginRatio() const
Definition: pad.h:396
PAD_PROP getSelectedProperty()
Return the pad property currently selected.
void SetRoundRectCornerRadius(double aRadius)
Has meaning only for rounded rectangle pads.
Definition: pad.cpp:261
int GetRoundRectCornerRadius() const
Definition: pad.cpp:255
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
const wxSize & GetDelta() const
Definition: pad.h:240
FOOTPRINT * GetParent() const
Definition: pad.cpp:1352
void SetChamferPositions(int aPositions)
Has meaning only for chamfered rectangular pads.
Definition: pad.h:541
bool Show(bool aShow) override
Definition: seg.h:40
EDA_UNITS
Definition: eda_units.h:38
void OnPrimitiveSelection(wxListEvent &event) override
Called on selection/deselection of a basic shape.
EDA_UNITS m_units
Definition: dialog_shim.h:200
bool IsFlipped() const
Definition: footprint.h:277
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
Use thermal relief for pads.
void onEditPrimitive(wxCommandEvent &event) override
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
virtual void SetUnits(EDA_UNITS aUnits)
Normally not needed (as the UNIT_BINDER inherits from the parent frame), but can be used to set to DE...
Definition: unit_binder.cpp:92
double GetOrientationDegrees() const
Definition: footprint.h:191
void TransformShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, PCB_LAYER_ID aLayer, int aClearanceValue, int aMaxError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the pad shape to a closed polygon.
Definition: pad.cpp:1467
bool TransferDataFromWindow() override
Updates the different parameters for the component being edited.
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:281
static LSET ApertureMask()
layer set for an aperture pad
Definition: pad.cpp:194
void SetLayerSet(LSET aLayers) override
Definition: pad.h:367
void PadOrientEvent(wxCommandEvent &event) override
CUST_PAD_SHAPE_IN_ZONE GetCustomShapeInZoneOpt() const
Definition: pad.h:188
virtual bool Validate(double aMin, double aMax, EDA_UNITS aUnits=EDA_UNITS::UNSCALED)
Validate the control against the given range, informing the user of any errors found.
multilayer pads, usually with holes
Definition: layer_ids.h:209
bool IsType(FRAME_T aType) const
a fiducial (usually a smd) for the full board
double GetChamferRectRatio() const
Definition: pad.h:532
PAD_PROP
Ghe set of pad properties used in Gerber files (Draw files, and P&P files) to define some properties ...
Definition: pad_shapes.h:95
wxPoint GetPosition() const override
Definition: pad.h:178
void onDeletePrimitive(wxCommandEvent &event) override
Event handlers of basic shapes list panel.
void SetLocalSolderPasteMargin(int aMargin)
Definition: pad.h:394
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
Definition: pns_item.h:265
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: pad.h:354
no special fabrication property
void onDuplicatePrimitive(wxCommandEvent &event) override
void SetSketchMode(int aItemLayer, bool aEnabled)
Turn on/off sketch mode for given item layer.
Definition: pcb_painter.h:107
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65
PAD_ATTRIB GetAttribute() const
Definition: pad.h:371
void SetLastEditTime(timestamp_t aTime)
Definition: footprint.h:341
void SetNumber(const wxString &aNumber)
Set the pad number (note that it can be alphanumeric, such as the array reference "AA12").
Definition: pad.h:128
#define APERTURE_DLG_TYPE
Definition: layer_ids.h:71
virtual void SetValue(int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
void SetPosition(const wxPoint &aPos) override
Definition: pad.h:172
#define PTH_DLG_TYPE
VECTOR2I A
Definition: seg.h:48
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
Handle the component boundary box.
Definition: eda_rect.h:42
void SetShape(SHAPE_T aShape)
Definition: eda_shape.h:91
void TransformOvalToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aStart, const wxPoint &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:73
PCB_DRAW_PANEL_GAL * m_padPreviewGAL
coord_type GetHeight() const
Definition: box2.h:181
void OnOffsetCheckbox(wxCommandEvent &event) override
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true) override
Revert the commit by restoring the modified items state.
Pads are not covered.
wxPoint GetPosition() const override
Definition: footprint.h:186
void MergePrimitivesAsPolygon(SHAPE_POLY_SET *aMergedPolygon, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Merge all basic shapes to a SHAPE_POLY_SET.
void SetGridVisibility(bool aVisibility)
Set the visibility setting of the grid.
#define SELECTED_ITEMS_LAYER
virtual long long int GetValue()
Return the current value in Internal Units.
static PAD_ATTRIB code_type[]
wxString StringFromValue(EDA_UNITS aUnits, double aValue, bool aAddUnitSymbol, EDA_DATA_TYPE aType)
Convert a value to a string using double notation.
Definition: base_units.cpp:204
void SetShape(PAD_SHAPE aShape)
Set the new shape of this pad.
Definition: pad.h:161
int GetChamferPositions() const
Definition: pad.h:542
bool padValuesOK()
test if all values are acceptable for the pad
constexpr int delta
a pad with a castellated through hole
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
Definition: pad.cpp:187
void SetCoordType(ORIGIN_TRANSFORMS::COORD_TYPES_T aCoordType)
Set the current origin transform mode.
Definition: unit_binder.h:177
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:318
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:54
GAL_TYPE GetBackend() const
Return the type of backend currently used by GAL canvas.
const Vec & GetSize() const
Definition: box2.h:172
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset intersection For aFastMode meaning, see function booleanOp.
coord_type GetLeft() const
Definition: box2.h:186
BOARD * GetBoard() const
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:68
virtual void SetDoubleValue(double aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
void SetBoundary(const BOX2D &aBoundary)
Set limits for view area.
Definition: view.h:274
virtual double GetDoubleValue()
Return the current value in Internal Units.
Definition: pad.h:57
void ShowPadPropertiesDialog(PAD *aPad)
void SetChamferRectRatio(double aChamferScale)
Has meaning only for chamfered rectangular pads.
Definition: pad.cpp:278
std::vector< PCB_SHAPE * > m_highlight
virtual wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition: fp_text.cpp:411
int GetWidth() const
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: pad.cpp:173
static constexpr int Millimeter2iu(double mm)
int GetPadToDieLength() const
Definition: pad.h:384
A dialog to apply geometry transforms to a shape or set of shapes (move, rotate around origin,...
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
static const int UNCONNECTED
Constant that forces initialization of a netinfo item to the NETINFO_ITEM ORPHANED (typically -1) whe...
Definition: netinfo.h:367
bool GetRemoveUnconnected() const
Definition: pad.h:557
#define SMD_DLG_TYPE
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
void StopDrawing()
Prevent the GAL canvas from further drawing until it is recreated or StartDrawing() is called.
const std::vector< std::shared_ptr< PCB_SHAPE > > & GetPrimitives() const
Accessor to the basic shape list for custom-shaped pads.
Definition: pad.h:301
PAD_SHAPE GetAnchorPadShape() const
Definition: pad.h:183
void Enable(bool aEnable)
Enable/disable the label, widget and units label.
A dialog to edit basic shape parameters.
void SetOrientation(double aAngle)
Set the rotation angle of the pad.
Definition: pad.cpp:595
bool TransferDataFromWindow() override
Transfer data out of the GUI.
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1512
void OnUpdateUI(wxUpdateUIEvent &event) override
void SetAnchorPadShape(PAD_SHAPE aShape)
Set the shape of the anchor pad for custom shaped pads.
Definition: pad.h:209
#define BRIGHTENED
item is drawn with a bright contour
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103
virtual void ChangeValue(int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion WITHOUT trigger...
VECTOR2I B
Definition: seg.h:49