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 <class_board.h>
31 #include <class_module.h>
32 #include <confirm.h>
33 #include <convert_basic_shapes_to_polygon.h> // for enum RECT_CHAMFER_POSITIONS definition
34 #include <geometry/shape_segment.h>
35 #include <dialog_pad_properties.h>
38 #include <macros.h>
39 #include <pcb_base_frame.h>
40 #include <pcb_painter.h>
41 #include <pcbnew_settings.h>
43 #include <view/view_controls.h>
44 #include <widgets/net_selector.h>
45 #include <tool/tool_manager.h>
46 #include <tools/pad_tool.h>
47 #include <advanced_config.h> // for pad property feature management
48 
49 
50 // list of pad shapes, ordered like the pad shape wxChoice in dialog.
52 {
59  PAD_SHAPE_CHAMFERED_RECT, // choice = CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT
60  PAD_SHAPE_CUSTOM, // choice = CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
61  PAD_SHAPE_CUSTOM // choice = PAD_SHAPE_CUSTOM_RECT_ANCHOR
62 };
63 
64 // the ordered index of the pad shape wxChoice in dialog.
65 // keep it consistent with code_shape[] and dialog strings
67 {
77 };
78 
80 {
85  PAD_ATTRIB_SMD // Aperture pad :type SMD with no copper layers,
86  // only on tech layers (usually only on paste layer
87 };
88 
89 // Default mask layers setup for pads according to the pad type
90 static const LSET std_pad_layers[] =
91 {
92  D_PAD::PTHMask(), // PAD_ATTRIB_PTH:
93  D_PAD::SMDMask(), // PAD_ATTRIB_SMD:
94  D_PAD::ConnSMDMask(), // PAD_ATTRIB_CONN:
95  D_PAD::UnplatedHoleMask(), // PAD_ATTRIB_NPTH:
97 };
98 
99 
101 {
102  DIALOG_PAD_PROPERTIES dlg( this, aPad );
103 
104  if( dlg.ShowQuasiModal() == wxID_OK ) // QuasiModal required for NET_SELECTOR
105  {
106  // aPad can be NULL, if the dialog is called from the footprint editor
107  // to set the default pad setup
108  if( aPad )
109  {
110  PAD_TOOL* padTools = m_toolManager->GetTool<PAD_TOOL>();
111 
112  if( padTools )
113  padTools->SetLastPadName( aPad->GetName() );
114  }
115  }
116 }
117 
118 
120  DIALOG_PAD_PROPERTIES_BASE( aParent ),
121  m_parent( aParent ),
122  m_canUpdate( false ),
123  m_posX( aParent, m_posXLabel, m_posXCtrl, m_posXUnits ),
124  m_posY( aParent, m_posYLabel, m_posYCtrl, m_posYUnits ),
125  m_sizeX( aParent, m_sizeXLabel, m_sizeXCtrl, m_sizeXUnits, true ),
126  m_sizeY( aParent, m_sizeYLabel, m_sizeYCtrl, m_sizeYUnits, true ),
127  m_offsetX( aParent, m_offsetXLabel, m_offsetXCtrl, m_offsetXUnits, true ),
128  m_offsetY( aParent, m_offsetYLabel, m_offsetYCtrl, m_offsetYUnits, true ),
129  m_padToDie( aParent, m_padToDieLabel, m_padToDieCtrl, m_padToDieUnits, true ),
130  m_trapDelta( aParent, m_trapDeltaLabel, m_trapDeltaCtrl, m_trapDeltaUnits, true ),
131  m_cornerRadius( aParent, m_cornerRadiusLabel, m_tcCornerRadius, m_cornerRadiusUnits, true ),
132  m_holeX( aParent, m_holeXLabel, m_holeXCtrl, m_holeXUnits, true ),
133  m_holeY( aParent, m_holeYLabel, m_holeYCtrl, m_holeYUnits, true ),
134  m_OrientValidator( 1, &m_OrientValue ),
135  m_clearance( aParent, m_clearanceLabel, m_clearanceCtrl, m_clearanceUnits, true ),
136  m_maskClearance( aParent, m_maskClearanceLabel, m_maskClearanceCtrl, m_maskClearanceUnits, true ),
137  m_pasteClearance( aParent, m_pasteClearanceLabel, m_pasteClearanceCtrl, m_pasteClearanceUnits, true ),
138  m_spokeWidth( aParent, m_spokeWidthLabel, m_spokeWidthCtrl, m_spokeWidthUnits, true ),
139  m_thermalGap( aParent, m_thermalGapLabel, m_thermalGapCtrl, m_thermalGapUnits, true )
140 {
141  m_currentPad = aPad; // aPad can be NULL, if the dialog is called
142  // from the footprint editor to set default pad setup
143 
145 
146  // Configure display origin transforms
149 
152 
153  m_OrientValidator.SetRange( -360.0, 360.0 );
154  m_orientation->SetValidator( m_OrientValidator );
155  m_OrientValidator.SetWindow( m_orientation );
156 
157  m_cbShowPadOutline->SetValue( m_sketchPreview );
158 
161 
163  m_dummyPad = new D_PAD( (MODULE*) NULL );
164 
165  if( aPad )
166  {
167  *m_dummyPad = *aPad;
169  }
170  else // We are editing a "master" pad, i.e. a template to create new pads
172 
173  // Pad needs to have a parent for painting; use the parent board for its design settings
174  if( !m_dummyPad->GetParent() )
176 
177  initValues();
178 
179  wxFont infoFont = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
180  infoFont.SetSymbolicSize( wxFONTSIZE_SMALL );
181  m_copperLayersLabel->SetFont( infoFont );
182  m_techLayersLabel->SetFont( infoFont );
183  m_parentInfo->SetFont( infoFont );
184 
185  infoFont.SetStyle( wxFONTSTYLE_ITALIC );
186  m_nonCopperNote->SetFont( infoFont );
187  m_staticTextInfoPaste->SetFont( infoFont );
188  m_staticTextInfoNegVal->SetFont( infoFont );
189  m_staticTextInfoPosValue->SetFont( infoFont );
190  m_staticTextPrimitiveListWarning->SetFont( infoFont );
191 
192  // Usually, TransferDataToWindow is called by OnInitDialog
193  // calling it here fixes all widget sizes so FinishDialogSettings can safely fix minsizes
195 
196  // Initialize canvas to be able to display the dummy pad:
197  prepareCanvas();
198 
200  m_sdbSizerOK->SetDefault();
201  m_canUpdate = true;
202 
203  m_PadNetSelector->Connect( NET_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ), NULL, this );
204 
205  // Now all widgets have the size fixed, call FinishDialogSettings
207 
208  wxUpdateUIEvent dummy;
209  OnUpdateUI( dummy );
210 }
211 
212 
214 {
215  m_PadNetSelector->Disconnect( NET_SELECTED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ), NULL, this );
216 
217  delete m_dummyPad;
218  delete m_axisOrigin;
219 }
220 
221 
222 bool DIALOG_PAD_PROPERTIES::m_sketchPreview = false; // Stores the pad draw option during a session
223 
224 
225 void DIALOG_PAD_PROPERTIES::OnInitDialog( wxInitDialogEvent& event )
226 {
227  m_selectedColor = COLOR4D( 1.0, 1.0, 1.0, 0.7 );
228 
229  // Needed on some WM to be sure the pad is redrawn according to the final size
230  // of the canvas, with the right zoom factor
231  redraw();
232 }
233 
234 
235 void DIALOG_PAD_PROPERTIES::OnCancel( wxCommandEvent& event )
236 {
237  // Mandatory to avoid m_panelShowPadGal trying to draw something
238  // in a non valid context during closing process:
240 
241  // Now call default handler for wxID_CANCEL command event
242  event.Skip();
243 }
244 
245 
247 {
248  // Enable or disable the widgets in page managing custom shape primitives
249  m_listCtrlPrimitives->Enable( aEnable );
250  m_buttonDel->Enable( aEnable );
251  m_buttonEditShape->Enable( aEnable );
252  m_buttonAddShape->Enable( aEnable );
253  m_buttonDup->Enable( aEnable );
254  m_buttonGeometry->Enable( aEnable );
255 }
256 
257 
259 {
260  // Initialize the canvas to display the pad
261  m_padPreviewGAL = new PCB_DRAW_PANEL_GAL( m_boardViewPanel, -1, wxDefaultPosition,
262  wxDefaultSize,
265 
266  m_padPreviewSizer->Add( m_padPreviewGAL, 12, wxEXPAND | wxALL, 5 );
267 
268  // Show the X and Y axis. It is usefull because pad shape can have an offset
269  // or be a complex shape.
270  KIGFX::COLOR4D axis_color = LIGHTBLUE;
271 
273  Millimeter2iu( 0.2 ),
275  m_axisOrigin->SetDrawAtZero( true );
276 
279  m_padPreviewGAL->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
280 
281  KIGFX::VIEW_CONTROLS* parentViewControls = m_parent->GetCanvas()->GetViewControls();
282  m_padPreviewGAL->GetViewControls()->ApplySettings( parentViewControls->GetSettings() );
283 
284  m_padPreviewGAL->Show();
285 
287 
288  // fix the pad render mode (filled/not filled)
289  auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
290  bool sketchMode = m_cbShowPadOutline->IsChecked();
291  settings->SetSketchMode( LAYER_PADS_TH, sketchMode );
292  settings->SetSketchMode( LAYER_PAD_FR, sketchMode );
293  settings->SetSketchMode( LAYER_PAD_BK, sketchMode );
294  settings->SetSketchModeGraphicItems( sketchMode );
295 
296  settings->SetHighContrast( false );
297  settings->SetContrastModeDisplay( HIGH_CONTRAST_MODE::NORMAL );
298 
299  // gives a non null grid size (0.001mm) because GAL layer does not like a 0 size grid:
300  double gridsize = 0.001 * IU_PER_MM;
301  view->GetGAL()->SetGridSize( VECTOR2D( gridsize, gridsize ) );
302  // And do not show the grid:
303  view->GetGAL()->SetGridVisibility( false );
304  view->Add( m_dummyPad );
305  view->Add( m_axisOrigin );
306 
308  Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_PAD_PROPERTIES::OnResize ) );
309 }
310 
311 
313 {
314  // Note: use m_tcCornerSizeRatio->ChangeValue() to avoid generating a wxEVT_TEXT event
315 
318  {
319  wxString ratio = wxString::Format( "%.1f", m_dummyPad->GetRoundRectRadiusRatio() * 100 );
320  m_tcCornerSizeRatio->ChangeValue( ratio );
321  m_tcCornerSizeRatio1->ChangeValue( ratio );
323 
324  ratio = wxString::Format( "%.1f", m_dummyPad->GetChamferRectRatio() * 100 );
325  m_tcChamferRatio->ChangeValue( ratio );
326  m_tcChamferRatio1->ChangeValue( ratio );
327  }
328 }
329 
330 
331 void DIALOG_PAD_PROPERTIES::onCornerRadiusChange( wxCommandEvent& event )
332 {
335  return;
336 
337  double rrRadius = m_cornerRadius.GetValue();
338 
339  if( rrRadius < 0.0 )
340  {
341  rrRadius = 0.0;
342  m_tcCornerRadius->ChangeValue( wxString::Format( "%.1f", rrRadius ) );
343  }
344 
347 
348  auto ratio = wxString::Format( "%.1f", m_dummyPad->GetRoundRectRadiusRatio() * 100 );
349  m_tcCornerSizeRatio->ChangeValue( ratio );
350  m_tcCornerSizeRatio1->ChangeValue( ratio );
351 
352  redraw();
353 }
354 
355 
357 {
360  {
361  return;
362  }
363 
364  wxObject* ctrl = event.GetEventObject();
365  wxString value = event.GetString();
366  bool changed = false;
367 
368  if( ctrl == m_tcCornerSizeRatio || ctrl == m_tcCornerSizeRatio1 )
369  {
370  double ratioPercent;
371 
372  if( value.ToDouble( &ratioPercent ) )
373  {
374  // Clamp ratioPercent to acceptable value (0.0 to 50.0)
375  if( ratioPercent < 0.0 )
376  {
377  ratioPercent = 0.0;
378  value.Printf( "%.1f", ratioPercent );
379  m_tcCornerSizeRatio->ChangeValue( value );
380  m_tcCornerSizeRatio1->ChangeValue( value );
381  }
382 
383  if( ratioPercent > 50.0 )
384  {
385  ratioPercent = 0.5;
386  value.Printf( "%.1f", ratioPercent*100.0 );
387  m_tcCornerSizeRatio->ChangeValue( value );
388  m_tcCornerSizeRatio1->ChangeValue( value );
389  }
390 
391  if( ctrl == m_tcCornerSizeRatio )
392  m_tcCornerSizeRatio1->ChangeValue( value );
393  else
394  m_tcCornerSizeRatio->ChangeValue( value );
395 
396  changed = true;
397  }
398  }
399  else if( ctrl == m_tcChamferRatio || ctrl == m_tcChamferRatio1 )
400  {
401  double ratioPercent;
402 
403  if( value.ToDouble( &ratioPercent ) )
404  {
405  // Clamp ratioPercent to acceptable value (0.0 to 50.0)
406  if( ratioPercent < 0.0 )
407  {
408  ratioPercent = 0.0;
409  value.Printf( "%.1f", ratioPercent );
410  m_tcChamferRatio->ChangeValue( value );
411  m_tcChamferRatio1->ChangeValue( value );
412  }
413 
414  if( ratioPercent > 50.0 )
415  {
416  ratioPercent = 0.5;
417  value.Printf( "%.1f", ratioPercent*100.0 );
418  m_tcChamferRatio->ChangeValue( value );
419  m_tcChamferRatio1->ChangeValue( value );
420  }
421 
422  if( ctrl == m_tcChamferRatio )
423  m_tcChamferRatio1->ChangeValue( value );
424  else
425  m_tcChamferRatio->ChangeValue( value );
426 
427  changed = true;
428  }
429  }
430 
431  if( changed )
432  {
435  }
436 
437  redraw();
438 }
439 
440 
442 {
443  wxString msg;
444  double angle;
445 
446  // Disable pad net name wxTextCtrl if the caller is the footprint editor
447  // because nets are living only in the board managed by the board editor
449 
450  m_PadLayerAdhCmp->SetLabel( m_board->GetLayerName( F_Adhes ) );
451  m_PadLayerAdhCu->SetLabel( m_board->GetLayerName( B_Adhes ) );
453  m_PadLayerPateCu->SetLabel( m_board->GetLayerName( B_Paste ) );
455  m_PadLayerSilkCu->SetLabel( m_board->GetLayerName( B_SilkS ) );
456  m_PadLayerMaskCmp->SetLabel( m_board->GetLayerName( F_Mask ) );
457  m_PadLayerMaskCu->SetLabel( m_board->GetLayerName( B_Mask ) );
458  m_PadLayerECO1->SetLabel( m_board->GetLayerName( Eco1_User ) );
459  m_PadLayerECO2->SetLabel( m_board->GetLayerName( Eco2_User ) );
461 
462  m_isFlipped = false;
463 
464  if( m_currentPad )
465  {
467 
468  // Diplay parent footprint info
469  MODULE* footprint = m_currentPad->GetParent();
470 
471  if( footprint )
472  {
473  msg.Printf( _("Footprint %s (%s), %s, rotated %.1f deg"),
474  footprint->Reference().GetShownText(),
475  footprint->Value().GetShownText(),
476  footprint->IsFlipped() ? _( "back side (mirrored)" )
477  : _( "front side" ),
478  footprint->GetOrientation() / 10.0 );
479  }
480 
481  m_parentInfo->SetLabel( msg );
482  }
483 
484  if( m_currentPad )
485  {
486  MODULE* footprint = m_currentPad->GetParent();
487 
488  if( footprint )
489  {
491  angle -= footprint->GetOrientation();
493  }
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_PadShape->SetSelection( CHOICE_SHAPE_CIRCLE ); break;
580  case PAD_SHAPE_OVAL: m_PadShape->SetSelection( CHOICE_SHAPE_OVAL ); break;
581  case PAD_SHAPE_RECT: m_PadShape->SetSelection( CHOICE_SHAPE_RECT ); break;
582  case PAD_SHAPE_TRAPEZOID: m_PadShape->SetSelection( CHOICE_SHAPE_TRAPEZOID ); break;
583  case PAD_SHAPE_ROUNDRECT: m_PadShape->SetSelection( CHOICE_SHAPE_ROUNDRECT ); break;
584 
586  if( m_dummyPad->GetRoundRectRadiusRatio() > 0.0 )
588  else
589  m_PadShape->SetSelection( CHOICE_SHAPE_CHAMFERED_RECT );
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( 4 );
619  }
620  else
621  {
622  switch( m_dummyPad->GetAttribute() )
623  {
624  case PAD_ATTRIB_PTH: m_PadType->SetSelection( 0 ); break;
625  case PAD_ATTRIB_SMD: m_PadType->SetSelection( 1 ); break;
626  case PAD_ATTRIB_CONN: m_PadType->SetSelection( 2 ); break;
627  case PAD_ATTRIB_NPTH: m_PadType->SetSelection( 3 ); 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 S_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 S_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 S_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 S_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 S_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_PadShape->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  // A reasonable default is all corners chamfered.
807  if( !m_cbTopLeft->GetValue() && !m_cbTopRight->GetValue()
808  && !m_cbBottomLeft->GetValue() && !m_cbBottomRight->GetValue() )
809  {
810  m_cbTopLeft->SetValue( true );
811  m_cbTopRight->SetValue( true );
812  m_cbBottomLeft->SetValue( true );
813  m_cbBottomRight->SetValue( true );
814  }
815  break;
816 
818  {
819  m_shapePropsBook->SetSelection( 4 );
820 
821  // Reasonable defaults (corner radius from IPC-7351C)
822  if( m_dummyPad->GetRoundRectRadiusRatio() == 0.0 )
823  m_tcCornerSizeRatio->ChangeValue( "25" );
824 
825  if( m_dummyPad->GetChamferRectRatio() == 0.0 )
826  m_tcChamferRatio1->ChangeValue( "20" );
827  }
828  break;
829 
830  case CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR: // PAD_SHAPE_CUSTOM, circular anchor
831  case CHOICE_SHAPE_CUSTOM_RECT_ANCHOR: // PAD_SHAPE_CUSTOM, rect anchor
832  m_shapePropsBook->SetSelection( 0 );
833  break;
834  }
835 
836  // Readjust props book size
837  wxSize size = m_shapePropsBook->GetSize();
838  size.y = m_shapePropsBook->GetPage( m_shapePropsBook->GetSelection() )->GetBestSize().y;
839  m_shapePropsBook->SetMaxSize( size );
840 
841  m_sizeY.Enable( m_PadShape->GetSelection() != CHOICE_SHAPE_CIRCLE
842  && m_PadShape->GetSelection() != CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR );
843 
844  m_offsetShapeOpt->Enable( m_PadShape->GetSelection() != CHOICE_SHAPE_CIRCLE
845  && m_PadShape->GetSelection() != CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
846  && m_PadShape->GetSelection() != CHOICE_SHAPE_CUSTOM_RECT_ANCHOR );
847 
848  if( !m_offsetShapeOpt->IsEnabled() )
849  m_offsetShapeOpt->SetValue( false );
850 
851  // Show/hide controls depending on m_offsetShapeOpt being enabled
852  m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
853  m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
854 
855  bool is_custom = m_PadShape->GetSelection() == CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
856  || m_PadShape->GetSelection() == CHOICE_SHAPE_CUSTOM_RECT_ANCHOR;
857 
858  enablePrimitivePage( is_custom );
859  m_staticTextcps->Enable( is_custom );
860  m_ZoneCustomPadShape->Enable( is_custom );
861 
863 
865 
866  for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
867  m_notebook->GetPage( i )->Layout();
868 
869  // Resize the dialog if its height is too small to show all widgets:
870  if( m_MainSizer->GetSize().y < m_MainSizer->GetMinSize().y )
871  m_MainSizer->SetSizeHints( this );
872 
873  redraw();
874 }
875 
876 
877 void DIALOG_PAD_PROPERTIES::OnDrillShapeSelected( wxCommandEvent& event )
878 {
880  redraw();
881 }
882 
883 
884 void DIALOG_PAD_PROPERTIES::PadOrientEvent( wxCommandEvent& event )
885 {
887  redraw();
888 }
889 
890 
892 {
893  m_rbCopperLayersSel->Clear();
894 
895  if( m_PadType->GetSelection() == 0 )
896  {
897  m_rbCopperLayersSel->Append( _( "All copper layers" ) );
898  m_rbCopperLayersSel->Append( wxString::Format( _( "%s, %s and connected layers" ),
900  m_board->GetLayerName( B_Cu ) ) );
901  m_rbCopperLayersSel->Append( _( "Connected layers only" ) );
902  m_rbCopperLayersSel->Append( _( "None" ) );
903  }
904  else if( m_PadType->GetSelection() == 3 )
905  {
906  m_rbCopperLayersSel->Append( wxString::Format( _( "%s and %s" ),
908  m_board->GetLayerName( B_Cu ) ) );
911  m_rbCopperLayersSel->Append( _( "None" ) );
912  }
913  else
914  {
917  }
918 }
919 
920 
921 void DIALOG_PAD_PROPERTIES::PadTypeSelected( wxCommandEvent& event )
922 {
923  int ii = m_PadType->GetSelection();
924 
925  if( (unsigned)ii >= arrayDim( code_type ) ) // catches < 0 also
926  ii = 0;
927 
928  bool hasHole, hasConnection, hasProperty;
929 
930  switch( ii )
931  {
932  default:
933  case 0: /* PTH */ hasHole = true; hasConnection = true; hasProperty = true; break;
934  case 1: /* SMD */ hasHole = false; hasConnection = true; hasProperty = true; break;
935  case 2: /* CONN */ hasHole = false; hasConnection = true; hasProperty = true; break;
936  case 3: /* NPTH */ hasHole = true; hasConnection = false; hasProperty = false; break;
937  case 4: /* Aperture */ hasHole = false; hasConnection = false; hasProperty = true; break;
938  }
939 
942 
943  if( !hasHole )
944  {
945  m_holeX.ChangeValue( 0 );
946  m_holeY.ChangeValue( 0 );
947  }
948  else if ( m_holeX.GetValue() == 0 && m_currentPad )
949  {
952  }
953 
954  if( !hasConnection )
955  {
956  m_PadNumCtrl->ChangeValue( wxEmptyString );
958  m_padToDieOpt->SetValue( false );
959  }
960  else if( m_PadNumCtrl->GetValue().IsEmpty() && m_currentPad )
961  {
962  m_PadNumCtrl->ChangeValue( m_currentPad->GetName() );
964  }
965 
966  if( !hasProperty )
967  m_choiceFabProperty->SetSelection( 0 );
968 
969  m_choiceFabProperty->Enable( hasProperty );
970 
972 
974 
975  redraw();
976 }
977 
978 
979 void DIALOG_PAD_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
980 {
981  int ii = m_PadType->GetSelection();
982 
983  if( (unsigned)ii >= arrayDim( code_type ) ) // catches < 0 also
984  ii = 0;
985 
986  bool hasHole, hasConnection;
987 
988  switch( ii )
989  {
990  default:
991  case 0: /* PTH */ hasHole = true; hasConnection = true; break;
992  case 1: /* SMD */ hasHole = false; hasConnection = true; break;
993  case 2: /* CONN */ hasHole = false; hasConnection = true; break;
994  case 3: /* NPTH */ hasHole = true; hasConnection = false; break;
995  case 4: /* Aperture */ hasHole = false; hasConnection = false; break;
996  }
997 
998  // Enable/disable hole controls
999  m_holeShapeLabel->Enable( hasHole );
1000  m_holeShapeCtrl->Enable( hasHole );
1001  m_holeX.Enable( hasHole );
1002  m_holeY.Enable( hasHole && m_holeShapeCtrl->GetSelection() == 1 );
1003 
1004  // Enable/disable Pad number, net and pad length-to-die
1005  m_PadNumText->Enable( hasConnection );
1006  m_PadNumCtrl->Enable( hasConnection );
1007  m_PadNameText->Enable( hasConnection );
1008  m_PadNetSelector->Enable( hasConnection && m_canEditNetName && m_currentPad );
1009  m_padToDieOpt->Enable( hasConnection );
1010 
1011  if( !m_padToDieOpt->IsEnabled() )
1012  m_padToDieOpt->SetValue( false );
1013 
1014  // We can show/hide this here because it doesn't require the layout to be refreshed.
1015  // All the others have to be done in their event handlers because doing a layout here
1016  // causes infinite looping on MSW.
1017  m_padToDie.Show( m_padToDieOpt->GetValue() );
1018 
1019  // Enable/disable Copper Layers control
1020  m_rbCopperLayersSel->Enable( ii != 4 );
1021 
1022  LSET cu_set = m_dummyPad->GetLayerSet() & LSET::AllCuMask();
1023 
1024  if( m_PadType->GetSelection() == 0 )
1025  {
1026  if( !cu_set.any() )
1027  m_stackupImagesBook->SetSelection( 3 );
1028  else if( !m_dummyPad->GetRemoveUnconnected() )
1029  m_stackupImagesBook->SetSelection( 0 );
1030  else if( m_dummyPad->GetKeepTopBottom() )
1031  m_stackupImagesBook->SetSelection( 1 );
1032  else
1033  m_stackupImagesBook->SetSelection( 2 );
1034  }
1035  else if( m_PadType->GetSelection() == 3 )
1036  {
1037  if( cu_set.test( F_Cu ) && cu_set.test( B_Cu ) )
1038  m_stackupImagesBook->SetSelection( 4 );
1039  else if( cu_set.test( F_Cu ) )
1040  m_stackupImagesBook->SetSelection( 5 );
1041  else if( cu_set.test( B_Cu ) )
1042  m_stackupImagesBook->SetSelection( 6 );
1043  else
1044  m_stackupImagesBook->SetSelection( 7 );
1045  }
1046  else
1047  {
1048  m_stackupImagesBook->SetSelection( 3 );
1049  }
1050 }
1051 
1052 
1053 void DIALOG_PAD_PROPERTIES::setPadLayersList( LSET layer_mask, bool remove_unconnected,
1054  bool keep_top_bottom )
1055 {
1057 
1058  LSET cu_set = layer_mask & LSET::AllCuMask();
1059 
1060  if( m_PadType->GetSelection() == 0 )
1061  {
1062  if( !cu_set.any() )
1063  m_rbCopperLayersSel->SetSelection( 3 );
1064  else if( !remove_unconnected )
1065  m_rbCopperLayersSel->SetSelection( 0 );
1066  else if( keep_top_bottom )
1067  m_rbCopperLayersSel->SetSelection( 1 );
1068  else
1069  m_rbCopperLayersSel->SetSelection( 2 );
1070  }
1071  else if( m_PadType->GetSelection() == 3 )
1072  {
1073  if( cu_set.test( F_Cu ) && cu_set.test( B_Cu ) )
1074  m_rbCopperLayersSel->SetSelection( 0 );
1075  else if( cu_set.test( F_Cu ) )
1076  m_rbCopperLayersSel->SetSelection( 1 );
1077  else if( cu_set.test( B_Cu ) )
1078  m_rbCopperLayersSel->SetSelection( 2 );
1079  else
1080  m_rbCopperLayersSel->SetSelection( 3 );
1081  }
1082  else
1083  {
1084  if( cu_set == LSET( F_Cu ) )
1085  m_rbCopperLayersSel->SetSelection( 0 );
1086  else
1087  m_rbCopperLayersSel->SetSelection( 1 );
1088  }
1089 
1090  m_PadLayerAdhCmp->SetValue( layer_mask[F_Adhes] );
1091  m_PadLayerAdhCu->SetValue( layer_mask[B_Adhes] );
1092 
1093  m_PadLayerPateCmp->SetValue( layer_mask[F_Paste] );
1094  m_PadLayerPateCu->SetValue( layer_mask[B_Paste] );
1095 
1096  m_PadLayerSilkCmp->SetValue( layer_mask[F_SilkS] );
1097  m_PadLayerSilkCu->SetValue( layer_mask[B_SilkS] );
1098 
1099  m_PadLayerMaskCmp->SetValue( layer_mask[F_Mask] );
1100  m_PadLayerMaskCu->SetValue( layer_mask[B_Mask] );
1101 
1102  m_PadLayerECO1->SetValue( layer_mask[Eco1_User] );
1103  m_PadLayerECO2->SetValue( layer_mask[Eco2_User] );
1104 
1105  m_PadLayerDraft->SetValue( layer_mask[Dwgs_User] );
1106 }
1107 
1108 
1110 {
1111  bool retVal = DIALOG_SHIM::Show( aShow );
1112 
1113  if( aShow )
1114  {
1115  // It *should* work to set the stackup bitmap in the constructor, but it doesn't.
1116  // wxWidgets needs to have these set when the panel is visible for some reason.
1117  // https://gitlab.com/kicad/code/kicad/-/issues/5534
1122  m_stackupImage5->SetBitmap( KiBitmap( pads_npth_top_xpm ) );
1124  m_stackupImage7->SetBitmap( KiBitmap( pads_npth_xpm ) );
1125 
1126  Layout();
1127  }
1128 
1129  return retVal;
1130 }
1131 
1132 
1133 void DIALOG_PAD_PROPERTIES::OnSetCopperLayers( wxCommandEvent& event )
1134 {
1136  redraw();
1137 }
1138 
1139 
1140 // Called when select/deselect a layer.
1141 void DIALOG_PAD_PROPERTIES::OnSetLayers( wxCommandEvent& event )
1142 {
1144  redraw();
1145 }
1146 
1147 
1148 // test if all values are acceptable for the pad
1150 {
1151  bool error = transferDataToPad( m_dummyPad );
1152  bool skip_tstoffset = false; // the offset prm is not always tested
1153 
1154  wxArrayString error_msgs;
1155  wxArrayString warning_msgs;
1156  wxString msg;
1157 
1158  // Test for incorrect values
1159  if( (m_dummyPad->GetSize().x <= 0) ||
1160  ((m_dummyPad->GetSize().y <= 0) && (m_dummyPad->GetShape() != PAD_SHAPE_CIRCLE)) )
1161  {
1162  error_msgs.Add( _( "Pad size must be greater than zero" ) );
1163  }
1164 
1165  // Test hole size against pad size
1167  PCB_LAYER_ID layer = lset.Seq().at( 0 );
1168  int maxError = m_board->GetDesignSettings().m_MaxError;
1169  SHAPE_POLY_SET padOutline, drillOutline;
1170 
1171  m_dummyPad->TransformShapeWithClearanceToPolygon( padOutline, layer, 0, maxError,
1173 
1174  const SHAPE_SEGMENT* drillShape = m_dummyPad->GetEffectiveHoleShape();
1175  const SEG drillSeg = drillShape->GetSeg();
1176 
1177  TransformOvalToPolygon( drillOutline, (wxPoint) drillSeg.A, (wxPoint) drillSeg.B,
1178  drillShape->GetWidth(), maxError, ERROR_LOC::ERROR_INSIDE );
1179 
1180  drillOutline.BooleanSubtract( padOutline, SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
1181 
1182  if( ( drillOutline.BBox().GetWidth() > 0 ) || ( drillOutline.BBox().GetHeight() > 0 ) )
1183  {
1184  warning_msgs.Add( _( "Warning: Pad drill bigger than pad size or shapes do not overlap" ) );
1185  skip_tstoffset = true; // offset prm will be not tested because if the drill value
1186  // is incorrect the offset prm is always seen as incorrect, even if it is 0
1187  }
1188 
1189  if( m_dummyPad->GetLocalClearance() < 0 )
1190  {
1191  error_msgs.Add( _( "Pad local clearance must be zero or greater than zero" ) );
1192  }
1193 
1194  // Some pads need a negative solder mask clearance (mainly for BGA with small pads)
1195  // However the negative solder mask clearance must not create negative mask size
1196  // Therefore test for minimal acceptable negative value
1197  // Hovewer, a negative value can give strange result with custom shapes, so it is not
1198  // allowed for custom pad shape
1200  {
1202  error_msgs.Add( _( "Pad local solder mask clearance must be zero or greater than zero" ) );
1203  else
1204  {
1205  int min_smClearance = -std::min( m_dummyPad->GetSize().x, m_dummyPad->GetSize().y )/2;
1206 
1207  if( m_dummyPad->GetLocalSolderMaskMargin() <= min_smClearance )
1208  {
1209  error_msgs.Add( wxString::Format(
1210  _( "Pad local solder mask clearance must be greater than %s" ),
1211  StringFromValue( GetUserUnits(), min_smClearance ) ) );
1212  }
1213  }
1214  }
1215 
1216  // Some pads need a positive solder paste clearance (mainly for BGA with small pads)
1217  // Hovewer, a positive value can create issues if the resulting shape is too big.
1218  // (like a solder paste creating a solder paste area on a neighbour pad or on the solder mask)
1219  // So we could ask for user to confirm the choice
1220  // Currently there are no test
1221 
1222  LSET padlayers_mask = m_dummyPad->GetLayerSet();
1223 
1224  if( padlayers_mask == 0 )
1225  error_msgs.Add( _( "Error: pad has no layer" ) );
1226 
1227  if( !padlayers_mask[F_Cu] && !padlayers_mask[B_Cu] )
1228  {
1229  if( ( m_dummyPad->GetDrillSize().x || m_dummyPad->GetDrillSize().y )
1231  {
1232  // Note: he message is shown in an HTML window
1233  msg = _( "Warning: plated through holes should normally have a copper pad on at least one layer" );
1234  warning_msgs.Add( msg );
1235  }
1236  }
1237 
1238  //Note: the below test might be unnecessary
1239  if( !skip_tstoffset && m_dummyPad->GetShape() != PAD_SHAPE_CUSTOM )
1240  {
1241  wxPoint max_size;
1242  max_size.x = std::abs( m_dummyPad->GetOffset().x );
1243  max_size.y = std::abs( m_dummyPad->GetOffset().y );
1244  max_size.x += m_dummyPad->GetDrillSize().x / 2;
1245  max_size.y += m_dummyPad->GetDrillSize().y / 2;
1246 
1247  if( ( m_dummyPad->GetSize().x / 2 < max_size.x ) ||
1248  ( m_dummyPad->GetSize().y / 2 < max_size.y ) )
1249  {
1250  error_msgs.Add( _( "Incorrect value for pad offset" ) );
1251  }
1252  }
1253 
1254  if( error )
1255  error_msgs.Add( _( "Too large value for pad delta size" ) );
1256 
1257  switch( m_dummyPad->GetAttribute() )
1258  {
1259  case PAD_ATTRIB_NPTH: // Not plated, but through hole, a hole is expected
1260  case PAD_ATTRIB_PTH: // Pad through hole, a hole is also expected
1261  if( m_dummyPad->GetDrillSize().x <= 0 ||
1263  error_msgs.Add( _( "Error: Through hole pad: drill diameter set to 0" ) );
1264  break;
1265 
1266  case PAD_ATTRIB_CONN: // Connector pads are smd pads, just they do not have solder paste.
1267  if( padlayers_mask[B_Paste] || padlayers_mask[F_Paste] )
1268  error_msgs.Add( _( "Error: Connector pads are not on the solder paste layer\n"
1269  "Use SMD pads instead" ) );
1271 
1272  case PAD_ATTRIB_SMD: // SMD and Connector pads (One external copper layer only)
1273  {
1274  LSET innerlayers_mask = padlayers_mask & LSET::InternalCuMask();
1275 
1276  if( ( padlayers_mask[F_Cu] && padlayers_mask[B_Cu] ) ||
1277  innerlayers_mask.count() != 0 )
1278  warning_msgs.Add( _( "Warning: The pad has been defined in an inner layer only." ) );
1279  }
1280  break;
1281  }
1282 
1283  if( m_dummyPad->GetProperty() != PAD_PROP_NONE &&
1285  error_msgs.Add( _( "Property cannot be set for NPTH" ) );
1286 
1289  error_msgs.Add( _( "Castellated property can be set only for PTH" ) );
1290 
1291  if( m_dummyPad->GetProperty() == PAD_PROP_BGA &&
1293  error_msgs.Add( _( "BGA property can be set only for SMD pads" ) );
1294 
1297  {
1298  wxASSERT( m_tcCornerSizeRatio->GetValue() == m_tcCornerSizeRatio1->GetValue() );
1299  wxString value = m_tcCornerSizeRatio->GetValue();
1300  double rrRadiusRatioPercent;
1301 
1302  if( !value.ToDouble( &rrRadiusRatioPercent ) )
1303  error_msgs.Add( _( "Incorrect corner size value" ) );
1304  else
1305  {
1306  if( rrRadiusRatioPercent < 0.0 )
1307  error_msgs.Add( _( "Incorrect (negative) corner size value" ) );
1308  else if( rrRadiusRatioPercent > 50.0 )
1309  error_msgs.Add( _( "Corner size value must be smaller than 50%" ) );
1310  }
1311  }
1312 
1313  // PADSTACKS TODO: this will need to check each layer in the pad...
1315  {
1316  SHAPE_POLY_SET mergedPolygon;
1318 
1319  if( mergedPolygon.OutlineCount() > 1 )
1320  error_msgs.Add( _( "Incorrect pad shape: the shape must be equivalent to only one polygon" ) );
1321  }
1322 
1323 
1324  if( error_msgs.GetCount() )
1325  {
1326  HTML_MESSAGE_BOX dlg( this, _("Pad setup errors list" ) );
1327  dlg.ListSet( error_msgs );
1328 
1329  if( warning_msgs.GetCount() )
1330  {
1331  dlg.ListSet( warning_msgs );
1332  }
1333 
1334  dlg.ShowModal();
1335  }
1336  else
1337  {
1338  for( size_t i = 0; i < warning_msgs.GetCount(); ++i )
1339  {
1340  m_parent->ShowInfoBarWarning( warning_msgs[i] );
1341  }
1342  }
1343 
1344  return error_msgs.GetCount() == 0;
1345 }
1346 
1347 
1349 {
1350  if( !m_canUpdate )
1351  return;
1352 
1353  KIGFX::VIEW* view = m_padPreviewGAL->GetView();
1355 
1356  // The layer used to place primitive items selected when editing custom pad shapes
1357  // we use here a layer never used in a pad:
1358  #define SELECTED_ITEMS_LAYER Dwgs_User
1359 
1361  KIGFX::PCB_RENDER_SETTINGS* settings =
1362  static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
1364 
1365  view->Update( m_dummyPad );
1366 
1367  // delete previous items if highlight list
1368  while( m_highlight.size() )
1369  {
1370  delete m_highlight.back(); // the dtor also removes item from view
1371  m_highlight.pop_back();
1372  }
1373 
1374  // highlight selected primitives:
1375  long select = m_listCtrlPrimitives->GetFirstSelected();
1376 
1377  while( select >= 0 )
1378  {
1379  PCB_SHAPE* dummyShape = (PCB_SHAPE*) m_primitives[select]->Clone();
1380  dummyShape->SetLayer( SELECTED_ITEMS_LAYER );
1381  dummyShape->Rotate( wxPoint( 0, 0), m_dummyPad->GetOrientation() );
1382  dummyShape->Move( m_dummyPad->GetPosition() );
1383 
1384  view->Add( dummyShape );
1385  m_highlight.push_back( dummyShape );
1386 
1387  select = m_listCtrlPrimitives->GetNextSelected( select );
1388  }
1389 
1390  BOX2I bbox = m_dummyPad->ViewBBox();
1391 
1392  if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
1393  {
1394  // The origin always goes in the middle of the canvas; we want offsetting the pad
1395  // shape to move the pad, not the hole
1396  bbox.Move( -m_dummyPad->GetPosition() );
1397  int maxXExtent = std::max( abs( bbox.GetLeft() ), abs( bbox.GetRight() ) );
1398  int maxYExtent = std::max( abs( bbox.GetTop() ), abs( bbox.GetBottom() ) );
1399 
1400  // Don't blow up the GAL on too-large numbers
1401  if( maxXExtent > INT_MAX / 4 )
1402  maxXExtent = INT_MAX / 4;
1403 
1404  if( maxYExtent > INT_MAX / 4 )
1405  maxYExtent = INT_MAX / 4;
1406 
1407  BOX2D viewBox( m_dummyPad->GetPosition(), {0, 0} );
1408  BOX2D canvasBox( m_dummyPad->GetPosition(), {0, 0} );
1409  viewBox.Inflate( maxXExtent * 1.4, maxYExtent * 1.4 ); // add a margin
1410  canvasBox.Inflate( maxXExtent * 2.0, maxYExtent * 2.0 );
1411 
1412  view->SetBoundary( canvasBox );
1413 
1414  // Autozoom
1415  view->SetViewport( viewBox );
1416 
1419  }
1420 }
1421 
1422 
1424 {
1425  if( !wxDialog::TransferDataToWindow() )
1426  return false;
1427 
1428  if( !m_panelGeneral->TransferDataToWindow() )
1429  return false;
1430 
1431  if( !m_localSettingsPanel->TransferDataToWindow() )
1432  return false;
1433 
1434  return true;
1435 }
1436 
1437 
1439 {
1440  BOARD_COMMIT commit( m_parent );
1441 
1442  if( !wxDialog::TransferDataFromWindow() )
1443  return false;
1444 
1445  if( !m_panelGeneral->TransferDataFromWindow() )
1446  return false;
1447 
1448  if( !m_localSettingsPanel->TransferDataFromWindow() )
1449  return false;
1450 
1451  if( !padValuesOK() )
1452  return false;
1453 
1455  // m_padMaster is a pattern: ensure there is no net for this pad:
1457 
1458  if( !m_currentPad ) // Set current Pad parameters
1459  return true;
1460 
1461  commit.Modify( m_currentPad );
1462 
1463  // redraw the area where the pad was, without pad (delete pad on screen)
1465  m_parent->GetCanvas()->Refresh();
1467 
1468  // Update values
1473 
1474  wxSize size;
1475  MODULE* footprint = m_currentPad->GetParent();
1476 
1478 
1479  size = m_padMaster->GetDelta();
1480  m_currentPad->SetDelta( size );
1481 
1484 
1485  wxPoint offset = m_padMaster->GetOffset();
1486  m_currentPad->SetOffset( offset );
1487 
1489 
1492 
1493 
1496 
1500 
1502 
1503  int padNetcode = NETINFO_LIST::UNCONNECTED;
1504 
1505  // For PAD_ATTRIB_NPTH, ensure there is no net name selected
1507  padNetcode = m_PadNetSelector->GetSelectedNetcode();
1508 
1509  m_currentPad->SetNetCode( padNetcode );
1520 
1521  // rounded rect pads with radius ratio = 0 are in fact rect pads.
1522  // So set the right shape (and perhaps issues with a radius = 0)
1525  {
1527  }
1528 
1529  // Set the fabrication property:
1531 
1532  // define the way the clearance area is defined in zones
1534 
1535  if( m_isFlipped )
1536  {
1537  // flip pad (up/down) around its position
1538  m_currentPad->Flip( m_currentPad->GetPosition(), false );
1539  }
1540 
1541  if( footprint )
1542  {
1543  footprint->SetLastEditTime();
1544 
1545  // compute the pos 0 value, i.e. pad position for footprint with orientation = 0
1546  // i.e. relative to footprint origin (footprint position)
1547  wxPoint pt = m_currentPad->GetPosition() - footprint->GetPosition();
1548  RotatePoint( &pt, -footprint->GetOrientation() );
1549  m_currentPad->SetPos0( pt );
1551  footprint->GetOrientation() );
1552  }
1553 
1554  if( footprint )
1555  footprint->CalculateBoundingBox();
1556 
1558 
1559  // redraw the area where the pad was
1560  m_parent->GetCanvas()->Refresh();
1561 
1562  commit.Push( _( "Modify pad" ) );
1563 
1564  return true;
1565 }
1566 
1567 
1569 {
1570  PAD_PROP_T prop = PAD_PROP_NONE;
1571 
1572  switch( m_choiceFabProperty->GetSelection() )
1573  {
1574  case 0: prop = PAD_PROP_NONE; break;
1575  case 1: prop = PAD_PROP_BGA; break;
1576  case 2: prop = PAD_PROP_FIDUCIAL_LOCAL; break;
1577  case 3: prop = PAD_PROP_FIDUCIAL_GLBL; break;
1578  case 4: prop = PAD_PROP_TESTPOINT; break;
1579  case 5: prop = PAD_PROP_HEATSINK; break;
1580  case 6: prop = PAD_PROP_CASTELLATED; break;
1581  }
1582 
1583  return prop;
1584 }
1585 
1586 
1588 {
1589  wxString msg;
1590 
1591  if( !Validate() )
1592  return true;
1593  if( !m_panelGeneral->Validate() )
1594  return true;
1595  if( !m_localSettingsPanel->Validate() )
1596  return true;
1597  if( !m_spokeWidth.Validate( 0, INT_MAX ) )
1598  return false;
1599 
1600  m_OrientValidator.TransferFromWindow();
1601 
1602  aPad->SetAttribute( code_type[m_PadType->GetSelection()] );
1603  aPad->SetShape( code_shape[m_PadShape->GetSelection()] );
1606 
1607  if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
1609 
1610  // Read pad clearances values:
1615  aPad->SetThermalGap( m_thermalGap.GetValue() );
1616  double dtmp = 0.0;
1617  msg = m_SolderPasteMarginRatioCtrl->GetValue();
1618  msg.ToDouble( &dtmp );
1619 
1620  // A -50% margin ratio means no paste on a pad, the ratio must be >= -50%
1621  if( dtmp < -50.0 )
1622  dtmp = -50.0;
1623  // A margin ratio is always <= 0
1624  // 0 means use full pad copper area
1625  if( dtmp > 0.0 )
1626  dtmp = 0.0;
1627 
1628  aPad->SetLocalSolderPasteMarginRatio( dtmp / 100 );
1629 
1630  switch( m_ZoneConnectionChoice->GetSelection() )
1631  {
1632  default:
1633  case 0: aPad->SetZoneConnection( ZONE_CONNECTION::INHERITED ); break;
1634  case 1: aPad->SetZoneConnection( ZONE_CONNECTION::FULL ); break;
1635  case 2: aPad->SetZoneConnection( ZONE_CONNECTION::THERMAL ); break;
1636  case 3: aPad->SetZoneConnection( ZONE_CONNECTION::NONE ); break;
1637  }
1638 
1639  aPad->SetPosition( wxPoint( m_posX.GetValue(), m_posY.GetValue() ) );
1640 
1641  if( m_holeShapeCtrl->GetSelection() == 0 )
1642  {
1644  aPad->SetDrillSize( wxSize( m_holeX.GetValue(), m_holeX.GetValue() ) );
1645  }
1646  else
1647  {
1649  aPad->SetDrillSize( wxSize( m_holeX.GetValue(), m_holeY.GetValue() ) );
1650  }
1651 
1652  if( aPad->GetShape() == PAD_SHAPE_CIRCLE )
1653  aPad->SetSize( wxSize( m_sizeX.GetValue(), m_sizeX.GetValue() ) );
1654  else
1655  aPad->SetSize( wxSize( m_sizeX.GetValue(), m_sizeY.GetValue() ) );
1656 
1657  // For a trapezoid, test delta value (be sure delta is not too large for pad size)
1658  // remember DeltaSize.x is the Y size variation
1659  bool error = false;
1660  wxSize delta( 0, 0 );
1661 
1662  if( aPad->GetShape() == PAD_SHAPE_TRAPEZOID )
1663  {
1664  // For a trapezoid, only one of delta.x or delta.y is not 0, depending on axis.
1665  if( m_trapAxisCtrl->GetSelection() == 0 )
1666  delta.x = m_trapDelta.GetValue();
1667  else
1668  delta.y = m_trapDelta.GetValue();
1669 
1670  if( delta.x < 0 && delta.x <= -aPad->GetSize().y )
1671  {
1672  delta.x = -aPad->GetSize().y + 2;
1673  error = true;
1674  }
1675 
1676  if( delta.x > 0 && delta.x >= aPad->GetSize().y )
1677  {
1678  delta.x = aPad->GetSize().y - 2;
1679  error = true;
1680  }
1681 
1682  if( delta.y < 0 && delta.y <= -aPad->GetSize().x )
1683  {
1684  delta.y = -aPad->GetSize().x + 2;
1685  error = true;
1686  }
1687 
1688  if( delta.y > 0 && delta.y >= aPad->GetSize().x )
1689  {
1690  delta.y = aPad->GetSize().x - 2;
1691  error = true;
1692  }
1693  }
1694 
1695  aPad->SetDelta( delta );
1696 
1697  if( m_offsetShapeOpt->GetValue() )
1698  aPad->SetOffset( wxPoint( m_offsetX.GetValue(), m_offsetY.GetValue() ) );
1699  else
1700  aPad->SetOffset( wxPoint() );
1701 
1702  // Read pad length die
1703  if( m_padToDieOpt->GetValue() )
1705  else
1706  aPad->SetPadToDieLength( 0 );
1707 
1708  aPad->SetOrientation( m_OrientValue * 10.0 );
1709  aPad->SetName( m_PadNumCtrl->GetValue() );
1711 
1712  int chamfers = 0;
1713 
1714  if( m_PadShape->GetSelection() == CHOICE_SHAPE_CHAMFERED_RECT )
1715  {
1716  if( m_cbTopLeft->GetValue() )
1717  chamfers |= RECT_CHAMFER_TOP_LEFT;
1718 
1719  if( m_cbTopRight->GetValue() )
1720  chamfers |= RECT_CHAMFER_TOP_RIGHT;
1721 
1722  if( m_cbBottomLeft->GetValue() )
1723  chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1724 
1725  if( m_cbBottomRight->GetValue() )
1726  chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1727  }
1728  else if( m_PadShape->GetSelection() == CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT )
1729  {
1730  if( m_cbTopLeft1->GetValue() )
1731  chamfers |= RECT_CHAMFER_TOP_LEFT;
1732 
1733  if( m_cbTopRight1->GetValue() )
1734  chamfers |= RECT_CHAMFER_TOP_RIGHT;
1735 
1736  if( m_cbBottomLeft1->GetValue() )
1737  chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1738 
1739  if( m_cbBottomRight1->GetValue() )
1740  chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1741  }
1742  aPad->SetChamferPositions( chamfers );
1743 
1744  if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
1745  {
1746  // The pad custom has a "anchor pad" (a basic shape: round or rect pad)
1747  // that is the minimal area of this pad, and is usefull to ensure a hole
1748  // diameter is acceptable, and is used in Gerber files as flashed area
1749  // reference
1750  if( aPad->GetAnchorPadShape() == PAD_SHAPE_CIRCLE )
1751  aPad->SetSize( wxSize( m_sizeX.GetValue(), m_sizeX.GetValue() ) );
1752 
1753  // define the way the clearance area is defined in zones
1754  aPad->SetCustomShapeInZoneOpt( m_ZoneCustomPadShape->GetSelection() == 0 ?
1757  }
1758 
1759  switch( aPad->GetAttribute() )
1760  {
1761  case PAD_ATTRIB_PTH:
1762  break;
1763 
1764  case PAD_ATTRIB_CONN:
1765  case PAD_ATTRIB_SMD:
1766  // SMD and PAD_ATTRIB_CONN has no hole.
1767  // basically, SMD and PAD_ATTRIB_CONN are same type of pads
1768  // PAD_ATTRIB_CONN has just a default non technical layers that differs from SMD
1769  // and are intended to be used in virtual edge board connectors
1770  // However we can accept a non null offset,
1771  // mainly to allow complex pads build from a set of basic pad shapes
1772  aPad->SetDrillSize( wxSize( 0, 0 ) );
1773  break;
1774 
1775  case PAD_ATTRIB_NPTH:
1776  // Mechanical purpose only:
1777  // no net name, no pad name allowed
1778  aPad->SetName( wxEmptyString );
1780  break;
1781 
1782  default:
1783  wxFAIL_MSG( "DIALOG_PAD_PROPERTIES::transferDataToPad: unknown pad type" );
1784  break;
1785  }
1786 
1787  if( aPad->GetShape() == PAD_SHAPE_ROUNDRECT )
1788  {
1789  double ratioPercent;
1790 
1791  m_tcCornerSizeRatio->GetValue().ToDouble( &ratioPercent );
1792  aPad->SetRoundRectRadiusRatio( ratioPercent / 100.0 );
1793  }
1794  else if( aPad->GetShape() == PAD_SHAPE_CHAMFERED_RECT
1795  && m_PadShape->GetSelection() == CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT )
1796  {
1797  double ratioPercent;
1798 
1799  m_tcCornerSizeRatio1->GetValue().ToDouble( &ratioPercent );
1800  aPad->SetRoundRectRadiusRatio( ratioPercent / 100.0 );
1801  }
1802 
1803  if( aPad->GetShape() == PAD_SHAPE_CHAMFERED_RECT )
1804  {
1805  double ratioPercent;
1806 
1807  m_tcChamferRatio->GetValue().ToDouble( &ratioPercent );
1808  aPad->SetChamferRectRatio( ratioPercent / 100.0 );
1809  }
1810 
1811  aPad->SetProperty( getSelectedProperty() );
1812 
1813  LSET padLayerMask = LSET();
1814  int copperLayersChoice = m_rbCopperLayersSel->GetSelection();
1815 
1816  aPad->SetRemoveUnconnected( false );
1817  aPad->SetKeepTopBottom( false );
1818 
1819  if( m_PadType->GetSelection() == 0 )
1820  {
1821  switch( copperLayersChoice )
1822  {
1823  case 0:
1824  // All copper layers
1825  padLayerMask |= LSET::AllCuMask();
1826  break;
1827 
1828  case 1:
1829  // Front, back and connected
1830  padLayerMask |= LSET::AllCuMask();
1831  aPad->SetRemoveUnconnected( true );
1832  aPad->SetKeepTopBottom( true );
1833  break;
1834 
1835  case 2:
1836  // Connected only
1837  padLayerMask |= LSET::AllCuMask();
1838  aPad->SetRemoveUnconnected( true );
1839  break;
1840 
1841  case 3:
1842  // No copper layers
1843  break;
1844  }
1845  }
1846  else if( m_PadType->GetSelection() == 3 )
1847  {
1848  switch( copperLayersChoice )
1849  {
1850  case 0: padLayerMask.set( F_Cu ).set( B_Cu ); break;
1851  case 1: padLayerMask.set( F_Cu ); break;
1852  case 2: padLayerMask.set( B_Cu ); break;
1853  default: break;
1854  }
1855  }
1856  else
1857  {
1858  switch( copperLayersChoice )
1859  {
1860  case 0: padLayerMask.set( F_Cu ); break;
1861  case 1: padLayerMask.set( B_Cu ); break;
1862  }
1863  }
1864 
1865  if( m_PadLayerAdhCmp->GetValue() )
1866  padLayerMask.set( F_Adhes );
1867 
1868  if( m_PadLayerAdhCu->GetValue() )
1869  padLayerMask.set( B_Adhes );
1870 
1871  if( m_PadLayerPateCmp->GetValue() )
1872  padLayerMask.set( F_Paste );
1873 
1874  if( m_PadLayerPateCu->GetValue() )
1875  padLayerMask.set( B_Paste );
1876 
1877  if( m_PadLayerSilkCmp->GetValue() )
1878  padLayerMask.set( F_SilkS );
1879 
1880  if( m_PadLayerSilkCu->GetValue() )
1881  padLayerMask.set( B_SilkS );
1882 
1883  if( m_PadLayerMaskCmp->GetValue() )
1884  padLayerMask.set( F_Mask );
1885 
1886  if( m_PadLayerMaskCu->GetValue() )
1887  padLayerMask.set( B_Mask );
1888 
1889  if( m_PadLayerECO1->GetValue() )
1890  padLayerMask.set( Eco1_User );
1891 
1892  if( m_PadLayerECO2->GetValue() )
1893  padLayerMask.set( Eco2_User );
1894 
1895  if( m_PadLayerDraft->GetValue() )
1896  padLayerMask.set( Dwgs_User );
1897 
1898  aPad->SetLayerSet( padLayerMask );
1899 
1900  return error;
1901 }
1902 
1903 
1904 void DIALOG_PAD_PROPERTIES::OnOffsetCheckbox( wxCommandEvent& event )
1905 {
1906  if( m_offsetShapeOpt->GetValue() )
1907  {
1910  }
1911 
1912  // Show/hide controls depending on m_offsetShapeOpt being enabled
1913  m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
1914  m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
1915 
1916  for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
1917  m_notebook->GetPage( i )->Layout();
1918 
1919  OnValuesChanged( event );
1920 }
1921 
1922 
1923 void DIALOG_PAD_PROPERTIES::OnPadToDieCheckbox( wxCommandEvent& event )
1924 {
1925  if( m_padToDieOpt->GetValue() && m_currentPad )
1927 
1928  OnValuesChanged( event );
1929 }
1930 
1931 
1932 void DIALOG_PAD_PROPERTIES::OnValuesChanged( wxCommandEvent& event )
1933 {
1934  if( m_canUpdate )
1935  {
1937  // If the pad size has changed, update the displayed values
1938  // for rounded rect pads
1940 
1941  redraw();
1942  }
1943 }
1944 
1946 {
1947  long select = m_listCtrlPrimitives->GetFirstSelected();
1948 
1949  if( select < 0 )
1950  {
1951  wxMessageBox( _( "No shape selected" ) );
1952  return;
1953  }
1954 
1955  std::shared_ptr<PCB_SHAPE>& shape = m_primitives[select];
1956 
1957  if( shape->GetShape() == S_POLYGON )
1958  {
1959  DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, m_parent, shape.get() );
1960 
1961  if( dlg.ShowModal() != wxID_OK )
1962  return;
1963 
1964  dlg.TransferDataFromWindow();
1965  }
1966 
1967  else
1968  {
1969  DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, m_parent, shape.get() );
1970 
1971  if( dlg.ShowModal() != wxID_OK )
1972  return;
1973 
1974  dlg.TransferDataFromWindow();
1975  }
1976 
1978 
1979  if( m_canUpdate )
1980  {
1982  redraw();
1983  }
1984 }
1985 
1986 
1988 {
1989  // Called on a double click on the basic shapes list
1990  // To Do: highligth the primitive(s) currently selected.
1991  redraw();
1992 }
1993 
1994 
1996 void DIALOG_PAD_PROPERTIES::onPrimitiveDClick( wxMouseEvent& event )
1997 {
1998  editPrimitive();
1999 }
2000 
2001 
2002 // Called on a click on basic shapes list panel button
2003 void DIALOG_PAD_PROPERTIES::onEditPrimitive( wxCommandEvent& event )
2004 {
2005  editPrimitive();
2006 }
2007 
2008 // Called on a click on basic shapes list panel button
2009 void DIALOG_PAD_PROPERTIES::onDeletePrimitive( wxCommandEvent& event )
2010 {
2011  long select = m_listCtrlPrimitives->GetFirstSelected();
2012 
2013  if( select < 0 )
2014  return;
2015 
2016  // Multiple selections are allowed. get them and remove corresponding shapes
2017  std::vector<long> indexes;
2018  indexes.push_back( select );
2019 
2020  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2021  indexes.push_back( select );
2022 
2023  // Erase all select shapes
2024  for( unsigned ii = indexes.size(); ii > 0; --ii )
2025  m_primitives.erase( m_primitives.begin() + indexes[ii-1] );
2026 
2028 
2029  if( m_canUpdate )
2030  {
2032  redraw();
2033  }
2034 }
2035 
2036 
2037 void DIALOG_PAD_PROPERTIES::onAddPrimitive( wxCommandEvent& event )
2038 {
2039  // Ask user for shape type
2040  wxString shapelist[] = { _( "Segment" ), _( "Arc" ), _( "Bezier" ),
2041  _( "Ring/Circle" ), _( "Polygon" ) };
2042 
2043  int type = wxGetSingleChoiceIndex( _( "Shape type:" ), _( "Add Primitive" ),
2044  arrayDim( shapelist ), shapelist, 0, this );
2045 
2046  // User pressed cancel
2047  if( type == -1 )
2048  return;
2049 
2051 
2052  PCB_SHAPE* primitive = new PCB_SHAPE();
2053  primitive->SetShape( listtype[type] );
2055 
2056  if( listtype[type] == S_POLYGON )
2057  {
2058  DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, m_parent, primitive );
2059 
2060  if( dlg.ShowModal() != wxID_OK )
2061  return;
2062  }
2063  else
2064  {
2065  DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, m_parent, primitive );
2066 
2067  if( dlg.ShowModal() != wxID_OK )
2068  return;
2069  }
2070 
2071  m_primitives.emplace_back( primitive );
2072 
2074 
2075  if( m_canUpdate )
2076  {
2078  redraw();
2079  }
2080 }
2081 
2082 
2083 void DIALOG_PAD_PROPERTIES::onGeometryTransform( wxCommandEvent& event )
2084 {
2085  long select = m_listCtrlPrimitives->GetFirstSelected();
2086 
2087  if( select < 0 )
2088  {
2089  wxMessageBox( _( "No shape selected" ) );
2090  return;
2091  }
2092 
2093  // Multiple selections are allowed. Build selected shapes list
2094  std::vector<std::shared_ptr<PCB_SHAPE>> shapeList;
2095  shapeList.emplace_back( m_primitives[select] );
2096 
2097  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2098  shapeList.emplace_back( m_primitives[select] );
2099 
2100  DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, m_parent, shapeList, false );
2101 
2102  if( dlg.ShowModal() != wxID_OK )
2103  return;
2104 
2105  dlg.Transform();
2106 
2108 
2109  if( m_canUpdate )
2110  {
2112  redraw();
2113  }
2114 }
2115 
2116 
2117 void DIALOG_PAD_PROPERTIES::onDuplicatePrimitive( wxCommandEvent& event )
2118 {
2119  long select = m_listCtrlPrimitives->GetFirstSelected();
2120 
2121  if( select < 0 )
2122  {
2123  wxMessageBox( _( "No shape selected" ) );
2124  return;
2125  }
2126 
2127  // Multiple selections are allowed. Build selected shapes list
2128  std::vector<std::shared_ptr<PCB_SHAPE>> shapeList;
2129  shapeList.emplace_back( m_primitives[select] );
2130 
2131  while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2132  shapeList.emplace_back( m_primitives[select] );
2133 
2134  DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, m_parent, shapeList, true );
2135 
2136  if( dlg.ShowModal() != wxID_OK )
2137  return;
2138 
2139  // Transfer new settings
2140  // save duplicates to a separate vector to avoid m_primitives reallocation,
2141  // as shapeList contains pointers to its elements
2142  std::vector<std::shared_ptr<PCB_SHAPE>> duplicates;
2143  dlg.Transform( &duplicates, dlg.GetDuplicateCount() );
2144  std::move( duplicates.begin(), duplicates.end(), std::back_inserter( m_primitives ) );
2145 
2147 
2148  if( m_canUpdate )
2149  {
2151  redraw();
2152  }
2153 }
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:749
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
void MergePrimitivesAsPolygon(SHAPE_POLY_SET *aMergedPolygon, PCB_LAYER_ID aLayer) const
Merge all basic shapes to a SHAPE_POLY_SET Note: The results are relative to the pad position,...
usual segment : line with rounded ends
wxString MessageTextFromValue(EDA_UNITS aUnits, int aValue, bool aAddUnitLabel, EDA_DATA_TYPE aType)
Definition: base_units.cpp:123
int GetLocalSolderMaskMargin() const
Definition: class_pad.h:364
double GetOrientation() const
Definition: class_module.h:206
COMMIT & Modify(EDA_ITEM *aItem)
Modifies a given item in the model.
Definition: commit.h:103
const BITMAP_OPAQUE pads_npth_top_xpm[1]
DIALOG_PAD_PROPERTIES(PCB_BASE_FRAME *aParent, D_PAD *aPad)
const BITMAP_OPAQUE pads_npth_xpm[1]
Definition: pads_npth.cpp:111
int GetNetCode() const
Function GetNetCode.
void SetViewport(const BOX2D &aViewport)
Function SetViewport() Sets the visible area of the VIEW.
Definition: view.cpp:531
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Returns the BOARD_DESIGN_SETTINGS for the open project Overloaded in FOOTPRINT_EDIT_FRAME.
void enablePrimitivePage(bool aEnable)
enable (or disable) the primitive page editor
int OutlineCount() const
Returns the number of outlines in the set
KIGFX::VIEW_CONTROLS * GetViewControls() const
Function GetViewControls() Returns a pointer to the VIEW_CONTROLS instance used in the panel.
void TransformShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, PCB_LAYER_ID aLayer, int aClearanceValue, int aMaxError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Function TransformShapeWithClearanceToPolygon Convert the pad shape to a closed polygon.
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
no special fabrication property
Definition: pad_shapes.h:97
KIGFX::GAL_DISPLAY_OPTIONS & GetGalDisplayOptions()
Return a reference to the gal rendering options used by GAL for rendering.
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:161
virtual void SetTopLayer(int aLayer, bool aEnabled=true)
Function SetTopLayer() Sets given layer to be displayed on the top or sets back the default order of ...
Definition: view.cpp:838
PAD_ATTR_T
Enum PAD_ATTR_T is the set of pad shapes, used with D_PAD::{Set,Get}Attribute() The double name is fo...
Definition: pad_shapes.h:78
bool IsFlipped() const
function IsFlipped
Definition: class_module.h:284
PAD_PROP_T getSelectedProperty()
Return the pad property currently selected.
multilayer pads, usually with holes
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
Implementation of conversion functions that require both schematic and board internal units.
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
Definition: class_pad.cpp:159
This file is part of the common library.
coord_type GetTop() const
Definition: box2.h:204
PAD_SHAPE_T GetAnchorPadShape() const
Function GetAnchorPadShape.
Definition: class_pad.h:178
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: class_pad.cpp:145
wxPoint GetPosition() const override
Definition: class_pad.h:172
FP_TEXT & Value()
read/write accessors:
Definition: class_module.h:475
const SHAPE_SEGMENT * GetEffectiveHoleShape() const
Function GetEffectiveHoleShape Returns a SHAPE object representing the pad's hole.
Definition: class_pad.cpp:270
static constexpr double IU_PER_MM
Mock up a conversion function.
VIEW_CONTROLS class definition.
static wxString formatCoord(EDA_UNITS aUnits, wxPoint aCoord)
void ApplySettings(const VC_SETTINGS &aSettings)
Applies VIEW_CONTROLS settings from an object
void CalculateBoundingBox()
Function CalculateBoundingBox calculates the bounding box in board coordinates.
void SetBoard(BOARD *aBoard)
void SetRemoveUnconnected(bool aSet)
Sets the unconnected removal property.
Definition: class_pad.h:537
bool transferDataToPad(D_PAD *aPad)
Copy values from dialog field to aPad's members.
std::vector< std::shared_ptr< PCB_SHAPE > > m_primitives
a fiducial (usually a smd) for the full board
Definition: pad_shapes.h:99
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
void OnPadToDieCheckbox(wxCommandEvent &event) override
void SetChamferPositions(int aPositions)
has meaning only for chamfered rect pads set the position of the chamfers for orientation 0.
Definition: class_pad.h:522
bool IsFlipped() const
Definition: class_pad.cpp:173
int GetPadToDieLength() const
Definition: class_pad.h:362
void FinishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:81
void setPadLayersList(LSET layer_mask, bool remove_unconnected, bool keep_top_bottom)
Function setPadLayersList updates the CheckBox states in pad layers list,.
wxFloatingPointValidator< double > m_OrientValidator
static constexpr GAL_TYPE GAL_FALLBACK
PAD_TOOL.
Definition: pad_tool.h:37
bool SetNetCode(int aNetCode, bool aNoAssert)
Sets net using a net code.
void ShowPadPropertiesDialog(D_PAD *aPad)
coord_type GetRight() const
Definition: box2.h:199
const BITMAP_OPAQUE pads_reset_unused_xpm[1]
Bezier Curve.
Smd pad, used in BGA footprints.
Definition: pad_shapes.h:98
GAL * GetGAL() const
Function GetGAL() Returns the GAL this view is using to draw graphical primitives.
Definition: view.h:182
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:166
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: class_board.h:558
int GetSelectedNetcode()
const NETINFO_LIST & GetNetInfo() const
Definition: class_board.h:724
static LSET PTHMask()
layer set for a through hole pad
Definition: class_pad.cpp:138
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 SetDrillSize(const wxSize &aSize)
Definition: class_pad.h:240
void NORMALIZE_ANGLE_180(T &Angle)
Definition: trigo.h:374
coord_type GetBottom() const
Definition: box2.h:200
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:85
a pad used as heat sink, usually in SMD footprints
Definition: pad_shapes.h:102
void SetRoundRectRadiusRatio(double aRadiusScale)
has meaning only for rounded rect pads Set the ratio between the smaller X or Y size and the rounded ...
Definition: class_pad.cpp:236
void SetKeepTopBottom(bool aSet)
Sets whether we keep the top and bottom connections even if they are not connected.
Definition: class_pad.h:543
virtual void Rotate(const wxPoint &aRotCentre, double aAngle) override
Function Rotate Rotate this object.
Definition: pcb_shape.cpp:193
Arcs (with rounded ends)
int GetThermalGap() const
Definition: class_pad.h:484
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:410
void onCornerSizePercentChange(wxCommandEvent &event) override
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:115
void SetSketchModeGraphicItems(bool aEnabled)
Turns on/off sketch mode for graphic items (DRAWSEGMENTs, texts).
Definition: pcb_painter.h:127
PAD_SHAPE_T
Enum PAD_SHAPE_T is the set of pad shapes, used with D_PAD::{Set,Get}Shape()
Definition: pad_shapes.h:33
PAINTER * GetPainter() const
Function GetPainter() Returns the painter object used by the view for drawing VIEW_ITEMS.
Definition: view.h:201
PAD_ATTR_T GetAttribute() const
Definition: class_pad.h:352
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:185
const SEG & GetSeg() const
const VC_SETTINGS & GetSettings() const
Returns the current VIEW_CONTROLS settings
This file contains miscellaneous commonly used macros and functions.
bool TransferDataFromWindow() override
Function TransferDataFromWindow Transfer data out of the GUI.
int GetChamferPositions() const
Definition: class_pad.h:523
a pad with a castellated through hole
Definition: pad_shapes.h:103
static PAD_SHAPE_T code_shape[]
Classes used in Pcbnew, CvPcb and GerbView.
EDA_UNITS GetUserUnits() const
Definition: dialog_shim.h:132
DIALOG_PAD_PROPERTIES, derived from DIALOG_PAD_PROPERTIES_BASE, created by wxFormBuilder.
FP_TEXT & Reference()
Definition: class_module.h:476
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
Function GetLineThickness Returns the default graphic segment thickness from the layer class for the ...
KIGFX::ORIGIN_VIEWITEM * m_axisOrigin
PCB_RENDER_SETTINGS Stores PCB specific render settings.
Definition: pcb_painter.h:64
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Construct a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:82
void SetThermalSpokeWidth(int aWidth)
Set the width of the thermal spokes connecting the pad to a zone.
Definition: class_pad.h:475
virtual void Move(const wxPoint &aMoveVector) override
Function Move move this object.
Definition: pcb_shape.cpp:112
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 ShowInfoBarWarning(const wxString &aWarningMsg)
void onAddPrimitive(wxCommandEvent &event) override
static PAD_ATTR_T code_type[]
void SetAnchorPadShape(PAD_SHAPE_T aShape)
Function SetAnchorPadShape Set the shape of the anchor pad for custm shped pads.
Definition: class_pad.h:205
void OnCancel(wxCommandEvent &event) override
std::string FormatAngle(double aAngle)
Function FormatAngle converts aAngle from board units to a string appropriate for writing to file.
Definition: base_units.cpp:557
PCB_LAYER_ID
A quick note on layer IDs:
#define BRIGHTENED
item is drawn with a bright contour
Definition: eda_item.h:128
void Show(bool aShow, bool aResize=false)
Function Show Shows/hides the label, widget and units label.
virtual const BOX2I ViewBBox() const override
Function ViewBBox() returns the bounding box of the item covering all its layers.
Definition: class_pad.cpp:1227
LSET is a set of PCB_LAYER_IDs.
pads are covered by copper
void SetFlags(STATUS_FLAGS aMask)
Definition: eda_item.h:221
void SetLastPadName(const wxString &aPadName)
Definition: pad_tool.h:67
#define NULL
VECTOR2< double > VECTOR2D
Definition: vector2d.h:593
void SetShape(PCB_SHAPE_TYPE_T aShape)
Definition: pcb_shape.h:113
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 SetName(const wxString &aName)
Set the pad name (sometimes called pad number, although it can be an array reference like AA12).
Definition: class_pad.h:131
void OnSetCopperLayers(wxCommandEvent &event) override
const BITMAP_OPAQUE dialog_warning_xpm[1]
SHAPE_POLY_SET.
void SetPos0(const wxPoint &aPos)
Definition: class_pad.h:224
int ShowQuasiModal()
void ListSet(const wxString &aList)
Add a list of items.
coord_type GetWidth() const
Definition: box2.h:197
bool GetRemoveUnconnected() const
Definition: class_pad.h:538
const wxPoint & GetOffset() const
Definition: class_pad.h:248
ZONE_CONNECTION GetZoneConnection() const
Definition: class_pad.h:461
#define SELECTED
Definition: eda_item.h:113
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: class_pad.h:343
double GetChamferRectRatio() const
Definition: class_pad.h:515
void SetLastEditTime(timestamp_t aTime)
Definition: class_module.h:339
LSET GetLayerSet() const override
Function GetLayerSet returns a std::bitset of all layers on which the item physically resides.
Definition: class_pad.h:349
void SetSelectedNetcode(int aNetcode)
void onCornerRadiusChange(wxCommandEvent &event) override
Class DIALOG_PAD_PROPERTIES_BASE.
void SetDrawAtZero(bool aDrawFlag)
Function SetDrawAtZero() Set the draw at zero flag.
void SetStealsFocus(bool aStealsFocus)
Set whether focus is taken on certain events (mouseover, keys, etc).
MODULE * GetParent() const
Definition: class_pad.cpp:1244
void ReplacePrimitives(const std::vector< std::shared_ptr< PCB_SHAPE >> &aPrimitivesList)
Clear the current custom shape primitives list and import a new list.
void OnResize(wxSizeEvent &event)
void OnPadShapeSelection(wxCommandEvent &event) override
void PadTypeSelected(wxCommandEvent &event) override
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:709
void onPrimitiveDClick(wxMouseEvent &event) override
Called on a double click on the basic shapes list.
int GetLocalClearance(wxString *aSource) const override
Function GetLocalClearance returns any local clearances set in the "classic" (ie: pre-rule) system.
Definition: class_pad.cpp:638
void SetHighContrast(bool aEnabled)
Function SetHighContrast Turns on/off high contrast display mode.
const wxString & GetName() const
Definition: class_pad.h:132
void SetSize(const wxSize &aSize)
Definition: class_pad.h:230
const BITMAP_OPAQUE pads_npth_bottom_xpm[1]
VIEW_CONTROLS is an interface for classes handling user events controlling the view behaviour (such a...
void SetLayerColor(int aLayer, const COLOR4D &aColor)
Function SetLayerColor Changes the color used to draw a layer.
#define DO_NOT_DRAW
Used to disable draw function.
Definition: eda_item.h:118
void SetRoundRectCornerRadius(double aRadius)
Function SetRoundRectCornerRadius has meaning only for rounded rect pads.
Definition: class_pad.cpp:227
void OnDrillShapeSelected(wxCommandEvent &event) override
PAD_PROP_T
Enum PAD_PROP_T is the set of pad properties used in Gerber files (Draw files, and P&P files) to defi...
Definition: pad_shapes.h:95
void SetZoneConnection(ZONE_CONNECTION aType)
Definition: class_pad.h:460
PAD_PROP_T GetProperty() const
Definition: class_pad.h:355
void SetNetInfo(NETINFO_LIST *aNetInfoList)
void SetPadToDieLength(int aLength)
Definition: class_pad.h:361
HTML_MESSAGE_BOX.
const wxSize & GetDelta() const
Definition: class_pad.h:238
void onGeometryTransform(wxCommandEvent &event) override
ZONE_CONNECTION GetEffectiveZoneConnection(wxString *aSource=nullptr) const
Return the zone connection in effect (either locally overridden or overridden in the parent module).
Definition: class_pad.cpp:746
Like smd, does not appear on the solder paste layer (default) note also has a special attribute in Ge...
Definition: pad_shapes.h:82
virtual KIGFX::PCB_VIEW * GetView() const override
Function GetView() Returns a pointer to the VIEW instance used in the panel.
void SetGridSize(const VECTOR2D &aGridSize)
Set the grid size.
void StartDrawing()
Function StartDrawing() Begins drawing if it was stopped previously.
void SetAttribute(PAD_ATTR_T aAttribute)
Definition: class_pad.cpp:512
bool Show(bool show) override
const BITMAP_OPAQUE pads_remove_unused_keep_bottom_xpm[1]
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()
Updates the color settings in the painter and GAL.
void SetLocalClearance(int aClearance)
Definition: class_pad.h:369
a dialog to edit basic polygonal shape parameters
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Definition: macros.h:121
void SetLocalSolderPasteMarginRatio(double aRatio)
Definition: class_pad.h:375
CUST_PAD_SHAPE_IN_ZONE GetCustomShapeInZoneOpt() const
Definition: class_pad.h:184
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
Definition: pns_item.h:277
bool Show(bool aShow) override
Definition: seg.h:39
EDA_UNITS
Definition: eda_units.h:38
PCB_SHAPE_TYPE_T
Enum PCB_SHAPE_TYPE_T is the set of shapes for PCB graphics and tracks and footprint graphics in the ...
void OnPrimitiveSelection(wxListEvent &event) override
Called on selection/deselection of a basic shape.
void SetDrillShape(PAD_DRILL_SHAPE_T aShape)
Definition: class_pad.h:342
EDA_UNITS m_units
Definition: dialog_shim.h:198
const BITMAP_OPAQUE pads_remove_unused_xpm[1]
const std::vector< std::shared_ptr< PCB_SHAPE > > & GetPrimitives() const
Accessor to the basic shape list for custom-shaped pads.
Definition: class_pad.h:290
Use thermal relief for pads.
void onEditPrimitive(wxCommandEvent &event) override
bool GetKeepTopBottom() const
Definition: class_pad.h:544
virtual RENDER_SETTINGS * GetSettings()=0
Function GetAdapter Returns pointer to current settings that are going to be used when drawing items.
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
void PadOrientEvent(wxCommandEvent &event) override
virtual bool Validate(double aMin, double aMax, EDA_UNITS aUnits=EDA_UNITS::UNSCALED)
Function Validate Validates the control against the given range, informing the user of any errors fou...
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:48
smd pads, front layer
a fiducial (usually a smd) local to the parent footprint
Definition: pad_shapes.h:100
bool IsType(FRAME_T aType) const
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:201
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
static const LSET std_pad_layers[]
void onDeletePrimitive(wxCommandEvent &event) override
Event handlers of basic shapes list panel.
void onDuplicatePrimitive(wxCommandEvent &event) override
polygon (not yet used for tracks, but could be in microwave apps)
void SetLocalSolderMaskMargin(int aMargin)
Definition: class_pad.h:365
#define _(s)
Definition: 3d_actions.cpp:33
void SetSketchMode(int aItemLayer, bool aEnabled)
Function SetSketchMode Turns on/off sketch mode for given item layer.
Definition: pcb_painter.h:107
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in a variety of units (the basic call r...
Definition: class_pad.h:338
virtual void SetValue(int aValue)
Function SetValue Sets new value (in Internal Units) for the text field, taking care of units convers...
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
const wxSize & GetDrillSize() const
Definition: class_pad.h:241
VECTOR2I A
Definition: seg.h:47
void Flip(const wxPoint &aCentre, bool aFlipLeftRight) override
Function Flip Flip this object, i.e.
Definition: class_pad.cpp:540
Plated through hole pad.
Definition: pad_shapes.h:80
void SetWidth(int aWidth)
Definition: pcb_shape.h:99
PCB_DRAW_PANEL_GAL * m_padPreviewGAL
bool IsAperturePad() const
Definition: class_pad.h:359
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
Executes the changes.
Pads are not covered.
void SetShape(PAD_SHAPE_T aShape)
Set the new shape of this pad.
Definition: class_pad.h:155
void SetGridVisibility(bool aVisibility)
Sets the visibility setting of the grid.
#define SELECTED_ITEMS_LAYER
virtual long long int GetValue()
Function GetValue Returns the current value in Internal Units.
int GetRoundRectCornerRadius() const
Definition: class_pad.cpp:221
void SetOrientation(double aAngle)
Function SetOrientation sets the rotation angle of the pad.
Definition: class_pad.cpp:531
double GetRoundRectRadiusRatio() const
Definition: class_pad.h:507
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:222
wxString StringFromValue(EDA_UNITS aUnits, double aValue, bool aAddUnitSymbol, EDA_DATA_TYPE aType)
Function StringFromValue returns the string from aValue according to units (inch, mm ....
Definition: base_units.cpp:220
bool padValuesOK()
test if all values are acceptable for the pad
void SetChamferRectRatio(double aChamferScale)
has meaning only for chamfered rect pads Set the ratio between the smaller X or Y size and chamfered ...
Definition: class_pad.cpp:244
void SetLocalSolderPasteMargin(int aMargin)
Definition: class_pad.h:372
static LSET ConnSMDMask()
layer set for a SMD pad on Front layer used for edge board connectors
Definition: class_pad.cpp:152
void SetCustomShapeInZoneOpt(CUST_PAD_SHAPE_IN_ZONE aOption)
Set the option for the custom pad shape to use as clearance area in copper zones.
Definition: class_pad.h:194
void SetCoordType(ORIGIN_TRANSFORMS::COORD_TYPES_T aCoordType)
Function SetOriginTransform Sets the current origin transform mode.
Definition: unit_binder.h:168
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Function Add() Adds a VIEW_ITEM to the view.
Definition: view.cpp:327
wxPoint GetPosition() const override
Definition: class_module.h:201
const Vec & GetSize() const
Definition: box2.h:189
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset difference For aFastMode meaning, see function booleanOp
PAD_SHAPE_T GetShape() const
Definition: class_pad.h:164
coord_type GetLeft() const
Definition: box2.h:203
static LSET ApertureMask()
layer set for an aperture pad
Definition: class_pad.cpp:166
BOARD * GetBoard() const
VIEW.
Definition: view.h:63
void SetBoundary(const BOX2D &aBoundary)
Function SetBoundary() Sets limits for view area.
Definition: view.h:269
const BITMAP_OPAQUE pads_npth_top_bottom_xpm[1]
const wxSize & GetSize() const
Definition: class_pad.h:231
void SetProperty(PAD_PROP_T aProperty)
Definition: class_pad.cpp:523
int GetLocalSolderPasteMargin() const
Definition: class_pad.h:371
std::vector< PCB_SHAPE * > m_highlight
void SetOffset(const wxPoint &aOffset)
Definition: class_pad.h:247
int GetThermalSpokeWidth() const
Definition: class_pad.h:476
virtual wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition: fp_text.cpp:422
a test point pad
Definition: pad_shapes.h:101
int GetWidth() const
static constexpr int Millimeter2iu(double mm)
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
Function BBox()
void SetThermalGap(int aGap)
Definition: class_pad.h:483
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition: netinfo.h:478
void SetLayerSet(LSET aLayers) override
Definition: class_pad.h:348
PCB_BASE_FRAME basic PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
void DeletePrimitivesList()
clear the basic shapes list
void StopDrawing()
Function StopDrawing() Prevents the GAL canvas from further drawing till it is recreated or StartDraw...
void Enable(bool aEnable)
Function Enable Enables/diasables the label, widget and units label.
a dialog to edit basics shapes parameters.
double GetLocalSolderPasteMarginRatio() const
Definition: class_pad.h:374
bool TransferDataFromWindow() override
Function TransferDataFromWindow Transfer data out of the GUI.
void SetDelta(const wxSize &aSize)
Definition: class_pad.h:237
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, informs the associated VIEW that the graphical representation of this item has cha...
Definition: view.cpp:1513
void OnUpdateUI(wxUpdateUIEvent &event) override
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:100
virtual void ChangeValue(int aValue)
Function ChangeValue Changes the value (in Internal Units) for the text field, taking care of units c...
VECTOR2I B
Definition: seg.h:48