KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 The 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 <drc/drc_item.h>
28#include <base_units.h>
29#include <bitmaps.h>
30#include <board_commit.h>
31#include <board.h>
33#include <footprint.h>
34#include <confirm.h>
35#include <core/arraydim.h>
36#include <convert_basic_shapes_to_polygon.h> // for enum RECT_CHAMFER_POSITIONS definition
41#include <macros.h>
42#include <pad.h>
43#include <pad_utils.h>
44#include <pcb_base_frame.h>
46#include <pcb_painter.h>
47#include <pcbnew_settings.h>
49#include <view/view_controls.h>
51#include <tool/tool_manager.h>
52#include <tools/pad_tool.h>
53#include <advanced_config.h> // for pad property feature management
54#include <wx/choicdlg.h>
55
56
57int DIALOG_PAD_PROPERTIES::m_page = 0; // remember the last open page during session
58
59
60// list of pad shapes, ordered like the pad shape wxChoice in dialog.
62{
69 PAD_SHAPE::CHAMFERED_RECT, // choice = CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT
70 PAD_SHAPE::CUSTOM, // choice = CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
71 PAD_SHAPE::CUSTOM // choice = PAD_SHAPE::CUSTOM_RECT_ANCHOR
72};
73
74
75// the ordered index of the pad shape wxChoice in dialog.
76// keep it consistent with code_shape[] and dialog strings
78{
88};
89
90
92{
97 PAD_ATTRIB::SMD // Aperture pad :type SMD with no copper layers,
98 // only on tech layers (usually only on paste layer
99};
100
101
102// These define have the same value as the m_PadType wxChoice GetSelected() return value
103#define PTH_DLG_TYPE 0
104#define SMD_DLG_TYPE 1
105#define CONN_DLG_TYPE 2
106#define NPTH_DLG_TYPE 3
107#define APERTURE_DLG_TYPE 4
108
109
111{
112 DIALOG_PAD_PROPERTIES dlg( this, aPad );
113
114 // QuasiModal required for NET_SELECTOR
115 dlg.ShowQuasiModal();
116}
117
118
120 DIALOG_PAD_PROPERTIES_BASE( aParent ), m_parent( aParent ), m_initialized( false ), m_editLayer( F_Cu ),
121 m_posX( aParent, m_posXLabel, m_posXCtrl, m_posXUnits ),
122 m_posY( aParent, m_posYLabel, m_posYCtrl, m_posYUnits ),
123 m_sizeX( aParent, m_sizeXLabel, m_sizeXCtrl, m_sizeXUnits ),
124 m_sizeY( aParent, m_sizeYLabel, m_sizeYCtrl, m_sizeYUnits ),
125 m_offsetX( aParent, m_offsetXLabel, m_offsetXCtrl, m_offsetXUnits ),
126 m_offsetY( aParent, m_offsetYLabel, m_offsetYCtrl, m_offsetYUnits ),
127 m_padToDie( aParent, m_padToDieLabel, m_padToDieCtrl, m_padToDieUnits ),
128 m_padToDieDelay( aParent, m_padToDieDelayLabel, m_padToDieDelayCtrl, m_padToDieDelayUnits ),
129 m_trapDelta( aParent, m_trapDeltaLabel, m_trapDeltaCtrl, m_trapDeltaUnits ),
130 m_cornerRadius( aParent, m_cornerRadiusLabel, m_cornerRadiusCtrl, m_cornerRadiusUnits ),
131 m_cornerRatio( aParent, m_cornerRatioLabel, m_cornerRatioCtrl, m_cornerRatioUnits ),
132 m_chamferRatio( aParent, m_chamferRatioLabel, m_chamferRatioCtrl, m_chamferRatioUnits ),
133 m_mixedCornerRatio( aParent, m_mixedCornerRatioLabel, m_mixedCornerRatioCtrl, m_mixedCornerRatioUnits ),
134 m_mixedChamferRatio( aParent, m_mixedChamferRatioLabel, m_mixedChamferRatioCtrl, m_mixedChamferRatioUnits ),
135 m_holeX( aParent, m_holeXLabel, m_holeXCtrl, m_holeXUnits ),
136 m_holeY( aParent, m_holeYLabel, m_holeYCtrl, m_holeYUnits ),
137 m_clearance( aParent, m_clearanceLabel, m_clearanceCtrl, m_clearanceUnits ),
138 m_maskMargin( aParent, m_maskMarginLabel, m_maskMarginCtrl, m_maskMarginUnits ),
139 m_pasteMargin( aParent, m_pasteMarginLabel, m_pasteMarginCtrl, m_pasteMarginUnits ),
140 m_pasteMarginRatio( aParent, m_pasteMarginRatioLabel, m_pasteMarginRatioCtrl, m_pasteMarginRatioUnits ),
141 m_thermalGap( aParent, m_thermalGapLabel, m_thermalGapCtrl, m_thermalGapUnits ),
142 m_spokeWidth( aParent, m_spokeWidthLabel, m_spokeWidthCtrl, m_spokeWidthUnits ),
143 m_spokeAngle( aParent, m_spokeAngleLabel, m_spokeAngleCtrl, m_spokeAngleUnits ),
144 m_pad_orientation( aParent, m_PadOrientText, m_cb_padrotation, m_orientationUnits ),
145 m_teardropMaxLenSetting( aParent, m_stMaxLen, m_tcTdMaxLen, m_stMaxLenUnits ),
146 m_teardropMaxHeightSetting( aParent, m_stTdMaxSize, m_tcMaxHeight, m_stMaxHeightUnits )
147{
148 SetName( PAD_PROPERTIES_DLG_NAME );
149 m_isFpEditor = dynamic_cast<FOOTPRINT_EDIT_FRAME*>( aParent ) != nullptr;
150
151 m_currentPad = aPad; // aPad can be NULL, if the dialog is called
152 // from the footprint editor to set default pad setup
153
155
156 // Configure display origin transforms
159
161
163
164 m_FlippedWarningIcon->SetBitmap( KiBitmapBundle( BITMAPS::dialog_warning ) );
165 m_nonCopperWarningIcon->SetBitmap( KiBitmapBundle( BITMAPS::dialog_warning ) );
166 m_legacyTeardropsIcon->SetBitmap( KiBitmapBundle( BITMAPS::dialog_warning ) );
167
169 m_previewPad = new PAD( (FOOTPRINT*) nullptr );
170
171 if( aPad )
172 {
173 SetTitle( _( "Pad Properties" ) );
174
175 *m_previewPad = *aPad;
178 }
179 else
180 {
181 SetTitle( _( "Default Pad Properties for Add Pad Tool" ) );
182
185 }
186
187 // TODO(JE) padstacks: should this be re-run when pad mode changes?
188 // Pads have a hardcoded internal rounding ratio which is 0.25 by default, even if
189 // they're not a rounded shape. This makes it hard to detect an intentional 0.25
190 // ratio, or one that's only there because it's the PAD default.
191 // Zero it out here to mark that we should recompute a better ratio if the user
192 // selects a pad shape which would need a default rounding ratio computed for it
194 [&]( PCB_LAYER_ID aLayer )
195 {
198 } );
199
200 if( m_isFpEditor )
201 {
202 m_padNetLabel->Show( false );
203 m_padNetSelector->Show( false );
204 }
205
206 m_FlippedWarningSizer->Show( false );
207
208 // Pad needs to have a parent for painting; use the parent board for its design settings
209 if( !m_previewPad->GetParent() )
211
212 m_cornerRatio.SetUnits( EDA_UNITS::PERCENT );
213 m_chamferRatio.SetUnits( EDA_UNITS::PERCENT );
214 m_mixedCornerRatio.SetUnits( EDA_UNITS::PERCENT );
215 m_mixedChamferRatio.SetUnits( EDA_UNITS::PERCENT );
216 m_pad_orientation.SetUnits( EDA_UNITS::DEGREES );
218
219 m_spokeAngle.SetUnits( EDA_UNITS::DEGREES );
221
223
224 m_pasteMarginRatio.SetUnits( EDA_UNITS::PERCENT );
226
227 m_padToDieDelay.SetUnits( EDA_UNITS::PS );
228
229 initValues();
230
231 m_techLayersLabel->SetFont( KIUI::GetStatusFont( this ) );
232 m_parentInfo->SetFont( KIUI::GetSmallInfoFont( this ) );
233 m_teardropShapeLabel->SetFont( KIUI::GetStatusFont( this ) );
234
235 wxFont infoFont = KIUI::GetSmallInfoFont( this ).Italic();
236 m_nonCopperNote->SetFont( infoFont );
237 m_staticTextInfoPaste->SetFont( infoFont );
238
241
242 // Usually, TransferDataToWindow is called by OnInitDialog
243 // calling it here fixes all widget sizes so FinishDialogSettings can safely fix minsizes
245
246 // Initialize canvas to be able to display the dummy pad:
248
249 m_notebook->SetSelection( m_page );
250
251 switch( m_page )
252 {
253 default:
254 case 0: SetInitialFocus( m_padNumCtrl ); break;
255 case 1: SetInitialFocus( m_thermalGapCtrl ); break;
256 case 2: SetInitialFocus( m_clearanceCtrl ); break;
257 }
258
260 m_initialized = true;
261
262 m_padNetSelector->Connect( FILTERED_ITEM_SELECTED,
263 wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ),
264 nullptr, this );
265
266 if( m_padType->GetSelection() != PTH_DLG_TYPE && m_padType->GetSelection() != NPTH_DLG_TYPE )
267 {
268 m_gbSizerHole->Show( false );
269 m_staticline71->Show( false );
270 }
271
272 // Now all widgets have the size fixed, call FinishDialogSettings
274
275 // Update widgets
276 wxUpdateUIEvent dummyUI;
277 OnUpdateUI( dummyUI );
278
279 // Post a dummy size event to force the pad preview panel to update the
280 // view: actual size, best zoom ... after the frame is shown
281 PostSizeEvent();
282}
283
284
286{
287 m_padNetSelector->Disconnect( FILTERED_ITEM_SELECTED,
288 wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ),
289 nullptr, this );
290
291 m_page = m_notebook->GetSelection();
292
293 delete m_previewPad;
294 delete m_axisOrigin;
295}
296
297
298// Store the pad draw option during a session.
300
301
302void DIALOG_PAD_PROPERTIES::OnInitDialog( wxInitDialogEvent& event )
303{
304 m_selectedColor = COLOR4D( 1.0, 1.0, 1.0, 0.7 );
305
306 // Needed on some WM to be sure the pad is redrawn according to the final size
307 // of the canvas, with the right zoom factor
308 redraw();
309}
310
311
312void DIALOG_PAD_PROPERTIES::OnCancel( wxCommandEvent& event )
313{
314 // Mandatory to avoid m_panelShowPadGal trying to draw something
315 // in a non valid context during closing process:
317
318 // Now call default handler for wxID_CANCEL command event
319 event.Skip();
320}
321
322
324{
326 COLOR_SETTINGS* colorSettings = m_parent->GetColorSettings();
327
328 opts.m_forceDisplayCursor = false;
329
330 // Initialize the canvas to display the pad
331 m_padPreviewGAL = new PCB_DRAW_PANEL_GAL( m_boardViewPanel, -1, wxDefaultPosition,
332 wxDefaultSize, opts,
334
335 m_padPreviewSizer->Add( m_padPreviewGAL, 12, wxEXPAND | wxALL, 5 );
336
337 // Show the X and Y axis. It is useful because pad shape can have an offset
338 // or be a complex shape.
343
346 m_padPreviewGAL->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
347
348 KIGFX::VIEW_CONTROLS* parentViewControls = m_parent->GetCanvas()->GetViewControls();
349 m_padPreviewGAL->GetViewControls()->ApplySettings( parentViewControls->GetSettings() );
350
351 m_padPreviewGAL->Show();
352
354
355 // fix the pad render mode (filled/not filled)
356 auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
357
358 settings->m_ForcePadSketchModeOn = m_cbShowPadOutline->IsChecked();
359 settings->SetHighContrast( false );
360 settings->m_ContrastModeDisplay = HIGH_CONTRAST_MODE::NORMAL;
361
362 // don't show the locked item shadow in pad preview
364
365 // gives a non null grid size (0.001mm) because GAL layer does not like a 0 size grid:
366 double gridsize = 0.001 * pcbIUScale.IU_PER_MM;
367 view->GetGAL()->SetGridSize( VECTOR2D( gridsize, gridsize ) );
368
369 // And do not show the grid:
370 view->GetGAL()->SetGridVisibility( false );
371 view->GetGAL()->SetAxesEnabled( false );
372 view->Add( m_previewPad );
373 view->Add( m_axisOrigin );
374
376 Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_PAD_PROPERTIES::OnResize ) );
377}
378
379
381{
384 redraw();
385}
386
387
388void DIALOG_PAD_PROPERTIES::OnEditLayerChanged( wxCommandEvent& aEvent )
389{
390 // Save data from the previous layer
392
393 switch( m_previewPad->Padstack().Mode() )
394 {
395 default:
398 break;
399
401 switch( m_cbEditLayer->GetSelection() )
402 {
403 default:
404 case 0: m_editLayer = F_Cu; break;
405 case 1: m_editLayer = PADSTACK::INNER_LAYERS; break;
406 case 2: m_editLayer = B_Cu; break;
407 }
408 break;
409
411 {
412 int layer = m_cbEditLayer->GetSelection();
413
414 if( layer < 0 )
415 layer = 0;
416
417 if( m_editLayerCtrlMap.contains( layer ) )
418 m_editLayer = m_editLayerCtrlMap.at( layer );
419 else
421 }
422 }
423
424 // Load controls with the current layer
426
427 wxCommandEvent cmd_event;
428 OnPadShapeSelection( cmd_event );
429 OnOffsetCheckbox( cmd_event );
430
431 redraw();
432}
433
434
436{
437 // Note: use ChangeValue() to avoid generating a wxEVT_TEXT event
439
442
445}
446
447
449{
450 if( m_previewPad->GetShape( m_editLayer ) != PAD_SHAPE::ROUNDRECT
451 && m_previewPad->GetShape( m_editLayer ) != PAD_SHAPE::CHAMFERED_RECT )
452 {
453 return;
454 }
455
456 if( m_cornerRadius.GetValue() < 0 )
457 m_cornerRadiusCtrl->ChangeValue( "0" );
458
460 {
462
465
466 redraw();
467 }
468
469 if( m_initialized )
470 OnModify();
471}
472
473
475{
476 // The maximum chamfer ratio is 50% of the smallest pad side if adjacent sides
477 // are selected, or 100% of the smallest pad side if only one side is selected.
478 double baseline = 1.0;
479
480 auto considerCheckboxes = [&]( const std::vector<wxCheckBox*>& checkBoxes )
481 {
482 for( size_t ii : { 0, 1, 2, 3 } )
483 {
484 if( !checkBoxes[ii]->IsChecked() )
485 continue;
486
487 if( checkBoxes[( ii + 1 ) % 4]->IsChecked() || checkBoxes[( ii - 1 ) % 4]->IsChecked() )
488 {
489 // If two adjacent corners are selected, the maximum chamfer ratio is 50%
490 baseline = std::max( baseline, 0.5 );
491 break;
492 }
493 }
494 };
495
496
498 considerCheckboxes( { m_cbTopLeft1, m_cbTopRight1, m_cbBottomRight1, m_cbBottomLeft1 } );
499 considerCheckboxes( { m_cbTopLeft, m_cbTopRight, m_cbBottomRight, m_cbBottomLeft } );
500
501 // If only one corner is selected, the maximum chamfer ratio is 100%
502 return baseline;
503}
504
505
507{
509}
510
511
513{
514 auto updateCheckBoxes = []( const std::vector<wxCheckBox*>& aCheckBoxes )
515 {
516 for( size_t ii : { 0, 1, 2, 3 } )
517 {
518 bool disable = aCheckBoxes[( ii + 1 ) % 4]->IsChecked()
519 || aCheckBoxes[( ii + 3 ) % 4]->IsChecked();
520
521 aCheckBoxes[ii]->Enable( !disable );
522
523 if( disable )
524 aCheckBoxes[ii]->SetValue( false );
525 }
526 };
527
529 {
531 }
532
533 if( m_chamferRatio.GetDoubleValue() > 50.0 )
534 {
535 updateCheckBoxes( { m_cbTopLeft, m_cbTopRight, m_cbBottomRight, m_cbBottomLeft } );
536 }
537}
538
539
541{
542 if( m_previewPad->GetShape( m_editLayer ) != PAD_SHAPE::ROUNDRECT
543 && m_previewPad->GetShape( m_editLayer ) != PAD_SHAPE::CHAMFERED_RECT )
544 {
545 return;
546 }
547
548 wxObject* ctrl = event.GetEventObject();
549 wxString value = event.GetString();
550 bool changed = false;
551
552 if( ctrl == m_cornerRatioCtrl || ctrl == m_mixedCornerRatioCtrl )
553 {
554 double ratioPercent;
555
556 if( value.ToDouble( &ratioPercent ) )
557 {
558 // Clamp ratioPercent to acceptable value (0.0 to 50.0)
559 double maxRatio = getMaxCornerRadius();
560
561 if( ratioPercent < 0.0 )
562 {
565 }
566 else if( ratioPercent > maxRatio * 100.0 )
567 {
568 m_cornerRatio.SetDoubleValue( maxRatio * 100.0 );
569 m_mixedCornerRatio.SetDoubleValue( maxRatio * 100.0 );
570 }
571
572 if( ctrl == m_cornerRatioCtrl )
573 m_mixedCornerRatioCtrl->ChangeValue( value );
574 else
575 m_cornerRatioCtrl->ChangeValue( value );
576
577 changed = true;
578 }
579 }
580 else if( ctrl == m_chamferRatioCtrl || ctrl == m_mixedChamferRatioCtrl )
581 {
582 double ratioPercent;
583
584 if( value.ToDouble( &ratioPercent ) )
585 {
586 double maxRatio = getMaxChamferRatio();
587 // Clamp ratioPercent to acceptable value (0.0 to maxRatio)
588 if( ratioPercent < 0.0 )
589 {
592 }
593 else if( ratioPercent > maxRatio * 100.0 )
594 {
595 m_chamferRatio.SetDoubleValue( maxRatio * 100.0 );
596 m_mixedChamferRatio.SetDoubleValue( maxRatio * 100.0 );
597 }
598
599 if( ctrl == m_chamferRatioCtrl )
600 m_mixedChamferRatioCtrl->ChangeValue( value );
601 else
602 m_chamferRatioCtrl->ChangeValue( value );
603
605
606 changed = true;
607 }
608 }
609
610 if( changed && transferDataToPad( m_previewPad ) )
612
613 redraw();
614
615 if( m_initialized )
616 OnModify();
617}
618
619
621{
622 wxString msg;
623
624 // Disable pad net name wxTextCtrl if the caller is the footprint editor
625 // because nets are living only in the board managed by the board editor
627
636 m_layerECO1->SetLabel( m_board->GetLayerName( Eco1_User ) );
637 m_layerECO2->SetLabel( m_board->GetLayerName( Eco2_User ) );
639
640 VECTOR2I absPos;
641
642 if( m_currentPad )
643 {
644 absPos = m_currentPad->GetPosition();
645
646 if( FOOTPRINT* footprint = m_currentPad->GetParentFootprint() )
647 {
649
650 if( footprint->IsFlipped() )
651 {
652 // flip pad (up/down) around its position
653 m_previewPad->Flip( m_previewPad->GetPosition(), FLIP_DIRECTION::TOP_BOTTOM );
654 relPos.y = - relPos.y;
655 }
656
657 m_previewPad->SetPosition( relPos );
659
660 // Display parent footprint info
661 msg.Printf( _("Footprint %s (%s), %s, rotated %g deg"),
662 footprint->Reference().GetShownText( false ),
663 footprint->Value().GetShownText( false ),
664 footprint->IsFlipped() ? _( "back side (mirrored)" ) : _( "front side" ),
665 footprint->GetOrientation().AsDegrees() );
666
667 m_FlippedWarningSizer->Show( footprint->IsFlipped() );
668 m_parentInfo->SetLabel( msg );
669 }
670
671 m_padNumCtrl->SetValue( m_previewPad->GetNumber() );
672 }
673 else
674 {
676 m_padNumCtrl->SetValue( padTool->GetLastPadNumber() );
677
679 {
681 {
682 case FOOTPRINT_ATTR_T::FP_THROUGH_HOLE:
683 m_previewPad->SetAttribute( PAD_ATTRIB::PTH );
684
685 if( m_previewPad->GetDrillSizeX() == 0 )
687
688 break;
689
690 case FOOTPRINT_ATTR_T::FP_SMD:
692 m_previewPad->SetAttribute( PAD_ATTRIB::SMD );
693 break;
694 }
695 }
696 }
697
699
701
702 // Display current pad parameters units:
703 m_posX.ChangeValue( absPos.x );
704 m_posY.ChangeValue( absPos.y );
705
708
709 // TODO(JE) padstacks -- does this need to be saved/restored every time the layer changes?
710 // Store the initial thermal spoke angle to restore it, because some initializations
711 // can change this value (mainly after m_PadShapeSelector initializations)
712 EDA_ANGLE spokeInitialAngle = m_previewPad->GetThermalSpokeAngle();
713
715
716 m_padToDieOpt->SetValue( m_previewPad->GetPadToDieLength() != 0 );
718
721
722 if( m_previewPad->GetLocalClearance().has_value() )
724 else
725 m_clearance.ChangeValue( wxEmptyString );
726
727 if( m_previewPad->GetLocalSolderMaskMargin().has_value() )
729 else
730 m_maskMargin.ChangeValue( wxEmptyString );
731
732 if( m_previewPad->GetLocalSolderPasteMargin().has_value() )
734 else
735 m_pasteMargin.ChangeValue( wxEmptyString );
736
739 else
740 m_pasteMarginRatio.ChangeValue( wxEmptyString );
741
744 else
746
747 if( m_previewPad->GetLocalThermalGapOverride().has_value() )
749 else
751
754
764
766 {
767 default:
768 case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
769 case ZONE_CONNECTION::FULL: m_ZoneConnectionChoice->SetSelection( 1 ); break;
770 case ZONE_CONNECTION::THERMAL: m_ZoneConnectionChoice->SetSelection( 2 ); break;
771 case ZONE_CONNECTION::NONE: m_ZoneConnectionChoice->SetSelection( 3 ); break;
772 }
773
775 m_ZoneCustomPadShape->SetSelection( 1 );
776 else
777 m_ZoneCustomPadShape->SetSelection( 0 );
778
779 // Type of pad selection
780 bool aperture =
781 m_previewPad->GetAttribute() == PAD_ATTRIB::SMD && m_previewPad->IsAperturePad();
782
783 if( aperture )
784 {
785 m_padType->SetSelection( APERTURE_DLG_TYPE );
786 }
787 else
788 {
789 switch( m_previewPad->GetAttribute() )
790 {
791 case PAD_ATTRIB::PTH: m_padType->SetSelection( PTH_DLG_TYPE ); break;
792 case PAD_ATTRIB::SMD: m_padType->SetSelection( SMD_DLG_TYPE ); break;
793 case PAD_ATTRIB::CONN: m_padType->SetSelection( CONN_DLG_TYPE ); break;
794 case PAD_ATTRIB::NPTH: m_padType->SetSelection( NPTH_DLG_TYPE ); break;
795 }
796 }
797
798 switch( m_previewPad->GetProperty() )
799 {
800 case PAD_PROP::NONE: m_choiceFabProperty->SetSelection( 0 ); break;
801 case PAD_PROP::BGA: m_choiceFabProperty->SetSelection( 1 ); break;
802 case PAD_PROP::FIDUCIAL_LOCAL: m_choiceFabProperty->SetSelection( 2 ); break;
803 case PAD_PROP::FIDUCIAL_GLBL: m_choiceFabProperty->SetSelection( 3 ); break;
804 case PAD_PROP::TESTPOINT: m_choiceFabProperty->SetSelection( 4 ); break;
805 case PAD_PROP::HEATSINK: m_choiceFabProperty->SetSelection( 5 ); break;
806 case PAD_PROP::CASTELLATED: m_choiceFabProperty->SetSelection( 6 ); break;
807 case PAD_PROP::MECHANICAL: m_choiceFabProperty->SetSelection( 7 ); break;
808 case PAD_PROP::PRESSFIT: m_choiceFabProperty->SetSelection( 8 ); break;
809 }
810
811 // Ensure the pad property is compatible with the pad type
812 if( m_previewPad->GetAttribute() == PAD_ATTRIB::NPTH )
813 {
814 m_choiceFabProperty->SetSelection( 0 );
815 m_choiceFabProperty->Enable( false );
816 }
817
818 if( m_previewPad->GetDrillShape() != PAD_DRILL_SHAPE::OBLONG )
819 m_holeShapeCtrl->SetSelection( 0 );
820 else
821 m_holeShapeCtrl->SetSelection( 1 );
822
825
826 // Update some dialog widgets state (Enable/disable options):
827 wxCommandEvent cmd_event;
828 OnPadShapeSelection( cmd_event );
829 OnOffsetCheckbox( cmd_event );
830
831 // Restore thermal spoke angle to its initial value, because it can be modified
832 // by the call to OnPadShapeSelection()
833 m_previewPad->SetThermalSpokeAngle( spokeInitialAngle );
835}
836
837
839{
841
844
848
850 {
852 m_trapAxisCtrl->SetSelection( 0 );
853 }
854 else
855 {
857 m_trapAxisCtrl->SetSelection( 1 );
858 }
859
860 switch( m_previewPad->GetShape( m_editLayer ) )
861 {
862 default:
863 case PAD_SHAPE::CIRCLE: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_CIRCLE ); break;
864 case PAD_SHAPE::OVAL: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_OVAL ); break;
865 case PAD_SHAPE::RECTANGLE: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_RECT ); break;
866 case PAD_SHAPE::TRAPEZOID: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_TRAPEZOID ); break;
867 case PAD_SHAPE::ROUNDRECT: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_ROUNDRECT ); break;
868
869 case PAD_SHAPE::CHAMFERED_RECT:
872 else
874 break;
875
876 case PAD_SHAPE::CUSTOM:
877 if( m_previewPad->GetAnchorPadShape( m_editLayer ) == PAD_SHAPE::RECTANGLE )
879 else
881 break;
882 }
883
884 int chamferPositions = m_previewPad->GetChamferPositions( m_editLayer );
885
886 m_cbTopLeft->SetValue( chamferPositions & RECT_CHAMFER_TOP_LEFT );
887 m_cbTopLeft1->SetValue( chamferPositions & RECT_CHAMFER_TOP_LEFT );
888 m_cbTopRight->SetValue( chamferPositions & RECT_CHAMFER_TOP_RIGHT );
889 m_cbTopRight1->SetValue( chamferPositions & RECT_CHAMFER_TOP_RIGHT );
890 m_cbBottomLeft->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_LEFT );
891 m_cbBottomLeft1->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_LEFT );
892 m_cbBottomRight->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_RIGHT );
893 m_cbBottomRight1->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_RIGHT );
894
896}
897
898
900{
901 // NOTE: synchronize changes here with DIALOG_TRACK_VIA_PROPERTIES::afterPadstackModeChanged
902
903 wxCHECK_MSG( m_board, /* void */, "Expected valid board in afterPadstackModeChanged" );
904 m_cbEditLayer->Clear();
905
906 switch( m_previewPad->Padstack().Mode() )
907 {
909 m_cbPadstackMode->SetSelection( 0 );
910 m_cbEditLayer->Append( m_board->GetLayerName( F_Cu ) );
911 m_cbEditLayer->Disable();
913 m_editLayerCtrlMap = { { 0, F_Cu } };
914 break;
915
917 {
918 m_cbPadstackMode->SetSelection( 1 );
919 m_cbEditLayer->Enable();
920
921 std::vector choices = {
923 _( "Inner Layers" ),
925 };
926
927 m_cbEditLayer->Append( choices );
928
930 { 0, F_Cu },
932 { 2, B_Cu }
933 };
934
935 if( m_editLayer != F_Cu && m_editLayer != B_Cu )
937
938 break;
939 }
940
942 {
943 m_cbPadstackMode->SetSelection( 2 );
944 m_cbEditLayer->Enable();
946
947 for( PCB_LAYER_ID layer : layers.UIOrder() )
948 {
949 int idx = m_cbEditLayer->Append( m_board->GetLayerName( layer ) );
950 m_editLayerCtrlMap[idx] = layer;
951 }
952
953 break;
954 }
955 }
956
957 for( const auto& [idx, layer] : m_editLayerCtrlMap )
958 {
959 if( layer == m_editLayer )
960 {
961 m_cbEditLayer->SetSelection( idx );
962 break;
963 }
964 }
965}
966
967
968void DIALOG_PAD_PROPERTIES::OnResize( wxSizeEvent& event )
969{
970 redraw();
971 event.Skip();
972}
973
974
975void DIALOG_PAD_PROPERTIES::onChangePadMode( wxCommandEvent& event )
976{
978
980
981 // fix the pad render mode (filled/not filled)
982 auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
983
984 settings->m_ForcePadSketchModeOn = m_cbShowPadOutline->IsChecked();
985 settings->SetHighContrast( false );
986 settings->m_ContrastModeDisplay = HIGH_CONTRAST_MODE::NORMAL;
987
988 redraw();
989}
990
991
993{
994 switch( m_PadShapeSelector->GetSelection() )
995 {
999 m_shapePropsBook->SetSelection( 0 );
1000 break;
1001
1003 m_shapePropsBook->SetSelection( 1 );
1004 break;
1005
1007 {
1008 m_shapePropsBook->SetSelection( 2 );
1009
1010 // Reasonable defaults
1012 {
1013 const double ipcRadiusRatio =
1015 m_cornerRatio.ChangeDoubleValue( ipcRadiusRatio * 100 );
1016 }
1017
1018 break;
1019 }
1020
1022 m_shapePropsBook->SetSelection( 3 );
1023
1024 // Reasonable default
1027
1028 // Ensure the displayed value is up to date:
1030
1031 // A reasonable default is one corner chamfered (usual for some SMD pads).
1032 if( !m_cbTopLeft->GetValue() && !m_cbTopRight->GetValue()
1033 && !m_cbBottomLeft->GetValue() && !m_cbBottomRight->GetValue() )
1034 {
1035 m_cbTopLeft->SetValue( true );
1036 m_cbTopRight->SetValue( false );
1037 m_cbBottomLeft->SetValue( false );
1038 m_cbBottomRight->SetValue( false );
1039 }
1040
1041 break;
1042
1044 m_shapePropsBook->SetSelection( 4 );
1045
1046 // Reasonable defaults
1049 {
1050 const double ipcRadiusRatio =
1054 }
1055
1056 // Ensure the displayed values are up to date:
1059 break;
1060
1061 case CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR: // PAD_SHAPE::CUSTOM, circular anchor
1062 case CHOICE_SHAPE_CUSTOM_RECT_ANCHOR: // PAD_SHAPE::CUSTOM, rect anchor
1063 m_shapePropsBook->SetSelection( 0 );
1064 break;
1065 }
1066
1067 // Note: must do this before enabling/disabling m_sizeY as we're using that as a flag to see
1068 // what the last shape was.
1069 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CIRCLE )
1070 {
1071 if( m_sizeYCtrl->IsEnabled() && m_spokeAngle.GetAngleValue() == ANGLE_90 )
1073 }
1074 else
1075 {
1076 if( !m_sizeYCtrl->IsEnabled() && m_spokeAngle.GetAngleValue() == ANGLE_45 )
1078 }
1079
1080 // Readjust props book size
1081 wxSize size = m_shapePropsBook->GetSize();
1082 size.y = m_shapePropsBook->GetPage( m_shapePropsBook->GetSelection() )->GetBestSize().y;
1083 m_shapePropsBook->SetMaxSize( size );
1084
1087
1088 m_offsetShapeOpt->Enable( m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CIRCLE );
1089
1090 if( !m_offsetShapeOpt->IsEnabled() )
1091 m_offsetShapeOpt->SetValue( false );
1092
1093 // Show/hide controls depending on m_offsetShapeOpt being enabled
1094 m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
1095 m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
1096
1099
1100 for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
1101 m_notebook->GetPage( i )->Layout();
1102
1103 // Resize the dialog if its height is too small to show all widgets:
1104 if( m_MainSizer->GetSize().y < m_MainSizer->GetMinSize().y )
1105 m_MainSizer->SetSizeHints( this );
1106
1108 redraw();
1109
1110 if( m_initialized )
1111 OnModify();
1112}
1113
1114
1116{
1119 redraw();
1120
1121 if( m_initialized )
1122 OnModify();
1123}
1124
1125
1126void DIALOG_PAD_PROPERTIES::PadOrientEvent( wxCommandEvent& event )
1127{
1129 redraw();
1130
1131 if( m_initialized )
1132 OnModify();
1133}
1134
1135
1137{
1138 m_rbCopperLayersSel->Clear();
1139
1140 switch( m_padType->GetSelection() )
1141 {
1142 case PTH_DLG_TYPE:
1143 m_rbCopperLayersSel->Append( _( "All copper layers" ) );
1144 m_rbCopperLayersSel->Append( wxString::Format( _( "%s, %s and connected layers" ),
1146 m_board->GetLayerName( B_Cu ) ) );
1147 m_rbCopperLayersSel->Append( _( "Connected layers only" ) );
1148 m_rbCopperLayersSel->Append( _( "None" ) );
1149 break;
1150
1151 case NPTH_DLG_TYPE:
1152 m_rbCopperLayersSel->Append( wxString::Format( _( "%s and %s" ),
1154 m_board->GetLayerName( B_Cu ) ) );
1157 m_rbCopperLayersSel->Append( _( "None" ) );
1158 break;
1159
1160 case SMD_DLG_TYPE:
1161 case CONN_DLG_TYPE:
1164 break;
1165
1166 case APERTURE_DLG_TYPE:
1167 m_rbCopperLayersSel->Append( _( "None" ) );
1168 break;
1169 }
1170}
1171
1172
1173void DIALOG_PAD_PROPERTIES::PadTypeSelected( wxCommandEvent& event )
1174{
1175 bool hasHole = true;
1176 bool hasConnection = true;
1177 bool hasProperty = true;
1178
1179 switch( m_padType->GetSelection() )
1180 {
1181 case PTH_DLG_TYPE: hasHole = true; hasConnection = true; hasProperty = true; break;
1182 case SMD_DLG_TYPE: hasHole = false; hasConnection = true; hasProperty = true; break;
1183 case CONN_DLG_TYPE: hasHole = false; hasConnection = true; hasProperty = true; break;
1184 case NPTH_DLG_TYPE: hasHole = true; hasConnection = false; hasProperty = false; break;
1185 case APERTURE_DLG_TYPE: hasHole = false; hasConnection = false; hasProperty = true; break;
1186 }
1187
1188 // Update Layers dropdown list and selects the "best" layer set for the new pad type:
1191
1192 m_gbSizerHole->Show( hasHole );
1193 m_staticline71->Show( hasHole );
1194
1195 if( !hasHole )
1196 {
1197 m_holeX.ChangeValue( 0 );
1198 m_holeY.ChangeValue( 0 );
1199 }
1200 else if( m_holeX.GetValue() == 0 )
1201 {
1202 if( m_currentPad )
1203 {
1206 }
1207 else
1208 {
1210 }
1211 }
1212
1213 if( !hasConnection )
1214 {
1215 m_padNumCtrl->ChangeValue( wxEmptyString );
1217 m_padToDieOpt->SetValue( false );
1218 m_padToDieDelayOpt->SetValue( false );
1219 }
1220 else if( m_padNumCtrl->GetValue().IsEmpty() && m_currentPad )
1221 {
1222 m_padNumCtrl->ChangeValue( m_currentPad->GetNumber() );
1224 }
1225
1226 if( !hasProperty )
1227 m_choiceFabProperty->SetSelection( 0 );
1228
1229 m_choiceFabProperty->Enable( hasProperty );
1230
1232
1233 // For now, padstack controls only enabled for PTH pads
1234 bool enablePadstack = m_padType->GetSelection() == PTH_DLG_TYPE;
1235 m_padstackControls->Show( enablePadstack );
1236
1237 if( !enablePadstack )
1238 {
1239 m_editLayer = F_Cu;
1241 }
1242
1243 // Layout adjustment is needed if the hole details got shown/hidden
1244 m_LeftBoxSizer->Layout();
1245 redraw();
1246
1247 if( m_initialized )
1248 OnModify();
1249}
1250
1251
1252void DIALOG_PAD_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
1253{
1254 bool hasHole = true;
1255 bool hasConnection = true;
1256
1257 switch( m_padType->GetSelection() )
1258 {
1259 case PTH_DLG_TYPE: /* PTH */ hasHole = true; hasConnection = true; break;
1260 case SMD_DLG_TYPE: /* SMD */ hasHole = false; hasConnection = true; break;
1261 case CONN_DLG_TYPE: /* CONN */ hasHole = false; hasConnection = true; break;
1262 case NPTH_DLG_TYPE: /* NPTH */ hasHole = true; hasConnection = false; break;
1263 case APERTURE_DLG_TYPE: /* Aperture */ hasHole = false; hasConnection = false; break;
1264 }
1265
1266 // Enable/disable hole controls
1267 m_holeShapeLabel->Enable( hasHole );
1268 m_holeShapeCtrl->Enable( hasHole );
1269 m_holeX.Enable( hasHole );
1270 m_holeY.Enable( hasHole && m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_OVAL );
1271
1272 // Enable/disable number and net
1273 m_padNumLabel->Enable( hasConnection );
1274 m_padNumCtrl->Enable( hasConnection );
1275
1276 if( m_padNetLabel->IsShown() )
1277 {
1278 m_padNetLabel->Enable( hasConnection && m_canEditNetName && m_currentPad );
1279 m_padNetSelector->Enable( hasConnection && m_canEditNetName && m_currentPad );
1280 }
1281
1282 // Enable/disable pad length-to-die
1283 m_padToDieOpt->Enable( hasConnection );
1284 m_padToDieDelayOpt->Enable( hasConnection );
1285
1286 if( !m_padToDieOpt->IsEnabled() )
1287 m_padToDieOpt->SetValue( false );
1288
1289 if( !m_padToDieDelayOpt->IsEnabled() )
1290 m_padToDieDelayOpt->SetValue( false );
1291
1292 // We can show/hide this here because it doesn't require the layout to be refreshed.
1293 // All the others have to be done in their event handlers because doing a layout here
1294 // causes infinite looping on MSW.
1295 m_padToDie.Show( m_padToDieOpt->GetValue() );
1297
1298 // Enable/disable Copper Layers control
1299 m_rbCopperLayersSel->Enable( m_padType->GetSelection() != APERTURE_DLG_TYPE );
1300
1302
1303 switch( m_padType->GetSelection() )
1304 {
1305 case PTH_DLG_TYPE:
1306 if( !cu_set.any() )
1307 m_stackupImagesBook->SetSelection( 3 );
1308 else if( !m_previewPad->GetRemoveUnconnected() )
1309 m_stackupImagesBook->SetSelection( 0 );
1310 else if( m_previewPad->GetKeepTopBottom() )
1311 m_stackupImagesBook->SetSelection( 1 );
1312 else
1313 m_stackupImagesBook->SetSelection( 2 );
1314
1315 break;
1316
1317 case NPTH_DLG_TYPE:
1318 if( cu_set.test( F_Cu ) && cu_set.test( B_Cu ) )
1319 m_stackupImagesBook->SetSelection( 4 );
1320 else if( cu_set.test( F_Cu ) )
1321 m_stackupImagesBook->SetSelection( 5 );
1322 else if( cu_set.test( B_Cu ) )
1323 m_stackupImagesBook->SetSelection( 6 );
1324 else
1325 m_stackupImagesBook->SetSelection( 7 );
1326
1327 break;
1328
1329 case SMD_DLG_TYPE:
1330 case CONN_DLG_TYPE:
1331 case APERTURE_DLG_TYPE:
1332 m_stackupImagesBook->ChangeSelection( 3 );
1333 break;
1334 }
1335
1337}
1338
1339
1341{
1342 event.Enable( !m_board->LegacyTeardrops() );
1343}
1344
1345
1347{
1348 bool isOnCopperLayer = ( m_previewPad->GetLayerSet() & LSET::AllCuMask() ).any();
1349 m_nonCopperWarningBook->ChangeSelection( isOnCopperLayer ? 0 : 1 );
1350}
1351
1352
1353void DIALOG_PAD_PROPERTIES::updatePadLayersList( LSET layer_mask, bool remove_unconnected,
1354 bool keep_top_bottom )
1355{
1357
1358 switch( m_padType->GetSelection() )
1359 {
1360 case PTH_DLG_TYPE:
1361 if( !layer_mask.any() )
1362 layer_mask = PAD::PTHMask();
1363
1364 if( !( layer_mask & LSET::AllCuMask() ).any() )
1365 m_rbCopperLayersSel->SetSelection( 3 );
1366 else if( !remove_unconnected )
1367 m_rbCopperLayersSel->SetSelection( 0 );
1368 else if( keep_top_bottom )
1369 m_rbCopperLayersSel->SetSelection( 1 );
1370 else
1371 m_rbCopperLayersSel->SetSelection( 2 );
1372
1373 break;
1374
1375 case SMD_DLG_TYPE:
1376 if( !layer_mask.any() )
1377 layer_mask = PAD::SMDMask();
1378
1379 if( layer_mask.test( F_Cu ) )
1380 m_rbCopperLayersSel->SetSelection( 0 );
1381 else
1382 m_rbCopperLayersSel->SetSelection( 1 );
1383
1384 break;
1385
1386 case CONN_DLG_TYPE:
1387 if( !layer_mask.any() )
1388 layer_mask = PAD::ConnSMDMask();
1389
1390 if( layer_mask.test( F_Cu ) )
1391 m_rbCopperLayersSel->SetSelection( 0 );
1392 else
1393 m_rbCopperLayersSel->SetSelection( 1 );
1394
1395 break;
1396
1397 case NPTH_DLG_TYPE:
1398 if( !layer_mask.any() )
1399 layer_mask = PAD::UnplatedHoleMask();
1400
1401 if( layer_mask.test( F_Cu ) && layer_mask.test( B_Cu ) )
1402 m_rbCopperLayersSel->SetSelection( 0 );
1403 else if( layer_mask.test( F_Cu ) )
1404 m_rbCopperLayersSel->SetSelection( 1 );
1405 else if( layer_mask.test( B_Cu ) )
1406 m_rbCopperLayersSel->SetSelection( 2 );
1407 else
1408 m_rbCopperLayersSel->SetSelection( 3 );
1409
1410 break;
1411
1412 case APERTURE_DLG_TYPE:
1413 if( !layer_mask.any() )
1414 layer_mask = PAD::ApertureMask();
1415
1416 m_rbCopperLayersSel->SetSelection( 0 );
1417 break;
1418 }
1419
1420 m_layerFrontAdhesive->SetValue( layer_mask[F_Adhes] );
1421 m_layerBackAdhesive->SetValue( layer_mask[B_Adhes] );
1422
1423 m_layerFrontPaste->SetValue( layer_mask[F_Paste] );
1424 m_layerBackPaste->SetValue( layer_mask[B_Paste] );
1425
1426 m_layerFrontSilk->SetValue( layer_mask[F_SilkS] );
1427 m_layerBackSilk->SetValue( layer_mask[B_SilkS] );
1428
1429 m_layerFrontMask->SetValue( layer_mask[F_Mask] );
1430 m_layerBackMask->SetValue( layer_mask[B_Mask] );
1431
1432 m_layerECO1->SetValue( layer_mask[Eco1_User] );
1433 m_layerECO2->SetValue( layer_mask[Eco2_User] );
1434
1435 m_layerUserDwgs->SetValue( layer_mask[Dwgs_User] );
1436}
1437
1438
1440{
1441 bool retVal = DIALOG_SHIM::Show( aShow );
1442
1443 if( aShow )
1444 {
1445 // It *should* work to set the stackup bitmap in the constructor, but it doesn't.
1446 // wxWidgets needs to have these set when the panel is visible for some reason.
1447 // https://gitlab.com/kicad/code/kicad/-/issues/5534
1448 m_stackupImage0->SetBitmap( KiBitmapBundle( BITMAPS::pads_reset_unused ) );
1449 m_stackupImage1->SetBitmap( KiBitmapBundle( BITMAPS::pads_remove_unused_keep_bottom ) );
1450 m_stackupImage2->SetBitmap( KiBitmapBundle( BITMAPS::pads_remove_unused ) );
1451 m_stackupImage4->SetBitmap( KiBitmapBundle( BITMAPS::pads_npth_top_bottom ) );
1452 m_stackupImage5->SetBitmap( KiBitmapBundle( BITMAPS::pads_npth_top ) );
1453 m_stackupImage6->SetBitmap( KiBitmapBundle( BITMAPS::pads_npth_bottom ) );
1454 m_stackupImage7->SetBitmap( KiBitmapBundle( BITMAPS::pads_npth ) );
1455
1456 Layout();
1457 }
1458
1459 return retVal;
1460}
1461
1462
1463void DIALOG_PAD_PROPERTIES::OnSetCopperLayers( wxCommandEvent& event )
1464{
1466 redraw();
1467
1468 if( m_initialized )
1469 OnModify();
1470}
1471
1472
1473void DIALOG_PAD_PROPERTIES::OnSetLayers( wxCommandEvent& event )
1474{
1476 redraw();
1477
1478 if( m_initialized )
1479 OnModify();
1480}
1481
1482
1484{
1486
1487 wxArrayString error_msgs;
1488 wxArrayString warning_msgs;
1489
1491 [&]( int errorCode, const wxString& msg )
1492 {
1493 if( errorCode == DRCE_PADSTACK_INVALID )
1494 error_msgs.Add( _( "Error: " ) + msg );
1495 else if( errorCode == DRCE_PADSTACK )
1496 warning_msgs.Add( _( "Warning: " ) + msg );
1497 else if( errorCode == DRCE_PAD_TH_WITH_NO_HOLE )
1498 error_msgs.Add( _( "Error: Through hole pad has no hole." ) );
1499 } );
1500
1501 if( error_msgs.GetCount() || warning_msgs.GetCount() )
1502 {
1503 wxString title = error_msgs.GetCount() ? _( "Pad Properties Errors" )
1504 : _( "Pad Properties Warnings" );
1505 HTML_MESSAGE_BOX dlg( this, title );
1506
1507 wxArrayString msgs = error_msgs;
1508
1509 for( const wxString& msg : warning_msgs )
1510 msgs.Add( msg );
1511
1512 dlg.ListSet( msgs );
1513
1514 dlg.ShowModal();
1515 }
1516
1517 return error_msgs.GetCount() == 0;
1518}
1519
1520
1522{
1523 if( !m_initialized )
1524 return;
1525
1527 KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( view->GetPainter() );
1528 KIGFX::PCB_RENDER_SETTINGS* settings = painter->GetSettings();
1529
1531
1532 // The layer used to place primitive items selected when editing custom pad shapes
1533 // we use here a layer never used in a pad:
1534 #define SELECTED_ITEMS_LAYER Dwgs_User
1535
1536 view->ClearTopLayers();
1538 view->SetTopLayer( m_editLayer );
1540
1541 static const std::vector<int> topLayers = {
1546 };
1547
1548 for( int layer : topLayers )
1549 view->SetTopLayer( layer );
1550
1552
1553 view->Update( m_previewPad );
1554
1555 // delete previous items if highlight list
1556 while( m_highlight.size() )
1557 {
1558 delete m_highlight.back(); // the dtor also removes item from view
1559 m_highlight.pop_back();
1560 }
1561
1562 BOX2I bbox = m_previewPad->ViewBBox();
1563
1564 if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
1565 {
1566 // The origin always goes in the middle of the canvas; we want offsetting the pad
1567 // shape to move the pad, not the hole
1568 bbox.Move( -m_previewPad->GetPosition() );
1569 int maxXExtent = std::max( abs( bbox.GetLeft() ), abs( bbox.GetRight() ) );
1570 int maxYExtent = std::max( abs( bbox.GetTop() ), abs( bbox.GetBottom() ) );
1571
1572 // Don't blow up the GAL on too-large numbers
1573 if( maxXExtent > INT_MAX / 4 )
1574 maxXExtent = INT_MAX / 4;
1575
1576 if( maxYExtent > INT_MAX / 4 )
1577 maxYExtent = INT_MAX / 4;
1578
1579 BOX2D viewBox( m_previewPad->GetPosition(), {0, 0} );
1580 BOX2D canvasBox( m_previewPad->GetPosition(), {0, 0} );
1581 viewBox.Inflate( maxXExtent * 1.4, maxYExtent * 1.4 ); // add a margin
1582 canvasBox.Inflate( maxXExtent * 2.0, maxYExtent * 2.0 );
1583
1584 view->SetBoundary( canvasBox );
1585
1586 // Autozoom
1587 view->SetViewport( viewBox );
1588
1591 }
1592}
1593
1594
1596{
1597 if( !wxDialog::TransferDataToWindow() )
1598 return false;
1599
1600 if( !m_panelGeneral->TransferDataToWindow() )
1601 return false;
1602
1603 if( !m_localSettingsPanel->TransferDataToWindow() )
1604 return false;
1605
1606 return true;
1607}
1608
1609
1611{
1612 BOARD_COMMIT commit( m_parent );
1613
1614 if( !wxDialog::TransferDataFromWindow() )
1615 return false;
1616
1617 if( !m_panelGeneral->TransferDataFromWindow() )
1618 return false;
1619
1620 if( !m_localSettingsPanel->TransferDataFromWindow() )
1621 return false;
1622
1623 if( !padValuesOK() )
1624 return false;
1625
1627 return false;
1628
1630
1632 padTool->SetLastPadNumber( m_masterPad->GetNumber() );
1633
1634 // m_masterPad is a pattern: ensure there is no net for this pad:
1636
1637 if( !m_currentPad ) // Set current Pad parameters
1638 return true;
1639
1640 commit.Modify( m_currentPad );
1641
1642 // Update values
1643
1644 // transferDataToPad only handles the current edit layer, so m_masterPad isn't accurate
1645 // TODO(JE) this could be cleaner
1647
1654
1655 int padNetcode = NETINFO_LIST::UNCONNECTED;
1656
1657 // For PAD_ATTRIB::NPTH, ensure there is no net name selected
1658 if( m_masterPad->GetAttribute() != PAD_ATTRIB::NPTH )
1659 padNetcode = m_padNetSelector->GetSelectedNetcode();
1660
1661 m_currentPad->SetNetCode( padNetcode );
1662
1664
1665 // Set the fabrication property:
1667
1668 // define the way the clearance area is defined in zones
1670
1672 {
1673 // flip pad (up/down) around its position
1674 m_currentPad->Flip( m_currentPad->GetPosition(), FLIP_DIRECTION::TOP_BOTTOM );
1675 }
1676
1678
1680
1681 // redraw the area where the pad was
1683
1684 commit.Push( _( "Edit Pad Properties" ) );
1685
1686 return true;
1687}
1688
1689
1691{
1692 PAD_PROP prop = PAD_PROP::NONE;
1693
1694 switch( m_choiceFabProperty->GetSelection() )
1695 {
1696 case 0: prop = PAD_PROP::NONE; break;
1697 case 1: prop = PAD_PROP::BGA; break;
1698 case 2: prop = PAD_PROP::FIDUCIAL_LOCAL; break;
1699 case 3: prop = PAD_PROP::FIDUCIAL_GLBL; break;
1700 case 4: prop = PAD_PROP::TESTPOINT; break;
1701 case 5: prop = PAD_PROP::HEATSINK; break;
1702 case 6: prop = PAD_PROP::CASTELLATED; break;
1703 case 7: prop = PAD_PROP::MECHANICAL; break;
1704 case 8: prop = PAD_PROP::PRESSFIT; break;
1705 }
1706
1707 return prop;
1708}
1709
1710
1712{
1713 if( m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_CIRCLE )
1714 {
1715 m_holeXLabel->SetLabel( _( "Diameter:" ) );
1716 m_holeY.Show( false );
1717 }
1718 else
1719 {
1720 m_holeXLabel->SetLabel( _( "Hole size X:" ) );
1721 m_holeY.Show( true );
1722 }
1723
1724 m_holeXLabel->GetParent()->Layout();
1725}
1726
1727
1729{
1730 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CIRCLE
1732 {
1733 m_sizeXLabel->SetLabel( _( "Diameter:" ) );
1734 m_sizeY.Show( false );
1735 m_bitmapTeardrop->SetBitmap( KiBitmapBundle( BITMAPS::teardrop_sizes ) );
1736 m_minTrackWidthHint->SetLabel( _( "d" ) );
1737 m_stLenPercentHint->SetLabel( _( "d" ) );
1738 m_stWidthPercentHint->SetLabel( _( "d" ) );
1739 }
1740 else
1741 {
1742 m_sizeXLabel->SetLabel( _( "Pad size X:" ) );
1743 m_sizeY.Show( true );
1744 m_bitmapTeardrop->SetBitmap( KiBitmapBundle( BITMAPS::teardrop_rect_sizes ) );
1745 m_minTrackWidthHint->SetLabel( _( "w" ) );
1746 m_stLenPercentHint->SetLabel( _( "w" ) );
1747 m_stWidthPercentHint->SetLabel( _( "w" ) );
1748 }
1749
1750 m_sizeXLabel->GetParent()->Layout();
1751 resetSize();
1752 Layout();
1753 m_MainSizer->Fit( this );
1754}
1755
1756
1758{
1759 if( !Validate() )
1760 return false;
1761
1762 if( !m_panelGeneral->Validate() )
1763 return false;
1764
1765 if( !m_localSettingsPanel->Validate() )
1766 return false;
1767
1768 if( !m_spokeWidth.Validate( 0, INT_MAX ) )
1769 return false;
1770
1771 switch( m_cbPadstackMode->GetSelection() )
1772 {
1773 default:
1774 case 0: aPad->Padstack().SetMode( PADSTACK::MODE::NORMAL ); break;
1775 case 1: aPad->Padstack().SetMode( PADSTACK::MODE::FRONT_INNER_BACK ); break;
1776 case 2: aPad->Padstack().SetMode( PADSTACK::MODE::CUSTOM ); break;
1777 }
1778
1779 aPad->SetAttribute( code_type[m_padType->GetSelection()] );
1780 aPad->SetShape( m_editLayer, code_shape[m_PadShapeSelector->GetSelection()] );
1781
1783 aPad->SetAnchorPadShape( m_editLayer, PAD_SHAPE::RECTANGLE );
1784 else
1785 aPad->SetAnchorPadShape( m_editLayer, PAD_SHAPE::CIRCLE );
1786
1787 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::CUSTOM )
1789
1790 aPad->GetTeardropParams().m_Enabled = m_cbTeardrops->GetValue();
1797 aPad->GetTeardropParams().m_CurvedEdges = m_curvedEdges->GetValue();
1799
1800 // Read pad clearances values:
1801 if( m_clearance.IsNull() )
1802 aPad->SetLocalClearance( {} );
1803 else
1805
1806 if( m_maskMargin.IsNull() )
1807 aPad->SetLocalSolderMaskMargin( {} );
1808 else
1810
1811 if( m_pasteMargin.IsNull() )
1812 aPad->SetLocalSolderPasteMargin( {} );
1813 else
1815
1818 else
1820
1821 if( m_spokeWidth.IsNull() )
1823 else
1825
1826 if( m_thermalGap.IsNull() )
1827 aPad->SetLocalThermalGapOverride( {} );
1828 else
1830
1832
1833 // And rotation
1835
1836 switch( m_ZoneConnectionChoice->GetSelection() )
1837 {
1838 default:
1839 case 0: aPad->SetLocalZoneConnection( ZONE_CONNECTION::INHERITED ); break;
1840 case 1: aPad->SetLocalZoneConnection( ZONE_CONNECTION::FULL ); break;
1841 case 2: aPad->SetLocalZoneConnection( ZONE_CONNECTION::THERMAL ); break;
1842 case 3: aPad->SetLocalZoneConnection( ZONE_CONNECTION::NONE ); break;
1843 }
1844
1846
1847 if( FOOTPRINT* fp = aPad->GetParentFootprint() )
1848 {
1849 pos -= fp->GetPosition();
1850 RotatePoint( pos, -fp->GetOrientation() );
1851 }
1852
1853 aPad->SetPosition( pos );
1854
1855 if( m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_CIRCLE )
1856 {
1857 aPad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
1859 }
1860 else
1861 {
1862 aPad->SetDrillShape( PAD_DRILL_SHAPE::OBLONG );
1864 }
1865
1866 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::CIRCLE )
1868 else
1870
1871 // For a trapezoid, test delta value (be sure delta is not too large for pad size)
1872 // remember DeltaSize.x is the Y size variation
1873 bool error = false;
1874 VECTOR2I delta( 0, 0 );
1875
1876 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::TRAPEZOID )
1877 {
1878 // For a trapezoid, only one of delta.x or delta.y is not 0, depending on axis.
1879 if( m_trapAxisCtrl->GetSelection() == 0 )
1881 else
1883
1884 if( delta.x < 0 && delta.x < -aPad->GetSize( m_editLayer ).y )
1885 {
1886 delta.x = -aPad->GetSize( m_editLayer ).y + 2;
1887 error = true;
1888 }
1889
1890 if( delta.x > 0 && delta.x > aPad->GetSize( m_editLayer ).y )
1891 {
1892 delta.x = aPad->GetSize( m_editLayer ).y - 2;
1893 error = true;
1894 }
1895
1896 if( delta.y < 0 && delta.y < -aPad->GetSize( m_editLayer ).x )
1897 {
1898 delta.y = -aPad->GetSize( m_editLayer ).x + 2;
1899 error = true;
1900 }
1901
1902 if( delta.y > 0 && delta.y > aPad->GetSize( m_editLayer ).x )
1903 {
1904 delta.y = aPad->GetSize( m_editLayer ).x - 2;
1905 error = true;
1906 }
1907 }
1908
1909 aPad->SetDelta( m_editLayer, delta );
1910
1911 if( m_offsetShapeOpt->GetValue() )
1913 else
1914 aPad->SetOffset( m_editLayer, VECTOR2I() );
1915
1916 // Read pad length die
1917 if( m_padToDieOpt->GetValue() )
1919 else
1920 aPad->SetPadToDieLength( 0 );
1921
1922 if( m_padToDieDelayOpt->GetValue() )
1924 else
1925 aPad->SetPadToDieDelay( 0 );
1926
1927 aPad->SetNumber( m_padNumCtrl->GetValue() );
1929
1930 int chamfers = 0;
1931
1932 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_RECT )
1933 {
1934 if( m_cbTopLeft->GetValue() )
1935 chamfers |= RECT_CHAMFER_TOP_LEFT;
1936
1937 if( m_cbTopRight->GetValue() )
1938 chamfers |= RECT_CHAMFER_TOP_RIGHT;
1939
1940 if( m_cbBottomLeft->GetValue() )
1941 chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1942
1943 if( m_cbBottomRight->GetValue() )
1944 chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1945 }
1946 else if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT )
1947 {
1948 if( m_cbTopLeft1->GetValue() )
1949 chamfers |= RECT_CHAMFER_TOP_LEFT;
1950
1951 if( m_cbTopRight1->GetValue() )
1952 chamfers |= RECT_CHAMFER_TOP_RIGHT;
1953
1954 if( m_cbBottomLeft1->GetValue() )
1955 chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1956
1957 if( m_cbBottomRight1->GetValue() )
1958 chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1959 }
1960
1961 aPad->SetChamferPositions( m_editLayer, chamfers );
1962
1963 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::CUSTOM )
1964 {
1965 // The pad custom has a "anchor pad" (a basic shape: round or rect pad)
1966 // that is the minimal area of this pad, and is useful to ensure a hole
1967 // diameter is acceptable, and is used in Gerber files as flashed area
1968 // reference
1969 if( aPad->GetAnchorPadShape( m_editLayer ) == PAD_SHAPE::CIRCLE )
1971 }
1972
1973 // Define the way the clearance area is defined in zones. Since all non-custom pad
1974 // shapes are convex to begin with, this really only makes any difference for custom
1975 // pad shapes.
1976 aPad->SetCustomShapeInZoneOpt( m_ZoneCustomPadShape->GetSelection() == 0 ?
1979
1980 switch( aPad->GetAttribute() )
1981 {
1982 case PAD_ATTRIB::PTH:
1983 break;
1984
1985 case PAD_ATTRIB::CONN:
1986 case PAD_ATTRIB::SMD:
1987 // SMD and PAD_ATTRIB::CONN has no hole.
1988 // basically, SMD and PAD_ATTRIB::CONN are same type of pads
1989 // PAD_ATTRIB::CONN has just a default non technical layers that differs from SMD
1990 // and are intended to be used in virtual edge board connectors
1991 // However we can accept a non null offset,
1992 // mainly to allow complex pads build from a set of basic pad shapes
1993 aPad->SetDrillSize( VECTOR2I( 0, 0 ) );
1994 break;
1995
1996 case PAD_ATTRIB::NPTH:
1997 // Mechanical purpose only:
1998 // no net name, no pad name allowed
1999 aPad->SetNumber( wxEmptyString );
2001 break;
2002
2003 default:
2004 wxFAIL_MSG( wxT( "DIALOG_PAD_PROPERTIES::transferDataToPad: unknown pad type" ) );
2005 break;
2006 }
2007
2008 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::ROUNDRECT )
2009 {
2011 }
2012 else if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::CHAMFERED_RECT )
2013 {
2015 {
2018 }
2019 else // Choice is CHOICE_SHAPE_CHAMFERED_RECT, no rounded corner
2020 {
2023 }
2024 }
2025
2027
2028 LSET padLayerMask = LSET();
2029 int copperLayersChoice = m_rbCopperLayersSel->GetSelection();
2030
2032
2033 switch( m_padType->GetSelection() )
2034 {
2035 case PTH_DLG_TYPE:
2036 switch( copperLayersChoice )
2037 {
2038 case 0:
2039 // All copper layers
2040 padLayerMask |= LSET::AllCuMask();
2041 break;
2042
2043 case 1:
2044 // Front, back and connected
2045 padLayerMask |= LSET::AllCuMask();
2047 break;
2048
2049 case 2:
2050 // Connected only
2051 padLayerMask |= LSET::AllCuMask();
2053 break;
2054
2055 case 3:
2056 // No copper layers
2057 break;
2058 }
2059
2060 break;
2061
2062 case NPTH_DLG_TYPE:
2063 switch( copperLayersChoice )
2064 {
2065 case 0: padLayerMask.set( F_Cu ).set( B_Cu ); break;
2066 case 1: padLayerMask.set( F_Cu ); break;
2067 case 2: padLayerMask.set( B_Cu ); break;
2068 default: break;
2069 }
2070
2071 break;
2072
2073 case SMD_DLG_TYPE:
2074 case CONN_DLG_TYPE:
2075 switch( copperLayersChoice )
2076 {
2077 case 0: padLayerMask.set( F_Cu ); break;
2078 case 1: padLayerMask.set( B_Cu ); break;
2079 }
2080
2081 break;
2082
2083 case APERTURE_DLG_TYPE:
2084 // no copper layers
2085 break;
2086 }
2087
2088 if( m_layerFrontAdhesive->GetValue() )
2089 padLayerMask.set( F_Adhes );
2090
2091 if( m_layerBackAdhesive->GetValue() )
2092 padLayerMask.set( B_Adhes );
2093
2094 if( m_layerFrontPaste->GetValue() )
2095 padLayerMask.set( F_Paste );
2096
2097 if( m_layerBackPaste->GetValue() )
2098 padLayerMask.set( B_Paste );
2099
2100 if( m_layerFrontSilk->GetValue() )
2101 padLayerMask.set( F_SilkS );
2102
2103 if( m_layerBackSilk->GetValue() )
2104 padLayerMask.set( B_SilkS );
2105
2106 if( m_layerFrontMask->GetValue() )
2107 padLayerMask.set( F_Mask );
2108
2109 if( m_layerBackMask->GetValue() )
2110 padLayerMask.set( B_Mask );
2111
2112 if( m_layerECO1->GetValue() )
2113 padLayerMask.set( Eco1_User );
2114
2115 if( m_layerECO2->GetValue() )
2116 padLayerMask.set( Eco2_User );
2117
2118 if( m_layerUserDwgs->GetValue() )
2119 padLayerMask.set( Dwgs_User );
2120
2121 aPad->SetLayerSet( padLayerMask );
2122
2123 return !error;
2124}
2125
2126
2127void DIALOG_PAD_PROPERTIES::OnOffsetCheckbox( wxCommandEvent& event )
2128{
2129 if( m_offsetShapeOpt->GetValue() )
2130 {
2133 }
2134
2135 // Show/hide controls depending on m_offsetShapeOpt being enabled
2136 m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
2137 m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
2138
2139 for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
2140 m_notebook->GetPage( i )->Layout();
2141
2142 OnValuesChanged( event );
2143}
2144
2145
2147{
2148 if( m_padToDieOpt->GetValue() && m_currentPad )
2150
2151 OnValuesChanged( event );
2152}
2153
2154
2156{
2157 if( m_padToDieDelayOpt->GetValue() && m_currentPad )
2159
2160 OnValuesChanged( event );
2161}
2162
2163
2164void DIALOG_PAD_PROPERTIES::onModify( wxSpinDoubleEvent& aEvent )
2165{
2166 if( m_initialized )
2167 OnModify();
2168}
2169
2170
2171void DIALOG_PAD_PROPERTIES::onModify( wxCommandEvent& aEvent )
2172{
2173 if( m_initialized )
2174 OnModify();
2175}
2176
2177
2178void DIALOG_PAD_PROPERTIES::OnValuesChanged( wxCommandEvent& event )
2179{
2180 if( m_initialized )
2181 {
2183 return;
2184
2185 // If the pad size has changed, update the displayed values for rounded rect pads.
2188
2189 redraw();
2190 OnModify();
2191 }
2192}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:112
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition: bitmap.cpp:110
#define DEFAULT_PAD_DRILL_DIAMETER_MM
BASE_SET & set(size_t pos)
Definition: base_set.h:116
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
TEARDROP_PARAMETERS & GetTeardropParams()
std::unique_ptr< PAD > m_Pad_Master
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:97
VECTOR2I GetFPRelativePosition() const
Definition: board_item.cpp:346
BOARD_ITEM_CONTAINER * GetParent() const
Definition: board_item.h:210
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:934
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition: board.h:489
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:680
bool LegacyTeardrops() const
Definition: board.h:1319
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:1024
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:907
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:558
constexpr coord_type GetLeft() const
Definition: box2.h:228
constexpr void Move(const Vec &aMoveVector)
Move the rectangle by the aMoveVector.
Definition: box2.h:138
constexpr coord_type GetRight() const
Definition: box2.h:217
constexpr const SizeVec & GetSize() const
Definition: box2.h:206
constexpr coord_type GetTop() const
Definition: box2.h:229
constexpr coord_type GetBottom() const
Definition: box2.h:222
Color settings are a bit different than most of the settings objects in that there can be more than o...
COLOR4D GetColor(int aLayer) const
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition: commit.h:107
Class DIALOG_PAD_PROPERTIES_BASE.
void OnUpdateUINonCopperWarning(wxUpdateUIEvent &event) override
void OnInitDialog(wxInitDialogEvent &event) override
void PadTypeSelected(wxCommandEvent &event) override
void OnPadToDieDelayCheckbox(wxCommandEvent &event) override
void OnPadShapeSelection(wxCommandEvent &event) override
bool transferDataToPad(PAD *aPad)
Copy values from dialog field to aPad's members.
bool TransferDataFromWindow() override
Updates the different parameters for the component being edited.
std::map< int, PCB_LAYER_ID > m_editLayerCtrlMap
bool Show(bool aShow) override
void OnEditLayerChanged(wxCommandEvent &event) override
std::vector< std::shared_ptr< PCB_SHAPE > > m_primitives
bool padValuesOK()
test if all values are acceptable for the pad
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 onTeardropsUpdateUi(wxUpdateUIEvent &event) override
void onChangePadMode(wxCommandEvent &event) override
std::vector< PCB_SHAPE * > m_highlight
void OnPadstackModeChanged(wxCommandEvent &event) override
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 OnPadToDieCheckbox(wxCommandEvent &event) override
void OnDrillShapeSelected(wxCommandEvent &event) override
void OnUpdateUI(wxUpdateUIEvent &event) override
void onModify(wxCommandEvent &aEvent) override
bool Show(bool show) override
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:75
void SetupStandardButtons(std::map< int, wxString > aLabels={})
int ShowQuasiModal()
void resetSize()
Clear the existing dialog size and position.
void OnModify()
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
EDA_BASE_FRAME * m_parentFrame
Definition: dialog_shim.h:254
int ShowModal() override
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.
GAL_DISPLAY_OPTIONS_IMPL & 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
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 ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:144
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:113
int GetAttributes() const
Definition: footprint.h:293
bool IsFlipped() const
Definition: footprint.h:400
void ListSet(const wxString &aList)
Add a list of items.
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
bool m_forceDisplayCursor
The pixel scale factor (>1 for hi-DPI scaled displays)
void SetAxesEnabled(bool aAxesEnabled)
Enable drawing the axes.
void SetGridSize(const VECTOR2D &aGridSize)
Set the grid size.
void SetGridVisibility(bool aVisibility)
Set the visibility setting of the grid.
void SetPosition(const VECTOR2I &aPosition) override
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.
Contains methods for drawing PCB-specific items.
Definition: pcb_painter.h:182
virtual PCB_RENDER_SETTINGS * GetSettings() override
Return a pointer to current settings that are going to be used when drawing items.
Definition: pcb_painter.h:187
PCB specific render settings.
Definition: pcb_painter.h:80
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)
Apply VIEW_CONTROLS settings from an object.
const VC_SETTINGS & GetSettings() const
Return the current VIEW_CONTROLS settings.
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:66
void SetViewport(const BOX2D &aViewport)
Set the visible area of the VIEW.
Definition: view.cpp:542
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:298
void SetBoundary(const BOX2D &aBoundary)
Set limits for view area.
Definition: view.h:286
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:1685
void SetLayerVisible(int aLayer, bool aVisible=true)
Control the visibility of a particular layer.
Definition: view.h:400
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:202
void ClearTopLayers()
Remove all layers from the on-the-top set (they are no longer displayed over the rest of layers).
Definition: view.cpp:891
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:839
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:220
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:37
LSEQ UIOrder() const
Return the copper, technical and user layers in the order shown in layer widget.
Definition: lset.cpp:733
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition: lset.cpp:591
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition: netinfo.h:381
void SetNetInfo(const NETINFO_LIST *aNetInfoList)
int GetSelectedNetcode()
void SetSelectedNetcode(int aNetcode)
void ForEachUniqueLayer(const std::function< void(PCB_LAYER_ID)> &aMethod) const
Runs the given callable for each active unique copper layer in this padstack, meaning F_Cu for MODE::...
Definition: padstack.cpp:882
void SetUnconnectedLayerMode(UNCONNECTED_LAYER_MODE aMode)
Definition: padstack.h:315
void SetMode(MODE aMode)
Definition: padstack.cpp:833
@ NORMAL
Shape is the same on all layers.
@ CUSTOM
Shapes can be defined on arbitrary layers.
@ FRONT_INNER_BACK
Up to three shapes can be defined (F_Cu, inner copper layers, B_Cu)
MODE Mode() const
Definition: padstack.h:295
static constexpr PCB_LAYER_ID INNER_LAYERS
! The layer identifier to use for "inner layers" on top/inner/bottom padstacks
Definition: padstack.h:148
void SetLastPadNumber(const wxString &aPadNumber)
Definition: pad_tool.h:65
wxString GetLastPadNumber() const
Definition: pad_tool.h:64
Definition: pad.h:54
void SetAnchorPadShape(PCB_LAYER_ID aLayer, PAD_SHAPE aShape)
Set the shape of the anchor pad for custom shaped pads.
Definition: pad.h:242
bool IsAperturePad() const
Definition: pad.h:447
void SetAttribute(PAD_ATTRIB aAttribute)
Definition: pad.cpp:883
void CheckPad(UNITS_PROVIDER *aUnitsProvider, bool aForPadProperties, const std::function< void(int aErrorCode, const wxString &aMsg)> &aErrorHandler) const
Definition: pad.cpp:2271
PAD_PROP GetProperty() const
Definition: pad.h:443
bool GetRemoveUnconnected() const
Definition: pad.h:734
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pad.h:437
const std::vector< std::shared_ptr< PCB_SHAPE > > & GetPrimitives(PCB_LAYER_ID aLayer) const
Accessor to the basic shape list for custom-shaped pads.
Definition: pad.h:365
int GetRoundRectCornerRadius(PCB_LAYER_ID aLayer) const
Definition: pad.cpp:467
void SetLocalThermalGapOverride(const std::optional< int > &aOverride)
Definition: pad.h:649
std::optional< double > GetLocalSolderPasteMarginRatio() const
Definition: pad.h:475
const VECTOR2I & GetDrillSize() const
Definition: pad.h:305
PAD_ATTRIB GetAttribute() const
Definition: pad.h:440
static LSET PTHMask()
layer set for a through hole pad
Definition: pad.cpp:291
void SetThermalSpokeAngle(const EDA_ANGLE &aAngle)
The orientation of the thermal spokes.
Definition: pad.h:621
const wxString & GetNumber() const
Definition: pad.h:136
const VECTOR2I & GetDelta(PCB_LAYER_ID aLayer) const
Definition: pad.h:299
void SetLocalSolderPasteMarginRatio(std::optional< double > aRatio)
Definition: pad.h:479
void SetLocalThermalSpokeWidthOverride(std::optional< int > aWidth)
Set the width of the thermal spokes connecting the pad to a zone.
Definition: pad.h:605
void SetShape(PCB_LAYER_ID aLayer, PAD_SHAPE aShape)
Set the new shape of this pad.
Definition: pad.h:186
VECTOR2I GetPosition() const override
Definition: pad.h:208
void SetProperty(PAD_PROP aProperty)
Definition: pad.cpp:950
EDA_ANGLE GetThermalSpokeAngle() const
Definition: pad.h:625
void Flip(const VECTOR2I &VECTOR2I, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
Definition: pad.cpp:983
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
Definition: pad.cpp:312
void SetDelta(PCB_LAYER_ID aLayer, const VECTOR2I &aSize)
Definition: pad.h:293
void SetPadToDieDelay(int aDelay)
Definition: pad.h:455
int GetDrillSizeX() const
Definition: pad.h:307
double GetRoundRectRadiusRatio(PCB_LAYER_ID aLayer) const
Definition: pad.h:671
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
Definition: pad.h:195
void SetNumber(const wxString &aNumber)
Set the pad number (note that it can be alphanumeric, such as the array reference "AA12").
Definition: pad.h:135
void SetDrillShape(PAD_DRILL_SHAPE aShape)
Definition: pad.cpp:456
void SetLocalSolderMaskMargin(std::optional< int > aMargin)
Definition: pad.h:462
void SetOffset(PCB_LAYER_ID aLayer, const VECTOR2I &aOffset)
Definition: pad.h:311
bool GetKeepTopBottom() const
Definition: pad.h:750
void SetLocalZoneConnection(ZONE_CONNECTION aType)
Definition: pad.h:485
void SetChamferRectRatio(PCB_LAYER_ID aLayer, double aChamferScale)
Has meaning only for chamfered rectangular pads.
Definition: pad.cpp:517
int GetPadToDieDelay() const
Definition: pad.h:456
std::optional< int > GetLocalClearance() const override
Return any local clearances set in the "classic" (ie: pre-rule) system.
Definition: pad.h:458
void SetPadstack(const PADSTACK &aPadstack)
Definition: pad.h:323
void SetPosition(const VECTOR2I &aPos) override
Definition: pad.h:202
const PADSTACK & Padstack() const
Definition: pad.h:321
const VECTOR2I & GetOffset(PCB_LAYER_ID aLayer) const
Definition: pad.h:317
static LSET ConnSMDMask()
layer set for a SMD pad on Front layer used for edge board connectors
Definition: pad.cpp:305
void SetDrillSize(const VECTOR2I &aSize)
Definition: pad.h:304
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition: pad.h:408
void SetSize(PCB_LAYER_ID aLayer, const VECTOR2I &aSize)
Definition: pad.h:259
PADSTACK::CUSTOM_SHAPE_ZONE_MODE GetCustomShapeInZoneOpt() const
Definition: pad.h:221
PAD_DRILL_SHAPE GetDrillShape() const
Definition: pad.h:422
void ReplacePrimitives(PCB_LAYER_ID aLayer, const std::vector< std::shared_ptr< PCB_SHAPE > > &aPrimitivesList)
Clear the current custom shape primitives list and import a new list.
Definition: pad.cpp:2632
int GetChamferPositions(PCB_LAYER_ID aLayer) const
Definition: pad.h:711
static LSET ApertureMask()
layer set for an aperture pad
Definition: pad.cpp:319
virtual const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: pad.cpp:1887
void SetRoundRectCornerRadius(PCB_LAYER_ID aLayer, double aRadius)
Has meaning only for rounded rectangle pads.
Definition: pad.cpp:473
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: pad.cpp:298
std::optional< int > GetLocalSolderPasteMargin() const
Definition: pad.h:468
void SetChamferPositions(PCB_LAYER_ID aLayer, int aPositions)
Has meaning only for chamfered rectangular pads.
Definition: pad.h:706
std::optional< int > GetLocalSolderMaskMargin() const
Definition: pad.h:461
void SetLocalSolderPasteMargin(std::optional< int > aMargin)
Definition: pad.h:469
EDA_ANGLE GetFPRelativeOrientation() const
Definition: pad.cpp:974
double GetChamferRectRatio(PCB_LAYER_ID aLayer) const
Definition: pad.h:694
void SetFPRelativeOrientation(const EDA_ANGLE &aAngle)
Definition: pad.cpp:965
void SetCustomShapeInZoneOpt(PADSTACK::CUSTOM_SHAPE_ZONE_MODE aOption)
Set the option for the custom pad shape to use as clearance area in copper zones.
Definition: pad.h:231
void SetOrientation(const EDA_ANGLE &aAngle)
Set the rotation angle of the pad.
Definition: pad.cpp:958
std::optional< int > GetLocalThermalSpokeWidthOverride() const
Definition: pad.h:609
void SetLocalClearance(std::optional< int > aClearance)
Definition: pad.h:459
ZONE_CONNECTION GetLocalZoneConnection() const
Definition: pad.h:486
int GetLocalThermalGapOverride(wxString *aSource) const
Definition: pad.cpp:1333
void SetLayerSet(const LSET &aLayers) override
Definition: pad.h:436
PAD_SHAPE GetAnchorPadShape(PCB_LAYER_ID aLayer) const
Definition: pad.h:213
void SetRoundRectRadiusRatio(PCB_LAYER_ID aLayer, double aRadiusScale)
Has meaning only for rounded rectangle pads.
Definition: pad.cpp:479
void SetPadToDieLength(int aLength)
Definition: pad.h:452
int GetPadToDieLength() const
Definition: pad.h:453
const VECTOR2I & GetSize(PCB_LAYER_ID aLayer) const
Definition: pad.h:264
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
Return the BOARD_DESIGN_SETTINGS for the open project.
virtual COLOR_SETTINGS * GetColorSettings(bool aForceRefresh=false) const override
Helper to retrieve the current color settings.
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.
double m_BestWidthRatio
The height of a teardrop as ratio between height and size of pad/via.
int m_TdMaxLen
max allowed length for teardrops in IU. <= 0 to disable
bool m_AllowUseTwoTracks
True to create teardrops using 2 track segments if the first in too small.
int m_TdMaxWidth
max allowed height for teardrops in IU. <= 0 to disable
double m_BestLengthRatio
The length of a teardrop as ratio between length and size of pad/via.
double m_WidthtoSizeFilterRatio
The ratio (H/D) between the via/pad size and the track width max value to create a teardrop 1....
bool m_TdOnPadsInZones
A filter to exclude pads inside zone fills.
bool m_Enabled
Flag to enable teardrops.
bool m_CurvedEdges
True if the teardrop should be curved.
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
int GetIntValue()
Definition: unit_binder.h:134
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:78
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.
void SetNull()
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:205
bool IsNull() const
Return true if the control holds no value (ie: empty string, not 0).
This file is part of the common library.
#define APERTURE_DLG_TYPE
#define CONN_DLG_TYPE
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.
@ DRCE_PADSTACK
Definition: drc_item.h:62
@ DRCE_PADSTACK_INVALID
Definition: drc_item.h:63
@ DRCE_PAD_TH_WITH_NO_HOLE
Definition: drc_item.h:84
#define _(s)
static constexpr EDA_ANGLE ANGLE_90
Definition: eda_angle.h:413
static constexpr EDA_ANGLE ANGLE_45
Definition: eda_angle.h:412
#define BRIGHTENED
item is drawn with a bright contour
#define SELECTED
Item was manually selected by the user.
@ FRAME_PCB_EDITOR
Definition: frame_type.h:42
@ LAYER_PAD_NETNAMES
Definition: layer_ids.h:202
@ LAYER_GRID
Definition: layer_ids.h:253
@ LAYER_LOCKED_ITEM_SHADOW
Shadow layer for locked items.
Definition: layer_ids.h:306
@ LAYER_NON_PLATEDHOLES
Draw usual through hole vias.
Definition: layer_ids.h:238
@ LAYER_PAD_PLATEDHOLES
to draw pad holes (plated)
Definition: layer_ids.h:270
@ LAYER_PAD_HOLEWALLS
Definition: layer_ids.h:296
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ B_Adhes
Definition: layer_ids.h:103
@ Dwgs_User
Definition: layer_ids.h:107
@ F_Paste
Definition: layer_ids.h:104
@ F_Adhes
Definition: layer_ids.h:102
@ B_Mask
Definition: layer_ids.h:98
@ B_Cu
Definition: layer_ids.h:65
@ Eco1_User
Definition: layer_ids.h:109
@ F_Mask
Definition: layer_ids.h:97
@ B_Paste
Definition: layer_ids.h:105
@ F_SilkS
Definition: layer_ids.h:100
@ Eco2_User
Definition: layer_ids.h:110
@ B_SilkS
Definition: layer_ids.h:101
@ F_Cu
Definition: layer_ids.h:64
This file contains miscellaneous commonly used macros and functions.
KICOMMON_API wxFont GetStatusFont(wxWindow *aWindow)
Definition: ui_common.cpp:132
KICOMMON_API wxFont GetSmallInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:162
bool PadHasMeaningfulRoundingRadius(const PAD &aPad, PCB_LAYER_ID aLayer)
Returns true if the pad's rounding ratio is valid (i.e.
Definition: pad_utils.cpp:44
double GetDefaultIpcRoundingRatio(const PAD &aPad, PCB_LAYER_ID aLayer)
Get a sensible default for a rounded rectangle pad's rounding ratio.
Definition: pad_utils.cpp:27
PAD_ATTRIB
The set of pad shapes, used with PAD::{Set,Get}Attribute().
Definition: padstack.h:81
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
@ 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) Note: also has a special attribute in G...
PAD_SHAPE
The set of pad shapes, used with PAD::{Set,Get}Shape()
Definition: padstack.h:52
PAD_PROP
The set of pad properties used in Gerber files (Draw files, and P&P files) to define some properties ...
Definition: padstack.h:98
const double IU_PER_MM
Definition: base_units.h:76
constexpr int mmToIU(double mm) const
Definition: base_units.h:92
int delta
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition: trigo.cpp:229
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695
VECTOR2< double > VECTOR2D
Definition: vector2d.h:694