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, dick@softplc.com
6  * Copyright (C) 2008-2013 Wayne Stambaugh <stambaughw@verizon.net>
7  * Copyright (C) 1992-2020 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 <footprint.h>
32 #include <confirm.h>
33 #include <core/arraydim.h>
34 #include <convert_basic_shapes_to_polygon.h> // for enum RECT_CHAMFER_POSITIONS definition
35 #include <geometry/shape_segment.h>
36 #include <dialog_pad_properties.h>
39 #include <macros.h>
40 #include <pcb_base_frame.h>
41 #include <footprint_edit_frame.h>
42 #include <pcb_painter.h>
43 #include <pcbnew_settings.h>
45 #include <view/view_controls.h>
46 #include <widgets/net_selector.h>
47 #include <tool/tool_manager.h>
48 #include <tools/pad_tool.h>
49 #include <advanced_config.h> // for pad property feature management
50 #include <wx/choicdlg.h>
51 
52 
53 // list of pad shapes, ordered like the pad shape wxChoice in dialog.
55 {
62  PAD_SHAPE::CHAMFERED_RECT, // choice = CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT
63  PAD_SHAPE::CUSTOM, // choice = CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
64  PAD_SHAPE::CUSTOM // choice = PAD_SHAPE::CUSTOM_RECT_ANCHOR
65 };
66 
67 // the ordered index of the pad shape wxChoice in dialog.
68 // keep it consistent with code_shape[] and dialog strings
70 {
80 };
81 
83 {
88  PAD_ATTRIB::SMD // Aperture pad :type SMD with no copper layers,
89  // only on tech layers (usually only on paste layer
90 };
91 
92 // Thse define have the same value as the m_PadType wxChoice GetSelected() return value
93 #define PTH_DLG_TYPE 0
94 #define SMD_DLG_TYPE 1
95 #define CONN_DLG_TYPE 2
96 #define NPTH_DLG_TYPE 3
97 #define APERTURE_DLG_TYPE 4
98 
100 {
101  DIALOG_PAD_PROPERTIES dlg( this, aPad );
102 
103  if( dlg.ShowQuasiModal() == wxID_OK ) // QuasiModal required for NET_SELECTOR
104  {
105  // aPad can be NULL, if the dialog is called from the footprint editor
106  // to set the default pad setup
107  if( aPad )
108  {
109  PAD_TOOL* padTools = m_toolManager->GetTool<PAD_TOOL>();
110 
111  if( padTools )
112  padTools->SetLastPadName( aPad->GetName() );
113  }
114  }
115 }
116 
117 
119  DIALOG_PAD_PROPERTIES_BASE( aParent ),
120  m_parent( aParent ),
121  m_canUpdate( false ),
122  m_posX( aParent, m_posXLabel, m_posXCtrl, m_posXUnits ),
123  m_posY( aParent, m_posYLabel, m_posYCtrl, m_posYUnits ),
124  m_sizeX( aParent, m_sizeXLabel, m_sizeXCtrl, m_sizeXUnits ),
125  m_sizeY( aParent, m_sizeYLabel, m_sizeYCtrl, m_sizeYUnits ),
126  m_offsetX( aParent, m_offsetXLabel, m_offsetXCtrl, m_offsetXUnits ),
127  m_offsetY( aParent, m_offsetYLabel, m_offsetYCtrl, m_offsetYUnits ),
128  m_padToDie( aParent, m_padToDieLabel, m_padToDieCtrl, m_padToDieUnits ),
129  m_trapDelta( aParent, m_trapDeltaLabel, m_trapDeltaCtrl, m_trapDeltaUnits ),
130  m_cornerRadius( aParent, m_cornerRadiusLabel, m_tcCornerRadius, m_cornerRadiusUnits ),
131  m_holeX( aParent, m_holeXLabel, m_holeXCtrl, m_holeXUnits ),
132  m_holeY( aParent, m_holeYLabel, m_holeYCtrl, m_holeYUnits ),
133  m_OrientValidator( 3, &m_OrientValue ),
134  m_clearance( aParent, m_clearanceLabel, m_clearanceCtrl, m_clearanceUnits ),
135  m_maskClearance( aParent, m_maskClearanceLabel, m_maskClearanceCtrl, m_maskClearanceUnits ),
136  m_pasteClearance( aParent, m_pasteClearanceLabel, m_pasteClearanceCtrl, m_pasteClearanceUnits ),
137  m_spokeWidth( aParent, m_spokeWidthLabel, m_spokeWidthCtrl, m_spokeWidthUnits ),
138  m_thermalGap( aParent, m_thermalGapLabel, m_thermalGapCtrl, m_thermalGapUnits )
139 {
140  SetName( PAD_PROPERTIES_DLG_NAME );
141  m_isFpEditor = dynamic_cast<FOOTPRINT_EDIT_FRAME*>( aParent ) != nullptr;
142 
143  m_currentPad = aPad; // aPad can be NULL, if the dialog is called
144  // from the footprint editor to set default pad setup
145 
147 
148  // Configure display origin transforms
151 
154 
155  m_OrientValidator.SetRange( -360.0, 360.0 );
156  m_orientation->SetValidator( m_OrientValidator );
157  m_OrientValidator.SetWindow( m_orientation );
158 
159  m_cbShowPadOutline->SetValue( m_sketchPreview );
160 
163 
165  m_dummyPad = new PAD( (FOOTPRINT*) NULL );
166 
167  if( aPad )
168  {
169  *m_dummyPad = *aPad;
171  }
172  else
173  {
174  // We are editing a "master" pad, i.e. a template to create new pads
176  }
177 
178  // Pad needs to have a parent for painting; use the parent board for its design settings
179  if( !m_dummyPad->GetParent() )
181 
182  initValues();
183 
184  wxFont infoFont = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
185  infoFont.SetSymbolicSize( wxFONTSIZE_SMALL );
186  m_copperLayersLabel->SetFont( infoFont );
187  m_techLayersLabel->SetFont( infoFont );
188  m_parentInfo->SetFont( infoFont );
189 
190  infoFont.SetStyle( wxFONTSTYLE_ITALIC );
191  m_nonCopperNote->SetFont( infoFont );
192  m_staticTextInfoPaste->SetFont( infoFont );
193  m_staticTextInfoNegVal->SetFont( infoFont );
194  m_staticTextInfoPosValue->SetFont( infoFont );
195  m_staticTextPrimitiveListWarning->SetFont( infoFont );
196 
197  // Do not allow locking items in the footprint editor
198  m_locked->Show( !m_isFpEditor );
199 
200  // Usually, TransferDataToWindow is called by OnInitDialog
201  // calling it here fixes all widget sizes so FinishDialogSettings can safely fix minsizes
203 
204  // Initialize canvas to be able to display the dummy pad:
205  prepareCanvas();
206 
208  m_sdbSizerOK->SetDefault();
209  m_canUpdate = true;
210 
211  m_PadNetSelector->Connect( NET_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ), NULL, this );
212 
213  // Now all widgets have the size fixed, call FinishDialogSettings
215 
216  wxUpdateUIEvent dummy;
217  OnUpdateUI( dummy );
218 }
219 
220 
222 {
223  m_PadNetSelector->Disconnect( NET_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ), NULL, this );
224 
225  delete m_dummyPad;
226  delete m_axisOrigin;
227 }
228 
229 
230 bool DIALOG_PAD_PROPERTIES::m_sketchPreview = false; // Stores the pad draw option during a session
231 
232 
233 void DIALOG_PAD_PROPERTIES::OnInitDialog( wxInitDialogEvent& event )
234 {
235  m_selectedColor = COLOR4D( 1.0, 1.0, 1.0, 0.7 );
236 
237  // Needed on some WM to be sure the pad is redrawn according to the final size
238  // of the canvas, with the right zoom factor
239  redraw();
240 }
241 
242 
243 void DIALOG_PAD_PROPERTIES::OnCancel( wxCommandEvent& event )
244 {
245  // Mandatory to avoid m_panelShowPadGal trying to draw something
246  // in a non valid context during closing process:
248 
249  // Now call default handler for wxID_CANCEL command event
250  event.Skip();
251 }
252 
253 
255 {
256  // Enable or disable the widgets in page managing custom shape primitives
257  m_listCtrlPrimitives->Enable( aEnable );
258  m_buttonDel->Enable( aEnable );
259  m_buttonEditShape->Enable( aEnable );
260  m_buttonAddShape->Enable( aEnable );
261  m_buttonDup->Enable( aEnable );
262  m_buttonGeometry->Enable( aEnable );
263 }
264 
265 
267 {
268  // Initialize the canvas to display the pad
269  m_padPreviewGAL = new PCB_DRAW_PANEL_GAL( m_boardViewPanel, -1, wxDefaultPosition,
270  wxDefaultSize,
272  m_parent->GetCanvas()->GetBackend() );
273 
274  m_padPreviewSizer->Add( m_padPreviewGAL, 12, wxEXPAND | wxALL, 5 );
275 
276  // Show the X and Y axis. It is usefull because pad shape can have an offset
277  // or be a complex shape.
278  KIGFX::COLOR4D axis_color = LIGHTBLUE;
279 
281  Millimeter2iu( 0.2 ),
283  m_axisOrigin->SetDrawAtZero( true );
284 
287  m_padPreviewGAL->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
288 
289  KIGFX::VIEW_CONTROLS* parentViewControls = m_parent->GetCanvas()->GetViewControls();
290  m_padPreviewGAL->GetViewControls()->ApplySettings( parentViewControls->GetSettings() );
291 
292  m_padPreviewGAL->Show();
293 
295 
296  // fix the pad render mode (filled/not filled)
297  auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
298  bool sketchMode = m_cbShowPadOutline->IsChecked();
299  settings->SetSketchMode( LAYER_PADS_TH, sketchMode );
300  settings->SetSketchMode( LAYER_PAD_FR, sketchMode );
301  settings->SetSketchMode( LAYER_PAD_BK, sketchMode );
302  settings->SetSketchModeGraphicItems( sketchMode );
303 
304  settings->SetHighContrast( false );
305  settings->SetContrastModeDisplay( HIGH_CONTRAST_MODE::NORMAL );
306 
307  // gives a non null grid size (0.001mm) because GAL layer does not like a 0 size grid:
308  double gridsize = 0.001 * IU_PER_MM;
309  view->GetGAL()->SetGridSize( VECTOR2D( gridsize, gridsize ) );
310  // And do not show the grid:
311  view->GetGAL()->SetGridVisibility( false );
312  view->Add( m_dummyPad );
313  view->Add( m_axisOrigin );
314 
316  Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_PAD_PROPERTIES::OnResize ) );
317 }
318 
319 
321 {
322  // Note: use m_tcCornerSizeRatio->ChangeValue() to avoid generating a wxEVT_TEXT event
323 
324  wxString ratio = wxString::Format( "%.1f", m_dummyPad->GetRoundRectRadiusRatio() * 100 );
325  m_tcCornerSizeRatio->ChangeValue( ratio );
326  m_tcMixedCornerSizeRatio->ChangeValue( ratio );
328 
329  ratio = wxString::Format( "%.1f", m_dummyPad->GetChamferRectRatio() * 100 );
330  m_tcChamferRatio->ChangeValue( ratio );
331  m_tcMixedChamferRatio->ChangeValue( ratio );
332 }
333 
334 
335 void DIALOG_PAD_PROPERTIES::onCornerRadiusChange( wxCommandEvent& event )
336 {
339  return;
340 
341  double rrRadius = m_cornerRadius.GetValue();
342 
343  if( rrRadius < 0.0 )
344  {
345  rrRadius = 0.0;
346  m_tcCornerRadius->ChangeValue( wxString::Format( "%.1f", rrRadius ) );
347  }
348 
351 
352  auto ratio = wxString::Format( "%.1f", m_dummyPad->GetRoundRectRadiusRatio() * 100 );
353  m_tcCornerSizeRatio->ChangeValue( ratio );
354  m_tcMixedCornerSizeRatio->ChangeValue( ratio );
355 
356  redraw();
357 }
358 
359 
361 {
364  {
365  return;
366  }
367 
368  wxObject* ctrl = event.GetEventObject();
369  wxString value = event.GetString();
370  bool changed = false;
371 
372  if( ctrl == m_tcCornerSizeRatio || ctrl == m_tcMixedCornerSizeRatio )
373  {
374  double ratioPercent;
375 
376  if( value.ToDouble( &ratioPercent ) )
377  {
378  // Clamp ratioPercent to acceptable value (0.0 to 50.0)
379  if( ratioPercent < 0.0 )
380  {
381  ratioPercent = 0.0;
382  value.Printf( "%.1f", ratioPercent );
383  m_tcCornerSizeRatio->ChangeValue( value );
384  m_tcMixedCornerSizeRatio->ChangeValue( value );
385  }
386 
387  if( ratioPercent > 50.0 )
388  {
389  ratioPercent = 0.5;
390  value.Printf( "%.1f", ratioPercent*100.0 );
391  m_tcCornerSizeRatio->ChangeValue( value );
392  m_tcMixedCornerSizeRatio->ChangeValue( value );
393  }
394 
395  if( ctrl == m_tcCornerSizeRatio )
396  m_tcMixedCornerSizeRatio->ChangeValue( value );
397  else
398  m_tcCornerSizeRatio->ChangeValue( value );
399 
400  changed = true;
401  }
402  }
403  else if( ctrl == m_tcChamferRatio || ctrl == m_tcMixedChamferRatio )
404  {
405  double ratioPercent;
406 
407  if( value.ToDouble( &ratioPercent ) )
408  {
409  // Clamp ratioPercent to acceptable value (0.0 to 50.0)
410  if( ratioPercent < 0.0 )
411  {
412  ratioPercent = 0.0;
413  value.Printf( "%.1f", ratioPercent );
414  m_tcChamferRatio->ChangeValue( value );
415  m_tcMixedChamferRatio->ChangeValue( value );
416  }
417 
418  if( ratioPercent > 50.0 )
419  {
420  ratioPercent = 0.5;
421  value.Printf( "%.1f", ratioPercent*100.0 );
422  m_tcChamferRatio->ChangeValue( value );
423  m_tcMixedChamferRatio->ChangeValue( value );
424  }
425 
426  if( ctrl == m_tcChamferRatio )
427  m_tcMixedChamferRatio->ChangeValue( value );
428  else
429  m_tcChamferRatio->ChangeValue( value );
430 
431  changed = true;
432  }
433  }
434 
435  if( changed )
436  {
439  }
440 
441  redraw();
442 }
443 
444 
446 {
447  wxString msg;
448  double angle;
449 
450  // Disable pad net name wxTextCtrl if the caller is the footprint editor
451  // because nets are living only in the board managed by the board editor
453 
454  m_PadLayerAdhCmp->SetLabel( m_board->GetLayerName( F_Adhes ) );
455  m_PadLayerAdhCu->SetLabel( m_board->GetLayerName( B_Adhes ) );
457  m_PadLayerPateCu->SetLabel( m_board->GetLayerName( B_Paste ) );
459  m_PadLayerSilkCu->SetLabel( m_board->GetLayerName( B_SilkS ) );
460  m_PadLayerMaskCmp->SetLabel( m_board->GetLayerName( F_Mask ) );
461  m_PadLayerMaskCu->SetLabel( m_board->GetLayerName( B_Mask ) );
462  m_PadLayerECO1->SetLabel( m_board->GetLayerName( Eco1_User ) );
463  m_PadLayerECO2->SetLabel( m_board->GetLayerName( Eco2_User ) );
465 
466  if( m_currentPad )
467  {
468  m_locked->SetValue( m_currentPad->IsLocked() );
470 
471  FOOTPRINT* footprint = m_currentPad->GetParent();
472 
473  if( footprint )
474  {
476  angle -= footprint->GetOrientation();
478 
479  // Diplay parent footprint info
480  msg.Printf( _("Footprint %s (%s), %s, rotated %g deg"),
481  footprint->Reference().GetShownText(),
482  footprint->Value().GetShownText(),
483  footprint->IsFlipped() ? _( "back side (mirrored)" )
484  : _( "front side" ),
485  footprint->GetOrientationDegrees() );
486  }
487 
488  m_parentInfo->SetLabel( msg );
489  }
490  else
491  {
492  m_locked->Hide();
493  m_isFlipped = false;
494  }
495 
496  if( m_isFlipped )
497  {
498  // flip pad (up/down) around its position
499  m_dummyPad->Flip( m_dummyPad->GetPosition(), false );
500  }
501 
503 
505 
506  m_PadNumCtrl->SetValue( m_dummyPad->GetName() );
508 
509  // Display current pad parameters units:
512 
515 
518 
519  m_offsetShapeOpt->SetValue( m_dummyPad->GetOffset() != wxPoint() );
522 
523  if( m_dummyPad->GetDelta().x )
524  {
526  m_trapAxisCtrl->SetSelection( 0 );
527  }
528  else
529  {
531  m_trapAxisCtrl->SetSelection( 1 );
532  }
533 
534  m_padToDieOpt->SetValue( m_dummyPad->GetPadToDieLength() != 0 );
536 
542 
543  // Prefer "-0" to "0" for normally negative values
545  m_pasteClearanceCtrl->ChangeValue( wxT( "-" ) + m_pasteClearanceCtrl->GetValue() );
546 
547  msg.Printf( wxT( "%f" ), m_dummyPad->GetLocalSolderPasteMarginRatio() * 100.0 );
548 
549  if( m_dummyPad->GetLocalSolderPasteMarginRatio() == 0.0 && msg[0] == '0' )
550  // Sometimes Printf adds a sign if the value is small
551  m_SolderPasteMarginRatioCtrl->ChangeValue( wxT( "-" ) + msg );
552  else
553  m_SolderPasteMarginRatioCtrl->ChangeValue( msg );
554 
555  switch( m_dummyPad->GetZoneConnection() )
556  {
557  default:
558  case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
559  case ZONE_CONNECTION::FULL: m_ZoneConnectionChoice->SetSelection( 1 ); break;
560  case ZONE_CONNECTION::THERMAL: m_ZoneConnectionChoice->SetSelection( 2 ); break;
561  case ZONE_CONNECTION::NONE: m_ZoneConnectionChoice->SetSelection( 3 ); break;
562  }
563 
565  m_ZoneCustomPadShape->SetSelection( 1 );
566  else
567  m_ZoneCustomPadShape->SetSelection( 0 );
568 
571 
572  // Pad Orient
573  // Note: use ChangeValue() instead of SetValue() so that we don't generate events
575 
576  switch( m_dummyPad->GetShape() )
577  {
578  default:
579  case PAD_SHAPE::CIRCLE: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_CIRCLE ); break;
580  case PAD_SHAPE::OVAL: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_OVAL ); break;
581  case PAD_SHAPE::RECT: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_RECT ); break;
582  case PAD_SHAPE::TRAPEZOID: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_TRAPEZOID ); break;
583  case PAD_SHAPE::ROUNDRECT: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_ROUNDRECT ); break;
584 
586  if( m_dummyPad->GetRoundRectRadiusRatio() > 0.0 )
588  else
590  break;
591 
592  case PAD_SHAPE::CUSTOM:
595  else
597  break;
598  }
599 
608 
610 
612 
613  // Type of pad selection
614  bool aperture = m_dummyPad->GetAttribute() == PAD_ATTRIB::SMD && m_dummyPad->IsAperturePad();
615 
616  if( aperture )
617  {
618  m_PadType->SetSelection( APERTURE_DLG_TYPE );
619  }
620  else
621  {
622  switch( m_dummyPad->GetAttribute() )
623  {
624  case PAD_ATTRIB::PTH: m_PadType->SetSelection( PTH_DLG_TYPE ); break;
625  case PAD_ATTRIB::SMD: m_PadType->SetSelection( SMD_DLG_TYPE ); break;
626  case PAD_ATTRIB::CONN: m_PadType->SetSelection( CONN_DLG_TYPE ); break;
627  case PAD_ATTRIB::NPTH: m_PadType->SetSelection( NPTH_DLG_TYPE ); break;
628  }
629  }
630 
631  switch( m_dummyPad->GetProperty() )
632  {
633  case PAD_PROP::NONE: m_choiceFabProperty->SetSelection( 0 ); break;
634  case PAD_PROP::BGA: m_choiceFabProperty->SetSelection( 1 ); break;
635  case PAD_PROP::FIDUCIAL_LOCAL: m_choiceFabProperty->SetSelection( 2 ); break;
636  case PAD_PROP::FIDUCIAL_GLBL: m_choiceFabProperty->SetSelection( 3 ); break;
637  case PAD_PROP::TESTPOINT: m_choiceFabProperty->SetSelection( 4 ); break;
638  case PAD_PROP::HEATSINK: m_choiceFabProperty->SetSelection( 5 ); break;
639  case PAD_PROP::CASTELLATED: m_choiceFabProperty->SetSelection( 6 ); break;
640  }
641 
642  // Ensure the pad property is compatible with the pad type
644  {
645  m_choiceFabProperty->SetSelection( 0 );
646  m_choiceFabProperty->Enable( false );
647  }
648 
650  m_holeShapeCtrl->SetSelection( 0 );
651  else
652  m_holeShapeCtrl->SetSelection( 1 );
653 
656 
657  // Update some dialog widgets state (Enable/disable options):
658  wxCommandEvent cmd_event;
659  OnPadShapeSelection( cmd_event );
660  OnOffsetCheckbox( cmd_event );
661 
662  // Update basic shapes list
664 }
665 
666 // A small helper function, to display coordinates:
667 static wxString formatCoord( EDA_UNITS aUnits, wxPoint aCoord )
668 {
669  return wxString::Format( "(X:%s Y:%s)",
670  MessageTextFromValue( aUnits, aCoord.x ),
671  MessageTextFromValue( aUnits, aCoord.y ) );
672 }
673 
675 {
676  m_listCtrlPrimitives->ClearAll();
677 
678  wxListItem itemCol;
679  itemCol.SetImage(-1);
680 
681  for( int ii = 0; ii < 5; ++ii )
682  m_listCtrlPrimitives->InsertColumn(ii, itemCol);
683 
684  wxString bs_info[5];
685 
686  for( unsigned ii = 0; ii < m_primitives.size(); ++ii )
687  {
688  const std::shared_ptr<PCB_SHAPE>& primitive = m_primitives[ii];
689 
690  for( wxString& s : bs_info )
691  s.Empty();
692 
693  bs_info[4] = _( "width" ) + wxS( " " )+ MessageTextFromValue( m_units, primitive->GetWidth() );
694 
695  switch( primitive->GetShape() )
696  {
697  case PCB_SHAPE_TYPE::SEGMENT: // usual segment : line with rounded ends
698  bs_info[0] = _( "Segment" );
699  bs_info[1] = _( "from" ) + wxS( " " )+ formatCoord( m_units, primitive->GetStart() );
700  bs_info[2] = _( "to" ) + wxS( " " )+ formatCoord( m_units, primitive->GetEnd() );
701  break;
702 
703  case PCB_SHAPE_TYPE::CURVE: // Bezier segment
704  bs_info[0] = _( "Bezier" );
705  bs_info[1] = _( "from" ) + wxS( " " )+ formatCoord( m_units, primitive->GetStart() );
706  bs_info[2] = _( "to" ) + wxS( " " )+ formatCoord( m_units, primitive->GetEnd() );
707  break;
708 
709  case PCB_SHAPE_TYPE::ARC: // Arc with rounded ends
710  bs_info[0] = _( "Arc" );
711  bs_info[1] = _( "center" ) + wxS( " " )+ formatCoord( m_units, primitive->GetCenter() );
712  bs_info[2] = _( "start" ) + wxS( " " )+ formatCoord( m_units, primitive->GetArcStart() );
713  bs_info[3] = _( "angle" ) + wxS( " " )+ FormatAngle( primitive->GetAngle() );
714  break;
715 
716  case PCB_SHAPE_TYPE::CIRCLE: // ring or circle
717  if( primitive->GetWidth() )
718  bs_info[0] = _( "ring" );
719  else
720  bs_info[0] = _( "circle" );
721 
722  bs_info[1] = formatCoord( m_units, primitive->GetStart() );
723  bs_info[2] = _( "radius" ) + wxS( " " )+ MessageTextFromValue( m_units, primitive->GetRadius() );
724  break;
725 
726  case PCB_SHAPE_TYPE::POLYGON: // polygon
727  bs_info[0] = "Polygon";
728  bs_info[1] = wxString::Format( _( "corners count %d" ),
729  (int) primitive->GetPolyShape().Outline( 0 ).PointCount() );
730  break;
731 
732  default:
733  bs_info[0] = "Unknown primitive";
734  break;
735  }
736 
737  long tmp = m_listCtrlPrimitives->InsertItem( ii, bs_info[0] );
738  m_listCtrlPrimitives->SetItemData( tmp, ii );
739 
740  for( int jj = 0, col = 0; jj < 5; ++jj )
741  m_listCtrlPrimitives->SetItem( tmp, col++, bs_info[jj] );
742  }
743 
744  // Now columns are filled, ensure correct width of columns
745  for( unsigned ii = 0; ii < 5; ++ii )
746  m_listCtrlPrimitives->SetColumnWidth( ii, wxLIST_AUTOSIZE );
747 }
748 
749 void DIALOG_PAD_PROPERTIES::OnResize( wxSizeEvent& event )
750 {
751  redraw();
752  event.Skip();
753 }
754 
755 
756 void DIALOG_PAD_PROPERTIES::onChangePadMode( wxCommandEvent& event )
757 {
758  m_sketchPreview = m_cbShowPadOutline->GetValue();
759 
761 
762  // fix the pad render mode (filled/not filled)
763  KIGFX::PCB_RENDER_SETTINGS* settings =
764  static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
765 
770 
771  settings->SetHighContrast( false );
773 
774  redraw();
775 }
776 
777 
778 
779 void DIALOG_PAD_PROPERTIES::OnPadShapeSelection( wxCommandEvent& event )
780 {
781  switch( m_PadShapeSelector->GetSelection() )
782  {
783  case CHOICE_SHAPE_CIRCLE:
784  case CHOICE_SHAPE_OVAL:
785  case CHOICE_SHAPE_RECT:
786  m_shapePropsBook->SetSelection( 0 );
787  break;
788 
790  m_shapePropsBook->SetSelection( 1 );
791  break;
792 
794  {
795  m_shapePropsBook->SetSelection( 2 );
796 
797  // A reasonable default (from IPC-7351C)
798  if( m_dummyPad->GetRoundRectRadiusRatio() == 0.0 )
799  m_tcCornerSizeRatio->ChangeValue( "25" );
800  }
801  break;
802 
804  m_shapePropsBook->SetSelection( 3 );
805 
806  // Reasonable default
807  if( m_dummyPad->GetChamferRectRatio() == 0.0 )
809 
810  // Ensure the displayed value is up to date:
811  m_tcChamferRatio->ChangeValue( wxString::Format( "%.1f",
812  m_dummyPad->GetChamferRectRatio() * 100 ) );
813 
814  // A reasonable default is one corner chamfered (usual for some SMD pads).
815  if( !m_cbTopLeft->GetValue() && !m_cbTopRight->GetValue()
816  && !m_cbBottomLeft->GetValue() && !m_cbBottomRight->GetValue() )
817  {
818  m_cbTopLeft->SetValue( true );
819  m_cbTopRight->SetValue( false );
820  m_cbBottomLeft->SetValue( false );
821  m_cbBottomRight->SetValue( false );
822  }
823  break;
824 
826  m_shapePropsBook->SetSelection( 4 );
827 
828  // Reasonable defaults (corner radius from IPC-7351C)
829  if( m_dummyPad->GetRoundRectRadiusRatio() == 0.0
830  && m_dummyPad->GetChamferRectRatio() == 0.0 )
831  {
832  if( m_dummyPad->GetRoundRectRadiusRatio() == 0.0 )
834 
835  if( m_dummyPad->GetChamferRectRatio() == 0.0 )
837  }
838 
839  // Ensure the displayed values are up to date:
840  m_tcMixedChamferRatio->ChangeValue( wxString::Format( "%.1f",
841  m_dummyPad->GetChamferRectRatio() * 100 ) );
842  m_tcMixedCornerSizeRatio->ChangeValue( wxString::Format( "%.1f",
843  m_dummyPad->GetRoundRectRadiusRatio() * 100 ) );
844  break;
845 
846  case CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR: // PAD_SHAPE::CUSTOM, circular anchor
847  case CHOICE_SHAPE_CUSTOM_RECT_ANCHOR: // PAD_SHAPE::CUSTOM, rect anchor
848  m_shapePropsBook->SetSelection( 0 );
849  break;
850  }
851 
852  // Readjust props book size
853  wxSize size = m_shapePropsBook->GetSize();
854  size.y = m_shapePropsBook->GetPage( m_shapePropsBook->GetSelection() )->GetBestSize().y;
855  m_shapePropsBook->SetMaxSize( size );
856 
858  && m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR );
859 
860  m_offsetShapeOpt->Enable( m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CIRCLE
862  && m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CUSTOM_RECT_ANCHOR );
863 
864  if( !m_offsetShapeOpt->IsEnabled() )
865  m_offsetShapeOpt->SetValue( false );
866 
867  // Show/hide controls depending on m_offsetShapeOpt being enabled
868  m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
869  m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
870 
871  bool is_custom = m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
873 
874  enablePrimitivePage( is_custom );
875  m_staticTextcps->Enable( is_custom );
876  m_ZoneCustomPadShape->Enable( is_custom );
877 
879 
881 
882  for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
883  m_notebook->GetPage( i )->Layout();
884 
885  // Resize the dialog if its height is too small to show all widgets:
886  if( m_MainSizer->GetSize().y < m_MainSizer->GetMinSize().y )
887  m_MainSizer->SetSizeHints( this );
888 
889  redraw();
890 }
891 
892 
893 void DIALOG_PAD_PROPERTIES::OnDrillShapeSelected( wxCommandEvent& event )
894 {
896  redraw();
897 }
898 
899 
900 void DIALOG_PAD_PROPERTIES::PadOrientEvent( wxCommandEvent& event )
901 {
903  redraw();
904 }
905 
906 
908 {
909  m_rbCopperLayersSel->Clear();
910 
911  switch( m_PadType->GetSelection() )
912  {
913  case PTH_DLG_TYPE:
914  m_rbCopperLayersSel->Append( _( "All copper layers" ) );
915  m_rbCopperLayersSel->Append( wxString::Format( _( "%s, %s and connected layers" ),
917  m_board->GetLayerName( B_Cu ) ) );
918  m_rbCopperLayersSel->Append( _( "Connected layers only" ) );
919  m_rbCopperLayersSel->Append( _( "None" ) );
920  break;
921 
922  case NPTH_DLG_TYPE:
923  m_rbCopperLayersSel->Append( wxString::Format( _( "%s and %s" ),
925  m_board->GetLayerName( B_Cu ) ) );
928  m_rbCopperLayersSel->Append( _( "None" ) );
929  break;
930 
931  case SMD_DLG_TYPE:
932  case CONN_DLG_TYPE:
935  break;
936 
937  case APERTURE_DLG_TYPE:
938  m_rbCopperLayersSel->Append( _( "None" ) );
939  break;
940  }
941 }
942 
943 
944 void DIALOG_PAD_PROPERTIES::PadTypeSelected( wxCommandEvent& event )
945 {
946  bool hasHole = true;
947  bool hasConnection = true;
948  bool hasProperty = true;
949 
950  switch( m_PadType->GetSelection() )
951  {
952  case PTH_DLG_TYPE: hasHole = true; hasConnection = true; hasProperty = true; break;
953  case SMD_DLG_TYPE: hasHole = false; hasConnection = true; hasProperty = true; break;
954  case CONN_DLG_TYPE: hasHole = false; hasConnection = true; hasProperty = true; break;
955  case NPTH_DLG_TYPE: hasHole = true; hasConnection = false; hasProperty = false; break;
956  case APERTURE_DLG_TYPE: hasHole = false; hasConnection = false; hasProperty = true; break;
957  }
958 
959  // Update Layers dropdown list and selects the "best" layer set for the new pad type:
961 
962  if( !hasHole )
963  {
964  m_holeX.ChangeValue( 0 );
965  m_holeY.ChangeValue( 0 );
966  }
967  else if ( m_holeX.GetValue() == 0 && m_currentPad )
968  {
971  }
972 
973  if( !hasConnection )
974  {
975  m_PadNumCtrl->ChangeValue( wxEmptyString );
977  m_padToDieOpt->SetValue( false );
978  }
979  else if( m_PadNumCtrl->GetValue().IsEmpty() && m_currentPad )
980  {
981  m_PadNumCtrl->ChangeValue( m_currentPad->GetName() );
983  }
984 
985  if( !hasProperty )
986  m_choiceFabProperty->SetSelection( 0 );
987 
988  m_choiceFabProperty->Enable( hasProperty );
989 
991 
992  redraw();
993 }
994 
995 
996 void DIALOG_PAD_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
997 {
998  // Enable/disable position
999  m_posX.Enable( !m_locked->GetValue() || m_isFpEditor );
1000  m_posY.Enable( !m_locked->GetValue() || m_isFpEditor );
1001 
1002  bool hasHole = true;
1003  bool hasConnection = true;
1004 
1005  switch( m_PadType->GetSelection() )
1006  {
1007  case PTH_DLG_TYPE: /* PTH */ hasHole = true; hasConnection = true; break;
1008  case SMD_DLG_TYPE: /* SMD */ hasHole = false; hasConnection = true; break;
1009  case CONN_DLG_TYPE: /* CONN */ hasHole = false; hasConnection = true; break;
1010  case NPTH_DLG_TYPE: /* NPTH */ hasHole = true; hasConnection = false; break;
1011  case APERTURE_DLG_TYPE: /* Aperture */ hasHole = false; hasConnection = false; break;
1012  }
1013 
1014  // Enable/disable hole controls
1015  m_holeShapeLabel->Enable( hasHole );
1016  m_holeShapeCtrl->Enable( hasHole );
1017  m_holeX.Enable( hasHole );
1018  m_holeY.Enable( hasHole && m_holeShapeCtrl->GetSelection() == 1 );
1019 
1020  // Enable/disable Pad number, net and pad length-to-die
1021  m_PadNumText->Enable( hasConnection );
1022  m_PadNumCtrl->Enable( hasConnection );
1023  m_PadNameText->Enable( hasConnection );
1024  m_PadNetSelector->Enable( hasConnection && m_canEditNetName && m_currentPad );
1025  m_padToDieOpt->Enable( hasConnection );
1026 
1027  if( !m_padToDieOpt->IsEnabled() )
1028  m_padToDieOpt->SetValue( false );
1029 
1030  // We can show/hide this here because it doesn't require the layout to be refreshed.
1031  // All the others have to be done in their event handlers because doing a layout here
1032  // causes infinite looping on MSW.
1033  m_padToDie.Show( m_padToDieOpt->GetValue() );
1034 
1035  // Enable/disable Copper Layers control
1036  m_rbCopperLayersSel->Enable( m_PadType->GetSelection() != APERTURE_DLG_TYPE );
1037 
1038  LSET cu_set = m_dummyPad->GetLayerSet() & LSET::AllCuMask();
1039 
1040  switch( m_PadType->GetSelection() )
1041  {
1042  case PTH_DLG_TYPE:
1043  if( !cu_set.any() )
1044  m_stackupImagesBook->SetSelection( 3 );
1045  else if( !m_dummyPad->GetRemoveUnconnected() )
1046  m_stackupImagesBook->SetSelection( 0 );
1047  else if( m_dummyPad->GetKeepTopBottom() )
1048  m_stackupImagesBook->SetSelection( 1 );
1049  else
1050  m_stackupImagesBook->SetSelection( 2 );
1051 
1052  break;
1053 
1054  case NPTH_DLG_TYPE:
1055  if( cu_set.test( F_Cu ) && cu_set.test( B_Cu ) )
1056  m_stackupImagesBook->SetSelection( 4 );
1057  else if( cu_set.test( F_Cu ) )
1058  m_stackupImagesBook->SetSelection( 5 );
1059  else if( cu_set.test( B_Cu ) )
1060  m_stackupImagesBook->SetSelection( 6 );
1061  else
1062  m_stackupImagesBook->SetSelection( 7 );
1063 
1064  break;
1065 
1066  case SMD_DLG_TYPE:
1067  case CONN_DLG_TYPE:
1068  case APERTURE_DLG_TYPE:
1069  m_stackupImagesBook->SetSelection( 3 );
1070  break;
1071  }
1072 }
1073 
1074 
1075 void DIALOG_PAD_PROPERTIES::updatePadLayersList( LSET layer_mask, bool remove_unconnected,
1076  bool keep_top_bottom )
1077 {
1079 
1080  switch( m_PadType->GetSelection() )
1081  {
1082  case PTH_DLG_TYPE:
1083  if( !layer_mask.any() )
1084  layer_mask = PAD::PTHMask();
1085 
1086  if( !( layer_mask & LSET::AllCuMask() ).any() )
1087  m_rbCopperLayersSel->SetSelection( 3 );
1088  else if( !remove_unconnected )
1089  m_rbCopperLayersSel->SetSelection( 0 );
1090  else if( keep_top_bottom )
1091  m_rbCopperLayersSel->SetSelection( 1 );
1092  else
1093  m_rbCopperLayersSel->SetSelection( 2 );
1094 
1095  break;
1096 
1097  case SMD_DLG_TYPE:
1098  if( !layer_mask.any() )
1099  layer_mask = PAD::SMDMask();
1100 
1101  if( layer_mask.test( F_Cu ) )
1102  m_rbCopperLayersSel->SetSelection( 0 );
1103  else
1104  m_rbCopperLayersSel->SetSelection( 1 );
1105 
1106  break;
1107 
1108  case CONN_DLG_TYPE:
1109  if( !layer_mask.any() )
1110  layer_mask = PAD::ConnSMDMask();
1111 
1112  if( layer_mask.test( F_Cu ) )
1113  m_rbCopperLayersSel->SetSelection( 0 );
1114  else
1115  m_rbCopperLayersSel->SetSelection( 1 );
1116 
1117  break;
1118 
1119  case NPTH_DLG_TYPE:
1120  if( !layer_mask.any() )
1121  layer_mask = PAD::UnplatedHoleMask();
1122 
1123  if( layer_mask.test( F_Cu ) && layer_mask.test( B_Cu ) )
1124  m_rbCopperLayersSel->SetSelection( 0 );
1125  else if( layer_mask.test( F_Cu ) )
1126  m_rbCopperLayersSel->SetSelection( 1 );
1127  else if( layer_mask.test( B_Cu ) )
1128  m_rbCopperLayersSel->SetSelection( 2 );
1129  else
1130  m_rbCopperLayersSel->SetSelection( 3 );
1131 
1132  break;
1133 
1134  case APERTURE_DLG_TYPE:
1135  if( !layer_mask.any() )
1136  layer_mask = PAD::ApertureMask();
1137 
1138  m_rbCopperLayersSel->SetSelection( 0 );
1139  break;
1140  }
1141 
1142  m_PadLayerAdhCmp->SetValue( layer_mask[F_Adhes] );
1143  m_PadLayerAdhCu->SetValue( layer_mask[B_Adhes] );
1144 
1145  m_PadLayerPateCmp->SetValue( layer_mask[F_Paste] );
1146  m_PadLayerPateCu->SetValue( layer_mask[B_Paste] );
1147 
1148  m_PadLayerSilkCmp->SetValue( layer_mask[F_SilkS] );
1149  m_PadLayerSilkCu->SetValue( layer_mask[B_SilkS] );
1150 
1151  m_PadLayerMaskCmp->SetValue( layer_mask[F_Mask] );
1152  m_PadLayerMaskCu->SetValue( layer_mask[B_Mask] );
1153 
1154  m_PadLayerECO1->SetValue( layer_mask[Eco1_User] );
1155  m_PadLayerECO2->SetValue( layer_mask[Eco2_User] );
1156 
1157  m_PadLayerDraft->SetValue( layer_mask[Dwgs_User] );
1158 }
1159 
1160 
1162 {
1163  bool retVal = DIALOG_SHIM::Show( aShow );
1164 
1165  if( aShow )
1166  {
1167  // It *should* work to set the stackup bitmap in the constructor, but it doesn't.
1168  // wxWidgets needs to have these set when the panel is visible for some reason.
1169  // https://gitlab.com/kicad/code/kicad/-/issues/5534
1176  m_stackupImage7->SetBitmap( KiBitmap( BITMAPS::pads_npth ) );
1177 
1178  Layout();
1179  }
1180 
1181  return retVal;
1182 }
1183 
1184 
1185 void DIALOG_PAD_PROPERTIES::OnSetCopperLayers( wxCommandEvent& event )
1186 {
1188  redraw();
1189 }
1190 
1191 
1192 // Called when select/deselect a layer.
1193 void DIALOG_PAD_PROPERTIES::OnSetLayers( wxCommandEvent& event )
1194 {
1196  redraw();
1197 }
1198 
1199 
1200 // test if all values are acceptable for the pad
1202 {
1203  bool error = transferDataToPad( m_dummyPad );
1204 
1205  wxArrayString error_msgs;
1206  wxArrayString warning_msgs;
1207  wxString msg;
1208  wxSize pad_size = m_dummyPad->GetSize();
1209  wxSize drill_size = m_dummyPad->GetDrillSize();
1210 
1212  {
1213  // allow 0-sized anchor pads
1214  }
1215  else if( m_dummyPad->GetShape() == PAD_SHAPE::CIRCLE )
1216  {
1217  if( pad_size.x <= 0 )
1218  warning_msgs.Add( _( "Warning: Pad size is less than zero." ) );
1219  }
1220  else
1221  {
1222  if( pad_size.x <= 0 || pad_size.y <= 0 )
1223  warning_msgs.Add( _( "Warning: Pad size is less than zero." ) );
1224  }
1225 
1226  // Test hole size against pad size
1227  if( m_dummyPad->IsOnCopperLayer() )
1228  {
1230  PCB_LAYER_ID layer = lset.Seq().at( 0 );
1231  int maxError = m_board->GetDesignSettings().m_MaxError;
1232  SHAPE_POLY_SET padOutline;
1233 
1234  m_dummyPad->TransformShapeWithClearanceToPolygon( padOutline, layer, 0, maxError,
1236 
1237  const SHAPE_SEGMENT* drillShape = m_dummyPad->GetEffectiveHoleShape();
1238  const SEG drillSeg = drillShape->GetSeg();
1239  SHAPE_POLY_SET drillOutline;
1240 
1241  TransformOvalToPolygon( drillOutline, (wxPoint) drillSeg.A, (wxPoint) drillSeg.B,
1242  drillShape->GetWidth(), maxError, ERROR_LOC::ERROR_INSIDE );
1243 
1244  drillOutline.BooleanSubtract( padOutline, SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
1245 
1246  if( drillOutline.BBox().GetWidth() > 0 || drillOutline.BBox().GetHeight() > 0 )
1247  {
1248  warning_msgs.Add( _( "Warning: Pad drill will leave no copper or drill shape and "
1249  "pad shape do not overlap." ) );
1250  }
1251  }
1252 
1253  if( m_dummyPad->GetLocalClearance() < 0 )
1254  warning_msgs.Add( _( "Warning: Negative local clearance values will have no effect." ) );
1255 
1256  // Some pads need a negative solder mask clearance (mainly for BGA with small pads)
1257  // However the negative solder mask clearance must not create negative mask size
1258  // Therefore test for minimal acceptable negative value
1259  // Hovewer, a negative value can give strange result with custom shapes, so it is not
1260  // allowed for custom pad shape
1262  {
1263  warning_msgs.Add( _( "Warning: Negative solder mask clearances are not supported for "
1264  "custom pad shapes." ) );
1265  }
1266  else
1267  {
1268  wxSize solder_size;
1269  int solder_margin = m_dummyPad->GetLocalSolderMaskMargin();
1270 
1271  solder_size.x = pad_size.x + solder_margin;
1272  solder_size.y = pad_size.y + solder_margin;
1273 
1274  if( solder_size.x <= 0 || solder_size.y <= 0 )
1275  {
1276  warning_msgs.Add( _( "Warning: Negative solder mask clearance larger than pad. No "
1277  "solder mask will be generated." ) );
1278  }
1279  }
1280 
1281  // Some pads need a positive solder paste clearance (mainly for BGA with small pads)
1282  // Hovewer, a positive value can create issues if the resulting shape is too big.
1283  // (like a solder paste creating a solder paste area on a neighbour pad or on the solder mask)
1284  // So we could ask for user to confirm the choice
1285  // For now we just check for disappearing paste
1286  wxSize paste_size;
1287  int paste_margin = m_dummyPad->GetLocalSolderPasteMargin();
1288  double paste_ratio = m_dummyPad->GetLocalSolderPasteMarginRatio();
1289 
1290  paste_size.x = pad_size.x + paste_margin + KiROUND( pad_size.x * paste_ratio );
1291  paste_size.y = pad_size.y + paste_margin + KiROUND( pad_size.y * paste_ratio );
1292 
1293  if( paste_size.x <= 0 || paste_size.y <= 0 )
1294  {
1295  warning_msgs.Add( _( "Warning: Negative solder paste margins larger than pad. No solder "
1296  "paste mask will be generated." ) );
1297  }
1298 
1299  LSET padlayers_mask = m_dummyPad->GetLayerSet();
1300 
1301  if( padlayers_mask == 0 )
1302  error_msgs.Add( _( "Error: pad has no layer." ) );
1303 
1304  if( !padlayers_mask[F_Cu] && !padlayers_mask[B_Cu] )
1305  {
1306  if( ( drill_size.x || drill_size.y ) && m_dummyPad->GetAttribute() != PAD_ATTRIB::NPTH )
1307  {
1308  warning_msgs.Add( _( "Warning: Plated through holes should normally have a copper pad "
1309  "on at least one layer." ) );
1310  }
1311  }
1312 
1313  if( error )
1314  error_msgs.Add( _( "Too large value for pad delta size." ) );
1315 
1316  switch( m_dummyPad->GetAttribute() )
1317  {
1318  case PAD_ATTRIB::NPTH: // Not plated, but through hole, a hole is expected
1319  case PAD_ATTRIB::PTH: // Pad through hole, a hole is also expected
1320  if( drill_size.x <= 0
1321  || ( drill_size.y <= 0 && m_dummyPad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ) )
1322  {
1323  warning_msgs.Add( _( "Warning: Through hole pad has no hole." ) );
1324  }
1325  break;
1326 
1327  case PAD_ATTRIB::CONN: // Connector pads are smd pads, just they do not have solder paste.
1328  if( padlayers_mask[B_Paste] || padlayers_mask[F_Paste] )
1329  {
1330  warning_msgs.Add( _( "Warning: Connector pads normally have no solder paste. Use an "
1331  "SMD pad instead." ) );
1332  }
1334 
1335  case PAD_ATTRIB::SMD: // SMD and Connector pads (One external copper layer only)
1336  {
1337  LSET innerlayers_mask = padlayers_mask & LSET::InternalCuMask();
1338 
1339  if( ( padlayers_mask[F_Cu] && padlayers_mask[B_Cu] ) || innerlayers_mask.count() != 0 )
1340  warning_msgs.Add( _( "Warning: SMD pad has no outer layers." ) );
1341  }
1342  break;
1343  }
1344 
1348  {
1349  warning_msgs.Add( _( "Warning: Fiducial property makes no sense on NPTH pads." ) );
1350  }
1351 
1354  {
1355  warning_msgs.Add( _( "Warning: Testpoint property makes no sense on NPTH pads." ) );
1356  }
1357 
1360  {
1361  warning_msgs.Add( _( "Warning: Heatsink property makes no sense of NPTH pads." ) );
1362  }
1363 
1366  {
1367  warning_msgs.Add( _( "Warning: Castellated property is for PTH pads." ) );
1368  }
1369 
1370  if( m_dummyPad->GetProperty() == PAD_PROP::BGA &&
1372  {
1373  warning_msgs.Add( _( "Warning: BGA property is for SMD pads." ) );
1374  }
1375 
1378  {
1379  wxASSERT( m_tcCornerSizeRatio->GetValue() == m_tcMixedCornerSizeRatio->GetValue() );
1380  wxString value = m_tcCornerSizeRatio->GetValue();
1381  double rrRadiusRatioPercent;
1382 
1383  if( !value.ToDouble( &rrRadiusRatioPercent ) )
1384  {
1385  error_msgs.Add( _( "Error: Corner size not a number." ) );
1386  }
1387  else
1388  {
1389  if( rrRadiusRatioPercent < 0.0 )
1390  error_msgs.Add( _( "Error: Negative corner size." ) );
1391  else if( rrRadiusRatioPercent > 50.0 )
1392  warning_msgs.Add( _( "Warning: Corner size will make pad circular." ) );
1393  }
1394  }
1395 
1396  // PADSTACKS TODO: this will need to check each layer in the pad...
1398  {
1399  SHAPE_POLY_SET mergedPolygon;
1401 
1402  if( mergedPolygon.OutlineCount() > 1 )
1403  error_msgs.Add( _( "Error: Custom pad shape must resolve to a single polygon." ) );
1404  }
1405 
1406 
1407  if( error_msgs.GetCount() || warning_msgs.GetCount() )
1408  {
1409  wxString title = error_msgs.GetCount() ? _( "Pad Properties Errors" )
1410  : _( "Pad Properties Warnings" );
1411  HTML_MESSAGE_BOX dlg( this, title );
1412 
1413  dlg.ListSet( error_msgs );
1414 
1415  if( warning_msgs.GetCount() )
1416  dlg.ListSet( warning_msgs );
1417 
1418  dlg.ShowModal();
1419  }
1420 
1421  return error_msgs.GetCount() == 0;
1422 }
1423 
1424 
1426 {
1427  if( !m_canUpdate )
1428  return;
1429 
1430  KIGFX::VIEW* view = m_padPreviewGAL->GetView();
1432 
1433  // The layer used to place primitive items selected when editing custom pad shapes
1434  // we use here a layer never used in a pad:
1435  #define SELECTED_ITEMS_LAYER Dwgs_User
1436 
1438  KIGFX::PCB_RENDER_SETTINGS* settings =
1439  static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
1441 
1442  view->Update( m_dummyPad );
1443 
1444  // delete previous items if highlight list
1445  while( m_highlight.size() )
1446  {
1447  delete m_highlight.back(); // the dtor also removes item from view
1448  m_highlight.pop_back();
1449  }
1450 
1451  // highlight selected primitives:
1452  long select = m_listCtrlPrimitives->GetFirstSelected();
1453 
1454  while( select >= 0 )
1455  {
1456  PCB_SHAPE* dummyShape = (PCB_SHAPE*) m_primitives[select]->Clone();
1457  dummyShape->SetLayer( SELECTED_ITEMS_LAYER );
1458  dummyShape->Rotate( wxPoint( 0, 0), m_dummyPad->GetOrientation() );
1459  dummyShape->Move( m_dummyPad->GetPosition() );
1460 
1461  view->Add( dummyShape );
1462  m_highlight.push_back( dummyShape );
1463 
1464  select = m_listCtrlPrimitives->GetNextSelected( select );
1465  }
1466 
1467  BOX2I bbox = m_dummyPad->ViewBBox();
1468 
1469  if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
1470  {
1471  // The origin always goes in the middle of the canvas; we want offsetting the pad
1472  // shape to move the pad, not the hole
1473  bbox.Move( -m_dummyPad->GetPosition() );
1474  int maxXExtent = std::max( abs( bbox.GetLeft() ), abs( bbox.GetRight() ) );
1475  int maxYExtent = std::max( abs( bbox.GetTop() ), abs( bbox.GetBottom() ) );
1476 
1477  // Don't blow up the GAL on too-large numbers
1478  if( maxXExtent > INT_MAX / 4 )
1479  maxXExtent = INT_MAX / 4;
1480 
1481  if( maxYExtent > INT_MAX / 4 )
1482  maxYExtent = INT_MAX / 4;
1483 
1484  BOX2D viewBox( m_dummyPad->GetPosition(), {0, 0} );
1485  BOX2D canvasBox( m_dummyPad->GetPosition(), {0, 0} );
1486  viewBox.Inflate( maxXExtent * 1.4, maxYExtent * 1.4 ); // add a margin
1487  canvasBox.Inflate( maxXExtent * 2.0, maxYExtent * 2.0 );
1488 
1489  view->SetBoundary( canvasBox );
1490 
1491  // Autozoom
1492  view->SetViewport( viewBox );
1493 
1496  }
1497 }
1498 
1499 
1501 {
1502  if( !wxDialog::TransferDataToWindow() )
1503  return false;
1504 
1505  if( !m_panelGeneral->TransferDataToWindow() )
1506  return false;
1507 
1508  if( !m_localSettingsPanel->TransferDataToWindow() )
1509  return false;
1510 
1511  return true;
1512 }
1513 
1514 
1516 {
1517  BOARD_COMMIT commit( m_parent );
1518 
1519  if( !wxDialog::TransferDataFromWindow() )
1520  return false;
1521 
1522  if( !m_panelGeneral->TransferDataFromWindow() )
1523  return false;
1524 
1525  if( !m_localSettingsPanel->TransferDataFromWindow() )
1526  return false;
1527 
1528  if( !padValuesOK() )
1529  return false;
1530 
1532  // m_padMaster is a pattern: ensure there is no net for this pad:
1534 
1535  if( !m_currentPad ) // Set current Pad parameters
1536  return true;
1537 
1538  commit.Modify( m_currentPad );
1539 
1540  // redraw the area where the pad was, without pad (delete pad on screen)
1542  m_parent->GetCanvas()->Refresh();
1544 
1545  // Update values
1549 
1550  m_currentPad->SetLocked( m_locked->GetValue() );
1551 
1552  if( !m_locked->GetValue() || m_isFpEditor )
1554 
1555  wxSize size;
1556  FOOTPRINT* footprint = m_currentPad->GetParent();
1557 
1559 
1560  size = m_padMaster->GetDelta();
1561  m_currentPad->SetDelta( size );
1562 
1565 
1566  wxPoint offset = m_padMaster->GetOffset();
1567  m_currentPad->SetOffset( offset );
1568 
1570 
1573 
1574 
1577 
1581 
1583 
1584  int padNetcode = NETINFO_LIST::UNCONNECTED;
1585 
1586  // For PAD_ATTRIB::NPTH, ensure there is no net name selected
1588  padNetcode = m_PadNetSelector->GetSelectedNetcode();
1589 
1590  m_currentPad->SetNetCode( padNetcode );
1601 
1602  // rounded rect pads with radius ratio = 0 are in fact rect pads.
1603  // So set the right shape (and perhaps issues with a radius = 0)
1606  {
1608  }
1609 
1610  // Set the fabrication property:
1612 
1613  // define the way the clearance area is defined in zones
1615 
1616  if( m_isFlipped )
1617  {
1618  // flip pad (up/down) around its position
1619  m_currentPad->Flip( m_currentPad->GetPosition(), false );
1620  }
1621 
1622  if( footprint )
1623  {
1624  footprint->SetLastEditTime();
1625 
1626  // compute the pos 0 value, i.e. pad position for footprint with orientation = 0
1627  // i.e. relative to footprint origin (footprint position)
1628  wxPoint pt = m_currentPad->GetPosition() - footprint->GetPosition();
1629  RotatePoint( &pt, -footprint->GetOrientation() );
1630  m_currentPad->SetPos0( pt );
1632  footprint->GetOrientation() );
1633  }
1634 
1636 
1637  // redraw the area where the pad was
1638  m_parent->GetCanvas()->Refresh();
1639 
1640  commit.Push( _( "Modify pad" ) );
1641 
1642  return true;
1643 }
1644 
1645 
1647 {
1648  PAD_PROP prop = PAD_PROP::NONE;
1649 
1650  switch( m_choiceFabProperty->GetSelection() )
1651  {
1652  case 0: prop = PAD_PROP::NONE; break;
1653  case 1: prop = PAD_PROP::BGA; break;
1654  case 2: prop = PAD_PROP::FIDUCIAL_LOCAL; break;
1655  case 3: prop = PAD_PROP::FIDUCIAL_GLBL; break;
1656  case 4: prop = PAD_PROP::TESTPOINT; break;
1657  case 5: prop = PAD_PROP::HEATSINK; break;
1658  case 6: prop = PAD_PROP::CASTELLATED; break;
1659  }
1660 
1661  return prop;
1662 }
1663 
1664 
1666 {
1667  wxString msg;
1668 
1669  if( !Validate() )
1670  return true;
1671  if( !m_panelGeneral->Validate() )
1672  return true;
1673  if( !m_localSettingsPanel->Validate() )
1674  return true;
1675  if( !m_spokeWidth.Validate( 0, INT_MAX ) )
1676  return false;
1677 
1678  m_OrientValidator.TransferFromWindow();
1679 
1680  aPad->SetAttribute( code_type[m_PadType->GetSelection()] );
1681  aPad->SetShape( code_shape[m_PadShapeSelector->GetSelection()] );
1682 
1683  if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CUSTOM_RECT_ANCHOR )
1685  else
1687 
1688  if( aPad->GetShape() == PAD_SHAPE::CUSTOM )
1690 
1691  // Read pad clearances values:
1696  aPad->SetThermalGap( m_thermalGap.GetValue() );
1697 
1698  double dtmp = 0.0;
1699  msg = m_SolderPasteMarginRatioCtrl->GetValue();
1700  msg.ToDouble( &dtmp );
1701  aPad->SetLocalSolderPasteMarginRatio( dtmp / 100 );
1702 
1703  switch( m_ZoneConnectionChoice->GetSelection() )
1704  {
1705  default:
1706  case 0: aPad->SetZoneConnection( ZONE_CONNECTION::INHERITED ); break;
1707  case 1: aPad->SetZoneConnection( ZONE_CONNECTION::FULL ); break;
1708  case 2: aPad->SetZoneConnection( ZONE_CONNECTION::THERMAL ); break;
1709  case 3: aPad->SetZoneConnection( ZONE_CONNECTION::NONE ); break;
1710  }
1711 
1712  aPad->SetPosition( wxPoint( m_posX.GetValue(), m_posY.GetValue() ) );
1713 
1714  if( m_holeShapeCtrl->GetSelection() == 0 )
1715  {
1717  aPad->SetDrillSize( wxSize( m_holeX.GetValue(), m_holeX.GetValue() ) );
1718  }
1719  else
1720  {
1722  aPad->SetDrillSize( wxSize( m_holeX.GetValue(), m_holeY.GetValue() ) );
1723  }
1724 
1725  if( aPad->GetShape() == PAD_SHAPE::CIRCLE )
1726  aPad->SetSize( wxSize( m_sizeX.GetValue(), m_sizeX.GetValue() ) );
1727  else
1728  aPad->SetSize( wxSize( m_sizeX.GetValue(), m_sizeY.GetValue() ) );
1729 
1730  // For a trapezoid, test delta value (be sure delta is not too large for pad size)
1731  // remember DeltaSize.x is the Y size variation
1732  bool error = false;
1733  wxSize delta( 0, 0 );
1734 
1735  if( aPad->GetShape() == PAD_SHAPE::TRAPEZOID )
1736  {
1737  // For a trapezoid, only one of delta.x or delta.y is not 0, depending on axis.
1738  if( m_trapAxisCtrl->GetSelection() == 0 )
1739  delta.x = m_trapDelta.GetValue();
1740  else
1741  delta.y = m_trapDelta.GetValue();
1742 
1743  if( delta.x < 0 && delta.x <= -aPad->GetSize().y )
1744  {
1745  delta.x = -aPad->GetSize().y + 2;
1746  error = true;
1747  }
1748 
1749  if( delta.x > 0 && delta.x >= aPad->GetSize().y )
1750  {
1751  delta.x = aPad->GetSize().y - 2;
1752  error = true;
1753  }
1754 
1755  if( delta.y < 0 && delta.y <= -aPad->GetSize().x )
1756  {
1757  delta.y = -aPad->GetSize().x + 2;
1758  error = true;
1759  }
1760 
1761  if( delta.y > 0 && delta.y >= aPad->GetSize().x )
1762  {
1763  delta.y = aPad->GetSize().x - 2;
1764  error = true;
1765  }
1766  }
1767 
1768  aPad->SetDelta( delta );
1769 
1770  if( m_offsetShapeOpt->GetValue() )
1771  aPad->SetOffset( wxPoint( m_offsetX.GetValue(), m_offsetY.GetValue() ) );
1772  else
1773  aPad->SetOffset( wxPoint() );
1774 
1775  // Read pad length die
1776  if( m_padToDieOpt->GetValue() )
1778  else
1779  aPad->SetPadToDieLength( 0 );
1780 
1781  aPad->SetOrientation( m_OrientValue * 10.0 );
1782  aPad->SetName( m_PadNumCtrl->GetValue() );
1784 
1785  int chamfers = 0;
1786 
1787  if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_RECT )
1788  {
1789  if( m_cbTopLeft->GetValue() )
1790  chamfers |= RECT_CHAMFER_TOP_LEFT;
1791 
1792  if( m_cbTopRight->GetValue() )
1793  chamfers |= RECT_CHAMFER_TOP_RIGHT;
1794 
1795  if( m_cbBottomLeft->GetValue() )
1796  chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1797 
1798  if( m_cbBottomRight->GetValue() )
1799  chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1800  }
1801  else if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT )
1802  {
1803  if( m_cbTopLeft1->GetValue() )
1804  chamfers |= RECT_CHAMFER_TOP_LEFT;
1805 
1806  if( m_cbTopRight1->GetValue() )
1807  chamfers |= RECT_CHAMFER_TOP_RIGHT;
1808 
1809  if( m_cbBottomLeft1->GetValue() )
1810  chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1811 
1812  if( m_cbBottomRight1->GetValue() )
1813  chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1814  }
1815  aPad->SetChamferPositions( chamfers );
1816 
1817  if( aPad->GetShape() == PAD_SHAPE::CUSTOM )
1818  {
1819  // The pad custom has a "anchor pad" (a basic shape: round or rect pad)
1820  // that is the minimal area of this pad, and is usefull to ensure a hole
1821  // diameter is acceptable, and is used in Gerber files as flashed area
1822  // reference
1823  if( aPad->GetAnchorPadShape() == PAD_SHAPE::CIRCLE )
1824  aPad->SetSize( wxSize( m_sizeX.GetValue(), m_sizeX.GetValue() ) );
1825 
1826  // define the way the clearance area is defined in zones
1827  aPad->SetCustomShapeInZoneOpt( m_ZoneCustomPadShape->GetSelection() == 0 ?
1830  }
1831 
1832  switch( aPad->GetAttribute() )
1833  {
1834  case PAD_ATTRIB::PTH:
1835  break;
1836 
1837  case PAD_ATTRIB::CONN:
1838  case PAD_ATTRIB::SMD:
1839  // SMD and PAD_ATTRIB::CONN has no hole.
1840  // basically, SMD and PAD_ATTRIB::CONN are same type of pads
1841  // PAD_ATTRIB::CONN has just a default non technical layers that differs from SMD
1842  // and are intended to be used in virtual edge board connectors
1843  // However we can accept a non null offset,
1844  // mainly to allow complex pads build from a set of basic pad shapes
1845  aPad->SetDrillSize( wxSize( 0, 0 ) );
1846  break;
1847 
1848  case PAD_ATTRIB::NPTH:
1849  // Mechanical purpose only:
1850  // no net name, no pad name allowed
1851  aPad->SetName( wxEmptyString );
1853  break;
1854 
1855  default:
1856  wxFAIL_MSG( "DIALOG_PAD_PROPERTIES::transferDataToPad: unknown pad type" );
1857  break;
1858  }
1859 
1860  if( aPad->GetShape() == PAD_SHAPE::ROUNDRECT )
1861  {
1862  double ratioPercent;
1863 
1864  m_tcCornerSizeRatio->GetValue().ToDouble( &ratioPercent );
1865  aPad->SetRoundRectRadiusRatio( ratioPercent / 100.0 );
1866  }
1867 
1868  if( aPad->GetShape() == PAD_SHAPE::CHAMFERED_RECT )
1869  {
1871  {
1872  double ratioPercent;
1873 
1874  m_tcMixedCornerSizeRatio->GetValue().ToDouble( &ratioPercent );
1875  aPad->SetRoundRectRadiusRatio( ratioPercent / 100.0 );
1876 
1877  m_tcMixedChamferRatio->GetValue().ToDouble( &ratioPercent );
1878  aPad->SetChamferRectRatio( ratioPercent / 100.0 );
1879  }
1880  else // Choice is CHOICE_SHAPE_CHAMFERED_RECT, no rounded corner
1881  {
1882  double ratioPercent;
1883 
1884  m_tcChamferRatio->GetValue().ToDouble( &ratioPercent );
1885  aPad->SetChamferRectRatio( ratioPercent / 100.0 );
1886  aPad->SetRoundRectRadiusRatio( 0 );
1887  }
1888  }
1889 
1890  aPad->SetProperty( getSelectedProperty() );
1891 
1892  LSET padLayerMask = LSET();
1893  int copperLayersChoice = m_rbCopperLayersSel->GetSelection();
1894 
1895  aPad->SetRemoveUnconnected( false );
1896  aPad->SetKeepTopBottom( false );
1897 
1898  switch( m_PadType->GetSelection() )
1899  {
1900  case PTH_DLG_TYPE:
1901  switch( copperLayersChoice )
1902  {
1903  case 0:
1904  // All copper layers
1905  padLayerMask |= LSET::AllCuMask();
1906  break;
1907 
1908  case 1:
1909  // Front, back and connected
1910  padLayerMask |= LSET::AllCuMask();
1911  aPad->SetRemoveUnconnected( true );
1912  aPad->SetKeepTopBottom( true );
1913  break;
1914 
1915  case 2:
1916  // Connected only
1917  padLayerMask |= LSET::AllCuMask();
1918  aPad->SetRemoveUnconnected( true );
1919  break;
1920 
1921  case 3:
1922  // No copper layers
1923  break;
1924  }
1925 
1926  break;
1927 
1928  case NPTH_DLG_TYPE:
1929  switch( copperLayersChoice )
1930  {
1931  case 0: padLayerMask.set( F_Cu ).set( B_Cu ); break;
1932  case 1: padLayerMask.set( F_Cu ); break;
1933  case 2: padLayerMask.set( B_Cu ); break;
1934  default: break;
1935  }
1936 
1937  break;
1938 
1939  case SMD_DLG_TYPE:
1940  case CONN_DLG_TYPE:
1941  switch( copperLayersChoice )
1942  {
1943  case 0: padLayerMask.set( F_Cu ); break;
1944  case 1: padLayerMask.set( B_Cu ); break;
1945  }
1946 
1947  break;
1948 
1949  case APERTURE_DLG_TYPE:
1950  // no copper layers
1951  break;
1952  }
1953 
1954  if( m_PadLayerAdhCmp->GetValue() )
1955  padLayerMask.set( F_Adhes );
1956 
1957  if( m_PadLayerAdhCu->GetValue() )
1958  padLayerMask.set( B_Adhes );
1959 
1960  if( m_PadLayerPateCmp->GetValue() )
1961  padLayerMask.set( F_Paste );
1962 
1963  if( m_PadLayerPateCu->GetValue() )
1964  padLayerMask.set( B_Paste );
1965 
1966  if( m_PadLayerSilkCmp->GetValue() )
1967  padLayerMask.set( F_SilkS );
1968 
1969  if( m_PadLayerSilkCu->GetValue() )
1970  padLayerMask.set( B_SilkS );
1971 
1972  if( m_PadLayerMaskCmp->GetValue() )
1973  padLayerMask.set( F_Mask );
1974 
1975  if( m_PadLayerMaskCu->GetValue() )
1976  padLayerMask.set( B_Mask );
1977 
1978  if( m_PadLayerECO1->GetValue() )
1979  padLayerMask.set( Eco1_User );
1980 
1981  if( m_PadLayerECO2->GetValue() )
1982  padLayerMask.set( Eco2_User );
1983 
1984  if( m_PadLayerDraft->GetValue() )
1985  padLayerMask.set( Dwgs_User );
1986 
1987  aPad->SetLayerSet( padLayerMask );
1988 
1989  return error;
1990 }
1991 
1992 
1993 void DIALOG_PAD_PROPERTIES::OnOffsetCheckbox( wxCommandEvent& event )
1994 {
1995  if( m_offsetShapeOpt->GetValue() )
1996  {
1999  }
2000 
2001  // Show/hide controls depending on m_offsetShapeOpt being enabled
2002  m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
2003  m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
2004 
2005  for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
2006  m_notebook->GetPage( i )->Layout();
2007 
2008  OnValuesChanged( event );
2009 }
2010 
2011 
2012 void DIALOG_PAD_PROPERTIES::OnPadToDieCheckbox( wxCommandEvent& event )
2013 {
2014  if( m_padToDieOpt->GetValue() && m_currentPad )
2016 
2017  OnValuesChanged( event );
2018 }
2019 
2020 
2021 void DIALOG_PAD_PROPERTIES::OnValuesChanged( wxCommandEvent& event )
2022 {
2023  if( m_canUpdate )
2024  {
2026  // If the pad size has changed, update the displayed values
2027  // for rounded rect pads
2029 
2030  redraw();
2031  }
2032 }
2033 
2035 {
2036  long select = m_listCtrlPrimitives->GetFirstSelected();
2037 
2038  if( select < 0 )
2039  {
2040  wxMessageBox( _( "No shape selected" ) );
2041  return;
2042  }
2043 
2044  std::shared_ptr<PCB_SHAPE>& shape = m_primitives[select];
2045 
2046  if( shape->GetShape() == PCB_SHAPE_TYPE::POLYGON )
2047  {
2048  DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, m_parent, shape.get() );
2049 
2050  if( dlg.ShowModal() != wxID_OK )
2051  return;
2052 
2053  dlg.TransferDataFromWindow();
2054  }
2055 
2056  else
2057  {
2058  DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, m_parent, shape.get() );
2059 
2060  if( dlg.ShowModal() != wxID_OK )
2061  return;
2062 
2063  dlg.TransferDataFromWindow();
2064  }
2065 
2067 
2068  if( m_canUpdate )
2069  {
2071  redraw();
2072  }
2073 }
2074 
2075 
2077 {
2078  // Called on a double click on the basic shapes list
2079  // To Do: highligth the primitive(s) currently selected.
2080  redraw();
2081 }
2082 
2083 
2085 void DIALOG_PAD_PROPERTIES::onPrimitiveDClick( wxMouseEvent& event )
2086 {
2087  editPrimitive();
2088 }
2089 
2090 
2091 // Called on a click on basic shapes list panel button
2092 void DIALOG_PAD_PROPERTIES::onEditPrimitive( wxCommandEvent& event )
2093 {
2094  editPrimitive();
2095 }
2096 
2097 // Called on a click on basic shapes list panel button
2098 void DIALOG_PAD_PROPERTIES::onDeletePrimitive( wxCommandEvent& event )
2099 {
2100  long select = m_listCtrlPrimitives->GetFirstSelected();
2101 
2102  if( select < 0 )
2103  return;
2104 
2105  // Multiple selections are allowed. get them and remove corresponding shapes
2106  std::vector<long> indexes;
2107  indexes.push_back( select );
2108 
2109  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2110  indexes.push_back( select );
2111 
2112  // Erase all select shapes
2113  for( unsigned ii = indexes.size(); ii > 0; --ii )
2114  m_primitives.erase( m_primitives.begin() + indexes[ii-1] );
2115 
2117 
2118  if( m_canUpdate )
2119  {
2121  redraw();
2122  }
2123 }
2124 
2125 
2126 void DIALOG_PAD_PROPERTIES::onAddPrimitive( wxCommandEvent& event )
2127 {
2128  // Ask user for shape type
2129  wxString shapelist[] = {
2130  _( "Segment" ),
2131  _( "Arc" ),
2132  _( "Bezier" ),
2133  _( "Ring/Circle" ),
2134  _( "Polygon" )
2135  };
2136 
2137  int type = wxGetSingleChoiceIndex( _( "Shape type:" ), _( "Add Primitive" ),
2138  arrayDim( shapelist ), shapelist, 0, this );
2139 
2140  // User pressed cancel
2141  if( type == -1 )
2142  return;
2143 
2147 
2148  PCB_SHAPE* primitive = new PCB_SHAPE();
2149  primitive->SetShape( listtype[type] );
2151  primitive->SetFilled( true );
2152 
2153  if( listtype[type] == PCB_SHAPE_TYPE::POLYGON )
2154  {
2155  DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, m_parent, primitive );
2156 
2157  if( dlg.ShowModal() != wxID_OK )
2158  return;
2159  }
2160  else
2161  {
2162  DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, m_parent, primitive );
2163 
2164  if( dlg.ShowModal() != wxID_OK )
2165  return;
2166  }
2167 
2168  m_primitives.emplace_back( primitive );
2169 
2171 
2172  if( m_canUpdate )
2173  {
2175  redraw();
2176  }
2177 }
2178 
2179 
2180 void DIALOG_PAD_PROPERTIES::onGeometryTransform( wxCommandEvent& event )
2181 {
2182  long select = m_listCtrlPrimitives->GetFirstSelected();
2183 
2184  if( select < 0 )
2185  {
2186  wxMessageBox( _( "No shape selected" ) );
2187  return;
2188  }
2189 
2190  // Multiple selections are allowed. Build selected shapes list
2191  std::vector<std::shared_ptr<PCB_SHAPE>> shapeList;
2192  shapeList.emplace_back( m_primitives[select] );
2193 
2194  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2195  shapeList.emplace_back( m_primitives[select] );
2196 
2197  DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, m_parent, shapeList, false );
2198 
2199  if( dlg.ShowModal() != wxID_OK )
2200  return;
2201 
2202  dlg.Transform();
2203 
2205 
2206  if( m_canUpdate )
2207  {
2209  redraw();
2210  }
2211 }
2212 
2213 
2214 void DIALOG_PAD_PROPERTIES::onDuplicatePrimitive( wxCommandEvent& event )
2215 {
2216  long select = m_listCtrlPrimitives->GetFirstSelected();
2217 
2218  if( select < 0 )
2219  {
2220  wxMessageBox( _( "No shape selected" ) );
2221  return;
2222  }
2223 
2224  // Multiple selections are allowed. Build selected shapes list
2225  std::vector<std::shared_ptr<PCB_SHAPE>> shapeList;
2226  shapeList.emplace_back( m_primitives[select] );
2227 
2228  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2229  shapeList.emplace_back( m_primitives[select] );
2230 
2231  DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, m_parent, shapeList, true );
2232 
2233  if( dlg.ShowModal() != wxID_OK )
2234  return;
2235 
2236  // Transfer new settings
2237  // save duplicates to a separate vector to avoid m_primitives reallocation,
2238  // as shapeList contains pointers to its elements
2239  std::vector<std::shared_ptr<PCB_SHAPE>> duplicates;
2240  dlg.Transform( &duplicates, dlg.GetDuplicateCount() );
2241  std::move( duplicates.begin(), duplicates.end(), std::back_inserter( m_primitives ) );
2242 
2244 
2245  if( m_canUpdate )
2246  {
2248  redraw();
2249  }
2250 }
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)
Function Move moves the rectangle by the aMoveVector.
Definition: box2.h:120
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:90
void SetOffset(const wxPoint &aOffset)
Definition: pad.h:248
COMMIT & Modify(EDA_ITEM *aItem)
Create an undo entry for an item that has been already modified.
Definition: commit.h:103
static LSET ConnSMDMask()
layer set for a SMD pad on Front layer used for edge board connectors
Definition: pad.cpp:161
void SetLocalSolderPasteMarginRatio(double aRatio)
Definition: pad.h:397
void SetViewport(const BOX2D &aViewport)
Set the visible area of the VIEW.
Definition: view.cpp:526
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:559
KIGFX::VIEW_CONTROLS * GetViewControls() const
Return a pointer to the #VIEW_CONTROLS instance used in the panel.
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:342
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:837
multilayer pads, usually with holes
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:194
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:204
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)
void SetFilled(bool aFlag)
Definition: pcb_shape.h:94
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
#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
void SetName(const wxString &aName)
Set the pad name (sometimes called pad number, although it can be an array reference like AA12).
Definition: pad.h:132
Tool relating to pads and pad settings.
Definition: pad_tool.h:35
bool IsLocked() const override
Definition: pad.cpp:138
double GetOrientation() const
Definition: footprint.h:186
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
coord_type GetRight() const
Definition: box2.h:199
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
Definition: sch_symbol.cpp:69
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:189
const SHAPE_SEGMENT * GetEffectiveHoleShape() const
Return a SHAPE object representing the pad's hole.
Definition: pad.cpp:285
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.h:593
int GetSelectedNetcode()
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:754
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:257
void SetSize(const wxSize &aSize)
Definition: pad.h:231
PCB_SHAPE_TYPE
The set of shapes for PCB graphics and tracks and footprint graphics in the .m_Shape member.
Definition: board_item.h:48
void NORMALIZE_ANGLE_180(T &Angle)
Definition: trigo.h:385
void SetDelta(const wxSize &aSize)
Definition: pad.h:238
coord_type GetBottom() const
Definition: box2.h:200
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:228
virtual void Rotate(const wxPoint &aRotCentre, double aAngle) override
Rotate this object.
Definition: pcb_shape.cpp:198
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
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:98
void SetSketchModeGraphicItems(bool aEnabled)
Turn on/off sketch mode for graphic items (DRAWSEGMENTs, texts).
Definition: pcb_painter.h:128
bool IsFlipped() const
Definition: pad.cpp:182
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:207
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:166
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
Function TransferDataFromWindow Transfer data out of the GUI.
FP_TEXT & Value()
read/write accessors:
Definition: footprint.h:462
void SetPadToDieLength(int aLength)
Definition: pad.h:383
void SetProperty(PAD_PROP aProperty)
Definition: pad.cpp:570
Classes used in Pcbnew, CvPcb and GerbView.
polygon (not yet used for tracks, but could be in microwave apps)
FP_TEXT & Reference()
Definition: footprint.h:463
a pad used as heat sink, usually in SMD footprints
void TransformOvalToPolygon(SHAPE_POLY_SET &aCornerBuffer, wxPoint aStart, wxPoint aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc)
convert a oblong shape to a polygon, using multiple segments It is similar to TransformRoundedEndsSeg...
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:113
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:249
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:242
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:506
PCB_LAYER_ID
A quick note on layer IDs:
#define BRIGHTENED
item is drawn with a bright contour
Definition: eda_item.h:131
void Show(bool aShow, bool aResize=false)
Show/hide the label, widget and units label.
LSET is a set of PCB_LAYER_IDs.
pads are covered by copper
int GetThermalSpokeWidth() const
Definition: pad.h:491
void SetFlags(STATUS_FLAGS aMask)
Definition: eda_item.h:203
void updatePadLayersList(LSET layer_mask, bool remove_unconnected, bool keep_top_bottom)
Function updatePadLayersList updates the CheckBox states in pad layers list, based on the layer_mask ...
void SetLastPadName(const wxString &aPadName)
Definition: pad_tool.h:63
#define NULL
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:225
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:587
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.
int ShowQuasiModal()
void ListSet(const wxString &aList)
Add a list of items.
coord_type GetWidth() const
Definition: box2.h:197
void SetDrillSize(const wxSize &aSize)
Definition: pad.h:241
const wxSize & GetSize() const
Definition: pad.h:232
#define SELECTED
Definition: eda_item.h:114
Inactive layers are shown normally (no high-contrast mode)
ZONE_CONNECTION GetEffectiveZoneConnection(wxString *aSource=nullptr) const
Return the zone connection in effect (either locally overridden or overridden in the parent footprint...
Definition: pad.cpp:791
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:1311
const wxString & GetName() const
Definition: pad.h:133
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:147
void onPrimitiveDClick(wxMouseEvent &event) override
Called on a double click on the basic shapes list.
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:169
a fiducial (usually a smd) local to the parent footprint
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.
#define DO_NOT_DRAW
Used to disable draw function.
Definition: eda_item.h:119
void OnDrillShapeSelected(wxCommandEvent &event) override
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)
HTML_MESSAGE_BOX.
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:197
bool IsOnCopperLayer() const override
Definition: pad.h:217
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:104
void MergePrimitivesAsPolygon(SHAPE_POLY_SET *aMergedPolygon, PCB_LAYER_ID aLayer, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Merge all basic shapes to a SHAPE_POLY_SET.
void SetRoundRectRadiusRatio(double aRadiusScale)
Has meaning only for rounded rectangle pads.
Definition: pad.cpp:251
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:685
void StartDrawing()
Begin drawing if it was stopped previously.
void SetDrillShape(PAD_DRILL_SHAPE_T aShape)
Definition: pad.h:353
bool Show(bool show) override
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
void 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:242
int GetRoundRectCornerRadius() const
Definition: pad.cpp:236
const wxSize & GetDelta() const
Definition: pad.h:239
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
FOOTPRINT * GetParent() const
Definition: pad.cpp:1334
void SetChamferPositions(int aPositions)
Has meaning only for chamfered rectangular pads.
Definition: pad.h:541
bool Show(bool aShow) override
Definition: seg.h:41
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:199
bool IsFlipped() const
Definition: footprint.h:266
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.
double GetOrientationDegrees() const
Definition: footprint.h:187
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.
bool TransferDataFromWindow() override
Updates the different parameters for the component being edited.
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:302
static LSET ApertureMask()
layer set for an aperture pad
Definition: pad.cpp:175
void SetLayerSet(LSET aLayers) override
Definition: pad.h:367
void PadOrientEvent(wxCommandEvent &event) override
CUST_PAD_SHAPE_IN_ZONE GetCustomShapeInZoneOpt() const
Definition: pad.h:187
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.
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:157
smd pads, front layer
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:177
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:257
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: pad.h:354
no special fabrication property
void onDuplicatePrimitive(wxCommandEvent &event) override
#define _(s)
Definition: 3d_actions.cpp:33
void SetSketchMode(int aItemLayer, bool aEnabled)
Turn on/off sketch mode for given item layer.
Definition: pcb_painter.h:107
PAD_ATTRIB GetAttribute() const
Definition: pad.h:371
void SetLastEditTime(timestamp_t aTime)
Definition: footprint.h:330
#define APERTURE_DLG_TYPE
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:171
#define PTH_DLG_TYPE
VECTOR2I A
Definition: seg.h:49
usual segment : line with rounded ends
void SetWidth(int aWidth)
Definition: pcb_shape.h:117
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:68
PCB_DRAW_PANEL_GAL * m_padPreviewGAL
coord_type GetHeight() const
Definition: box2.h:198
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:182
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 ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:204
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:190
void SetShape(PAD_SHAPE aShape)
Set the new shape of this pad.
Definition: pad.h:160
int GetChamferPositions() const
Definition: pad.h:542
bool padValuesOK()
test if all values are acceptable for the pad
a pad with a castellated through hole
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
Definition: pad.cpp:168
void SetCoordType(ORIGIN_TRANSFORMS::COORD_TYPES_T aCoordType)
Set the current origin transform mode.
Definition: unit_binder.h:173
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:322
GAL_TYPE GetBackend() const
Return the type of backend currently used by GAL canvas.
const Vec & GetSize() const
Definition: box2.h:189
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:203
BOARD * GetBoard() const
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:67
void SetBoundary(const BOX2D &aBoundary)
Set limits for view area.
Definition: view.h:273
Definition: pad.h:60
void ShowPadPropertiesDialog(PAD *aPad)
void SetChamferRectRatio(double aChamferScale)
Has meaning only for chamfered rectangular pads.
Definition: pad.cpp:259
void SetShape(PCB_SHAPE_TYPE aShape)
Definition: pcb_shape.h:129
Arcs (with rounded ends)
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:398
int GetWidth() const
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: pad.cpp:154
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:365
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:182
void Enable(bool aEnable)
Enable/disable the label, widget and units label.
a dialog to edit basics shapes parameters.
void SetOrientation(double aAngle)
Set the rotation angle of the pad.
Definition: pad.cpp:578
bool TransferDataFromWindow() override
Function TransferDataFromWindow 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:1503
void OnUpdateUI(wxUpdateUIEvent &event) override
void SetAnchorPadShape(PAD_SHAPE aShape)
Set the shape of the anchor pad for custom shaped pads.
Definition: pad.h:208
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:98
virtual void ChangeValue(int aValue)
Change the value (in Internal Units) for the text field, taking care of units conversion but does not...
VECTOR2I B
Definition: seg.h:50