KiCad PCB EDA Suite
dialog_pad_properties.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2013 Dick Hollenbeck, [email protected]
6 * Copyright (C) 2008-2013 Wayne Stambaugh <[email protected]>
7 * Copyright (C) 1992-2022 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>
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
40#include <macros.h>
41#include <pad.h>
42#include <pcb_base_frame.h>
44#include <pcb_painter.h>
45#include <pcbnew_settings.h>
47#include <view/view_controls.h>
49#include <tool/tool_manager.h>
50#include <tools/pad_tool.h>
51#include <advanced_config.h> // for pad property feature management
52#include <wx/choicdlg.h>
53
54
55// list of pad shapes, ordered like the pad shape wxChoice in dialog.
57{
64 PAD_SHAPE::CHAMFERED_RECT, // choice = CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT
65 PAD_SHAPE::CUSTOM, // choice = CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
66 PAD_SHAPE::CUSTOM // choice = PAD_SHAPE::CUSTOM_RECT_ANCHOR
67};
68
69
70// the ordered index of the pad shape wxChoice in dialog.
71// keep it consistent with code_shape[] and dialog strings
73{
83};
84
85
87{
92 PAD_ATTRIB::SMD // Aperture pad :type SMD with no copper layers,
93 // only on tech layers (usually only on paste layer
94};
95
96
97// These define have the same value as the m_PadType wxChoice GetSelected() return value
98#define PTH_DLG_TYPE 0
99#define SMD_DLG_TYPE 1
100#define CONN_DLG_TYPE 2
101#define NPTH_DLG_TYPE 3
102#define APERTURE_DLG_TYPE 4
103
104
106{
107 DIALOG_PAD_PROPERTIES dlg( this, aPad );
108
109 dlg.ShowQuasiModal();
110}
111
112
115 m_parent( aParent ),
116 m_canUpdate( false ),
117 m_posX( aParent, m_posXLabel, m_posXCtrl, m_posXUnits ),
118 m_posY( aParent, m_posYLabel, m_posYCtrl, m_posYUnits ),
119 m_sizeX( aParent, m_sizeXLabel, m_sizeXCtrl, m_sizeXUnits ),
120 m_sizeY( aParent, m_sizeYLabel, m_sizeYCtrl, m_sizeYUnits ),
121 m_offsetX( aParent, m_offsetXLabel, m_offsetXCtrl, m_offsetXUnits ),
122 m_offsetY( aParent, m_offsetYLabel, m_offsetYCtrl, m_offsetYUnits ),
123 m_padToDie( aParent, m_padToDieLabel, m_padToDieCtrl, m_padToDieUnits ),
124 m_trapDelta( aParent, m_trapDeltaLabel, m_trapDeltaCtrl, m_trapDeltaUnits ),
125 m_cornerRadius( aParent, m_cornerRadiusLabel, m_cornerRadiusCtrl, m_cornerRadiusUnits ),
126 m_cornerRatio( aParent, m_cornerRatioLabel, m_cornerRatioCtrl, m_cornerRatioUnits ),
127 m_chamferRatio( aParent, m_chamferRatioLabel, m_chamferRatioCtrl, m_chamferRatioUnits ),
128 m_mixedCornerRatio( aParent, m_mixedCornerRatioLabel, m_mixedCornerRatioCtrl,
129 m_mixedCornerRatioUnits ),
130 m_mixedChamferRatio( aParent, m_mixedChamferRatioLabel, m_mixedChamferRatioCtrl,
131 m_mixedChamferRatioUnits ),
132 m_holeX( aParent, m_holeXLabel, m_holeXCtrl, m_holeXUnits ),
133 m_holeY( aParent, m_holeYLabel, m_holeYCtrl, m_holeYUnits ),
134 m_clearance( aParent, m_clearanceLabel, m_clearanceCtrl, m_clearanceUnits ),
135 m_maskMargin( aParent, m_maskMarginLabel, m_maskMarginCtrl, m_maskMarginUnits ),
136 m_pasteMargin( aParent, m_pasteMarginLabel, m_pasteMarginCtrl, m_pasteMarginUnits ),
137 m_pasteMarginRatio( aParent, m_pasteMarginRatioLabel, m_pasteMarginRatioCtrl,
138 m_pasteMarginRatioUnits ),
139 m_thermalGap( aParent, m_thermalGapLabel, m_thermalGapCtrl, m_thermalGapUnits ),
140 m_spokeWidth( aParent, m_spokeWidthLabel, m_spokeWidthCtrl, m_spokeWidthUnits ),
141 m_spokeAngle( aParent, m_spokeAngleLabel, m_spokeAngleCtrl, m_spokeAngleUnits ),
142 m_pad_orientation( aParent, m_PadOrientText, m_cb_padrotation, m_orientationUnits )
143{
144 SetName( PAD_PROPERTIES_DLG_NAME );
145 m_isFpEditor = dynamic_cast<FOOTPRINT_EDIT_FRAME*>( aParent ) != nullptr;
146
147 m_currentPad = aPad; // aPad can be NULL, if the dialog is called
148 // from the footprint editor to set default pad setup
149
151
152 // Configure display origin transforms
155
158
160
163
165 m_dummyPad = new PAD( (FOOTPRINT*) nullptr );
166
167 if( aPad )
168 {
169 SetTitle( _( "Pad Properties" ) );
170
171 *m_dummyPad = *aPad;
173 }
174 else
175 {
176 SetTitle( _( "Default Pad Properties for Add Pad Tool" ) );
177
179 }
180
181 if( m_isFpEditor )
182 {
183 m_padNetLabel->Show( false );
184 m_padNetSelector->Show( false );
185 }
186
187 // Pad needs to have a parent for painting; use the parent board for its design settings
188 if( !m_dummyPad->GetParent() )
190
197
200
202
205
206 initValues();
207
208 wxFont infoFont = KIUI::GetInfoFont( this );
209 m_copperLayersLabel->SetFont( infoFont );
210 m_techLayersLabel->SetFont( infoFont );
211 m_parentInfo->SetFont( infoFont );
212
213 infoFont.SetStyle( wxFONTSTYLE_ITALIC );
214 m_nonCopperNote->SetFont( infoFont );
215 m_staticTextInfoPaste->SetFont( infoFont );
216 m_staticTextPrimitiveListWarning->SetFont( infoFont );
217
220
221 // Usually, TransferDataToWindow is called by OnInitDialog
222 // calling it here fixes all widget sizes so FinishDialogSettings can safely fix minsizes
224
225 // Initialize canvas to be able to display the dummy pad:
227
230 m_canUpdate = true;
231
232 m_padNetSelector->Connect( NET_SELECTED,
233 wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ),
234 nullptr, this );
235
236 if( m_padType->GetSelection() != PTH_DLG_TYPE && m_padType->GetSelection() != NPTH_DLG_TYPE )
237 {
238 m_gbSizerHole->Show( false );
239 m_staticline6->Show( false );
240 }
241
242 // Now all widgets have the size fixed, call FinishDialogSettings
244
245 // Update widgets
246 wxUpdateUIEvent dummyUI;
247 OnUpdateUI( dummyUI );
248
249 // Post a dummy size event to force the pad preview panel to update the
250 // view: actual size, best zoom ... after the frame is shown
251 PostSizeEvent();
252}
253
254
256{
257 m_padNetSelector->Disconnect( NET_SELECTED,
258 wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ),
259 nullptr, this );
260
261 delete m_dummyPad;
262 delete m_axisOrigin;
263}
264
265
266// Store the pad draw option during a session.
268
269
270void DIALOG_PAD_PROPERTIES::OnInitDialog( wxInitDialogEvent& event )
271{
272 m_selectedColor = COLOR4D( 1.0, 1.0, 1.0, 0.7 );
273
274 // Needed on some WM to be sure the pad is redrawn according to the final size
275 // of the canvas, with the right zoom factor
276 redraw();
277}
278
279
280void DIALOG_PAD_PROPERTIES::OnCancel( wxCommandEvent& event )
281{
282 // Mandatory to avoid m_panelShowPadGal trying to draw something
283 // in a non valid context during closing process:
285
286 // Now call default handler for wxID_CANCEL command event
287 event.Skip();
288}
289
290
292{
293 // Enable or disable the widgets in page managing custom shape primitives
294 m_listCtrlPrimitives->Enable( aEnable );
295 m_buttonDel->Enable( aEnable );
296 m_buttonEditShape->Enable( aEnable );
297 m_buttonAddShape->Enable( aEnable );
298 m_buttonDup->Enable( aEnable );
299 m_buttonGeometry->Enable( aEnable );
300}
301
302
304{
305 // Initialize the canvas to display the pad
306 m_padPreviewGAL = new PCB_DRAW_PANEL_GAL( m_boardViewPanel, -1, wxDefaultPosition,
307 wxDefaultSize,
310
311 m_padPreviewSizer->Add( m_padPreviewGAL, 12, wxEXPAND | wxALL, 5 );
312
313 // Show the X and Y axis. It is useful because pad shape can have an offset
314 // or be a complex shape.
315 KIGFX::COLOR4D axis_color = LIGHTBLUE;
316
318 pcbIUScale.mmToIU( 0.2 ),
321
324 m_padPreviewGAL->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
325
326 KIGFX::VIEW_CONTROLS* parentViewControls = m_parent->GetCanvas()->GetViewControls();
327 m_padPreviewGAL->GetViewControls()->ApplySettings( parentViewControls->GetSettings() );
328
329 m_padPreviewGAL->Show();
330
332
333 // fix the pad render mode (filled/not filled)
334 auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
335
336 if( m_cbShowPadOutline->IsChecked() )
337 settings->m_ForcePadSketchModeOn = true;
338 else
339 settings->m_ForcePadSketchModeOff = true;
340
341 settings->SetHighContrast( false );
342 settings->m_ContrastModeDisplay = HIGH_CONTRAST_MODE::NORMAL;
343
344 // gives a non null grid size (0.001mm) because GAL layer does not like a 0 size grid:
345 double gridsize = 0.001 * pcbIUScale.IU_PER_MM;
346 view->GetGAL()->SetGridSize( VECTOR2D( gridsize, gridsize ) );
347
348 // And do not show the grid:
349 view->GetGAL()->SetGridVisibility( false );
350 view->Add( m_dummyPad );
351 view->Add( m_axisOrigin );
352
354 Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_PAD_PROPERTIES::OnResize ) );
355}
356
357
359{
360 // Note: use ChangeValue() to avoid generating a wxEVT_TEXT event
362
365
368}
369
370
372{
375 {
376 return;
377 }
378
379 if( m_cornerRadius.GetValue() < 0 )
380 m_cornerRadiusCtrl->ChangeValue( "0" );
381
383 {
385
388
389 redraw();
390 }
391}
392
393
395{
398 {
399 return;
400 }
401
402 wxObject* ctrl = event.GetEventObject();
403 wxString value = event.GetString();
404 bool changed = false;
405
406 if( ctrl == m_cornerRatioCtrl || ctrl == m_mixedCornerRatioCtrl )
407 {
408 double ratioPercent;
409
410 if( value.ToDouble( &ratioPercent ) )
411 {
412 // Clamp ratioPercent to acceptable value (0.0 to 50.0)
413 if( ratioPercent < 0.0 )
414 {
417 }
418 else if( ratioPercent > 50.0 )
419 {
422 }
423
424 if( ctrl == m_cornerRatioCtrl )
425 m_mixedCornerRatioCtrl->ChangeValue( value );
426 else
427 m_cornerRatioCtrl->ChangeValue( value );
428
429 changed = true;
430 }
431 }
432 else if( ctrl == m_chamferRatioCtrl || ctrl == m_mixedChamferRatioCtrl )
433 {
434 double ratioPercent;
435
436 if( value.ToDouble( &ratioPercent ) )
437 {
438 // Clamp ratioPercent to acceptable value (0.0 to 50.0)
439 if( ratioPercent < 0.0 )
440 {
443 }
444 else if( ratioPercent > 50.0 )
445 {
448 }
449
450 if( ctrl == m_chamferRatioCtrl )
451 m_mixedChamferRatioCtrl->ChangeValue( value );
452 else
453 m_chamferRatioCtrl->ChangeValue( value );
454
455 changed = true;
456 }
457 }
458
459 if( changed && transferDataToPad( m_dummyPad ) )
461
462 redraw();
463}
464
465
467{
468 wxString msg;
469
470 // Disable pad net name wxTextCtrl if the caller is the footprint editor
471 // because nets are living only in the board managed by the board editor
473
485
486 if( m_currentPad )
487 {
489
490 FOOTPRINT* footprint = m_currentPad->GetParent();
491
492 if( footprint )
493 {
496
497 // Display parent footprint info
498 msg.Printf( _("Footprint %s (%s), %s, rotated %g deg"),
499 footprint->Reference().GetShownText(),
500 footprint->Value().GetShownText(),
501 footprint->IsFlipped() ? _( "back side (mirrored)" ) : _( "front side" ),
502 footprint->GetOrientation().AsDegrees() );
503 }
504
505 m_parentInfo->SetLabel( msg );
506 }
507 else
508 {
509 m_isFlipped = false;
510 }
511
512 if( m_isFlipped )
513 {
514 // flip pad (up/down) around its position
516 }
517
519
521
522 if( m_currentPad )
523 {
524 m_padNumCtrl->SetValue( m_dummyPad->GetNumber() );
525 }
526 else
527 {
529 m_padNumCtrl->SetValue( padTool->GetLastPadNumber() );
530 }
531
533
534 // Display current pad parameters units:
537
540
543
544 m_offsetShapeOpt->SetValue( m_dummyPad->GetOffset() != wxPoint() );
547
548 if( m_dummyPad->GetDelta().x )
549 {
551 m_trapAxisCtrl->SetSelection( 0 );
552 }
553 else
554 {
556 m_trapAxisCtrl->SetSelection( 1 );
557 }
558
559 m_padToDieOpt->SetValue( m_dummyPad->GetPadToDieLength() != 0 );
561
570
571 switch( m_dummyPad->GetZoneConnection() )
572 {
573 default:
574 case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
575 case ZONE_CONNECTION::FULL: m_ZoneConnectionChoice->SetSelection( 1 ); break;
576 case ZONE_CONNECTION::THERMAL: m_ZoneConnectionChoice->SetSelection( 2 ); break;
577 case ZONE_CONNECTION::NONE: m_ZoneConnectionChoice->SetSelection( 3 ); break;
578 }
579
581 m_ZoneCustomPadShape->SetSelection( 1 );
582 else
583 m_ZoneCustomPadShape->SetSelection( 0 );
584
585 switch( m_dummyPad->GetShape() )
586 {
587 default:
588 case PAD_SHAPE::CIRCLE: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_CIRCLE ); break;
589 case PAD_SHAPE::OVAL: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_OVAL ); break;
590 case PAD_SHAPE::RECT: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_RECT ); break;
593
597 else
599 break;
600
604 else
606 break;
607 }
608
617
619
621
622 // Type of pad selection
624
625 if( aperture )
626 {
627 m_padType->SetSelection( APERTURE_DLG_TYPE );
628 }
629 else
630 {
631 switch( m_dummyPad->GetAttribute() )
632 {
633 case PAD_ATTRIB::PTH: m_padType->SetSelection( PTH_DLG_TYPE ); break;
634 case PAD_ATTRIB::SMD: m_padType->SetSelection( SMD_DLG_TYPE ); break;
635 case PAD_ATTRIB::CONN: m_padType->SetSelection( CONN_DLG_TYPE ); break;
636 case PAD_ATTRIB::NPTH: m_padType->SetSelection( NPTH_DLG_TYPE ); break;
637 }
638 }
639
640 switch( m_dummyPad->GetProperty() )
641 {
642 case PAD_PROP::NONE: m_choiceFabProperty->SetSelection( 0 ); break;
643 case PAD_PROP::BGA: m_choiceFabProperty->SetSelection( 1 ); break;
644 case PAD_PROP::FIDUCIAL_LOCAL: m_choiceFabProperty->SetSelection( 2 ); break;
645 case PAD_PROP::FIDUCIAL_GLBL: m_choiceFabProperty->SetSelection( 3 ); break;
646 case PAD_PROP::TESTPOINT: m_choiceFabProperty->SetSelection( 4 ); break;
647 case PAD_PROP::HEATSINK: m_choiceFabProperty->SetSelection( 5 ); break;
648 case PAD_PROP::CASTELLATED: m_choiceFabProperty->SetSelection( 6 ); break;
649 }
650
651 // Ensure the pad property is compatible with the pad type
653 {
654 m_choiceFabProperty->SetSelection( 0 );
655 m_choiceFabProperty->Enable( false );
656 }
657
659 m_holeShapeCtrl->SetSelection( 0 );
660 else
661 m_holeShapeCtrl->SetSelection( 1 );
662
665
666 // Update some dialog widgets state (Enable/disable options):
667 wxCommandEvent cmd_event;
668 OnPadShapeSelection( cmd_event );
669 OnOffsetCheckbox( cmd_event );
670
671 // Update basic shapes list
673}
674
675// A small helper function, to display coordinates:
676static wxString formatCoord( EDA_UNITS aUnits, VECTOR2I aCoord )
677{
678 return wxString::Format( wxT( "(X:%s Y:%s)" ),
681}
682
684{
685 m_listCtrlPrimitives->ClearAll();
686
687 wxListItem itemCol;
688 itemCol.SetImage(-1);
689
690 for( int ii = 0; ii < 5; ++ii )
691 m_listCtrlPrimitives->InsertColumn(ii, itemCol);
692
693 wxString bs_info[5];
694
695 for( unsigned ii = 0; ii < m_primitives.size(); ++ii )
696 {
697 const std::shared_ptr<PCB_SHAPE>& primitive = m_primitives[ii];
698
699 for( wxString& s : bs_info )
700 s.Empty();
701
702 bs_info[4] = _( "width" ) + wxS( " " )+ EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_units,
703 primitive->GetWidth() );
704
705 switch( primitive->GetShape() )
706 {
707 case SHAPE_T::SEGMENT:
708 bs_info[0] = _( "Segment" );
709 bs_info[1] = _( "from" ) + wxS( " " ) + formatCoord( m_units, primitive->GetStart() );
710 bs_info[2] = _( "to" ) + wxS( " " ) + formatCoord( m_units, primitive->GetEnd() );
711 break;
712
713 case SHAPE_T::BEZIER:
714 bs_info[0] = _( "Bezier" );
715 bs_info[1] = _( "from" ) + wxS( " " ) + formatCoord( m_units, primitive->GetStart() );
716 bs_info[2] = _( "to" ) + wxS( " " ) + formatCoord( m_units, primitive->GetEnd() );
717 break;
718
719 case SHAPE_T::ARC:
720 bs_info[0] = _( "Arc" );
721 bs_info[1] = _( "center" ) + wxS( " " ) + formatCoord( m_units, primitive->GetCenter() );
722 bs_info[2] = _( "start" ) + wxS( " " ) + formatCoord( m_units, primitive->GetStart() );
723 bs_info[3] = _( "angle" ) + wxS( " " ) + EDA_UNIT_UTILS::FormatAngle( primitive->GetArcAngle() );
724 break;
725
726 case SHAPE_T::CIRCLE:
727 if( primitive->GetWidth() )
728 bs_info[0] = _( "Ring" );
729 else
730 bs_info[0] = _( "Circle" );
731
732 bs_info[1] = _( "at" ) + wxS( " " ) + formatCoord( m_units, primitive->GetStart() );
733 bs_info[2] = _( "radius" ) + wxS( " " ) + EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_units,
734 primitive->GetRadius() );
735 break;
736
737 case SHAPE_T::POLY:
738 bs_info[0] = _( "Polygon" );
739 bs_info[1] = wxString::Format( _( "corners count %d" ),
740 primitive->GetPolyShape().Outline( 0 ).PointCount() );
741 break;
742
743 case SHAPE_T::RECT:
744 if( primitive->IsAnnotationProxy() )
745 bs_info[0] = _( "Number box" );
746 else
747 bs_info[0] = _( "Rectangle" );
748
749 bs_info[1] = _( "from" ) + wxS( " " ) + formatCoord( m_units, primitive->GetStart() );
750 bs_info[2] = _( "to" ) + wxS( " " ) + formatCoord( m_units, primitive->GetEnd() );
751 break;
752
753 default:
754 bs_info[0] = _( "Unknown primitive" );
755 break;
756 }
757
758 long tmp = m_listCtrlPrimitives->InsertItem( ii, bs_info[0] );
759 m_listCtrlPrimitives->SetItemData( tmp, ii );
760
761 for( int jj = 0, col = 0; jj < 5; ++jj )
762 m_listCtrlPrimitives->SetItem( tmp, col++, bs_info[jj] );
763 }
764
765 // Now columns are filled, ensure correct width of columns
766 for( unsigned ii = 0; ii < 5; ++ii )
767 m_listCtrlPrimitives->SetColumnWidth( ii, wxLIST_AUTOSIZE );
768}
769
770
771void DIALOG_PAD_PROPERTIES::OnResize( wxSizeEvent& event )
772{
773 redraw();
774 event.Skip();
775}
776
777
778void DIALOG_PAD_PROPERTIES::onChangePadMode( wxCommandEvent& event )
779{
781
783
784 // fix the pad render mode (filled/not filled)
785 auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
786
787 if( m_cbShowPadOutline->IsChecked() )
788 settings->m_ForcePadSketchModeOn = true;
789 else
790 settings->m_ForcePadSketchModeOff = true;
791
792 settings->SetHighContrast( false );
793 settings->m_ContrastModeDisplay = HIGH_CONTRAST_MODE::NORMAL;
794
795 redraw();
796}
797
798
800{
801 switch( m_PadShapeSelector->GetSelection() )
802 {
806 m_shapePropsBook->SetSelection( 0 );
807 break;
808
810 m_shapePropsBook->SetSelection( 1 );
811 break;
812
814 {
815 m_shapePropsBook->SetSelection( 2 );
816
817 // A reasonable default (from IPC-7351C)
818 if( m_dummyPad->GetRoundRectRadiusRatio() == 0.0 )
820
821 break;
822 }
823
825 m_shapePropsBook->SetSelection( 3 );
826
827 // Reasonable default
828 if( m_dummyPad->GetChamferRectRatio() == 0.0 )
830
831 // Ensure the displayed value is up to date:
833
834 // A reasonable default is one corner chamfered (usual for some SMD pads).
835 if( !m_cbTopLeft->GetValue() && !m_cbTopRight->GetValue()
836 && !m_cbBottomLeft->GetValue() && !m_cbBottomRight->GetValue() )
837 {
838 m_cbTopLeft->SetValue( true );
839 m_cbTopRight->SetValue( false );
840 m_cbBottomLeft->SetValue( false );
841 m_cbBottomRight->SetValue( false );
842 }
843
844 break;
845
847 m_shapePropsBook->SetSelection( 4 );
848
849 // Reasonable defaults (corner radius from IPC-7351C)
851 && m_dummyPad->GetChamferRectRatio() == 0.0 )
852 {
853 if( m_dummyPad->GetRoundRectRadiusRatio() == 0.0 )
855
856 if( m_dummyPad->GetChamferRectRatio() == 0.0 )
858 }
859
860 // Ensure the displayed values are up to date:
863 break;
864
865 case CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR: // PAD_SHAPE::CUSTOM, circular anchor
866 case CHOICE_SHAPE_CUSTOM_RECT_ANCHOR: // PAD_SHAPE::CUSTOM, rect anchor
867 m_shapePropsBook->SetSelection( 0 );
868 break;
869 }
870
871 // Note: must do this before enabling/disabling m_sizeY as we're using that as a flag to see
872 // what the last shape was.
873 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CIRCLE )
874 {
875 if( m_sizeYCtrl->IsEnabled() && m_spokeAngle.GetAngleValue() == ANGLE_90 )
877 }
878 else
879 {
880 if( !m_sizeYCtrl->IsEnabled() && m_spokeAngle.GetAngleValue() == ANGLE_45 )
882 }
883
884 // Readjust props book size
885 wxSize size = m_shapePropsBook->GetSize();
886 size.y = m_shapePropsBook->GetPage( m_shapePropsBook->GetSelection() )->GetBestSize().y;
887 m_shapePropsBook->SetMaxSize( size );
888
891
895
896 if( !m_offsetShapeOpt->IsEnabled() )
897 m_offsetShapeOpt->SetValue( false );
898
899 // Show/hide controls depending on m_offsetShapeOpt being enabled
900 m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
901 m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
902
903 bool is_custom = m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
905
906 enablePrimitivePage( is_custom );
907
910
911 for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
912 m_notebook->GetPage( i )->Layout();
913
914 // Resize the dialog if its height is too small to show all widgets:
915 if( m_MainSizer->GetSize().y < m_MainSizer->GetMinSize().y )
916 m_MainSizer->SetSizeHints( this );
917
919 redraw();
920}
921
922
924{
927 redraw();
928}
929
930
931void DIALOG_PAD_PROPERTIES::PadOrientEvent( wxCommandEvent& event )
932{
934 redraw();
935}
936
937
939{
940 m_rbCopperLayersSel->Clear();
941
942 switch( m_padType->GetSelection() )
943 {
944 case PTH_DLG_TYPE:
945 m_rbCopperLayersSel->Append( _( "All copper layers" ) );
946 m_rbCopperLayersSel->Append( wxString::Format( _( "%s, %s and connected layers" ),
948 m_board->GetLayerName( B_Cu ) ) );
949 m_rbCopperLayersSel->Append( _( "Connected layers only" ) );
950 m_rbCopperLayersSel->Append( _( "None" ) );
951 break;
952
953 case NPTH_DLG_TYPE:
954 m_rbCopperLayersSel->Append( wxString::Format( _( "%s and %s" ),
956 m_board->GetLayerName( B_Cu ) ) );
959 m_rbCopperLayersSel->Append( _( "None" ) );
960 break;
961
962 case SMD_DLG_TYPE:
963 case CONN_DLG_TYPE:
966 break;
967
969 m_rbCopperLayersSel->Append( _( "None" ) );
970 break;
971 }
972}
973
974
975void DIALOG_PAD_PROPERTIES::PadTypeSelected( wxCommandEvent& event )
976{
977 bool hasHole = true;
978 bool hasConnection = true;
979 bool hasProperty = true;
980
981 switch( m_padType->GetSelection() )
982 {
983 case PTH_DLG_TYPE: hasHole = true; hasConnection = true; hasProperty = true; break;
984 case SMD_DLG_TYPE: hasHole = false; hasConnection = true; hasProperty = true; break;
985 case CONN_DLG_TYPE: hasHole = false; hasConnection = true; hasProperty = true; break;
986 case NPTH_DLG_TYPE: hasHole = true; hasConnection = false; hasProperty = false; break;
987 case APERTURE_DLG_TYPE: hasHole = false; hasConnection = false; hasProperty = true; break;
988 }
989
990 // Update Layers dropdown list and selects the "best" layer set for the new pad type:
992
993 m_gbSizerHole->Show( hasHole );
994 m_staticline6->Show( hasHole );
995 if( !hasHole )
996 {
997 m_holeX.ChangeValue( 0 );
998 m_holeY.ChangeValue( 0 );
999 }
1000 else if ( m_holeX.GetValue() == 0 && m_currentPad )
1001 {
1004 }
1005
1006 if( !hasConnection )
1007 {
1008 m_padNumCtrl->ChangeValue( wxEmptyString );
1010 m_padToDieOpt->SetValue( false );
1011 }
1012 else if( m_padNumCtrl->GetValue().IsEmpty() && m_currentPad )
1013 {
1014 m_padNumCtrl->ChangeValue( m_currentPad->GetNumber() );
1016 }
1017
1018 if( !hasProperty )
1019 m_choiceFabProperty->SetSelection( 0 );
1020
1021 m_choiceFabProperty->Enable( hasProperty );
1022
1024
1025 // Layout adjustment is needed if the hole details got shown/hidden
1026 m_LeftBoxSizer->Layout();
1027 redraw();
1028}
1029
1030
1031void DIALOG_PAD_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
1032{
1033 bool hasHole = true;
1034 bool hasConnection = true;
1035
1036 switch( m_padType->GetSelection() )
1037 {
1038 case PTH_DLG_TYPE: /* PTH */ hasHole = true; hasConnection = true; break;
1039 case SMD_DLG_TYPE: /* SMD */ hasHole = false; hasConnection = true; break;
1040 case CONN_DLG_TYPE: /* CONN */ hasHole = false; hasConnection = true; break;
1041 case NPTH_DLG_TYPE: /* NPTH */ hasHole = true; hasConnection = false; break;
1042 case APERTURE_DLG_TYPE: /* Aperture */ hasHole = false; hasConnection = false; break;
1043 }
1044
1045 // Enable/disable hole controls
1046 m_holeShapeLabel->Enable( hasHole );
1047 m_holeShapeCtrl->Enable( hasHole );
1048 m_holeX.Enable( hasHole );
1049 m_holeY.Enable( hasHole && m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_OVAL );
1050
1051 // Enable/disable number and net
1052 m_padNumLabel->Enable( hasConnection );
1053 m_padNumCtrl->Enable( hasConnection );
1054
1055 if( m_padNetLabel->IsShown() )
1056 {
1057 m_padNetLabel->Enable( hasConnection && m_canEditNetName && m_currentPad );
1058 m_padNetSelector->Enable( hasConnection && m_canEditNetName && m_currentPad );
1059 }
1060
1061 // Enable/disable pad length-to-die
1062 m_padToDieOpt->Enable( hasConnection );
1063
1064 if( !m_padToDieOpt->IsEnabled() )
1065 m_padToDieOpt->SetValue( false );
1066
1067 // We can show/hide this here because it doesn't require the layout to be refreshed.
1068 // All the others have to be done in their event handlers because doing a layout here
1069 // causes infinite looping on MSW.
1070 m_padToDie.Show( m_padToDieOpt->GetValue() );
1071
1072 // Enable/disable Copper Layers control
1073 m_rbCopperLayersSel->Enable( m_padType->GetSelection() != APERTURE_DLG_TYPE );
1074
1076
1077 switch( m_padType->GetSelection() )
1078 {
1079 case PTH_DLG_TYPE:
1080 if( !cu_set.any() )
1081 m_stackupImagesBook->SetSelection( 3 );
1082 else if( !m_dummyPad->GetRemoveUnconnected() )
1083 m_stackupImagesBook->SetSelection( 0 );
1084 else if( m_dummyPad->GetKeepTopBottom() )
1085 m_stackupImagesBook->SetSelection( 1 );
1086 else
1087 m_stackupImagesBook->SetSelection( 2 );
1088
1089 break;
1090
1091 case NPTH_DLG_TYPE:
1092 if( cu_set.test( F_Cu ) && cu_set.test( B_Cu ) )
1093 m_stackupImagesBook->SetSelection( 4 );
1094 else if( cu_set.test( F_Cu ) )
1095 m_stackupImagesBook->SetSelection( 5 );
1096 else if( cu_set.test( B_Cu ) )
1097 m_stackupImagesBook->SetSelection( 6 );
1098 else
1099 m_stackupImagesBook->SetSelection( 7 );
1100
1101 break;
1102
1103 case SMD_DLG_TYPE:
1104 case CONN_DLG_TYPE:
1105 case APERTURE_DLG_TYPE:
1106 m_stackupImagesBook->ChangeSelection( 3 );
1107 break;
1108 }
1109}
1110
1111
1113{
1114 bool isOnCopperLayer = ( m_dummyPad->GetLayerSet() & LSET::AllCuMask() ).any();
1115 m_nonCopperWarningBook->ChangeSelection( isOnCopperLayer ? 0 : 1 );
1116}
1117
1118
1119void DIALOG_PAD_PROPERTIES::updatePadLayersList( LSET layer_mask, bool remove_unconnected,
1120 bool keep_top_bottom )
1121{
1123
1124 switch( m_padType->GetSelection() )
1125 {
1126 case PTH_DLG_TYPE:
1127 if( !layer_mask.any() )
1128 layer_mask = PAD::PTHMask();
1129
1130 if( !( layer_mask & LSET::AllCuMask() ).any() )
1131 m_rbCopperLayersSel->SetSelection( 3 );
1132 else if( !remove_unconnected )
1133 m_rbCopperLayersSel->SetSelection( 0 );
1134 else if( keep_top_bottom )
1135 m_rbCopperLayersSel->SetSelection( 1 );
1136 else
1137 m_rbCopperLayersSel->SetSelection( 2 );
1138
1139 break;
1140
1141 case SMD_DLG_TYPE:
1142 if( !layer_mask.any() )
1143 layer_mask = PAD::SMDMask();
1144
1145 if( layer_mask.test( F_Cu ) )
1146 m_rbCopperLayersSel->SetSelection( 0 );
1147 else
1148 m_rbCopperLayersSel->SetSelection( 1 );
1149
1150 break;
1151
1152 case CONN_DLG_TYPE:
1153 if( !layer_mask.any() )
1154 layer_mask = PAD::ConnSMDMask();
1155
1156 if( layer_mask.test( F_Cu ) )
1157 m_rbCopperLayersSel->SetSelection( 0 );
1158 else
1159 m_rbCopperLayersSel->SetSelection( 1 );
1160
1161 break;
1162
1163 case NPTH_DLG_TYPE:
1164 if( !layer_mask.any() )
1165 layer_mask = PAD::UnplatedHoleMask();
1166
1167 if( layer_mask.test( F_Cu ) && layer_mask.test( B_Cu ) )
1168 m_rbCopperLayersSel->SetSelection( 0 );
1169 else if( layer_mask.test( F_Cu ) )
1170 m_rbCopperLayersSel->SetSelection( 1 );
1171 else if( layer_mask.test( B_Cu ) )
1172 m_rbCopperLayersSel->SetSelection( 2 );
1173 else
1174 m_rbCopperLayersSel->SetSelection( 3 );
1175
1176 break;
1177
1178 case APERTURE_DLG_TYPE:
1179 if( !layer_mask.any() )
1180 layer_mask = PAD::ApertureMask();
1181
1182 m_rbCopperLayersSel->SetSelection( 0 );
1183 break;
1184 }
1185
1186 m_PadLayerAdhCmp->SetValue( layer_mask[F_Adhes] );
1187 m_PadLayerAdhCu->SetValue( layer_mask[B_Adhes] );
1188
1189 m_PadLayerPateCmp->SetValue( layer_mask[F_Paste] );
1190 m_PadLayerPateCu->SetValue( layer_mask[B_Paste] );
1191
1192 m_PadLayerSilkCmp->SetValue( layer_mask[F_SilkS] );
1193 m_PadLayerSilkCu->SetValue( layer_mask[B_SilkS] );
1194
1195 m_PadLayerMaskCmp->SetValue( layer_mask[F_Mask] );
1196 m_PadLayerMaskCu->SetValue( layer_mask[B_Mask] );
1197
1198 m_PadLayerECO1->SetValue( layer_mask[Eco1_User] );
1199 m_PadLayerECO2->SetValue( layer_mask[Eco2_User] );
1200
1201 m_PadLayerDraft->SetValue( layer_mask[Dwgs_User] );
1202}
1203
1204
1206{
1207 bool retVal = DIALOG_SHIM::Show( aShow );
1208
1209 if( aShow )
1210 {
1211 // It *should* work to set the stackup bitmap in the constructor, but it doesn't.
1212 // wxWidgets needs to have these set when the panel is visible for some reason.
1213 // https://gitlab.com/kicad/code/kicad/-/issues/5534
1221
1222 Layout();
1223 }
1224
1225 return retVal;
1226}
1227
1228
1229void DIALOG_PAD_PROPERTIES::OnSetCopperLayers( wxCommandEvent& event )
1230{
1232 redraw();
1233}
1234
1235
1236void DIALOG_PAD_PROPERTIES::OnSetLayers( wxCommandEvent& event )
1237{
1239 redraw();
1240}
1241
1242
1244{
1245 bool error = !transferDataToPad( m_dummyPad );
1246
1247 wxArrayString error_msgs;
1248 wxArrayString warning_msgs;
1249 VECTOR2I pad_size = m_dummyPad->GetSize();
1250 VECTOR2I drill_size = m_dummyPad->GetDrillSize();
1251
1253 {
1254 // allow 0-sized anchor pads
1255 }
1256 else if( m_dummyPad->GetShape() == PAD_SHAPE::CIRCLE )
1257 {
1258 if( pad_size.x <= 0 )
1259 warning_msgs.Add( _( "Warning: Pad size is less than zero." ) );
1260 }
1261 else
1262 {
1263 if( pad_size.x <= 0 || pad_size.y <= 0 )
1264 warning_msgs.Add( _( "Warning: Pad size is less than zero." ) );
1265 }
1266
1267 // Test hole against pad shape
1269 {
1270 int maxError = m_board->GetDesignSettings().m_MaxError;
1271 SHAPE_POLY_SET padOutline;
1272
1274 maxError, ERROR_INSIDE );
1275
1276 if( !padOutline.Collide( m_dummyPad->GetPosition() ) )
1277 {
1278 warning_msgs.Add( _( "Warning: Pad hole not inside pad shape." ) );
1279 }
1280 else if( m_dummyPad->GetAttribute() == PAD_ATTRIB::PTH )
1281 {
1282 std::shared_ptr<SHAPE_SEGMENT> slot = m_dummyPad->GetEffectiveHoleShape();
1283 SHAPE_POLY_SET slotOutline;
1284
1285 TransformOvalToPolygon( slotOutline, slot->GetSeg().A, slot->GetSeg().B,
1286 slot->GetWidth(), maxError, ERROR_INSIDE );
1287
1288 padOutline.BooleanSubtract( slotOutline, SHAPE_POLY_SET::PM_FAST );
1289
1290 if( padOutline.IsEmpty() )
1291 warning_msgs.Add( _( "Warning: Pad hole will leave no copper." ) );
1292 }
1293 }
1294
1295 if( m_dummyPad->GetLocalClearance() < 0 )
1296 warning_msgs.Add( _( "Warning: Negative local clearance values will have no effect." ) );
1297
1298 // Some pads need a negative solder mask clearance (mainly for BGA with small pads)
1299 // However the negative solder mask clearance must not create negative mask size
1300 // Therefore test for minimal acceptable negative value
1302 {
1303 int absMargin = abs( m_dummyPad->GetLocalSolderMaskMargin() );
1304
1306 {
1307 for( const std::shared_ptr<PCB_SHAPE>& shape : m_dummyPad->GetPrimitives() )
1308 {
1309 BOX2I shapeBBox = shape->GetBoundingBox();
1310
1311 if( absMargin > shapeBBox.GetWidth() || absMargin > shapeBBox.GetHeight() )
1312 {
1313 warning_msgs.Add( _( "Warning: Negative solder mask clearances larger than "
1314 "some shape primitives. Results may be surprising." ) );
1315
1316 break;
1317 }
1318 }
1319 }
1320 else if( absMargin > pad_size.x || absMargin > pad_size.y )
1321 {
1322 warning_msgs.Add( _( "Warning: Negative solder mask clearance larger than pad. No "
1323 "solder mask will be generated." ) );
1324 }
1325 }
1326
1327 // Some pads need a positive solder paste clearance (mainly for BGA with small pads)
1328 // However, a positive value can create issues if the resulting shape is too big.
1329 // (like a solder paste creating a solder paste area on a neighbor pad or on the solder mask)
1330 // So we could ask for user to confirm the choice
1331 // For now we just check for disappearing paste
1332 wxSize paste_size;
1333 int paste_margin = m_dummyPad->GetLocalSolderPasteMargin();
1334 double paste_ratio = m_dummyPad->GetLocalSolderPasteMarginRatio();
1335
1336 paste_size.x = pad_size.x + paste_margin + KiROUND( pad_size.x * paste_ratio );
1337 paste_size.y = pad_size.y + paste_margin + KiROUND( pad_size.y * paste_ratio );
1338
1339 if( paste_size.x <= 0 || paste_size.y <= 0 )
1340 {
1341 warning_msgs.Add( _( "Warning: Negative solder paste margins larger than pad. No solder "
1342 "paste mask will be generated." ) );
1343 }
1344
1345 LSET padlayers_mask = m_dummyPad->GetLayerSet();
1346
1347 if( padlayers_mask == 0 )
1348 error_msgs.Add( _( "Error: pad has no layer." ) );
1349
1350 if( !padlayers_mask[F_Cu] && !padlayers_mask[B_Cu] )
1351 {
1352 if( ( drill_size.x || drill_size.y ) && m_dummyPad->GetAttribute() != PAD_ATTRIB::NPTH )
1353 {
1354 warning_msgs.Add( _( "Warning: Plated through holes should normally have a copper pad "
1355 "on at least one layer." ) );
1356 }
1357 }
1358
1359 if( error )
1360 error_msgs.Add( _( "Error: Trapazoid delta is too large." ) );
1361
1362 switch( m_dummyPad->GetAttribute() )
1363 {
1364 case PAD_ATTRIB::NPTH: // Not plated, but through hole, a hole is expected
1365 case PAD_ATTRIB::PTH: // Pad through hole, a hole is also expected
1366 if( drill_size.x <= 0
1367 || ( drill_size.y <= 0 && m_dummyPad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ) )
1368 {
1369 error_msgs.Add( _( "Error: Through hole pad has no hole." ) );
1370 }
1371 break;
1372
1373 case PAD_ATTRIB::CONN: // Connector pads are smd pads, just they do not have solder paste.
1374 if( padlayers_mask[B_Paste] || padlayers_mask[F_Paste] )
1375 {
1376 warning_msgs.Add( _( "Warning: Connector pads normally have no solder paste. Use a "
1377 "SMD pad instead." ) );
1378 }
1380
1381 case PAD_ATTRIB::SMD: // SMD and Connector pads (One external copper layer only)
1382 {
1383 if( drill_size.x > 0 || drill_size.y > 0 )
1384 {
1385 error_msgs.Add( _( "Error: SMD pad has a hole." ) );
1386 }
1387
1388 LSET innerlayers_mask = padlayers_mask & LSET::InternalCuMask();
1389
1390 if( ( padlayers_mask[F_Cu] && padlayers_mask[B_Cu] ) || innerlayers_mask.count() != 0 )
1391 warning_msgs.Add( _( "Warning: SMD pad has no outer layers." ) );
1392 }
1393 break;
1394 }
1395
1399 {
1400 warning_msgs.Add( _( "Warning: Fiducial property makes no sense on NPTH pads." ) );
1401 }
1402
1405 {
1406 warning_msgs.Add( _( "Warning: Testpoint property makes no sense on NPTH pads." ) );
1407 }
1408
1411 {
1412 warning_msgs.Add( _( "Warning: Heatsink property makes no sense of NPTH pads." ) );
1413 }
1414
1417 {
1418 warning_msgs.Add( _( "Warning: Castellated property is for PTH pads." ) );
1419 }
1420
1423 {
1424 warning_msgs.Add( _( "Warning: BGA property is for SMD pads." ) );
1425 }
1426
1429 {
1431
1432 if( m_cornerRatio.GetDoubleValue() < 0.0 )
1433 error_msgs.Add( _( "Error: Negative corner size." ) );
1434 else if( m_cornerRatio.GetDoubleValue() > 50.0 )
1435 warning_msgs.Add( _( "Warning: Corner size will make pad circular." ) );
1436 }
1437
1438 // PADSTACKS TODO: this will need to check each layer in the pad...
1440 {
1441 SHAPE_POLY_SET mergedPolygon;
1442 m_dummyPad->MergePrimitivesAsPolygon( &mergedPolygon );
1443
1444 if( mergedPolygon.OutlineCount() > 1 )
1445 error_msgs.Add( _( "Error: Custom pad shape must resolve to a single polygon." ) );
1446 }
1447
1448
1449 if( error_msgs.GetCount() || warning_msgs.GetCount() )
1450 {
1451 wxString title = error_msgs.GetCount() ? _( "Pad Properties Errors" )
1452 : _( "Pad Properties Warnings" );
1453 HTML_MESSAGE_BOX dlg( this, title );
1454
1455 dlg.ListSet( error_msgs );
1456
1457 if( warning_msgs.GetCount() )
1458 dlg.ListSet( warning_msgs );
1459
1460 dlg.ShowModal();
1461 }
1462
1463 return error_msgs.GetCount() == 0;
1464}
1465
1466
1468{
1469 if( !m_canUpdate )
1470 return;
1471
1474
1475 // The layer used to place primitive items selected when editing custom pad shapes
1476 // we use here a layer never used in a pad:
1477 #define SELECTED_ITEMS_LAYER Dwgs_User
1478
1480 KIGFX::PCB_RENDER_SETTINGS* settings =
1481 static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
1483
1484 view->Update( m_dummyPad );
1485
1486 // delete previous items if highlight list
1487 while( m_highlight.size() )
1488 {
1489 delete m_highlight.back(); // the dtor also removes item from view
1490 m_highlight.pop_back();
1491 }
1492
1493 // highlight selected primitives:
1494 long select = m_listCtrlPrimitives->GetFirstSelected();
1495
1496 while( select >= 0 )
1497 {
1498 PCB_SHAPE* dummyShape = static_cast<PCB_SHAPE*>( m_primitives[select]->Clone() );
1499 dummyShape->SetLayer( SELECTED_ITEMS_LAYER );
1500 dummyShape->Rotate( VECTOR2I( 0, 0), m_dummyPad->GetOrientation() );
1501 dummyShape->Move( m_dummyPad->GetPosition() );
1502
1503 view->Add( dummyShape );
1504 m_highlight.push_back( dummyShape );
1505
1506 select = m_listCtrlPrimitives->GetNextSelected( select );
1507 }
1508
1509 BOX2I bbox = m_dummyPad->ViewBBox();
1510
1511 if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
1512 {
1513 // The origin always goes in the middle of the canvas; we want offsetting the pad
1514 // shape to move the pad, not the hole
1515 bbox.Move( -m_dummyPad->GetPosition() );
1516 int maxXExtent = std::max( abs( bbox.GetLeft() ), abs( bbox.GetRight() ) );
1517 int maxYExtent = std::max( abs( bbox.GetTop() ), abs( bbox.GetBottom() ) );
1518
1519 // Don't blow up the GAL on too-large numbers
1520 if( maxXExtent > INT_MAX / 4 )
1521 maxXExtent = INT_MAX / 4;
1522
1523 if( maxYExtent > INT_MAX / 4 )
1524 maxYExtent = INT_MAX / 4;
1525
1526 BOX2D viewBox( m_dummyPad->GetPosition(), {0, 0} );
1527 BOX2D canvasBox( m_dummyPad->GetPosition(), {0, 0} );
1528 viewBox.Inflate( maxXExtent * 1.4, maxYExtent * 1.4 ); // add a margin
1529 canvasBox.Inflate( maxXExtent * 2.0, maxYExtent * 2.0 );
1530
1531 view->SetBoundary( canvasBox );
1532
1533 // Autozoom
1534 view->SetViewport( viewBox );
1535
1538 }
1539}
1540
1541
1543{
1544 if( !wxDialog::TransferDataToWindow() )
1545 return false;
1546
1547 if( !m_panelGeneral->TransferDataToWindow() )
1548 return false;
1549
1550 if( !m_localSettingsPanel->TransferDataToWindow() )
1551 return false;
1552
1553 return true;
1554}
1555
1556
1558{
1559 BOARD_COMMIT commit( m_parent );
1560
1561 if( !wxDialog::TransferDataFromWindow() )
1562 return false;
1563
1564 if( !m_panelGeneral->TransferDataFromWindow() )
1565 return false;
1566
1567 if( !m_localSettingsPanel->TransferDataFromWindow() )
1568 return false;
1569
1570 if( !padValuesOK() )
1571 return false;
1572
1574 return false;
1575
1577 padTool->SetLastPadNumber( m_padMaster->GetNumber() );
1578
1579 // m_padMaster is a pattern: ensure there is no net for this pad:
1581
1582 if( !m_currentPad ) // Set current Pad parameters
1583 return true;
1584
1585 commit.Modify( m_currentPad );
1586
1587 // redraw the area where the pad was, without pad (delete pad on screen)
1591
1592 // Update values
1597
1598 VECTOR2I size;
1599 FOOTPRINT* footprint = m_currentPad->GetParent();
1600
1602
1603 size = m_padMaster->GetDelta();
1604 m_currentPad->SetDelta( size );
1605
1608
1609 VECTOR2I offset = m_padMaster->GetOffset();
1610 m_currentPad->SetOffset( offset );
1611
1613
1616
1619
1623
1625
1626 int padNetcode = NETINFO_LIST::UNCONNECTED;
1627
1628 // For PAD_ATTRIB::NPTH, ensure there is no net name selected
1630 padNetcode = m_padNetSelector->GetSelectedNetcode();
1631
1632 m_currentPad->SetNetCode( padNetcode );
1644
1645 // rounded rect pads with radius ratio = 0 are in fact rect pads.
1646 // So set the right shape (and perhaps issues with a radius = 0)
1649 {
1651 }
1652
1653 // Set the fabrication property:
1655
1656 // define the way the clearance area is defined in zones
1658
1659 if( m_isFlipped )
1660 {
1661 // flip pad (up/down) around its position
1663 }
1664
1665 if( footprint )
1666 {
1667 // compute the pos 0 value, i.e. pad position for footprint with orientation = 0
1668 // i.e. relative to footprint origin (footprint position)
1669 VECTOR2I pt = m_currentPad->GetPosition() - footprint->GetPosition();
1670 RotatePoint( pt, -footprint->GetOrientation() );
1671 m_currentPad->SetPos0( pt );
1673 }
1674
1676
1677 // redraw the area where the pad was
1679
1680 commit.Push( _( "Modify pad" ) );
1681
1682 return true;
1683}
1684
1685
1687{
1688 PAD_PROP prop = PAD_PROP::NONE;
1689
1690 switch( m_choiceFabProperty->GetSelection() )
1691 {
1692 case 0: prop = PAD_PROP::NONE; break;
1693 case 1: prop = PAD_PROP::BGA; break;
1694 case 2: prop = PAD_PROP::FIDUCIAL_LOCAL; break;
1695 case 3: prop = PAD_PROP::FIDUCIAL_GLBL; break;
1696 case 4: prop = PAD_PROP::TESTPOINT; break;
1697 case 5: prop = PAD_PROP::HEATSINK; break;
1698 case 6: prop = PAD_PROP::CASTELLATED; break;
1699 }
1700
1701 return prop;
1702}
1703
1705{
1706 m_holeXLabel->SetLabel( ( m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_CIRCLE )
1707 ? _( "Diameter:" )
1708 : _( "Hole size X:" ) );
1710 && m_holeShapeCtrl->GetSelection() != CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR );
1711 m_holeXLabel->GetParent()->Layout();
1712}
1713
1715{
1716 m_sizeXLabel->SetLabel( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CIRCLE
1717 || m_PadShapeSelector->GetSelection()
1719 ? _( "Diameter:" )
1720 : _( "Pad size X:" ) );
1723 m_sizeXLabel->GetParent()->Layout();
1724}
1725
1726
1728{
1729 if( !Validate() )
1730 return false;
1731
1732 if( !m_panelGeneral->Validate() )
1733 return false;
1734
1735 if( !m_localSettingsPanel->Validate() )
1736 return false;
1737
1738 if( !m_spokeWidth.Validate( 0, INT_MAX ) )
1739 return false;
1740
1741 aPad->SetAttribute( code_type[m_padType->GetSelection()] );
1742 aPad->SetShape( code_shape[m_PadShapeSelector->GetSelection()] );
1743
1746 else
1748
1749 if( aPad->GetShape() == PAD_SHAPE::CUSTOM )
1751
1752 // Read pad clearances values:
1760
1761 // And rotation
1763
1764 switch( m_ZoneConnectionChoice->GetSelection() )
1765 {
1766 default:
1767 case 0: aPad->SetZoneConnection( ZONE_CONNECTION::INHERITED ); break;
1768 case 1: aPad->SetZoneConnection( ZONE_CONNECTION::FULL ); break;
1769 case 2: aPad->SetZoneConnection( ZONE_CONNECTION::THERMAL ); break;
1770 case 3: aPad->SetZoneConnection( ZONE_CONNECTION::NONE ); break;
1771 }
1772
1773 aPad->SetPosition( wxPoint( m_posX.GetValue(), m_posY.GetValue() ) );
1774
1775 if( m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_CIRCLE )
1776 {
1778 aPad->SetDrillSize( wxSize( m_holeX.GetValue(), m_holeX.GetValue() ) );
1779 }
1780 else
1781 {
1783 aPad->SetDrillSize( wxSize( m_holeX.GetValue(), m_holeY.GetValue() ) );
1784 }
1785
1786 if( aPad->GetShape() == PAD_SHAPE::CIRCLE )
1787 aPad->SetSize( wxSize( m_sizeX.GetValue(), m_sizeX.GetValue() ) );
1788 else
1789 aPad->SetSize( wxSize( m_sizeX.GetValue(), m_sizeY.GetValue() ) );
1790
1791 // For a trapezoid, test delta value (be sure delta is not too large for pad size)
1792 // remember DeltaSize.x is the Y size variation
1793 bool error = false;
1794 wxSize delta( 0, 0 );
1795
1796 if( aPad->GetShape() == PAD_SHAPE::TRAPEZOID )
1797 {
1798 // For a trapezoid, only one of delta.x or delta.y is not 0, depending on axis.
1799 if( m_trapAxisCtrl->GetSelection() == 0 )
1801 else
1803
1804 if( delta.x < 0 && delta.x < -aPad->GetSize().y )
1805 {
1806 delta.x = -aPad->GetSize().y + 2;
1807 error = true;
1808 }
1809
1810 if( delta.x > 0 && delta.x > aPad->GetSize().y )
1811 {
1812 delta.x = aPad->GetSize().y - 2;
1813 error = true;
1814 }
1815
1816 if( delta.y < 0 && delta.y < -aPad->GetSize().x )
1817 {
1818 delta.y = -aPad->GetSize().x + 2;
1819 error = true;
1820 }
1821
1822 if( delta.y > 0 && delta.y > aPad->GetSize().x )
1823 {
1824 delta.y = aPad->GetSize().x - 2;
1825 error = true;
1826 }
1827 }
1828
1829 aPad->SetDelta( delta );
1830
1831 if( m_offsetShapeOpt->GetValue() )
1832 aPad->SetOffset( wxPoint( m_offsetX.GetValue(), m_offsetY.GetValue() ) );
1833 else
1834 aPad->SetOffset( wxPoint() );
1835
1836 // Read pad length die
1837 if( m_padToDieOpt->GetValue() )
1839 else
1840 aPad->SetPadToDieLength( 0 );
1841
1842 aPad->SetNumber( m_padNumCtrl->GetValue() );
1844
1845 int chamfers = 0;
1846
1847 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_RECT )
1848 {
1849 if( m_cbTopLeft->GetValue() )
1850 chamfers |= RECT_CHAMFER_TOP_LEFT;
1851
1852 if( m_cbTopRight->GetValue() )
1853 chamfers |= RECT_CHAMFER_TOP_RIGHT;
1854
1855 if( m_cbBottomLeft->GetValue() )
1856 chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1857
1858 if( m_cbBottomRight->GetValue() )
1859 chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1860 }
1861 else if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT )
1862 {
1863 if( m_cbTopLeft1->GetValue() )
1864 chamfers |= RECT_CHAMFER_TOP_LEFT;
1865
1866 if( m_cbTopRight1->GetValue() )
1867 chamfers |= RECT_CHAMFER_TOP_RIGHT;
1868
1869 if( m_cbBottomLeft1->GetValue() )
1870 chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1871
1872 if( m_cbBottomRight1->GetValue() )
1873 chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1874 }
1875 aPad->SetChamferPositions( chamfers );
1876
1877 if( aPad->GetShape() == PAD_SHAPE::CUSTOM )
1878 {
1879 // The pad custom has a "anchor pad" (a basic shape: round or rect pad)
1880 // that is the minimal area of this pad, and is useful to ensure a hole
1881 // diameter is acceptable, and is used in Gerber files as flashed area
1882 // reference
1883 if( aPad->GetAnchorPadShape() == PAD_SHAPE::CIRCLE )
1884 aPad->SetSize( wxSize( m_sizeX.GetValue(), m_sizeX.GetValue() ) );
1885 }
1886
1887 // Define the way the clearance area is defined in zones. Since all non-custom pad
1888 // shapes are convex to begin with, this really only makes any difference for custom
1889 // pad shapes.
1890 aPad->SetCustomShapeInZoneOpt( m_ZoneCustomPadShape->GetSelection() == 0 ?
1893
1894 switch( aPad->GetAttribute() )
1895 {
1896 case PAD_ATTRIB::PTH:
1897 break;
1898
1899 case PAD_ATTRIB::CONN:
1900 case PAD_ATTRIB::SMD:
1901 // SMD and PAD_ATTRIB::CONN has no hole.
1902 // basically, SMD and PAD_ATTRIB::CONN are same type of pads
1903 // PAD_ATTRIB::CONN has just a default non technical layers that differs from SMD
1904 // and are intended to be used in virtual edge board connectors
1905 // However we can accept a non null offset,
1906 // mainly to allow complex pads build from a set of basic pad shapes
1907 aPad->SetDrillSize( wxSize( 0, 0 ) );
1908 break;
1909
1910 case PAD_ATTRIB::NPTH:
1911 // Mechanical purpose only:
1912 // no net name, no pad name allowed
1913 aPad->SetNumber( wxEmptyString );
1915 break;
1916
1917 default:
1918 wxFAIL_MSG( wxT( "DIALOG_PAD_PROPERTIES::transferDataToPad: unknown pad type" ) );
1919 break;
1920 }
1921
1922 if( aPad->GetShape() == PAD_SHAPE::ROUNDRECT )
1923 {
1925 }
1926 else if( aPad->GetShape() == PAD_SHAPE::CHAMFERED_RECT )
1927 {
1929 {
1932 }
1933 else // Choice is CHOICE_SHAPE_CHAMFERED_RECT, no rounded corner
1934 {
1936 aPad->SetRoundRectRadiusRatio( 0 );
1937 }
1938 }
1939
1941
1942 LSET padLayerMask = LSET();
1943 int copperLayersChoice = m_rbCopperLayersSel->GetSelection();
1944
1945 aPad->SetRemoveUnconnected( false );
1946 aPad->SetKeepTopBottom( false );
1947
1948 switch( m_padType->GetSelection() )
1949 {
1950 case PTH_DLG_TYPE:
1951 switch( copperLayersChoice )
1952 {
1953 case 0:
1954 // All copper layers
1955 padLayerMask |= LSET::AllCuMask();
1956 break;
1957
1958 case 1:
1959 // Front, back and connected
1960 padLayerMask |= LSET::AllCuMask();
1961 aPad->SetRemoveUnconnected( true );
1962 aPad->SetKeepTopBottom( true );
1963 break;
1964
1965 case 2:
1966 // Connected only
1967 padLayerMask |= LSET::AllCuMask();
1968 aPad->SetRemoveUnconnected( true );
1969 break;
1970
1971 case 3:
1972 // No copper layers
1973 break;
1974 }
1975
1976 break;
1977
1978 case NPTH_DLG_TYPE:
1979 switch( copperLayersChoice )
1980 {
1981 case 0: padLayerMask.set( F_Cu ).set( B_Cu ); break;
1982 case 1: padLayerMask.set( F_Cu ); break;
1983 case 2: padLayerMask.set( B_Cu ); break;
1984 default: break;
1985 }
1986
1987 break;
1988
1989 case SMD_DLG_TYPE:
1990 case CONN_DLG_TYPE:
1991 switch( copperLayersChoice )
1992 {
1993 case 0: padLayerMask.set( F_Cu ); break;
1994 case 1: padLayerMask.set( B_Cu ); break;
1995 }
1996
1997 break;
1998
1999 case APERTURE_DLG_TYPE:
2000 // no copper layers
2001 break;
2002 }
2003
2004 if( m_PadLayerAdhCmp->GetValue() )
2005 padLayerMask.set( F_Adhes );
2006
2007 if( m_PadLayerAdhCu->GetValue() )
2008 padLayerMask.set( B_Adhes );
2009
2010 if( m_PadLayerPateCmp->GetValue() )
2011 padLayerMask.set( F_Paste );
2012
2013 if( m_PadLayerPateCu->GetValue() )
2014 padLayerMask.set( B_Paste );
2015
2016 if( m_PadLayerSilkCmp->GetValue() )
2017 padLayerMask.set( F_SilkS );
2018
2019 if( m_PadLayerSilkCu->GetValue() )
2020 padLayerMask.set( B_SilkS );
2021
2022 if( m_PadLayerMaskCmp->GetValue() )
2023 padLayerMask.set( F_Mask );
2024
2025 if( m_PadLayerMaskCu->GetValue() )
2026 padLayerMask.set( B_Mask );
2027
2028 if( m_PadLayerECO1->GetValue() )
2029 padLayerMask.set( Eco1_User );
2030
2031 if( m_PadLayerECO2->GetValue() )
2032 padLayerMask.set( Eco2_User );
2033
2034 if( m_PadLayerDraft->GetValue() )
2035 padLayerMask.set( Dwgs_User );
2036
2037 aPad->SetLayerSet( padLayerMask );
2038
2039 return !error;
2040}
2041
2042
2043void DIALOG_PAD_PROPERTIES::OnOffsetCheckbox( wxCommandEvent& event )
2044{
2045 if( m_offsetShapeOpt->GetValue() )
2046 {
2049 }
2050
2051 // Show/hide controls depending on m_offsetShapeOpt being enabled
2052 m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
2053 m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
2054
2055 for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
2056 m_notebook->GetPage( i )->Layout();
2057
2058 OnValuesChanged( event );
2059}
2060
2061
2063{
2064 if( m_padToDieOpt->GetValue() && m_currentPad )
2066
2067 OnValuesChanged( event );
2068}
2069
2070
2071void DIALOG_PAD_PROPERTIES::OnValuesChanged( wxCommandEvent& event )
2072{
2073 if( m_canUpdate )
2074 {
2076 return;
2077
2078 // If the pad size has changed, update the displayed values for rounded rect pads.
2080
2081 redraw();
2082 }
2083}
2084
2086{
2087 long select = m_listCtrlPrimitives->GetFirstSelected();
2088
2089 if( select < 0 )
2090 {
2091 wxMessageBox( _( "No shape selected" ) );
2092 return;
2093 }
2094
2095 std::shared_ptr<PCB_SHAPE>& shape = m_primitives[select];
2096
2097 if( shape->GetShape() == SHAPE_T::POLY )
2098 {
2099 DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, m_parent, shape.get() );
2100
2101 if( dlg.ShowModal() != wxID_OK )
2102 return;
2103
2105 }
2106
2107 else
2108 {
2109 DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, m_parent, shape.get() );
2110
2111 if( dlg.ShowModal() != wxID_OK )
2112 return;
2113
2115 }
2116
2118
2120 redraw();
2121}
2122
2123
2125{
2126 // Called on a double click on the basic shapes list
2127 // To Do: highlight the primitive(s) currently selected.
2128 redraw();
2129}
2130
2131
2133{
2134 editPrimitive();
2135}
2136
2137
2138void DIALOG_PAD_PROPERTIES::onEditPrimitive( wxCommandEvent& event )
2139{
2140 editPrimitive();
2141}
2142
2143
2144void DIALOG_PAD_PROPERTIES::onDeletePrimitive( wxCommandEvent& event )
2145{
2146 long select = m_listCtrlPrimitives->GetFirstSelected();
2147
2148 if( select < 0 )
2149 return;
2150
2151 // Multiple selections are allowed. get them and remove corresponding shapes
2152 std::vector<long> indexes;
2153 indexes.push_back( select );
2154
2155 while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2156 indexes.push_back( select );
2157
2158 // Erase all select shapes
2159 for( unsigned ii = indexes.size(); ii > 0; --ii )
2160 m_primitives.erase( m_primitives.begin() + indexes[ii-1] );
2161
2163
2165 redraw();
2166}
2167
2168
2169void DIALOG_PAD_PROPERTIES::onAddPrimitive( wxCommandEvent& event )
2170{
2171 // Ask user for shape type
2172 wxString shapelist[] = {
2173 _( "Segment" ),
2174 _( "Arc" ),
2175 _( "Bezier" ),
2176 _( "Ring/Circle" ),
2177 _( "Polygon" ),
2178 _( "Number box" ),
2179 };
2180
2181 int type = wxGetSingleChoiceIndex( _( "Shape type:" ), _( "Add Primitive" ),
2182 arrayDim( shapelist ), shapelist, 0, this );
2183
2184 // User pressed cancel
2185 if( type == -1 )
2186 return;
2187
2190
2191 PCB_SHAPE* primitive = new PCB_SHAPE();
2192 primitive->SetShape( listtype[type] );
2193
2194 if( type == arrayDim( shapelist ) - 1 )
2195 primitive->SetIsAnnotationProxy();
2196
2199 primitive->SetFilled( true );
2200
2201 if( listtype[type] == SHAPE_T::POLY )
2202 {
2203 DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, m_parent, primitive );
2204
2205 if( dlg.ShowModal() != wxID_OK )
2206 return;
2207 }
2208 else
2209 {
2210 DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, m_parent, primitive );
2211
2212 if( dlg.ShowModal() != wxID_OK )
2213 return;
2214 }
2215
2216 m_primitives.emplace_back( primitive );
2217
2219
2221 redraw();
2222}
2223
2224
2226{
2227 long select = m_listCtrlPrimitives->GetFirstSelected();
2228
2229 if( select < 0 )
2230 {
2231 wxMessageBox( _( "No shape selected" ) );
2232 return;
2233 }
2234
2235 // Multiple selections are allowed. Build selected shapes list
2236 std::vector<std::shared_ptr<PCB_SHAPE>> shapeList;
2237 shapeList.emplace_back( m_primitives[select] );
2238
2239 while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2240 shapeList.emplace_back( m_primitives[select] );
2241
2242 DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, m_parent, shapeList, false );
2243
2244 if( dlg.ShowModal() != wxID_OK )
2245 return;
2246
2247 dlg.Transform();
2248
2250
2252 redraw();
2253}
2254
2255
2257{
2258 long select = m_listCtrlPrimitives->GetFirstSelected();
2259
2260 if( select < 0 )
2261 {
2262 wxMessageBox( _( "No shape selected" ) );
2263 return;
2264 }
2265
2266 // Multiple selections are allowed. Build selected shapes list
2267 std::vector<std::shared_ptr<PCB_SHAPE>> shapeList;
2268 shapeList.emplace_back( m_primitives[select] );
2269
2270 while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2271 shapeList.emplace_back( m_primitives[select] );
2272
2273 DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, m_parent, shapeList, true );
2274
2275 if( dlg.ShowModal() != wxID_OK )
2276 return;
2277
2278 // Transfer new settings
2279 // save duplicates to a separate vector to avoid m_primitives reallocation,
2280 // as shapeList contains pointers to its elements
2281 std::vector<std::shared_ptr<PCB_SHAPE>> duplicates;
2282 dlg.Transform( &duplicates, dlg.GetDuplicateCount() );
2283 std::move( duplicates.begin(), duplicates.end(), std::back_inserter( m_primitives ) );
2284
2286
2288 redraw();
2289}
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
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
@ pads_npth_top
@ pads_reset_unused
@ pads_remove_unused
@ pads_npth_bottom
@ pads_npth_top_bottom
@ pads_remove_unused_keep_bottom
@ dialog_warning
@ NORMAL
Inactive layers are shown normally (no high-contrast mode)
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
std::unique_ptr< PAD > m_Pad_Master
int GetLineThickness(PCB_LAYER_ID aLayer) const
Return the default graphic segment thickness from the layer class for the given layer.
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:201
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:763
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:399
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:617
coord_type GetTop() const
Definition: box2.h:194
coord_type GetHeight() const
Definition: box2.h:188
coord_type GetWidth() const
Definition: box2.h:187
void Move(const Vec &aMoveVector)
Move the rectangle by the aMoveVector.
Definition: box2.h:111
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:506
coord_type GetRight() const
Definition: box2.h:189
coord_type GetLeft() const
Definition: box2.h:193
const Vec & GetSize() const
Definition: box2.h:179
coord_type GetBottom() const
Definition: box2.h:190
COMMIT & Modify(EDA_ITEM *aItem)
Create an undo entry for an item that has been already modified.
Definition: commit.h:103
A dialog to edit basic shape parameters.
bool TransferDataFromWindow() override
Transfer data out of the GUI.
A dialog to apply geometry transforms to a shape or set of shapes (move, rotate around origin,...
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 .
A dialog to edit basic polygonal shape parameters.
bool TransferDataFromWindow() override
Transfer data out of the GUI.
Class DIALOG_PAD_PROPERTIES_BASE.
void OnUpdateUINonCopperWarning(wxUpdateUIEvent &event) override
void OnInitDialog(wxInitDialogEvent &event) override
void PadTypeSelected(wxCommandEvent &event) override
void OnPadShapeSelection(wxCommandEvent &event) override
bool transferDataToPad(PAD *aPad)
Copy values from dialog field to aPad's members.
void onAddPrimitive(wxCommandEvent &event) override
bool TransferDataFromWindow() override
Updates the different parameters for the component being edited.
bool Show(bool aShow) override
std::vector< std::shared_ptr< PCB_SHAPE > > m_primitives
bool padValuesOK()
test if all values are acceptable for the pad
void onPrimitiveDClick(wxMouseEvent &event) override
Called on a double click on the basic shapes list.
void PadOrientEvent(wxCommandEvent &event) override
void OnResize(wxSizeEvent &event)
void OnOffsetCheckbox(wxCommandEvent &event) override
PCB_DRAW_PANEL_GAL * m_padPreviewGAL
void OnValuesChanged(wxCommandEvent &event) override
Called when a dimension has changed.
DIALOG_PAD_PROPERTIES(PCB_BASE_FRAME *aParent, PAD *aPad)
void onEditPrimitive(wxCommandEvent &event) override
void onChangePadMode(wxCommandEvent &event) override
void OnPrimitiveSelection(wxListEvent &event) override
Called on selection/deselection of a basic shape.
std::vector< PCB_SHAPE * > m_highlight
KIGFX::ORIGIN_VIEWITEM * m_axisOrigin
void OnSetCopperLayers(wxCommandEvent &event) override
void OnCancel(wxCommandEvent &event) override
void onCornerRadiusChange(wxCommandEvent &event) override
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...
PAD_PROP getSelectedProperty()
Return the pad property currently selected.
void OnSetLayers(wxCommandEvent &event) override
void onCornerSizePercentChange(wxCommandEvent &event) override
void enablePrimitivePage(bool aEnable)
enable (or disable) the primitive page editor
void OnPadToDieCheckbox(wxCommandEvent &event) override
void onGeometryTransform(wxCommandEvent &event) override
void onDuplicatePrimitive(wxCommandEvent &event) override
void OnDrillShapeSelected(wxCommandEvent &event) override
void onDeletePrimitive(wxCommandEvent &event) override
Event handlers of basic shapes list panel.
void OnUpdateUI(wxUpdateUIEvent &event) override
bool Show(bool show) override
EDA_UNITS m_units
Definition: dialog_shim.h:202
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 SetupStandardButtons(std::map< int, wxString > aLabels={})
int ShowQuasiModal()
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
double AsDegrees() const
Definition: eda_angle.h:149
bool IsType(FRAME_T aType) const
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
KIGFX::GAL_DISPLAY_OPTIONS & GetGalDisplayOptions()
Return a reference to the gal rendering options used by GAL for rendering.
GAL_TYPE GetBackend() const
Return the type of backend currently used by GAL canvas.
void StopDrawing()
Prevent the GAL canvas from further drawing until it is recreated or StartDrawing() is called.
KIGFX::VIEW_CONTROLS * GetViewControls() const
Return a pointer to the #VIEW_CONTROLS instance used in the panel.
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...
void StartDrawing()
Begin drawing if it was stopped previously.
void SetStealsFocus(bool aStealsFocus)
Set whether focus is taken on certain events (mouseover, keys, etc).
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:142
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:143
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:100
void SetFilled(bool aFlag)
Definition: eda_shape.h:95
void SetShape(SHAPE_T aShape)
Definition: eda_shape.h:110
void SetIsAnnotationProxy(bool aIsProxy=true)
Definition: eda_shape.h:88
EDA_ANGLE GetOrientation() const
Definition: footprint.h:195
bool IsFlipped() const
Definition: footprint.h:319
FP_TEXT & Value()
read/write accessors:
Definition: footprint.h:555
VECTOR2I GetPosition() const override
Definition: footprint.h:192
FP_TEXT & Reference()
Definition: footprint.h:556
virtual wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition: fp_text.cpp:412
void ListSet(const wxString &aList)
Add a list of items.
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
void SetGridSize(const VECTOR2D &aGridSize)
Set the grid size.
void SetGridVisibility(bool aVisibility)
Set the visibility setting of the grid.
void SetDrawAtZero(bool aDrawFlag)
Set the draw at zero flag.
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
PCB specific render settings.
Definition: pcb_painter.h:71
void SetLayerColor(int aLayer, const COLOR4D &aColor)
Change the color used to draw a layer.
An interface for classes handling user events controlling the view behavior such as zooming,...
void ApplySettings(const VC_SETTINGS &aSettings)
Load new settings from program common settings.
const VC_SETTINGS & GetSettings() const
Apply VIEW_CONTROLS settings from an object.
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:69
void SetViewport(const BOX2D &aViewport)
Set the visible area of the VIEW.
Definition: view.cpp:520
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:316
void SetBoundary(const BOX2D &aBoundary)
Set limits for view area.
Definition: view.h:279
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:1574
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:195
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:822
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:213
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:530
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:733
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:773
static const int UNCONNECTED
Constant that forces initialization of a netinfo item to the NETINFO_ITEM ORPHANED (typically -1) whe...
Definition: netinfo.h:373
void SetBoard(BOARD *aBoard)
int GetSelectedNetcode()
void SetSelectedNetcode(int aNetcode)
void SetNetInfo(NETINFO_LIST *aNetInfoList)
Tool relating to pads and pad settings.
Definition: pad_tool.h:37
void SetLastPadNumber(const wxString &aPadNumber)
Definition: pad_tool.h:66
wxString GetLastPadNumber() const
Definition: pad_tool.h:65
Definition: pad.h:58
int GetLocalClearance(wxString *aSource) const override
Return any local clearances set in the "classic" (ie: pre-rule) system.
Definition: pad.cpp:777
bool IsAperturePad() const
Definition: pad.h:401
void SetAttribute(PAD_ATTRIB aAttribute)
Definition: pad.cpp:653
void SetLayerSet(LSET aLayers) override
Definition: pad.h:390
PAD_PROP GetProperty() const
Definition: pad.h:397
bool GetRemoveUnconnected() const
Definition: pad.h:590
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: pad.h:377
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pad.h:391
const VECTOR2I & GetDrillSize() const
Definition: pad.h:261
PAD_ATTRIB GetAttribute() const
Definition: pad.h:394
void SetLocalSolderPasteMargin(int aMargin)
Definition: pad.h:417
static LSET PTHMask()
layer set for a through hole pad
Definition: pad.cpp:174
ZONE_CONNECTION GetZoneConnection() const
Definition: pad.h:503
void SetRemoveUnconnected(bool aSet)
Set the unconnected removal property.
Definition: pad.h:589
void SetThermalGap(int aGap)
Definition: pad.h:534
void SetThermalSpokeAngle(const EDA_ANGLE &aAngle)
The orientation of the thermal spokes.
Definition: pad.h:521
const wxString & GetNumber() const
Definition: pad.h:134
void MergePrimitivesAsPolygon(SHAPE_POLY_SET *aMergedPolygon, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Merge all basic shapes to a SHAPE_POLY_SET.
double GetLocalSolderPasteMarginRatio() const
Definition: pad.h:419
int GetRoundRectCornerRadius() const
Definition: pad.cpp:307
void DeletePrimitivesList()
Clear the basic shapes list.
void SetDrillShape(PAD_DRILL_SHAPE_T aShape)
Definition: pad.h:376
VECTOR2I GetPosition() const override
Definition: pad.h:196
void SetProperty(PAD_PROP aProperty)
Definition: pad.cpp:664
const std::vector< std::shared_ptr< PCB_SHAPE > > & GetPrimitives() const
Accessor to the basic shape list for custom-shaped pads.
Definition: pad.h:324
EDA_ANGLE GetThermalSpokeAngle() const
Definition: pad.h:522
void SetOffset(const VECTOR2I &aOffset)
Definition: pad.h:267
void TransformShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, PCB_LAYER_ID aLayer, int aClearanceValue, int aMaxError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the pad shape to a closed polygon.
Definition: pad.cpp:1576
void SetChamferRectRatio(double aChamferScale)
Has meaning only for chamfered rectangular pads.
Definition: pad.cpp:330
const VECTOR2I & GetOffset() const
Definition: pad.h:268
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
Definition: pad.cpp:195
void SetRoundRectCornerRadius(double aRadius)
Has meaning only for rounded rectangle pads.
Definition: pad.cpp:313
void SetLocalClearance(int aClearance)
Definition: pad.h:414
void SetKeepTopBottom(bool aSet)
Set whether we keep the top and bottom connections even if they are not connected.
Definition: pad.h:595
void SetNumber(const wxString &aNumber)
Set the pad number (note that it can be alphanumeric, such as the array reference "AA12").
Definition: pad.h:133
void SetZoneConnection(ZONE_CONNECTION aType)
Definition: pad.h:502
int GetLocalSolderMaskMargin() const
Definition: pad.h:409
bool GetKeepTopBottom() const
Definition: pad.h:596
CUST_PAD_SHAPE_IN_ZONE GetCustomShapeInZoneOpt() const
Definition: pad.h:206
FOOTPRINT * GetParent() const
Definition: pad.cpp:1464
void SetDelta(const VECTOR2I &aSize)
Definition: pad.h:257
bool IsOnCopperLayer() const override
Definition: pad.h:236
void SetPosition(const VECTOR2I &aPos) override
Definition: pad.h:190
const VECTOR2I & GetDelta() const
Definition: pad.h:258
static LSET ConnSMDMask()
layer set for a SMD pad on Front layer used for edge board connectors
Definition: pad.cpp:188
void SetDrillSize(const VECTOR2I &aSize)
Definition: pad.h:260
PAD_SHAPE GetShape() const
Definition: pad.h:188
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition: pad.h:364
void Flip(const VECTOR2I &VECTOR2I, bool aFlipLeftRight) override
Flip this object, i.e.
Definition: pad.cpp:681
static LSET ApertureMask()
layer set for an aperture pad
Definition: pad.cpp:202
virtual const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: pad.cpp:1441
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: pad.cpp:181
void SetLocalSolderPasteMarginRatio(double aRatio)
Definition: pad.h:420
void SetShape(PAD_SHAPE aShape)
Set the new shape of this pad.
Definition: pad.h:179
int GetThermalSpokeWidth() const
Definition: pad.h:512
int GetLocalSolderPasteMargin() const
Definition: pad.h:416
void SetPos0(const VECTOR2I &aPos)
Definition: pad.h:244
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:216
void SetRoundRectRadiusRatio(double aRadiusScale)
Has meaning only for rounded rectangle pads.
Definition: pad.cpp:322
void SetAnchorPadShape(PAD_SHAPE aShape)
Set the shape of the anchor pad for custom shaped pads.
Definition: pad.h:227
void SetOrientation(const EDA_ANGLE &aAngle)
Set the rotation angle of the pad.
Definition: pad.cpp:672
int GetChamferPositions() const
Definition: pad.h:575
void ReplacePrimitives(const std::vector< std::shared_ptr< PCB_SHAPE > > &aPrimitivesList)
Clear the current custom shape primitives list and import a new list.
void SetLocalSolderMaskMargin(int aMargin)
Definition: pad.h:410
void SetThermalSpokeWidth(int aWidth)
Set the width of the thermal spokes connecting the pad to a zone.
Definition: pad.h:511
void SetSize(const VECTOR2I &aSize)
Definition: pad.h:250
double GetRoundRectRadiusRatio() const
Definition: pad.h:556
int GetThermalGap() const
Definition: pad.h:535
std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const override
Return a SHAPE_SEGMENT object representing the pad's hole.
Definition: pad.cpp:384
const VECTOR2I & GetSize() const
Definition: pad.h:251
void SetChamferPositions(int aPositions)
Has meaning only for chamfered rectangular pads.
Definition: pad.h:574
PAD_SHAPE GetAnchorPadShape() const
Definition: pad.h:201
double GetChamferRectRatio() const
Definition: pad.h:565
void SetPadToDieLength(int aLength)
Definition: pad.h:406
bool IsFlipped() const
Definition: pad.cpp:209
int GetPadToDieLength() const
Definition: pad.h:407
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
void ShowPadPropertiesDialog(PAD *aPad)
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
BOARD * GetBoard() const
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Returns the BOARD_DESIGN_SETTINGS for the open project.
void UpdateColors()
Update the color settings in the painter and GAL.
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
virtual void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
Definition: pcb_shape.cpp:186
virtual void Move(const VECTOR2I &aMoveVector) override
Move this object.
Definition: pcb_shape.cpp:158
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition: pcb_shape.h:70
Represent a set of closed polygons.
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset intersection For aFastMode meaning, see function booleanOp.
bool IsEmpty() const
bool Collide(const SHAPE *aShape, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if the boundary of shape (this) lies closer to the shape aShape than aClearance,...
int OutlineCount() const
Return the number of vertices in a given outline/hole.
Simple container to manage line stroke parameters.
Definition: stroke_params.h:88
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:54
virtual void ChangeDoubleValue(double aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion WITHOUT trigger...
virtual long long int GetValue()
Return the current value in Internal Units.
void Enable(bool aEnable)
Enable/disable the label, widget and units label.
virtual void SetPrecision(int aLength)
Normally not needed, but can be used to set the precision when using internal units that are floats (...
virtual void SetUnits(EDA_UNITS aUnits)
Normally not needed (as the UNIT_BINDER inherits from the parent frame), but can be used to set to DE...
virtual EDA_ANGLE GetAngleValue()
virtual void SetNegativeZero()
Definition: unit_binder.h:70
virtual double GetDoubleValue()
Return the current value in Internal Units.
virtual void SetAngleValue(const EDA_ANGLE &aValue)
virtual void ChangeAngleValue(const EDA_ANGLE &aValue)
virtual void SetDoubleValue(double aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
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.
virtual void ChangeValue(int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion WITHOUT trigger...
virtual void SetValue(long long int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
void Show(bool aShow, bool aResize=false)
Show/hide the label, widget and units label.
void SetCoordType(ORIGIN_TRANSFORMS::COORD_TYPES_T aCoordType)
Set the current origin transform mode.
Definition: unit_binder.h:186
@ LIGHTBLUE
Definition: color4d.h:62
This file is part of the common library.
void TransformOvalToPolygon(SHAPE_POLY_SET &aCornerBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
#define APERTURE_DLG_TYPE
#define CONN_DLG_TYPE
static wxString formatCoord(EDA_UNITS aUnits, VECTOR2I aCoord)
static PAD_ATTRIB code_type[]
#define SELECTED_ITEMS_LAYER
static PAD_SHAPE code_shape[]
#define SMD_DLG_TYPE
@ CHOICE_SHAPE_CIRCLE
@ CHOICE_SHAPE_ROUNDRECT
@ CHOICE_SHAPE_CUSTOM_RECT_ANCHOR
@ CHOICE_SHAPE_CHAMFERED_RECT
@ CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
@ CHOICE_SHAPE_RECT
@ CHOICE_SHAPE_OVAL
@ CHOICE_SHAPE_TRAPEZOID
@ CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT
#define NPTH_DLG_TYPE
#define PTH_DLG_TYPE
#define PAD_PROPERTIES_DLG_NAME
DIALOG_PAD_PROPERTIES, derived from DIALOG_PAD_PROPERTIES_BASE, created by wxFormBuilder.
#define _(s)
static constexpr EDA_ANGLE & ANGLE_45
Definition: eda_angle.h:413
static constexpr EDA_ANGLE & ANGLE_90
Definition: eda_angle.h:414
#define BRIGHTENED
item is drawn with a bright contour
#define SELECTED
Item was manually selected by the user.
#define DO_NOT_DRAW
Used to disable draw function.
SHAPE_T
Definition: eda_shape.h:41
EDA_UNITS
Definition: eda_units.h:43
@ FRAME_PCB_EDITOR
Definition: frame_type.h:40
@ ERROR_INSIDE
@ B_Adhes
Definition: layer_ids.h:97
@ Dwgs_User
Definition: layer_ids.h:109
@ F_Paste
Definition: layer_ids.h:101
@ F_Adhes
Definition: layer_ids.h:98
@ B_Mask
Definition: layer_ids.h:106
@ B_Cu
Definition: layer_ids.h:95
@ Eco1_User
Definition: layer_ids.h:111
@ F_Mask
Definition: layer_ids.h:107
@ B_Paste
Definition: layer_ids.h:100
@ F_SilkS
Definition: layer_ids.h:104
@ UNDEFINED_LAYER
Definition: layer_ids.h:60
@ Eco2_User
Definition: layer_ids.h:112
@ B_SilkS
Definition: layer_ids.h:103
@ F_Cu
Definition: layer_ids.h:64
This file contains miscellaneous commonly used macros and functions.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
wxString MessageTextFromValue(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, double aValue, bool aAddUnitsText=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
A helper to convert the double length aValue to a string in inches, millimeters, or unscaled units.
Definition: eda_units.cpp:323
std::string FormatAngle(const EDA_ANGLE &aAngle)
Converts aAngle from board units to a string appropriate for writing to file.
Definition: eda_units.cpp:135
wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:144
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:401
@ CUST_PAD_SHAPE_IN_ZONE_OUTLINE
Definition: pad.h:43
@ CUST_PAD_SHAPE_IN_ZONE_CONVEXHULL
Definition: pad.h:44
PAD_ATTRIB
The set of pad shapes, used with PAD::{Set,Get}Attribute().
Definition: pad_shapes.h:81
@ NPTH
like PAD_PTH, but not plated
@ SMD
Smd pad, appears on the solder paste layer (default)
@ PTH
Plated through hole pad.
@ CONN
Like smd, does not appear on the solder paste layer (default)
@ PAD_DRILL_SHAPE_CIRCLE
Definition: pad_shapes.h:70
@ PAD_DRILL_SHAPE_OBLONG
Definition: pad_shapes.h:71
PAD_SHAPE
The set of pad shapes, used with PAD::{Set,Get}Shape()
Definition: pad_shapes.h:35
PAD_PROP
The set of pad properties used in Gerber files (Draw files, and P&P files) to define some properties ...
Definition: pad_shapes.h:97
@ FIDUCIAL_LOCAL
a fiducial (usually a smd) local to the parent footprint
@ FIDUCIAL_GLBL
a fiducial (usually a smd) for the full board
@ HEATSINK
a pad used as heat sink, usually in SMD footprints
@ NONE
no special fabrication property
@ TESTPOINT
a test point pad
@ CASTELLATED
a pad with a castellated through hole
@ BGA
Smd pad, used in BGA footprints.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
const double IU_PER_MM
Definition: base_units.h:77
constexpr int mmToIU(double mm) const
Definition: base_units.h:89
constexpr int delta
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183
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:80
VECTOR2< double > VECTOR2D
Definition: vector2d.h:617
VECTOR2< int > VECTOR2I
Definition: vector2d.h:618
@ THERMAL
Use thermal relief for pads.
@ NONE
Pads are not covered.
@ FULL
pads are covered by copper