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 // gives a non null grid size (0.001mm) because GAL layer does not like a 0 size grid:
363 double gridsize = 0.001 * pcbIUScale.IU_PER_MM;
364 view->GetGAL()->SetGridSize( VECTOR2D( gridsize, gridsize ) );
365
366 // And do not show the grid:
367 view->GetGAL()->SetGridVisibility( false );
368 view->GetGAL()->SetAxesEnabled( false );
369 view->Add( m_previewPad );
370 view->Add( m_axisOrigin );
371
373 Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_PAD_PROPERTIES::OnResize ) );
374}
375
376
378{
381 redraw();
382}
383
384
385void DIALOG_PAD_PROPERTIES::OnEditLayerChanged( wxCommandEvent& aEvent )
386{
387 // Save data from the previous layer
389
390 switch( m_previewPad->Padstack().Mode() )
391 {
392 default:
395 break;
396
398 switch( m_cbEditLayer->GetSelection() )
399 {
400 default:
401 case 0: m_editLayer = F_Cu; break;
402 case 1: m_editLayer = PADSTACK::INNER_LAYERS; break;
403 case 2: m_editLayer = B_Cu; break;
404 }
405 break;
406
408 {
409 int layer = m_cbEditLayer->GetSelection();
410
411 if( layer < 0 )
412 layer = 0;
413
414 if( m_editLayerCtrlMap.contains( layer ) )
415 m_editLayer = m_editLayerCtrlMap.at( layer );
416 else
418 }
419 }
420
421 // Load controls with the current layer
423
424 wxCommandEvent cmd_event;
425 OnPadShapeSelection( cmd_event );
426 OnOffsetCheckbox( cmd_event );
427
428 redraw();
429}
430
431
433{
434 // Note: use ChangeValue() to avoid generating a wxEVT_TEXT event
436
439
442}
443
444
446{
447 if( m_previewPad->GetShape( m_editLayer ) != PAD_SHAPE::ROUNDRECT
448 && m_previewPad->GetShape( m_editLayer ) != PAD_SHAPE::CHAMFERED_RECT )
449 {
450 return;
451 }
452
453 if( m_cornerRadius.GetValue() < 0 )
454 m_cornerRadiusCtrl->ChangeValue( "0" );
455
457 {
459
462
463 redraw();
464 }
465
466 if( m_initialized )
467 OnModify();
468}
469
470
472{
473 if( m_previewPad->GetShape( m_editLayer ) != PAD_SHAPE::ROUNDRECT
474 && m_previewPad->GetShape( m_editLayer ) != PAD_SHAPE::CHAMFERED_RECT )
475 {
476 return;
477 }
478
479 wxObject* ctrl = event.GetEventObject();
480 wxString value = event.GetString();
481 bool changed = false;
482
483 if( ctrl == m_cornerRatioCtrl || ctrl == m_mixedCornerRatioCtrl )
484 {
485 double ratioPercent;
486
487 if( value.ToDouble( &ratioPercent ) )
488 {
489 // Clamp ratioPercent to acceptable value (0.0 to 50.0)
490 if( ratioPercent < 0.0 )
491 {
494 }
495 else if( ratioPercent > 50.0 )
496 {
499 }
500
501 if( ctrl == m_cornerRatioCtrl )
502 m_mixedCornerRatioCtrl->ChangeValue( value );
503 else
504 m_cornerRatioCtrl->ChangeValue( value );
505
506 changed = true;
507 }
508 }
509 else if( ctrl == m_chamferRatioCtrl || ctrl == m_mixedChamferRatioCtrl )
510 {
511 double ratioPercent;
512
513 if( value.ToDouble( &ratioPercent ) )
514 {
515 // Clamp ratioPercent to acceptable value (0.0 to 50.0)
516 if( ratioPercent < 0.0 )
517 {
520 }
521 else if( ratioPercent > 50.0 )
522 {
525 }
526
527 if( ctrl == m_chamferRatioCtrl )
528 m_mixedChamferRatioCtrl->ChangeValue( value );
529 else
530 m_chamferRatioCtrl->ChangeValue( value );
531
532 changed = true;
533 }
534 }
535
536 if( changed && transferDataToPad( m_previewPad ) )
538
539 redraw();
540
541 if( m_initialized )
542 OnModify();
543}
544
545
547{
548 wxString msg;
549
550 // Disable pad net name wxTextCtrl if the caller is the footprint editor
551 // because nets are living only in the board managed by the board editor
553
562 m_layerECO1->SetLabel( m_board->GetLayerName( Eco1_User ) );
563 m_layerECO2->SetLabel( m_board->GetLayerName( Eco2_User ) );
565
566 VECTOR2I absPos;
567
568 if( m_currentPad )
569 {
570 absPos = m_currentPad->GetPosition();
571
572 if( FOOTPRINT* footprint = m_currentPad->GetParentFootprint() )
573 {
575
576 if( footprint->IsFlipped() )
577 {
578 // flip pad (up/down) around its position
579 m_previewPad->Flip( m_previewPad->GetPosition(), FLIP_DIRECTION::TOP_BOTTOM );
580 relPos.y = - relPos.y;
581 }
582
583 m_previewPad->SetPosition( relPos );
585
586 // Display parent footprint info
587 msg.Printf( _("Footprint %s (%s), %s, rotated %g deg"),
588 footprint->Reference().GetShownText( false ),
589 footprint->Value().GetShownText( false ),
590 footprint->IsFlipped() ? _( "back side (mirrored)" ) : _( "front side" ),
591 footprint->GetOrientation().AsDegrees() );
592
593 m_FlippedWarningSizer->Show( footprint->IsFlipped() );
594 m_parentInfo->SetLabel( msg );
595 }
596
597 m_padNumCtrl->SetValue( m_previewPad->GetNumber() );
598 }
599 else
600 {
602 m_padNumCtrl->SetValue( padTool->GetLastPadNumber() );
603
605 {
607 {
608 case FOOTPRINT_ATTR_T::FP_THROUGH_HOLE:
609 m_previewPad->SetAttribute( PAD_ATTRIB::PTH );
610
611 if( m_previewPad->GetDrillSizeX() == 0 )
613
614 break;
615
616 case FOOTPRINT_ATTR_T::FP_SMD:
618 m_previewPad->SetAttribute( PAD_ATTRIB::SMD );
619 break;
620 }
621 }
622 }
623
625
627
628 // Display current pad parameters units:
629 m_posX.ChangeValue( absPos.x );
630 m_posY.ChangeValue( absPos.y );
631
634
635 // TODO(JE) padstacks -- does this need to be saved/restored every time the layer changes?
636 // Store the initial thermal spoke angle to restore it, because some initializations
637 // can change this value (mainly after m_PadShapeSelector initializations)
638 EDA_ANGLE spokeInitialAngle = m_previewPad->GetThermalSpokeAngle();
639
641
642 m_padToDieOpt->SetValue( m_previewPad->GetPadToDieLength() != 0 );
644
647
648 if( m_previewPad->GetLocalClearance().has_value() )
650 else
651 m_clearance.ChangeValue( wxEmptyString );
652
653 if( m_previewPad->GetLocalSolderMaskMargin().has_value() )
655 else
656 m_maskMargin.ChangeValue( wxEmptyString );
657
658 if( m_previewPad->GetLocalSolderPasteMargin().has_value() )
660 else
661 m_pasteMargin.ChangeValue( wxEmptyString );
662
665 else
666 m_pasteMarginRatio.ChangeValue( wxEmptyString );
667
670 else
672
673 if( m_previewPad->GetLocalThermalGapOverride().has_value() )
675 else
677
680
690
692 {
693 default:
694 case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
695 case ZONE_CONNECTION::FULL: m_ZoneConnectionChoice->SetSelection( 1 ); break;
696 case ZONE_CONNECTION::THERMAL: m_ZoneConnectionChoice->SetSelection( 2 ); break;
697 case ZONE_CONNECTION::NONE: m_ZoneConnectionChoice->SetSelection( 3 ); break;
698 }
699
701 m_ZoneCustomPadShape->SetSelection( 1 );
702 else
703 m_ZoneCustomPadShape->SetSelection( 0 );
704
705 // Type of pad selection
706 bool aperture =
707 m_previewPad->GetAttribute() == PAD_ATTRIB::SMD && m_previewPad->IsAperturePad();
708
709 if( aperture )
710 {
711 m_padType->SetSelection( APERTURE_DLG_TYPE );
712 }
713 else
714 {
715 switch( m_previewPad->GetAttribute() )
716 {
717 case PAD_ATTRIB::PTH: m_padType->SetSelection( PTH_DLG_TYPE ); break;
718 case PAD_ATTRIB::SMD: m_padType->SetSelection( SMD_DLG_TYPE ); break;
719 case PAD_ATTRIB::CONN: m_padType->SetSelection( CONN_DLG_TYPE ); break;
720 case PAD_ATTRIB::NPTH: m_padType->SetSelection( NPTH_DLG_TYPE ); break;
721 }
722 }
723
724 switch( m_previewPad->GetProperty() )
725 {
726 case PAD_PROP::NONE: m_choiceFabProperty->SetSelection( 0 ); break;
727 case PAD_PROP::BGA: m_choiceFabProperty->SetSelection( 1 ); break;
728 case PAD_PROP::FIDUCIAL_LOCAL: m_choiceFabProperty->SetSelection( 2 ); break;
729 case PAD_PROP::FIDUCIAL_GLBL: m_choiceFabProperty->SetSelection( 3 ); break;
730 case PAD_PROP::TESTPOINT: m_choiceFabProperty->SetSelection( 4 ); break;
731 case PAD_PROP::HEATSINK: m_choiceFabProperty->SetSelection( 5 ); break;
732 case PAD_PROP::CASTELLATED: m_choiceFabProperty->SetSelection( 6 ); break;
733 case PAD_PROP::MECHANICAL: m_choiceFabProperty->SetSelection( 7 ); break;
734 }
735
736 // Ensure the pad property is compatible with the pad type
737 if( m_previewPad->GetAttribute() == PAD_ATTRIB::NPTH )
738 {
739 m_choiceFabProperty->SetSelection( 0 );
740 m_choiceFabProperty->Enable( false );
741 }
742
743 if( m_previewPad->GetDrillShape() != PAD_DRILL_SHAPE::OBLONG )
744 m_holeShapeCtrl->SetSelection( 0 );
745 else
746 m_holeShapeCtrl->SetSelection( 1 );
747
750
751 // Update some dialog widgets state (Enable/disable options):
752 wxCommandEvent cmd_event;
753 OnPadShapeSelection( cmd_event );
754 OnOffsetCheckbox( cmd_event );
755
756 // Restore thermal spoke angle to its initial value, because it can be modified
757 // by the call to OnPadShapeSelection()
758 m_previewPad->SetThermalSpokeAngle( spokeInitialAngle );
760}
761
762
764{
766
769
773
775 {
777 m_trapAxisCtrl->SetSelection( 0 );
778 }
779 else
780 {
782 m_trapAxisCtrl->SetSelection( 1 );
783 }
784
785 switch( m_previewPad->GetShape( m_editLayer ) )
786 {
787 default:
788 case PAD_SHAPE::CIRCLE: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_CIRCLE ); break;
789 case PAD_SHAPE::OVAL: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_OVAL ); break;
790 case PAD_SHAPE::RECTANGLE: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_RECT ); break;
791 case PAD_SHAPE::TRAPEZOID: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_TRAPEZOID ); break;
792 case PAD_SHAPE::ROUNDRECT: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_ROUNDRECT ); break;
793
794 case PAD_SHAPE::CHAMFERED_RECT:
797 else
799 break;
800
801 case PAD_SHAPE::CUSTOM:
802 if( m_previewPad->GetAnchorPadShape( m_editLayer ) == PAD_SHAPE::RECTANGLE )
804 else
806 break;
807 }
808
809 int chamferPositions = m_previewPad->GetChamferPositions( m_editLayer );
810
811 m_cbTopLeft->SetValue( chamferPositions & RECT_CHAMFER_TOP_LEFT );
812 m_cbTopLeft1->SetValue( chamferPositions & RECT_CHAMFER_TOP_LEFT );
813 m_cbTopRight->SetValue( chamferPositions & RECT_CHAMFER_TOP_RIGHT );
814 m_cbTopRight1->SetValue( chamferPositions & RECT_CHAMFER_TOP_RIGHT );
815 m_cbBottomLeft->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_LEFT );
816 m_cbBottomLeft1->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_LEFT );
817 m_cbBottomRight->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_RIGHT );
818 m_cbBottomRight1->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_RIGHT );
819
821}
822
823
825{
826 // NOTE: synchronize changes here with DIALOG_TRACK_VIA_PROPERTIES::afterPadstackModeChanged
827
828 wxCHECK_MSG( m_board, /* void */, "Expected valid board in afterPadstackModeChanged" );
829 m_cbEditLayer->Clear();
830
831 switch( m_previewPad->Padstack().Mode() )
832 {
834 m_cbPadstackMode->SetSelection( 0 );
835 m_cbEditLayer->Append( m_board->GetLayerName( F_Cu ) );
836 m_cbEditLayer->Disable();
838 m_editLayerCtrlMap = { { 0, F_Cu } };
839 break;
840
842 {
843 m_cbPadstackMode->SetSelection( 1 );
844 m_cbEditLayer->Enable();
845
846 std::vector choices = {
848 _( "Inner Layers" ),
850 };
851
852 m_cbEditLayer->Append( choices );
853
855 { 0, F_Cu },
857 { 2, B_Cu }
858 };
859
860 if( m_editLayer != F_Cu && m_editLayer != B_Cu )
862
863 break;
864 }
865
867 {
868 m_cbPadstackMode->SetSelection( 2 );
869 m_cbEditLayer->Enable();
871
872 for( PCB_LAYER_ID layer : layers.UIOrder() )
873 {
874 int idx = m_cbEditLayer->Append( m_board->GetLayerName( layer ) );
875 m_editLayerCtrlMap[idx] = layer;
876 }
877
878 break;
879 }
880 }
881
882 for( const auto& [idx, layer] : m_editLayerCtrlMap )
883 {
884 if( layer == m_editLayer )
885 {
886 m_cbEditLayer->SetSelection( idx );
887 break;
888 }
889 }
890}
891
892
893void DIALOG_PAD_PROPERTIES::OnResize( wxSizeEvent& event )
894{
895 redraw();
896 event.Skip();
897}
898
899
900void DIALOG_PAD_PROPERTIES::onChangePadMode( wxCommandEvent& event )
901{
903
905
906 // fix the pad render mode (filled/not filled)
907 auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
908
909 settings->m_ForcePadSketchModeOn = m_cbShowPadOutline->IsChecked();
910 settings->SetHighContrast( false );
911 settings->m_ContrastModeDisplay = HIGH_CONTRAST_MODE::NORMAL;
912
913 redraw();
914}
915
916
918{
919 switch( m_PadShapeSelector->GetSelection() )
920 {
924 m_shapePropsBook->SetSelection( 0 );
925 break;
926
928 m_shapePropsBook->SetSelection( 1 );
929 break;
930
932 {
933 m_shapePropsBook->SetSelection( 2 );
934
935 // Reasonable defaults
937 {
938 const double ipcRadiusRatio =
940 m_cornerRatio.ChangeDoubleValue( ipcRadiusRatio * 100 );
941 }
942
943 break;
944 }
945
947 m_shapePropsBook->SetSelection( 3 );
948
949 // Reasonable default
952
953 // Ensure the displayed value is up to date:
955
956 // A reasonable default is one corner chamfered (usual for some SMD pads).
957 if( !m_cbTopLeft->GetValue() && !m_cbTopRight->GetValue()
958 && !m_cbBottomLeft->GetValue() && !m_cbBottomRight->GetValue() )
959 {
960 m_cbTopLeft->SetValue( true );
961 m_cbTopRight->SetValue( false );
962 m_cbBottomLeft->SetValue( false );
963 m_cbBottomRight->SetValue( false );
964 }
965
966 break;
967
969 m_shapePropsBook->SetSelection( 4 );
970
971 // Reasonable defaults
974 {
975 const double ipcRadiusRatio =
979 }
980
981 // Ensure the displayed values are up to date:
984 break;
985
986 case CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR: // PAD_SHAPE::CUSTOM, circular anchor
987 case CHOICE_SHAPE_CUSTOM_RECT_ANCHOR: // PAD_SHAPE::CUSTOM, rect anchor
988 m_shapePropsBook->SetSelection( 0 );
989 break;
990 }
991
992 // Note: must do this before enabling/disabling m_sizeY as we're using that as a flag to see
993 // what the last shape was.
994 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CIRCLE )
995 {
996 if( m_sizeYCtrl->IsEnabled() && m_spokeAngle.GetAngleValue() == ANGLE_90 )
998 }
999 else
1000 {
1001 if( !m_sizeYCtrl->IsEnabled() && m_spokeAngle.GetAngleValue() == ANGLE_45 )
1003 }
1004
1005 // Readjust props book size
1006 wxSize size = m_shapePropsBook->GetSize();
1007 size.y = m_shapePropsBook->GetPage( m_shapePropsBook->GetSelection() )->GetBestSize().y;
1008 m_shapePropsBook->SetMaxSize( size );
1009
1012
1013 m_offsetShapeOpt->Enable( m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CIRCLE );
1014
1015 if( !m_offsetShapeOpt->IsEnabled() )
1016 m_offsetShapeOpt->SetValue( false );
1017
1018 // Show/hide controls depending on m_offsetShapeOpt being enabled
1019 m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
1020 m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
1021
1024
1025 for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
1026 m_notebook->GetPage( i )->Layout();
1027
1028 // Resize the dialog if its height is too small to show all widgets:
1029 if( m_MainSizer->GetSize().y < m_MainSizer->GetMinSize().y )
1030 m_MainSizer->SetSizeHints( this );
1031
1033 redraw();
1034
1035 if( m_initialized )
1036 OnModify();
1037}
1038
1039
1041{
1044 redraw();
1045
1046 if( m_initialized )
1047 OnModify();
1048}
1049
1050
1051void DIALOG_PAD_PROPERTIES::PadOrientEvent( wxCommandEvent& event )
1052{
1054 redraw();
1055
1056 if( m_initialized )
1057 OnModify();
1058}
1059
1060
1062{
1063 m_rbCopperLayersSel->Clear();
1064
1065 switch( m_padType->GetSelection() )
1066 {
1067 case PTH_DLG_TYPE:
1068 m_rbCopperLayersSel->Append( _( "All copper layers" ) );
1069 m_rbCopperLayersSel->Append( wxString::Format( _( "%s, %s and connected layers" ),
1071 m_board->GetLayerName( B_Cu ) ) );
1072 m_rbCopperLayersSel->Append( _( "Connected layers only" ) );
1073 m_rbCopperLayersSel->Append( _( "None" ) );
1074 break;
1075
1076 case NPTH_DLG_TYPE:
1077 m_rbCopperLayersSel->Append( wxString::Format( _( "%s and %s" ),
1079 m_board->GetLayerName( B_Cu ) ) );
1082 m_rbCopperLayersSel->Append( _( "None" ) );
1083 break;
1084
1085 case SMD_DLG_TYPE:
1086 case CONN_DLG_TYPE:
1089 break;
1090
1091 case APERTURE_DLG_TYPE:
1092 m_rbCopperLayersSel->Append( _( "None" ) );
1093 break;
1094 }
1095}
1096
1097
1098void DIALOG_PAD_PROPERTIES::PadTypeSelected( wxCommandEvent& event )
1099{
1100 bool hasHole = true;
1101 bool hasConnection = true;
1102 bool hasProperty = true;
1103
1104 switch( m_padType->GetSelection() )
1105 {
1106 case PTH_DLG_TYPE: hasHole = true; hasConnection = true; hasProperty = true; break;
1107 case SMD_DLG_TYPE: hasHole = false; hasConnection = true; hasProperty = true; break;
1108 case CONN_DLG_TYPE: hasHole = false; hasConnection = true; hasProperty = true; break;
1109 case NPTH_DLG_TYPE: hasHole = true; hasConnection = false; hasProperty = false; break;
1110 case APERTURE_DLG_TYPE: hasHole = false; hasConnection = false; hasProperty = true; break;
1111 }
1112
1113 // Update Layers dropdown list and selects the "best" layer set for the new pad type:
1116
1117 m_gbSizerHole->Show( hasHole );
1118 m_staticline71->Show( hasHole );
1119
1120 if( !hasHole )
1121 {
1122 m_holeX.ChangeValue( 0 );
1123 m_holeY.ChangeValue( 0 );
1124 }
1125 else if( m_holeX.GetValue() == 0 )
1126 {
1127 if( m_currentPad )
1128 {
1131 }
1132 else
1133 {
1135 }
1136 }
1137
1138 if( !hasConnection )
1139 {
1140 m_padNumCtrl->ChangeValue( wxEmptyString );
1142 m_padToDieOpt->SetValue( false );
1143 m_padToDieDelayOpt->SetValue( false );
1144 }
1145 else if( m_padNumCtrl->GetValue().IsEmpty() && m_currentPad )
1146 {
1147 m_padNumCtrl->ChangeValue( m_currentPad->GetNumber() );
1149 }
1150
1151 if( !hasProperty )
1152 m_choiceFabProperty->SetSelection( 0 );
1153
1154 m_choiceFabProperty->Enable( hasProperty );
1155
1157
1158 // For now, padstack controls only enabled for PTH pads
1159 bool enablePadstack = m_padType->GetSelection() == PTH_DLG_TYPE;
1160 m_padstackControls->Show( enablePadstack );
1161
1162 if( !enablePadstack )
1163 {
1164 m_editLayer = F_Cu;
1166 }
1167
1168 // Layout adjustment is needed if the hole details got shown/hidden
1169 m_LeftBoxSizer->Layout();
1170 redraw();
1171
1172 if( m_initialized )
1173 OnModify();
1174}
1175
1176
1177void DIALOG_PAD_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
1178{
1179 bool hasHole = true;
1180 bool hasConnection = true;
1181
1182 switch( m_padType->GetSelection() )
1183 {
1184 case PTH_DLG_TYPE: /* PTH */ hasHole = true; hasConnection = true; break;
1185 case SMD_DLG_TYPE: /* SMD */ hasHole = false; hasConnection = true; break;
1186 case CONN_DLG_TYPE: /* CONN */ hasHole = false; hasConnection = true; break;
1187 case NPTH_DLG_TYPE: /* NPTH */ hasHole = true; hasConnection = false; break;
1188 case APERTURE_DLG_TYPE: /* Aperture */ hasHole = false; hasConnection = false; break;
1189 }
1190
1191 // Enable/disable hole controls
1192 m_holeShapeLabel->Enable( hasHole );
1193 m_holeShapeCtrl->Enable( hasHole );
1194 m_holeX.Enable( hasHole );
1195 m_holeY.Enable( hasHole && m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_OVAL );
1196
1197 // Enable/disable number and net
1198 m_padNumLabel->Enable( hasConnection );
1199 m_padNumCtrl->Enable( hasConnection );
1200
1201 if( m_padNetLabel->IsShown() )
1202 {
1203 m_padNetLabel->Enable( hasConnection && m_canEditNetName && m_currentPad );
1204 m_padNetSelector->Enable( hasConnection && m_canEditNetName && m_currentPad );
1205 }
1206
1207 // Enable/disable pad length-to-die
1208 m_padToDieOpt->Enable( hasConnection );
1209 m_padToDieDelayOpt->Enable( hasConnection );
1210
1211 if( !m_padToDieOpt->IsEnabled() )
1212 m_padToDieOpt->SetValue( false );
1213
1214 if( !m_padToDieDelayOpt->IsEnabled() )
1215 m_padToDieDelayOpt->SetValue( false );
1216
1217 // We can show/hide this here because it doesn't require the layout to be refreshed.
1218 // All the others have to be done in their event handlers because doing a layout here
1219 // causes infinite looping on MSW.
1220 m_padToDie.Show( m_padToDieOpt->GetValue() );
1222
1223 // Enable/disable Copper Layers control
1224 m_rbCopperLayersSel->Enable( m_padType->GetSelection() != APERTURE_DLG_TYPE );
1225
1227
1228 switch( m_padType->GetSelection() )
1229 {
1230 case PTH_DLG_TYPE:
1231 if( !cu_set.any() )
1232 m_stackupImagesBook->SetSelection( 3 );
1233 else if( !m_previewPad->GetRemoveUnconnected() )
1234 m_stackupImagesBook->SetSelection( 0 );
1235 else if( m_previewPad->GetKeepTopBottom() )
1236 m_stackupImagesBook->SetSelection( 1 );
1237 else
1238 m_stackupImagesBook->SetSelection( 2 );
1239
1240 break;
1241
1242 case NPTH_DLG_TYPE:
1243 if( cu_set.test( F_Cu ) && cu_set.test( B_Cu ) )
1244 m_stackupImagesBook->SetSelection( 4 );
1245 else if( cu_set.test( F_Cu ) )
1246 m_stackupImagesBook->SetSelection( 5 );
1247 else if( cu_set.test( B_Cu ) )
1248 m_stackupImagesBook->SetSelection( 6 );
1249 else
1250 m_stackupImagesBook->SetSelection( 7 );
1251
1252 break;
1253
1254 case SMD_DLG_TYPE:
1255 case CONN_DLG_TYPE:
1256 case APERTURE_DLG_TYPE:
1257 m_stackupImagesBook->ChangeSelection( 3 );
1258 break;
1259 }
1260
1262}
1263
1264
1266{
1267 event.Enable( !m_board->LegacyTeardrops() );
1268}
1269
1270
1272{
1273 bool isOnCopperLayer = ( m_previewPad->GetLayerSet() & LSET::AllCuMask() ).any();
1274 m_nonCopperWarningBook->ChangeSelection( isOnCopperLayer ? 0 : 1 );
1275}
1276
1277
1278void DIALOG_PAD_PROPERTIES::updatePadLayersList( LSET layer_mask, bool remove_unconnected,
1279 bool keep_top_bottom )
1280{
1282
1283 switch( m_padType->GetSelection() )
1284 {
1285 case PTH_DLG_TYPE:
1286 if( !layer_mask.any() )
1287 layer_mask = PAD::PTHMask();
1288
1289 if( !( layer_mask & LSET::AllCuMask() ).any() )
1290 m_rbCopperLayersSel->SetSelection( 3 );
1291 else if( !remove_unconnected )
1292 m_rbCopperLayersSel->SetSelection( 0 );
1293 else if( keep_top_bottom )
1294 m_rbCopperLayersSel->SetSelection( 1 );
1295 else
1296 m_rbCopperLayersSel->SetSelection( 2 );
1297
1298 break;
1299
1300 case SMD_DLG_TYPE:
1301 if( !layer_mask.any() )
1302 layer_mask = PAD::SMDMask();
1303
1304 if( layer_mask.test( F_Cu ) )
1305 m_rbCopperLayersSel->SetSelection( 0 );
1306 else
1307 m_rbCopperLayersSel->SetSelection( 1 );
1308
1309 break;
1310
1311 case CONN_DLG_TYPE:
1312 if( !layer_mask.any() )
1313 layer_mask = PAD::ConnSMDMask();
1314
1315 if( layer_mask.test( F_Cu ) )
1316 m_rbCopperLayersSel->SetSelection( 0 );
1317 else
1318 m_rbCopperLayersSel->SetSelection( 1 );
1319
1320 break;
1321
1322 case NPTH_DLG_TYPE:
1323 if( !layer_mask.any() )
1324 layer_mask = PAD::UnplatedHoleMask();
1325
1326 if( layer_mask.test( F_Cu ) && layer_mask.test( B_Cu ) )
1327 m_rbCopperLayersSel->SetSelection( 0 );
1328 else if( layer_mask.test( F_Cu ) )
1329 m_rbCopperLayersSel->SetSelection( 1 );
1330 else if( layer_mask.test( B_Cu ) )
1331 m_rbCopperLayersSel->SetSelection( 2 );
1332 else
1333 m_rbCopperLayersSel->SetSelection( 3 );
1334
1335 break;
1336
1337 case APERTURE_DLG_TYPE:
1338 if( !layer_mask.any() )
1339 layer_mask = PAD::ApertureMask();
1340
1341 m_rbCopperLayersSel->SetSelection( 0 );
1342 break;
1343 }
1344
1345 m_layerFrontAdhesive->SetValue( layer_mask[F_Adhes] );
1346 m_layerBackAdhesive->SetValue( layer_mask[B_Adhes] );
1347
1348 m_layerFrontPaste->SetValue( layer_mask[F_Paste] );
1349 m_layerBackPaste->SetValue( layer_mask[B_Paste] );
1350
1351 m_layerFrontSilk->SetValue( layer_mask[F_SilkS] );
1352 m_layerBackSilk->SetValue( layer_mask[B_SilkS] );
1353
1354 m_layerFrontMask->SetValue( layer_mask[F_Mask] );
1355 m_layerBackMask->SetValue( layer_mask[B_Mask] );
1356
1357 m_layerECO1->SetValue( layer_mask[Eco1_User] );
1358 m_layerECO2->SetValue( layer_mask[Eco2_User] );
1359
1360 m_layerUserDwgs->SetValue( layer_mask[Dwgs_User] );
1361}
1362
1363
1365{
1366 bool retVal = DIALOG_SHIM::Show( aShow );
1367
1368 if( aShow )
1369 {
1370 // It *should* work to set the stackup bitmap in the constructor, but it doesn't.
1371 // wxWidgets needs to have these set when the panel is visible for some reason.
1372 // https://gitlab.com/kicad/code/kicad/-/issues/5534
1373 m_stackupImage0->SetBitmap( KiBitmapBundle( BITMAPS::pads_reset_unused ) );
1374 m_stackupImage1->SetBitmap( KiBitmapBundle( BITMAPS::pads_remove_unused_keep_bottom ) );
1375 m_stackupImage2->SetBitmap( KiBitmapBundle( BITMAPS::pads_remove_unused ) );
1376 m_stackupImage4->SetBitmap( KiBitmapBundle( BITMAPS::pads_npth_top_bottom ) );
1377 m_stackupImage5->SetBitmap( KiBitmapBundle( BITMAPS::pads_npth_top ) );
1378 m_stackupImage6->SetBitmap( KiBitmapBundle( BITMAPS::pads_npth_bottom ) );
1379 m_stackupImage7->SetBitmap( KiBitmapBundle( BITMAPS::pads_npth ) );
1380
1381 Layout();
1382 }
1383
1384 return retVal;
1385}
1386
1387
1388void DIALOG_PAD_PROPERTIES::OnSetCopperLayers( wxCommandEvent& event )
1389{
1391 redraw();
1392
1393 if( m_initialized )
1394 OnModify();
1395}
1396
1397
1398void DIALOG_PAD_PROPERTIES::OnSetLayers( wxCommandEvent& event )
1399{
1401 redraw();
1402
1403 if( m_initialized )
1404 OnModify();
1405}
1406
1407
1409{
1411
1412 wxArrayString error_msgs;
1413 wxArrayString warning_msgs;
1414
1416 [&]( int errorCode, const wxString& msg )
1417 {
1418 if( errorCode == DRCE_PADSTACK_INVALID )
1419 error_msgs.Add( _( "Error: " ) + msg );
1420 else if( errorCode == DRCE_PADSTACK )
1421 warning_msgs.Add( _( "Warning: " ) + msg );
1422 else if( errorCode == DRCE_PAD_TH_WITH_NO_HOLE )
1423 error_msgs.Add( _( "Error: Through hole pad has no hole." ) );
1424 } );
1425
1426 if( error_msgs.GetCount() || warning_msgs.GetCount() )
1427 {
1428 wxString title = error_msgs.GetCount() ? _( "Pad Properties Errors" )
1429 : _( "Pad Properties Warnings" );
1430 HTML_MESSAGE_BOX dlg( this, title );
1431
1432 wxArrayString msgs = error_msgs;
1433
1434 for( const wxString& msg : warning_msgs )
1435 msgs.Add( msg );
1436
1437 dlg.ListSet( msgs );
1438
1439 dlg.ShowModal();
1440 }
1441
1442 return error_msgs.GetCount() == 0;
1443}
1444
1445
1447{
1448 if( !m_initialized )
1449 return;
1450
1452 KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( view->GetPainter() );
1453 KIGFX::PCB_RENDER_SETTINGS* settings = painter->GetSettings();
1454
1456
1457 // The layer used to place primitive items selected when editing custom pad shapes
1458 // we use here a layer never used in a pad:
1459 #define SELECTED_ITEMS_LAYER Dwgs_User
1460
1461 view->ClearTopLayers();
1463 view->SetTopLayer( m_editLayer );
1465
1466 static const std::vector<int> topLayers = {
1471 };
1472
1473 for( int layer : topLayers )
1474 view->SetTopLayer( layer );
1475
1477
1478 view->Update( m_previewPad );
1479
1480 // delete previous items if highlight list
1481 while( m_highlight.size() )
1482 {
1483 delete m_highlight.back(); // the dtor also removes item from view
1484 m_highlight.pop_back();
1485 }
1486
1487 BOX2I bbox = m_previewPad->ViewBBox();
1488
1489 if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
1490 {
1491 // The origin always goes in the middle of the canvas; we want offsetting the pad
1492 // shape to move the pad, not the hole
1493 bbox.Move( -m_previewPad->GetPosition() );
1494 int maxXExtent = std::max( abs( bbox.GetLeft() ), abs( bbox.GetRight() ) );
1495 int maxYExtent = std::max( abs( bbox.GetTop() ), abs( bbox.GetBottom() ) );
1496
1497 // Don't blow up the GAL on too-large numbers
1498 if( maxXExtent > INT_MAX / 4 )
1499 maxXExtent = INT_MAX / 4;
1500
1501 if( maxYExtent > INT_MAX / 4 )
1502 maxYExtent = INT_MAX / 4;
1503
1504 BOX2D viewBox( m_previewPad->GetPosition(), {0, 0} );
1505 BOX2D canvasBox( m_previewPad->GetPosition(), {0, 0} );
1506 viewBox.Inflate( maxXExtent * 1.4, maxYExtent * 1.4 ); // add a margin
1507 canvasBox.Inflate( maxXExtent * 2.0, maxYExtent * 2.0 );
1508
1509 view->SetBoundary( canvasBox );
1510
1511 // Autozoom
1512 view->SetViewport( viewBox );
1513
1516 }
1517}
1518
1519
1521{
1522 if( !wxDialog::TransferDataToWindow() )
1523 return false;
1524
1525 if( !m_panelGeneral->TransferDataToWindow() )
1526 return false;
1527
1528 if( !m_localSettingsPanel->TransferDataToWindow() )
1529 return false;
1530
1531 return true;
1532}
1533
1534
1536{
1537 BOARD_COMMIT commit( m_parent );
1538
1539 if( !wxDialog::TransferDataFromWindow() )
1540 return false;
1541
1542 if( !m_panelGeneral->TransferDataFromWindow() )
1543 return false;
1544
1545 if( !m_localSettingsPanel->TransferDataFromWindow() )
1546 return false;
1547
1548 if( !padValuesOK() )
1549 return false;
1550
1552 return false;
1553
1555
1557 padTool->SetLastPadNumber( m_masterPad->GetNumber() );
1558
1559 // m_masterPad is a pattern: ensure there is no net for this pad:
1561
1562 if( !m_currentPad ) // Set current Pad parameters
1563 return true;
1564
1565 commit.Modify( m_currentPad );
1566
1567 // Update values
1568
1569 // transferDataToPad only handles the current edit layer, so m_masterPad isn't accurate
1570 // TODO(JE) this could be cleaner
1572
1579
1580 int padNetcode = NETINFO_LIST::UNCONNECTED;
1581
1582 // For PAD_ATTRIB::NPTH, ensure there is no net name selected
1583 if( m_masterPad->GetAttribute() != PAD_ATTRIB::NPTH )
1584 padNetcode = m_padNetSelector->GetSelectedNetcode();
1585
1586 m_currentPad->SetNetCode( padNetcode );
1587
1589
1590 // Set the fabrication property:
1592
1593 // define the way the clearance area is defined in zones
1595
1597 {
1598 // flip pad (up/down) around its position
1599 m_currentPad->Flip( m_currentPad->GetPosition(), FLIP_DIRECTION::TOP_BOTTOM );
1600 }
1601
1603
1605
1606 // redraw the area where the pad was
1608
1609 commit.Push( _( "Edit Pad Properties" ) );
1610
1611 return true;
1612}
1613
1614
1616{
1617 PAD_PROP prop = PAD_PROP::NONE;
1618
1619 switch( m_choiceFabProperty->GetSelection() )
1620 {
1621 case 0: prop = PAD_PROP::NONE; break;
1622 case 1: prop = PAD_PROP::BGA; break;
1623 case 2: prop = PAD_PROP::FIDUCIAL_LOCAL; break;
1624 case 3: prop = PAD_PROP::FIDUCIAL_GLBL; break;
1625 case 4: prop = PAD_PROP::TESTPOINT; break;
1626 case 5: prop = PAD_PROP::HEATSINK; break;
1627 case 6: prop = PAD_PROP::CASTELLATED; break;
1628 case 7: prop = PAD_PROP::MECHANICAL; break;
1629 }
1630
1631 return prop;
1632}
1633
1634
1636{
1637 if( m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_CIRCLE )
1638 {
1639 m_holeXLabel->SetLabel( _( "Diameter:" ) );
1640 m_holeY.Show( false );
1641 }
1642 else
1643 {
1644 m_holeXLabel->SetLabel( _( "Hole size X:" ) );
1645 m_holeY.Show( true );
1646 }
1647
1648 m_holeXLabel->GetParent()->Layout();
1649}
1650
1651
1653{
1654 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CIRCLE
1656 {
1657 m_sizeXLabel->SetLabel( _( "Diameter:" ) );
1658 m_sizeY.Show( false );
1659 m_bitmapTeardrop->SetBitmap( KiBitmapBundle( BITMAPS::teardrop_sizes ) );
1660 m_minTrackWidthHint->SetLabel( _( "d" ) );
1661 m_stLenPercentHint->SetLabel( _( "d" ) );
1662 m_stWidthPercentHint->SetLabel( _( "d" ) );
1663 }
1664 else
1665 {
1666 m_sizeXLabel->SetLabel( _( "Pad size X:" ) );
1667 m_sizeY.Show( true );
1668 m_bitmapTeardrop->SetBitmap( KiBitmapBundle( BITMAPS::teardrop_rect_sizes ) );
1669 m_minTrackWidthHint->SetLabel( _( "w" ) );
1670 m_stLenPercentHint->SetLabel( _( "w" ) );
1671 m_stWidthPercentHint->SetLabel( _( "w" ) );
1672 }
1673
1674 m_sizeXLabel->GetParent()->Layout();
1675 resetSize();
1676 Layout();
1677 m_MainSizer->Fit( this );
1678}
1679
1680
1682{
1683 if( !Validate() )
1684 return false;
1685
1686 if( !m_panelGeneral->Validate() )
1687 return false;
1688
1689 if( !m_localSettingsPanel->Validate() )
1690 return false;
1691
1692 if( !m_spokeWidth.Validate( 0, INT_MAX ) )
1693 return false;
1694
1695 switch( m_cbPadstackMode->GetSelection() )
1696 {
1697 default:
1698 case 0: aPad->Padstack().SetMode( PADSTACK::MODE::NORMAL ); break;
1699 case 1: aPad->Padstack().SetMode( PADSTACK::MODE::FRONT_INNER_BACK ); break;
1700 case 2: aPad->Padstack().SetMode( PADSTACK::MODE::CUSTOM ); break;
1701 }
1702
1703 aPad->SetAttribute( code_type[m_padType->GetSelection()] );
1704 aPad->SetShape( m_editLayer, code_shape[m_PadShapeSelector->GetSelection()] );
1705
1707 aPad->SetAnchorPadShape( m_editLayer, PAD_SHAPE::RECTANGLE );
1708 else
1709 aPad->SetAnchorPadShape( m_editLayer, PAD_SHAPE::CIRCLE );
1710
1711 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::CUSTOM )
1713
1714 aPad->GetTeardropParams().m_Enabled = m_cbTeardrops->GetValue();
1721 aPad->GetTeardropParams().m_CurvedEdges = m_curvedEdges->GetValue();
1723
1724 // Read pad clearances values:
1725 if( m_clearance.IsNull() )
1726 aPad->SetLocalClearance( {} );
1727 else
1729
1730 if( m_maskMargin.IsNull() )
1731 aPad->SetLocalSolderMaskMargin( {} );
1732 else
1734
1735 if( m_pasteMargin.IsNull() )
1736 aPad->SetLocalSolderPasteMargin( {} );
1737 else
1739
1742 else
1744
1745 if( m_spokeWidth.IsNull() )
1747 else
1749
1750 if( m_thermalGap.IsNull() )
1751 aPad->SetLocalThermalGapOverride( {} );
1752 else
1754
1756
1757 // And rotation
1759
1760 switch( m_ZoneConnectionChoice->GetSelection() )
1761 {
1762 default:
1763 case 0: aPad->SetLocalZoneConnection( ZONE_CONNECTION::INHERITED ); break;
1764 case 1: aPad->SetLocalZoneConnection( ZONE_CONNECTION::FULL ); break;
1765 case 2: aPad->SetLocalZoneConnection( ZONE_CONNECTION::THERMAL ); break;
1766 case 3: aPad->SetLocalZoneConnection( ZONE_CONNECTION::NONE ); break;
1767 }
1768
1770
1771 if( FOOTPRINT* fp = aPad->GetParentFootprint() )
1772 {
1773 pos -= fp->GetPosition();
1774 RotatePoint( pos, -fp->GetOrientation() );
1775 }
1776
1777 aPad->SetPosition( pos );
1778
1779 if( m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_CIRCLE )
1780 {
1781 aPad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
1783 }
1784 else
1785 {
1786 aPad->SetDrillShape( PAD_DRILL_SHAPE::OBLONG );
1788 }
1789
1790 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::CIRCLE )
1792 else
1794
1795 // For a trapezoid, test delta value (be sure delta is not too large for pad size)
1796 // remember DeltaSize.x is the Y size variation
1797 bool error = false;
1798 VECTOR2I delta( 0, 0 );
1799
1800 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::TRAPEZOID )
1801 {
1802 // For a trapezoid, only one of delta.x or delta.y is not 0, depending on axis.
1803 if( m_trapAxisCtrl->GetSelection() == 0 )
1805 else
1807
1808 if( delta.x < 0 && delta.x < -aPad->GetSize( m_editLayer ).y )
1809 {
1810 delta.x = -aPad->GetSize( m_editLayer ).y + 2;
1811 error = true;
1812 }
1813
1814 if( delta.x > 0 && delta.x > aPad->GetSize( m_editLayer ).y )
1815 {
1816 delta.x = aPad->GetSize( m_editLayer ).y - 2;
1817 error = true;
1818 }
1819
1820 if( delta.y < 0 && delta.y < -aPad->GetSize( m_editLayer ).x )
1821 {
1822 delta.y = -aPad->GetSize( m_editLayer ).x + 2;
1823 error = true;
1824 }
1825
1826 if( delta.y > 0 && delta.y > aPad->GetSize( m_editLayer ).x )
1827 {
1828 delta.y = aPad->GetSize( m_editLayer ).x - 2;
1829 error = true;
1830 }
1831 }
1832
1833 aPad->SetDelta( m_editLayer, delta );
1834
1835 if( m_offsetShapeOpt->GetValue() )
1837 else
1838 aPad->SetOffset( m_editLayer, VECTOR2I() );
1839
1840 // Read pad length die
1841 if( m_padToDieOpt->GetValue() )
1843 else
1844 aPad->SetPadToDieLength( 0 );
1845
1846 if( m_padToDieDelayOpt->GetValue() )
1848 else
1849 aPad->SetPadToDieDelay( 0 );
1850
1851 aPad->SetNumber( m_padNumCtrl->GetValue() );
1853
1854 int chamfers = 0;
1855
1856 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_RECT )
1857 {
1858 if( m_cbTopLeft->GetValue() )
1859 chamfers |= RECT_CHAMFER_TOP_LEFT;
1860
1861 if( m_cbTopRight->GetValue() )
1862 chamfers |= RECT_CHAMFER_TOP_RIGHT;
1863
1864 if( m_cbBottomLeft->GetValue() )
1865 chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1866
1867 if( m_cbBottomRight->GetValue() )
1868 chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1869 }
1870 else if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT )
1871 {
1872 if( m_cbTopLeft1->GetValue() )
1873 chamfers |= RECT_CHAMFER_TOP_LEFT;
1874
1875 if( m_cbTopRight1->GetValue() )
1876 chamfers |= RECT_CHAMFER_TOP_RIGHT;
1877
1878 if( m_cbBottomLeft1->GetValue() )
1879 chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1880
1881 if( m_cbBottomRight1->GetValue() )
1882 chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1883 }
1884
1885 aPad->SetChamferPositions( m_editLayer, chamfers );
1886
1887 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::CUSTOM )
1888 {
1889 // The pad custom has a "anchor pad" (a basic shape: round or rect pad)
1890 // that is the minimal area of this pad, and is useful to ensure a hole
1891 // diameter is acceptable, and is used in Gerber files as flashed area
1892 // reference
1893 if( aPad->GetAnchorPadShape( m_editLayer ) == PAD_SHAPE::CIRCLE )
1895 }
1896
1897 // Define the way the clearance area is defined in zones. Since all non-custom pad
1898 // shapes are convex to begin with, this really only makes any difference for custom
1899 // pad shapes.
1900 aPad->SetCustomShapeInZoneOpt( m_ZoneCustomPadShape->GetSelection() == 0 ?
1903
1904 switch( aPad->GetAttribute() )
1905 {
1906 case PAD_ATTRIB::PTH:
1907 break;
1908
1909 case PAD_ATTRIB::CONN:
1910 case PAD_ATTRIB::SMD:
1911 // SMD and PAD_ATTRIB::CONN has no hole.
1912 // basically, SMD and PAD_ATTRIB::CONN are same type of pads
1913 // PAD_ATTRIB::CONN has just a default non technical layers that differs from SMD
1914 // and are intended to be used in virtual edge board connectors
1915 // However we can accept a non null offset,
1916 // mainly to allow complex pads build from a set of basic pad shapes
1917 aPad->SetDrillSize( VECTOR2I( 0, 0 ) );
1918 break;
1919
1920 case PAD_ATTRIB::NPTH:
1921 // Mechanical purpose only:
1922 // no net name, no pad name allowed
1923 aPad->SetNumber( wxEmptyString );
1925 break;
1926
1927 default:
1928 wxFAIL_MSG( wxT( "DIALOG_PAD_PROPERTIES::transferDataToPad: unknown pad type" ) );
1929 break;
1930 }
1931
1932 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::ROUNDRECT )
1933 {
1935 }
1936 else if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::CHAMFERED_RECT )
1937 {
1939 {
1942 }
1943 else // Choice is CHOICE_SHAPE_CHAMFERED_RECT, no rounded corner
1944 {
1947 }
1948 }
1949
1951
1952 LSET padLayerMask = LSET();
1953 int copperLayersChoice = m_rbCopperLayersSel->GetSelection();
1954
1956
1957 switch( m_padType->GetSelection() )
1958 {
1959 case PTH_DLG_TYPE:
1960 switch( copperLayersChoice )
1961 {
1962 case 0:
1963 // All copper layers
1964 padLayerMask |= LSET::AllCuMask();
1965 break;
1966
1967 case 1:
1968 // Front, back and connected
1969 padLayerMask |= LSET::AllCuMask();
1972 break;
1973
1974 case 2:
1975 // Connected only
1976 padLayerMask |= LSET::AllCuMask();
1978 break;
1979
1980 case 3:
1981 // No copper layers
1982 break;
1983 }
1984
1985 break;
1986
1987 case NPTH_DLG_TYPE:
1988 switch( copperLayersChoice )
1989 {
1990 case 0: padLayerMask.set( F_Cu ).set( B_Cu ); break;
1991 case 1: padLayerMask.set( F_Cu ); break;
1992 case 2: padLayerMask.set( B_Cu ); break;
1993 default: break;
1994 }
1995
1996 break;
1997
1998 case SMD_DLG_TYPE:
1999 case CONN_DLG_TYPE:
2000 switch( copperLayersChoice )
2001 {
2002 case 0: padLayerMask.set( F_Cu ); break;
2003 case 1: padLayerMask.set( B_Cu ); break;
2004 }
2005
2006 break;
2007
2008 case APERTURE_DLG_TYPE:
2009 // no copper layers
2010 break;
2011 }
2012
2013 if( m_layerFrontAdhesive->GetValue() )
2014 padLayerMask.set( F_Adhes );
2015
2016 if( m_layerBackAdhesive->GetValue() )
2017 padLayerMask.set( B_Adhes );
2018
2019 if( m_layerFrontPaste->GetValue() )
2020 padLayerMask.set( F_Paste );
2021
2022 if( m_layerBackPaste->GetValue() )
2023 padLayerMask.set( B_Paste );
2024
2025 if( m_layerFrontSilk->GetValue() )
2026 padLayerMask.set( F_SilkS );
2027
2028 if( m_layerBackSilk->GetValue() )
2029 padLayerMask.set( B_SilkS );
2030
2031 if( m_layerFrontMask->GetValue() )
2032 padLayerMask.set( F_Mask );
2033
2034 if( m_layerBackMask->GetValue() )
2035 padLayerMask.set( B_Mask );
2036
2037 if( m_layerECO1->GetValue() )
2038 padLayerMask.set( Eco1_User );
2039
2040 if( m_layerECO2->GetValue() )
2041 padLayerMask.set( Eco2_User );
2042
2043 if( m_layerUserDwgs->GetValue() )
2044 padLayerMask.set( Dwgs_User );
2045
2046 aPad->SetLayerSet( padLayerMask );
2047
2048 return !error;
2049}
2050
2051
2052void DIALOG_PAD_PROPERTIES::OnOffsetCheckbox( wxCommandEvent& event )
2053{
2054 if( m_offsetShapeOpt->GetValue() )
2055 {
2058 }
2059
2060 // Show/hide controls depending on m_offsetShapeOpt being enabled
2061 m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
2062 m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
2063
2064 for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
2065 m_notebook->GetPage( i )->Layout();
2066
2067 OnValuesChanged( event );
2068}
2069
2070
2072{
2073 if( m_padToDieOpt->GetValue() && m_currentPad )
2075
2076 OnValuesChanged( event );
2077}
2078
2079
2081{
2082 if( m_padToDieDelayOpt->GetValue() && m_currentPad )
2084
2085 OnValuesChanged( event );
2086}
2087
2088
2089void DIALOG_PAD_PROPERTIES::onModify( wxSpinDoubleEvent& aEvent )
2090{
2091 if( m_initialized )
2092 OnModify();
2093}
2094
2095
2096void DIALOG_PAD_PROPERTIES::onModify( wxCommandEvent& aEvent )
2097{
2098 if( m_initialized )
2099 OnModify();
2100}
2101
2102
2103void DIALOG_PAD_PROPERTIES::OnValuesChanged( wxCommandEvent& event )
2104{
2105 if( m_initialized )
2106 {
2108 return;
2109
2110 // If the pad size has changed, update the displayed values for rounded rect pads.
2112
2113 redraw();
2114 OnModify();
2115 }
2116}
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:922
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition: board.h:487
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:679
bool LegacyTeardrops() const
Definition: board.h:1297
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:1011
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:894
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:66
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:212
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:143
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:112
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:67
void SetViewport(const BOX2D &aViewport)
Set the visible area of the VIEW.
Definition: view.cpp:532
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:297
void SetBoundary(const BOX2D &aBoundary)
Set limits for view area.
Definition: view.h:282
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:1675
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:198
void ClearTopLayers()
Remove all layers from the on-the-top set (they are no longer displayed over the rest of layers).
Definition: view.cpp:881
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:829
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:216
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:735
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:582
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:313
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:293
static constexpr PCB_LAYER_ID INNER_LAYERS
! The layer identifier to use for "inner layers" on top/inner/bottom padstacks
Definition: padstack.h:147
Tool relating to pads and pad settings.
Definition: pad_tool.h:37
void SetLastPadNumber(const wxString &aPadNumber)
Definition: pad_tool.h:69
wxString GetLastPadNumber() const
Definition: pad_tool.h:68
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:864
void CheckPad(UNITS_PROVIDER *aUnitsProvider, bool aForPadProperties, const std::function< void(int aErrorCode, const wxString &aMsg)> &aErrorHandler) const
Definition: pad.cpp:2241
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:456
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:285
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:931
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:964
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
Definition: pad.cpp:306
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:445
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:506
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:299
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:2600
int GetChamferPositions(PCB_LAYER_ID aLayer) const
Definition: pad.h:711
static LSET ApertureMask()
layer set for an aperture pad
Definition: pad.cpp:313
virtual const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: pad.cpp:1853
void SetRoundRectCornerRadius(PCB_LAYER_ID aLayer, double aRadius)
Has meaning only for rounded rectangle pads.
Definition: pad.cpp:462
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: pad.cpp:292
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:955
double GetChamferRectRatio(PCB_LAYER_ID aLayer) const
Definition: pad.h:694
void SetFPRelativeOrientation(const EDA_ANGLE &aAngle)
Definition: pad.cpp:946
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:939
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:1314
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:468
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:129
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:73
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:200
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:408
static constexpr EDA_ANGLE ANGLE_45
Definition: eda_angle.h:407
#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_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
constexpr 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