KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_pad_properties.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2013 Dick Hollenbeck, [email protected]
6 * Copyright (C) 2008-2013 Wayne Stambaugh <[email protected]>
7 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27#include <drc/drc_item.h>
28#include <base_units.h>
29#include <bitmaps.h>
30#include <board_commit.h>
31#include <board.h>
33#include <footprint.h>
34#include <confirm.h>
35#include <core/arraydim.h>
36#include <convert_basic_shapes_to_polygon.h> // for enum RECT_CHAMFER_POSITIONS definition
41#include <macros.h>
42#include <pad.h>
43#include <pad_utils.h>
44#include <pcb_base_frame.h>
46#include <pcb_painter.h>
47#include <pcbnew_settings.h>
49#include <view/view_controls.h>
51#include <tool/tool_manager.h>
52#include <tools/pad_tool.h>
53#include <advanced_config.h> // for pad property feature management
54#include <wx/choicdlg.h>
55
56
57int DIALOG_PAD_PROPERTIES::m_page = 0; // remember the last open page during session
58
59
60// list of pad shapes, ordered like the pad shape wxChoice in dialog.
62{
69 PAD_SHAPE::CHAMFERED_RECT, // choice = CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT
70 PAD_SHAPE::CUSTOM, // choice = CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
71 PAD_SHAPE::CUSTOM // choice = PAD_SHAPE::CUSTOM_RECT_ANCHOR
72};
73
74
75// the ordered index of the pad shape wxChoice in dialog.
76// keep it consistent with code_shape[] and dialog strings
89
90
92{
97 PAD_ATTRIB::SMD // Aperture pad :type SMD with no copper layers,
98 // only on tech layers (usually only on paste layer
99};
100
101
102// These define have the same value as the m_PadType wxChoice GetSelected() return value
103#define PTH_DLG_TYPE 0
104#define SMD_DLG_TYPE 1
105#define CONN_DLG_TYPE 2
106#define NPTH_DLG_TYPE 3
107#define APERTURE_DLG_TYPE 4
108
109
111{
112 DIALOG_PAD_PROPERTIES dlg( this, aPad );
113
114 // QuasiModal required for NET_SELECTOR
115 dlg.ShowQuasiModal();
116}
117
118
121 m_parent( aParent ),
122 m_initialized( false ),
123 m_editLayer( F_Cu ),
150{
151 SetName( PAD_PROPERTIES_DLG_NAME );
153
154 m_currentPad = aPad; // aPad can be NULL, if the dialog is called
155 // from the footprint editor to set default pad setup
156
157 m_board = m_parent->GetBoard();
158
159 // Configure display origin transforms
162
163 m_padNetSelector->SetNetInfo( &m_board->GetNetInfo() );
164
166
170
171 m_masterPad = m_parent->GetDesignSettings().m_Pad_Master.get();
172 m_previewPad = new PAD( (FOOTPRINT*) nullptr );
173
174 if( aPad )
175 {
176 SetTitle( _( "Pad Properties" ) );
177
178 *m_previewPad = *aPad;
179 m_previewPad->GetTeardropParams() = aPad->GetTeardropParams();
180 m_previewPad->ClearFlags( SELECTED|BRIGHTENED );
181 }
182 else
183 {
184 SetTitle( _( "Default Pad Properties for Add Pad Tool" ) );
185
187 m_previewPad->GetTeardropParams() = m_masterPad->GetTeardropParams();
188 }
189
190 // TODO(JE) padstacks: should this be re-run when pad mode changes?
191 // Pads have a hardcoded internal rounding ratio which is 0.25 by default, even if
192 // they're not a rounded shape. This makes it hard to detect an intentional 0.25
193 // ratio, or one that's only there because it's the PAD default.
194 // Zero it out here to mark that we should recompute a better ratio if the user
195 // selects a pad shape which would need a default rounding ratio computed for it
196 m_previewPad->Padstack().ForEachUniqueLayer(
197 [&]( PCB_LAYER_ID aLayer )
198 {
200 m_previewPad->SetRoundRectRadiusRatio( aLayer, 0.0 );
201 } );
202
203 if( m_isFpEditor )
204 {
205 m_padNetLabel->Show( false );
206 m_padNetSelector->Show( false );
207 }
208
209 m_FlippedWarningSizer->Show( false );
210
211 // Pad needs to have a parent for painting; use the parent board for its design settings
212 if( !m_previewPad->GetParent() )
213 m_previewPad->SetParent( m_board );
214
220 m_pad_orientation.SetPrecision( 3 );
221
223 m_spokeAngle.SetPrecision( 3 );
224
225 m_pasteMargin.SetNegativeZero();
226
228 m_pasteMarginRatio.SetNegativeZero();
229
230 m_padToDieDelay.SetUnits( EDA_UNITS::PS );
232
233 initValues();
234
235 m_techLayersLabel->SetFont( KIUI::GetStatusFont( this ) );
236 m_parentInfo->SetFont( KIUI::GetSmallInfoFont( this ) );
237 m_teardropShapeLabel->SetFont( KIUI::GetStatusFont( this ) );
238
239 wxFont infoFont = KIUI::GetSmallInfoFont( this ).Italic();
240 m_nonCopperNote->SetFont( infoFont );
241 m_staticTextInfoPaste->SetFont( infoFont );
242
245
246 // Usually, TransferDataToWindow is called by OnInitDialog
247 // calling it here fixes all widget sizes so FinishDialogSettings can safely fix minsizes
249
250 // Initialize canvas to be able to display the dummy pad:
252
253 m_notebook->SetSelection( m_page );
254
255 switch( m_page )
256 {
257 default:
258 case 0: SetInitialFocus( m_padNumCtrl ); break;
259 case 1: SetInitialFocus( m_thermalGapCtrl ); break;
260 case 2: SetInitialFocus( m_clearanceCtrl ); break;
261 }
262
264 m_initialized = true;
265
266 m_padNetSelector->Connect( FILTERED_ITEM_SELECTED,
267 wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ),
268 nullptr, this );
269
270 if( m_padType->GetSelection() != PTH_DLG_TYPE && m_padType->GetSelection() != NPTH_DLG_TYPE )
271 {
272 m_gbSizerHole->Show( false );
273 m_staticline71->Show( false );
274 }
275
276 // Now all widgets have the size fixed, call FinishDialogSettings
278
279 // Update widgets
280 wxUpdateUIEvent dummyUI;
281 OnUpdateUI( dummyUI );
282
283 // Post a dummy size event to force the pad preview panel to update the
284 // view: actual size, best zoom ... after the frame is shown
285 PostSizeEvent();
286}
287
288
290{
291 m_padNetSelector->Disconnect( FILTERED_ITEM_SELECTED,
292 wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ),
293 nullptr, this );
294
295 m_page = m_notebook->GetSelection();
296
297 delete m_previewPad;
298 delete m_axisOrigin;
299}
300
301
302// Store the pad draw option during a session.
304
305
306void DIALOG_PAD_PROPERTIES::OnInitDialog( wxInitDialogEvent& event )
307{
308 m_selectedColor = COLOR4D( 1.0, 1.0, 1.0, 0.7 );
309
310 // Needed on some WM to be sure the pad is redrawn according to the final size
311 // of the canvas, with the right zoom factor
312 redraw();
313}
314
315
316void DIALOG_PAD_PROPERTIES::OnCancel( wxCommandEvent& event )
317{
318 // Mandatory to avoid m_panelShowPadGal trying to draw something
319 // in a non valid context during closing process:
320 m_padPreviewGAL->StopDrawing();
321
322 // Now call default handler for wxID_CANCEL command event
323 event.Skip();
324}
325
326
328{
329 GAL_DISPLAY_OPTIONS_IMPL opts = m_parent->GetGalDisplayOptions();
330 COLOR_SETTINGS* colorSettings = m_parent->GetColorSettings();
331
332 opts.m_forceDisplayCursor = false;
333
334 // Initialize the canvas to display the pad
335 m_padPreviewGAL = new PCB_DRAW_PANEL_GAL( m_boardViewPanel, -1, wxDefaultPosition,
336 wxDefaultSize, opts,
337 m_parent->GetCanvas()->GetBackend() );
338
339 m_padPreviewSizer->Add( m_padPreviewGAL, 12, wxEXPAND | wxALL, 5 );
340
341 // Show the X and Y axis. It is useful because pad shape can have an offset
342 // or be a complex shape.
345 VECTOR2D( m_previewPad->GetPosition() ) );
346 m_axisOrigin->SetDrawAtZero( true );
347
348 m_padPreviewGAL->UpdateColors();
349 m_padPreviewGAL->SetStealsFocus( false );
350 m_padPreviewGAL->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
351
352 KIGFX::VIEW_CONTROLS* parentViewControls = m_parent->GetCanvas()->GetViewControls();
353 m_padPreviewGAL->GetViewControls()->ApplySettings( parentViewControls->GetSettings() );
354
355 m_padPreviewGAL->Show();
356
357 KIGFX::VIEW* view = m_padPreviewGAL->GetView();
358
359 // fix the pad render mode (filled/not filled)
360 auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
361
362 settings->m_ForcePadSketchModeOn = m_cbShowPadOutline->IsChecked();
363 settings->SetHighContrast( false );
364 settings->m_ContrastModeDisplay = HIGH_CONTRAST_MODE::NORMAL;
365
366 // don't show the locked item shadow in pad preview
368
369 // gives a non null grid size (0.001mm) because GAL layer does not like a 0 size grid:
370 double gridsize = 0.001 * pcbIUScale.IU_PER_MM;
371 view->GetGAL()->SetGridSize( VECTOR2D( gridsize, gridsize ) );
372
373 // And do not show the grid:
374 view->GetGAL()->SetGridVisibility( false );
375 view->GetGAL()->SetAxesEnabled( false );
376 view->Add( m_previewPad );
377 view->Add( m_axisOrigin );
378
379 m_padPreviewGAL->StartDrawing();
380 Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_PAD_PROPERTIES::OnResize ) );
381}
382
383
390
391
392void DIALOG_PAD_PROPERTIES::OnEditLayerChanged( wxCommandEvent& aEvent )
393{
394 // Save data from the previous layer
396
397 switch( m_previewPad->Padstack().Mode() )
398 {
399 default:
402 break;
403
405 switch( m_cbEditLayer->GetSelection() )
406 {
407 default:
408 case 0: m_editLayer = F_Cu; break;
409 case 1: m_editLayer = PADSTACK::INNER_LAYERS; break;
410 case 2: m_editLayer = B_Cu; break;
411 }
412 break;
413
415 {
416 int layer = m_cbEditLayer->GetSelection();
417
418 if( layer < 0 )
419 layer = 0;
420
421 if( m_editLayerCtrlMap.contains( layer ) )
422 m_editLayer = m_editLayerCtrlMap.at( layer );
423 else
425 }
426 }
427
428 // Load controls with the current layer
430
431 wxCommandEvent cmd_event;
432 OnPadShapeSelection( cmd_event );
433 OnOffsetCheckbox( cmd_event );
434
435 redraw();
436}
437
438
440{
441 // Note: use ChangeValue() to avoid generating a wxEVT_TEXT event
442 m_cornerRadius.ChangeValue( m_previewPad->GetRoundRectCornerRadius( m_editLayer ) );
443
444 m_cornerRatio.ChangeDoubleValue( m_previewPad->GetRoundRectRadiusRatio( m_editLayer ) * 100.0 );
445 m_mixedCornerRatio.ChangeDoubleValue( m_previewPad->GetRoundRectRadiusRatio( m_editLayer ) * 100.0 );
446
447 m_chamferRatio.ChangeDoubleValue( m_previewPad->GetChamferRectRatio( m_editLayer ) * 100.0 );
448 m_mixedChamferRatio.ChangeDoubleValue( m_previewPad->GetChamferRectRatio( m_editLayer ) * 100.0 );
449}
450
451
453{
456 {
457 return;
458 }
459
460 if( m_cornerRadius.GetValue() < 0 )
461 m_cornerRadiusCtrl->ChangeValue( "0" );
462
464 {
465 m_previewPad->SetRoundRectCornerRadius( m_editLayer, m_cornerRadius.GetValue() );
466
467 m_cornerRatio.ChangeDoubleValue( m_previewPad->GetRoundRectRadiusRatio( m_editLayer ) * 100.0 );
468 m_mixedCornerRatio.ChangeDoubleValue( m_previewPad->GetRoundRectRadiusRatio( m_editLayer ) * 100.0 );
469
470 redraw();
471 }
472
473 if( m_initialized )
474 OnModify();
475}
476
477
479{
480 // The maximum chamfer ratio is 50% of the smallest pad side if adjacent sides
481 // are selected, or 100% of the smallest pad side if only one side is selected.
482 double baseline = 1.0;
483
484 auto considerCheckboxes = [&]( const std::vector<wxCheckBox*>& checkBoxes )
485 {
486 for( size_t ii : { 0, 1, 2, 3 } )
487 {
488 if( !checkBoxes[ii]->IsChecked() )
489 continue;
490
491 if( checkBoxes[( ii + 1 ) % 4]->IsChecked() || checkBoxes[( ii - 1 ) % 4]->IsChecked() )
492 {
493 // If two adjacent corners are selected, the maximum chamfer ratio is 50%
494 baseline = std::max( baseline, 0.5 );
495 break;
496 }
497 }
498 };
499
500
501 baseline = 1.0 - m_previewPad->GetRoundRectRadiusRatio( m_editLayer );
502 considerCheckboxes( { m_cbTopLeft1, m_cbTopRight1, m_cbBottomRight1, m_cbBottomLeft1 } );
503 considerCheckboxes( { m_cbTopLeft, m_cbTopRight, m_cbBottomRight, m_cbBottomLeft } );
504
505 // If only one corner is selected, the maximum chamfer ratio is 100%
506 return baseline;
507}
508
509
511{
512 return 1.0 - m_previewPad->GetChamferRectRatio( m_editLayer );
513}
514
515
517{
518 auto updateCheckBoxes = []( const std::vector<wxCheckBox*>& aCheckBoxes )
519 {
520 for( size_t ii : { 0, 1, 2, 3 } )
521 {
522 bool disable = aCheckBoxes[( ii + 1 ) % 4]->IsChecked()
523 || aCheckBoxes[( ii + 3 ) % 4]->IsChecked();
524
525 aCheckBoxes[ii]->Enable( !disable );
526
527 if( disable )
528 aCheckBoxes[ii]->SetValue( false );
529 }
530 };
531
532 if( m_mixedChamferRatio.GetDoubleValue() > 50.0 )
533 {
535 }
536
537 if( m_chamferRatio.GetDoubleValue() > 50.0 )
538 {
539 updateCheckBoxes( { m_cbTopLeft, m_cbTopRight, m_cbBottomRight, m_cbBottomLeft } );
540 }
541}
542
543
545{
548 {
549 return;
550 }
551
552 wxObject* ctrl = event.GetEventObject();
553 wxString value = event.GetString();
554 bool changed = false;
555
556 if( ctrl == m_cornerRatioCtrl || ctrl == m_mixedCornerRatioCtrl )
557 {
558 double ratioPercent;
559
560 if( value.ToDouble( &ratioPercent ) )
561 {
562 // Clamp ratioPercent to acceptable value (0.0 to 50.0)
563 double maxRatio = getMaxCornerRadius();
564
565 if( ratioPercent < 0.0 )
566 {
567 m_cornerRatio.SetDoubleValue( 0.0 );
568 m_mixedCornerRatio.SetDoubleValue( 0.0 );
569 }
570 else if( ratioPercent > maxRatio * 100.0 )
571 {
572 m_cornerRatio.SetDoubleValue( maxRatio * 100.0 );
573 m_mixedCornerRatio.SetDoubleValue( maxRatio * 100.0 );
574 }
575
576 if( ctrl == m_cornerRatioCtrl )
577 m_mixedCornerRatioCtrl->ChangeValue( value );
578 else
579 m_cornerRatioCtrl->ChangeValue( value );
580
581 changed = true;
582 }
583 }
584 else if( ctrl == m_chamferRatioCtrl || ctrl == m_mixedChamferRatioCtrl )
585 {
586 double ratioPercent;
587
588 if( value.ToDouble( &ratioPercent ) )
589 {
590 double maxRatio = getMaxChamferRatio();
591 // Clamp ratioPercent to acceptable value (0.0 to maxRatio)
592 if( ratioPercent < 0.0 )
593 {
594 m_chamferRatio.SetDoubleValue( 0.0 );
595 m_mixedChamferRatio.SetDoubleValue( 0.0 );
596 }
597 else if( ratioPercent > maxRatio * 100.0 )
598 {
599 m_chamferRatio.SetDoubleValue( maxRatio * 100.0 );
600 m_mixedChamferRatio.SetDoubleValue( maxRatio * 100.0 );
601 }
602
603 if( ctrl == m_chamferRatioCtrl )
604 m_mixedChamferRatioCtrl->ChangeValue( value );
605 else
606 m_chamferRatioCtrl->ChangeValue( value );
607
609
610 changed = true;
611 }
612 }
613
614 if( changed && transferDataToPad( m_previewPad ) )
615 m_cornerRadius.ChangeValue( m_previewPad->GetRoundRectCornerRadius( m_editLayer ) );
616
617 redraw();
618
619 if( m_initialized )
620 OnModify();
621}
622
623
625{
626 wxString msg;
627
628 // Disable pad net name wxTextCtrl if the caller is the footprint editor
629 // because nets are living only in the board managed by the board editor
631
632 m_layerFrontAdhesive->SetLabel( m_board->GetLayerName( F_Adhes ) );
633 m_layerBackAdhesive->SetLabel( m_board->GetLayerName( B_Adhes ) );
634 m_layerFrontPaste->SetLabel( m_board->GetLayerName( F_Paste ) );
635 m_layerBackPaste->SetLabel( m_board->GetLayerName( B_Paste ) );
636 m_layerFrontSilk->SetLabel( m_board->GetLayerName( F_SilkS ) );
637 m_layerBackSilk->SetLabel( m_board->GetLayerName( B_SilkS ) );
638 m_layerFrontMask->SetLabel( m_board->GetLayerName( F_Mask ) );
639 m_layerBackMask->SetLabel( m_board->GetLayerName( B_Mask ) );
640 m_layerECO1->SetLabel( m_board->GetLayerName( Eco1_User ) );
641 m_layerECO2->SetLabel( m_board->GetLayerName( Eco2_User ) );
642 m_layerUserDwgs->SetLabel( m_board->GetLayerName( Dwgs_User ) );
643
644 VECTOR2I absPos;
645
646 if( m_currentPad )
647 {
648 absPos = m_currentPad->GetPosition();
649
650 if( FOOTPRINT* footprint = m_currentPad->GetParentFootprint() )
651 {
652 VECTOR2I relPos = m_currentPad->GetFPRelativePosition();
653
654 if( footprint->IsFlipped() )
655 {
656 // flip pad (up/down) around its position
658 relPos.y = - relPos.y;
659 }
660
661 m_previewPad->SetPosition( relPos );
662 m_previewPad->SetOrientation( m_currentPad->GetFPRelativeOrientation() );
663
664 // Display parent footprint info
665 msg.Printf( _("Footprint %s (%s), %s, rotated %g deg"),
666 footprint->Reference().GetShownText( false ),
667 footprint->Value().GetShownText( false ),
668 footprint->IsFlipped() ? _( "back side (mirrored)" ) : _( "front side" ),
669 footprint->GetOrientation().AsDegrees() );
670
671 m_FlippedWarningSizer->Show( footprint->IsFlipped() );
672 m_parentInfo->SetLabel( msg );
673 }
674
675 m_padNumCtrl->SetValue( m_previewPad->GetNumber() );
676 }
677 else
678 {
679 PAD_TOOL* padTool = m_parent->GetToolManager()->GetTool<PAD_TOOL>();
680 m_padNumCtrl->SetValue( padTool->GetLastPadNumber() );
681
682 if( m_isFpEditor && m_board->GetFirstFootprint() )
683 {
684 switch( m_board->GetFirstFootprint()->GetAttributes() )
685 {
687 m_previewPad->SetAttribute( PAD_ATTRIB::PTH );
688
689 if( m_previewPad->GetDrillSizeX() == 0 )
690 m_board->GetDesignSettings().SetDefaultMasterPad();
691
692 break;
693
695 m_previewPad->SetLayerSet( PAD::SMDMask() );
696 m_previewPad->SetAttribute( PAD_ATTRIB::SMD );
697 break;
698 }
699 }
700 }
701
703
704 m_padNetSelector->SetSelectedNetcode( m_previewPad->GetNetCode() );
705
706 // Display current pad parameters units:
707 m_posX.ChangeValue( absPos.x );
708 m_posY.ChangeValue( absPos.y );
709
710 m_holeX.ChangeValue( m_previewPad->GetDrillSize().x );
711 m_holeY.ChangeValue( m_previewPad->GetDrillSize().y );
712
713 // TODO(JE) padstacks -- does this need to be saved/restored every time the layer changes?
714 // Store the initial thermal spoke angle to restore it, because some initializations
715 // can change this value (mainly after m_PadShapeSelector initializations)
716 EDA_ANGLE spokeInitialAngle = m_previewPad->GetThermalSpokeAngle();
717
719
720 m_padToDieOpt->SetValue( m_previewPad->GetPadToDieLength() != 0 );
721 m_padToDie.ChangeValue( m_previewPad->GetPadToDieLength() );
722
723 m_padToDieDelayOpt->SetValue( m_previewPad->GetPadToDieDelay() != 0 );
724 m_padToDieDelay.ChangeValue( m_previewPad->GetPadToDieDelay() );
725
726 if( m_previewPad->GetLocalClearance().has_value() )
727 m_clearance.ChangeValue( m_previewPad->GetLocalClearance().value() );
728 else
729 m_clearance.ChangeValue( wxEmptyString );
730
731 if( m_previewPad->GetLocalSolderMaskMargin().has_value() )
732 m_maskMargin.ChangeValue( m_previewPad->GetLocalSolderMaskMargin().value() );
733 else
734 m_maskMargin.ChangeValue( wxEmptyString );
735
736 if( m_previewPad->GetLocalSolderPasteMargin().has_value() )
737 m_pasteMargin.ChangeValue( m_previewPad->GetLocalSolderPasteMargin().value() );
738 else
739 m_pasteMargin.ChangeValue( wxEmptyString );
740
741 if( m_previewPad->GetLocalSolderPasteMarginRatio().has_value() )
742 m_pasteMarginRatio.ChangeDoubleValue( m_previewPad->GetLocalSolderPasteMarginRatio().value() * 100.0 );
743 else
744 m_pasteMarginRatio.ChangeValue( wxEmptyString );
745
746 if( m_previewPad->GetLocalThermalSpokeWidthOverride().has_value() )
747 m_spokeWidth.ChangeValue( m_previewPad->GetLocalThermalSpokeWidthOverride().value() );
748 else
749 m_spokeWidth.SetNull();
750
751 if( m_previewPad->GetLocalThermalGapOverride().has_value() )
752 m_thermalGap.ChangeValue( m_previewPad->GetLocalThermalGapOverride().value() );
753 else
754 m_thermalGap.SetNull();
755
756 m_spokeAngle.ChangeAngleValue( m_previewPad->GetThermalSpokeAngle() );
757 m_pad_orientation.ChangeAngleValue( m_previewPad->GetOrientation() );
758
759 m_cbTeardrops->SetValue( m_previewPad->GetTeardropParams().m_Enabled );
760 m_cbTeardropsUseNextTrack->SetValue( m_previewPad->GetTeardropParams().m_AllowUseTwoTracks );
761 m_cbPreferZoneConnection->SetValue( !m_previewPad->GetTeardropParams().m_TdOnPadsInZones );
762 m_teardropMaxLenSetting.SetValue( m_previewPad->GetTeardropParams().m_TdMaxLen );
763 m_teardropMaxHeightSetting.SetValue( m_previewPad->GetTeardropParams().m_TdMaxWidth );
764 m_spTeardropLenPercent->SetValue( m_previewPad->GetTeardropParams().m_BestLengthRatio *100 );
765 m_spTeardropSizePercent->SetValue( m_previewPad->GetTeardropParams().m_BestWidthRatio *100 );
766 m_spTeardropHDPercent->SetValue( m_previewPad->GetTeardropParams().m_WidthtoSizeFilterRatio*100 );
767 m_curvedEdges->SetValue( m_previewPad->GetTeardropParams().m_CurvedEdges );
768
769 switch( m_previewPad->GetLocalZoneConnection() )
770 {
771 default:
772 case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
773 case ZONE_CONNECTION::FULL: m_ZoneConnectionChoice->SetSelection( 1 ); break;
774 case ZONE_CONNECTION::THERMAL: m_ZoneConnectionChoice->SetSelection( 2 ); break;
775 case ZONE_CONNECTION::NONE: m_ZoneConnectionChoice->SetSelection( 3 ); break;
776 }
777
778 if( m_previewPad->GetCustomShapeInZoneOpt() == PADSTACK::CUSTOM_SHAPE_ZONE_MODE::CONVEXHULL )
779 m_ZoneCustomPadShape->SetSelection( 1 );
780 else
781 m_ZoneCustomPadShape->SetSelection( 0 );
782
783 // Type of pad selection
784 bool aperture =
785 m_previewPad->GetAttribute() == PAD_ATTRIB::SMD && m_previewPad->IsAperturePad();
786
787 if( aperture )
788 {
789 m_padType->SetSelection( APERTURE_DLG_TYPE );
790 }
791 else
792 {
793 switch( m_previewPad->GetAttribute() )
794 {
795 case PAD_ATTRIB::PTH: m_padType->SetSelection( PTH_DLG_TYPE ); break;
796 case PAD_ATTRIB::SMD: m_padType->SetSelection( SMD_DLG_TYPE ); break;
797 case PAD_ATTRIB::CONN: m_padType->SetSelection( CONN_DLG_TYPE ); break;
798 case PAD_ATTRIB::NPTH: m_padType->SetSelection( NPTH_DLG_TYPE ); break;
799 }
800 }
801
802 switch( m_previewPad->GetProperty() )
803 {
804 case PAD_PROP::NONE: m_choiceFabProperty->SetSelection( 0 ); break;
805 case PAD_PROP::BGA: m_choiceFabProperty->SetSelection( 1 ); break;
806 case PAD_PROP::FIDUCIAL_LOCAL: m_choiceFabProperty->SetSelection( 2 ); break;
807 case PAD_PROP::FIDUCIAL_GLBL: m_choiceFabProperty->SetSelection( 3 ); break;
808 case PAD_PROP::TESTPOINT: m_choiceFabProperty->SetSelection( 4 ); break;
809 case PAD_PROP::HEATSINK: m_choiceFabProperty->SetSelection( 5 ); break;
810 case PAD_PROP::MECHANICAL: m_choiceFabProperty->SetSelection( 6 ); break;
811 case PAD_PROP::CASTELLATED: m_choiceFabProperty->SetSelection( 7 ); break;
812 case PAD_PROP::PRESSFIT: m_choiceFabProperty->SetSelection( 8 ); break;
813 }
814
815 if( m_previewPad->GetDrillShape() != PAD_DRILL_SHAPE::OBLONG )
816 m_holeShapeCtrl->SetSelection( 0 );
817 else
818 m_holeShapeCtrl->SetSelection( 1 );
819
820 updatePadLayersList( m_previewPad->GetLayerSet(), m_previewPad->GetRemoveUnconnected(),
821 m_previewPad->GetKeepTopBottom() );
822
823 // Update some dialog widgets state (Enable/disable options):
824 wxCommandEvent cmd_event;
825 OnPadShapeSelection( cmd_event );
826 OnOffsetCheckbox( cmd_event );
827
828 // Restore thermal spoke angle to its initial value, because it can be modified
829 // by the call to OnPadShapeSelection()
830 m_previewPad->SetThermalSpokeAngle( spokeInitialAngle );
831 m_spokeAngle.SetAngleValue( m_previewPad->GetThermalSpokeAngle() );
832}
833
834
836{
837 m_primitives = m_previewPad->GetPrimitives( m_editLayer );
838
839 m_sizeX.ChangeValue( m_previewPad->GetSize( m_editLayer ).x );
840 m_sizeY.ChangeValue( m_previewPad->GetSize( m_editLayer ).y );
841
842 m_offsetShapeOpt->SetValue( m_previewPad->GetOffset( m_editLayer ) != VECTOR2I() );
843 m_offsetX.ChangeValue( m_previewPad->GetOffset( m_editLayer ).x );
844 m_offsetY.ChangeValue( m_previewPad->GetOffset( m_editLayer ).y );
845
846 if( m_previewPad->GetDelta( m_editLayer ).x )
847 {
848 m_trapDelta.ChangeValue( m_previewPad->GetDelta( m_editLayer ).x );
849 m_trapAxisCtrl->SetSelection( 0 );
850 }
851 else
852 {
853 m_trapDelta.ChangeValue( m_previewPad->GetDelta( m_editLayer ).y );
854 m_trapAxisCtrl->SetSelection( 1 );
855 }
856
857 switch( m_previewPad->GetShape( m_editLayer ) )
858 {
859 default:
860 case PAD_SHAPE::CIRCLE: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_CIRCLE ); break;
861 case PAD_SHAPE::OVAL: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_OVAL ); break;
862 case PAD_SHAPE::RECTANGLE: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_RECT ); break;
865
867 if( m_previewPad->GetRoundRectRadiusRatio( m_editLayer ) > 0.0 )
869 else
871 break;
872
874 if( m_previewPad->GetAnchorPadShape( m_editLayer ) == PAD_SHAPE::RECTANGLE )
876 else
878 break;
879 }
880
881 int chamferPositions = m_previewPad->GetChamferPositions( m_editLayer );
882
883 m_cbTopLeft->SetValue( chamferPositions & RECT_CHAMFER_TOP_LEFT );
884 m_cbTopLeft1->SetValue( chamferPositions & RECT_CHAMFER_TOP_LEFT );
885 m_cbTopRight->SetValue( chamferPositions & RECT_CHAMFER_TOP_RIGHT );
886 m_cbTopRight1->SetValue( chamferPositions & RECT_CHAMFER_TOP_RIGHT );
887 m_cbBottomLeft->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_LEFT );
888 m_cbBottomLeft1->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_LEFT );
889 m_cbBottomRight->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_RIGHT );
890 m_cbBottomRight1->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_RIGHT );
891
893}
894
895
897{
898 // NOTE: synchronize changes here with DIALOG_TRACK_VIA_PROPERTIES::afterPadstackModeChanged
899
900 wxCHECK_MSG( m_board, /* void */, "Expected valid board in afterPadstackModeChanged" );
901 m_cbEditLayer->Clear();
902
903 switch( m_previewPad->Padstack().Mode() )
904 {
906 m_cbPadstackMode->SetSelection( 0 );
907 m_cbEditLayer->Append( m_board->GetLayerName( F_Cu ) );
908 m_cbEditLayer->Disable();
910 m_editLayerCtrlMap = { { 0, F_Cu } };
911 break;
912
914 {
915 m_cbPadstackMode->SetSelection( 1 );
916 m_cbEditLayer->Enable();
917
918 std::vector choices = {
919 m_board->GetLayerName( F_Cu ),
920 _( "Inner Layers" ),
921 m_board->GetLayerName( B_Cu )
922 };
923
924 m_cbEditLayer->Append( choices );
925
927 { 0, F_Cu },
929 { 2, B_Cu }
930 };
931
932 if( m_editLayer != F_Cu && m_editLayer != B_Cu )
934
935 break;
936 }
937
939 {
940 m_cbPadstackMode->SetSelection( 2 );
941 m_cbEditLayer->Enable();
942 LSET layers = LSET::AllCuMask() & m_board->GetEnabledLayers();
943
944 for( PCB_LAYER_ID layer : layers.UIOrder() )
945 {
946 int idx = m_cbEditLayer->Append( m_board->GetLayerName( layer ) );
947 m_editLayerCtrlMap[idx] = layer;
948 }
949
950 break;
951 }
952 }
953
954 for( const auto& [idx, layer] : m_editLayerCtrlMap )
955 {
956 if( layer == m_editLayer )
957 {
958 m_cbEditLayer->SetSelection( idx );
959 break;
960 }
961 }
962}
963
964
965void DIALOG_PAD_PROPERTIES::OnResize( wxSizeEvent& event )
966{
967 redraw();
968 event.Skip();
969}
970
971
972void DIALOG_PAD_PROPERTIES::onChangePadMode( wxCommandEvent& event )
973{
975
976 KIGFX::VIEW* view = m_padPreviewGAL->GetView();
977
978 // fix the pad render mode (filled/not filled)
979 auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
980
981 settings->m_ForcePadSketchModeOn = m_cbShowPadOutline->IsChecked();
982 settings->SetHighContrast( false );
983 settings->m_ContrastModeDisplay = HIGH_CONTRAST_MODE::NORMAL;
984
985 redraw();
986}
987
988
990{
991 switch( m_PadShapeSelector->GetSelection() )
992 {
996 m_shapePropsBook->SetSelection( 0 );
997 break;
998
1000 m_shapePropsBook->SetSelection( 1 );
1001 break;
1002
1004 {
1005 m_shapePropsBook->SetSelection( 2 );
1006
1007 // Reasonable defaults
1008 if( m_previewPad->GetRoundRectRadiusRatio( m_editLayer ) == 0.0 )
1009 {
1010 const double ipcRadiusRatio =
1012 m_cornerRatio.ChangeDoubleValue( ipcRadiusRatio * 100 );
1013 }
1014
1015 break;
1016 }
1017
1019 m_shapePropsBook->SetSelection( 3 );
1020
1021 // Reasonable default
1022 if( m_previewPad->GetChamferRectRatio( m_editLayer ) == 0.0 )
1023 m_previewPad->SetChamferRectRatio( m_editLayer, 0.2 );
1024
1025 // Ensure the displayed value is up to date:
1026 m_chamferRatio.ChangeDoubleValue( m_previewPad->GetChamferRectRatio( m_editLayer ) * 100.0 );
1027
1028 // A reasonable default is one corner chamfered (usual for some SMD pads).
1029 if( !m_cbTopLeft->GetValue() && !m_cbTopRight->GetValue()
1030 && !m_cbBottomLeft->GetValue() && !m_cbBottomRight->GetValue() )
1031 {
1032 m_cbTopLeft->SetValue( true );
1033 m_cbTopRight->SetValue( false );
1034 m_cbBottomLeft->SetValue( false );
1035 m_cbBottomRight->SetValue( false );
1036 }
1037
1038 break;
1039
1041 m_shapePropsBook->SetSelection( 4 );
1042
1043 // Reasonable defaults
1044 if( m_previewPad->GetRoundRectRadiusRatio( m_editLayer ) == 0.0
1045 && m_previewPad->GetChamferRectRatio( m_editLayer ) == 0.0 )
1046 {
1047 const double ipcRadiusRatio =
1049 m_previewPad->SetRoundRectRadiusRatio( m_editLayer, ipcRadiusRatio );
1050 m_previewPad->SetChamferRectRatio( m_editLayer, 0.2 );
1051 }
1052
1053 // Ensure the displayed values are up to date:
1054 m_mixedChamferRatio.ChangeDoubleValue( m_previewPad->GetChamferRectRatio( m_editLayer ) * 100.0 );
1055 m_mixedCornerRatio.ChangeDoubleValue( m_previewPad->GetRoundRectRadiusRatio( m_editLayer ) * 100.0 );
1056 break;
1057
1058 case CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR: // PAD_SHAPE::CUSTOM, circular anchor
1059 case CHOICE_SHAPE_CUSTOM_RECT_ANCHOR: // PAD_SHAPE::CUSTOM, rect anchor
1060 m_shapePropsBook->SetSelection( 0 );
1061 break;
1062 }
1063
1064 // Note: must do this before enabling/disabling m_sizeY as we're using that as a flag to see
1065 // what the last shape was.
1066 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CIRCLE )
1067 {
1068 if( m_sizeYCtrl->IsEnabled() && m_spokeAngle.GetAngleValue() == ANGLE_90 )
1069 m_spokeAngle.SetAngleValue( ANGLE_45 );
1070 }
1071 else
1072 {
1073 if( !m_sizeYCtrl->IsEnabled() && m_spokeAngle.GetAngleValue() == ANGLE_45 )
1074 m_spokeAngle.SetAngleValue( ANGLE_90 );
1075 }
1076
1077 // Readjust props book size
1078 wxSize size = m_shapePropsBook->GetSize();
1079 size.y = m_shapePropsBook->GetPage( m_shapePropsBook->GetSelection() )->GetBestSize().y;
1080 m_shapePropsBook->SetMaxSize( size );
1081
1082 m_sizeY.Enable( m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CIRCLE
1084
1085 m_offsetShapeOpt->Enable( m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CIRCLE );
1086
1087 if( !m_offsetShapeOpt->IsEnabled() )
1088 m_offsetShapeOpt->SetValue( false );
1089
1090 // Show/hide controls depending on m_offsetShapeOpt being enabled
1091 m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
1092 m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
1093
1096
1097 for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
1098 m_notebook->GetPage( i )->Layout();
1099
1100 // Resize the dialog if its height is too small to show all widgets:
1101 if( m_MainSizer->GetSize().y < m_MainSizer->GetMinSize().y )
1102 m_MainSizer->SetSizeHints( this );
1103
1105 redraw();
1106
1107 if( m_initialized )
1108 OnModify();
1109}
1110
1111
1113{
1116 redraw();
1117
1118 if( m_initialized )
1119 OnModify();
1120}
1121
1122
1123void DIALOG_PAD_PROPERTIES::PadOrientEvent( wxCommandEvent& event )
1124{
1126 redraw();
1127
1128 if( m_initialized )
1129 OnModify();
1130}
1131
1132
1134{
1135 m_rbCopperLayersSel->Clear();
1136
1137 switch( m_padType->GetSelection() )
1138 {
1139 case PTH_DLG_TYPE:
1140 m_rbCopperLayersSel->Append( _( "All copper layers" ) );
1141 m_rbCopperLayersSel->Append( wxString::Format( _( "%s, %s and connected layers" ),
1142 m_board->GetLayerName( F_Cu ),
1143 m_board->GetLayerName( B_Cu ) ) );
1144 m_rbCopperLayersSel->Append( _( "Connected layers only" ) );
1145 m_rbCopperLayersSel->Append( _( "None" ) );
1146 break;
1147
1148 case NPTH_DLG_TYPE:
1149 m_rbCopperLayersSel->Append( wxString::Format( _( "%s and %s" ),
1150 m_board->GetLayerName( F_Cu ),
1151 m_board->GetLayerName( B_Cu ) ) );
1152 m_rbCopperLayersSel->Append( m_board->GetLayerName( F_Cu ) );
1153 m_rbCopperLayersSel->Append( m_board->GetLayerName( B_Cu ) );
1154 m_rbCopperLayersSel->Append( _( "None" ) );
1155 break;
1156
1157 case SMD_DLG_TYPE:
1158 case CONN_DLG_TYPE:
1159 m_rbCopperLayersSel->Append( m_board->GetLayerName( F_Cu ) );
1160 m_rbCopperLayersSel->Append( m_board->GetLayerName( B_Cu ) );
1161 break;
1162
1163 case APERTURE_DLG_TYPE:
1164 m_rbCopperLayersSel->Append( _( "None" ) );
1165 break;
1166 }
1167}
1168
1169
1170void DIALOG_PAD_PROPERTIES::PadTypeSelected( wxCommandEvent& event )
1171{
1172 bool hasHole = true;
1173 bool hasConnection = true;
1174
1175 switch( m_padType->GetSelection() )
1176 {
1177 case PTH_DLG_TYPE: hasHole = true; hasConnection = true; break;
1178 case SMD_DLG_TYPE: hasHole = false; hasConnection = true; break;
1179 case CONN_DLG_TYPE: hasHole = false; hasConnection = true; break;
1180 case NPTH_DLG_TYPE: hasHole = true; hasConnection = false; break;
1181 case APERTURE_DLG_TYPE: hasHole = false; hasConnection = false; break;
1182 }
1183
1184 // Update Layers dropdown list and selects the "best" layer set for the new pad type:
1185 updatePadLayersList( {}, m_previewPad->GetRemoveUnconnected(),
1186 m_previewPad->GetKeepTopBottom() );
1187
1188 m_gbSizerHole->Show( hasHole );
1189 m_staticline71->Show( hasHole );
1190
1191 if( !hasHole )
1192 {
1193 m_holeX.ChangeValue( 0 );
1194 m_holeY.ChangeValue( 0 );
1195 }
1196 else if( m_holeX.GetValue() == 0 )
1197 {
1198 if( m_currentPad )
1199 {
1200 m_holeX.ChangeValue( m_currentPad->GetDrillSize().x );
1201 m_holeY.ChangeValue( m_currentPad->GetDrillSize().y );
1202 }
1203 else
1204 {
1205 m_holeX.ChangeValue( pcbIUScale.mmToIU( DEFAULT_PAD_DRILL_DIAMETER_MM ) );
1206 }
1207 }
1208
1209 if( !hasConnection )
1210 {
1211 m_padNumCtrl->ChangeValue( wxEmptyString );
1212 m_padNetSelector->SetSelectedNetcode( 0 );
1213 m_padToDieOpt->SetValue( false );
1214 m_padToDieDelayOpt->SetValue( false );
1215 }
1216 else if( m_padNumCtrl->GetValue().IsEmpty() && m_currentPad )
1217 {
1218 m_padNumCtrl->ChangeValue( m_currentPad->GetNumber() );
1219 m_padNetSelector->SetSelectedNetcode( m_currentPad->GetNetCode() );
1220 }
1221
1223
1224 // For now, padstack controls only enabled for PTH pads
1225 bool enablePadstack = m_padType->GetSelection() == PTH_DLG_TYPE;
1226 m_padstackControls->Show( enablePadstack );
1227
1228 if( !enablePadstack )
1229 {
1230 m_editLayer = F_Cu;
1232 }
1233
1234 // Layout adjustment is needed if the hole details got shown/hidden
1235 m_LeftBoxSizer->Layout();
1236 redraw();
1237
1238 if( m_initialized )
1239 OnModify();
1240}
1241
1242
1243void DIALOG_PAD_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
1244{
1245 bool hasHole = true;
1246 bool hasConnection = true;
1247
1248 switch( m_padType->GetSelection() )
1249 {
1250 case PTH_DLG_TYPE: /* PTH */ hasHole = true; hasConnection = true; break;
1251 case SMD_DLG_TYPE: /* SMD */ hasHole = false; hasConnection = true; break;
1252 case CONN_DLG_TYPE: /* CONN */ hasHole = false; hasConnection = true; break;
1253 case NPTH_DLG_TYPE: /* NPTH */ hasHole = true; hasConnection = false; break;
1254 case APERTURE_DLG_TYPE: /* Aperture */ hasHole = false; hasConnection = false; break;
1255 }
1256
1257 // Enable/disable hole controls
1258 m_holeShapeLabel->Enable( hasHole );
1259 m_holeShapeCtrl->Enable( hasHole );
1260 m_holeX.Enable( hasHole );
1261 m_holeY.Enable( hasHole && m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_OVAL );
1262
1263 // Enable/disable number and net
1264 m_padNumLabel->Enable( hasConnection );
1265 m_padNumCtrl->Enable( hasConnection );
1266
1267 if( m_padNetLabel->IsShown() )
1268 {
1269 m_padNetLabel->Enable( hasConnection && m_canEditNetName && m_currentPad );
1270 m_padNetSelector->Enable( hasConnection && m_canEditNetName && m_currentPad );
1271 }
1272
1273 // Enable/disable pad length-to-die
1274 m_padToDieOpt->Enable( hasConnection );
1275 m_padToDieDelayOpt->Enable( hasConnection );
1276
1277 if( !m_padToDieOpt->IsEnabled() )
1278 m_padToDieOpt->SetValue( false );
1279
1280 if( !m_padToDieDelayOpt->IsEnabled() )
1281 m_padToDieDelayOpt->SetValue( false );
1282
1283 // We can show/hide this here because it doesn't require the layout to be refreshed.
1284 // All the others have to be done in their event handlers because doing a layout here
1285 // causes infinite looping on MSW.
1286 m_padToDie.Show( m_padToDieOpt->GetValue() );
1287 m_padToDieDelay.Show( m_padToDieDelayOpt->GetValue() );
1288
1289 // Enable/disable Copper Layers control
1290 m_rbCopperLayersSel->Enable( m_padType->GetSelection() != APERTURE_DLG_TYPE );
1291
1292 LSET cu_set = m_previewPad->GetLayerSet() & LSET::AllCuMask();
1293
1294 switch( m_padType->GetSelection() )
1295 {
1296 case PTH_DLG_TYPE:
1297 if( !cu_set.any() )
1298 m_stackupImagesBook->SetSelection( 3 );
1299 else if( !m_previewPad->GetRemoveUnconnected() )
1300 m_stackupImagesBook->SetSelection( 0 );
1301 else if( m_previewPad->GetKeepTopBottom() )
1302 m_stackupImagesBook->SetSelection( 1 );
1303 else
1304 m_stackupImagesBook->SetSelection( 2 );
1305
1306 break;
1307
1308 case NPTH_DLG_TYPE:
1309 if( cu_set.test( F_Cu ) && cu_set.test( B_Cu ) )
1310 m_stackupImagesBook->SetSelection( 4 );
1311 else if( cu_set.test( F_Cu ) )
1312 m_stackupImagesBook->SetSelection( 5 );
1313 else if( cu_set.test( B_Cu ) )
1314 m_stackupImagesBook->SetSelection( 6 );
1315 else
1316 m_stackupImagesBook->SetSelection( 7 );
1317
1318 break;
1319
1320 case SMD_DLG_TYPE:
1321 case CONN_DLG_TYPE:
1322 case APERTURE_DLG_TYPE:
1323 m_stackupImagesBook->ChangeSelection( 3 );
1324 break;
1325 }
1326
1327 m_legacyTeardropsWarning->Show( m_board->LegacyTeardrops() );
1328}
1329
1330
1332{
1333 event.Enable( !m_board->LegacyTeardrops() );
1334}
1335
1336
1338{
1339 bool isOnCopperLayer = ( m_previewPad->GetLayerSet() & LSET::AllCuMask() ).any();
1340 m_nonCopperWarningBook->ChangeSelection( isOnCopperLayer ? 0 : 1 );
1341}
1342
1343
1344void DIALOG_PAD_PROPERTIES::updatePadLayersList( LSET layer_mask, bool remove_unconnected,
1345 bool keep_top_bottom )
1346{
1348
1349 switch( m_padType->GetSelection() )
1350 {
1351 case PTH_DLG_TYPE:
1352 if( !layer_mask.any() )
1353 layer_mask = PAD::PTHMask();
1354
1355 if( !( layer_mask & LSET::AllCuMask() ).any() )
1356 m_rbCopperLayersSel->SetSelection( 3 );
1357 else if( !remove_unconnected )
1358 m_rbCopperLayersSel->SetSelection( 0 );
1359 else if( keep_top_bottom )
1360 m_rbCopperLayersSel->SetSelection( 1 );
1361 else
1362 m_rbCopperLayersSel->SetSelection( 2 );
1363
1364 break;
1365
1366 case SMD_DLG_TYPE:
1367 if( !layer_mask.any() )
1368 layer_mask = PAD::SMDMask();
1369
1370 if( layer_mask.test( F_Cu ) )
1371 m_rbCopperLayersSel->SetSelection( 0 );
1372 else
1373 m_rbCopperLayersSel->SetSelection( 1 );
1374
1375 break;
1376
1377 case CONN_DLG_TYPE:
1378 if( !layer_mask.any() )
1379 layer_mask = PAD::ConnSMDMask();
1380
1381 if( layer_mask.test( F_Cu ) )
1382 m_rbCopperLayersSel->SetSelection( 0 );
1383 else
1384 m_rbCopperLayersSel->SetSelection( 1 );
1385
1386 break;
1387
1388 case NPTH_DLG_TYPE:
1389 if( !layer_mask.any() )
1390 layer_mask = PAD::UnplatedHoleMask();
1391
1392 if( layer_mask.test( F_Cu ) && layer_mask.test( B_Cu ) )
1393 m_rbCopperLayersSel->SetSelection( 0 );
1394 else if( layer_mask.test( F_Cu ) )
1395 m_rbCopperLayersSel->SetSelection( 1 );
1396 else if( layer_mask.test( B_Cu ) )
1397 m_rbCopperLayersSel->SetSelection( 2 );
1398 else
1399 m_rbCopperLayersSel->SetSelection( 3 );
1400
1401 break;
1402
1403 case APERTURE_DLG_TYPE:
1404 if( !layer_mask.any() )
1405 layer_mask = PAD::ApertureMask();
1406
1407 m_rbCopperLayersSel->SetSelection( 0 );
1408 break;
1409 }
1410
1411 m_layerFrontAdhesive->SetValue( layer_mask[F_Adhes] );
1412 m_layerBackAdhesive->SetValue( layer_mask[B_Adhes] );
1413
1414 m_layerFrontPaste->SetValue( layer_mask[F_Paste] );
1415 m_layerBackPaste->SetValue( layer_mask[B_Paste] );
1416
1417 m_layerFrontSilk->SetValue( layer_mask[F_SilkS] );
1418 m_layerBackSilk->SetValue( layer_mask[B_SilkS] );
1419
1420 m_layerFrontMask->SetValue( layer_mask[F_Mask] );
1421 m_layerBackMask->SetValue( layer_mask[B_Mask] );
1422
1423 m_layerECO1->SetValue( layer_mask[Eco1_User] );
1424 m_layerECO2->SetValue( layer_mask[Eco2_User] );
1425
1426 m_layerUserDwgs->SetValue( layer_mask[Dwgs_User] );
1427}
1428
1429
1431{
1432 bool retVal = DIALOG_SHIM::Show( aShow );
1433
1434 if( aShow )
1435 {
1436 // It *should* work to set the stackup bitmap in the constructor, but it doesn't.
1437 // wxWidgets needs to have these set when the panel is visible for some reason.
1438 // https://gitlab.com/kicad/code/kicad/-/issues/5534
1446
1447 Layout();
1448 }
1449
1450 return retVal;
1451}
1452
1453
1454void DIALOG_PAD_PROPERTIES::OnSetCopperLayers( wxCommandEvent& event )
1455{
1457 redraw();
1458
1459 if( m_initialized )
1460 OnModify();
1461}
1462
1463
1464void DIALOG_PAD_PROPERTIES::OnSetLayers( wxCommandEvent& event )
1465{
1467 redraw();
1468
1469 if( m_initialized )
1470 OnModify();
1471}
1472
1473
1475{
1477
1478 wxArrayString error_msgs;
1479 wxArrayString warning_msgs;
1480
1481 m_previewPad->CheckPad( m_parentFrame, true,
1482 [&]( int errorCode, const wxString& msg )
1483 {
1484 if( errorCode == DRCE_PADSTACK_INVALID )
1485 error_msgs.Add( _( "Error: " ) + msg );
1486 else if( errorCode == DRCE_PADSTACK )
1487 warning_msgs.Add( _( "Warning: " ) + msg );
1488 else if( errorCode == DRCE_PAD_TH_WITH_NO_HOLE )
1489 error_msgs.Add( _( "Error: Through hole pad has no hole." ) );
1490 } );
1491
1492 if( error_msgs.GetCount() || warning_msgs.GetCount() )
1493 {
1494 wxString title = error_msgs.GetCount() ? _( "Pad Properties Errors" )
1495 : _( "Pad Properties Warnings" );
1496 HTML_MESSAGE_BOX dlg( this, title );
1497
1498 wxArrayString msgs = error_msgs;
1499
1500 for( const wxString& msg : warning_msgs )
1501 msgs.Add( msg );
1502
1503 dlg.ListSet( msgs );
1504
1505 dlg.ShowModal();
1506 }
1507
1508 return error_msgs.GetCount() == 0;
1509}
1510
1511
1513{
1514 if( !m_initialized )
1515 return;
1516
1517 KIGFX::VIEW* view = m_padPreviewGAL->GetView();
1518 KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( view->GetPainter() );
1519 KIGFX::PCB_RENDER_SETTINGS* settings = painter->GetSettings();
1520
1521 m_padPreviewGAL->StopDrawing();
1522
1523 // The layer used to place primitive items selected when editing custom pad shapes
1524 // we use here a layer never used in a pad:
1525 #define SELECTED_ITEMS_LAYER Dwgs_User
1526
1527 view->ClearTopLayers();
1529 view->SetTopLayer( m_editLayer );
1531
1532 static const std::vector<int> topLayers = {
1537 };
1538
1539 for( int layer : topLayers )
1540 view->SetTopLayer( layer );
1541
1542 m_axisOrigin->SetPosition( m_previewPad->GetPosition() );
1543
1544 view->Update( m_previewPad );
1545
1546 // delete previous items if highlight list
1547 while( m_highlight.size() )
1548 {
1549 delete m_highlight.back(); // the dtor also removes item from view
1550 m_highlight.pop_back();
1551 }
1552
1553 BOX2I bbox = m_previewPad->ViewBBox();
1554
1555 if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
1556 {
1557 // The origin always goes in the middle of the canvas; we want offsetting the pad
1558 // shape to move the pad, not the hole
1559 bbox.Move( -m_previewPad->GetPosition() );
1560 int maxXExtent = std::max( abs( bbox.GetLeft() ), abs( bbox.GetRight() ) );
1561 int maxYExtent = std::max( abs( bbox.GetTop() ), abs( bbox.GetBottom() ) );
1562
1563 // Don't blow up the GAL on too-large numbers
1564 if( maxXExtent > INT_MAX / 4 )
1565 maxXExtent = INT_MAX / 4;
1566
1567 if( maxYExtent > INT_MAX / 4 )
1568 maxYExtent = INT_MAX / 4;
1569
1570 BOX2D viewBox( m_previewPad->GetPosition(), {0, 0} );
1571 BOX2D canvasBox( m_previewPad->GetPosition(), {0, 0} );
1572 viewBox.Inflate( maxXExtent * 1.4, maxYExtent * 1.4 ); // add a margin
1573 canvasBox.Inflate( maxXExtent * 2.0, maxYExtent * 2.0 );
1574
1575 view->SetBoundary( canvasBox );
1576
1577 // Autozoom
1578 view->SetViewport( viewBox );
1579
1580 m_padPreviewGAL->StartDrawing();
1581 m_padPreviewGAL->Refresh();
1582 }
1583}
1584
1585
1587{
1588 if( !wxDialog::TransferDataToWindow() )
1589 return false;
1590
1591 if( !m_panelGeneral->TransferDataToWindow() )
1592 return false;
1593
1594 if( !m_localSettingsPanel->TransferDataToWindow() )
1595 return false;
1596
1597 return true;
1598}
1599
1600
1602{
1603 BOARD_COMMIT commit( m_parent );
1604
1605 if( !wxDialog::TransferDataFromWindow() )
1606 return false;
1607
1608 if( !m_panelGeneral->TransferDataFromWindow() )
1609 return false;
1610
1611 if( !m_localSettingsPanel->TransferDataFromWindow() )
1612 return false;
1613
1614 if( !padValuesOK() )
1615 return false;
1616
1618 return false;
1619
1620 m_padPreviewGAL->StopDrawing();
1621
1622 PAD_TOOL* padTool = m_parent->GetToolManager()->GetTool<PAD_TOOL>();
1623 padTool->SetLastPadNumber( m_masterPad->GetNumber() );
1624
1625 // m_masterPad is a pattern: ensure there is no net for this pad:
1627
1628 if( !m_currentPad ) // Set current Pad parameters
1629 return true;
1630
1631 commit.Modify( m_currentPad );
1632
1633 // Update values
1634
1635 // transferDataToPad only handles the current edit layer, so m_masterPad isn't accurate
1636 // TODO(JE) this could be cleaner
1637 m_currentPad->SetPadstack( m_previewPad->Padstack() );
1638
1639 m_currentPad->SetAttribute( m_masterPad->GetAttribute() );
1640 m_currentPad->SetFPRelativeOrientation( m_masterPad->GetOrientation() );
1641 m_currentPad->SetPadToDieLength( m_masterPad->GetPadToDieLength() );
1642 m_currentPad->SetPadToDieDelay( m_masterPad->GetPadToDieDelay() );
1643 m_currentPad->SetLayerSet( m_masterPad->GetLayerSet() );
1644 m_currentPad->SetNumber( m_masterPad->GetNumber() );
1645
1646 int padNetcode = NETINFO_LIST::UNCONNECTED;
1647
1648 // For PAD_ATTRIB::NPTH, ensure there is no net name selected
1649 if( m_masterPad->GetAttribute() != PAD_ATTRIB::NPTH )
1650 padNetcode = m_padNetSelector->GetSelectedNetcode();
1651
1652 m_currentPad->SetNetCode( padNetcode );
1653
1654 m_currentPad->GetTeardropParams() = m_masterPad->GetTeardropParams();
1655
1656 // Set the fabrication property:
1657 m_currentPad->SetProperty( getSelectedProperty() );
1658
1659 // define the way the clearance area is defined in zones
1660 m_currentPad->SetCustomShapeInZoneOpt( m_masterPad->GetCustomShapeInZoneOpt() );
1661
1662 if( m_currentPad->GetParentFootprint() && m_currentPad->GetParentFootprint()->IsFlipped() )
1663 {
1664 // flip pad (up/down) around its position
1665 m_currentPad->Flip( m_currentPad->GetPosition(), FLIP_DIRECTION::TOP_BOTTOM );
1666 }
1667
1668 m_currentPad->SetPosition( m_masterPad->GetPosition() );
1669
1670 m_parent->SetMsgPanel( m_currentPad );
1671
1672 // redraw the area where the pad was
1673 m_parent->GetCanvas()->Refresh();
1674
1675 commit.Push( _( "Edit Pad Properties" ) );
1676
1677 return true;
1678}
1679
1680
1682{
1683 PAD_PROP prop = PAD_PROP::NONE;
1684
1685 switch( m_choiceFabProperty->GetSelection() )
1686 {
1687 case 0: prop = PAD_PROP::NONE; break;
1688 case 1: prop = PAD_PROP::BGA; break;
1689 case 2: prop = PAD_PROP::FIDUCIAL_LOCAL; break;
1690 case 3: prop = PAD_PROP::FIDUCIAL_GLBL; break;
1691 case 4: prop = PAD_PROP::TESTPOINT; break;
1692 case 5: prop = PAD_PROP::HEATSINK; break;
1693 case 6: prop = PAD_PROP::MECHANICAL; break;
1694 case 7: prop = PAD_PROP::CASTELLATED; break;
1695 case 8: prop = PAD_PROP::PRESSFIT; break;
1696 }
1697
1698 return prop;
1699}
1700
1701
1703{
1704 if( m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_CIRCLE )
1705 {
1706 m_holeXLabel->SetLabel( _( "Diameter:" ) );
1707 m_holeY.Show( false );
1708 }
1709 else
1710 {
1711 m_holeXLabel->SetLabel( _( "Hole size X:" ) );
1712 m_holeY.Show( true );
1713 }
1714
1715 m_holeXLabel->GetParent()->Layout();
1716}
1717
1718
1720{
1721 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CIRCLE
1723 {
1724 m_sizeXLabel->SetLabel( _( "Diameter:" ) );
1725 m_sizeY.Show( false );
1727 m_minTrackWidthHint->SetLabel( _( "d" ) );
1728 m_stLenPercentHint->SetLabel( _( "d" ) );
1729 m_stWidthPercentHint->SetLabel( _( "d" ) );
1730 }
1731 else
1732 {
1733 m_sizeXLabel->SetLabel( _( "Pad size X:" ) );
1734 m_sizeY.Show( true );
1736 m_minTrackWidthHint->SetLabel( _( "w" ) );
1737 m_stLenPercentHint->SetLabel( _( "w" ) );
1738 m_stWidthPercentHint->SetLabel( _( "w" ) );
1739 }
1740
1741 m_sizeXLabel->GetParent()->Layout();
1742 resetSize();
1743 Layout();
1744 m_MainSizer->Fit( this );
1745}
1746
1747
1749{
1750 if( !Validate() )
1751 return false;
1752
1753 if( !m_panelGeneral->Validate() )
1754 return false;
1755
1756 if( !m_localSettingsPanel->Validate() )
1757 return false;
1758
1759 if( !m_spokeWidth.Validate( 0, INT_MAX ) )
1760 return false;
1761
1762 switch( m_cbPadstackMode->GetSelection() )
1763 {
1764 default:
1765 case 0: aPad->Padstack().SetMode( PADSTACK::MODE::NORMAL ); break;
1766 case 1: aPad->Padstack().SetMode( PADSTACK::MODE::FRONT_INNER_BACK ); break;
1767 case 2: aPad->Padstack().SetMode( PADSTACK::MODE::CUSTOM ); break;
1768 }
1769
1770 aPad->SetAttribute( code_type[m_padType->GetSelection()] );
1771 aPad->SetShape( m_editLayer, code_shape[m_PadShapeSelector->GetSelection()] );
1772
1775 else
1777
1778 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::CUSTOM )
1780
1781 aPad->GetTeardropParams().m_Enabled = m_cbTeardrops->GetValue();
1788 aPad->GetTeardropParams().m_CurvedEdges = m_curvedEdges->GetValue();
1790
1791 // Read pad clearances values:
1792 if( m_clearance.IsNull() )
1793 aPad->SetLocalClearance( {} );
1794 else
1795 aPad->SetLocalClearance( m_clearance.GetIntValue() );
1796
1797 if( m_maskMargin.IsNull() )
1798 aPad->SetLocalSolderMaskMargin( {} );
1799 else
1800 aPad->SetLocalSolderMaskMargin( m_maskMargin.GetIntValue() );
1801
1802 if( m_pasteMargin.IsNull() )
1803 aPad->SetLocalSolderPasteMargin( {} );
1804 else
1805 aPad->SetLocalSolderPasteMargin( m_pasteMargin.GetIntValue() );
1806
1807 if( m_pasteMarginRatio.IsNull() )
1809 else
1810 aPad->SetLocalSolderPasteMarginRatio( m_pasteMarginRatio.GetDoubleValue() / 100.0 );
1811
1812 if( m_spokeWidth.IsNull() )
1814 else
1815 aPad->SetLocalThermalSpokeWidthOverride( m_spokeWidth.GetIntValue() );
1816
1817 if( m_thermalGap.IsNull() )
1818 aPad->SetLocalThermalGapOverride( {} );
1819 else
1820 aPad->SetLocalThermalGapOverride( m_thermalGap.GetIntValue() );
1821
1822 aPad->SetThermalSpokeAngle( m_spokeAngle.GetAngleValue() );
1823
1824 // And rotation
1825 aPad->SetOrientation( m_pad_orientation.GetAngleValue() );
1826
1827 switch( m_ZoneConnectionChoice->GetSelection() )
1828 {
1829 default:
1830 case 0: aPad->SetLocalZoneConnection( ZONE_CONNECTION::INHERITED ); break;
1831 case 1: aPad->SetLocalZoneConnection( ZONE_CONNECTION::FULL ); break;
1832 case 2: aPad->SetLocalZoneConnection( ZONE_CONNECTION::THERMAL ); break;
1833 case 3: aPad->SetLocalZoneConnection( ZONE_CONNECTION::NONE ); break;
1834 }
1835
1836 VECTOR2I pos( m_posX.GetIntValue(), m_posY.GetIntValue() );
1837
1838 if( FOOTPRINT* fp = aPad->GetParentFootprint() )
1839 {
1840 pos -= fp->GetPosition();
1841 RotatePoint( pos, -fp->GetOrientation() );
1842 }
1843
1844 aPad->SetPosition( pos );
1845
1846 if( m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_CIRCLE )
1847 {
1849 aPad->SetDrillSize( VECTOR2I( m_holeX.GetIntValue(), m_holeX.GetIntValue() ) );
1850 }
1851 else
1852 {
1854 aPad->SetDrillSize( VECTOR2I( m_holeX.GetIntValue(), m_holeY.GetIntValue() ) );
1855 }
1856
1857 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::CIRCLE )
1858 aPad->SetSize( m_editLayer, VECTOR2I( m_sizeX.GetIntValue(), m_sizeX.GetIntValue() ) );
1859 else
1860 aPad->SetSize( m_editLayer, VECTOR2I( m_sizeX.GetIntValue(), m_sizeY.GetIntValue() ) );
1861
1862 // For a trapezoid, test delta value (be sure delta is not too large for pad size)
1863 // remember DeltaSize.x is the Y size variation
1864 bool error = false;
1865 VECTOR2I delta( 0, 0 );
1866
1867 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::TRAPEZOID )
1868 {
1869 // For a trapezoid, only one of delta.x or delta.y is not 0, depending on axis.
1870 if( m_trapAxisCtrl->GetSelection() == 0 )
1871 delta.x = m_trapDelta.GetIntValue();
1872 else
1873 delta.y = m_trapDelta.GetIntValue();
1874
1875 if( delta.x < 0 && delta.x < -aPad->GetSize( m_editLayer ).y )
1876 {
1877 delta.x = -aPad->GetSize( m_editLayer ).y + 2;
1878 error = true;
1879 }
1880
1881 if( delta.x > 0 && delta.x > aPad->GetSize( m_editLayer ).y )
1882 {
1883 delta.x = aPad->GetSize( m_editLayer ).y - 2;
1884 error = true;
1885 }
1886
1887 if( delta.y < 0 && delta.y < -aPad->GetSize( m_editLayer ).x )
1888 {
1889 delta.y = -aPad->GetSize( m_editLayer ).x + 2;
1890 error = true;
1891 }
1892
1893 if( delta.y > 0 && delta.y > aPad->GetSize( m_editLayer ).x )
1894 {
1895 delta.y = aPad->GetSize( m_editLayer ).x - 2;
1896 error = true;
1897 }
1898 }
1899
1900 aPad->SetDelta( m_editLayer, delta );
1901
1902 if( m_offsetShapeOpt->GetValue() )
1903 aPad->SetOffset( m_editLayer, VECTOR2I( m_offsetX.GetIntValue(), m_offsetY.GetIntValue() ) );
1904 else
1905 aPad->SetOffset( m_editLayer, VECTOR2I() );
1906
1907 // Read pad length die
1908 if( m_padToDieOpt->GetValue() )
1909 aPad->SetPadToDieLength( m_padToDie.GetIntValue() );
1910 else
1911 aPad->SetPadToDieLength( 0 );
1912
1913 if( m_padToDieDelayOpt->GetValue() )
1914 aPad->SetPadToDieDelay( m_padToDieDelay.GetIntValue() );
1915 else
1916 aPad->SetPadToDieDelay( 0 );
1917
1918 aPad->SetNumber( m_padNumCtrl->GetValue() );
1919 aPad->SetNetCode( m_padNetSelector->GetSelectedNetcode() );
1920
1921 int chamfers = 0;
1922
1923 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_RECT )
1924 {
1925 if( m_cbTopLeft->GetValue() )
1926 chamfers |= RECT_CHAMFER_TOP_LEFT;
1927
1928 if( m_cbTopRight->GetValue() )
1929 chamfers |= RECT_CHAMFER_TOP_RIGHT;
1930
1931 if( m_cbBottomLeft->GetValue() )
1932 chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1933
1934 if( m_cbBottomRight->GetValue() )
1935 chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1936 }
1937 else if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT )
1938 {
1939 if( m_cbTopLeft1->GetValue() )
1940 chamfers |= RECT_CHAMFER_TOP_LEFT;
1941
1942 if( m_cbTopRight1->GetValue() )
1943 chamfers |= RECT_CHAMFER_TOP_RIGHT;
1944
1945 if( m_cbBottomLeft1->GetValue() )
1946 chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1947
1948 if( m_cbBottomRight1->GetValue() )
1949 chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1950 }
1951
1952 aPad->SetChamferPositions( m_editLayer, chamfers );
1953
1954 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::CUSTOM )
1955 {
1956 // The pad custom has a "anchor pad" (a basic shape: round or rect pad)
1957 // that is the minimal area of this pad, and is useful to ensure a hole
1958 // diameter is acceptable, and is used in Gerber files as flashed area
1959 // reference
1961 aPad->SetSize( m_editLayer, VECTOR2I( m_sizeX.GetIntValue(), m_sizeX.GetIntValue() ) );
1962 }
1963
1964 // Define the way the clearance area is defined in zones. Since all non-custom pad
1965 // shapes are convex to begin with, this really only makes any difference for custom
1966 // pad shapes.
1967 aPad->SetCustomShapeInZoneOpt( m_ZoneCustomPadShape->GetSelection() == 0 ?
1970
1971 switch( aPad->GetAttribute() )
1972 {
1973 case PAD_ATTRIB::PTH:
1974 break;
1975
1976 case PAD_ATTRIB::CONN:
1977 case PAD_ATTRIB::SMD:
1978 // SMD and PAD_ATTRIB::CONN has no hole.
1979 // basically, SMD and PAD_ATTRIB::CONN are same type of pads
1980 // PAD_ATTRIB::CONN has just a default non technical layers that differs from SMD
1981 // and are intended to be used in virtual edge board connectors
1982 // However we can accept a non null offset,
1983 // mainly to allow complex pads build from a set of basic pad shapes
1984 aPad->SetDrillSize( VECTOR2I( 0, 0 ) );
1985 break;
1986
1987 case PAD_ATTRIB::NPTH:
1988 // Mechanical purpose only:
1989 // no net name, no pad name allowed
1990 aPad->SetNumber( wxEmptyString );
1992 break;
1993
1994 default:
1995 wxFAIL_MSG( wxT( "DIALOG_PAD_PROPERTIES::transferDataToPad: unknown pad type" ) );
1996 break;
1997 }
1998
1999 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::ROUNDRECT )
2000 {
2001 aPad->SetRoundRectRadiusRatio( m_editLayer, m_cornerRatio.GetDoubleValue() / 100.0 );
2002 }
2003 else if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::CHAMFERED_RECT )
2004 {
2006 {
2007 aPad->SetChamferRectRatio( m_editLayer, m_mixedChamferRatio.GetDoubleValue() / 100.0 );
2008 aPad->SetRoundRectRadiusRatio( m_editLayer, m_mixedCornerRatio.GetDoubleValue() / 100.0 );
2009 }
2010 else // Choice is CHOICE_SHAPE_CHAMFERED_RECT, no rounded corner
2011 {
2012 aPad->SetChamferRectRatio( m_editLayer, m_chamferRatio.GetDoubleValue() / 100.0 );
2014 }
2015 }
2016
2018
2019 LSET padLayerMask = LSET();
2020 int copperLayersChoice = m_rbCopperLayersSel->GetSelection();
2021
2023
2024 switch( m_padType->GetSelection() )
2025 {
2026 case PTH_DLG_TYPE:
2027 switch( copperLayersChoice )
2028 {
2029 case 0:
2030 // All copper layers
2031 padLayerMask |= LSET::AllCuMask();
2032 break;
2033
2034 case 1:
2035 // Front, back and connected
2036 padLayerMask |= LSET::AllCuMask();
2038 break;
2039
2040 case 2:
2041 // Connected only
2042 padLayerMask |= LSET::AllCuMask();
2044 break;
2045
2046 case 3:
2047 // No copper layers
2048 break;
2049 }
2050
2051 break;
2052
2053 case NPTH_DLG_TYPE:
2054 switch( copperLayersChoice )
2055 {
2056 case 0: padLayerMask.set( F_Cu ).set( B_Cu ); break;
2057 case 1: padLayerMask.set( F_Cu ); break;
2058 case 2: padLayerMask.set( B_Cu ); break;
2059 default: break;
2060 }
2061
2062 break;
2063
2064 case SMD_DLG_TYPE:
2065 case CONN_DLG_TYPE:
2066 switch( copperLayersChoice )
2067 {
2068 case 0: padLayerMask.set( F_Cu ); break;
2069 case 1: padLayerMask.set( B_Cu ); break;
2070 }
2071
2072 break;
2073
2074 case APERTURE_DLG_TYPE:
2075 // no copper layers
2076 break;
2077 }
2078
2079 if( m_layerFrontAdhesive->GetValue() )
2080 padLayerMask.set( F_Adhes );
2081
2082 if( m_layerBackAdhesive->GetValue() )
2083 padLayerMask.set( B_Adhes );
2084
2085 if( m_layerFrontPaste->GetValue() )
2086 padLayerMask.set( F_Paste );
2087
2088 if( m_layerBackPaste->GetValue() )
2089 padLayerMask.set( B_Paste );
2090
2091 if( m_layerFrontSilk->GetValue() )
2092 padLayerMask.set( F_SilkS );
2093
2094 if( m_layerBackSilk->GetValue() )
2095 padLayerMask.set( B_SilkS );
2096
2097 if( m_layerFrontMask->GetValue() )
2098 padLayerMask.set( F_Mask );
2099
2100 if( m_layerBackMask->GetValue() )
2101 padLayerMask.set( B_Mask );
2102
2103 if( m_layerECO1->GetValue() )
2104 padLayerMask.set( Eco1_User );
2105
2106 if( m_layerECO2->GetValue() )
2107 padLayerMask.set( Eco2_User );
2108
2109 if( m_layerUserDwgs->GetValue() )
2110 padLayerMask.set( Dwgs_User );
2111
2112 aPad->SetLayerSet( padLayerMask );
2113
2114 return !error;
2115}
2116
2117
2118void DIALOG_PAD_PROPERTIES::OnOffsetCheckbox( wxCommandEvent& event )
2119{
2120 if( m_offsetShapeOpt->GetValue() )
2121 {
2122 m_offsetX.SetValue( m_previewPad->GetOffset( m_editLayer ).x );
2123 m_offsetY.SetValue( m_previewPad->GetOffset( m_editLayer ).y );
2124 }
2125
2126 // Show/hide controls depending on m_offsetShapeOpt being enabled
2127 m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
2128 m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
2129
2130 for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
2131 m_notebook->GetPage( i )->Layout();
2132
2133 OnValuesChanged( event );
2134}
2135
2136
2138{
2139 if( m_padToDieOpt->GetValue() && m_currentPad )
2140 m_padToDie.SetValue( m_currentPad->GetPadToDieLength() );
2141
2142 OnValuesChanged( event );
2143}
2144
2145
2147{
2148 if( m_padToDieDelayOpt->GetValue() && m_currentPad )
2149 m_padToDieDelay.SetValue( m_currentPad->GetPadToDieDelay() );
2150
2151 OnValuesChanged( event );
2152}
2153
2154
2155void DIALOG_PAD_PROPERTIES::onModify( wxSpinDoubleEvent& aEvent )
2156{
2157 if( m_initialized )
2158 OnModify();
2159}
2160
2161
2162void DIALOG_PAD_PROPERTIES::onModify( wxCommandEvent& aEvent )
2163{
2164 if( m_initialized )
2165 OnModify();
2166}
2167
2168
2169void DIALOG_PAD_PROPERTIES::OnValuesChanged( wxCommandEvent& event )
2170{
2171 if( m_initialized )
2172 {
2174 return;
2175
2176 // If the pad size has changed, update the displayed values for rounded rect pads.
2179
2180 redraw();
2181 OnModify();
2182 }
2183}
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:112
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:110
@ teardrop_rect_sizes
@ pads_reset_unused
@ pads_remove_unused
@ pads_npth_bottom
@ pads_npth_top_bottom
@ pads_remove_unused_keep_bottom
#define DEFAULT_PAD_DRILL_DIAMETER_MM
@ NORMAL
Inactive layers are shown normally (no high-contrast mode)
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
BOX2< VECTOR2D > BOX2D
Definition box2.h:923
BASE_SET & set(size_t pos)
Definition base_set.h:116
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
TEARDROP_PARAMETERS & GetTeardropParams()
FOOTPRINT * GetParentFootprint() const
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:558
constexpr coord_type GetLeft() const
Definition box2.h:228
constexpr void Move(const Vec &aMoveVector)
Move the rectangle by the aMoveVector.
Definition box2.h:138
constexpr coord_type GetRight() const
Definition box2.h:217
constexpr const SizeVec & GetSize() const
Definition box2.h:206
constexpr coord_type GetTop() const
Definition box2.h:229
constexpr coord_type GetBottom() const
Definition box2.h:222
Color settings are a bit different than most of the settings objects in that there can be more than o...
COLOR4D GetColor(int aLayer) const
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:106
DIALOG_PAD_PROPERTIES_BASE(wxWindow *parent, wxWindowID id=wxID_DIALOG_EDIT_PAD, const wxString &title=_("Pad Properties"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
void OnUpdateUINonCopperWarning(wxUpdateUIEvent &event) override
void OnInitDialog(wxInitDialogEvent &event) override
void PadTypeSelected(wxCommandEvent &event) override
void OnPadToDieDelayCheckbox(wxCommandEvent &event) override
void OnPadShapeSelection(wxCommandEvent &event) override
bool transferDataToPad(PAD *aPad)
Copy values from dialog field to aPad's members.
bool TransferDataFromWindow() override
Updates the different parameters for the component being edited.
std::map< int, PCB_LAYER_ID > m_editLayerCtrlMap
bool Show(bool aShow) override
void OnEditLayerChanged(wxCommandEvent &event) override
std::vector< std::shared_ptr< PCB_SHAPE > > m_primitives
bool padValuesOK()
test if all values are acceptable for the pad
void PadOrientEvent(wxCommandEvent &event) override
void OnResize(wxSizeEvent &event)
void OnOffsetCheckbox(wxCommandEvent &event) override
PCB_DRAW_PANEL_GAL * m_padPreviewGAL
void OnValuesChanged(wxCommandEvent &event) override
Called when a dimension has changed.
DIALOG_PAD_PROPERTIES(PCB_BASE_FRAME *aParent, PAD *aPad)
void onTeardropsUpdateUi(wxUpdateUIEvent &event) override
void onChangePadMode(wxCommandEvent &event) override
std::vector< PCB_SHAPE * > m_highlight
void OnPadstackModeChanged(wxCommandEvent &event) override
KIGFX::ORIGIN_VIEWITEM * m_axisOrigin
void OnSetCopperLayers(wxCommandEvent &event) override
void OnCancel(wxCommandEvent &event) override
void onCornerRadiusChange(wxCommandEvent &event) override
void updatePadLayersList(LSET layer_mask, bool remove_unconnected, bool keep_top_bottom)
Updates the CheckBox states in pad layers list, based on the layer_mask (if non-empty) or the default...
PAD_PROP getSelectedProperty()
Return the pad property currently selected.
void OnSetLayers(wxCommandEvent &event) override
void onCornerSizePercentChange(wxCommandEvent &event) override
void OnPadToDieCheckbox(wxCommandEvent &event) override
void OnDrillShapeSelected(wxCommandEvent &event) override
void OnUpdateUI(wxUpdateUIEvent &event) override
void onModify(wxCommandEvent &aEvent) override
bool Show(bool show) override
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition dialog_shim.h:82
void SetupStandardButtons(std::map< int, wxString > aLabels={})
void resetSize()
Clear the existing dialog size and position.
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
int ShowModal() override
FRAME_T GetFrameType() const
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.
Contains methods for drawing PCB-specific items.
virtual PCB_RENDER_SETTINGS * GetSettings() override
Return a pointer to current settings that are going to be used when drawing items.
PCB specific render settings.
Definition pcb_painter.h:82
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,...
const VC_SETTINGS & GetSettings() const
Return the current VIEW_CONTROLS settings.
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:66
void SetViewport(const BOX2D &aViewport)
Set the visible area of the VIEW.
Definition view.cpp:542
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition view.cpp:298
void SetBoundary(const BOX2D &aBoundary)
Set limits for view area.
Definition view.h:286
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition view.cpp:1685
void SetLayerVisible(int aLayer, bool aVisible=true)
Control the visibility of a particular layer.
Definition view.h:400
GAL * GetGAL() const
Return the GAL this view is using to draw graphical primitives.
Definition view.h:202
void ClearTopLayers()
Remove all layers from the on-the-top set (they are no longer displayed over the rest of layers).
Definition view.cpp:891
virtual void SetTopLayer(int aLayer, bool aEnabled=true)
Set given layer to be displayed on the top or sets back the default order of layers.
Definition view.cpp:839
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition view.h:220
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
LSEQ UIOrder() const
Return the copper, technical and user layers in the order shown in layer widget.
Definition lset.cpp:726
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition lset.cpp:582
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:591
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition netinfo.h:247
void SetUnconnectedLayerMode(UNCONNECTED_LAYER_MODE aMode)
Definition padstack.h:315
void SetMode(MODE aMode)
Definition padstack.cpp:833
@ NORMAL
Shape is the same on all layers.
Definition padstack.h:139
@ CUSTOM
Shapes can be defined on arbitrary layers.
Definition padstack.h:141
@ FRONT_INNER_BACK
Up to three shapes can be defined (F_Cu, inner copper layers, B_Cu)
Definition padstack.h:140
static constexpr PCB_LAYER_ID INNER_LAYERS
! The layer identifier to use for "inner layers" on top/inner/bottom padstacks
Definition padstack.h:148
void SetLastPadNumber(const wxString &aPadNumber)
Definition pad_tool.h:67
wxString GetLastPadNumber() const
Definition pad_tool.h:66
Definition pad.h:54
void SetAnchorPadShape(PCB_LAYER_ID aLayer, PAD_SHAPE aShape)
Set the shape of the anchor pad for custom shaped pads.
Definition pad.h:242
void SetAttribute(PAD_ATTRIB aAttribute)
Definition pad.cpp:883
void SetLocalThermalGapOverride(const std::optional< int > &aOverride)
Definition pad.h:649
PAD_ATTRIB GetAttribute() const
Definition pad.h:440
static LSET PTHMask()
layer set for a through hole pad
Definition pad.cpp:291
void SetThermalSpokeAngle(const EDA_ANGLE &aAngle)
The orientation of the thermal spokes.
Definition pad.h:621
void SetLocalSolderPasteMarginRatio(std::optional< double > aRatio)
Definition pad.h:479
void SetLocalThermalSpokeWidthOverride(std::optional< int > aWidth)
Set the width of the thermal spokes connecting the pad to a zone.
Definition pad.h:605
void SetShape(PCB_LAYER_ID aLayer, PAD_SHAPE aShape)
Set the new shape of this pad.
Definition pad.h:186
void SetProperty(PAD_PROP aProperty)
Definition pad.cpp:950
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
Definition pad.cpp:312
void SetDelta(PCB_LAYER_ID aLayer, const VECTOR2I &aSize)
Definition pad.h:293
void SetPadToDieDelay(int aDelay)
Definition pad.h:455
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
Definition pad.h:195
void SetNumber(const wxString &aNumber)
Set the pad number (note that it can be alphanumeric, such as the array reference "AA12").
Definition pad.h:135
void SetDrillShape(PAD_DRILL_SHAPE aShape)
Definition pad.cpp:456
void SetLocalSolderMaskMargin(std::optional< int > aMargin)
Definition pad.h:462
void SetOffset(PCB_LAYER_ID aLayer, const VECTOR2I &aOffset)
Definition pad.h:311
void SetLocalZoneConnection(ZONE_CONNECTION aType)
Definition pad.h:485
void SetChamferRectRatio(PCB_LAYER_ID aLayer, double aChamferScale)
Has meaning only for chamfered rectangular pads.
Definition pad.cpp:517
void SetPosition(const VECTOR2I &aPos) override
Definition pad.h:202
const PADSTACK & Padstack() const
Definition pad.h:321
static LSET ConnSMDMask()
layer set for a SMD pad on Front layer used for edge board connectors
Definition pad.cpp:305
void SetDrillSize(const VECTOR2I &aSize)
Definition pad.h:304
void SetSize(PCB_LAYER_ID aLayer, const VECTOR2I &aSize)
Definition pad.h:259
void ReplacePrimitives(PCB_LAYER_ID aLayer, const std::vector< std::shared_ptr< PCB_SHAPE > > &aPrimitivesList)
Clear the current custom shape primitives list and import a new list.
Definition pad.cpp:2640
static LSET ApertureMask()
layer set for an aperture pad
Definition pad.cpp:319
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition pad.cpp:298
void SetChamferPositions(PCB_LAYER_ID aLayer, int aPositions)
Has meaning only for chamfered rectangular pads.
Definition pad.h:706
void SetLocalSolderPasteMargin(std::optional< int > aMargin)
Definition pad.h:469
void SetCustomShapeInZoneOpt(PADSTACK::CUSTOM_SHAPE_ZONE_MODE aOption)
Set the option for the custom pad shape to use as clearance area in copper zones.
Definition pad.h:231
void SetOrientation(const EDA_ANGLE &aAngle)
Set the rotation angle of the pad.
Definition pad.cpp:958
void SetLocalClearance(std::optional< int > aClearance)
Definition pad.h:459
void SetLayerSet(const LSET &aLayers) override
Definition pad.h:436
PAD_SHAPE GetAnchorPadShape(PCB_LAYER_ID aLayer) const
Definition pad.h:213
void SetRoundRectRadiusRatio(PCB_LAYER_ID aLayer, double aRadiusScale)
Has meaning only for rounded rectangle pads.
Definition pad.cpp:479
void SetPadToDieLength(int aLength)
Definition pad.h:452
const VECTOR2I & GetSize(PCB_LAYER_ID aLayer) const
Definition pad.h:264
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
void ShowPadPropertiesDialog(PAD *aPad)
double m_BestWidthRatio
The height of a teardrop as ratio between height and size of pad/via.
int m_TdMaxLen
max allowed length for teardrops in IU. <= 0 to disable
bool m_AllowUseTwoTracks
True to create teardrops using 2 track segments if the first in too small.
int m_TdMaxWidth
max allowed height for teardrops in IU. <= 0 to disable
double m_BestLengthRatio
The length of a teardrop as ratio between length and size of pad/via.
double m_WidthtoSizeFilterRatio
The ratio (H/D) between the via/pad size and the track width max value to create a teardrop 1....
bool m_TdOnPadsInZones
A filter to exclude pads inside zone fills.
bool m_Enabled
Flag to enable teardrops.
bool m_CurvedEdges
True if the teardrop should be curved.
A type-safe container of any type.
Definition ki_any.h:93
This file is part of the common library.
#define APERTURE_DLG_TYPE
#define CONN_DLG_TYPE
static PAD_ATTRIB code_type[]
#define SELECTED_ITEMS_LAYER
static PAD_SHAPE code_shape[]
#define SMD_DLG_TYPE
@ CHOICE_SHAPE_CIRCLE
@ CHOICE_SHAPE_ROUNDRECT
@ CHOICE_SHAPE_CUSTOM_RECT_ANCHOR
@ CHOICE_SHAPE_CHAMFERED_RECT
@ CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
@ CHOICE_SHAPE_RECT
@ CHOICE_SHAPE_OVAL
@ CHOICE_SHAPE_TRAPEZOID
@ CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT
#define NPTH_DLG_TYPE
#define PTH_DLG_TYPE
#define PAD_PROPERTIES_DLG_NAME
DIALOG_PAD_PROPERTIES, derived from DIALOG_PAD_PROPERTIES_BASE, created by wxFormBuilder.
@ DRCE_PADSTACK
Definition drc_item.h:63
@ DRCE_PADSTACK_INVALID
Definition drc_item.h:64
@ DRCE_PAD_TH_WITH_NO_HOLE
Definition drc_item.h:85
#define _(s)
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:413
static constexpr EDA_ANGLE ANGLE_45
Definition eda_angle.h:412
#define BRIGHTENED
item is drawn with a bright contour
#define SELECTED
Item was manually selected by the user.
@ FP_SMD
Definition footprint.h:82
@ FP_THROUGH_HOLE
Definition footprint.h:81
@ FRAME_PCB_EDITOR
Definition frame_type.h:42
@ FRAME_FOOTPRINT_EDITOR
Definition frame_type.h:43
@ LAYER_PAD_NETNAMES
Definition layer_ids.h:202
@ LAYER_GRID
Definition layer_ids.h:254
@ LAYER_LOCKED_ITEM_SHADOW
Shadow layer for locked items.
Definition layer_ids.h:307
@ LAYER_NON_PLATEDHOLES
Draw usual through hole vias.
Definition layer_ids.h:239
@ LAYER_PAD_PLATEDHOLES
to draw pad holes (plated)
Definition layer_ids.h:271
@ LAYER_PAD_HOLEWALLS
Definition layer_ids.h:297
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.
@ TOP_BOTTOM
Flip top to bottom (around the X axis)
Definition mirror.h:29
KICOMMON_API wxFont GetStatusFont(wxWindow *aWindow)
KICOMMON_API wxFont GetSmallInfoFont(wxWindow *aWindow)
bool PadHasMeaningfulRoundingRadius(const PAD &aPad, PCB_LAYER_ID aLayer)
Returns true if the pad's rounding ratio is valid (i.e.
Definition pad_utils.cpp:44
double GetDefaultIpcRoundingRatio(const PAD &aPad, PCB_LAYER_ID aLayer)
Get a sensible default for a rounded rectangle pad's rounding ratio.
Definition pad_utils.cpp:27
PAD_ATTRIB
The set of pad shapes, used with PAD::{Set,Get}Attribute().
Definition padstack.h:81
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition padstack.h:87
@ SMD
Smd pad, appears on the solder paste layer (default)
Definition padstack.h:83
@ PTH
Plated through hole pad.
Definition padstack.h:82
@ CONN
Like smd, does not appear on the solder paste layer (default) Note: also has a special attribute in G...
Definition padstack.h:84
PAD_SHAPE
The set of pad shapes, used with PAD::{Set,Get}Shape()
Definition padstack.h:52
@ CHAMFERED_RECT
Definition padstack.h:60
@ ROUNDRECT
Definition padstack.h:57
@ TRAPEZOID
Definition padstack.h:56
@ RECTANGLE
Definition padstack.h:54
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
@ FIDUCIAL_LOCAL
a fiducial (usually a smd) local to the parent footprint
Definition padstack.h:102
@ FIDUCIAL_GLBL
a fiducial (usually a smd) for the full board
Definition padstack.h:101
@ MECHANICAL
a pad used for mechanical support
Definition padstack.h:106
@ PRESSFIT
a PTH with a hole diameter with tight tolerances for press fit pin
Definition padstack.h:107
@ HEATSINK
a pad used as heat sink, usually in SMD footprints
Definition padstack.h:104
@ NONE
no special fabrication property
Definition padstack.h:99
@ TESTPOINT
a test point pad
Definition padstack.h:103
@ CASTELLATED
a pad with a castellated through hole
Definition padstack.h:105
@ BGA
Smd pad, used in BGA footprints.
Definition padstack.h:100
int delta
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition trigo.cpp:229
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694
@ THERMAL
Use thermal relief for pads.
Definition zones.h:50
@ NONE
Pads are not covered.
Definition zones.h:49
@ FULL
pads are covered by copper
Definition zones.h:51