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-2023 KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27#include <base_units.h>
28#include <bitmaps.h>
29#include <board_commit.h>
30#include <board.h>
32#include <footprint.h>
33#include <confirm.h>
34#include <core/arraydim.h>
35#include <convert_basic_shapes_to_polygon.h> // for enum RECT_CHAMFER_POSITIONS definition
40#include <macros.h>
41#include <pad.h>
42#include <pcb_base_frame.h>
44#include <pcb_painter.h>
45#include <pcbnew_settings.h>
47#include <view/view_controls.h>
49#include <tool/tool_manager.h>
50#include <tools/pad_tool.h>
51#include <advanced_config.h> // for pad property feature management
52#include <wx/choicdlg.h>
53
54
55// list of pad shapes, ordered like the pad shape wxChoice in dialog.
57{
64 PAD_SHAPE::CHAMFERED_RECT, // choice = CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT
65 PAD_SHAPE::CUSTOM, // choice = CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
66 PAD_SHAPE::CUSTOM // choice = PAD_SHAPE::CUSTOM_RECT_ANCHOR
67};
68
69
70// the ordered index of the pad shape wxChoice in dialog.
71// keep it consistent with code_shape[] and dialog strings
73{
83};
84
85
87{
92 PAD_ATTRIB::SMD // Aperture pad :type SMD with no copper layers,
93 // only on tech layers (usually only on paste layer
94};
95
96
97// These define have the same value as the m_PadType wxChoice GetSelected() return value
98#define PTH_DLG_TYPE 0
99#define SMD_DLG_TYPE 1
100#define CONN_DLG_TYPE 2
101#define NPTH_DLG_TYPE 3
102#define APERTURE_DLG_TYPE 4
103
104
109static bool PadHasMeaningfulRoundingRadius( const PAD& aPad )
110{
111 const PAD_SHAPE shape = aPad.GetShape();
112 return shape == PAD_SHAPE::ROUNDRECT || shape == PAD_SHAPE::CHAMFERED_RECT;
113}
114
115
121static double GetDefaultIpcRoundingRatio( const PAD& aPad )
122{
123 const double defaultProportion = 0.25;
124 const double minimumSizeIU = pcbIUScale.mmToIU( 0.25 );
125
126 const int padMinSizeIU = std::min( aPad.GetSizeX(), aPad.GetSizeY() );
127 const double defaultRadiusIU = std::min( minimumSizeIU, padMinSizeIU * defaultProportion );
128
129 // Convert back to a ratio
130 return defaultRadiusIU / padMinSizeIU;
131}
132
133
135{
136 DIALOG_PAD_PROPERTIES dlg( this, aPad );
137
138 dlg.ShowQuasiModal();
139}
140
141
144 m_parent( aParent ),
145 m_canUpdate( false ),
146 m_posX( aParent, m_posXLabel, m_posXCtrl, m_posXUnits ),
147 m_posY( aParent, m_posYLabel, m_posYCtrl, m_posYUnits ),
148 m_sizeX( aParent, m_sizeXLabel, m_sizeXCtrl, m_sizeXUnits ),
149 m_sizeY( aParent, m_sizeYLabel, m_sizeYCtrl, m_sizeYUnits ),
150 m_offsetX( aParent, m_offsetXLabel, m_offsetXCtrl, m_offsetXUnits ),
151 m_offsetY( aParent, m_offsetYLabel, m_offsetYCtrl, m_offsetYUnits ),
152 m_padToDie( aParent, m_padToDieLabel, m_padToDieCtrl, m_padToDieUnits ),
153 m_trapDelta( aParent, m_trapDeltaLabel, m_trapDeltaCtrl, m_trapDeltaUnits ),
154 m_cornerRadius( aParent, m_cornerRadiusLabel, m_cornerRadiusCtrl, m_cornerRadiusUnits ),
155 m_cornerRatio( aParent, m_cornerRatioLabel, m_cornerRatioCtrl, m_cornerRatioUnits ),
156 m_chamferRatio( aParent, m_chamferRatioLabel, m_chamferRatioCtrl, m_chamferRatioUnits ),
157 m_mixedCornerRatio( aParent, m_mixedCornerRatioLabel, m_mixedCornerRatioCtrl,
158 m_mixedCornerRatioUnits ),
159 m_mixedChamferRatio( aParent, m_mixedChamferRatioLabel, m_mixedChamferRatioCtrl,
160 m_mixedChamferRatioUnits ),
161 m_holeX( aParent, m_holeXLabel, m_holeXCtrl, m_holeXUnits ),
162 m_holeY( aParent, m_holeYLabel, m_holeYCtrl, m_holeYUnits ),
163 m_clearance( aParent, m_clearanceLabel, m_clearanceCtrl, m_clearanceUnits ),
164 m_maskMargin( aParent, m_maskMarginLabel, m_maskMarginCtrl, m_maskMarginUnits ),
165 m_pasteMargin( aParent, m_pasteMarginLabel, m_pasteMarginCtrl, m_pasteMarginUnits ),
166 m_pasteMarginRatio( aParent, m_pasteMarginRatioLabel, m_pasteMarginRatioCtrl,
167 m_pasteMarginRatioUnits ),
168 m_thermalGap( aParent, m_thermalGapLabel, m_thermalGapCtrl, m_thermalGapUnits ),
169 m_spokeWidth( aParent, m_spokeWidthLabel, m_spokeWidthCtrl, m_spokeWidthUnits ),
170 m_spokeAngle( aParent, m_spokeAngleLabel, m_spokeAngleCtrl, m_spokeAngleUnits ),
171 m_pad_orientation( aParent, m_PadOrientText, m_cb_padrotation, m_orientationUnits ),
172 m_teardropMaxLenSetting( aParent, m_stMaxLen, m_tcTdMaxLen, m_stMaxLenUnits ),
173 m_teardropMaxHeightSetting( aParent, m_stTdMaxSize, m_tcMaxHeight, m_stMaxHeightUnits )
174{
175 SetName( PAD_PROPERTIES_DLG_NAME );
176 m_isFpEditor = dynamic_cast<FOOTPRINT_EDIT_FRAME*>( aParent ) != nullptr;
177
178 m_currentPad = aPad; // aPad can be NULL, if the dialog is called
179 // from the footprint editor to set default pad setup
180
182
183 // Configure display origin transforms
186
189
191
192 m_FlippedWarningIcon->SetBitmap( KiBitmap( BITMAPS::dialog_warning ) );
193 m_nonCopperWarningIcon->SetBitmap( KiBitmap( BITMAPS::dialog_warning ) );
194 m_legacyTeardropsIcon->SetBitmap( KiBitmap( BITMAPS::dialog_warning ) );
195
197 m_previewPad = new PAD( (FOOTPRINT*) nullptr );
198
199 if( aPad )
200 {
201 SetTitle( _( "Pad Properties" ) );
202
203 *m_previewPad = *aPad;
206 }
207 else
208 {
209 SetTitle( _( "Default Pad Properties for Add Pad Tool" ) );
210
213 }
214
215 // Pads have a hardcoded internal rounding ratio which is 0.25 by default, even if
216 // they're not a rounded shape. This makes it hard to detect an intentional 0.25
217 // ratio, or one that's only there because it's the PAD default.
218 // Zero it out here to mark that we should recompute a better ratio if the user
219 // selects a pad shape which would need a default rounding ratio computed for it
222
223 if( m_isFpEditor )
224 {
225 m_padNetLabel->Show( false );
226 m_padNetSelector->Show( false );
227 }
228
229 m_FlippedWarningSizer->Show( false );
230
231 // Pad needs to have a parent for painting; use the parent board for its design settings
232 if( !m_previewPad->GetParent() )
234
235 m_cornerRatio.SetUnits( EDA_UNITS::PERCENT );
236 m_chamferRatio.SetUnits( EDA_UNITS::PERCENT );
237 m_mixedCornerRatio.SetUnits( EDA_UNITS::PERCENT );
238 m_mixedChamferRatio.SetUnits( EDA_UNITS::PERCENT );
239 m_pad_orientation.SetUnits( EDA_UNITS::DEGREES );
241
242 m_spokeAngle.SetUnits( EDA_UNITS::DEGREES );
244
246
247 m_pasteMarginRatio.SetUnits( EDA_UNITS::PERCENT );
249
250 initValues();
251
252 wxFont infoFont = KIUI::GetInfoFont( this );
253 m_copperLayersLabel->SetFont( infoFont );
254 m_techLayersLabel->SetFont( infoFont );
255 m_parentInfo->SetFont( infoFont );
256 m_teardropShapeLabel->SetFont( infoFont );
257
258 infoFont.SetStyle( wxFONTSTYLE_ITALIC );
259 m_nonCopperNote->SetFont( infoFont );
260 m_staticTextInfoPaste->SetFont( infoFont );
261 m_minTrackWidthHint->SetFont( infoFont );
262
265
266 // Usually, TransferDataToWindow is called by OnInitDialog
267 // calling it here fixes all widget sizes so FinishDialogSettings can safely fix minsizes
269
270 // Initialize canvas to be able to display the dummy pad:
272
275 m_canUpdate = true;
276
277 m_padNetSelector->Connect( NET_SELECTED,
278 wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ),
279 nullptr, this );
280
281 if( m_padType->GetSelection() != PTH_DLG_TYPE && m_padType->GetSelection() != NPTH_DLG_TYPE )
282 {
283 m_gbSizerHole->Show( false );
284 m_staticline6->Show( false );
285 }
286
287 // Now all widgets have the size fixed, call FinishDialogSettings
289
290 // Update widgets
291 wxUpdateUIEvent dummyUI;
292 OnUpdateUI( dummyUI );
293
294 // Post a dummy size event to force the pad preview panel to update the
295 // view: actual size, best zoom ... after the frame is shown
296 PostSizeEvent();
297}
298
299
301{
302 m_padNetSelector->Disconnect( NET_SELECTED,
303 wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ),
304 nullptr, this );
305
306 delete m_previewPad;
307 delete m_axisOrigin;
308}
309
310
311// Store the pad draw option during a session.
313
314
315void DIALOG_PAD_PROPERTIES::OnInitDialog( wxInitDialogEvent& event )
316{
317 m_selectedColor = COLOR4D( 1.0, 1.0, 1.0, 0.7 );
318
319 // Needed on some WM to be sure the pad is redrawn according to the final size
320 // of the canvas, with the right zoom factor
321 redraw();
322}
323
324
325void DIALOG_PAD_PROPERTIES::OnCancel( wxCommandEvent& event )
326{
327 // Mandatory to avoid m_panelShowPadGal trying to draw something
328 // in a non valid context during closing process:
330
331 // Now call default handler for wxID_CANCEL command event
332 event.Skip();
333}
334
335
337{
339 COLOR_SETTINGS* colorSettings = m_parent->GetColorSettings();
340
341 opts.m_forceDisplayCursor = false;
342
343 // Initialize the canvas to display the pad
344 m_padPreviewGAL = new PCB_DRAW_PANEL_GAL( m_boardViewPanel, -1, wxDefaultPosition,
345 wxDefaultSize, opts,
347
348 m_padPreviewSizer->Add( m_padPreviewGAL, 12, wxEXPAND | wxALL, 5 );
349
350 // Show the X and Y axis. It is useful because pad shape can have an offset
351 // or be a complex shape.
356
359 m_padPreviewGAL->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
360
361 KIGFX::VIEW_CONTROLS* parentViewControls = m_parent->GetCanvas()->GetViewControls();
362 m_padPreviewGAL->GetViewControls()->ApplySettings( parentViewControls->GetSettings() );
363
364 m_padPreviewGAL->Show();
365
367
368 // fix the pad render mode (filled/not filled)
369 auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
370
371 settings->m_ForcePadSketchModeOn = m_cbShowPadOutline->IsChecked();
372 settings->SetHighContrast( false );
373 settings->m_ContrastModeDisplay = HIGH_CONTRAST_MODE::NORMAL;
374
375 // gives a non null grid size (0.001mm) because GAL layer does not like a 0 size grid:
376 double gridsize = 0.001 * pcbIUScale.IU_PER_MM;
377 view->GetGAL()->SetGridSize( VECTOR2D( gridsize, gridsize ) );
378
379 // And do not show the grid:
380 view->GetGAL()->SetGridVisibility( false );
381 view->GetGAL()->SetAxesEnabled( false );
382 view->Add( m_previewPad );
383 view->Add( m_axisOrigin );
384
386 Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_PAD_PROPERTIES::OnResize ) );
387}
388
389
391{
392 // Note: use ChangeValue() to avoid generating a wxEVT_TEXT event
394
397
400}
401
402
404{
405 if( m_previewPad->GetShape() != PAD_SHAPE::ROUNDRECT
406 && m_previewPad->GetShape() != PAD_SHAPE::CHAMFERED_RECT )
407 {
408 return;
409 }
410
411 if( m_cornerRadius.GetValue() < 0 )
412 m_cornerRadiusCtrl->ChangeValue( "0" );
413
415 {
417
420
421 redraw();
422 }
423}
424
425
427{
428 if( m_previewPad->GetShape() != PAD_SHAPE::ROUNDRECT
429 && m_previewPad->GetShape() != PAD_SHAPE::CHAMFERED_RECT )
430 {
431 return;
432 }
433
434 wxObject* ctrl = event.GetEventObject();
435 wxString value = event.GetString();
436 bool changed = false;
437
438 if( ctrl == m_cornerRatioCtrl || ctrl == m_mixedCornerRatioCtrl )
439 {
440 double ratioPercent;
441
442 if( value.ToDouble( &ratioPercent ) )
443 {
444 // Clamp ratioPercent to acceptable value (0.0 to 50.0)
445 if( ratioPercent < 0.0 )
446 {
449 }
450 else if( ratioPercent > 50.0 )
451 {
454 }
455
456 if( ctrl == m_cornerRatioCtrl )
457 m_mixedCornerRatioCtrl->ChangeValue( value );
458 else
459 m_cornerRatioCtrl->ChangeValue( value );
460
461 changed = true;
462 }
463 }
464 else if( ctrl == m_chamferRatioCtrl || ctrl == m_mixedChamferRatioCtrl )
465 {
466 double ratioPercent;
467
468 if( value.ToDouble( &ratioPercent ) )
469 {
470 // Clamp ratioPercent to acceptable value (0.0 to 50.0)
471 if( ratioPercent < 0.0 )
472 {
475 }
476 else if( ratioPercent > 50.0 )
477 {
480 }
481
482 if( ctrl == m_chamferRatioCtrl )
483 m_mixedChamferRatioCtrl->ChangeValue( value );
484 else
485 m_chamferRatioCtrl->ChangeValue( value );
486
487 changed = true;
488 }
489 }
490
491 if( changed && transferDataToPad( m_previewPad ) )
493
494 redraw();
495}
496
497
499{
500 wxString msg;
501
502 // Disable pad net name wxTextCtrl if the caller is the footprint editor
503 // because nets are living only in the board managed by the board editor
505
514 m_layerECO1->SetLabel( m_board->GetLayerName( Eco1_User ) );
515 m_layerECO2->SetLabel( m_board->GetLayerName( Eco2_User ) );
517
518 if( m_currentPad )
519 {
520 if( FOOTPRINT* footprint = m_currentPad->GetParentFootprint() )
521 {
523
524 if( footprint->IsFlipped() )
525 {
526 // flip pad (up/down) around its position
528 relPos.y = - relPos.y;
529 }
530
531 m_previewPad->SetPosition( relPos );
533
534 // Display parent footprint info
535 msg.Printf( _("Footprint %s (%s), %s, rotated %g deg"),
536 footprint->Reference().GetShownText( false ),
537 footprint->Value().GetShownText( false ),
538 footprint->IsFlipped() ? _( "back side (mirrored)" ) : _( "front side" ),
539 footprint->GetOrientation().AsDegrees() );
540
541 m_FlippedWarningSizer->Show( footprint->IsFlipped() );
542 m_parentInfo->SetLabel( msg );
543 }
544 }
545
547
548 if( m_currentPad )
549 {
550 m_padNumCtrl->SetValue( m_previewPad->GetNumber() );
551 }
552 else
553 {
555 m_padNumCtrl->SetValue( padTool->GetLastPadNumber() );
556 }
557
559
560 // Display current pad parameters units:
563
566
569
570 m_offsetShapeOpt->SetValue( m_previewPad->GetOffset() != VECTOR2I() );
573
574 if( m_previewPad->GetDelta().x )
575 {
577 m_trapAxisCtrl->SetSelection( 0 );
578 }
579 else
580 {
582 m_trapAxisCtrl->SetSelection( 1 );
583 }
584
585 // Store the initial thermal spoke angle to restore it, because some initializations
586 // can change this value (mainly after m_PadShapeSelector initializations)
587 EDA_ANGLE spokeInitialAngle = m_previewPad->GetThermalSpokeAngle();
588
589 m_padToDieOpt->SetValue( m_previewPad->GetPadToDieLength() != 0 );
591
600
609
611
612 if( m_curvedEdges->GetValue() )
614 else
615 m_curvePointsCtrl->SetValue( 5 );
616
618 {
619 default:
620 case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
621 case ZONE_CONNECTION::FULL: m_ZoneConnectionChoice->SetSelection( 1 ); break;
622 case ZONE_CONNECTION::THERMAL: m_ZoneConnectionChoice->SetSelection( 2 ); break;
623 case ZONE_CONNECTION::NONE: m_ZoneConnectionChoice->SetSelection( 3 ); break;
624 }
625
627 m_ZoneCustomPadShape->SetSelection( 1 );
628 else
629 m_ZoneCustomPadShape->SetSelection( 0 );
630
631 switch( m_previewPad->GetShape() )
632 {
633 default:
634 case PAD_SHAPE::CIRCLE: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_CIRCLE ); break;
635 case PAD_SHAPE::OVAL: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_OVAL ); break;
636 case PAD_SHAPE::RECTANGLE: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_RECT ); break;
637 case PAD_SHAPE::TRAPEZOID: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_TRAPEZOID ); break;
638 case PAD_SHAPE::ROUNDRECT: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_ROUNDRECT ); break;
639
640 case PAD_SHAPE::CHAMFERED_RECT:
643 else
645 break;
646
647 case PAD_SHAPE::CUSTOM:
648 if( m_previewPad->GetAnchorPadShape() == PAD_SHAPE::RECTANGLE )
650 else
652 break;
653 }
654
663
665
666 // Type of pad selection
667 bool aperture =
668 m_previewPad->GetAttribute() == PAD_ATTRIB::SMD && m_previewPad->IsAperturePad();
669
670 if( aperture )
671 {
672 m_padType->SetSelection( APERTURE_DLG_TYPE );
673 }
674 else
675 {
676 switch( m_previewPad->GetAttribute() )
677 {
678 case PAD_ATTRIB::PTH: m_padType->SetSelection( PTH_DLG_TYPE ); break;
679 case PAD_ATTRIB::SMD: m_padType->SetSelection( SMD_DLG_TYPE ); break;
680 case PAD_ATTRIB::CONN: m_padType->SetSelection( CONN_DLG_TYPE ); break;
681 case PAD_ATTRIB::NPTH: m_padType->SetSelection( NPTH_DLG_TYPE ); break;
682 }
683 }
684
685 switch( m_previewPad->GetProperty() )
686 {
687 case PAD_PROP::NONE: m_choiceFabProperty->SetSelection( 0 ); break;
688 case PAD_PROP::BGA: m_choiceFabProperty->SetSelection( 1 ); break;
689 case PAD_PROP::FIDUCIAL_LOCAL: m_choiceFabProperty->SetSelection( 2 ); break;
690 case PAD_PROP::FIDUCIAL_GLBL: m_choiceFabProperty->SetSelection( 3 ); break;
691 case PAD_PROP::TESTPOINT: m_choiceFabProperty->SetSelection( 4 ); break;
692 case PAD_PROP::HEATSINK: m_choiceFabProperty->SetSelection( 5 ); break;
693 case PAD_PROP::CASTELLATED: m_choiceFabProperty->SetSelection( 6 ); break;
694 }
695
696 // Ensure the pad property is compatible with the pad type
697 if( m_previewPad->GetAttribute() == PAD_ATTRIB::NPTH )
698 {
699 m_choiceFabProperty->SetSelection( 0 );
700 m_choiceFabProperty->Enable( false );
701 }
702
704 m_holeShapeCtrl->SetSelection( 0 );
705 else
706 m_holeShapeCtrl->SetSelection( 1 );
707
710
711 // Update some dialog widgets state (Enable/disable options):
712 wxCommandEvent cmd_event;
713 OnPadShapeSelection( cmd_event );
714 OnOffsetCheckbox( cmd_event );
715
716 // Restore thermal spoke angle to its initial value, because it can be modified
717 // by the call to OnPadShapeSelection()
718 m_previewPad->SetThermalSpokeAngle( spokeInitialAngle );
720}
721
722
723void DIALOG_PAD_PROPERTIES::OnResize( wxSizeEvent& event )
724{
725 redraw();
726 event.Skip();
727}
728
729
730void DIALOG_PAD_PROPERTIES::onChangePadMode( wxCommandEvent& event )
731{
733
735
736 // fix the pad render mode (filled/not filled)
737 auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
738
739 settings->m_ForcePadSketchModeOn = m_cbShowPadOutline->IsChecked();
740 settings->SetHighContrast( false );
741 settings->m_ContrastModeDisplay = HIGH_CONTRAST_MODE::NORMAL;
742
743 redraw();
744}
745
746
748{
749 switch( m_PadShapeSelector->GetSelection() )
750 {
754 m_shapePropsBook->SetSelection( 0 );
755 break;
756
758 m_shapePropsBook->SetSelection( 1 );
759 break;
760
762 {
763 m_shapePropsBook->SetSelection( 2 );
764
765 // Reasonable defaults
768
769 break;
770 }
771
773 m_shapePropsBook->SetSelection( 3 );
774
775 // Reasonable default
776 if( m_previewPad->GetChamferRectRatio() == 0.0 )
778
779 // Ensure the displayed value is up to date:
781
782 // A reasonable default is one corner chamfered (usual for some SMD pads).
783 if( !m_cbTopLeft->GetValue() && !m_cbTopRight->GetValue()
784 && !m_cbBottomLeft->GetValue() && !m_cbBottomRight->GetValue() )
785 {
786 m_cbTopLeft->SetValue( true );
787 m_cbTopRight->SetValue( false );
788 m_cbBottomLeft->SetValue( false );
789 m_cbBottomRight->SetValue( false );
790 }
791
792 break;
793
795 m_shapePropsBook->SetSelection( 4 );
796
797 // Reasonable defaults
799 && m_previewPad->GetChamferRectRatio() == 0.0 )
800 {
804 }
805
806 // Ensure the displayed values are up to date:
809 break;
810
811 case CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR: // PAD_SHAPE::CUSTOM, circular anchor
812 case CHOICE_SHAPE_CUSTOM_RECT_ANCHOR: // PAD_SHAPE::CUSTOM, rect anchor
813 m_shapePropsBook->SetSelection( 0 );
814 break;
815 }
816
817 // Note: must do this before enabling/disabling m_sizeY as we're using that as a flag to see
818 // what the last shape was.
819 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CIRCLE )
820 {
821 if( m_sizeYCtrl->IsEnabled() && m_spokeAngle.GetAngleValue() == ANGLE_90 )
823 }
824 else
825 {
826 if( !m_sizeYCtrl->IsEnabled() && m_spokeAngle.GetAngleValue() == ANGLE_45 )
828 }
829
830 // Readjust props book size
831 wxSize size = m_shapePropsBook->GetSize();
832 size.y = m_shapePropsBook->GetPage( m_shapePropsBook->GetSelection() )->GetBestSize().y;
833 m_shapePropsBook->SetMaxSize( size );
834
837
838 m_offsetShapeOpt->Enable( m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CIRCLE );
839
840 if( !m_offsetShapeOpt->IsEnabled() )
841 m_offsetShapeOpt->SetValue( false );
842
843 // Show/hide controls depending on m_offsetShapeOpt being enabled
844 m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
845 m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
846
849
850 for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
851 m_notebook->GetPage( i )->Layout();
852
853 // Resize the dialog if its height is too small to show all widgets:
854 if( m_MainSizer->GetSize().y < m_MainSizer->GetMinSize().y )
855 m_MainSizer->SetSizeHints( this );
856
858 redraw();
859}
860
861
863{
866 redraw();
867}
868
869
870void DIALOG_PAD_PROPERTIES::PadOrientEvent( wxCommandEvent& event )
871{
873 redraw();
874}
875
876
878{
879 m_rbCopperLayersSel->Clear();
880
881 switch( m_padType->GetSelection() )
882 {
883 case PTH_DLG_TYPE:
884 m_rbCopperLayersSel->Append( _( "All copper layers" ) );
885 m_rbCopperLayersSel->Append( wxString::Format( _( "%s, %s and connected layers" ),
887 m_board->GetLayerName( B_Cu ) ) );
888 m_rbCopperLayersSel->Append( _( "Connected layers only" ) );
889 m_rbCopperLayersSel->Append( _( "None" ) );
890 break;
891
892 case NPTH_DLG_TYPE:
893 m_rbCopperLayersSel->Append( wxString::Format( _( "%s and %s" ),
895 m_board->GetLayerName( B_Cu ) ) );
898 m_rbCopperLayersSel->Append( _( "None" ) );
899 break;
900
901 case SMD_DLG_TYPE:
902 case CONN_DLG_TYPE:
905 break;
906
908 m_rbCopperLayersSel->Append( _( "None" ) );
909 break;
910 }
911}
912
913
914void DIALOG_PAD_PROPERTIES::PadTypeSelected( wxCommandEvent& event )
915{
916 bool hasHole = true;
917 bool hasConnection = true;
918 bool hasProperty = true;
919
920 switch( m_padType->GetSelection() )
921 {
922 case PTH_DLG_TYPE: hasHole = true; hasConnection = true; hasProperty = true; break;
923 case SMD_DLG_TYPE: hasHole = false; hasConnection = true; hasProperty = true; break;
924 case CONN_DLG_TYPE: hasHole = false; hasConnection = true; hasProperty = true; break;
925 case NPTH_DLG_TYPE: hasHole = true; hasConnection = false; hasProperty = false; break;
926 case APERTURE_DLG_TYPE: hasHole = false; hasConnection = false; hasProperty = true; break;
927 }
928
929 // Update Layers dropdown list and selects the "best" layer set for the new pad type:
932
933 m_gbSizerHole->Show( hasHole );
934 m_staticline6->Show( hasHole );
935 if( !hasHole )
936 {
937 m_holeX.ChangeValue( 0 );
938 m_holeY.ChangeValue( 0 );
939 }
940 else if ( m_holeX.GetValue() == 0 && m_currentPad )
941 {
944 }
945
946 if( !hasConnection )
947 {
948 m_padNumCtrl->ChangeValue( wxEmptyString );
950 m_padToDieOpt->SetValue( false );
951 }
952 else if( m_padNumCtrl->GetValue().IsEmpty() && m_currentPad )
953 {
954 m_padNumCtrl->ChangeValue( m_currentPad->GetNumber() );
956 }
957
958 if( !hasProperty )
959 m_choiceFabProperty->SetSelection( 0 );
960
961 m_choiceFabProperty->Enable( hasProperty );
962
964
965 // Layout adjustment is needed if the hole details got shown/hidden
966 m_LeftBoxSizer->Layout();
967 redraw();
968}
969
970
971void DIALOG_PAD_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
972{
973 bool hasHole = true;
974 bool hasConnection = true;
975
976 switch( m_padType->GetSelection() )
977 {
978 case PTH_DLG_TYPE: /* PTH */ hasHole = true; hasConnection = true; break;
979 case SMD_DLG_TYPE: /* SMD */ hasHole = false; hasConnection = true; break;
980 case CONN_DLG_TYPE: /* CONN */ hasHole = false; hasConnection = true; break;
981 case NPTH_DLG_TYPE: /* NPTH */ hasHole = true; hasConnection = false; break;
982 case APERTURE_DLG_TYPE: /* Aperture */ hasHole = false; hasConnection = false; break;
983 }
984
985 // Enable/disable hole controls
986 m_holeShapeLabel->Enable( hasHole );
987 m_holeShapeCtrl->Enable( hasHole );
988 m_holeX.Enable( hasHole );
989 m_holeY.Enable( hasHole && m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_OVAL );
990
991 // Enable/disable number and net
992 m_padNumLabel->Enable( hasConnection );
993 m_padNumCtrl->Enable( hasConnection );
994
995 if( m_padNetLabel->IsShown() )
996 {
997 m_padNetLabel->Enable( hasConnection && m_canEditNetName && m_currentPad );
998 m_padNetSelector->Enable( hasConnection && m_canEditNetName && m_currentPad );
999 }
1000
1001 // Enable/disable pad length-to-die
1002 m_padToDieOpt->Enable( hasConnection );
1003
1004 if( !m_padToDieOpt->IsEnabled() )
1005 m_padToDieOpt->SetValue( false );
1006
1007 // We can show/hide this here because it doesn't require the layout to be refreshed.
1008 // All the others have to be done in their event handlers because doing a layout here
1009 // causes infinite looping on MSW.
1010 m_padToDie.Show( m_padToDieOpt->GetValue() );
1011
1012 // Enable/disable Copper Layers control
1013 m_rbCopperLayersSel->Enable( m_padType->GetSelection() != APERTURE_DLG_TYPE );
1014
1016
1017 switch( m_padType->GetSelection() )
1018 {
1019 case PTH_DLG_TYPE:
1020 if( !cu_set.any() )
1021 m_stackupImagesBook->SetSelection( 3 );
1022 else if( !m_previewPad->GetRemoveUnconnected() )
1023 m_stackupImagesBook->SetSelection( 0 );
1024 else if( m_previewPad->GetKeepTopBottom() )
1025 m_stackupImagesBook->SetSelection( 1 );
1026 else
1027 m_stackupImagesBook->SetSelection( 2 );
1028
1029 break;
1030
1031 case NPTH_DLG_TYPE:
1032 if( cu_set.test( F_Cu ) && cu_set.test( B_Cu ) )
1033 m_stackupImagesBook->SetSelection( 4 );
1034 else if( cu_set.test( F_Cu ) )
1035 m_stackupImagesBook->SetSelection( 5 );
1036 else if( cu_set.test( B_Cu ) )
1037 m_stackupImagesBook->SetSelection( 6 );
1038 else
1039 m_stackupImagesBook->SetSelection( 7 );
1040
1041 break;
1042
1043 case SMD_DLG_TYPE:
1044 case CONN_DLG_TYPE:
1045 case APERTURE_DLG_TYPE:
1046 m_stackupImagesBook->ChangeSelection( 3 );
1047 break;
1048 }
1049
1051}
1052
1053
1055{
1056 event.Enable( !m_board->LegacyTeardrops() );
1057}
1058
1059
1061{
1062 event.Enable( !m_board->LegacyTeardrops() && m_curvedEdges->GetValue() );
1063}
1064
1065
1067{
1068 bool isOnCopperLayer = ( m_previewPad->GetLayerSet() & LSET::AllCuMask() ).any();
1069 m_nonCopperWarningBook->ChangeSelection( isOnCopperLayer ? 0 : 1 );
1070}
1071
1072
1073void DIALOG_PAD_PROPERTIES::updatePadLayersList( LSET layer_mask, bool remove_unconnected,
1074 bool keep_top_bottom )
1075{
1077
1078 switch( m_padType->GetSelection() )
1079 {
1080 case PTH_DLG_TYPE:
1081 if( !layer_mask.any() )
1082 layer_mask = PAD::PTHMask();
1083
1084 if( !( layer_mask & LSET::AllCuMask() ).any() )
1085 m_rbCopperLayersSel->SetSelection( 3 );
1086 else if( !remove_unconnected )
1087 m_rbCopperLayersSel->SetSelection( 0 );
1088 else if( keep_top_bottom )
1089 m_rbCopperLayersSel->SetSelection( 1 );
1090 else
1091 m_rbCopperLayersSel->SetSelection( 2 );
1092
1093 break;
1094
1095 case SMD_DLG_TYPE:
1096 if( !layer_mask.any() )
1097 layer_mask = PAD::SMDMask();
1098
1099 if( layer_mask.test( F_Cu ) )
1100 m_rbCopperLayersSel->SetSelection( 0 );
1101 else
1102 m_rbCopperLayersSel->SetSelection( 1 );
1103
1104 break;
1105
1106 case CONN_DLG_TYPE:
1107 if( !layer_mask.any() )
1108 layer_mask = PAD::ConnSMDMask();
1109
1110 if( layer_mask.test( F_Cu ) )
1111 m_rbCopperLayersSel->SetSelection( 0 );
1112 else
1113 m_rbCopperLayersSel->SetSelection( 1 );
1114
1115 break;
1116
1117 case NPTH_DLG_TYPE:
1118 if( !layer_mask.any() )
1119 layer_mask = PAD::UnplatedHoleMask();
1120
1121 if( layer_mask.test( F_Cu ) && layer_mask.test( B_Cu ) )
1122 m_rbCopperLayersSel->SetSelection( 0 );
1123 else if( layer_mask.test( F_Cu ) )
1124 m_rbCopperLayersSel->SetSelection( 1 );
1125 else if( layer_mask.test( B_Cu ) )
1126 m_rbCopperLayersSel->SetSelection( 2 );
1127 else
1128 m_rbCopperLayersSel->SetSelection( 3 );
1129
1130 break;
1131
1132 case APERTURE_DLG_TYPE:
1133 if( !layer_mask.any() )
1134 layer_mask = PAD::ApertureMask();
1135
1136 m_rbCopperLayersSel->SetSelection( 0 );
1137 break;
1138 }
1139
1140 m_layerFrontAdhesive->SetValue( layer_mask[F_Adhes] );
1141 m_layerBackAdhesive->SetValue( layer_mask[B_Adhes] );
1142
1143 m_layerFrontPaste->SetValue( layer_mask[F_Paste] );
1144 m_layerBackPaste->SetValue( layer_mask[B_Paste] );
1145
1146 m_layerFrontSilk->SetValue( layer_mask[F_SilkS] );
1147 m_layerBackSilk->SetValue( layer_mask[B_SilkS] );
1148
1149 m_layerFrontMask->SetValue( layer_mask[F_Mask] );
1150 m_layerBackMask->SetValue( layer_mask[B_Mask] );
1151
1152 m_layerECO1->SetValue( layer_mask[Eco1_User] );
1153 m_layerECO2->SetValue( layer_mask[Eco2_User] );
1154
1155 m_layerUserDwgs->SetValue( layer_mask[Dwgs_User] );
1156}
1157
1158
1160{
1161 bool retVal = DIALOG_SHIM::Show( aShow );
1162
1163 if( aShow )
1164 {
1165 // It *should* work to set the stackup bitmap in the constructor, but it doesn't.
1166 // wxWidgets needs to have these set when the panel is visible for some reason.
1167 // https://gitlab.com/kicad/code/kicad/-/issues/5534
1168 m_stackupImage0->SetBitmap( KiBitmap( BITMAPS::pads_reset_unused ) );
1169 m_stackupImage1->SetBitmap( KiBitmap( BITMAPS::pads_remove_unused_keep_bottom ) );
1170 m_stackupImage2->SetBitmap( KiBitmap( BITMAPS::pads_remove_unused ) );
1171 m_stackupImage4->SetBitmap( KiBitmap( BITMAPS::pads_npth_top_bottom ) );
1172 m_stackupImage5->SetBitmap( KiBitmap( BITMAPS::pads_npth_top ) );
1173 m_stackupImage6->SetBitmap( KiBitmap( BITMAPS::pads_npth_bottom ) );
1174 m_stackupImage7->SetBitmap( KiBitmap( BITMAPS::pads_npth ) );
1175
1176 Layout();
1177 }
1178
1179 return retVal;
1180}
1181
1182
1183void DIALOG_PAD_PROPERTIES::OnSetCopperLayers( wxCommandEvent& event )
1184{
1186 redraw();
1187}
1188
1189
1190void DIALOG_PAD_PROPERTIES::OnSetLayers( wxCommandEvent& event )
1191{
1193 redraw();
1194}
1195
1196
1198{
1199 bool error = !transferDataToPad( m_previewPad );
1200
1201 wxArrayString error_msgs;
1202 wxArrayString warning_msgs;
1203 VECTOR2I pad_size = m_previewPad->GetSize();
1204 VECTOR2I drill_size = m_previewPad->GetDrillSize();
1205
1206 if( m_previewPad->GetShape() == PAD_SHAPE::CUSTOM )
1207 {
1208 pad_size = m_previewPad->GetBoundingBox().GetSize();
1209 }
1210 else if( m_previewPad->GetShape() == PAD_SHAPE::CIRCLE )
1211 {
1212 if( pad_size.x <= 0 )
1213 error_msgs.Add( _( "Error: Pad must have a positive size." ) );
1214 }
1215 else
1216 {
1217 if( pad_size.x <= 0 || pad_size.y <= 0 )
1218 error_msgs.Add( _( "Error: Pad must have a positive size." ) );
1219 }
1220
1221 // Test hole against pad shape
1223 {
1224 int maxError = m_board->GetDesignSettings().m_MaxError;
1225 SHAPE_POLY_SET padOutline;
1226
1227 m_previewPad->TransformShapeToPolygon( padOutline, UNDEFINED_LAYER, 0, maxError,
1228 ERROR_INSIDE );
1229
1230 if( !padOutline.Collide( m_previewPad->GetPosition() ) )
1231 {
1232 warning_msgs.Add( _( "Warning: Pad hole not inside pad shape." ) );
1233 }
1234 else if( m_previewPad->GetAttribute() == PAD_ATTRIB::PTH )
1235 {
1236 std::shared_ptr<SHAPE_SEGMENT> slot = m_previewPad->GetEffectiveHoleShape();
1237 SHAPE_POLY_SET slotOutline;
1238
1239 TransformOvalToPolygon( slotOutline, slot->GetSeg().A, slot->GetSeg().B,
1240 slot->GetWidth(), maxError, ERROR_INSIDE );
1241
1242 padOutline.BooleanSubtract( slotOutline, SHAPE_POLY_SET::PM_FAST );
1243
1244 if( padOutline.IsEmpty() )
1245 warning_msgs.Add( _( "Warning: Pad hole will leave no copper." ) );
1246 }
1247 }
1248
1249 if( m_previewPad->GetLocalClearance() < 0 )
1250 warning_msgs.Add( _( "Warning: Negative local clearance values will have no effect." ) );
1251
1252 // Some pads need a negative solder mask clearance (mainly for BGA with small pads)
1253 // However the negative solder mask clearance must not create negative mask size
1254 // Therefore test for minimal acceptable negative value
1256 {
1257 int absMargin = abs( m_previewPad->GetLocalSolderMaskMargin() );
1258
1259 if( m_previewPad->GetShape() == PAD_SHAPE::CUSTOM )
1260 {
1261 for( const std::shared_ptr<PCB_SHAPE>& shape : m_previewPad->GetPrimitives() )
1262 {
1263 BOX2I shapeBBox = shape->GetBoundingBox();
1264
1265 if( absMargin > shapeBBox.GetWidth() || absMargin > shapeBBox.GetHeight() )
1266 {
1267 warning_msgs.Add( _( "Warning: Negative solder mask clearances larger than "
1268 "some shape primitives. Results may be surprising." ) );
1269
1270 break;
1271 }
1272 }
1273 }
1274 else if( absMargin > pad_size.x || absMargin > pad_size.y )
1275 {
1276 warning_msgs.Add( _( "Warning: Negative solder mask clearance larger than pad. No "
1277 "solder mask will be generated." ) );
1278 }
1279 }
1280
1281 // Some pads need a positive solder paste clearance (mainly for BGA with small pads)
1282 // However, a positive value can create issues if the resulting shape is too big.
1283 // (like a solder paste creating a solder paste area on a neighbor pad or on the solder mask)
1284 // So we could ask for user to confirm the choice
1285 // For now we just check for disappearing paste
1286 wxSize paste_size;
1287 int paste_margin = m_previewPad->GetLocalSolderPasteMargin();
1288 double paste_ratio = m_previewPad->GetLocalSolderPasteMarginRatio();
1289
1290 paste_size.x = pad_size.x + paste_margin + KiROUND( pad_size.x * paste_ratio );
1291 paste_size.y = pad_size.y + paste_margin + KiROUND( pad_size.y * paste_ratio );
1292
1293 if( paste_size.x <= 0 || paste_size.y <= 0 )
1294 {
1295 warning_msgs.Add( _( "Warning: Negative solder paste margins larger than pad. No solder "
1296 "paste mask will be generated." ) );
1297 }
1298
1299 LSET padlayers_mask = m_previewPad->GetLayerSet();
1300
1301 if( padlayers_mask == 0 )
1302 error_msgs.Add( _( "Error: pad has no layer." ) );
1303
1304 if( !padlayers_mask[F_Cu] && !padlayers_mask[B_Cu] )
1305 {
1306 if( ( drill_size.x || drill_size.y ) && m_previewPad->GetAttribute() != PAD_ATTRIB::NPTH )
1307 {
1308 warning_msgs.Add( _( "Warning: Plated through holes should normally have a copper pad "
1309 "on at least one layer." ) );
1310 }
1311 }
1312
1313 if( error )
1314 error_msgs.Add( _( "Error: Trapazoid delta is too large." ) );
1315
1316 switch( m_previewPad->GetAttribute() )
1317 {
1318 case PAD_ATTRIB::NPTH: // Not plated, but through hole, a hole is expected
1319 case PAD_ATTRIB::PTH: // Pad through hole, a hole is also expected
1320 if( drill_size.x <= 0
1321 || ( drill_size.y <= 0 && m_previewPad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ) )
1322 {
1323 error_msgs.Add( _( "Error: Through hole pad has no hole." ) );
1324 }
1325 break;
1326
1327 case PAD_ATTRIB::CONN: // Connector pads are smd pads, just they do not have solder paste.
1328 if( padlayers_mask[B_Paste] || padlayers_mask[F_Paste] )
1329 {
1330 warning_msgs.Add( _( "Warning: Connector pads normally have no solder paste. Use a "
1331 "SMD pad instead." ) );
1332 }
1334
1335 case PAD_ATTRIB::SMD: // SMD and Connector pads (One external copper layer only)
1336 {
1337 if( drill_size.x > 0 || drill_size.y > 0 )
1338 {
1339 error_msgs.Add( _( "Error: SMD pad has a hole." ) );
1340 }
1341
1342 LSET innerlayers_mask = padlayers_mask & LSET::InternalCuMask();
1343
1344 if( ( padlayers_mask[F_Cu] && padlayers_mask[B_Cu] ) || innerlayers_mask.count() != 0 )
1345 warning_msgs.Add( _( "Warning: SMD pad has no outer layers." ) );
1346 }
1347 break;
1348 }
1349
1350 if( ( m_previewPad->GetProperty() == PAD_PROP::FIDUCIAL_GLBL || m_previewPad->GetProperty() == PAD_PROP::FIDUCIAL_LOCAL )
1351 && m_previewPad->GetAttribute() == PAD_ATTRIB::NPTH )
1352 {
1353 warning_msgs.Add( _( "Warning: Fiducial property makes no sense on NPTH pads." ) );
1354 }
1355
1356 if( m_previewPad->GetProperty() == PAD_PROP::TESTPOINT
1357 && m_previewPad->GetAttribute() == PAD_ATTRIB::NPTH )
1358 {
1359 warning_msgs.Add( _( "Warning: Testpoint property makes no sense on NPTH pads." ) );
1360 }
1361
1362 if( m_previewPad->GetProperty() == PAD_PROP::HEATSINK
1363 && m_previewPad->GetAttribute() == PAD_ATTRIB::NPTH )
1364 {
1365 warning_msgs.Add( _( "Warning: Heatsink property makes no sense of NPTH pads." ) );
1366 }
1367
1368 if( m_previewPad->GetProperty() == PAD_PROP::CASTELLATED
1369 && m_previewPad->GetAttribute() != PAD_ATTRIB::PTH )
1370 {
1371 warning_msgs.Add( _( "Warning: Castellated property is for PTH pads." ) );
1372 }
1373
1374 if( m_previewPad->GetProperty() == PAD_PROP::BGA
1375 && m_previewPad->GetAttribute() != PAD_ATTRIB::SMD )
1376 {
1377 warning_msgs.Add( _( "Warning: BGA property is for SMD pads." ) );
1378 }
1379
1380 if( m_previewPad->GetShape() == PAD_SHAPE::ROUNDRECT
1381 || m_previewPad->GetShape() == PAD_SHAPE::CHAMFERED_RECT )
1382 {
1384
1385 if( m_cornerRatio.GetDoubleValue() < 0.0 )
1386 error_msgs.Add( _( "Error: Negative corner size." ) );
1387 else if( m_cornerRatio.GetDoubleValue() > 50.0 )
1388 warning_msgs.Add( _( "Warning: Corner size will make pad circular." ) );
1389 }
1390
1391 // PADSTACKS TODO: this will need to check each layer in the pad...
1392 if( m_previewPad->GetShape() == PAD_SHAPE::CUSTOM )
1393 {
1394 SHAPE_POLY_SET mergedPolygon;
1395 m_previewPad->MergePrimitivesAsPolygon( &mergedPolygon );
1396
1397 if( mergedPolygon.OutlineCount() > 1 )
1398 error_msgs.Add( _( "Error: Custom pad shape must resolve to a single polygon." ) );
1399 }
1400
1401
1402 if( error_msgs.GetCount() || warning_msgs.GetCount() )
1403 {
1404 wxString title = error_msgs.GetCount() ? _( "Pad Properties Errors" )
1405 : _( "Pad Properties Warnings" );
1406 HTML_MESSAGE_BOX dlg( this, title );
1407
1408 wxArrayString msgs = error_msgs;
1409
1410 for( const wxString& msg : warning_msgs )
1411 msgs.Add( msg );
1412
1413 dlg.ListSet( msgs );
1414
1415 dlg.ShowModal();
1416 }
1417
1418 return error_msgs.GetCount() == 0;
1419}
1420
1421
1423{
1424 if( !m_canUpdate )
1425 return;
1426
1428 KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( view->GetPainter() );
1429 KIGFX::PCB_RENDER_SETTINGS* settings = painter->GetSettings();
1430
1432
1433 // The layer used to place primitive items selected when editing custom pad shapes
1434 // we use here a layer never used in a pad:
1435 #define SELECTED_ITEMS_LAYER Dwgs_User
1436
1439
1441
1442 view->Update( m_previewPad );
1443
1444 // delete previous items if highlight list
1445 while( m_highlight.size() )
1446 {
1447 delete m_highlight.back(); // the dtor also removes item from view
1448 m_highlight.pop_back();
1449 }
1450
1451 BOX2I bbox = m_previewPad->ViewBBox();
1452
1453 if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
1454 {
1455 // The origin always goes in the middle of the canvas; we want offsetting the pad
1456 // shape to move the pad, not the hole
1457 bbox.Move( -m_previewPad->GetPosition() );
1458 int maxXExtent = std::max( abs( bbox.GetLeft() ), abs( bbox.GetRight() ) );
1459 int maxYExtent = std::max( abs( bbox.GetTop() ), abs( bbox.GetBottom() ) );
1460
1461 // Don't blow up the GAL on too-large numbers
1462 if( maxXExtent > INT_MAX / 4 )
1463 maxXExtent = INT_MAX / 4;
1464
1465 if( maxYExtent > INT_MAX / 4 )
1466 maxYExtent = INT_MAX / 4;
1467
1468 BOX2D viewBox( m_previewPad->GetPosition(), {0, 0} );
1469 BOX2D canvasBox( m_previewPad->GetPosition(), {0, 0} );
1470 viewBox.Inflate( maxXExtent * 1.4, maxYExtent * 1.4 ); // add a margin
1471 canvasBox.Inflate( maxXExtent * 2.0, maxYExtent * 2.0 );
1472
1473 view->SetBoundary( canvasBox );
1474
1475 // Autozoom
1476 view->SetViewport( viewBox );
1477
1480 }
1481}
1482
1483
1485{
1486 if( !wxDialog::TransferDataToWindow() )
1487 return false;
1488
1489 if( !m_panelGeneral->TransferDataToWindow() )
1490 return false;
1491
1492 if( !m_localSettingsPanel->TransferDataToWindow() )
1493 return false;
1494
1495 return true;
1496}
1497
1498
1500{
1501 BOARD_COMMIT commit( m_parent );
1502
1503 if( !wxDialog::TransferDataFromWindow() )
1504 return false;
1505
1506 if( !m_panelGeneral->TransferDataFromWindow() )
1507 return false;
1508
1509 if( !m_localSettingsPanel->TransferDataFromWindow() )
1510 return false;
1511
1512 if( !padValuesOK() )
1513 return false;
1514
1516 return false;
1517
1519 padTool->SetLastPadNumber( m_masterPad->GetNumber() );
1520
1521 // m_masterPad is a pattern: ensure there is no net for this pad:
1523
1524 if( !m_currentPad ) // Set current Pad parameters
1525 return true;
1526
1527 commit.Modify( m_currentPad );
1528
1529 // Update values
1533
1535
1536 VECTOR2I size = m_masterPad->GetDelta();
1537 m_currentPad->SetDelta( size );
1538
1541
1542 VECTOR2I offset = m_masterPad->GetOffset();
1543 m_currentPad->SetOffset( offset );
1544
1546
1547 if( m_masterPad->GetShape() != PAD_SHAPE::CUSTOM )
1549
1552
1556
1558
1559 int padNetcode = NETINFO_LIST::UNCONNECTED;
1560
1561 // For PAD_ATTRIB::NPTH, ensure there is no net name selected
1562 if( m_masterPad->GetAttribute() != PAD_ATTRIB::NPTH )
1563 padNetcode = m_padNetSelector->GetSelectedNetcode();
1564
1565 m_currentPad->SetNetCode( padNetcode );
1577
1579
1580 // rounded rect pads with radius ratio = 0 are in fact rect pads.
1581 // So set the right shape (and perhaps issues with a radius = 0)
1582 if( m_currentPad->GetShape() == PAD_SHAPE::ROUNDRECT &&
1584 {
1585 m_currentPad->SetShape( PAD_SHAPE::RECTANGLE );
1586 }
1587
1588 // Set the fabrication property:
1590
1591 // define the way the clearance area is defined in zones
1593
1594 VECTOR2I relPos = m_masterPad->GetPosition();
1595
1597 {
1598 // flip pad (up/down) around its position
1600 relPos.y = -relPos.y;
1601 }
1602
1603 // Must be done after flipping
1605
1607
1608 // redraw the area where the pad was
1610
1611 commit.Push( _( "Modify pad" ) );
1612
1613 return true;
1614}
1615
1616
1618{
1619 PAD_PROP prop = PAD_PROP::NONE;
1620
1621 switch( m_choiceFabProperty->GetSelection() )
1622 {
1623 case 0: prop = PAD_PROP::NONE; break;
1624 case 1: prop = PAD_PROP::BGA; break;
1625 case 2: prop = PAD_PROP::FIDUCIAL_LOCAL; break;
1626 case 3: prop = PAD_PROP::FIDUCIAL_GLBL; break;
1627 case 4: prop = PAD_PROP::TESTPOINT; break;
1628 case 5: prop = PAD_PROP::HEATSINK; break;
1629 case 6: prop = PAD_PROP::CASTELLATED; break;
1630 }
1631
1632 return prop;
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
1652{
1653 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CIRCLE
1655 {
1656 m_sizeXLabel->SetLabel( _( "Diameter:" ) );
1657 m_sizeY.Show( false );
1658 m_bitmapTeardrop->SetBitmap( KiBitmap( BITMAPS::teardrop_sizes ) );
1659 }
1660 else
1661 {
1662 m_sizeXLabel->SetLabel( _( "Pad size X:" ) );
1663 m_sizeY.Show( true );
1664 m_bitmapTeardrop->SetBitmap( KiBitmap( BITMAPS::teardrop_rect_sizes ) );
1665 }
1666
1667 m_sizeXLabel->GetParent()->Layout();
1668}
1669
1670
1672{
1673 if( !Validate() )
1674 return false;
1675
1676 if( !m_panelGeneral->Validate() )
1677 return false;
1678
1679 if( !m_localSettingsPanel->Validate() )
1680 return false;
1681
1682 if( !m_spokeWidth.Validate( 0, INT_MAX ) )
1683 return false;
1684
1685 aPad->SetAttribute( code_type[m_padType->GetSelection()] );
1686 aPad->SetShape( code_shape[m_PadShapeSelector->GetSelection()] );
1687
1689 aPad->SetAnchorPadShape( PAD_SHAPE::RECTANGLE );
1690 else
1691 aPad->SetAnchorPadShape( PAD_SHAPE::CIRCLE );
1692
1693 if( aPad->GetShape() == PAD_SHAPE::CUSTOM )
1695
1696 aPad->GetTeardropParams().m_Enabled = m_cbTeardrops->GetValue();
1703
1704 if( m_curvedEdges->GetValue() )
1706 else
1708
1710
1711 // Read pad clearances values:
1719
1720 // And rotation
1722
1723 switch( m_ZoneConnectionChoice->GetSelection() )
1724 {
1725 default:
1726 case 0: aPad->SetZoneConnection( ZONE_CONNECTION::INHERITED ); break;
1727 case 1: aPad->SetZoneConnection( ZONE_CONNECTION::FULL ); break;
1728 case 2: aPad->SetZoneConnection( ZONE_CONNECTION::THERMAL ); break;
1729 case 3: aPad->SetZoneConnection( ZONE_CONNECTION::NONE ); break;
1730 }
1731
1733
1734 if( m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_CIRCLE )
1735 {
1738 }
1739 else
1740 {
1743 }
1744
1745 if( aPad->GetShape() == PAD_SHAPE::CIRCLE )
1747 else
1749
1750 // For a trapezoid, test delta value (be sure delta is not too large for pad size)
1751 // remember DeltaSize.x is the Y size variation
1752 bool error = false;
1753 VECTOR2I delta( 0, 0 );
1754
1755 if( aPad->GetShape() == PAD_SHAPE::TRAPEZOID )
1756 {
1757 // For a trapezoid, only one of delta.x or delta.y is not 0, depending on axis.
1758 if( m_trapAxisCtrl->GetSelection() == 0 )
1760 else
1762
1763 if( delta.x < 0 && delta.x < -aPad->GetSize().y )
1764 {
1765 delta.x = -aPad->GetSize().y + 2;
1766 error = true;
1767 }
1768
1769 if( delta.x > 0 && delta.x > aPad->GetSize().y )
1770 {
1771 delta.x = aPad->GetSize().y - 2;
1772 error = true;
1773 }
1774
1775 if( delta.y < 0 && delta.y < -aPad->GetSize().x )
1776 {
1777 delta.y = -aPad->GetSize().x + 2;
1778 error = true;
1779 }
1780
1781 if( delta.y > 0 && delta.y > aPad->GetSize().x )
1782 {
1783 delta.y = aPad->GetSize().x - 2;
1784 error = true;
1785 }
1786 }
1787
1788 aPad->SetDelta( delta );
1789
1790 if( m_offsetShapeOpt->GetValue() )
1792 else
1793 aPad->SetOffset( VECTOR2I() );
1794
1795 // Read pad length die
1796 if( m_padToDieOpt->GetValue() )
1798 else
1799 aPad->SetPadToDieLength( 0 );
1800
1801 aPad->SetNumber( m_padNumCtrl->GetValue() );
1803
1804 int chamfers = 0;
1805
1806 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_RECT )
1807 {
1808 if( m_cbTopLeft->GetValue() )
1809 chamfers |= RECT_CHAMFER_TOP_LEFT;
1810
1811 if( m_cbTopRight->GetValue() )
1812 chamfers |= RECT_CHAMFER_TOP_RIGHT;
1813
1814 if( m_cbBottomLeft->GetValue() )
1815 chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1816
1817 if( m_cbBottomRight->GetValue() )
1818 chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1819 }
1820 else if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT )
1821 {
1822 if( m_cbTopLeft1->GetValue() )
1823 chamfers |= RECT_CHAMFER_TOP_LEFT;
1824
1825 if( m_cbTopRight1->GetValue() )
1826 chamfers |= RECT_CHAMFER_TOP_RIGHT;
1827
1828 if( m_cbBottomLeft1->GetValue() )
1829 chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1830
1831 if( m_cbBottomRight1->GetValue() )
1832 chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1833 }
1834 aPad->SetChamferPositions( chamfers );
1835
1836 if( aPad->GetShape() == PAD_SHAPE::CUSTOM )
1837 {
1838 // The pad custom has a "anchor pad" (a basic shape: round or rect pad)
1839 // that is the minimal area of this pad, and is useful to ensure a hole
1840 // diameter is acceptable, and is used in Gerber files as flashed area
1841 // reference
1842 if( aPad->GetAnchorPadShape() == PAD_SHAPE::CIRCLE )
1844 }
1845
1846 // Define the way the clearance area is defined in zones. Since all non-custom pad
1847 // shapes are convex to begin with, this really only makes any difference for custom
1848 // pad shapes.
1849 aPad->SetCustomShapeInZoneOpt( m_ZoneCustomPadShape->GetSelection() == 0 ?
1852
1853 switch( aPad->GetAttribute() )
1854 {
1855 case PAD_ATTRIB::PTH:
1856 break;
1857
1858 case PAD_ATTRIB::CONN:
1859 case PAD_ATTRIB::SMD:
1860 // SMD and PAD_ATTRIB::CONN has no hole.
1861 // basically, SMD and PAD_ATTRIB::CONN are same type of pads
1862 // PAD_ATTRIB::CONN has just a default non technical layers that differs from SMD
1863 // and are intended to be used in virtual edge board connectors
1864 // However we can accept a non null offset,
1865 // mainly to allow complex pads build from a set of basic pad shapes
1866 aPad->SetDrillSize( VECTOR2I( 0, 0 ) );
1867 break;
1868
1869 case PAD_ATTRIB::NPTH:
1870 // Mechanical purpose only:
1871 // no net name, no pad name allowed
1872 aPad->SetNumber( wxEmptyString );
1874 break;
1875
1876 default:
1877 wxFAIL_MSG( wxT( "DIALOG_PAD_PROPERTIES::transferDataToPad: unknown pad type" ) );
1878 break;
1879 }
1880
1881 if( aPad->GetShape() == PAD_SHAPE::ROUNDRECT )
1882 {
1884 }
1885 else if( aPad->GetShape() == PAD_SHAPE::CHAMFERED_RECT )
1886 {
1888 {
1891 }
1892 else // Choice is CHOICE_SHAPE_CHAMFERED_RECT, no rounded corner
1893 {
1895 aPad->SetRoundRectRadiusRatio( 0 );
1896 }
1897 }
1898
1900
1901 LSET padLayerMask = LSET();
1902 int copperLayersChoice = m_rbCopperLayersSel->GetSelection();
1903
1904 aPad->SetRemoveUnconnected( false );
1905 aPad->SetKeepTopBottom( false );
1906
1907 switch( m_padType->GetSelection() )
1908 {
1909 case PTH_DLG_TYPE:
1910 switch( copperLayersChoice )
1911 {
1912 case 0:
1913 // All copper layers
1914 padLayerMask |= LSET::AllCuMask();
1915 break;
1916
1917 case 1:
1918 // Front, back and connected
1919 padLayerMask |= LSET::AllCuMask();
1920 aPad->SetRemoveUnconnected( true );
1921 aPad->SetKeepTopBottom( true );
1922 break;
1923
1924 case 2:
1925 // Connected only
1926 padLayerMask |= LSET::AllCuMask();
1927 aPad->SetRemoveUnconnected( true );
1928 break;
1929
1930 case 3:
1931 // No copper layers
1932 break;
1933 }
1934
1935 break;
1936
1937 case NPTH_DLG_TYPE:
1938 switch( copperLayersChoice )
1939 {
1940 case 0: padLayerMask.set( F_Cu ).set( B_Cu ); break;
1941 case 1: padLayerMask.set( F_Cu ); break;
1942 case 2: padLayerMask.set( B_Cu ); break;
1943 default: break;
1944 }
1945
1946 break;
1947
1948 case SMD_DLG_TYPE:
1949 case CONN_DLG_TYPE:
1950 switch( copperLayersChoice )
1951 {
1952 case 0: padLayerMask.set( F_Cu ); break;
1953 case 1: padLayerMask.set( B_Cu ); break;
1954 }
1955
1956 break;
1957
1958 case APERTURE_DLG_TYPE:
1959 // no copper layers
1960 break;
1961 }
1962
1963 if( m_layerFrontAdhesive->GetValue() )
1964 padLayerMask.set( F_Adhes );
1965
1966 if( m_layerBackAdhesive->GetValue() )
1967 padLayerMask.set( B_Adhes );
1968
1969 if( m_layerFrontPaste->GetValue() )
1970 padLayerMask.set( F_Paste );
1971
1972 if( m_layerBackPaste->GetValue() )
1973 padLayerMask.set( B_Paste );
1974
1975 if( m_layerFrontSilk->GetValue() )
1976 padLayerMask.set( F_SilkS );
1977
1978 if( m_layerBackSilk->GetValue() )
1979 padLayerMask.set( B_SilkS );
1980
1981 if( m_layerFrontMask->GetValue() )
1982 padLayerMask.set( F_Mask );
1983
1984 if( m_layerBackMask->GetValue() )
1985 padLayerMask.set( B_Mask );
1986
1987 if( m_layerECO1->GetValue() )
1988 padLayerMask.set( Eco1_User );
1989
1990 if( m_layerECO2->GetValue() )
1991 padLayerMask.set( Eco2_User );
1992
1993 if( m_layerUserDwgs->GetValue() )
1994 padLayerMask.set( Dwgs_User );
1995
1996 aPad->SetLayerSet( padLayerMask );
1997
1998 return !error;
1999}
2000
2001
2002void DIALOG_PAD_PROPERTIES::OnOffsetCheckbox( wxCommandEvent& event )
2003{
2004 if( m_offsetShapeOpt->GetValue() )
2005 {
2008 }
2009
2010 // Show/hide controls depending on m_offsetShapeOpt being enabled
2011 m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
2012 m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
2013
2014 for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
2015 m_notebook->GetPage( i )->Layout();
2016
2017 OnValuesChanged( event );
2018}
2019
2020
2022{
2023 if( m_padToDieOpt->GetValue() && m_currentPad )
2025
2026 OnValuesChanged( event );
2027}
2028
2029
2030void DIALOG_PAD_PROPERTIES::OnValuesChanged( wxCommandEvent& event )
2031{
2032 if( m_canUpdate )
2033 {
2035 return;
2036
2037 // If the pad size has changed, update the displayed values for rounded rect pads.
2039
2040 redraw();
2041 }
2042}
2043
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:106
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
TEARDROP_PARAMETERS & GetTeardropParams()
std::unique_ptr< PAD > m_Pad_Master
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:247
VECTOR2I GetFPRelativePosition() const
Definition: board_item.cpp:261
void SetFPRelativePosition(const VECTOR2I &aPos)
Definition: board_item.cpp:275
BOARD_ITEM_CONTAINER * GetParent() const
Definition: board_item.h:182
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:803
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:501
bool LegacyTeardrops() const
Definition: board.h:1175
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:731
coord_type GetTop() const
Definition: box2.h:195
coord_type GetHeight() const
Definition: box2.h:189
coord_type GetWidth() const
Definition: box2.h:188
void Move(const Vec &aMoveVector)
Move the rectangle by the aMoveVector.
Definition: box2.h:112
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:507
coord_type GetRight() const
Definition: box2.h:190
coord_type GetLeft() const
Definition: box2.h:194
const Vec & GetSize() const
Definition: box2.h:180
coord_type GetBottom() const
Definition: box2.h:191
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:103
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.
bool Show(bool aShow) override
std::vector< std::shared_ptr< PCB_SHAPE > > m_primitives
bool padValuesOK()
test if all values are acceptable for the pad
void 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
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
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:97
void SetupStandardButtons(std::map< int, wxString > aLabels={})
int ShowQuasiModal()
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
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:125
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:100
bool IsFlipped() const
Definition: footprint.h:351
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:163
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:168
PCB specific render settings.
Definition: pcb_painter.h:76
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:519
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:313
void SetBoundary(const BOX2D &aBoundary)
Set limits for view area.
Definition: view.h:278
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:1607
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:194
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:821
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:212
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:552
static LSET InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
Definition: lset.cpp:733
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:773
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition: netinfo.h:387
void SetBoard(BOARD *aBoard)
int GetSelectedNetcode()
void SetSelectedNetcode(int aNetcode)
void SetNetInfo(NETINFO_LIST *aNetInfoList)
Tool relating to pads and pad settings.
Definition: pad_tool.h:37
void SetLastPadNumber(const wxString &aPadNumber)
Definition: pad_tool.h:68
wxString GetLastPadNumber() const
Definition: pad_tool.h:67
Definition: pad.h:58
int GetLocalClearance(wxString *aSource) const override
Return any local clearances set in the "classic" (ie: pre-rule) system.
Definition: pad.cpp:817
bool IsAperturePad() const
Definition: pad.h:379
void SetAttribute(PAD_ATTRIB aAttribute)
Definition: pad.cpp:645
void SetLayerSet(LSET aLayers) override
Definition: pad.h:368
PAD_PROP GetProperty() const
Definition: pad.h:375
bool GetRemoveUnconnected() const
Definition: pad.h:581
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: pad.h:355
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pad.h:369
int GetSizeX() const
Definition: pad.h:245
const BOX2I GetBoundingBox() const override
The bounding box is cached, so this will be efficient most of the time.
Definition: pad.cpp:636
const VECTOR2I & GetDrillSize() const
Definition: pad.h:253
PAD_ATTRIB GetAttribute() const
Definition: pad.h:372
void SetLocalSolderPasteMargin(int aMargin)
Definition: pad.h:395
static LSET PTHMask()
layer set for a through hole pad
Definition: pad.cpp:194
ZONE_CONNECTION GetZoneConnection() const
Definition: pad.h:494
void SetRemoveUnconnected(bool aSet)
Set the unconnected removal property.
Definition: pad.h:580
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the pad shape to a closed polygon.
Definition: pad.cpp:1578
void SetThermalGap(int aGap)
Definition: pad.h:525
void SetThermalSpokeAngle(const EDA_ANGLE &aAngle)
The orientation of the thermal spokes.
Definition: pad.h:512
const wxString & GetNumber() const
Definition: pad.h:130
void MergePrimitivesAsPolygon(SHAPE_POLY_SET *aMergedPolygon, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Merge all basic shapes to a SHAPE_POLY_SET.
double GetLocalSolderPasteMarginRatio() const
Definition: pad.h:397
int GetRoundRectCornerRadius() const
Definition: pad.cpp:328
void DeletePrimitivesList()
Clear the basic shapes list.
void SetDrillShape(PAD_DRILL_SHAPE_T aShape)
Definition: pad.h:354
VECTOR2I GetPosition() const override
Definition: pad.h:197
void SetProperty(PAD_PROP aProperty)
Definition: pad.cpp:656
const std::vector< std::shared_ptr< PCB_SHAPE > > & GetPrimitives() const
Accessor to the basic shape list for custom-shaped pads.
Definition: pad.h:300
EDA_ANGLE GetThermalSpokeAngle() const
Definition: pad.h:513
void SetOffset(const VECTOR2I &aOffset)
Definition: pad.h:259
void SetChamferRectRatio(double aChamferScale)
Has meaning only for chamfered rectangular pads.
Definition: pad.cpp:351
const VECTOR2I & GetOffset() const
Definition: pad.h:260
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
Definition: pad.cpp:215
void SetRoundRectCornerRadius(double aRadius)
Has meaning only for rounded rectangle pads.
Definition: pad.cpp:334
void SetLocalClearance(int aClearance)
Definition: pad.h:392
void SetKeepTopBottom(bool aSet)
Set whether we keep the top and bottom connections even if they are not connected.
Definition: pad.h:586
void SetNumber(const wxString &aNumber)
Set the pad number (note that it can be alphanumeric, such as the array reference "AA12").
Definition: pad.h:129
void SetZoneConnection(ZONE_CONNECTION aType)
Definition: pad.h:493
int GetLocalSolderMaskMargin() const
Definition: pad.h:387
bool GetKeepTopBottom() const
Definition: pad.h:587
CUST_PAD_SHAPE_IN_ZONE GetCustomShapeInZoneOpt() const
Definition: pad.h:207
void SetDelta(const VECTOR2I &aSize)
Definition: pad.h:249
bool IsOnCopperLayer() const override
Definition: pad.cpp:771
void SetPosition(const VECTOR2I &aPos) override
Definition: pad.h:191
const VECTOR2I & GetDelta() const
Definition: pad.h:250
static LSET ConnSMDMask()
layer set for a SMD pad on Front layer used for edge board connectors
Definition: pad.cpp:208
void SetDrillSize(const VECTOR2I &aSize)
Definition: pad.h:252
PAD_SHAPE GetShape() const
Definition: pad.h:189
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition: pad.h:341
EDA_ANGLE GetFPRelativeOrientation()
Definition: pad.cpp:682
void Flip(const VECTOR2I &VECTOR2I, bool aFlipLeftRight) override
Flip this object, i.e.
Definition: pad.cpp:691
static LSET ApertureMask()
layer set for an aperture pad
Definition: pad.cpp:222
virtual const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: pad.cpp:1445
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: pad.cpp:201
void SetLocalSolderPasteMarginRatio(double aRatio)
Definition: pad.h:398
void SetShape(PAD_SHAPE aShape)
Set the new shape of this pad.
Definition: pad.h:180
int GetSizeY() const
Definition: pad.h:247
int GetThermalSpokeWidth() const
Definition: pad.h:503
int GetLocalSolderPasteMargin() const
Definition: pad.h:394
void SetFPRelativeOrientation(const EDA_ANGLE &aAngle)
Definition: pad.cpp:673
void SetCustomShapeInZoneOpt(CUST_PAD_SHAPE_IN_ZONE aOption)
Set the option for the custom pad shape to use as clearance area in copper zones.
Definition: pad.h:217
void SetRoundRectRadiusRatio(double aRadiusScale)
Has meaning only for rounded rectangle pads.
Definition: pad.cpp:343
void SetAnchorPadShape(PAD_SHAPE aShape)
Set the shape of the anchor pad for custom shaped pads.
Definition: pad.h:228
void SetOrientation(const EDA_ANGLE &aAngle)
Set the rotation angle of the pad.
Definition: pad.cpp:664
int GetChamferPositions() const
Definition: pad.h:566
void ReplacePrimitives(const std::vector< std::shared_ptr< PCB_SHAPE > > &aPrimitivesList)
Clear the current custom shape primitives list and import a new list.
void SetLocalSolderMaskMargin(int aMargin)
Definition: pad.h:388
void SetThermalSpokeWidth(int aWidth)
Set the width of the thermal spokes connecting the pad to a zone.
Definition: pad.h:502
void SetSize(const VECTOR2I &aSize)
Definition: pad.h:242
double GetRoundRectRadiusRatio() const
Definition: pad.h:547
int GetThermalGap() const
Definition: pad.h:526
std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const override
Return a SHAPE_SEGMENT object representing the pad's hole.
Definition: pad.cpp:405
const VECTOR2I & GetSize() const
Definition: pad.h:243
void SetChamferPositions(int aPositions)
Has meaning only for chamfered rectangular pads.
Definition: pad.h:565
PAD_SHAPE GetAnchorPadShape() const
Definition: pad.h:202
double GetChamferRectRatio() const
Definition: pad.h:556
void SetPadToDieLength(int aLength)
Definition: pad.h:384
int GetPadToDieLength() const
Definition: pad.h:385
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.
Represent a set of closed polygons.
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset difference For aFastMode meaning, see function booleanOp.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
bool Collide(const SHAPE *aShape, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if the boundary of shape (this) lies closer to the shape aShape than aClearance,...
int OutlineCount() const
Return the number of outlines in the set.
int m_CurveSegCount
number of segments to build the curved sides of a teardrop area must be > 2.
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.
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
int GetIntValue()
Definition: unit_binder.h:127
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:71
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:189
This file is part of the common library.
void TransformOvalToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
#define APERTURE_DLG_TYPE
#define CONN_DLG_TYPE
static PAD_ATTRIB code_type[]
#define SELECTED_ITEMS_LAYER
static PAD_SHAPE code_shape[]
static bool PadHasMeaningfulRoundingRadius(const PAD &aPad)
Returns true if the pad's rounding ratio is valid (i.e.
#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
static double GetDefaultIpcRoundingRatio(const PAD &aPad)
Get a sensible default for a rounded rectangle pad's rounding ratio.
#define NPTH_DLG_TYPE
#define PTH_DLG_TYPE
#define PAD_PROPERTIES_DLG_NAME
DIALOG_PAD_PROPERTIES, derived from DIALOG_PAD_PROPERTIES_BASE, created by wxFormBuilder.
#define _(s)
static constexpr EDA_ANGLE & ANGLE_45
Definition: eda_angle.h:438
static constexpr EDA_ANGLE & ANGLE_90
Definition: eda_angle.h:439
#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:40
@ ERROR_INSIDE
@ LAYER_GRID
Definition: layer_ids.h:206
@ B_Adhes
Definition: layer_ids.h:98
@ Dwgs_User
Definition: layer_ids.h:110
@ F_Paste
Definition: layer_ids.h:102
@ F_Adhes
Definition: layer_ids.h:99
@ B_Mask
Definition: layer_ids.h:107
@ B_Cu
Definition: layer_ids.h:96
@ Eco1_User
Definition: layer_ids.h:112
@ F_Mask
Definition: layer_ids.h:108
@ B_Paste
Definition: layer_ids.h:101
@ F_SilkS
Definition: layer_ids.h:105
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
@ Eco2_User
Definition: layer_ids.h:113
@ B_SilkS
Definition: layer_ids.h:104
@ F_Cu
Definition: layer_ids.h:65
This file contains miscellaneous commonly used macros and functions.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:160
@ CUST_PAD_SHAPE_IN_ZONE_OUTLINE
Definition: pad.h:44
@ CUST_PAD_SHAPE_IN_ZONE_CONVEXHULL
Definition: pad.h:45
PAD_ATTRIB
The set of pad shapes, used with PAD::{Set,Get}Attribute().
Definition: pad_shapes.h:81
@ NPTH
like PAD_PTH, but not plated
@ SMD
Smd pad, appears on the solder paste layer (default)
@ PTH
Plated through hole pad.
@ CONN
Like smd, does not appear on the solder paste layer (default)
@ PAD_DRILL_SHAPE_CIRCLE
Definition: pad_shapes.h:70
@ PAD_DRILL_SHAPE_OBLONG
Definition: pad_shapes.h:71
PAD_SHAPE
The set of pad shapes, used with PAD::{Set,Get}Shape()
Definition: pad_shapes.h:35
PAD_PROP
The set of pad properties used in Gerber files (Draw files, and P&P files) to define some properties ...
Definition: pad_shapes.h:97
const double IU_PER_MM
Definition: base_units.h:77
constexpr int mmToIU(double mm) const
Definition: base_units.h:89
constexpr int delta
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85
VECTOR2< double > VECTOR2D
Definition: vector2d.h:587
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588