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_clearance( aParent, m_clearanceLabel, m_clearanceCtrl, m_clearanceUnits ),
135  m_maskMargin( aParent, m_maskMarginLabel, m_maskMarginCtrl, m_maskMarginUnits ),
136  m_pasteMargin( aParent, m_pasteMarginLabel, m_pasteMarginCtrl, m_pasteMarginUnits ),
137  m_pasteMarginRatio( aParent, m_pasteMarginRatioLabel, m_pasteMarginRatioCtrl,
138  m_pasteMarginRatioUnits ),
139  m_spokeWidth( aParent, m_spokeWidthLabel, m_spokeWidthCtrl, m_spokeWidthUnits ),
140  m_thermalGap( aParent, m_thermalGapLabel, m_thermalGapCtrl, m_thermalGapUnits ),
141  m_pad_orientation( aParent, m_PadOrientText, m_cb_padrotation, m_orientationUnits )
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_cbShowPadOutline->SetValue( m_sketchPreview );
159 
162 
164  m_dummyPad = new PAD( (FOOTPRINT*) nullptr );
165 
166  if( aPad )
167  {
168  SetTitle( _( "Pad Properties" ) );
169 
170  *m_dummyPad = *aPad;
172  }
173  else
174  {
175  SetTitle( _( "Default Pad Properties for Add Pad Tool" ) );
176 
178  }
179 
180  if( m_isFpEditor )
181  {
182  m_padNetLabel->Show( false );
183  m_padNetSelector->Show( false );
184  }
185 
186  // Pad needs to have a parent for painting; use the parent board for its design settings
187  if( !m_dummyPad->GetParent() )
189 
196 
198 
201 
202  initValues();
203 
204  wxFont infoFont = KIUI::GetInfoFont( this );
205  m_copperLayersLabel->SetFont( infoFont );
206  m_techLayersLabel->SetFont( infoFont );
207  m_parentInfo->SetFont( infoFont );
208 
209  infoFont.SetStyle( wxFONTSTYLE_ITALIC );
210  m_nonCopperNote->SetFont( infoFont );
211  m_staticTextInfoPaste->SetFont( infoFont );
212  m_staticTextInfoNegVal->SetFont( infoFont );
213  m_staticTextInfoPosValue->SetFont( infoFont );
214  m_staticTextPrimitiveListWarning->SetFont( infoFont );
215 
216  // Do not allow locking items in the footprint editor
217  m_locked->Show( !m_isFpEditor );
218 
219  // Usually, TransferDataToWindow is called by OnInitDialog
220  // calling it here fixes all widget sizes so FinishDialogSettings can safely fix minsizes
222 
223  // Initialize canvas to be able to display the dummy pad:
224  prepareCanvas();
225 
227  m_sdbSizerOK->SetDefault();
228  m_canUpdate = true;
229 
230  m_padNetSelector->Connect( NET_SELECTED,
231  wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ),
232  nullptr, this );
233 
234  // Now all widgets have the size fixed, call FinishDialogSettings
236 
237  // Update widgets
238  wxUpdateUIEvent dummyUI;
239  OnUpdateUI( dummyUI );
240 
241  // Post a dummy size event to force the pad preview panel to update the
242  // view: actual size, best zoom ... after the frame is shown
243  PostSizeEvent();
244 }
245 
246 
248 {
249  m_padNetSelector->Disconnect( NET_SELECTED,
250  wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ),
251  nullptr, this );
252 
253  delete m_dummyPad;
254  delete m_axisOrigin;
255 }
256 
257 
258 // Store the pad draw option during a session.
260 
261 
262 void DIALOG_PAD_PROPERTIES::OnInitDialog( wxInitDialogEvent& event )
263 {
264  m_selectedColor = COLOR4D( 1.0, 1.0, 1.0, 0.7 );
265 
266  // Needed on some WM to be sure the pad is redrawn according to the final size
267  // of the canvas, with the right zoom factor
268  redraw();
269 }
270 
271 
272 void DIALOG_PAD_PROPERTIES::OnCancel( wxCommandEvent& event )
273 {
274  // Mandatory to avoid m_panelShowPadGal trying to draw something
275  // in a non valid context during closing process:
277 
278  // Now call default handler for wxID_CANCEL command event
279  event.Skip();
280 }
281 
282 
284 {
285  // Enable or disable the widgets in page managing custom shape primitives
286  m_listCtrlPrimitives->Enable( aEnable );
287  m_buttonDel->Enable( aEnable );
288  m_buttonEditShape->Enable( aEnable );
289  m_buttonAddShape->Enable( aEnable );
290  m_buttonDup->Enable( aEnable );
291  m_buttonGeometry->Enable( aEnable );
292 }
293 
294 
296 {
297  // Initialize the canvas to display the pad
298  m_padPreviewGAL = new PCB_DRAW_PANEL_GAL( m_boardViewPanel, -1, wxDefaultPosition,
299  wxDefaultSize,
301  m_parent->GetCanvas()->GetBackend() );
302 
303  m_padPreviewSizer->Add( m_padPreviewGAL, 12, wxEXPAND | wxALL, 5 );
304 
305  // Show the X and Y axis. It is useful because pad shape can have an offset
306  // or be a complex shape.
307  KIGFX::COLOR4D axis_color = LIGHTBLUE;
308 
310  Millimeter2iu( 0.2 ),
312  m_axisOrigin->SetDrawAtZero( true );
313 
316  m_padPreviewGAL->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
317 
318  KIGFX::VIEW_CONTROLS* parentViewControls = m_parent->GetCanvas()->GetViewControls();
319  m_padPreviewGAL->GetViewControls()->ApplySettings( parentViewControls->GetSettings() );
320 
321  m_padPreviewGAL->Show();
322 
324 
325  // fix the pad render mode (filled/not filled)
326  auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
327  bool sketchMode = m_cbShowPadOutline->IsChecked();
328  settings->SetSketchMode( LAYER_PADS_TH, sketchMode );
329  settings->SetSketchMode( LAYER_PAD_FR, sketchMode );
330  settings->SetSketchMode( LAYER_PAD_BK, sketchMode );
331  settings->SetSketchModeGraphicItems( sketchMode );
332 
333  settings->SetHighContrast( false );
334  settings->SetContrastModeDisplay( HIGH_CONTRAST_MODE::NORMAL );
335 
336  // gives a non null grid size (0.001mm) because GAL layer does not like a 0 size grid:
337  double gridsize = 0.001 * IU_PER_MM;
338  view->GetGAL()->SetGridSize( VECTOR2D( gridsize, gridsize ) );
339 
340  // And do not show the grid:
341  view->GetGAL()->SetGridVisibility( false );
342  view->Add( m_dummyPad );
343  view->Add( m_axisOrigin );
344 
346  Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_PAD_PROPERTIES::OnResize ) );
347 }
348 
349 
351 {
352  // Note: use ChangeValue() to avoid generating a wxEVT_TEXT event
354 
357 
360 }
361 
362 
363 void DIALOG_PAD_PROPERTIES::onCornerRadiusChange( wxCommandEvent& event )
364 {
367  {
368  return;
369  }
370 
371  if( m_cornerRadius.GetValue() < 0 )
372  m_cornerRadiusCtrl->ChangeValue( "0" );
373 
376 
379 
380  redraw();
381 }
382 
383 
385 {
388  {
389  return;
390  }
391 
392  wxObject* ctrl = event.GetEventObject();
393  wxString value = event.GetString();
394  bool changed = false;
395 
396  if( ctrl == m_cornerRatioCtrl || ctrl == m_mixedCornerRatioCtrl )
397  {
398  double ratioPercent;
399 
400  if( value.ToDouble( &ratioPercent ) )
401  {
402  // Clamp ratioPercent to acceptable value (0.0 to 50.0)
403  if( ratioPercent < 0.0 )
404  {
407  }
408  else if( ratioPercent > 50.0 )
409  {
412  }
413 
414  if( ctrl == m_cornerRatioCtrl )
415  m_mixedCornerRatioCtrl->ChangeValue( value );
416  else
417  m_cornerRatioCtrl->ChangeValue( value );
418 
419  changed = true;
420  }
421  }
422  else if( ctrl == m_chamferRatioCtrl || ctrl == m_mixedChamferRatioCtrl )
423  {
424  double ratioPercent;
425 
426  if( value.ToDouble( &ratioPercent ) )
427  {
428  // Clamp ratioPercent to acceptable value (0.0 to 50.0)
429  if( ratioPercent < 0.0 )
430  {
433  }
434  else if( ratioPercent > 50.0 )
435  {
438  }
439 
440  if( ctrl == m_chamferRatioCtrl )
441  m_mixedChamferRatioCtrl->ChangeValue( value );
442  else
443  m_chamferRatioCtrl->ChangeValue( value );
444 
445  changed = true;
446  }
447  }
448 
449  if( changed )
450  {
453  }
454 
455  redraw();
456 }
457 
458 
460 {
461  wxString msg;
462 
463  // Disable pad net name wxTextCtrl if the caller is the footprint editor
464  // because nets are living only in the board managed by the board editor
466 
467  m_PadLayerAdhCmp->SetLabel( m_board->GetLayerName( F_Adhes ) );
468  m_PadLayerAdhCu->SetLabel( m_board->GetLayerName( B_Adhes ) );
470  m_PadLayerPateCu->SetLabel( m_board->GetLayerName( B_Paste ) );
472  m_PadLayerSilkCu->SetLabel( m_board->GetLayerName( B_SilkS ) );
473  m_PadLayerMaskCmp->SetLabel( m_board->GetLayerName( F_Mask ) );
474  m_PadLayerMaskCu->SetLabel( m_board->GetLayerName( B_Mask ) );
475  m_PadLayerECO1->SetLabel( m_board->GetLayerName( Eco1_User ) );
476  m_PadLayerECO2->SetLabel( m_board->GetLayerName( Eco2_User ) );
478 
479  if( m_currentPad )
480  {
481  m_locked->SetValue( m_currentPad->IsLocked() );
483 
484  FOOTPRINT* footprint = m_currentPad->GetParent();
485 
486  if( footprint )
487  {
488  double angle = m_dummyPad->GetOrientation();
489  angle -= footprint->GetOrientation();
491 
492  // Display parent footprint info
493  msg.Printf( _("Footprint %s (%s), %s, rotated %g deg"),
494  footprint->Reference().GetShownText(),
495  footprint->Value().GetShownText(),
496  footprint->IsFlipped() ? _( "back side (mirrored)" ) : _( "front side" ),
497  footprint->GetOrientationDegrees() );
498  }
499 
500  m_parentInfo->SetLabel( msg );
501  }
502  else
503  {
504  m_locked->Hide();
505  m_isFlipped = false;
506  }
507 
508  if( m_isFlipped )
509  {
510  // flip pad (up/down) around its position
511  m_dummyPad->Flip( m_dummyPad->GetPosition(), false );
512  }
513 
515 
517 
518  if( m_currentPad )
519  {
520  m_padNumCtrl->SetValue( m_dummyPad->GetNumber() );
521  }
522  else
523  {
524  PAD_TOOL* padTool = m_parent->GetToolManager()->GetTool<PAD_TOOL>();
525  m_padNumCtrl->SetValue( padTool->GetLastPadNumber() );
526  }
527 
529 
530  // Display current pad parameters units:
533 
536 
539 
540  m_offsetShapeOpt->SetValue( m_dummyPad->GetOffset() != wxPoint() );
543 
544  if( m_dummyPad->GetDelta().x )
545  {
547  m_trapAxisCtrl->SetSelection( 0 );
548  }
549  else
550  {
552  m_trapAxisCtrl->SetSelection( 1 );
553  }
554 
555  m_padToDieOpt->SetValue( m_dummyPad->GetPadToDieLength() != 0 );
557 
565 
566  switch( m_dummyPad->GetZoneConnection() )
567  {
568  default:
569  case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
570  case ZONE_CONNECTION::FULL: m_ZoneConnectionChoice->SetSelection( 1 ); break;
571  case ZONE_CONNECTION::THERMAL: m_ZoneConnectionChoice->SetSelection( 2 ); break;
572  case ZONE_CONNECTION::NONE: m_ZoneConnectionChoice->SetSelection( 3 ); break;
573  }
574 
576  m_ZoneCustomPadShape->SetSelection( 1 );
577  else
578  m_ZoneCustomPadShape->SetSelection( 0 );
579 
580  switch( m_dummyPad->GetShape() )
581  {
582  default:
583  case PAD_SHAPE::CIRCLE: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_CIRCLE ); break;
584  case PAD_SHAPE::OVAL: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_OVAL ); break;
585  case PAD_SHAPE::RECT: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_RECT ); break;
586  case PAD_SHAPE::TRAPEZOID: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_TRAPEZOID ); break;
587  case PAD_SHAPE::ROUNDRECT: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_ROUNDRECT ); break;
588 
590  if( m_dummyPad->GetRoundRectRadiusRatio() > 0.0 )
592  else
594  break;
595 
596  case PAD_SHAPE::CUSTOM:
599  else
601  break;
602  }
603 
612 
614 
616 
617  // Type of pad selection
618  bool aperture = m_dummyPad->GetAttribute() == PAD_ATTRIB::SMD && m_dummyPad->IsAperturePad();
619 
620  if( aperture )
621  {
622  m_padType->SetSelection( APERTURE_DLG_TYPE );
623  }
624  else
625  {
626  switch( m_dummyPad->GetAttribute() )
627  {
628  case PAD_ATTRIB::PTH: m_padType->SetSelection( PTH_DLG_TYPE ); break;
629  case PAD_ATTRIB::SMD: m_padType->SetSelection( SMD_DLG_TYPE ); break;
630  case PAD_ATTRIB::CONN: m_padType->SetSelection( CONN_DLG_TYPE ); break;
631  case PAD_ATTRIB::NPTH: m_padType->SetSelection( NPTH_DLG_TYPE ); break;
632  }
633  }
634 
635  switch( m_dummyPad->GetProperty() )
636  {
637  case PAD_PROP::NONE: m_choiceFabProperty->SetSelection( 0 ); break;
638  case PAD_PROP::BGA: m_choiceFabProperty->SetSelection( 1 ); break;
639  case PAD_PROP::FIDUCIAL_LOCAL: m_choiceFabProperty->SetSelection( 2 ); break;
640  case PAD_PROP::FIDUCIAL_GLBL: m_choiceFabProperty->SetSelection( 3 ); break;
641  case PAD_PROP::TESTPOINT: m_choiceFabProperty->SetSelection( 4 ); break;
642  case PAD_PROP::HEATSINK: m_choiceFabProperty->SetSelection( 5 ); break;
643  case PAD_PROP::CASTELLATED: m_choiceFabProperty->SetSelection( 6 ); break;
644  }
645 
646  // Ensure the pad property is compatible with the pad type
648  {
649  m_choiceFabProperty->SetSelection( 0 );
650  m_choiceFabProperty->Enable( false );
651  }
652 
654  m_holeShapeCtrl->SetSelection( 0 );
655  else
656  m_holeShapeCtrl->SetSelection( 1 );
657 
660 
661  // Update some dialog widgets state (Enable/disable options):
662  wxCommandEvent cmd_event;
663  OnPadShapeSelection( cmd_event );
664  OnOffsetCheckbox( cmd_event );
665 
666  // Update basic shapes list
668 }
669 
670 // A small helper function, to display coordinates:
671 static wxString formatCoord( EDA_UNITS aUnits, wxPoint aCoord )
672 {
673  return wxString::Format( wxT( "(X:%s Y:%s)" ),
674  MessageTextFromValue( aUnits, aCoord.x ),
675  MessageTextFromValue( aUnits, aCoord.y ) );
676 }
677 
679 {
680  m_listCtrlPrimitives->ClearAll();
681 
682  wxListItem itemCol;
683  itemCol.SetImage(-1);
684 
685  for( int ii = 0; ii < 5; ++ii )
686  m_listCtrlPrimitives->InsertColumn(ii, itemCol);
687 
688  wxString bs_info[5];
689 
690  for( unsigned ii = 0; ii < m_primitives.size(); ++ii )
691  {
692  const std::shared_ptr<PCB_SHAPE>& primitive = m_primitives[ii];
693 
694  for( wxString& s : bs_info )
695  s.Empty();
696 
697  bs_info[4] = _( "width" ) + wxS( " " )+ MessageTextFromValue( m_units,
698  primitive->GetWidth() );
699 
700  switch( primitive->GetShape() )
701  {
702  case SHAPE_T::SEGMENT:
703  bs_info[0] = _( "Segment" );
704  bs_info[1] = _( "from" ) + wxS( " " )+ formatCoord( m_units, primitive->GetStart() );
705  bs_info[2] = _( "to" ) + wxS( " " )+ formatCoord( m_units, primitive->GetEnd() );
706  break;
707 
708  case SHAPE_T::BEZIER:
709  bs_info[0] = _( "Bezier" );
710  bs_info[1] = _( "from" ) + wxS( " " )+ formatCoord( m_units, primitive->GetStart() );
711  bs_info[2] = _( "to" ) + wxS( " " )+ formatCoord( m_units, primitive->GetEnd() );
712  break;
713 
714  case SHAPE_T::ARC:
715  bs_info[0] = _( "Arc" );
716  bs_info[1] = _( "center" ) + wxS( " " )+ formatCoord( m_units, primitive->GetCenter() );
717  bs_info[2] = _( "start" ) + wxS( " " )+ formatCoord( m_units, primitive->GetStart() );
718  bs_info[3] = _( "angle" ) + wxS( " " )+ FormatAngle( primitive->GetArcAngle() );
719  break;
720 
721  case SHAPE_T::CIRCLE:
722  if( primitive->GetWidth() )
723  bs_info[0] = _( "ring" );
724  else
725  bs_info[0] = _( "circle" );
726 
727  bs_info[1] = formatCoord( m_units, primitive->GetStart() );
728  bs_info[2] = _( "radius" ) + wxS( " " )+ MessageTextFromValue( m_units,
729  primitive->GetRadius() );
730  break;
731 
732  case SHAPE_T::POLY:
733  bs_info[0] = _( "Polygon" );
734  bs_info[1] = wxString::Format( _( "corners count %d" ),
735  primitive->GetPolyShape().Outline( 0 ).PointCount() );
736  break;
737 
738  default:
739  bs_info[0] = _( "Unknown primitive" );
740  break;
741  }
742 
743  long tmp = m_listCtrlPrimitives->InsertItem( ii, bs_info[0] );
744  m_listCtrlPrimitives->SetItemData( tmp, ii );
745 
746  for( int jj = 0, col = 0; jj < 5; ++jj )
747  m_listCtrlPrimitives->SetItem( tmp, col++, bs_info[jj] );
748  }
749 
750  // Now columns are filled, ensure correct width of columns
751  for( unsigned ii = 0; ii < 5; ++ii )
752  m_listCtrlPrimitives->SetColumnWidth( ii, wxLIST_AUTOSIZE );
753 }
754 
755 
756 void DIALOG_PAD_PROPERTIES::OnResize( wxSizeEvent& event )
757 {
758  redraw();
759  event.Skip();
760 }
761 
762 
763 void DIALOG_PAD_PROPERTIES::onChangePadMode( wxCommandEvent& event )
764 {
765  m_sketchPreview = m_cbShowPadOutline->GetValue();
766 
768 
769  // fix the pad render mode (filled/not filled)
770  KIGFX::PCB_RENDER_SETTINGS* settings =
771  static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
772 
777 
778  settings->SetHighContrast( false );
780 
781  redraw();
782 }
783 
784 
785 void DIALOG_PAD_PROPERTIES::OnPadShapeSelection( wxCommandEvent& event )
786 {
787  switch( m_PadShapeSelector->GetSelection() )
788  {
789  case CHOICE_SHAPE_CIRCLE:
790  case CHOICE_SHAPE_OVAL:
791  case CHOICE_SHAPE_RECT:
792  m_shapePropsBook->SetSelection( 0 );
793  break;
794 
796  m_shapePropsBook->SetSelection( 1 );
797  break;
798 
800  {
801  m_shapePropsBook->SetSelection( 2 );
802 
803  // A reasonable default (from IPC-7351C)
804  if( m_dummyPad->GetRoundRectRadiusRatio() == 0.0 )
806 
807  break;
808  }
809 
811  m_shapePropsBook->SetSelection( 3 );
812 
813  // Reasonable default
814  if( m_dummyPad->GetChamferRectRatio() == 0.0 )
816 
817  // Ensure the displayed value is up to date:
819 
820  // A reasonable default is one corner chamfered (usual for some SMD pads).
821  if( !m_cbTopLeft->GetValue() && !m_cbTopRight->GetValue()
822  && !m_cbBottomLeft->GetValue() && !m_cbBottomRight->GetValue() )
823  {
824  m_cbTopLeft->SetValue( true );
825  m_cbTopRight->SetValue( false );
826  m_cbBottomLeft->SetValue( false );
827  m_cbBottomRight->SetValue( false );
828  }
829 
830  break;
831 
833  m_shapePropsBook->SetSelection( 4 );
834 
835  // Reasonable defaults (corner radius from IPC-7351C)
836  if( m_dummyPad->GetRoundRectRadiusRatio() == 0.0
837  && m_dummyPad->GetChamferRectRatio() == 0.0 )
838  {
839  if( m_dummyPad->GetRoundRectRadiusRatio() == 0.0 )
841 
842  if( m_dummyPad->GetChamferRectRatio() == 0.0 )
844  }
845 
846  // Ensure the displayed values are up to date:
849  break;
850 
851  case CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR: // PAD_SHAPE::CUSTOM, circular anchor
852  case CHOICE_SHAPE_CUSTOM_RECT_ANCHOR: // PAD_SHAPE::CUSTOM, rect anchor
853  m_shapePropsBook->SetSelection( 0 );
854  break;
855  }
856 
857  // Readjust props book size
858  wxSize size = m_shapePropsBook->GetSize();
859  size.y = m_shapePropsBook->GetPage( m_shapePropsBook->GetSelection() )->GetBestSize().y;
860  m_shapePropsBook->SetMaxSize( size );
861 
863  && m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR );
864 
865  m_offsetShapeOpt->Enable( m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CIRCLE
867  && m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CUSTOM_RECT_ANCHOR );
868 
869  if( !m_offsetShapeOpt->IsEnabled() )
870  m_offsetShapeOpt->SetValue( false );
871 
872  // Show/hide controls depending on m_offsetShapeOpt being enabled
873  m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
874  m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
875 
876  bool is_custom = m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
878 
879  enablePrimitivePage( is_custom );
880  m_staticTextcps->Enable( is_custom );
881  m_ZoneCustomPadShape->Enable( is_custom );
882 
884 
886 
887  for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
888  m_notebook->GetPage( i )->Layout();
889 
890  // Resize the dialog if its height is too small to show all widgets:
891  if( m_MainSizer->GetSize().y < m_MainSizer->GetMinSize().y )
892  m_MainSizer->SetSizeHints( this );
893 
894  redraw();
895 }
896 
897 
898 void DIALOG_PAD_PROPERTIES::OnDrillShapeSelected( wxCommandEvent& event )
899 {
901  redraw();
902 }
903 
904 
905 void DIALOG_PAD_PROPERTIES::PadOrientEvent( wxCommandEvent& event )
906 {
908  redraw();
909 }
910 
911 
913 {
914  m_rbCopperLayersSel->Clear();
915 
916  switch( m_padType->GetSelection() )
917  {
918  case PTH_DLG_TYPE:
919  m_rbCopperLayersSel->Append( _( "All copper layers" ) );
920  m_rbCopperLayersSel->Append( wxString::Format( _( "%s, %s and connected layers" ),
922  m_board->GetLayerName( B_Cu ) ) );
923  m_rbCopperLayersSel->Append( _( "Connected layers only" ) );
924  m_rbCopperLayersSel->Append( _( "None" ) );
925  break;
926 
927  case NPTH_DLG_TYPE:
928  m_rbCopperLayersSel->Append( wxString::Format( _( "%s and %s" ),
930  m_board->GetLayerName( B_Cu ) ) );
933  m_rbCopperLayersSel->Append( _( "None" ) );
934  break;
935 
936  case SMD_DLG_TYPE:
937  case CONN_DLG_TYPE:
940  break;
941 
942  case APERTURE_DLG_TYPE:
943  m_rbCopperLayersSel->Append( _( "None" ) );
944  break;
945  }
946 }
947 
948 
949 void DIALOG_PAD_PROPERTIES::PadTypeSelected( wxCommandEvent& event )
950 {
951  bool hasHole = true;
952  bool hasConnection = true;
953  bool hasProperty = true;
954 
955  switch( m_padType->GetSelection() )
956  {
957  case PTH_DLG_TYPE: hasHole = true; hasConnection = true; hasProperty = true; break;
958  case SMD_DLG_TYPE: hasHole = false; hasConnection = true; hasProperty = true; break;
959  case CONN_DLG_TYPE: hasHole = false; hasConnection = true; hasProperty = true; break;
960  case NPTH_DLG_TYPE: hasHole = true; hasConnection = false; hasProperty = false; break;
961  case APERTURE_DLG_TYPE: hasHole = false; hasConnection = false; hasProperty = true; break;
962  }
963 
964  // Update Layers dropdown list and selects the "best" layer set for the new pad type:
966 
967  if( !hasHole )
968  {
969  m_holeX.ChangeValue( 0 );
970  m_holeY.ChangeValue( 0 );
971  }
972  else if ( m_holeX.GetValue() == 0 && m_currentPad )
973  {
976  }
977 
978  if( !hasConnection )
979  {
980  m_padNumCtrl->ChangeValue( wxEmptyString );
982  m_padToDieOpt->SetValue( false );
983  }
984  else if( m_padNumCtrl->GetValue().IsEmpty() && m_currentPad )
985  {
986  m_padNumCtrl->ChangeValue( m_currentPad->GetNumber() );
988  }
989 
990  if( !hasProperty )
991  m_choiceFabProperty->SetSelection( 0 );
992 
993  m_choiceFabProperty->Enable( hasProperty );
994 
996 
997  redraw();
998 }
999 
1000 
1001 void DIALOG_PAD_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
1002 {
1003  // Enable/disable position
1004  m_posX.Enable( !m_locked->GetValue() || m_isFpEditor );
1005  m_posY.Enable( !m_locked->GetValue() || m_isFpEditor );
1006 
1007  bool hasHole = true;
1008  bool hasConnection = true;
1009 
1010  switch( m_padType->GetSelection() )
1011  {
1012  case PTH_DLG_TYPE: /* PTH */ hasHole = true; hasConnection = true; break;
1013  case SMD_DLG_TYPE: /* SMD */ hasHole = false; hasConnection = true; break;
1014  case CONN_DLG_TYPE: /* CONN */ hasHole = false; hasConnection = true; break;
1015  case NPTH_DLG_TYPE: /* NPTH */ hasHole = true; hasConnection = false; break;
1016  case APERTURE_DLG_TYPE: /* Aperture */ hasHole = false; hasConnection = false; break;
1017  }
1018 
1019  // Enable/disable hole controls
1020  m_holeShapeLabel->Enable( hasHole );
1021  m_holeShapeCtrl->Enable( hasHole );
1022  m_holeX.Enable( hasHole );
1023  m_holeY.Enable( hasHole && m_holeShapeCtrl->GetSelection() == 1 );
1024 
1025  // Enable/disable number and net
1026  m_padNumLabel->Enable( hasConnection );
1027  m_padNumCtrl->Enable( hasConnection );
1028 
1029  if( m_padNetLabel->IsShown() )
1030  {
1031  m_padNetLabel->Enable( hasConnection && m_canEditNetName && m_currentPad );
1032  m_padNetSelector->Enable( hasConnection && m_canEditNetName && m_currentPad );
1033  }
1034 
1035  // Enable/disable pad length-to-die
1036  m_padToDieOpt->Enable( hasConnection );
1037 
1038  if( !m_padToDieOpt->IsEnabled() )
1039  m_padToDieOpt->SetValue( false );
1040 
1041  // We can show/hide this here because it doesn't require the layout to be refreshed.
1042  // All the others have to be done in their event handlers because doing a layout here
1043  // causes infinite looping on MSW.
1044  m_padToDie.Show( m_padToDieOpt->GetValue() );
1045 
1046  // Enable/disable Copper Layers control
1047  m_rbCopperLayersSel->Enable( m_padType->GetSelection() != APERTURE_DLG_TYPE );
1048 
1049  LSET cu_set = m_dummyPad->GetLayerSet() & LSET::AllCuMask();
1050 
1051  switch( m_padType->GetSelection() )
1052  {
1053  case PTH_DLG_TYPE:
1054  if( !cu_set.any() )
1055  m_stackupImagesBook->SetSelection( 3 );
1056  else if( !m_dummyPad->GetRemoveUnconnected() )
1057  m_stackupImagesBook->SetSelection( 0 );
1058  else if( m_dummyPad->GetKeepTopBottom() )
1059  m_stackupImagesBook->SetSelection( 1 );
1060  else
1061  m_stackupImagesBook->SetSelection( 2 );
1062 
1063  break;
1064 
1065  case NPTH_DLG_TYPE:
1066  if( cu_set.test( F_Cu ) && cu_set.test( B_Cu ) )
1067  m_stackupImagesBook->SetSelection( 4 );
1068  else if( cu_set.test( F_Cu ) )
1069  m_stackupImagesBook->SetSelection( 5 );
1070  else if( cu_set.test( B_Cu ) )
1071  m_stackupImagesBook->SetSelection( 6 );
1072  else
1073  m_stackupImagesBook->SetSelection( 7 );
1074 
1075  break;
1076 
1077  case SMD_DLG_TYPE:
1078  case CONN_DLG_TYPE:
1079  case APERTURE_DLG_TYPE:
1080  m_stackupImagesBook->ChangeSelection( 3 );
1081  break;
1082  }
1083 }
1084 
1085 
1087 {
1088  bool isOnCopperLayer = ( m_dummyPad->GetLayerSet() & LSET::AllCuMask() ).any();
1089  m_nonCopperWarningBook->ChangeSelection( isOnCopperLayer ? 0 : 1 );
1090 }
1091 
1092 
1093 void DIALOG_PAD_PROPERTIES::updatePadLayersList( LSET layer_mask, bool remove_unconnected,
1094  bool keep_top_bottom )
1095 {
1097 
1098  switch( m_padType->GetSelection() )
1099  {
1100  case PTH_DLG_TYPE:
1101  if( !layer_mask.any() )
1102  layer_mask = PAD::PTHMask();
1103 
1104  if( !( layer_mask & LSET::AllCuMask() ).any() )
1105  m_rbCopperLayersSel->SetSelection( 3 );
1106  else if( !remove_unconnected )
1107  m_rbCopperLayersSel->SetSelection( 0 );
1108  else if( keep_top_bottom )
1109  m_rbCopperLayersSel->SetSelection( 1 );
1110  else
1111  m_rbCopperLayersSel->SetSelection( 2 );
1112 
1113  break;
1114 
1115  case SMD_DLG_TYPE:
1116  if( !layer_mask.any() )
1117  layer_mask = PAD::SMDMask();
1118 
1119  if( layer_mask.test( F_Cu ) )
1120  m_rbCopperLayersSel->SetSelection( 0 );
1121  else
1122  m_rbCopperLayersSel->SetSelection( 1 );
1123 
1124  break;
1125 
1126  case CONN_DLG_TYPE:
1127  if( !layer_mask.any() )
1128  layer_mask = PAD::ConnSMDMask();
1129 
1130  if( layer_mask.test( F_Cu ) )
1131  m_rbCopperLayersSel->SetSelection( 0 );
1132  else
1133  m_rbCopperLayersSel->SetSelection( 1 );
1134 
1135  break;
1136 
1137  case NPTH_DLG_TYPE:
1138  if( !layer_mask.any() )
1139  layer_mask = PAD::UnplatedHoleMask();
1140 
1141  if( layer_mask.test( F_Cu ) && layer_mask.test( B_Cu ) )
1142  m_rbCopperLayersSel->SetSelection( 0 );
1143  else if( layer_mask.test( F_Cu ) )
1144  m_rbCopperLayersSel->SetSelection( 1 );
1145  else if( layer_mask.test( B_Cu ) )
1146  m_rbCopperLayersSel->SetSelection( 2 );
1147  else
1148  m_rbCopperLayersSel->SetSelection( 3 );
1149 
1150  break;
1151 
1152  case APERTURE_DLG_TYPE:
1153  if( !layer_mask.any() )
1154  layer_mask = PAD::ApertureMask();
1155 
1156  m_rbCopperLayersSel->SetSelection( 0 );
1157  break;
1158  }
1159 
1160  m_PadLayerAdhCmp->SetValue( layer_mask[F_Adhes] );
1161  m_PadLayerAdhCu->SetValue( layer_mask[B_Adhes] );
1162 
1163  m_PadLayerPateCmp->SetValue( layer_mask[F_Paste] );
1164  m_PadLayerPateCu->SetValue( layer_mask[B_Paste] );
1165 
1166  m_PadLayerSilkCmp->SetValue( layer_mask[F_SilkS] );
1167  m_PadLayerSilkCu->SetValue( layer_mask[B_SilkS] );
1168 
1169  m_PadLayerMaskCmp->SetValue( layer_mask[F_Mask] );
1170  m_PadLayerMaskCu->SetValue( layer_mask[B_Mask] );
1171 
1172  m_PadLayerECO1->SetValue( layer_mask[Eco1_User] );
1173  m_PadLayerECO2->SetValue( layer_mask[Eco2_User] );
1174 
1175  m_PadLayerDraft->SetValue( layer_mask[Dwgs_User] );
1176 }
1177 
1178 
1180 {
1181  bool retVal = DIALOG_SHIM::Show( aShow );
1182 
1183  if( aShow )
1184  {
1185  // It *should* work to set the stackup bitmap in the constructor, but it doesn't.
1186  // wxWidgets needs to have these set when the panel is visible for some reason.
1187  // https://gitlab.com/kicad/code/kicad/-/issues/5534
1194  m_stackupImage7->SetBitmap( KiBitmap( BITMAPS::pads_npth ) );
1195 
1196  Layout();
1197  }
1198 
1199  return retVal;
1200 }
1201 
1202 
1203 void DIALOG_PAD_PROPERTIES::OnSetCopperLayers( wxCommandEvent& event )
1204 {
1206  redraw();
1207 }
1208 
1209 
1210 void DIALOG_PAD_PROPERTIES::OnSetLayers( wxCommandEvent& event )
1211 {
1213  redraw();
1214 }
1215 
1216 
1218 {
1219  bool error = transferDataToPad( m_dummyPad );
1220 
1221  wxArrayString error_msgs;
1222  wxArrayString warning_msgs;
1223  wxString msg;
1224  wxSize pad_size = m_dummyPad->GetSize();
1225  wxSize drill_size = m_dummyPad->GetDrillSize();
1226 
1228  {
1229  // allow 0-sized anchor pads
1230  }
1231  else if( m_dummyPad->GetShape() == PAD_SHAPE::CIRCLE )
1232  {
1233  if( pad_size.x <= 0 )
1234  warning_msgs.Add( _( "Warning: Pad size is less than zero." ) );
1235  }
1236  else
1237  {
1238  if( pad_size.x <= 0 || pad_size.y <= 0 )
1239  warning_msgs.Add( _( "Warning: Pad size is less than zero." ) );
1240  }
1241 
1242  // Test hole size against pad size
1243  if( m_dummyPad->IsOnCopperLayer() )
1244  {
1246  PCB_LAYER_ID layer = lset.Seq().at( 0 );
1247  int maxError = m_board->GetDesignSettings().m_MaxError;
1248  SHAPE_POLY_SET padOutline;
1249 
1250  m_dummyPad->TransformShapeWithClearanceToPolygon( padOutline, layer, 0, maxError,
1252 
1253  const SHAPE_SEGMENT* drillShape = m_dummyPad->GetEffectiveHoleShape();
1254  const SEG drillSeg = drillShape->GetSeg();
1255  SHAPE_POLY_SET drillOutline;
1256 
1257  TransformOvalToPolygon( drillOutline, (wxPoint) drillSeg.A, (wxPoint) drillSeg.B,
1258  drillShape->GetWidth(), maxError, ERROR_LOC::ERROR_INSIDE );
1259 
1260  drillOutline.BooleanSubtract( padOutline, SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
1261 
1262  if( drillOutline.BBox().GetWidth() > 0 || drillOutline.BBox().GetHeight() > 0 )
1263  {
1264  warning_msgs.Add( _( "Warning: Pad drill will leave no copper or drill shape and "
1265  "pad shape do not overlap." ) );
1266  }
1267  }
1268 
1269  if( m_dummyPad->GetLocalClearance() < 0 )
1270  warning_msgs.Add( _( "Warning: Negative local clearance values will have no effect." ) );
1271 
1272  // Some pads need a negative solder mask clearance (mainly for BGA with small pads)
1273  // However the negative solder mask clearance must not create negative mask size
1274  // Therefore test for minimal acceptable negative value
1276  {
1277  int absMargin = abs( m_dummyPad->GetLocalSolderMaskMargin() );
1278 
1280  {
1281  for( const std::shared_ptr<PCB_SHAPE>& shape : m_dummyPad->GetPrimitives() )
1282  {
1283  EDA_RECT shapeBBox = shape->GetBoundingBox();
1284 
1285  if( absMargin > shapeBBox.GetWidth() || absMargin > shapeBBox.GetHeight() )
1286  {
1287  warning_msgs.Add( _( "Warning: Negative solder mask clearances larger than "
1288  "some shape primitives. Results may be surprising." ) );
1289 
1290  break;
1291  }
1292  }
1293  }
1294  else if( absMargin > pad_size.x || absMargin > pad_size.y )
1295  {
1296  warning_msgs.Add( _( "Warning: Negative solder mask clearance larger than pad. No "
1297  "solder mask will be generated." ) );
1298  }
1299  }
1300 
1301  // Some pads need a positive solder paste clearance (mainly for BGA with small pads)
1302  // However, a positive value can create issues if the resulting shape is too big.
1303  // (like a solder paste creating a solder paste area on a neighbor pad or on the solder mask)
1304  // So we could ask for user to confirm the choice
1305  // For now we just check for disappearing paste
1306  wxSize paste_size;
1307  int paste_margin = m_dummyPad->GetLocalSolderPasteMargin();
1308  double paste_ratio = m_dummyPad->GetLocalSolderPasteMarginRatio();
1309 
1310  paste_size.x = pad_size.x + paste_margin + KiROUND( pad_size.x * paste_ratio );
1311  paste_size.y = pad_size.y + paste_margin + KiROUND( pad_size.y * paste_ratio );
1312 
1313  if( paste_size.x <= 0 || paste_size.y <= 0 )
1314  {
1315  warning_msgs.Add( _( "Warning: Negative solder paste margins larger than pad. No solder "
1316  "paste mask will be generated." ) );
1317  }
1318 
1319  LSET padlayers_mask = m_dummyPad->GetLayerSet();
1320 
1321  if( padlayers_mask == 0 )
1322  error_msgs.Add( _( "Error: pad has no layer." ) );
1323 
1324  if( !padlayers_mask[F_Cu] && !padlayers_mask[B_Cu] )
1325  {
1326  if( ( drill_size.x || drill_size.y ) && m_dummyPad->GetAttribute() != PAD_ATTRIB::NPTH )
1327  {
1328  warning_msgs.Add( _( "Warning: Plated through holes should normally have a copper pad "
1329  "on at least one layer." ) );
1330  }
1331  }
1332 
1333  if( error )
1334  error_msgs.Add( _( "Too large value for pad delta size." ) );
1335 
1336  switch( m_dummyPad->GetAttribute() )
1337  {
1338  case PAD_ATTRIB::NPTH: // Not plated, but through hole, a hole is expected
1339  case PAD_ATTRIB::PTH: // Pad through hole, a hole is also expected
1340  if( drill_size.x <= 0
1341  || ( drill_size.y <= 0 && m_dummyPad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ) )
1342  {
1343  warning_msgs.Add( _( "Warning: Through hole pad has no hole." ) );
1344  }
1345  break;
1346 
1347  case PAD_ATTRIB::CONN: // Connector pads are smd pads, just they do not have solder paste.
1348  if( padlayers_mask[B_Paste] || padlayers_mask[F_Paste] )
1349  {
1350  warning_msgs.Add( _( "Warning: Connector pads normally have no solder paste. Use an "
1351  "SMD pad instead." ) );
1352  }
1354 
1355  case PAD_ATTRIB::SMD: // SMD and Connector pads (One external copper layer only)
1356  {
1357  LSET innerlayers_mask = padlayers_mask & LSET::InternalCuMask();
1358 
1359  if( ( padlayers_mask[F_Cu] && padlayers_mask[B_Cu] ) || innerlayers_mask.count() != 0 )
1360  warning_msgs.Add( _( "Warning: SMD pad has no outer layers." ) );
1361  }
1362  break;
1363  }
1364 
1368  {
1369  warning_msgs.Add( _( "Warning: Fiducial property makes no sense on NPTH pads." ) );
1370  }
1371 
1374  {
1375  warning_msgs.Add( _( "Warning: Testpoint property makes no sense on NPTH pads." ) );
1376  }
1377 
1380  {
1381  warning_msgs.Add( _( "Warning: Heatsink property makes no sense of NPTH pads." ) );
1382  }
1383 
1386  {
1387  warning_msgs.Add( _( "Warning: Castellated property is for PTH pads." ) );
1388  }
1389 
1390  if( m_dummyPad->GetProperty() == PAD_PROP::BGA &&
1392  {
1393  warning_msgs.Add( _( "Warning: BGA property is for SMD pads." ) );
1394  }
1395 
1398  {
1400 
1401  if( m_cornerRatio.GetDoubleValue() < 0.0 )
1402  error_msgs.Add( _( "Error: Negative corner size." ) );
1403  else if( m_cornerRatio.GetDoubleValue() > 50.0 )
1404  warning_msgs.Add( _( "Warning: Corner size will make pad circular." ) );
1405  }
1406 
1407  // PADSTACKS TODO: this will need to check each layer in the pad...
1409  {
1410  SHAPE_POLY_SET mergedPolygon;
1411  m_dummyPad->MergePrimitivesAsPolygon( &mergedPolygon );
1412 
1413  if( mergedPolygon.OutlineCount() > 1 )
1414  error_msgs.Add( _( "Error: Custom pad shape must resolve to a single polygon." ) );
1415  }
1416 
1417 
1418  if( error_msgs.GetCount() || warning_msgs.GetCount() )
1419  {
1420  wxString title = error_msgs.GetCount() ? _( "Pad Properties Errors" )
1421  : _( "Pad Properties Warnings" );
1422  HTML_MESSAGE_BOX dlg( this, title );
1423 
1424  dlg.ListSet( error_msgs );
1425 
1426  if( warning_msgs.GetCount() )
1427  dlg.ListSet( warning_msgs );
1428 
1429  dlg.ShowModal();
1430  }
1431 
1432  return error_msgs.GetCount() == 0;
1433 }
1434 
1435 
1437 {
1438  if( !m_canUpdate )
1439  return;
1440 
1441  KIGFX::VIEW* view = m_padPreviewGAL->GetView();
1443 
1444  // The layer used to place primitive items selected when editing custom pad shapes
1445  // we use here a layer never used in a pad:
1446  #define SELECTED_ITEMS_LAYER Dwgs_User
1447 
1449  KIGFX::PCB_RENDER_SETTINGS* settings =
1450  static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
1452 
1453  view->Update( m_dummyPad );
1454 
1455  // delete previous items if highlight list
1456  while( m_highlight.size() )
1457  {
1458  delete m_highlight.back(); // the dtor also removes item from view
1459  m_highlight.pop_back();
1460  }
1461 
1462  // highlight selected primitives:
1463  long select = m_listCtrlPrimitives->GetFirstSelected();
1464 
1465  while( select >= 0 )
1466  {
1467  PCB_SHAPE* dummyShape = static_cast<PCB_SHAPE*>( m_primitives[select]->Clone() );
1468  dummyShape->SetLayer( SELECTED_ITEMS_LAYER );
1469  dummyShape->Rotate( wxPoint( 0, 0), m_dummyPad->GetOrientation() );
1470  dummyShape->Move( m_dummyPad->GetPosition() );
1471 
1472  view->Add( dummyShape );
1473  m_highlight.push_back( dummyShape );
1474 
1475  select = m_listCtrlPrimitives->GetNextSelected( select );
1476  }
1477 
1478  BOX2I bbox = m_dummyPad->ViewBBox();
1479 
1480  if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
1481  {
1482  // The origin always goes in the middle of the canvas; we want offsetting the pad
1483  // shape to move the pad, not the hole
1484  bbox.Move( -m_dummyPad->GetPosition() );
1485  int maxXExtent = std::max( abs( bbox.GetLeft() ), abs( bbox.GetRight() ) );
1486  int maxYExtent = std::max( abs( bbox.GetTop() ), abs( bbox.GetBottom() ) );
1487 
1488  // Don't blow up the GAL on too-large numbers
1489  if( maxXExtent > INT_MAX / 4 )
1490  maxXExtent = INT_MAX / 4;
1491 
1492  if( maxYExtent > INT_MAX / 4 )
1493  maxYExtent = INT_MAX / 4;
1494 
1495  BOX2D viewBox( m_dummyPad->GetPosition(), {0, 0} );
1496  BOX2D canvasBox( m_dummyPad->GetPosition(), {0, 0} );
1497  viewBox.Inflate( maxXExtent * 1.4, maxYExtent * 1.4 ); // add a margin
1498  canvasBox.Inflate( maxXExtent * 2.0, maxYExtent * 2.0 );
1499 
1500  view->SetBoundary( canvasBox );
1501 
1502  // Autozoom
1503  view->SetViewport( viewBox );
1504 
1507  }
1508 }
1509 
1510 
1512 {
1513  if( !wxDialog::TransferDataToWindow() )
1514  return false;
1515 
1516  if( !m_panelGeneral->TransferDataToWindow() )
1517  return false;
1518 
1519  if( !m_localSettingsPanel->TransferDataToWindow() )
1520  return false;
1521 
1522  return true;
1523 }
1524 
1525 
1527 {
1528  BOARD_COMMIT commit( m_parent );
1529 
1530  if( !wxDialog::TransferDataFromWindow() )
1531  return false;
1532 
1533  if( !m_panelGeneral->TransferDataFromWindow() )
1534  return false;
1535 
1536  if( !m_localSettingsPanel->TransferDataFromWindow() )
1537  return false;
1538 
1539  if( !padValuesOK() )
1540  return false;
1541 
1543 
1544  PAD_TOOL* padTool = m_parent->GetToolManager()->GetTool<PAD_TOOL>();
1545  padTool->SetLastPadNumber( m_padMaster->GetNumber() );
1546 
1547  // m_padMaster is a pattern: ensure there is no net for this pad:
1549 
1550  if( !m_currentPad ) // Set current Pad parameters
1551  return true;
1552 
1553  commit.Modify( m_currentPad );
1554 
1555  // redraw the area where the pad was, without pad (delete pad on screen)
1557  m_parent->GetCanvas()->Refresh();
1559 
1560  // Update values
1564 
1565  m_currentPad->SetLocked( m_locked->GetValue() );
1566 
1567  if( !m_locked->GetValue() || m_isFpEditor )
1569 
1570  wxSize size;
1571  FOOTPRINT* footprint = m_currentPad->GetParent();
1572 
1574 
1575  size = m_padMaster->GetDelta();
1576  m_currentPad->SetDelta( size );
1577 
1580 
1581  wxPoint offset = m_padMaster->GetOffset();
1582  m_currentPad->SetOffset( offset );
1583 
1585 
1588 
1591 
1595 
1597 
1598  int padNetcode = NETINFO_LIST::UNCONNECTED;
1599 
1600  // For PAD_ATTRIB::NPTH, ensure there is no net name selected
1602  padNetcode = m_padNetSelector->GetSelectedNetcode();
1603 
1604  m_currentPad->SetNetCode( padNetcode );
1615 
1616  // rounded rect pads with radius ratio = 0 are in fact rect pads.
1617  // So set the right shape (and perhaps issues with a radius = 0)
1620  {
1622  }
1623 
1624  // Set the fabrication property:
1626 
1627  // define the way the clearance area is defined in zones
1629 
1630  if( m_isFlipped )
1631  {
1632  // flip pad (up/down) around its position
1633  m_currentPad->Flip( m_currentPad->GetPosition(), false );
1634  }
1635 
1636  if( footprint )
1637  {
1638  // compute the pos 0 value, i.e. pad position for footprint with orientation = 0
1639  // i.e. relative to footprint origin (footprint position)
1640  wxPoint pt = m_currentPad->GetPosition() - footprint->GetPosition();
1641  RotatePoint( &pt, -footprint->GetOrientation() );
1642  m_currentPad->SetPos0( pt );
1644  footprint->GetOrientation() );
1645  }
1646 
1648 
1649  // redraw the area where the pad was
1650  m_parent->GetCanvas()->Refresh();
1651 
1652  commit.Push( _( "Modify pad" ) );
1653 
1654  return true;
1655 }
1656 
1657 
1659 {
1660  PAD_PROP prop = PAD_PROP::NONE;
1661 
1662  switch( m_choiceFabProperty->GetSelection() )
1663  {
1664  case 0: prop = PAD_PROP::NONE; break;
1665  case 1: prop = PAD_PROP::BGA; break;
1666  case 2: prop = PAD_PROP::FIDUCIAL_LOCAL; break;
1667  case 3: prop = PAD_PROP::FIDUCIAL_GLBL; break;
1668  case 4: prop = PAD_PROP::TESTPOINT; break;
1669  case 5: prop = PAD_PROP::HEATSINK; break;
1670  case 6: prop = PAD_PROP::CASTELLATED; break;
1671  }
1672 
1673  return prop;
1674 }
1675 
1676 
1678 {
1679  wxString msg;
1680 
1681  if( !Validate() )
1682  return true;
1683  if( !m_panelGeneral->Validate() )
1684  return true;
1685  if( !m_localSettingsPanel->Validate() )
1686  return true;
1687  if( !m_spokeWidth.Validate( 0, INT_MAX ) )
1688  return false;
1689 
1690  aPad->SetAttribute( code_type[m_padType->GetSelection()] );
1691  aPad->SetShape( code_shape[m_PadShapeSelector->GetSelection()] );
1692 
1693  if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CUSTOM_RECT_ANCHOR )
1695  else
1697 
1698  if( aPad->GetShape() == PAD_SHAPE::CUSTOM )
1700 
1701  // Read pad clearances values:
1707  aPad->SetThermalGap( m_thermalGap.GetValue() );
1708 
1709  // And rotation
1711 
1712  switch( m_ZoneConnectionChoice->GetSelection() )
1713  {
1714  default:
1715  case 0: aPad->SetZoneConnection( ZONE_CONNECTION::INHERITED ); break;
1716  case 1: aPad->SetZoneConnection( ZONE_CONNECTION::FULL ); break;
1717  case 2: aPad->SetZoneConnection( ZONE_CONNECTION::THERMAL ); break;
1718  case 3: aPad->SetZoneConnection( ZONE_CONNECTION::NONE ); break;
1719  }
1720 
1721  aPad->SetPosition( wxPoint( m_posX.GetValue(), m_posY.GetValue() ) );
1722 
1723  if( m_holeShapeCtrl->GetSelection() == 0 )
1724  {
1726  aPad->SetDrillSize( wxSize( m_holeX.GetValue(), m_holeX.GetValue() ) );
1727  }
1728  else
1729  {
1731  aPad->SetDrillSize( wxSize( m_holeX.GetValue(), m_holeY.GetValue() ) );
1732  }
1733 
1734  if( aPad->GetShape() == PAD_SHAPE::CIRCLE )
1735  aPad->SetSize( wxSize( m_sizeX.GetValue(), m_sizeX.GetValue() ) );
1736  else
1737  aPad->SetSize( wxSize( m_sizeX.GetValue(), m_sizeY.GetValue() ) );
1738 
1739  // For a trapezoid, test delta value (be sure delta is not too large for pad size)
1740  // remember DeltaSize.x is the Y size variation
1741  bool error = false;
1742  wxSize delta( 0, 0 );
1743 
1744  if( aPad->GetShape() == PAD_SHAPE::TRAPEZOID )
1745  {
1746  // For a trapezoid, only one of delta.x or delta.y is not 0, depending on axis.
1747  if( m_trapAxisCtrl->GetSelection() == 0 )
1748  delta.x = m_trapDelta.GetValue();
1749  else
1750  delta.y = m_trapDelta.GetValue();
1751 
1752  if( delta.x < 0 && delta.x < -aPad->GetSize().y )
1753  {
1754  delta.x = -aPad->GetSize().y + 2;
1755  error = true;
1756  }
1757 
1758  if( delta.x > 0 && delta.x > aPad->GetSize().y )
1759  {
1760  delta.x = aPad->GetSize().y - 2;
1761  error = true;
1762  }
1763 
1764  if( delta.y < 0 && delta.y < -aPad->GetSize().x )
1765  {
1766  delta.y = -aPad->GetSize().x + 2;
1767  error = true;
1768  }
1769 
1770  if( delta.y > 0 && delta.y > aPad->GetSize().x )
1771  {
1772  delta.y = aPad->GetSize().x - 2;
1773  error = true;
1774  }
1775  }
1776 
1777  aPad->SetDelta( delta );
1778 
1779  if( m_offsetShapeOpt->GetValue() )
1780  aPad->SetOffset( wxPoint( m_offsetX.GetValue(), m_offsetY.GetValue() ) );
1781  else
1782  aPad->SetOffset( wxPoint() );
1783 
1784  // Read pad length die
1785  if( m_padToDieOpt->GetValue() )
1787  else
1788  aPad->SetPadToDieLength( 0 );
1789 
1790  aPad->SetNumber( m_padNumCtrl->GetValue() );
1792 
1793  int chamfers = 0;
1794 
1795  if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_RECT )
1796  {
1797  if( m_cbTopLeft->GetValue() )
1798  chamfers |= RECT_CHAMFER_TOP_LEFT;
1799 
1800  if( m_cbTopRight->GetValue() )
1801  chamfers |= RECT_CHAMFER_TOP_RIGHT;
1802 
1803  if( m_cbBottomLeft->GetValue() )
1804  chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1805 
1806  if( m_cbBottomRight->GetValue() )
1807  chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1808  }
1809  else if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT )
1810  {
1811  if( m_cbTopLeft1->GetValue() )
1812  chamfers |= RECT_CHAMFER_TOP_LEFT;
1813 
1814  if( m_cbTopRight1->GetValue() )
1815  chamfers |= RECT_CHAMFER_TOP_RIGHT;
1816 
1817  if( m_cbBottomLeft1->GetValue() )
1818  chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1819 
1820  if( m_cbBottomRight1->GetValue() )
1821  chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1822  }
1823  aPad->SetChamferPositions( chamfers );
1824 
1825  if( aPad->GetShape() == PAD_SHAPE::CUSTOM )
1826  {
1827  // The pad custom has a "anchor pad" (a basic shape: round or rect pad)
1828  // that is the minimal area of this pad, and is useful to ensure a hole
1829  // diameter is acceptable, and is used in Gerber files as flashed area
1830  // reference
1831  if( aPad->GetAnchorPadShape() == PAD_SHAPE::CIRCLE )
1832  aPad->SetSize( wxSize( m_sizeX.GetValue(), m_sizeX.GetValue() ) );
1833 
1834  // define the way the clearance area is defined in zones
1835  aPad->SetCustomShapeInZoneOpt( m_ZoneCustomPadShape->GetSelection() == 0 ?
1838  }
1839 
1840  switch( aPad->GetAttribute() )
1841  {
1842  case PAD_ATTRIB::PTH:
1843  break;
1844 
1845  case PAD_ATTRIB::CONN:
1846  case PAD_ATTRIB::SMD:
1847  // SMD and PAD_ATTRIB::CONN has no hole.
1848  // basically, SMD and PAD_ATTRIB::CONN are same type of pads
1849  // PAD_ATTRIB::CONN has just a default non technical layers that differs from SMD
1850  // and are intended to be used in virtual edge board connectors
1851  // However we can accept a non null offset,
1852  // mainly to allow complex pads build from a set of basic pad shapes
1853  aPad->SetDrillSize( wxSize( 0, 0 ) );
1854  break;
1855 
1856  case PAD_ATTRIB::NPTH:
1857  // Mechanical purpose only:
1858  // no net name, no pad name allowed
1859  aPad->SetNumber( wxEmptyString );
1861  break;
1862 
1863  default:
1864  wxFAIL_MSG( wxT( "DIALOG_PAD_PROPERTIES::transferDataToPad: unknown pad type" ) );
1865  break;
1866  }
1867 
1868  if( aPad->GetShape() == PAD_SHAPE::ROUNDRECT )
1869  {
1871  }
1872  else if( aPad->GetShape() == PAD_SHAPE::CHAMFERED_RECT )
1873  {
1875  {
1878  }
1879  else // Choice is CHOICE_SHAPE_CHAMFERED_RECT, no rounded corner
1880  {
1882  aPad->SetRoundRectRadiusRatio( 0 );
1883  }
1884  }
1885 
1886  aPad->SetProperty( getSelectedProperty() );
1887 
1888  LSET padLayerMask = LSET();
1889  int copperLayersChoice = m_rbCopperLayersSel->GetSelection();
1890 
1891  aPad->SetRemoveUnconnected( false );
1892  aPad->SetKeepTopBottom( false );
1893 
1894  switch( m_padType->GetSelection() )
1895  {
1896  case PTH_DLG_TYPE:
1897  switch( copperLayersChoice )
1898  {
1899  case 0:
1900  // All copper layers
1901  padLayerMask |= LSET::AllCuMask();
1902  break;
1903 
1904  case 1:
1905  // Front, back and connected
1906  padLayerMask |= LSET::AllCuMask();
1907  aPad->SetRemoveUnconnected( true );
1908  aPad->SetKeepTopBottom( true );
1909  break;
1910 
1911  case 2:
1912  // Connected only
1913  padLayerMask |= LSET::AllCuMask();
1914  aPad->SetRemoveUnconnected( true );
1915  break;
1916 
1917  case 3:
1918  // No copper layers
1919  break;
1920  }
1921 
1922  break;
1923 
1924  case NPTH_DLG_TYPE:
1925  switch( copperLayersChoice )
1926  {
1927  case 0: padLayerMask.set( F_Cu ).set( B_Cu ); break;
1928  case 1: padLayerMask.set( F_Cu ); break;
1929  case 2: padLayerMask.set( B_Cu ); break;
1930  default: break;
1931  }
1932 
1933  break;
1934 
1935  case SMD_DLG_TYPE:
1936  case CONN_DLG_TYPE:
1937  switch( copperLayersChoice )
1938  {
1939  case 0: padLayerMask.set( F_Cu ); break;
1940  case 1: padLayerMask.set( B_Cu ); break;
1941  }
1942 
1943  break;
1944 
1945  case APERTURE_DLG_TYPE:
1946  // no copper layers
1947  break;
1948  }
1949 
1950  if( m_PadLayerAdhCmp->GetValue() )
1951  padLayerMask.set( F_Adhes );
1952 
1953  if( m_PadLayerAdhCu->GetValue() )
1954  padLayerMask.set( B_Adhes );
1955 
1956  if( m_PadLayerPateCmp->GetValue() )
1957  padLayerMask.set( F_Paste );
1958 
1959  if( m_PadLayerPateCu->GetValue() )
1960  padLayerMask.set( B_Paste );
1961 
1962  if( m_PadLayerSilkCmp->GetValue() )
1963  padLayerMask.set( F_SilkS );
1964 
1965  if( m_PadLayerSilkCu->GetValue() )
1966  padLayerMask.set( B_SilkS );
1967 
1968  if( m_PadLayerMaskCmp->GetValue() )
1969  padLayerMask.set( F_Mask );
1970 
1971  if( m_PadLayerMaskCu->GetValue() )
1972  padLayerMask.set( B_Mask );
1973 
1974  if( m_PadLayerECO1->GetValue() )
1975  padLayerMask.set( Eco1_User );
1976 
1977  if( m_PadLayerECO2->GetValue() )
1978  padLayerMask.set( Eco2_User );
1979 
1980  if( m_PadLayerDraft->GetValue() )
1981  padLayerMask.set( Dwgs_User );
1982 
1983  aPad->SetLayerSet( padLayerMask );
1984 
1985  return error;
1986 }
1987 
1988 
1989 void DIALOG_PAD_PROPERTIES::OnOffsetCheckbox( wxCommandEvent& event )
1990 {
1991  if( m_offsetShapeOpt->GetValue() )
1992  {
1995  }
1996 
1997  // Show/hide controls depending on m_offsetShapeOpt being enabled
1998  m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
1999  m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
2000 
2001  for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
2002  m_notebook->GetPage( i )->Layout();
2003 
2004  OnValuesChanged( event );
2005 }
2006 
2007 
2008 void DIALOG_PAD_PROPERTIES::OnPadToDieCheckbox( wxCommandEvent& event )
2009 {
2010  if( m_padToDieOpt->GetValue() && m_currentPad )
2012 
2013  OnValuesChanged( event );
2014 }
2015 
2016 
2017 void DIALOG_PAD_PROPERTIES::OnValuesChanged( wxCommandEvent& event )
2018 {
2019  if( m_canUpdate )
2020  {
2022 
2023  // If the pad size has changed, update the displayed values for rounded rect pads.
2025 
2026  redraw();
2027  }
2028 }
2029 
2031 {
2032  long select = m_listCtrlPrimitives->GetFirstSelected();
2033 
2034  if( select < 0 )
2035  {
2036  wxMessageBox( _( "No shape selected" ) );
2037  return;
2038  }
2039 
2040  std::shared_ptr<PCB_SHAPE>& shape = m_primitives[select];
2041 
2042  if( shape->GetShape() == SHAPE_T::POLY )
2043  {
2044  DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, m_parent, shape.get() );
2045 
2046  if( dlg.ShowModal() != wxID_OK )
2047  return;
2048 
2049  dlg.TransferDataFromWindow();
2050  }
2051 
2052  else
2053  {
2054  DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, m_parent, shape.get() );
2055 
2056  if( dlg.ShowModal() != wxID_OK )
2057  return;
2058 
2059  dlg.TransferDataFromWindow();
2060  }
2061 
2063 
2064  if( m_canUpdate )
2065  {
2067  redraw();
2068  }
2069 }
2070 
2071 
2073 {
2074  // Called on a double click on the basic shapes list
2075  // To Do: highligth the primitive(s) currently selected.
2076  redraw();
2077 }
2078 
2079 
2080 void DIALOG_PAD_PROPERTIES::onPrimitiveDClick( wxMouseEvent& event )
2081 {
2082  editPrimitive();
2083 }
2084 
2085 
2086 void DIALOG_PAD_PROPERTIES::onEditPrimitive( wxCommandEvent& event )
2087 {
2088  editPrimitive();
2089 }
2090 
2091 
2092 void DIALOG_PAD_PROPERTIES::onDeletePrimitive( wxCommandEvent& event )
2093 {
2094  long select = m_listCtrlPrimitives->GetFirstSelected();
2095 
2096  if( select < 0 )
2097  return;
2098 
2099  // Multiple selections are allowed. get them and remove corresponding shapes
2100  std::vector<long> indexes;
2101  indexes.push_back( select );
2102 
2103  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2104  indexes.push_back( select );
2105 
2106  // Erase all select shapes
2107  for( unsigned ii = indexes.size(); ii > 0; --ii )
2108  m_primitives.erase( m_primitives.begin() + indexes[ii-1] );
2109 
2111 
2112  if( m_canUpdate )
2113  {
2115  redraw();
2116  }
2117 }
2118 
2119 
2120 void DIALOG_PAD_PROPERTIES::onAddPrimitive( wxCommandEvent& event )
2121 {
2122  // Ask user for shape type
2123  wxString shapelist[] = {
2124  _( "Segment" ),
2125  _( "Arc" ),
2126  _( "Bezier" ),
2127  _( "Ring/Circle" ),
2128  _( "Polygon" )
2129  };
2130 
2131  int type = wxGetSingleChoiceIndex( _( "Shape type:" ), _( "Add Primitive" ),
2132  arrayDim( shapelist ), shapelist, 0, this );
2133 
2134  // User pressed cancel
2135  if( type == -1 )
2136  return;
2137 
2139  SHAPE_T::POLY };
2140 
2141  PCB_SHAPE* primitive = new PCB_SHAPE();
2142  primitive->SetShape( listtype[type] );
2144  primitive->SetFilled( true );
2145 
2146  if( listtype[type] == SHAPE_T::POLY )
2147  {
2148  DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, m_parent, primitive );
2149 
2150  if( dlg.ShowModal() != wxID_OK )
2151  return;
2152  }
2153  else
2154  {
2155  DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, m_parent, primitive );
2156 
2157  if( dlg.ShowModal() != wxID_OK )
2158  return;
2159  }
2160 
2161  m_primitives.emplace_back( primitive );
2162 
2164 
2165  if( m_canUpdate )
2166  {
2168  redraw();
2169  }
2170 }
2171 
2172 
2173 void DIALOG_PAD_PROPERTIES::onGeometryTransform( wxCommandEvent& event )
2174 {
2175  long select = m_listCtrlPrimitives->GetFirstSelected();
2176 
2177  if( select < 0 )
2178  {
2179  wxMessageBox( _( "No shape selected" ) );
2180  return;
2181  }
2182 
2183  // Multiple selections are allowed. Build selected shapes list
2184  std::vector<std::shared_ptr<PCB_SHAPE>> shapeList;
2185  shapeList.emplace_back( m_primitives[select] );
2186 
2187  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2188  shapeList.emplace_back( m_primitives[select] );
2189 
2190  DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, m_parent, shapeList, false );
2191 
2192  if( dlg.ShowModal() != wxID_OK )
2193  return;
2194 
2195  dlg.Transform();
2196 
2198 
2199  if( m_canUpdate )
2200  {
2202  redraw();
2203  }
2204 }
2205 
2206 
2207 void DIALOG_PAD_PROPERTIES::onDuplicatePrimitive( wxCommandEvent& event )
2208 {
2209  long select = m_listCtrlPrimitives->GetFirstSelected();
2210 
2211  if( select < 0 )
2212  {
2213  wxMessageBox( _( "No shape selected" ) );
2214  return;
2215  }
2216 
2217  // Multiple selections are allowed. Build selected shapes list
2218  std::vector<std::shared_ptr<PCB_SHAPE>> shapeList;
2219  shapeList.emplace_back( m_primitives[select] );
2220 
2221  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2222  shapeList.emplace_back( m_primitives[select] );
2223 
2224  DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, m_parent, shapeList, true );
2225 
2226  if( dlg.ShowModal() != wxID_OK )
2227  return;
2228 
2229  // Transfer new settings
2230  // save duplicates to a separate vector to avoid m_primitives reallocation,
2231  // as shapeList contains pointers to its elements
2232  std::vector<std::shared_ptr<PCB_SHAPE>> duplicates;
2233  dlg.Transform( &duplicates, dlg.GetDuplicateCount() );
2234  std::move( duplicates.begin(), duplicates.end(), std::back_inserter( m_primitives ) );
2235 
2237 
2238  if( m_canUpdate )
2239  {
2241  redraw();
2242  }
2243 }
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:759
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:209
void SetOffset(const wxPoint &aOffset)
Definition: pad.h:249
void SetLastPadNumber(const wxString &aPadNumber)
Definition: pad_tool.h:65
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:173
void SetLocalSolderPasteMarginRatio(double aRatio)
Definition: pad.h:397
void SetViewport(const BOX2D &aViewport)
Set the visible area of the VIEW.
Definition: view.cpp:524
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:563
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:611
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:524
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:826
void SetFilled(bool aFlag)
Definition: eda_shape.h:92
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:164
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:491
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:210
#define NPTH_DLG_TYPE
Like smd, does not appear on the solder paste layer (default)
Smd pad, appears on the solder paste layer (default)
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:118
Tool relating to pads and pad settings.
Definition: pad_tool.h:35
bool IsLocked() const override
Definition: pad.cpp:150
double GetOrientation() const
Definition: footprint.h:191
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:152
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:336
int GetSelectedNetcode()
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:680
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:218
void SetSize(const wxSize &aSize)
Definition: pad.h:232
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:500
void onCornerSizePercentChange(wxCommandEvent &event) override
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:590
bool GetKeepTopBottom() const
Definition: pad.h:564
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:194
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:115
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:622
Classes used in Pcbnew, CvPcb and GerbView.
FP_TEXT & Reference()
Definition: footprint.h:500
a pad used as heat sink, usually in SMD footprints
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:477
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
virtual void SetPrecision(int aLength)
Normally not needed, but can be used to set the precision when using internal units that are floats (...
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:516
pads are covered by copper
int GetThermalSpokeWidth() const
Definition: pad.h:492
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:621
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:639
void SetThermalGap(int aGap)
Definition: pad.h:499
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:1416
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:557
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:719
static LSET PTHMask()
layer set for a through hole pad
Definition: pad.cpp:159
wxString GetLastPadNumber() const
Definition: pad_tool.h:64
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:153
#define SELECTED
void OnDrillShapeSelected(wxCommandEvent &event) override
void SetWidth(int aWidth)
Definition: eda_shape.h:97
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:476
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:284
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:735
void StartDrawing()
Begin drawing if it was stopped previously.
int GetHeight() const
Definition: eda_rect.h:119
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:275
int GetRoundRectCornerRadius() const
Definition: pad.cpp:269
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:1439
void SetChamferPositions(int aPositions)
Has meaning only for chamfered rectangular pads.
Definition: pad.h:542
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:278
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:192
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:1554
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:187
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:220
bool IsType(FRAME_T aType) const
a fiducial (usually a smd) for the full board
double GetChamferRectRatio() const
Definition: pad.h:533
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:271
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 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:100
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:187
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[]
void SetShape(PAD_SHAPE aShape)
Set the new shape of this pad.
Definition: pad.h:161
int GetChamferPositions() const
Definition: pad.h:543
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:180
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:320
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:292
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:166
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:372
bool GetRemoveUnconnected() const
Definition: pad.h:558
#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:630
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:1570
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