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