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 (C) 1992-2024 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 <pcb_base_frame.h>
45#include <pcb_painter.h>
46#include <pcbnew_settings.h>
48#include <view/view_controls.h>
50#include <tool/tool_manager.h>
51#include <tools/pad_tool.h>
52#include <advanced_config.h> // for pad property feature management
53#include <wx/choicdlg.h>
54
55
56int DIALOG_PAD_PROPERTIES::m_page = 0; // remember the last open page during session
57
58
59// list of pad shapes, ordered like the pad shape wxChoice in dialog.
61{
68 PAD_SHAPE::CHAMFERED_RECT, // choice = CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT
69 PAD_SHAPE::CUSTOM, // choice = CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
70 PAD_SHAPE::CUSTOM // choice = PAD_SHAPE::CUSTOM_RECT_ANCHOR
71};
72
73
74// the ordered index of the pad shape wxChoice in dialog.
75// keep it consistent with code_shape[] and dialog strings
77{
87};
88
89
91{
96 PAD_ATTRIB::SMD // Aperture pad :type SMD with no copper layers,
97 // only on tech layers (usually only on paste layer
98};
99
100
101// These define have the same value as the m_PadType wxChoice GetSelected() return value
102#define PTH_DLG_TYPE 0
103#define SMD_DLG_TYPE 1
104#define CONN_DLG_TYPE 2
105#define NPTH_DLG_TYPE 3
106#define APERTURE_DLG_TYPE 4
107
108
113static bool PadHasMeaningfulRoundingRadius( const PAD& aPad, PCB_LAYER_ID aLayer )
114{
115 const PAD_SHAPE shape = aPad.GetShape( aLayer );
116 return shape == PAD_SHAPE::ROUNDRECT || shape == PAD_SHAPE::CHAMFERED_RECT;
117}
118
119
125static double GetDefaultIpcRoundingRatio( const PAD& aPad, PCB_LAYER_ID aLayer )
126{
127 const double defaultProportion = 0.25;
128 const double minimumSizeIU = pcbIUScale.mmToIU( 0.25 );
129
130 const VECTOR2I& size = aPad.GetSize( aLayer );
131 const int padMinSizeIU = std::min( size.x, size.y );
132 const double defaultRadiusIU = std::min( minimumSizeIU, padMinSizeIU * defaultProportion );
133
134 // Convert back to a ratio
135 return defaultRadiusIU / padMinSizeIU;
136}
137
138
140{
141 DIALOG_PAD_PROPERTIES dlg( this, aPad );
142
143 // QuasiModal required for NET_SELECTOR
144 dlg.ShowQuasiModal();
145}
146
147
150 m_parent( aParent ),
151 m_initialized( false ),
152 m_editLayer( F_Cu ),
153 m_posX( aParent, m_posXLabel, m_posXCtrl, m_posXUnits ),
154 m_posY( aParent, m_posYLabel, m_posYCtrl, m_posYUnits ),
155 m_sizeX( aParent, m_sizeXLabel, m_sizeXCtrl, m_sizeXUnits ),
156 m_sizeY( aParent, m_sizeYLabel, m_sizeYCtrl, m_sizeYUnits ),
157 m_offsetX( aParent, m_offsetXLabel, m_offsetXCtrl, m_offsetXUnits ),
158 m_offsetY( aParent, m_offsetYLabel, m_offsetYCtrl, m_offsetYUnits ),
159 m_padToDie( aParent, m_padToDieLabel, m_padToDieCtrl, m_padToDieUnits ),
160 m_trapDelta( aParent, m_trapDeltaLabel, m_trapDeltaCtrl, m_trapDeltaUnits ),
161 m_cornerRadius( aParent, m_cornerRadiusLabel, m_cornerRadiusCtrl, m_cornerRadiusUnits ),
162 m_cornerRatio( aParent, m_cornerRatioLabel, m_cornerRatioCtrl, m_cornerRatioUnits ),
163 m_chamferRatio( aParent, m_chamferRatioLabel, m_chamferRatioCtrl, m_chamferRatioUnits ),
164 m_mixedCornerRatio( aParent, m_mixedCornerRatioLabel, m_mixedCornerRatioCtrl,
165 m_mixedCornerRatioUnits ),
166 m_mixedChamferRatio( aParent, m_mixedChamferRatioLabel, m_mixedChamferRatioCtrl,
167 m_mixedChamferRatioUnits ),
168 m_holeX( aParent, m_holeXLabel, m_holeXCtrl, m_holeXUnits ),
169 m_holeY( aParent, m_holeYLabel, m_holeYCtrl, m_holeYUnits ),
170 m_clearance( aParent, m_clearanceLabel, m_clearanceCtrl, m_clearanceUnits ),
171 m_maskMargin( aParent, m_maskMarginLabel, m_maskMarginCtrl, m_maskMarginUnits ),
172 m_pasteMargin( aParent, m_pasteMarginLabel, m_pasteMarginCtrl, m_pasteMarginUnits ),
173 m_pasteMarginRatio( aParent, m_pasteMarginRatioLabel, m_pasteMarginRatioCtrl,
174 m_pasteMarginRatioUnits ),
175 m_thermalGap( aParent, m_thermalGapLabel, m_thermalGapCtrl, m_thermalGapUnits ),
176 m_spokeWidth( aParent, m_spokeWidthLabel, m_spokeWidthCtrl, m_spokeWidthUnits ),
177 m_spokeAngle( aParent, m_spokeAngleLabel, m_spokeAngleCtrl, m_spokeAngleUnits ),
178 m_pad_orientation( aParent, m_PadOrientText, m_cb_padrotation, m_orientationUnits ),
179 m_teardropMaxLenSetting( aParent, m_stMaxLen, m_tcTdMaxLen, m_stMaxLenUnits ),
180 m_teardropMaxHeightSetting( aParent, m_stTdMaxSize, m_tcMaxHeight, m_stMaxHeightUnits )
181{
182 SetName( PAD_PROPERTIES_DLG_NAME );
183 m_isFpEditor = dynamic_cast<FOOTPRINT_EDIT_FRAME*>( aParent ) != nullptr;
184
185 m_currentPad = aPad; // aPad can be NULL, if the dialog is called
186 // from the footprint editor to set default pad setup
187
189
190 // Configure display origin transforms
193
196
198
199 m_FlippedWarningIcon->SetBitmap( KiBitmapBundle( BITMAPS::dialog_warning ) );
200 m_nonCopperWarningIcon->SetBitmap( KiBitmapBundle( BITMAPS::dialog_warning ) );
201 m_legacyTeardropsIcon->SetBitmap( KiBitmapBundle( BITMAPS::dialog_warning ) );
202
204 m_previewPad = new PAD( (FOOTPRINT*) nullptr );
205
206 if( aPad )
207 {
208 SetTitle( _( "Pad Properties" ) );
209
210 *m_previewPad = *aPad;
213 }
214 else
215 {
216 SetTitle( _( "Default Pad Properties for Add Pad Tool" ) );
217
220 }
221
222 // TODO(JE) padstacks: should this be re-run when pad mode changes?
223 // Pads have a hardcoded internal rounding ratio which is 0.25 by default, even if
224 // they're not a rounded shape. This makes it hard to detect an intentional 0.25
225 // ratio, or one that's only there because it's the PAD default.
226 // Zero it out here to mark that we should recompute a better ratio if the user
227 // selects a pad shape which would need a default rounding ratio computed for it
229 [&]( PCB_LAYER_ID aLayer )
230 {
233 } );
234
235 if( m_isFpEditor )
236 {
237 m_padNetLabel->Show( false );
238 m_padNetSelector->Show( false );
239 }
240
241 m_FlippedWarningSizer->Show( false );
242
243 // Pad needs to have a parent for painting; use the parent board for its design settings
244 if( !m_previewPad->GetParent() )
246
247 m_cornerRatio.SetUnits( EDA_UNITS::PERCENT );
248 m_chamferRatio.SetUnits( EDA_UNITS::PERCENT );
249 m_mixedCornerRatio.SetUnits( EDA_UNITS::PERCENT );
250 m_mixedChamferRatio.SetUnits( EDA_UNITS::PERCENT );
251 m_pad_orientation.SetUnits( EDA_UNITS::DEGREES );
253
254 m_spokeAngle.SetUnits( EDA_UNITS::DEGREES );
256
258
259 m_pasteMarginRatio.SetUnits( EDA_UNITS::PERCENT );
261
262 initValues();
263
264 wxFont infoFont = KIUI::GetInfoFont( this );
265 m_copperLayersLabel->SetFont( infoFont );
266 m_techLayersLabel->SetFont( infoFont );
267 m_parentInfo->SetFont( infoFont );
268 m_teardropShapeLabel->SetFont( infoFont );
269
270 infoFont.SetStyle( wxFONTSTYLE_ITALIC );
271 m_nonCopperNote->SetFont( infoFont );
272 m_staticTextInfoPaste->SetFont( infoFont );
273
276
277 // Usually, TransferDataToWindow is called by OnInitDialog
278 // calling it here fixes all widget sizes so FinishDialogSettings can safely fix minsizes
280
281 // Initialize canvas to be able to display the dummy pad:
283
284 m_notebook->SetSelection( m_page );
285
286 switch( m_page )
287 {
288 default:
289 case 0: SetInitialFocus( m_padNumCtrl ); break;
290 case 1: SetInitialFocus( m_thermalGapCtrl ); break;
291 case 2: SetInitialFocus( m_clearanceCtrl ); break;
292 }
293
295 m_initialized = true;
296
297 m_padNetSelector->Connect( FILTERED_ITEM_SELECTED,
298 wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ),
299 nullptr, this );
300
301 if( m_padType->GetSelection() != PTH_DLG_TYPE && m_padType->GetSelection() != NPTH_DLG_TYPE )
302 {
303 m_gbSizerHole->Show( false );
304 m_staticline6->Show( false );
305 }
306
307 // Now all widgets have the size fixed, call FinishDialogSettings
309
310 // Update widgets
311 wxUpdateUIEvent dummyUI;
312 OnUpdateUI( dummyUI );
313
314 // Post a dummy size event to force the pad preview panel to update the
315 // view: actual size, best zoom ... after the frame is shown
316 PostSizeEvent();
317}
318
319
321{
322 m_padNetSelector->Disconnect( FILTERED_ITEM_SELECTED,
323 wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ),
324 nullptr, this );
325
326 m_page = m_notebook->GetSelection();
327
328 // Remove the preview pad from the group of the actual pad before deletion
329 if( m_previewPad )
330 m_previewPad->SetParentGroup( nullptr );
331
332 delete m_previewPad;
333 delete m_axisOrigin;
334}
335
336
337// Store the pad draw option during a session.
339
340
341void DIALOG_PAD_PROPERTIES::OnInitDialog( wxInitDialogEvent& event )
342{
343 m_selectedColor = COLOR4D( 1.0, 1.0, 1.0, 0.7 );
344
345 // Needed on some WM to be sure the pad is redrawn according to the final size
346 // of the canvas, with the right zoom factor
347 redraw();
348}
349
350
351void DIALOG_PAD_PROPERTIES::OnCancel( wxCommandEvent& event )
352{
353 // Mandatory to avoid m_panelShowPadGal trying to draw something
354 // in a non valid context during closing process:
356
357 // Now call default handler for wxID_CANCEL command event
358 event.Skip();
359}
360
361
363{
365 COLOR_SETTINGS* colorSettings = m_parent->GetColorSettings();
366
367 opts.m_forceDisplayCursor = false;
368
369 // Initialize the canvas to display the pad
370 m_padPreviewGAL = new PCB_DRAW_PANEL_GAL( m_boardViewPanel, -1, wxDefaultPosition,
371 wxDefaultSize, opts,
373
374 m_padPreviewSizer->Add( m_padPreviewGAL, 12, wxEXPAND | wxALL, 5 );
375
376 // Show the X and Y axis. It is useful because pad shape can have an offset
377 // or be a complex shape.
382
385 m_padPreviewGAL->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
386
387 KIGFX::VIEW_CONTROLS* parentViewControls = m_parent->GetCanvas()->GetViewControls();
388 m_padPreviewGAL->GetViewControls()->ApplySettings( parentViewControls->GetSettings() );
389
390 m_padPreviewGAL->Show();
391
393
394 // fix the pad render mode (filled/not filled)
395 auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
396
397 settings->m_ForcePadSketchModeOn = m_cbShowPadOutline->IsChecked();
398 settings->SetHighContrast( false );
399 settings->m_ContrastModeDisplay = HIGH_CONTRAST_MODE::NORMAL;
400
401 // gives a non null grid size (0.001mm) because GAL layer does not like a 0 size grid:
402 double gridsize = 0.001 * pcbIUScale.IU_PER_MM;
403 view->GetGAL()->SetGridSize( VECTOR2D( gridsize, gridsize ) );
404
405 // And do not show the grid:
406 view->GetGAL()->SetGridVisibility( false );
407 view->GetGAL()->SetAxesEnabled( false );
408 view->Add( m_previewPad );
409 view->Add( m_axisOrigin );
410
412 Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_PAD_PROPERTIES::OnResize ) );
413}
414
415
417{
420 redraw();
421}
422
423
424void DIALOG_PAD_PROPERTIES::OnEditLayerChanged( wxCommandEvent& aEvent )
425{
426 // Save data from the previous layer
428
429 switch( m_previewPad->Padstack().Mode() )
430 {
431 default:
434 break;
435
437 switch( m_cbEditLayer->GetSelection() )
438 {
439 default:
440 case 0: m_editLayer = F_Cu; break;
441 case 1: m_editLayer = PADSTACK::INNER_LAYERS; break;
442 case 2: m_editLayer = B_Cu; break;
443 }
444 break;
445
447 {
448 int layer = m_cbEditLayer->GetSelection();
449
450 if( layer < 0 )
451 layer = 0;
452
453 if( m_editLayerCtrlMap.contains( layer ) )
454 m_editLayer = m_editLayerCtrlMap.at( layer );
455 else
457 }
458 }
459
460 // Load controls with the current layer
462 redraw();
463}
464
465
467{
468 // Note: use ChangeValue() to avoid generating a wxEVT_TEXT event
470
473
476}
477
478
480{
481 if( m_previewPad->GetShape( m_editLayer ) != PAD_SHAPE::ROUNDRECT
482 && m_previewPad->GetShape( m_editLayer ) != PAD_SHAPE::CHAMFERED_RECT )
483 {
484 return;
485 }
486
487 if( m_cornerRadius.GetValue() < 0 )
488 m_cornerRadiusCtrl->ChangeValue( "0" );
489
491 {
493
496
497 redraw();
498 }
499
500 if( m_initialized )
501 OnModify();
502}
503
504
506{
507 if( m_previewPad->GetShape( m_editLayer ) != PAD_SHAPE::ROUNDRECT
508 && m_previewPad->GetShape( m_editLayer ) != PAD_SHAPE::CHAMFERED_RECT )
509 {
510 return;
511 }
512
513 wxObject* ctrl = event.GetEventObject();
514 wxString value = event.GetString();
515 bool changed = false;
516
517 if( ctrl == m_cornerRatioCtrl || ctrl == m_mixedCornerRatioCtrl )
518 {
519 double ratioPercent;
520
521 if( value.ToDouble( &ratioPercent ) )
522 {
523 // Clamp ratioPercent to acceptable value (0.0 to 50.0)
524 if( ratioPercent < 0.0 )
525 {
528 }
529 else if( ratioPercent > 50.0 )
530 {
533 }
534
535 if( ctrl == m_cornerRatioCtrl )
536 m_mixedCornerRatioCtrl->ChangeValue( value );
537 else
538 m_cornerRatioCtrl->ChangeValue( value );
539
540 changed = true;
541 }
542 }
543 else if( ctrl == m_chamferRatioCtrl || ctrl == m_mixedChamferRatioCtrl )
544 {
545 double ratioPercent;
546
547 if( value.ToDouble( &ratioPercent ) )
548 {
549 // Clamp ratioPercent to acceptable value (0.0 to 50.0)
550 if( ratioPercent < 0.0 )
551 {
554 }
555 else if( ratioPercent > 50.0 )
556 {
559 }
560
561 if( ctrl == m_chamferRatioCtrl )
562 m_mixedChamferRatioCtrl->ChangeValue( value );
563 else
564 m_chamferRatioCtrl->ChangeValue( value );
565
566 changed = true;
567 }
568 }
569
570 if( changed && transferDataToPad( m_previewPad ) )
572
573 redraw();
574
575 if( m_initialized )
576 OnModify();
577}
578
579
581{
582 wxString msg;
583
584 // Disable pad net name wxTextCtrl if the caller is the footprint editor
585 // because nets are living only in the board managed by the board editor
587
596 m_layerECO1->SetLabel( m_board->GetLayerName( Eco1_User ) );
597 m_layerECO2->SetLabel( m_board->GetLayerName( Eco2_User ) );
599
600 VECTOR2I absPos;
601
602 if( m_currentPad )
603 {
604 absPos = m_currentPad->GetPosition();
605
606 if( FOOTPRINT* footprint = m_currentPad->GetParentFootprint() )
607 {
609
610 if( footprint->IsFlipped() )
611 {
612 // flip pad (up/down) around its position
613 m_previewPad->Flip( m_previewPad->GetPosition(), FLIP_DIRECTION::TOP_BOTTOM );
614 relPos.y = - relPos.y;
615 }
616
617 m_previewPad->SetPosition( relPos );
619
620 // Display parent footprint info
621 msg.Printf( _("Footprint %s (%s), %s, rotated %g deg"),
622 footprint->Reference().GetShownText( false ),
623 footprint->Value().GetShownText( false ),
624 footprint->IsFlipped() ? _( "back side (mirrored)" ) : _( "front side" ),
625 footprint->GetOrientation().AsDegrees() );
626
627 m_FlippedWarningSizer->Show( footprint->IsFlipped() );
628 m_parentInfo->SetLabel( msg );
629 }
630
631 m_padNumCtrl->SetValue( m_previewPad->GetNumber() );
632 }
633 else
634 {
636 m_padNumCtrl->SetValue( padTool->GetLastPadNumber() );
637
639 {
641 {
642 case FOOTPRINT_ATTR_T::FP_THROUGH_HOLE:
643 m_previewPad->SetAttribute( PAD_ATTRIB::PTH );
644
645 if( m_previewPad->GetDrillSizeX() == 0 )
647
648 break;
649
650 case FOOTPRINT_ATTR_T::FP_SMD:
652 m_previewPad->SetAttribute( PAD_ATTRIB::SMD );
653 break;
654 }
655 }
656 }
657
659
661
662 // Display current pad parameters units:
663 m_posX.ChangeValue( absPos.x );
664 m_posY.ChangeValue( absPos.y );
665
668
669 // TODO(JE) padstacks -- does this need to be saved/restored every time the layer changes?
670 // Store the initial thermal spoke angle to restore it, because some initializations
671 // can change this value (mainly after m_PadShapeSelector initializations)
672 EDA_ANGLE spokeInitialAngle = m_previewPad->GetThermalSpokeAngle();
673
675
676 m_padToDieOpt->SetValue( m_previewPad->GetPadToDieLength() != 0 );
678
679 if( m_previewPad->GetLocalClearance().has_value() )
681 else
682 m_clearance.ChangeValue( wxEmptyString );
683
684 if( m_previewPad->GetLocalSolderMaskMargin().has_value() )
686 else
687 m_maskMargin.ChangeValue( wxEmptyString );
688
689 if( m_previewPad->GetLocalSolderPasteMargin().has_value() )
691 else
692 m_pasteMargin.ChangeValue( wxEmptyString );
693
696 else
697 m_pasteMarginRatio.ChangeValue( wxEmptyString );
698
703
712
714
716 {
717 default:
718 case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
719 case ZONE_CONNECTION::FULL: m_ZoneConnectionChoice->SetSelection( 1 ); break;
720 case ZONE_CONNECTION::THERMAL: m_ZoneConnectionChoice->SetSelection( 2 ); break;
721 case ZONE_CONNECTION::NONE: m_ZoneConnectionChoice->SetSelection( 3 ); break;
722 }
723
725 m_ZoneCustomPadShape->SetSelection( 1 );
726 else
727 m_ZoneCustomPadShape->SetSelection( 0 );
728
729 // Type of pad selection
730 bool aperture =
731 m_previewPad->GetAttribute() == PAD_ATTRIB::SMD && m_previewPad->IsAperturePad();
732
733 if( aperture )
734 {
735 m_padType->SetSelection( APERTURE_DLG_TYPE );
736 }
737 else
738 {
739 switch( m_previewPad->GetAttribute() )
740 {
741 case PAD_ATTRIB::PTH: m_padType->SetSelection( PTH_DLG_TYPE ); break;
742 case PAD_ATTRIB::SMD: m_padType->SetSelection( SMD_DLG_TYPE ); break;
743 case PAD_ATTRIB::CONN: m_padType->SetSelection( CONN_DLG_TYPE ); break;
744 case PAD_ATTRIB::NPTH: m_padType->SetSelection( NPTH_DLG_TYPE ); break;
745 }
746 }
747
748 switch( m_previewPad->GetProperty() )
749 {
750 case PAD_PROP::NONE: m_choiceFabProperty->SetSelection( 0 ); break;
751 case PAD_PROP::BGA: m_choiceFabProperty->SetSelection( 1 ); break;
752 case PAD_PROP::FIDUCIAL_LOCAL: m_choiceFabProperty->SetSelection( 2 ); break;
753 case PAD_PROP::FIDUCIAL_GLBL: m_choiceFabProperty->SetSelection( 3 ); break;
754 case PAD_PROP::TESTPOINT: m_choiceFabProperty->SetSelection( 4 ); break;
755 case PAD_PROP::HEATSINK: m_choiceFabProperty->SetSelection( 5 ); break;
756 case PAD_PROP::CASTELLATED: m_choiceFabProperty->SetSelection( 6 ); break;
757 case PAD_PROP::MECHANICAL: m_choiceFabProperty->SetSelection( 7 ); break;
758 }
759
760 // Ensure the pad property is compatible with the pad type
761 if( m_previewPad->GetAttribute() == PAD_ATTRIB::NPTH )
762 {
763 m_choiceFabProperty->SetSelection( 0 );
764 m_choiceFabProperty->Enable( false );
765 }
766
767 if( m_previewPad->GetDrillShape() != PAD_DRILL_SHAPE::OBLONG )
768 m_holeShapeCtrl->SetSelection( 0 );
769 else
770 m_holeShapeCtrl->SetSelection( 1 );
771
774
775 // Update some dialog widgets state (Enable/disable options):
776 wxCommandEvent cmd_event;
777 OnPadShapeSelection( cmd_event );
778 OnOffsetCheckbox( cmd_event );
779
780 // Restore thermal spoke angle to its initial value, because it can be modified
781 // by the call to OnPadShapeSelection()
782 m_previewPad->SetThermalSpokeAngle( spokeInitialAngle );
784}
785
786
788{
790
793
797
799 {
801 m_trapAxisCtrl->SetSelection( 0 );
802 }
803 else
804 {
806 m_trapAxisCtrl->SetSelection( 1 );
807 }
808
809 switch( m_previewPad->GetShape( m_editLayer ) )
810 {
811 default:
812 case PAD_SHAPE::CIRCLE: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_CIRCLE ); break;
813 case PAD_SHAPE::OVAL: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_OVAL ); break;
814 case PAD_SHAPE::RECTANGLE: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_RECT ); break;
815 case PAD_SHAPE::TRAPEZOID: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_TRAPEZOID ); break;
816 case PAD_SHAPE::ROUNDRECT: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_ROUNDRECT ); break;
817
818 case PAD_SHAPE::CHAMFERED_RECT:
821 else
823 break;
824
825 case PAD_SHAPE::CUSTOM:
826 if( m_previewPad->GetAnchorPadShape( m_editLayer ) == PAD_SHAPE::RECTANGLE )
828 else
830 break;
831 }
832
833 int chamferPositions = m_previewPad->GetChamferPositions( m_editLayer );
834
835 m_cbTopLeft->SetValue( chamferPositions & RECT_CHAMFER_TOP_LEFT );
836 m_cbTopLeft1->SetValue( chamferPositions & RECT_CHAMFER_TOP_LEFT );
837 m_cbTopRight->SetValue( chamferPositions & RECT_CHAMFER_TOP_RIGHT );
838 m_cbTopRight1->SetValue( chamferPositions & RECT_CHAMFER_TOP_RIGHT );
839 m_cbBottomLeft->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_LEFT );
840 m_cbBottomLeft1->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_LEFT );
841 m_cbBottomRight->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_RIGHT );
842 m_cbBottomRight1->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_RIGHT );
843
845}
846
847
849{
850 // NOTE: synchronize changes here with DIALOG_TRACK_VIA_PROPERTIES::afterPadstackModeChanged
851
852 wxCHECK_MSG( m_board, /* void */, "Expected valid board in afterPadstackModeChanged" );
853 m_cbEditLayer->Clear();
854
855 switch( m_previewPad->Padstack().Mode() )
856 {
858 m_cbPadstackMode->SetSelection( 0 );
859 m_cbEditLayer->Append( m_board->GetLayerName( F_Cu ) );
860 m_cbEditLayer->Disable();
862 m_editLayerCtrlMap = { { 0, F_Cu } };
863 break;
864
866 {
867 m_cbPadstackMode->SetSelection( 1 );
868 m_cbEditLayer->Enable();
869
870 std::vector choices = {
872 _( "Inner Layers" ),
874 };
875
876 m_cbEditLayer->Append( choices );
877
879 { 0, F_Cu },
881 { 2, B_Cu }
882 };
883
884 if( m_editLayer != F_Cu && m_editLayer != B_Cu )
886
887 break;
888 }
889
891 {
892 m_cbPadstackMode->SetSelection( 2 );
893 m_cbEditLayer->Enable();
895
896 for( PCB_LAYER_ID layer : layers.UIOrder() )
897 {
898 int idx = m_cbEditLayer->Append( m_board->GetLayerName( layer ) );
899 m_editLayerCtrlMap[idx] = layer;
900 }
901
902 break;
903 }
904 }
905
906 for( const auto& [idx, layer] : m_editLayerCtrlMap )
907 {
908 if( layer == m_editLayer )
909 {
910 m_cbEditLayer->SetSelection( idx );
911 break;
912 }
913 }
914}
915
916
917void DIALOG_PAD_PROPERTIES::OnResize( wxSizeEvent& event )
918{
919 redraw();
920 event.Skip();
921}
922
923
924void DIALOG_PAD_PROPERTIES::onChangePadMode( wxCommandEvent& event )
925{
927
929
930 // fix the pad render mode (filled/not filled)
931 auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
932
933 settings->m_ForcePadSketchModeOn = m_cbShowPadOutline->IsChecked();
934 settings->SetHighContrast( false );
935 settings->m_ContrastModeDisplay = HIGH_CONTRAST_MODE::NORMAL;
936
937 redraw();
938}
939
940
942{
943 switch( m_PadShapeSelector->GetSelection() )
944 {
948 m_shapePropsBook->SetSelection( 0 );
949 break;
950
952 m_shapePropsBook->SetSelection( 1 );
953 break;
954
956 {
957 m_shapePropsBook->SetSelection( 2 );
958
959 // Reasonable defaults
961 {
964 }
965
966 break;
967 }
968
970 m_shapePropsBook->SetSelection( 3 );
971
972 // Reasonable default
975
976 // Ensure the displayed value is up to date:
978
979 // A reasonable default is one corner chamfered (usual for some SMD pads).
980 if( !m_cbTopLeft->GetValue() && !m_cbTopRight->GetValue()
981 && !m_cbBottomLeft->GetValue() && !m_cbBottomRight->GetValue() )
982 {
983 m_cbTopLeft->SetValue( true );
984 m_cbTopRight->SetValue( false );
985 m_cbBottomLeft->SetValue( false );
986 m_cbBottomRight->SetValue( false );
987 }
988
989 break;
990
992 m_shapePropsBook->SetSelection( 4 );
993
994 // Reasonable defaults
997 {
1001 }
1002
1003 // Ensure the displayed values are up to date:
1006 break;
1007
1008 case CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR: // PAD_SHAPE::CUSTOM, circular anchor
1009 case CHOICE_SHAPE_CUSTOM_RECT_ANCHOR: // PAD_SHAPE::CUSTOM, rect anchor
1010 m_shapePropsBook->SetSelection( 0 );
1011 break;
1012 }
1013
1014 // Note: must do this before enabling/disabling m_sizeY as we're using that as a flag to see
1015 // what the last shape was.
1016 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CIRCLE )
1017 {
1018 if( m_sizeYCtrl->IsEnabled() && m_spokeAngle.GetAngleValue() == ANGLE_90 )
1020 }
1021 else
1022 {
1023 if( !m_sizeYCtrl->IsEnabled() && m_spokeAngle.GetAngleValue() == ANGLE_45 )
1025 }
1026
1027 // Readjust props book size
1028 wxSize size = m_shapePropsBook->GetSize();
1029 size.y = m_shapePropsBook->GetPage( m_shapePropsBook->GetSelection() )->GetBestSize().y;
1030 m_shapePropsBook->SetMaxSize( size );
1031
1034
1035 m_offsetShapeOpt->Enable( m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CIRCLE );
1036
1037 if( !m_offsetShapeOpt->IsEnabled() )
1038 m_offsetShapeOpt->SetValue( false );
1039
1040 // Show/hide controls depending on m_offsetShapeOpt being enabled
1041 m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
1042 m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
1043
1046
1047 for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
1048 m_notebook->GetPage( i )->Layout();
1049
1050 // Resize the dialog if its height is too small to show all widgets:
1051 if( m_MainSizer->GetSize().y < m_MainSizer->GetMinSize().y )
1052 m_MainSizer->SetSizeHints( this );
1053
1055 redraw();
1056
1057 if( m_initialized )
1058 OnModify();
1059}
1060
1061
1063{
1066 redraw();
1067
1068 if( m_initialized )
1069 OnModify();
1070}
1071
1072
1073void DIALOG_PAD_PROPERTIES::PadOrientEvent( wxCommandEvent& event )
1074{
1076 redraw();
1077
1078 if( m_initialized )
1079 OnModify();
1080}
1081
1082
1084{
1085 m_rbCopperLayersSel->Clear();
1086
1087 switch( m_padType->GetSelection() )
1088 {
1089 case PTH_DLG_TYPE:
1090 m_rbCopperLayersSel->Append( _( "All copper layers" ) );
1091 m_rbCopperLayersSel->Append( wxString::Format( _( "%s, %s and connected layers" ),
1093 m_board->GetLayerName( B_Cu ) ) );
1094 m_rbCopperLayersSel->Append( _( "Connected layers only" ) );
1095 m_rbCopperLayersSel->Append( _( "None" ) );
1096 break;
1097
1098 case NPTH_DLG_TYPE:
1099 m_rbCopperLayersSel->Append( wxString::Format( _( "%s and %s" ),
1101 m_board->GetLayerName( B_Cu ) ) );
1104 m_rbCopperLayersSel->Append( _( "None" ) );
1105 break;
1106
1107 case SMD_DLG_TYPE:
1108 case CONN_DLG_TYPE:
1111 break;
1112
1113 case APERTURE_DLG_TYPE:
1114 m_rbCopperLayersSel->Append( _( "None" ) );
1115 break;
1116 }
1117}
1118
1119
1120void DIALOG_PAD_PROPERTIES::PadTypeSelected( wxCommandEvent& event )
1121{
1122 bool hasHole = true;
1123 bool hasConnection = true;
1124 bool hasProperty = true;
1125
1126 switch( m_padType->GetSelection() )
1127 {
1128 case PTH_DLG_TYPE: hasHole = true; hasConnection = true; hasProperty = true; break;
1129 case SMD_DLG_TYPE: hasHole = false; hasConnection = true; hasProperty = true; break;
1130 case CONN_DLG_TYPE: hasHole = false; hasConnection = true; hasProperty = true; break;
1131 case NPTH_DLG_TYPE: hasHole = true; hasConnection = false; hasProperty = false; break;
1132 case APERTURE_DLG_TYPE: hasHole = false; hasConnection = false; hasProperty = true; break;
1133 }
1134
1135 // Update Layers dropdown list and selects the "best" layer set for the new pad type:
1138
1139 m_gbSizerHole->Show( hasHole );
1140 m_staticline6->Show( hasHole );
1141
1142 if( !hasHole )
1143 {
1144 m_holeX.ChangeValue( 0 );
1145 m_holeY.ChangeValue( 0 );
1146 }
1147 else if( m_holeX.GetValue() == 0 )
1148 {
1149 if( m_currentPad )
1150 {
1153 }
1154 else
1155 {
1157 }
1158 }
1159
1160 if( !hasConnection )
1161 {
1162 m_padNumCtrl->ChangeValue( wxEmptyString );
1164 m_padToDieOpt->SetValue( false );
1165 }
1166 else if( m_padNumCtrl->GetValue().IsEmpty() && m_currentPad )
1167 {
1168 m_padNumCtrl->ChangeValue( m_currentPad->GetNumber() );
1170 }
1171
1172 if( !hasProperty )
1173 m_choiceFabProperty->SetSelection( 0 );
1174
1175 m_choiceFabProperty->Enable( hasProperty );
1176
1178
1179 // For now, padstack controls only enabled for PTH pads
1180 bool enablePadstack = m_padType->GetSelection() == PTH_DLG_TYPE;
1181 m_padstackControls->Show( enablePadstack );
1182
1183 if( !enablePadstack )
1184 {
1185 m_editLayer = F_Cu;
1187 }
1188
1189 // Layout adjustment is needed if the hole details got shown/hidden
1190 m_LeftBoxSizer->Layout();
1191 redraw();
1192
1193 if( m_initialized )
1194 OnModify();
1195}
1196
1197
1198void DIALOG_PAD_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
1199{
1200 bool hasHole = true;
1201 bool hasConnection = true;
1202
1203 switch( m_padType->GetSelection() )
1204 {
1205 case PTH_DLG_TYPE: /* PTH */ hasHole = true; hasConnection = true; break;
1206 case SMD_DLG_TYPE: /* SMD */ hasHole = false; hasConnection = true; break;
1207 case CONN_DLG_TYPE: /* CONN */ hasHole = false; hasConnection = true; break;
1208 case NPTH_DLG_TYPE: /* NPTH */ hasHole = true; hasConnection = false; break;
1209 case APERTURE_DLG_TYPE: /* Aperture */ hasHole = false; hasConnection = false; break;
1210 }
1211
1212 // Enable/disable hole controls
1213 m_holeShapeLabel->Enable( hasHole );
1214 m_holeShapeCtrl->Enable( hasHole );
1215 m_holeX.Enable( hasHole );
1216 m_holeY.Enable( hasHole && m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_OVAL );
1217
1218 // Enable/disable number and net
1219 m_padNumLabel->Enable( hasConnection );
1220 m_padNumCtrl->Enable( hasConnection );
1221
1222 if( m_padNetLabel->IsShown() )
1223 {
1224 m_padNetLabel->Enable( hasConnection && m_canEditNetName && m_currentPad );
1225 m_padNetSelector->Enable( hasConnection && m_canEditNetName && m_currentPad );
1226 }
1227
1228 // Enable/disable pad length-to-die
1229 m_padToDieOpt->Enable( hasConnection );
1230
1231 if( !m_padToDieOpt->IsEnabled() )
1232 m_padToDieOpt->SetValue( false );
1233
1234 // We can show/hide this here because it doesn't require the layout to be refreshed.
1235 // All the others have to be done in their event handlers because doing a layout here
1236 // causes infinite looping on MSW.
1237 m_padToDie.Show( m_padToDieOpt->GetValue() );
1238
1239 // Enable/disable Copper Layers control
1240 m_rbCopperLayersSel->Enable( m_padType->GetSelection() != APERTURE_DLG_TYPE );
1241
1243
1244 switch( m_padType->GetSelection() )
1245 {
1246 case PTH_DLG_TYPE:
1247 if( !cu_set.any() )
1248 m_stackupImagesBook->SetSelection( 3 );
1249 else if( !m_previewPad->GetRemoveUnconnected() )
1250 m_stackupImagesBook->SetSelection( 0 );
1251 else if( m_previewPad->GetKeepTopBottom() )
1252 m_stackupImagesBook->SetSelection( 1 );
1253 else
1254 m_stackupImagesBook->SetSelection( 2 );
1255
1256 break;
1257
1258 case NPTH_DLG_TYPE:
1259 if( cu_set.test( F_Cu ) && cu_set.test( B_Cu ) )
1260 m_stackupImagesBook->SetSelection( 4 );
1261 else if( cu_set.test( F_Cu ) )
1262 m_stackupImagesBook->SetSelection( 5 );
1263 else if( cu_set.test( B_Cu ) )
1264 m_stackupImagesBook->SetSelection( 6 );
1265 else
1266 m_stackupImagesBook->SetSelection( 7 );
1267
1268 break;
1269
1270 case SMD_DLG_TYPE:
1271 case CONN_DLG_TYPE:
1272 case APERTURE_DLG_TYPE:
1273 m_stackupImagesBook->ChangeSelection( 3 );
1274 break;
1275 }
1276
1278}
1279
1280
1282{
1283 event.Enable( !m_board->LegacyTeardrops() );
1284}
1285
1286
1288{
1289 event.Enable( !m_board->LegacyTeardrops() && m_curvedEdges->GetValue() );
1290}
1291
1292
1294{
1295 bool isOnCopperLayer = ( m_previewPad->GetLayerSet() & LSET::AllCuMask() ).any();
1296 m_nonCopperWarningBook->ChangeSelection( isOnCopperLayer ? 0 : 1 );
1297}
1298
1299
1300void DIALOG_PAD_PROPERTIES::updatePadLayersList( LSET layer_mask, bool remove_unconnected,
1301 bool keep_top_bottom )
1302{
1304
1305 switch( m_padType->GetSelection() )
1306 {
1307 case PTH_DLG_TYPE:
1308 if( !layer_mask.any() )
1309 layer_mask = PAD::PTHMask();
1310
1311 if( !( layer_mask & LSET::AllCuMask() ).any() )
1312 m_rbCopperLayersSel->SetSelection( 3 );
1313 else if( !remove_unconnected )
1314 m_rbCopperLayersSel->SetSelection( 0 );
1315 else if( keep_top_bottom )
1316 m_rbCopperLayersSel->SetSelection( 1 );
1317 else
1318 m_rbCopperLayersSel->SetSelection( 2 );
1319
1320 break;
1321
1322 case SMD_DLG_TYPE:
1323 if( !layer_mask.any() )
1324 layer_mask = PAD::SMDMask();
1325
1326 if( layer_mask.test( F_Cu ) )
1327 m_rbCopperLayersSel->SetSelection( 0 );
1328 else
1329 m_rbCopperLayersSel->SetSelection( 1 );
1330
1331 break;
1332
1333 case CONN_DLG_TYPE:
1334 if( !layer_mask.any() )
1335 layer_mask = PAD::ConnSMDMask();
1336
1337 if( layer_mask.test( F_Cu ) )
1338 m_rbCopperLayersSel->SetSelection( 0 );
1339 else
1340 m_rbCopperLayersSel->SetSelection( 1 );
1341
1342 break;
1343
1344 case NPTH_DLG_TYPE:
1345 if( !layer_mask.any() )
1346 layer_mask = PAD::UnplatedHoleMask();
1347
1348 if( layer_mask.test( F_Cu ) && layer_mask.test( B_Cu ) )
1349 m_rbCopperLayersSel->SetSelection( 0 );
1350 else if( layer_mask.test( F_Cu ) )
1351 m_rbCopperLayersSel->SetSelection( 1 );
1352 else if( layer_mask.test( B_Cu ) )
1353 m_rbCopperLayersSel->SetSelection( 2 );
1354 else
1355 m_rbCopperLayersSel->SetSelection( 3 );
1356
1357 break;
1358
1359 case APERTURE_DLG_TYPE:
1360 if( !layer_mask.any() )
1361 layer_mask = PAD::ApertureMask();
1362
1363 m_rbCopperLayersSel->SetSelection( 0 );
1364 break;
1365 }
1366
1367 m_layerFrontAdhesive->SetValue( layer_mask[F_Adhes] );
1368 m_layerBackAdhesive->SetValue( layer_mask[B_Adhes] );
1369
1370 m_layerFrontPaste->SetValue( layer_mask[F_Paste] );
1371 m_layerBackPaste->SetValue( layer_mask[B_Paste] );
1372
1373 m_layerFrontSilk->SetValue( layer_mask[F_SilkS] );
1374 m_layerBackSilk->SetValue( layer_mask[B_SilkS] );
1375
1376 m_layerFrontMask->SetValue( layer_mask[F_Mask] );
1377 m_layerBackMask->SetValue( layer_mask[B_Mask] );
1378
1379 m_layerECO1->SetValue( layer_mask[Eco1_User] );
1380 m_layerECO2->SetValue( layer_mask[Eco2_User] );
1381
1382 m_layerUserDwgs->SetValue( layer_mask[Dwgs_User] );
1383}
1384
1385
1387{
1388 bool retVal = DIALOG_SHIM::Show( aShow );
1389
1390 if( aShow )
1391 {
1392 // It *should* work to set the stackup bitmap in the constructor, but it doesn't.
1393 // wxWidgets needs to have these set when the panel is visible for some reason.
1394 // https://gitlab.com/kicad/code/kicad/-/issues/5534
1395 m_stackupImage0->SetBitmap( KiBitmapBundle( BITMAPS::pads_reset_unused ) );
1396 m_stackupImage1->SetBitmap( KiBitmapBundle( BITMAPS::pads_remove_unused_keep_bottom ) );
1397 m_stackupImage2->SetBitmap( KiBitmapBundle( BITMAPS::pads_remove_unused ) );
1398 m_stackupImage4->SetBitmap( KiBitmapBundle( BITMAPS::pads_npth_top_bottom ) );
1399 m_stackupImage5->SetBitmap( KiBitmapBundle( BITMAPS::pads_npth_top ) );
1400 m_stackupImage6->SetBitmap( KiBitmapBundle( BITMAPS::pads_npth_bottom ) );
1401 m_stackupImage7->SetBitmap( KiBitmapBundle( BITMAPS::pads_npth ) );
1402
1403 Layout();
1404 }
1405
1406 return retVal;
1407}
1408
1409
1410void DIALOG_PAD_PROPERTIES::OnSetCopperLayers( wxCommandEvent& event )
1411{
1413 redraw();
1414
1415 if( m_initialized )
1416 OnModify();
1417}
1418
1419
1420void DIALOG_PAD_PROPERTIES::OnSetLayers( wxCommandEvent& event )
1421{
1423 redraw();
1424
1425 if( m_initialized )
1426 OnModify();
1427}
1428
1429
1431{
1433
1434 wxArrayString error_msgs;
1435 wxArrayString warning_msgs;
1436
1438 [&]( int errorCode, const wxString& msg )
1439 {
1440 if( errorCode == DRCE_PADSTACK_INVALID )
1441 error_msgs.Add( _( "Error: " ) + msg );
1442 else if( errorCode == DRCE_PADSTACK )
1443 warning_msgs.Add( _( "Warning: " ) + msg );
1444 else if( errorCode == DRCE_PAD_TH_WITH_NO_HOLE )
1445 error_msgs.Add( _( "Error: Through hole pad has no hole." ) );
1446 } );
1447
1448 if( error_msgs.GetCount() || warning_msgs.GetCount() )
1449 {
1450 wxString title = error_msgs.GetCount() ? _( "Pad Properties Errors" )
1451 : _( "Pad Properties Warnings" );
1452 HTML_MESSAGE_BOX dlg( this, title );
1453
1454 wxArrayString msgs = error_msgs;
1455
1456 for( const wxString& msg : warning_msgs )
1457 msgs.Add( msg );
1458
1459 dlg.ListSet( msgs );
1460
1461 dlg.ShowModal();
1462 }
1463
1464 return error_msgs.GetCount() == 0;
1465}
1466
1467
1469{
1470 if( !m_initialized )
1471 return;
1472
1474 KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( view->GetPainter() );
1475 KIGFX::PCB_RENDER_SETTINGS* settings = painter->GetSettings();
1476
1478
1479 // The layer used to place primitive items selected when editing custom pad shapes
1480 // we use here a layer never used in a pad:
1481 #define SELECTED_ITEMS_LAYER Dwgs_User
1482
1483 view->ClearTopLayers();
1485 view->SetTopLayer( m_editLayer );
1487
1488 static const std::vector<int> topLayers = {
1493 };
1494
1495 for( int layer : topLayers )
1496 view->SetTopLayer( layer );
1497
1499
1500 view->Update( m_previewPad );
1501
1502 // delete previous items if highlight list
1503 while( m_highlight.size() )
1504 {
1505 delete m_highlight.back(); // the dtor also removes item from view
1506 m_highlight.pop_back();
1507 }
1508
1509 BOX2I bbox = m_previewPad->ViewBBox();
1510
1511 if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
1512 {
1513 // The origin always goes in the middle of the canvas; we want offsetting the pad
1514 // shape to move the pad, not the hole
1515 bbox.Move( -m_previewPad->GetPosition() );
1516 int maxXExtent = std::max( abs( bbox.GetLeft() ), abs( bbox.GetRight() ) );
1517 int maxYExtent = std::max( abs( bbox.GetTop() ), abs( bbox.GetBottom() ) );
1518
1519 // Don't blow up the GAL on too-large numbers
1520 if( maxXExtent > INT_MAX / 4 )
1521 maxXExtent = INT_MAX / 4;
1522
1523 if( maxYExtent > INT_MAX / 4 )
1524 maxYExtent = INT_MAX / 4;
1525
1526 BOX2D viewBox( m_previewPad->GetPosition(), {0, 0} );
1527 BOX2D canvasBox( m_previewPad->GetPosition(), {0, 0} );
1528 viewBox.Inflate( maxXExtent * 1.4, maxYExtent * 1.4 ); // add a margin
1529 canvasBox.Inflate( maxXExtent * 2.0, maxYExtent * 2.0 );
1530
1531 view->SetBoundary( canvasBox );
1532
1533 // Autozoom
1534 view->SetViewport( viewBox );
1535
1538 }
1539}
1540
1541
1543{
1544 if( !wxDialog::TransferDataToWindow() )
1545 return false;
1546
1547 if( !m_panelGeneral->TransferDataToWindow() )
1548 return false;
1549
1550 if( !m_localSettingsPanel->TransferDataToWindow() )
1551 return false;
1552
1553 return true;
1554}
1555
1556
1558{
1559 BOARD_COMMIT commit( m_parent );
1560
1561 if( !wxDialog::TransferDataFromWindow() )
1562 return false;
1563
1564 if( !m_panelGeneral->TransferDataFromWindow() )
1565 return false;
1566
1567 if( !m_localSettingsPanel->TransferDataFromWindow() )
1568 return false;
1569
1570 if( !padValuesOK() )
1571 return false;
1572
1574 return false;
1575
1577
1579 padTool->SetLastPadNumber( m_masterPad->GetNumber() );
1580
1581 // m_masterPad is a pattern: ensure there is no net for this pad:
1583
1584 if( !m_currentPad ) // Set current Pad parameters
1585 return true;
1586
1587 commit.Modify( m_currentPad );
1588
1589 // Update values
1590
1591 // transferDataToPad only handles the current edit layer, so m_masterPad isn't accurate
1592 // TODO(JE) this could be cleaner
1594
1600
1601 int padNetcode = NETINFO_LIST::UNCONNECTED;
1602
1603 // For PAD_ATTRIB::NPTH, ensure there is no net name selected
1604 if( m_masterPad->GetAttribute() != PAD_ATTRIB::NPTH )
1605 padNetcode = m_padNetSelector->GetSelectedNetcode();
1606
1607 m_currentPad->SetNetCode( padNetcode );
1608
1610
1611 // Set the fabrication property:
1613
1614 // define the way the clearance area is defined in zones
1616
1618 {
1619 // flip pad (up/down) around its position
1620 m_currentPad->Flip( m_currentPad->GetPosition(), FLIP_DIRECTION::TOP_BOTTOM );
1621 }
1622
1624
1626
1627 // redraw the area where the pad was
1629
1630 commit.Push( _( "Edit Pad Properties" ) );
1631
1632 return true;
1633}
1634
1635
1637{
1638 PAD_PROP prop = PAD_PROP::NONE;
1639
1640 switch( m_choiceFabProperty->GetSelection() )
1641 {
1642 case 0: prop = PAD_PROP::NONE; break;
1643 case 1: prop = PAD_PROP::BGA; break;
1644 case 2: prop = PAD_PROP::FIDUCIAL_LOCAL; break;
1645 case 3: prop = PAD_PROP::FIDUCIAL_GLBL; break;
1646 case 4: prop = PAD_PROP::TESTPOINT; break;
1647 case 5: prop = PAD_PROP::HEATSINK; break;
1648 case 6: prop = PAD_PROP::CASTELLATED; break;
1649 case 7: prop = PAD_PROP::MECHANICAL; break;
1650 }
1651
1652 return prop;
1653}
1654
1655
1657{
1658 if( m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_CIRCLE )
1659 {
1660 m_holeXLabel->SetLabel( _( "Diameter:" ) );
1661 m_holeY.Show( false );
1662 }
1663 else
1664 {
1665 m_holeXLabel->SetLabel( _( "Hole size X:" ) );
1666 m_holeY.Show( true );
1667 }
1668
1669 m_holeXLabel->GetParent()->Layout();
1670}
1671
1672
1674{
1675 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CIRCLE
1677 {
1678 m_sizeXLabel->SetLabel( _( "Diameter:" ) );
1679 m_sizeY.Show( false );
1680 m_bitmapTeardrop->SetBitmap( KiBitmapBundle( BITMAPS::teardrop_sizes ) );
1681 m_minTrackWidthHint->SetLabel( _( "d" ) );
1682 m_stLenPercentHint->SetLabel( _( "d" ) );
1683 m_stWidthPercentHint->SetLabel( _( "d" ) );
1684 }
1685 else
1686 {
1687 m_sizeXLabel->SetLabel( _( "Pad size X:" ) );
1688 m_sizeY.Show( true );
1689 m_bitmapTeardrop->SetBitmap( KiBitmapBundle( BITMAPS::teardrop_rect_sizes ) );
1690 m_minTrackWidthHint->SetLabel( _( "w" ) );
1691 m_stLenPercentHint->SetLabel( _( "w" ) );
1692 m_stWidthPercentHint->SetLabel( _( "w" ) );
1693 }
1694
1695 m_sizeXLabel->GetParent()->Layout();
1696 resetSize();
1697 Layout();
1698 m_MainSizer->Fit( this );
1699}
1700
1701
1703{
1704 if( !Validate() )
1705 return false;
1706
1707 if( !m_panelGeneral->Validate() )
1708 return false;
1709
1710 if( !m_localSettingsPanel->Validate() )
1711 return false;
1712
1713 if( !m_spokeWidth.Validate( 0, INT_MAX ) )
1714 return false;
1715
1716 switch( m_cbPadstackMode->GetSelection() )
1717 {
1718 default:
1719 case 0: aPad->Padstack().SetMode( PADSTACK::MODE::NORMAL ); break;
1720 case 1: aPad->Padstack().SetMode( PADSTACK::MODE::FRONT_INNER_BACK ); break;
1721 case 2: aPad->Padstack().SetMode( PADSTACK::MODE::CUSTOM ); break;
1722 }
1723
1724 aPad->SetAttribute( code_type[m_padType->GetSelection()] );
1725 aPad->SetShape( m_editLayer, code_shape[m_PadShapeSelector->GetSelection()] );
1726
1728 aPad->SetAnchorPadShape( m_editLayer, PAD_SHAPE::RECTANGLE );
1729 else
1730 aPad->SetAnchorPadShape( m_editLayer, PAD_SHAPE::CIRCLE );
1731
1732 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::CUSTOM )
1734
1735 aPad->GetTeardropParams().m_Enabled = m_cbTeardrops->GetValue();
1742
1743 if( m_curvedEdges->GetValue() )
1745 else
1747
1749
1750 // Read pad clearances values:
1751 if( m_clearance.IsNull() )
1752 aPad->SetLocalClearance( {} );
1753 else
1755
1756 if( m_maskMargin.IsNull() )
1757 aPad->SetLocalSolderMaskMargin( {} );
1758 else
1760
1761 if( m_pasteMargin.IsNull() )
1762 aPad->SetLocalSolderPasteMargin( {} );
1763 else
1765
1768 else
1770
1774
1775 // And rotation
1777
1778 switch( m_ZoneConnectionChoice->GetSelection() )
1779 {
1780 default:
1781 case 0: aPad->SetLocalZoneConnection( ZONE_CONNECTION::INHERITED ); break;
1782 case 1: aPad->SetLocalZoneConnection( ZONE_CONNECTION::FULL ); break;
1783 case 2: aPad->SetLocalZoneConnection( ZONE_CONNECTION::THERMAL ); break;
1784 case 3: aPad->SetLocalZoneConnection( ZONE_CONNECTION::NONE ); break;
1785 }
1786
1788
1789 if( FOOTPRINT* fp = aPad->GetParentFootprint() )
1790 {
1791 pos -= fp->GetPosition();
1792 RotatePoint( pos, -fp->GetOrientation() );
1793 }
1794
1795 aPad->SetPosition( pos );
1796
1797 if( m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_CIRCLE )
1798 {
1799 aPad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
1801 }
1802 else
1803 {
1804 aPad->SetDrillShape( PAD_DRILL_SHAPE::OBLONG );
1806 }
1807
1808 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::CIRCLE )
1810 else
1812
1813 // For a trapezoid, test delta value (be sure delta is not too large for pad size)
1814 // remember DeltaSize.x is the Y size variation
1815 bool error = false;
1816 VECTOR2I delta( 0, 0 );
1817
1818 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::TRAPEZOID )
1819 {
1820 // For a trapezoid, only one of delta.x or delta.y is not 0, depending on axis.
1821 if( m_trapAxisCtrl->GetSelection() == 0 )
1823 else
1825
1826 if( delta.x < 0 && delta.x < -aPad->GetSize( m_editLayer ).y )
1827 {
1828 delta.x = -aPad->GetSize( m_editLayer ).y + 2;
1829 error = true;
1830 }
1831
1832 if( delta.x > 0 && delta.x > aPad->GetSize( m_editLayer ).y )
1833 {
1834 delta.x = aPad->GetSize( m_editLayer ).y - 2;
1835 error = true;
1836 }
1837
1838 if( delta.y < 0 && delta.y < -aPad->GetSize( m_editLayer ).x )
1839 {
1840 delta.y = -aPad->GetSize( m_editLayer ).x + 2;
1841 error = true;
1842 }
1843
1844 if( delta.y > 0 && delta.y > aPad->GetSize( m_editLayer ).x )
1845 {
1846 delta.y = aPad->GetSize( m_editLayer ).x - 2;
1847 error = true;
1848 }
1849 }
1850
1851 aPad->SetDelta( m_editLayer, delta );
1852
1853 if( m_offsetShapeOpt->GetValue() )
1855 else
1856 aPad->SetOffset( m_editLayer, VECTOR2I() );
1857
1858 // Read pad length die
1859 if( m_padToDieOpt->GetValue() )
1861 else
1862 aPad->SetPadToDieLength( 0 );
1863
1864 aPad->SetNumber( m_padNumCtrl->GetValue() );
1866
1867 int chamfers = 0;
1868
1869 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_RECT )
1870 {
1871 if( m_cbTopLeft->GetValue() )
1872 chamfers |= RECT_CHAMFER_TOP_LEFT;
1873
1874 if( m_cbTopRight->GetValue() )
1875 chamfers |= RECT_CHAMFER_TOP_RIGHT;
1876
1877 if( m_cbBottomLeft->GetValue() )
1878 chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1879
1880 if( m_cbBottomRight->GetValue() )
1881 chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1882 }
1883 else if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT )
1884 {
1885 if( m_cbTopLeft1->GetValue() )
1886 chamfers |= RECT_CHAMFER_TOP_LEFT;
1887
1888 if( m_cbTopRight1->GetValue() )
1889 chamfers |= RECT_CHAMFER_TOP_RIGHT;
1890
1891 if( m_cbBottomLeft1->GetValue() )
1892 chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1893
1894 if( m_cbBottomRight1->GetValue() )
1895 chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1896 }
1897
1898 aPad->SetChamferPositions( m_editLayer, chamfers );
1899
1900 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::CUSTOM )
1901 {
1902 // The pad custom has a "anchor pad" (a basic shape: round or rect pad)
1903 // that is the minimal area of this pad, and is useful to ensure a hole
1904 // diameter is acceptable, and is used in Gerber files as flashed area
1905 // reference
1906 if( aPad->GetAnchorPadShape( m_editLayer ) == PAD_SHAPE::CIRCLE )
1908 }
1909
1910 // Define the way the clearance area is defined in zones. Since all non-custom pad
1911 // shapes are convex to begin with, this really only makes any difference for custom
1912 // pad shapes.
1913 aPad->SetCustomShapeInZoneOpt( m_ZoneCustomPadShape->GetSelection() == 0 ?
1916
1917 switch( aPad->GetAttribute() )
1918 {
1919 case PAD_ATTRIB::PTH:
1920 break;
1921
1922 case PAD_ATTRIB::CONN:
1923 case PAD_ATTRIB::SMD:
1924 // SMD and PAD_ATTRIB::CONN has no hole.
1925 // basically, SMD and PAD_ATTRIB::CONN are same type of pads
1926 // PAD_ATTRIB::CONN has just a default non technical layers that differs from SMD
1927 // and are intended to be used in virtual edge board connectors
1928 // However we can accept a non null offset,
1929 // mainly to allow complex pads build from a set of basic pad shapes
1930 aPad->SetDrillSize( VECTOR2I( 0, 0 ) );
1931 break;
1932
1933 case PAD_ATTRIB::NPTH:
1934 // Mechanical purpose only:
1935 // no net name, no pad name allowed
1936 aPad->SetNumber( wxEmptyString );
1938 break;
1939
1940 default:
1941 wxFAIL_MSG( wxT( "DIALOG_PAD_PROPERTIES::transferDataToPad: unknown pad type" ) );
1942 break;
1943 }
1944
1945 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::ROUNDRECT )
1946 {
1948 }
1949 else if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::CHAMFERED_RECT )
1950 {
1952 {
1955 }
1956 else // Choice is CHOICE_SHAPE_CHAMFERED_RECT, no rounded corner
1957 {
1960 }
1961 }
1962
1964
1965 LSET padLayerMask = LSET();
1966 int copperLayersChoice = m_rbCopperLayersSel->GetSelection();
1967
1969
1970 switch( m_padType->GetSelection() )
1971 {
1972 case PTH_DLG_TYPE:
1973 switch( copperLayersChoice )
1974 {
1975 case 0:
1976 // All copper layers
1977 padLayerMask |= LSET::AllCuMask();
1978 break;
1979
1980 case 1:
1981 // Front, back and connected
1982 padLayerMask |= LSET::AllCuMask();
1985 break;
1986
1987 case 2:
1988 // Connected only
1989 padLayerMask |= LSET::AllCuMask();
1991 break;
1992
1993 case 3:
1994 // No copper layers
1995 break;
1996 }
1997
1998 break;
1999
2000 case NPTH_DLG_TYPE:
2001 switch( copperLayersChoice )
2002 {
2003 case 0: padLayerMask.set( F_Cu ).set( B_Cu ); break;
2004 case 1: padLayerMask.set( F_Cu ); break;
2005 case 2: padLayerMask.set( B_Cu ); break;
2006 default: break;
2007 }
2008
2009 break;
2010
2011 case SMD_DLG_TYPE:
2012 case CONN_DLG_TYPE:
2013 switch( copperLayersChoice )
2014 {
2015 case 0: padLayerMask.set( F_Cu ); break;
2016 case 1: padLayerMask.set( B_Cu ); break;
2017 }
2018
2019 break;
2020
2021 case APERTURE_DLG_TYPE:
2022 // no copper layers
2023 break;
2024 }
2025
2026 if( m_layerFrontAdhesive->GetValue() )
2027 padLayerMask.set( F_Adhes );
2028
2029 if( m_layerBackAdhesive->GetValue() )
2030 padLayerMask.set( B_Adhes );
2031
2032 if( m_layerFrontPaste->GetValue() )
2033 padLayerMask.set( F_Paste );
2034
2035 if( m_layerBackPaste->GetValue() )
2036 padLayerMask.set( B_Paste );
2037
2038 if( m_layerFrontSilk->GetValue() )
2039 padLayerMask.set( F_SilkS );
2040
2041 if( m_layerBackSilk->GetValue() )
2042 padLayerMask.set( B_SilkS );
2043
2044 if( m_layerFrontMask->GetValue() )
2045 padLayerMask.set( F_Mask );
2046
2047 if( m_layerBackMask->GetValue() )
2048 padLayerMask.set( B_Mask );
2049
2050 if( m_layerECO1->GetValue() )
2051 padLayerMask.set( Eco1_User );
2052
2053 if( m_layerECO2->GetValue() )
2054 padLayerMask.set( Eco2_User );
2055
2056 if( m_layerUserDwgs->GetValue() )
2057 padLayerMask.set( Dwgs_User );
2058
2059 aPad->SetLayerSet( padLayerMask );
2060
2061 return !error;
2062}
2063
2064
2065void DIALOG_PAD_PROPERTIES::OnOffsetCheckbox( wxCommandEvent& event )
2066{
2067 if( m_offsetShapeOpt->GetValue() )
2068 {
2071 }
2072
2073 // Show/hide controls depending on m_offsetShapeOpt being enabled
2074 m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
2075 m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
2076
2077 for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
2078 m_notebook->GetPage( i )->Layout();
2079
2080 OnValuesChanged( event );
2081}
2082
2083
2085{
2086 if( m_padToDieOpt->GetValue() && m_currentPad )
2088
2089 OnValuesChanged( event );
2090}
2091
2092
2093void DIALOG_PAD_PROPERTIES::onModify( wxSpinDoubleEvent& aEvent )
2094{
2095 if( m_initialized )
2096 OnModify();
2097}
2098
2099
2100void DIALOG_PAD_PROPERTIES::onModify( wxCommandEvent& aEvent )
2101{
2102 if( m_initialized )
2103 OnModify();
2104}
2105
2106
2107void DIALOG_PAD_PROPERTIES::OnValuesChanged( wxCommandEvent& event )
2108{
2109 if( m_initialized )
2110 {
2112 return;
2113
2114 // If the pad size has changed, update the displayed values for rounded rect pads.
2116
2117 redraw();
2118 OnModify();
2119 }
2120}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap)
Definition: bitmap.cpp:110
#define DEFAULT_PAD_DRILL_DIAMETER_MM
BASE_SET & set(size_t pos)
Definition: base_set.h:115
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
TEARDROP_PARAMETERS & GetTeardropParams()
std::unique_ptr< PAD > m_Pad_Master
void SetParentGroup(PCB_GROUP *aGroup)
Definition: board_item.h:89
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:298
VECTOR2I GetFPRelativePosition() const
Definition: board_item.cpp:327
BOARD_ITEM_CONTAINER * GetParent() const
Definition: board_item.h:215
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:871
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:775
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition: board.h:448
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:579
bool LegacyTeardrops() const
Definition: board.h:1261
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:892
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)
Create an undo entry for an item that has been already modified.
Definition: commit.h:105
Class DIALOG_PAD_PROPERTIES_BASE.
void OnUpdateUINonCopperWarning(wxUpdateUIEvent &event) override
void OnInitDialog(wxInitDialogEvent &event) override
void PadTypeSelected(wxCommandEvent &event) override
void OnPadShapeSelection(wxCommandEvent &event) override
bool transferDataToPad(PAD *aPad)
Copy values from dialog field to aPad's members.
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 onTeardropCurvePointsUpdateUi(wxUpdateUIEvent &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:102
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:231
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:129
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:104
int GetAttributes() const
Definition: footprint.h:290
bool IsFlipped() const
Definition: footprint.h:391
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:173
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:178
PCB specific render settings.
Definition: pcb_painter.h:78
void SetLayerColor(int aLayer, const COLOR4D &aColor)
Change the color used to draw a layer.
An interface for classes handling user events controlling the view behavior such as zooming,...
void ApplySettings(const VC_SETTINGS &aSettings)
Load new settings from program common settings.
const VC_SETTINGS & GetSettings() const
Apply VIEW_CONTROLS settings from an object.
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:68
void SetViewport(const BOX2D &aViewport)
Set the visible area of the VIEW.
Definition: view.cpp:534
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:299
void SetBoundary(const BOX2D &aBoundary)
Set limits for view area.
Definition: view.h:283
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:1669
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:199
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:217
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:36
LSEQ UIOrder() const
Returns the copper, technical and user layers in the order shown in layer widget.
Definition: lset.cpp:799
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:676
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)
void SetBoard(BOARD *aBoard)
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:870
void SetUnconnectedLayerMode(UNCONNECTED_LAYER_MODE aMode)
Definition: padstack.h:307
void SetMode(MODE aMode)
Definition: padstack.cpp:821
@ 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:287
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:244
bool IsAperturePad() const
Definition: pad.h:449
void SetAttribute(PAD_ATTRIB aAttribute)
Definition: pad.cpp:811
PAD_PROP GetProperty() const
Definition: pad.h:445
bool GetRemoveUnconnected() const
Definition: pad.h:711
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pad.h:439
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:367
int GetRoundRectCornerRadius(PCB_LAYER_ID aLayer) const
Definition: pad.cpp:441
std::optional< double > GetLocalSolderPasteMarginRatio() const
Definition: pad.h:472
const VECTOR2I & GetDrillSize() const
Definition: pad.h:307
PAD_ATTRIB GetAttribute() const
Definition: pad.h:442
static LSET PTHMask()
layer set for a through hole pad
Definition: pad.cpp:269
void SetThermalGap(int aGap)
Definition: pad.h:630
void SetThermalSpokeAngle(const EDA_ANGLE &aAngle)
The orientation of the thermal spokes.
Definition: pad.h:611
const wxString & GetNumber() const
Definition: pad.h:134
const VECTOR2I & GetDelta(PCB_LAYER_ID aLayer) const
Definition: pad.h:301
void SetLocalSolderPasteMarginRatio(std::optional< double > aRatio)
Definition: pad.h:476
void SetShape(PCB_LAYER_ID aLayer, PAD_SHAPE aShape)
Set the new shape of this pad.
Definition: pad.h:184
VECTOR2I GetPosition() const override
Definition: pad.h:210
void SetProperty(PAD_PROP aProperty)
Definition: pad.cpp:859
EDA_ANGLE GetThermalSpokeAngle() const
Definition: pad.h:615
void Flip(const VECTOR2I &VECTOR2I, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
Definition: pad.cpp:892
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
Definition: pad.cpp:290
void SetDelta(PCB_LAYER_ID aLayer, const VECTOR2I &aSize)
Definition: pad.h:295
int GetDrillSizeX() const
Definition: pad.h:309
double GetRoundRectRadiusRatio(PCB_LAYER_ID aLayer) const
Definition: pad.h:652
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
Definition: pad.h:193
void SetNumber(const wxString &aNumber)
Set the pad number (note that it can be alphanumeric, such as the array reference "AA12").
Definition: pad.h:133
void SetDrillShape(PAD_DRILL_SHAPE aShape)
Definition: pad.cpp:430
void SetLocalSolderMaskMargin(std::optional< int > aMargin)
Definition: pad.h:461
void SetOffset(PCB_LAYER_ID aLayer, const VECTOR2I &aOffset)
Definition: pad.h:313
bool GetKeepTopBottom() const
Definition: pad.h:727
void SetLocalZoneConnection(ZONE_CONNECTION aType)
Definition: pad.h:481
void SetChamferRectRatio(PCB_LAYER_ID aLayer, double aChamferScale)
Has meaning only for chamfered rectangular pads.
Definition: pad.cpp:468
std::optional< int > GetLocalClearance() const override
Return any local clearances set in the "classic" (ie: pre-rule) system.
Definition: pad.h:457
void SetPadstack(const PADSTACK &aPadstack)
Definition: pad.h:325
void SetPosition(const VECTOR2I &aPos) override
Definition: pad.h:204
const PADSTACK & Padstack() const
Definition: pad.h:323
const VECTOR2I & GetOffset(PCB_LAYER_ID aLayer) const
Definition: pad.h:319
static LSET ConnSMDMask()
layer set for a SMD pad on Front layer used for edge board connectors
Definition: pad.cpp:283
void SetDrillSize(const VECTOR2I &aSize)
Definition: pad.h:306
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition: pad.h:410
void SetSize(PCB_LAYER_ID aLayer, const VECTOR2I &aSize)
Definition: pad.h:261
PADSTACK::CUSTOM_SHAPE_ZONE_MODE GetCustomShapeInZoneOpt() const
Definition: pad.h:223
PAD_DRILL_SHAPE GetDrillShape() const
Definition: pad.h:424
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.
int GetChamferPositions(PCB_LAYER_ID aLayer) const
Definition: pad.h:688
static LSET ApertureMask()
layer set for an aperture pad
Definition: pad.cpp:297
virtual const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: pad.cpp:1745
void SetRoundRectCornerRadius(PCB_LAYER_ID aLayer, double aRadius)
Has meaning only for rounded rectangle pads.
Definition: pad.cpp:447
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: pad.cpp:276
std::optional< int > GetLocalSolderPasteMargin() const
Definition: pad.h:466
void CheckPad(UNITS_PROVIDER *aUnitsProvider, const std::function< void(int aErrorCode, const wxString &aMsg)> &aErrorHandler) const
Definition: pad.cpp:2121
void SetChamferPositions(PCB_LAYER_ID aLayer, int aPositions)
Has meaning only for chamfered rectangular pads.
Definition: pad.h:683
std::optional< int > GetLocalSolderMaskMargin() const
Definition: pad.h:460
void SetLocalSolderPasteMargin(std::optional< int > aMargin)
Definition: pad.h:467
int GetThermalSpokeWidth() const
Definition: pad.h:602
EDA_ANGLE GetFPRelativeOrientation() const
Definition: pad.cpp:883
double GetChamferRectRatio(PCB_LAYER_ID aLayer) const
Definition: pad.h:671
void SetFPRelativeOrientation(const EDA_ANGLE &aAngle)
Definition: pad.cpp:874
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:233
void SetOrientation(const EDA_ANGLE &aAngle)
Set the rotation angle of the pad.
Definition: pad.cpp:867
void SetLocalClearance(std::optional< int > aClearance)
Definition: pad.h:458
ZONE_CONNECTION GetLocalZoneConnection() const
Definition: pad.h:482
void SetThermalSpokeWidth(int aWidth)
Set the width of the thermal spokes connecting the pad to a zone.
Definition: pad.h:601
int GetThermalGap() const
Definition: pad.h:631
void SetLayerSet(const LSET &aLayers) override
Definition: pad.h:438
PAD_SHAPE GetAnchorPadShape(PCB_LAYER_ID aLayer) const
Definition: pad.h:215
void SetRoundRectRadiusRatio(PCB_LAYER_ID aLayer, double aRadiusScale)
Has meaning only for rounded rectangle pads.
Definition: pad.cpp:453
void SetPadToDieLength(int aLength)
Definition: pad.h:454
int GetPadToDieLength() const
Definition: pad.h:455
const VECTOR2I & GetSize(PCB_LAYER_ID aLayer) const
Definition: pad.h:266
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
void ShowPadPropertiesDialog(PAD *aPad)
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
BOARD * GetBoard() const
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Returns the BOARD_DESIGN_SETTINGS for the open project.
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.
int m_CurveSegCount
True if the teardrop should be curved.
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.
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.
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:199
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[]
static bool PadHasMeaningfulRoundingRadius(const PAD &aPad, PCB_LAYER_ID aLayer)
Returns true if the pad's rounding ratio is valid (i.e.
#define SMD_DLG_TYPE
static double GetDefaultIpcRoundingRatio(const PAD &aPad, PCB_LAYER_ID aLayer)
Get a sensible default for a rounded rectangle pad's rounding ratio.
@ 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:403
static constexpr EDA_ANGLE ANGLE_45
Definition: eda_angle.h:402
#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:167
@ LAYER_GRID
Definition: layer_ids.h:206
@ LAYER_NON_PLATEDHOLES
handle color for not plated holes (holes, not pads)
Definition: layer_ids.h:198
@ LAYER_PAD_PLATEDHOLES
to draw pad holes (plated)
Definition: layer_ids.h:215
@ LAYER_PAD_HOLEWALLS
Definition: layer_ids.h:234
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 GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:154
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:88
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:691
VECTOR2< double > VECTOR2D
Definition: vector2d.h:690