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 );
231
232 initValues();
233
234 m_techLayersLabel->SetFont( KIUI::GetStatusFont( this ) );
235 m_parentInfo->SetFont( KIUI::GetSmallInfoFont( this ) );
236 m_teardropShapeLabel->SetFont( KIUI::GetStatusFont( this ) );
237
238 wxFont infoFont = KIUI::GetSmallInfoFont( this ).Italic();
239 m_nonCopperNote->SetFont( infoFont );
240 m_staticTextInfoPaste->SetFont( infoFont );
241
244
245 // Usually, TransferDataToWindow is called by OnInitDialog
246 // calling it here fixes all widget sizes so FinishDialogSettings can safely fix minsizes
248
249 // Initialize canvas to be able to display the dummy pad:
251
252 m_notebook->SetSelection( m_page );
253
254 switch( m_page )
255 {
256 default:
257 case 0: SetInitialFocus( m_padNumCtrl ); break;
258 case 1: SetInitialFocus( m_thermalGapCtrl ); break;
259 case 2: SetInitialFocus( m_clearanceCtrl ); break;
260 }
261
263 m_initialized = true;
264
265 m_padNetSelector->Connect( FILTERED_ITEM_SELECTED,
266 wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ),
267 nullptr, this );
268
269 if( m_padType->GetSelection() != PTH_DLG_TYPE && m_padType->GetSelection() != NPTH_DLG_TYPE )
270 {
271 m_gbSizerHole->Show( false );
272 m_staticline71->Show( false );
273 }
274
275 // Now all widgets have the size fixed, call FinishDialogSettings
277
278 // Update widgets
279 wxUpdateUIEvent dummyUI;
280 OnUpdateUI( dummyUI );
281
282 // Post a dummy size event to force the pad preview panel to update the
283 // view: actual size, best zoom ... after the frame is shown
284 PostSizeEvent();
285}
286
287
289{
290 m_padNetSelector->Disconnect( FILTERED_ITEM_SELECTED,
291 wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ),
292 nullptr, this );
293
294 m_page = m_notebook->GetSelection();
295
296 delete m_previewPad;
297 delete m_axisOrigin;
298}
299
300
301// Store the pad draw option during a session.
303
304
305void DIALOG_PAD_PROPERTIES::OnInitDialog( wxInitDialogEvent& event )
306{
307 m_selectedColor = COLOR4D( 1.0, 1.0, 1.0, 0.7 );
308
309 // Needed on some WM to be sure the pad is redrawn according to the final size
310 // of the canvas, with the right zoom factor
311 redraw();
312}
313
314
315void DIALOG_PAD_PROPERTIES::OnCancel( wxCommandEvent& event )
316{
317 // Mandatory to avoid m_panelShowPadGal trying to draw something
318 // in a non valid context during closing process:
319 m_padPreviewGAL->StopDrawing();
320
321 // Now call default handler for wxID_CANCEL command event
322 event.Skip();
323}
324
325
327{
328 GAL_DISPLAY_OPTIONS_IMPL opts = m_parent->GetGalDisplayOptions();
329 COLOR_SETTINGS* colorSettings = m_parent->GetColorSettings();
330
331 opts.m_forceDisplayCursor = false;
332
333 // Initialize the canvas to display the pad
334 m_padPreviewGAL = new PCB_DRAW_PANEL_GAL( m_boardViewPanel, -1, wxDefaultPosition,
335 wxDefaultSize, opts,
336 m_parent->GetCanvas()->GetBackend() );
337
338 m_padPreviewSizer->Add( m_padPreviewGAL, 12, wxEXPAND | wxALL, 5 );
339
340 // Show the X and Y axis. It is useful because pad shape can have an offset
341 // or be a complex shape.
344 VECTOR2D( m_previewPad->GetPosition() ) );
345 m_axisOrigin->SetDrawAtZero( true );
346
347 m_padPreviewGAL->UpdateColors();
348 m_padPreviewGAL->SetStealsFocus( false );
349 m_padPreviewGAL->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
350
351 KIGFX::VIEW_CONTROLS* parentViewControls = m_parent->GetCanvas()->GetViewControls();
352 m_padPreviewGAL->GetViewControls()->ApplySettings( parentViewControls->GetSettings() );
353
354 m_padPreviewGAL->Show();
355
356 KIGFX::VIEW* view = m_padPreviewGAL->GetView();
357
358 // fix the pad render mode (filled/not filled)
359 auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
360
361 settings->m_ForcePadSketchModeOn = m_cbShowPadOutline->IsChecked();
362 settings->SetHighContrast( false );
363 settings->m_ContrastModeDisplay = HIGH_CONTRAST_MODE::NORMAL;
364
365 // don't show the locked item shadow in pad preview
367
368 // gives a non null grid size (0.001mm) because GAL layer does not like a 0 size grid:
369 double gridsize = 0.001 * pcbIUScale.IU_PER_MM;
370 view->GetGAL()->SetGridSize( VECTOR2D( gridsize, gridsize ) );
371
372 // And do not show the grid:
373 view->GetGAL()->SetGridVisibility( false );
374 view->GetGAL()->SetAxesEnabled( false );
375 view->Add( m_previewPad );
376 view->Add( m_axisOrigin );
377
378 m_padPreviewGAL->StartDrawing();
379 Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_PAD_PROPERTIES::OnResize ) );
380}
381
382
389
390
391void DIALOG_PAD_PROPERTIES::OnEditLayerChanged( wxCommandEvent& aEvent )
392{
393 // Save data from the previous layer
395
396 switch( m_previewPad->Padstack().Mode() )
397 {
398 default:
401 break;
402
404 switch( m_cbEditLayer->GetSelection() )
405 {
406 default:
407 case 0: m_editLayer = F_Cu; break;
408 case 1: m_editLayer = PADSTACK::INNER_LAYERS; break;
409 case 2: m_editLayer = B_Cu; break;
410 }
411 break;
412
414 {
415 int layer = m_cbEditLayer->GetSelection();
416
417 if( layer < 0 )
418 layer = 0;
419
420 if( m_editLayerCtrlMap.contains( layer ) )
421 m_editLayer = m_editLayerCtrlMap.at( layer );
422 else
424 }
425 }
426
427 // Load controls with the current layer
429
430 wxCommandEvent cmd_event;
431 OnPadShapeSelection( cmd_event );
432 OnOffsetCheckbox( cmd_event );
433
434 redraw();
435}
436
437
439{
440 // Note: use ChangeValue() to avoid generating a wxEVT_TEXT event
441 m_cornerRadius.ChangeValue( m_previewPad->GetRoundRectCornerRadius( m_editLayer ) );
442
443 m_cornerRatio.ChangeDoubleValue( m_previewPad->GetRoundRectRadiusRatio( m_editLayer ) * 100.0 );
444 m_mixedCornerRatio.ChangeDoubleValue( m_previewPad->GetRoundRectRadiusRatio( m_editLayer ) * 100.0 );
445
446 m_chamferRatio.ChangeDoubleValue( m_previewPad->GetChamferRectRatio( m_editLayer ) * 100.0 );
447 m_mixedChamferRatio.ChangeDoubleValue( m_previewPad->GetChamferRectRatio( m_editLayer ) * 100.0 );
448}
449
450
452{
455 {
456 return;
457 }
458
459 if( m_cornerRadius.GetValue() < 0 )
460 m_cornerRadiusCtrl->ChangeValue( "0" );
461
463 {
464 m_previewPad->SetRoundRectCornerRadius( m_editLayer, m_cornerRadius.GetValue() );
465
466 m_cornerRatio.ChangeDoubleValue( m_previewPad->GetRoundRectRadiusRatio( m_editLayer ) * 100.0 );
467 m_mixedCornerRatio.ChangeDoubleValue( m_previewPad->GetRoundRectRadiusRatio( m_editLayer ) * 100.0 );
468
469 redraw();
470 }
471
472 if( m_initialized )
473 OnModify();
474}
475
476
478{
479 // The maximum chamfer ratio is 50% of the smallest pad side if adjacent sides
480 // are selected, or 100% of the smallest pad side if only one side is selected.
481 double baseline = 1.0;
482
483 auto considerCheckboxes = [&]( const std::vector<wxCheckBox*>& checkBoxes )
484 {
485 for( size_t ii : { 0, 1, 2, 3 } )
486 {
487 if( !checkBoxes[ii]->IsChecked() )
488 continue;
489
490 if( checkBoxes[( ii + 1 ) % 4]->IsChecked() || checkBoxes[( ii - 1 ) % 4]->IsChecked() )
491 {
492 // If two adjacent corners are selected, the maximum chamfer ratio is 50%
493 baseline = std::max( baseline, 0.5 );
494 break;
495 }
496 }
497 };
498
499
500 baseline = 1.0 - m_previewPad->GetRoundRectRadiusRatio( m_editLayer );
501 considerCheckboxes( { m_cbTopLeft1, m_cbTopRight1, m_cbBottomRight1, m_cbBottomLeft1 } );
502 considerCheckboxes( { m_cbTopLeft, m_cbTopRight, m_cbBottomRight, m_cbBottomLeft } );
503
504 // If only one corner is selected, the maximum chamfer ratio is 100%
505 return baseline;
506}
507
508
510{
511 return 1.0 - m_previewPad->GetChamferRectRatio( m_editLayer );
512}
513
514
516{
517 auto updateCheckBoxes = []( const std::vector<wxCheckBox*>& aCheckBoxes )
518 {
519 for( size_t ii : { 0, 1, 2, 3 } )
520 {
521 bool disable = aCheckBoxes[( ii + 1 ) % 4]->IsChecked()
522 || aCheckBoxes[( ii + 3 ) % 4]->IsChecked();
523
524 aCheckBoxes[ii]->Enable( !disable );
525
526 if( disable )
527 aCheckBoxes[ii]->SetValue( false );
528 }
529 };
530
531 if( m_mixedChamferRatio.GetDoubleValue() > 50.0 )
532 {
534 }
535
536 if( m_chamferRatio.GetDoubleValue() > 50.0 )
537 {
538 updateCheckBoxes( { m_cbTopLeft, m_cbTopRight, m_cbBottomRight, m_cbBottomLeft } );
539 }
540}
541
542
544{
547 {
548 return;
549 }
550
551 wxObject* ctrl = event.GetEventObject();
552 wxString value = event.GetString();
553 bool changed = false;
554
555 if( ctrl == m_cornerRatioCtrl || ctrl == m_mixedCornerRatioCtrl )
556 {
557 double ratioPercent;
558
559 if( value.ToDouble( &ratioPercent ) )
560 {
561 // Clamp ratioPercent to acceptable value (0.0 to 50.0)
562 double maxRatio = getMaxCornerRadius();
563
564 if( ratioPercent < 0.0 )
565 {
566 m_cornerRatio.SetDoubleValue( 0.0 );
567 m_mixedCornerRatio.SetDoubleValue( 0.0 );
568 }
569 else if( ratioPercent > maxRatio * 100.0 )
570 {
571 m_cornerRatio.SetDoubleValue( maxRatio * 100.0 );
572 m_mixedCornerRatio.SetDoubleValue( maxRatio * 100.0 );
573 }
574
575 if( ctrl == m_cornerRatioCtrl )
576 m_mixedCornerRatioCtrl->ChangeValue( value );
577 else
578 m_cornerRatioCtrl->ChangeValue( value );
579
580 changed = true;
581 }
582 }
583 else if( ctrl == m_chamferRatioCtrl || ctrl == m_mixedChamferRatioCtrl )
584 {
585 double ratioPercent;
586
587 if( value.ToDouble( &ratioPercent ) )
588 {
589 double maxRatio = getMaxChamferRatio();
590 // Clamp ratioPercent to acceptable value (0.0 to maxRatio)
591 if( ratioPercent < 0.0 )
592 {
593 m_chamferRatio.SetDoubleValue( 0.0 );
594 m_mixedChamferRatio.SetDoubleValue( 0.0 );
595 }
596 else if( ratioPercent > maxRatio * 100.0 )
597 {
598 m_chamferRatio.SetDoubleValue( maxRatio * 100.0 );
599 m_mixedChamferRatio.SetDoubleValue( maxRatio * 100.0 );
600 }
601
602 if( ctrl == m_chamferRatioCtrl )
603 m_mixedChamferRatioCtrl->ChangeValue( value );
604 else
605 m_chamferRatioCtrl->ChangeValue( value );
606
608
609 changed = true;
610 }
611 }
612
613 if( changed && transferDataToPad( m_previewPad ) )
614 m_cornerRadius.ChangeValue( m_previewPad->GetRoundRectCornerRadius( m_editLayer ) );
615
616 redraw();
617
618 if( m_initialized )
619 OnModify();
620}
621
622
624{
625 wxString msg;
626
627 // Disable pad net name wxTextCtrl if the caller is the footprint editor
628 // because nets are living only in the board managed by the board editor
630
631 m_layerFrontAdhesive->SetLabel( m_board->GetLayerName( F_Adhes ) );
632 m_layerBackAdhesive->SetLabel( m_board->GetLayerName( B_Adhes ) );
633 m_layerFrontPaste->SetLabel( m_board->GetLayerName( F_Paste ) );
634 m_layerBackPaste->SetLabel( m_board->GetLayerName( B_Paste ) );
635 m_layerFrontSilk->SetLabel( m_board->GetLayerName( F_SilkS ) );
636 m_layerBackSilk->SetLabel( m_board->GetLayerName( B_SilkS ) );
637 m_layerFrontMask->SetLabel( m_board->GetLayerName( F_Mask ) );
638 m_layerBackMask->SetLabel( m_board->GetLayerName( B_Mask ) );
639 m_layerECO1->SetLabel( m_board->GetLayerName( Eco1_User ) );
640 m_layerECO2->SetLabel( m_board->GetLayerName( Eco2_User ) );
641 m_layerUserDwgs->SetLabel( m_board->GetLayerName( Dwgs_User ) );
642
643 VECTOR2I absPos;
644
645 if( m_currentPad )
646 {
647 absPos = m_currentPad->GetPosition();
648
649 if( FOOTPRINT* footprint = m_currentPad->GetParentFootprint() )
650 {
651 VECTOR2I relPos = m_currentPad->GetFPRelativePosition();
652
653 if( footprint->IsFlipped() )
654 {
655 // flip pad (up/down) around its position
657 relPos.y = - relPos.y;
658 }
659
660 m_previewPad->SetPosition( relPos );
661 m_previewPad->SetOrientation( m_currentPad->GetFPRelativeOrientation() );
662
663 // Display parent footprint info
664 msg.Printf( _("Footprint %s (%s), %s, rotated %g deg"),
665 footprint->Reference().GetShownText( false ),
666 footprint->Value().GetShownText( false ),
667 footprint->IsFlipped() ? _( "back side (mirrored)" ) : _( "front side" ),
668 footprint->GetOrientation().AsDegrees() );
669
670 m_FlippedWarningSizer->Show( footprint->IsFlipped() );
671 m_parentInfo->SetLabel( msg );
672 }
673
674 m_padNumCtrl->SetValue( m_previewPad->GetNumber() );
675 }
676 else
677 {
678 PAD_TOOL* padTool = m_parent->GetToolManager()->GetTool<PAD_TOOL>();
679 m_padNumCtrl->SetValue( padTool->GetLastPadNumber() );
680
681 if( m_isFpEditor && m_board->GetFirstFootprint() )
682 {
683 switch( m_board->GetFirstFootprint()->GetAttributes() )
684 {
686 m_previewPad->SetAttribute( PAD_ATTRIB::PTH );
687
688 if( m_previewPad->GetDrillSizeX() == 0 )
689 m_board->GetDesignSettings().SetDefaultMasterPad();
690
691 break;
692
694 m_previewPad->SetLayerSet( PAD::SMDMask() );
695 m_previewPad->SetAttribute( PAD_ATTRIB::SMD );
696 break;
697 }
698 }
699 }
700
702
703 m_padNetSelector->SetSelectedNetcode( m_previewPad->GetNetCode() );
704
705 // Display current pad parameters units:
706 m_posX.ChangeValue( absPos.x );
707 m_posY.ChangeValue( absPos.y );
708
709 m_holeX.ChangeValue( m_previewPad->GetDrillSize().x );
710 m_holeY.ChangeValue( m_previewPad->GetDrillSize().y );
711
712 // TODO(JE) padstacks -- does this need to be saved/restored every time the layer changes?
713 // Store the initial thermal spoke angle to restore it, because some initializations
714 // can change this value (mainly after m_PadShapeSelector initializations)
715 EDA_ANGLE spokeInitialAngle = m_previewPad->GetThermalSpokeAngle();
716
718
719 m_padToDieOpt->SetValue( m_previewPad->GetPadToDieLength() != 0 );
720 m_padToDie.ChangeValue( m_previewPad->GetPadToDieLength() );
721
722 m_padToDieDelayOpt->SetValue( m_previewPad->GetPadToDieDelay() != 0 );
723 m_padToDieDelay.ChangeValue( m_previewPad->GetPadToDieDelay() );
724
725 if( m_previewPad->GetLocalClearance().has_value() )
726 m_clearance.ChangeValue( m_previewPad->GetLocalClearance().value() );
727 else
728 m_clearance.ChangeValue( wxEmptyString );
729
730 if( m_previewPad->GetLocalSolderMaskMargin().has_value() )
731 m_maskMargin.ChangeValue( m_previewPad->GetLocalSolderMaskMargin().value() );
732 else
733 m_maskMargin.ChangeValue( wxEmptyString );
734
735 if( m_previewPad->GetLocalSolderPasteMargin().has_value() )
736 m_pasteMargin.ChangeValue( m_previewPad->GetLocalSolderPasteMargin().value() );
737 else
738 m_pasteMargin.ChangeValue( wxEmptyString );
739
740 if( m_previewPad->GetLocalSolderPasteMarginRatio().has_value() )
741 m_pasteMarginRatio.ChangeDoubleValue( m_previewPad->GetLocalSolderPasteMarginRatio().value() * 100.0 );
742 else
743 m_pasteMarginRatio.ChangeValue( wxEmptyString );
744
745 if( m_previewPad->GetLocalThermalSpokeWidthOverride().has_value() )
746 m_spokeWidth.ChangeValue( m_previewPad->GetLocalThermalSpokeWidthOverride().value() );
747 else
748 m_spokeWidth.SetNull();
749
750 if( m_previewPad->GetLocalThermalGapOverride().has_value() )
751 m_thermalGap.ChangeValue( m_previewPad->GetLocalThermalGapOverride().value() );
752 else
753 m_thermalGap.SetNull();
754
755 m_spokeAngle.ChangeAngleValue( m_previewPad->GetThermalSpokeAngle() );
756 m_pad_orientation.ChangeAngleValue( m_previewPad->GetOrientation() );
757
758 m_cbTeardrops->SetValue( m_previewPad->GetTeardropParams().m_Enabled );
759 m_cbTeardropsUseNextTrack->SetValue( m_previewPad->GetTeardropParams().m_AllowUseTwoTracks );
760 m_cbPreferZoneConnection->SetValue( !m_previewPad->GetTeardropParams().m_TdOnPadsInZones );
761 m_teardropMaxLenSetting.SetValue( m_previewPad->GetTeardropParams().m_TdMaxLen );
762 m_teardropMaxHeightSetting.SetValue( m_previewPad->GetTeardropParams().m_TdMaxWidth );
763 m_spTeardropLenPercent->SetValue( m_previewPad->GetTeardropParams().m_BestLengthRatio *100 );
764 m_spTeardropSizePercent->SetValue( m_previewPad->GetTeardropParams().m_BestWidthRatio *100 );
765 m_spTeardropHDPercent->SetValue( m_previewPad->GetTeardropParams().m_WidthtoSizeFilterRatio*100 );
766 m_curvedEdges->SetValue( m_previewPad->GetTeardropParams().m_CurvedEdges );
767
768 switch( m_previewPad->GetLocalZoneConnection() )
769 {
770 default:
771 case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
772 case ZONE_CONNECTION::FULL: m_ZoneConnectionChoice->SetSelection( 1 ); break;
773 case ZONE_CONNECTION::THERMAL: m_ZoneConnectionChoice->SetSelection( 2 ); break;
774 case ZONE_CONNECTION::NONE: m_ZoneConnectionChoice->SetSelection( 3 ); break;
775 }
776
777 if( m_previewPad->GetCustomShapeInZoneOpt() == PADSTACK::CUSTOM_SHAPE_ZONE_MODE::CONVEXHULL )
778 m_ZoneCustomPadShape->SetSelection( 1 );
779 else
780 m_ZoneCustomPadShape->SetSelection( 0 );
781
782 // Type of pad selection
783 bool aperture =
784 m_previewPad->GetAttribute() == PAD_ATTRIB::SMD && m_previewPad->IsAperturePad();
785
786 if( aperture )
787 {
788 m_padType->SetSelection( APERTURE_DLG_TYPE );
789 }
790 else
791 {
792 switch( m_previewPad->GetAttribute() )
793 {
794 case PAD_ATTRIB::PTH: m_padType->SetSelection( PTH_DLG_TYPE ); break;
795 case PAD_ATTRIB::SMD: m_padType->SetSelection( SMD_DLG_TYPE ); break;
796 case PAD_ATTRIB::CONN: m_padType->SetSelection( CONN_DLG_TYPE ); break;
797 case PAD_ATTRIB::NPTH: m_padType->SetSelection( NPTH_DLG_TYPE ); break;
798 }
799 }
800
801 switch( m_previewPad->GetProperty() )
802 {
803 case PAD_PROP::NONE: m_choiceFabProperty->SetSelection( 0 ); break;
804 case PAD_PROP::BGA: m_choiceFabProperty->SetSelection( 1 ); break;
805 case PAD_PROP::FIDUCIAL_LOCAL: m_choiceFabProperty->SetSelection( 2 ); break;
806 case PAD_PROP::FIDUCIAL_GLBL: m_choiceFabProperty->SetSelection( 3 ); break;
807 case PAD_PROP::TESTPOINT: m_choiceFabProperty->SetSelection( 4 ); break;
808 case PAD_PROP::HEATSINK: m_choiceFabProperty->SetSelection( 5 ); break;
809 case PAD_PROP::MECHANICAL: m_choiceFabProperty->SetSelection( 6 ); break;
810 case PAD_PROP::CASTELLATED: m_choiceFabProperty->SetSelection( 7 ); break;
811 case PAD_PROP::PRESSFIT: m_choiceFabProperty->SetSelection( 8 ); break;
812 }
813
814 // Ensure the pad property is compatible with the pad type
815 if( m_previewPad->GetAttribute() == PAD_ATTRIB::NPTH )
816 {
817 m_choiceFabProperty->SetSelection( 0 );
818 m_choiceFabProperty->Enable( false );
819 }
820
821 if( m_previewPad->GetDrillShape() != PAD_DRILL_SHAPE::OBLONG )
822 m_holeShapeCtrl->SetSelection( 0 );
823 else
824 m_holeShapeCtrl->SetSelection( 1 );
825
826 updatePadLayersList( m_previewPad->GetLayerSet(), m_previewPad->GetRemoveUnconnected(),
827 m_previewPad->GetKeepTopBottom() );
828
829 // Update some dialog widgets state (Enable/disable options):
830 wxCommandEvent cmd_event;
831 OnPadShapeSelection( cmd_event );
832 OnOffsetCheckbox( cmd_event );
833
834 // Restore thermal spoke angle to its initial value, because it can be modified
835 // by the call to OnPadShapeSelection()
836 m_previewPad->SetThermalSpokeAngle( spokeInitialAngle );
837 m_spokeAngle.SetAngleValue( m_previewPad->GetThermalSpokeAngle() );
838}
839
840
842{
843 m_primitives = m_previewPad->GetPrimitives( m_editLayer );
844
845 m_sizeX.ChangeValue( m_previewPad->GetSize( m_editLayer ).x );
846 m_sizeY.ChangeValue( m_previewPad->GetSize( m_editLayer ).y );
847
848 m_offsetShapeOpt->SetValue( m_previewPad->GetOffset( m_editLayer ) != VECTOR2I() );
849 m_offsetX.ChangeValue( m_previewPad->GetOffset( m_editLayer ).x );
850 m_offsetY.ChangeValue( m_previewPad->GetOffset( m_editLayer ).y );
851
852 if( m_previewPad->GetDelta( m_editLayer ).x )
853 {
854 m_trapDelta.ChangeValue( m_previewPad->GetDelta( m_editLayer ).x );
855 m_trapAxisCtrl->SetSelection( 0 );
856 }
857 else
858 {
859 m_trapDelta.ChangeValue( m_previewPad->GetDelta( m_editLayer ).y );
860 m_trapAxisCtrl->SetSelection( 1 );
861 }
862
863 switch( m_previewPad->GetShape( m_editLayer ) )
864 {
865 default:
866 case PAD_SHAPE::CIRCLE: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_CIRCLE ); break;
867 case PAD_SHAPE::OVAL: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_OVAL ); break;
868 case PAD_SHAPE::RECTANGLE: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_RECT ); break;
871
873 if( m_previewPad->GetRoundRectRadiusRatio( m_editLayer ) > 0.0 )
875 else
877 break;
878
880 if( m_previewPad->GetAnchorPadShape( m_editLayer ) == PAD_SHAPE::RECTANGLE )
882 else
884 break;
885 }
886
887 int chamferPositions = m_previewPad->GetChamferPositions( m_editLayer );
888
889 m_cbTopLeft->SetValue( chamferPositions & RECT_CHAMFER_TOP_LEFT );
890 m_cbTopLeft1->SetValue( chamferPositions & RECT_CHAMFER_TOP_LEFT );
891 m_cbTopRight->SetValue( chamferPositions & RECT_CHAMFER_TOP_RIGHT );
892 m_cbTopRight1->SetValue( chamferPositions & RECT_CHAMFER_TOP_RIGHT );
893 m_cbBottomLeft->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_LEFT );
894 m_cbBottomLeft1->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_LEFT );
895 m_cbBottomRight->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_RIGHT );
896 m_cbBottomRight1->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_RIGHT );
897
899}
900
901
903{
904 // NOTE: synchronize changes here with DIALOG_TRACK_VIA_PROPERTIES::afterPadstackModeChanged
905
906 wxCHECK_MSG( m_board, /* void */, "Expected valid board in afterPadstackModeChanged" );
907 m_cbEditLayer->Clear();
908
909 switch( m_previewPad->Padstack().Mode() )
910 {
912 m_cbPadstackMode->SetSelection( 0 );
913 m_cbEditLayer->Append( m_board->GetLayerName( F_Cu ) );
914 m_cbEditLayer->Disable();
916 m_editLayerCtrlMap = { { 0, F_Cu } };
917 break;
918
920 {
921 m_cbPadstackMode->SetSelection( 1 );
922 m_cbEditLayer->Enable();
923
924 std::vector choices = {
925 m_board->GetLayerName( F_Cu ),
926 _( "Inner Layers" ),
927 m_board->GetLayerName( B_Cu )
928 };
929
930 m_cbEditLayer->Append( choices );
931
933 { 0, F_Cu },
935 { 2, B_Cu }
936 };
937
938 if( m_editLayer != F_Cu && m_editLayer != B_Cu )
940
941 break;
942 }
943
945 {
946 m_cbPadstackMode->SetSelection( 2 );
947 m_cbEditLayer->Enable();
948 LSET layers = LSET::AllCuMask() & m_board->GetEnabledLayers();
949
950 for( PCB_LAYER_ID layer : layers.UIOrder() )
951 {
952 int idx = m_cbEditLayer->Append( m_board->GetLayerName( layer ) );
953 m_editLayerCtrlMap[idx] = layer;
954 }
955
956 break;
957 }
958 }
959
960 for( const auto& [idx, layer] : m_editLayerCtrlMap )
961 {
962 if( layer == m_editLayer )
963 {
964 m_cbEditLayer->SetSelection( idx );
965 break;
966 }
967 }
968}
969
970
971void DIALOG_PAD_PROPERTIES::OnResize( wxSizeEvent& event )
972{
973 redraw();
974 event.Skip();
975}
976
977
978void DIALOG_PAD_PROPERTIES::onChangePadMode( wxCommandEvent& event )
979{
981
982 KIGFX::VIEW* view = m_padPreviewGAL->GetView();
983
984 // fix the pad render mode (filled/not filled)
985 auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
986
987 settings->m_ForcePadSketchModeOn = m_cbShowPadOutline->IsChecked();
988 settings->SetHighContrast( false );
989 settings->m_ContrastModeDisplay = HIGH_CONTRAST_MODE::NORMAL;
990
991 redraw();
992}
993
994
996{
997 switch( m_PadShapeSelector->GetSelection() )
998 {
1000 case CHOICE_SHAPE_OVAL:
1001 case CHOICE_SHAPE_RECT:
1002 m_shapePropsBook->SetSelection( 0 );
1003 break;
1004
1006 m_shapePropsBook->SetSelection( 1 );
1007 break;
1008
1010 {
1011 m_shapePropsBook->SetSelection( 2 );
1012
1013 // Reasonable defaults
1014 if( m_previewPad->GetRoundRectRadiusRatio( m_editLayer ) == 0.0 )
1015 {
1016 const double ipcRadiusRatio =
1018 m_cornerRatio.ChangeDoubleValue( ipcRadiusRatio * 100 );
1019 }
1020
1021 break;
1022 }
1023
1025 m_shapePropsBook->SetSelection( 3 );
1026
1027 // Reasonable default
1028 if( m_previewPad->GetChamferRectRatio( m_editLayer ) == 0.0 )
1029 m_previewPad->SetChamferRectRatio( m_editLayer, 0.2 );
1030
1031 // Ensure the displayed value is up to date:
1032 m_chamferRatio.ChangeDoubleValue( m_previewPad->GetChamferRectRatio( m_editLayer ) * 100.0 );
1033
1034 // A reasonable default is one corner chamfered (usual for some SMD pads).
1035 if( !m_cbTopLeft->GetValue() && !m_cbTopRight->GetValue()
1036 && !m_cbBottomLeft->GetValue() && !m_cbBottomRight->GetValue() )
1037 {
1038 m_cbTopLeft->SetValue( true );
1039 m_cbTopRight->SetValue( false );
1040 m_cbBottomLeft->SetValue( false );
1041 m_cbBottomRight->SetValue( false );
1042 }
1043
1044 break;
1045
1047 m_shapePropsBook->SetSelection( 4 );
1048
1049 // Reasonable defaults
1050 if( m_previewPad->GetRoundRectRadiusRatio( m_editLayer ) == 0.0
1051 && m_previewPad->GetChamferRectRatio( m_editLayer ) == 0.0 )
1052 {
1053 const double ipcRadiusRatio =
1055 m_previewPad->SetRoundRectRadiusRatio( m_editLayer, ipcRadiusRatio );
1056 m_previewPad->SetChamferRectRatio( m_editLayer, 0.2 );
1057 }
1058
1059 // Ensure the displayed values are up to date:
1060 m_mixedChamferRatio.ChangeDoubleValue( m_previewPad->GetChamferRectRatio( m_editLayer ) * 100.0 );
1061 m_mixedCornerRatio.ChangeDoubleValue( m_previewPad->GetRoundRectRadiusRatio( m_editLayer ) * 100.0 );
1062 break;
1063
1064 case CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR: // PAD_SHAPE::CUSTOM, circular anchor
1065 case CHOICE_SHAPE_CUSTOM_RECT_ANCHOR: // PAD_SHAPE::CUSTOM, rect anchor
1066 m_shapePropsBook->SetSelection( 0 );
1067 break;
1068 }
1069
1070 // Note: must do this before enabling/disabling m_sizeY as we're using that as a flag to see
1071 // what the last shape was.
1072 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CIRCLE )
1073 {
1074 if( m_sizeYCtrl->IsEnabled() && m_spokeAngle.GetAngleValue() == ANGLE_90 )
1075 m_spokeAngle.SetAngleValue( ANGLE_45 );
1076 }
1077 else
1078 {
1079 if( !m_sizeYCtrl->IsEnabled() && m_spokeAngle.GetAngleValue() == ANGLE_45 )
1080 m_spokeAngle.SetAngleValue( ANGLE_90 );
1081 }
1082
1083 // Readjust props book size
1084 wxSize size = m_shapePropsBook->GetSize();
1085 size.y = m_shapePropsBook->GetPage( m_shapePropsBook->GetSelection() )->GetBestSize().y;
1086 m_shapePropsBook->SetMaxSize( size );
1087
1088 m_sizeY.Enable( m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CIRCLE
1090
1091 m_offsetShapeOpt->Enable( m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CIRCLE );
1092
1093 if( !m_offsetShapeOpt->IsEnabled() )
1094 m_offsetShapeOpt->SetValue( false );
1095
1096 // Show/hide controls depending on m_offsetShapeOpt being enabled
1097 m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
1098 m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
1099
1102
1103 for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
1104 m_notebook->GetPage( i )->Layout();
1105
1106 // Resize the dialog if its height is too small to show all widgets:
1107 if( m_MainSizer->GetSize().y < m_MainSizer->GetMinSize().y )
1108 m_MainSizer->SetSizeHints( this );
1109
1111 redraw();
1112
1113 if( m_initialized )
1114 OnModify();
1115}
1116
1117
1119{
1122 redraw();
1123
1124 if( m_initialized )
1125 OnModify();
1126}
1127
1128
1129void DIALOG_PAD_PROPERTIES::PadOrientEvent( wxCommandEvent& event )
1130{
1132 redraw();
1133
1134 if( m_initialized )
1135 OnModify();
1136}
1137
1138
1140{
1141 m_rbCopperLayersSel->Clear();
1142
1143 switch( m_padType->GetSelection() )
1144 {
1145 case PTH_DLG_TYPE:
1146 m_rbCopperLayersSel->Append( _( "All copper layers" ) );
1147 m_rbCopperLayersSel->Append( wxString::Format( _( "%s, %s and connected layers" ),
1148 m_board->GetLayerName( F_Cu ),
1149 m_board->GetLayerName( B_Cu ) ) );
1150 m_rbCopperLayersSel->Append( _( "Connected layers only" ) );
1151 m_rbCopperLayersSel->Append( _( "None" ) );
1152 break;
1153
1154 case NPTH_DLG_TYPE:
1155 m_rbCopperLayersSel->Append( wxString::Format( _( "%s and %s" ),
1156 m_board->GetLayerName( F_Cu ),
1157 m_board->GetLayerName( B_Cu ) ) );
1158 m_rbCopperLayersSel->Append( m_board->GetLayerName( F_Cu ) );
1159 m_rbCopperLayersSel->Append( m_board->GetLayerName( B_Cu ) );
1160 m_rbCopperLayersSel->Append( _( "None" ) );
1161 break;
1162
1163 case SMD_DLG_TYPE:
1164 case CONN_DLG_TYPE:
1165 m_rbCopperLayersSel->Append( m_board->GetLayerName( F_Cu ) );
1166 m_rbCopperLayersSel->Append( m_board->GetLayerName( B_Cu ) );
1167 break;
1168
1169 case APERTURE_DLG_TYPE:
1170 m_rbCopperLayersSel->Append( _( "None" ) );
1171 break;
1172 }
1173}
1174
1175
1176void DIALOG_PAD_PROPERTIES::PadTypeSelected( wxCommandEvent& event )
1177{
1178 bool hasHole = true;
1179 bool hasConnection = true;
1180 bool hasProperty = true;
1181
1182 switch( m_padType->GetSelection() )
1183 {
1184 case PTH_DLG_TYPE: hasHole = true; hasConnection = true; hasProperty = true; break;
1185 case SMD_DLG_TYPE: hasHole = false; hasConnection = true; hasProperty = true; break;
1186 case CONN_DLG_TYPE: hasHole = false; hasConnection = true; hasProperty = true; break;
1187 case NPTH_DLG_TYPE: hasHole = true; hasConnection = false; hasProperty = false; break;
1188 case APERTURE_DLG_TYPE: hasHole = false; hasConnection = false; hasProperty = true; break;
1189 }
1190
1191 // Update Layers dropdown list and selects the "best" layer set for the new pad type:
1192 updatePadLayersList( {}, m_previewPad->GetRemoveUnconnected(),
1193 m_previewPad->GetKeepTopBottom() );
1194
1195 m_gbSizerHole->Show( hasHole );
1196 m_staticline71->Show( hasHole );
1197
1198 if( !hasHole )
1199 {
1200 m_holeX.ChangeValue( 0 );
1201 m_holeY.ChangeValue( 0 );
1202 }
1203 else if( m_holeX.GetValue() == 0 )
1204 {
1205 if( m_currentPad )
1206 {
1207 m_holeX.ChangeValue( m_currentPad->GetDrillSize().x );
1208 m_holeY.ChangeValue( m_currentPad->GetDrillSize().y );
1209 }
1210 else
1211 {
1212 m_holeX.ChangeValue( pcbIUScale.mmToIU( DEFAULT_PAD_DRILL_DIAMETER_MM ) );
1213 }
1214 }
1215
1216 if( !hasConnection )
1217 {
1218 m_padNumCtrl->ChangeValue( wxEmptyString );
1219 m_padNetSelector->SetSelectedNetcode( 0 );
1220 m_padToDieOpt->SetValue( false );
1221 m_padToDieDelayOpt->SetValue( false );
1222 }
1223 else if( m_padNumCtrl->GetValue().IsEmpty() && m_currentPad )
1224 {
1225 m_padNumCtrl->ChangeValue( m_currentPad->GetNumber() );
1226 m_padNetSelector->SetSelectedNetcode( m_currentPad->GetNetCode() );
1227 }
1228
1229 if( !hasProperty )
1230 m_choiceFabProperty->SetSelection( 0 );
1231
1232 m_choiceFabProperty->Enable( hasProperty );
1233
1235
1236 // For now, padstack controls only enabled for PTH pads
1237 bool enablePadstack = m_padType->GetSelection() == PTH_DLG_TYPE;
1238 m_padstackControls->Show( enablePadstack );
1239
1240 if( !enablePadstack )
1241 {
1242 m_editLayer = F_Cu;
1244 }
1245
1246 // Layout adjustment is needed if the hole details got shown/hidden
1247 m_LeftBoxSizer->Layout();
1248 redraw();
1249
1250 if( m_initialized )
1251 OnModify();
1252}
1253
1254
1255void DIALOG_PAD_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
1256{
1257 bool hasHole = true;
1258 bool hasConnection = true;
1259
1260 switch( m_padType->GetSelection() )
1261 {
1262 case PTH_DLG_TYPE: /* PTH */ hasHole = true; hasConnection = true; break;
1263 case SMD_DLG_TYPE: /* SMD */ hasHole = false; hasConnection = true; break;
1264 case CONN_DLG_TYPE: /* CONN */ hasHole = false; hasConnection = true; break;
1265 case NPTH_DLG_TYPE: /* NPTH */ hasHole = true; hasConnection = false; break;
1266 case APERTURE_DLG_TYPE: /* Aperture */ hasHole = false; hasConnection = false; break;
1267 }
1268
1269 // Enable/disable hole controls
1270 m_holeShapeLabel->Enable( hasHole );
1271 m_holeShapeCtrl->Enable( hasHole );
1272 m_holeX.Enable( hasHole );
1273 m_holeY.Enable( hasHole && m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_OVAL );
1274
1275 // Enable/disable number and net
1276 m_padNumLabel->Enable( hasConnection );
1277 m_padNumCtrl->Enable( hasConnection );
1278
1279 if( m_padNetLabel->IsShown() )
1280 {
1281 m_padNetLabel->Enable( hasConnection && m_canEditNetName && m_currentPad );
1282 m_padNetSelector->Enable( hasConnection && m_canEditNetName && m_currentPad );
1283 }
1284
1285 // Enable/disable pad length-to-die
1286 m_padToDieOpt->Enable( hasConnection );
1287 m_padToDieDelayOpt->Enable( hasConnection );
1288
1289 if( !m_padToDieOpt->IsEnabled() )
1290 m_padToDieOpt->SetValue( false );
1291
1292 if( !m_padToDieDelayOpt->IsEnabled() )
1293 m_padToDieDelayOpt->SetValue( false );
1294
1295 // We can show/hide this here because it doesn't require the layout to be refreshed.
1296 // All the others have to be done in their event handlers because doing a layout here
1297 // causes infinite looping on MSW.
1298 m_padToDie.Show( m_padToDieOpt->GetValue() );
1299 m_padToDieDelay.Show( m_padToDieDelayOpt->GetValue() );
1300
1301 // Enable/disable Copper Layers control
1302 m_rbCopperLayersSel->Enable( m_padType->GetSelection() != APERTURE_DLG_TYPE );
1303
1304 LSET cu_set = m_previewPad->GetLayerSet() & LSET::AllCuMask();
1305
1306 switch( m_padType->GetSelection() )
1307 {
1308 case PTH_DLG_TYPE:
1309 if( !cu_set.any() )
1310 m_stackupImagesBook->SetSelection( 3 );
1311 else if( !m_previewPad->GetRemoveUnconnected() )
1312 m_stackupImagesBook->SetSelection( 0 );
1313 else if( m_previewPad->GetKeepTopBottom() )
1314 m_stackupImagesBook->SetSelection( 1 );
1315 else
1316 m_stackupImagesBook->SetSelection( 2 );
1317
1318 break;
1319
1320 case NPTH_DLG_TYPE:
1321 if( cu_set.test( F_Cu ) && cu_set.test( B_Cu ) )
1322 m_stackupImagesBook->SetSelection( 4 );
1323 else if( cu_set.test( F_Cu ) )
1324 m_stackupImagesBook->SetSelection( 5 );
1325 else if( cu_set.test( B_Cu ) )
1326 m_stackupImagesBook->SetSelection( 6 );
1327 else
1328 m_stackupImagesBook->SetSelection( 7 );
1329
1330 break;
1331
1332 case SMD_DLG_TYPE:
1333 case CONN_DLG_TYPE:
1334 case APERTURE_DLG_TYPE:
1335 m_stackupImagesBook->ChangeSelection( 3 );
1336 break;
1337 }
1338
1339 m_legacyTeardropsWarning->Show( m_board->LegacyTeardrops() );
1340}
1341
1342
1344{
1345 event.Enable( !m_board->LegacyTeardrops() );
1346}
1347
1348
1350{
1351 bool isOnCopperLayer = ( m_previewPad->GetLayerSet() & LSET::AllCuMask() ).any();
1352 m_nonCopperWarningBook->ChangeSelection( isOnCopperLayer ? 0 : 1 );
1353}
1354
1355
1356void DIALOG_PAD_PROPERTIES::updatePadLayersList( LSET layer_mask, bool remove_unconnected,
1357 bool keep_top_bottom )
1358{
1360
1361 switch( m_padType->GetSelection() )
1362 {
1363 case PTH_DLG_TYPE:
1364 if( !layer_mask.any() )
1365 layer_mask = PAD::PTHMask();
1366
1367 if( !( layer_mask & LSET::AllCuMask() ).any() )
1368 m_rbCopperLayersSel->SetSelection( 3 );
1369 else if( !remove_unconnected )
1370 m_rbCopperLayersSel->SetSelection( 0 );
1371 else if( keep_top_bottom )
1372 m_rbCopperLayersSel->SetSelection( 1 );
1373 else
1374 m_rbCopperLayersSel->SetSelection( 2 );
1375
1376 break;
1377
1378 case SMD_DLG_TYPE:
1379 if( !layer_mask.any() )
1380 layer_mask = PAD::SMDMask();
1381
1382 if( layer_mask.test( F_Cu ) )
1383 m_rbCopperLayersSel->SetSelection( 0 );
1384 else
1385 m_rbCopperLayersSel->SetSelection( 1 );
1386
1387 break;
1388
1389 case CONN_DLG_TYPE:
1390 if( !layer_mask.any() )
1391 layer_mask = PAD::ConnSMDMask();
1392
1393 if( layer_mask.test( F_Cu ) )
1394 m_rbCopperLayersSel->SetSelection( 0 );
1395 else
1396 m_rbCopperLayersSel->SetSelection( 1 );
1397
1398 break;
1399
1400 case NPTH_DLG_TYPE:
1401 if( !layer_mask.any() )
1402 layer_mask = PAD::UnplatedHoleMask();
1403
1404 if( layer_mask.test( F_Cu ) && layer_mask.test( B_Cu ) )
1405 m_rbCopperLayersSel->SetSelection( 0 );
1406 else if( layer_mask.test( F_Cu ) )
1407 m_rbCopperLayersSel->SetSelection( 1 );
1408 else if( layer_mask.test( B_Cu ) )
1409 m_rbCopperLayersSel->SetSelection( 2 );
1410 else
1411 m_rbCopperLayersSel->SetSelection( 3 );
1412
1413 break;
1414
1415 case APERTURE_DLG_TYPE:
1416 if( !layer_mask.any() )
1417 layer_mask = PAD::ApertureMask();
1418
1419 m_rbCopperLayersSel->SetSelection( 0 );
1420 break;
1421 }
1422
1423 m_layerFrontAdhesive->SetValue( layer_mask[F_Adhes] );
1424 m_layerBackAdhesive->SetValue( layer_mask[B_Adhes] );
1425
1426 m_layerFrontPaste->SetValue( layer_mask[F_Paste] );
1427 m_layerBackPaste->SetValue( layer_mask[B_Paste] );
1428
1429 m_layerFrontSilk->SetValue( layer_mask[F_SilkS] );
1430 m_layerBackSilk->SetValue( layer_mask[B_SilkS] );
1431
1432 m_layerFrontMask->SetValue( layer_mask[F_Mask] );
1433 m_layerBackMask->SetValue( layer_mask[B_Mask] );
1434
1435 m_layerECO1->SetValue( layer_mask[Eco1_User] );
1436 m_layerECO2->SetValue( layer_mask[Eco2_User] );
1437
1438 m_layerUserDwgs->SetValue( layer_mask[Dwgs_User] );
1439}
1440
1441
1443{
1444 bool retVal = DIALOG_SHIM::Show( aShow );
1445
1446 if( aShow )
1447 {
1448 // It *should* work to set the stackup bitmap in the constructor, but it doesn't.
1449 // wxWidgets needs to have these set when the panel is visible for some reason.
1450 // https://gitlab.com/kicad/code/kicad/-/issues/5534
1458
1459 Layout();
1460 }
1461
1462 return retVal;
1463}
1464
1465
1466void DIALOG_PAD_PROPERTIES::OnSetCopperLayers( wxCommandEvent& event )
1467{
1469 redraw();
1470
1471 if( m_initialized )
1472 OnModify();
1473}
1474
1475
1476void DIALOG_PAD_PROPERTIES::OnSetLayers( wxCommandEvent& event )
1477{
1479 redraw();
1480
1481 if( m_initialized )
1482 OnModify();
1483}
1484
1485
1487{
1489
1490 wxArrayString error_msgs;
1491 wxArrayString warning_msgs;
1492
1493 m_previewPad->CheckPad( m_parentFrame, true,
1494 [&]( int errorCode, const wxString& msg )
1495 {
1496 if( errorCode == DRCE_PADSTACK_INVALID )
1497 error_msgs.Add( _( "Error: " ) + msg );
1498 else if( errorCode == DRCE_PADSTACK )
1499 warning_msgs.Add( _( "Warning: " ) + msg );
1500 else if( errorCode == DRCE_PAD_TH_WITH_NO_HOLE )
1501 error_msgs.Add( _( "Error: Through hole pad has no hole." ) );
1502 } );
1503
1504 if( error_msgs.GetCount() || warning_msgs.GetCount() )
1505 {
1506 wxString title = error_msgs.GetCount() ? _( "Pad Properties Errors" )
1507 : _( "Pad Properties Warnings" );
1508 HTML_MESSAGE_BOX dlg( this, title );
1509
1510 wxArrayString msgs = error_msgs;
1511
1512 for( const wxString& msg : warning_msgs )
1513 msgs.Add( msg );
1514
1515 dlg.ListSet( msgs );
1516
1517 dlg.ShowModal();
1518 }
1519
1520 return error_msgs.GetCount() == 0;
1521}
1522
1523
1525{
1526 if( !m_initialized )
1527 return;
1528
1529 KIGFX::VIEW* view = m_padPreviewGAL->GetView();
1530 KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( view->GetPainter() );
1531 KIGFX::PCB_RENDER_SETTINGS* settings = painter->GetSettings();
1532
1533 m_padPreviewGAL->StopDrawing();
1534
1535 // The layer used to place primitive items selected when editing custom pad shapes
1536 // we use here a layer never used in a pad:
1537 #define SELECTED_ITEMS_LAYER Dwgs_User
1538
1539 view->ClearTopLayers();
1541 view->SetTopLayer( m_editLayer );
1543
1544 static const std::vector<int> topLayers = {
1549 };
1550
1551 for( int layer : topLayers )
1552 view->SetTopLayer( layer );
1553
1554 m_axisOrigin->SetPosition( m_previewPad->GetPosition() );
1555
1556 view->Update( m_previewPad );
1557
1558 // delete previous items if highlight list
1559 while( m_highlight.size() )
1560 {
1561 delete m_highlight.back(); // the dtor also removes item from view
1562 m_highlight.pop_back();
1563 }
1564
1565 BOX2I bbox = m_previewPad->ViewBBox();
1566
1567 if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
1568 {
1569 // The origin always goes in the middle of the canvas; we want offsetting the pad
1570 // shape to move the pad, not the hole
1571 bbox.Move( -m_previewPad->GetPosition() );
1572 int maxXExtent = std::max( abs( bbox.GetLeft() ), abs( bbox.GetRight() ) );
1573 int maxYExtent = std::max( abs( bbox.GetTop() ), abs( bbox.GetBottom() ) );
1574
1575 // Don't blow up the GAL on too-large numbers
1576 if( maxXExtent > INT_MAX / 4 )
1577 maxXExtent = INT_MAX / 4;
1578
1579 if( maxYExtent > INT_MAX / 4 )
1580 maxYExtent = INT_MAX / 4;
1581
1582 BOX2D viewBox( m_previewPad->GetPosition(), {0, 0} );
1583 BOX2D canvasBox( m_previewPad->GetPosition(), {0, 0} );
1584 viewBox.Inflate( maxXExtent * 1.4, maxYExtent * 1.4 ); // add a margin
1585 canvasBox.Inflate( maxXExtent * 2.0, maxYExtent * 2.0 );
1586
1587 view->SetBoundary( canvasBox );
1588
1589 // Autozoom
1590 view->SetViewport( viewBox );
1591
1592 m_padPreviewGAL->StartDrawing();
1593 m_padPreviewGAL->Refresh();
1594 }
1595}
1596
1597
1599{
1600 if( !wxDialog::TransferDataToWindow() )
1601 return false;
1602
1603 if( !m_panelGeneral->TransferDataToWindow() )
1604 return false;
1605
1606 if( !m_localSettingsPanel->TransferDataToWindow() )
1607 return false;
1608
1609 return true;
1610}
1611
1612
1614{
1615 BOARD_COMMIT commit( m_parent );
1616
1617 if( !wxDialog::TransferDataFromWindow() )
1618 return false;
1619
1620 if( !m_panelGeneral->TransferDataFromWindow() )
1621 return false;
1622
1623 if( !m_localSettingsPanel->TransferDataFromWindow() )
1624 return false;
1625
1626 if( !padValuesOK() )
1627 return false;
1628
1630 return false;
1631
1632 m_padPreviewGAL->StopDrawing();
1633
1634 PAD_TOOL* padTool = m_parent->GetToolManager()->GetTool<PAD_TOOL>();
1635 padTool->SetLastPadNumber( m_masterPad->GetNumber() );
1636
1637 // m_masterPad is a pattern: ensure there is no net for this pad:
1639
1640 if( !m_currentPad ) // Set current Pad parameters
1641 return true;
1642
1643 commit.Modify( m_currentPad );
1644
1645 // Update values
1646
1647 // transferDataToPad only handles the current edit layer, so m_masterPad isn't accurate
1648 // TODO(JE) this could be cleaner
1649 m_currentPad->SetPadstack( m_previewPad->Padstack() );
1650
1651 m_currentPad->SetAttribute( m_masterPad->GetAttribute() );
1652 m_currentPad->SetFPRelativeOrientation( m_masterPad->GetOrientation() );
1653 m_currentPad->SetPadToDieLength( m_masterPad->GetPadToDieLength() );
1654 m_currentPad->SetPadToDieDelay( m_masterPad->GetPadToDieDelay() );
1655 m_currentPad->SetLayerSet( m_masterPad->GetLayerSet() );
1656 m_currentPad->SetNumber( m_masterPad->GetNumber() );
1657
1658 int padNetcode = NETINFO_LIST::UNCONNECTED;
1659
1660 // For PAD_ATTRIB::NPTH, ensure there is no net name selected
1661 if( m_masterPad->GetAttribute() != PAD_ATTRIB::NPTH )
1662 padNetcode = m_padNetSelector->GetSelectedNetcode();
1663
1664 m_currentPad->SetNetCode( padNetcode );
1665
1666 m_currentPad->GetTeardropParams() = m_masterPad->GetTeardropParams();
1667
1668 // Set the fabrication property:
1669 m_currentPad->SetProperty( getSelectedProperty() );
1670
1671 // define the way the clearance area is defined in zones
1672 m_currentPad->SetCustomShapeInZoneOpt( m_masterPad->GetCustomShapeInZoneOpt() );
1673
1674 if( m_currentPad->GetParentFootprint() && m_currentPad->GetParentFootprint()->IsFlipped() )
1675 {
1676 // flip pad (up/down) around its position
1677 m_currentPad->Flip( m_currentPad->GetPosition(), FLIP_DIRECTION::TOP_BOTTOM );
1678 }
1679
1680 m_currentPad->SetPosition( m_masterPad->GetPosition() );
1681
1682 m_parent->SetMsgPanel( m_currentPad );
1683
1684 // redraw the area where the pad was
1685 m_parent->GetCanvas()->Refresh();
1686
1687 commit.Push( _( "Edit Pad Properties" ) );
1688
1689 return true;
1690}
1691
1692
1694{
1695 PAD_PROP prop = PAD_PROP::NONE;
1696
1697 switch( m_choiceFabProperty->GetSelection() )
1698 {
1699 case 0: prop = PAD_PROP::NONE; break;
1700 case 1: prop = PAD_PROP::BGA; break;
1701 case 2: prop = PAD_PROP::FIDUCIAL_LOCAL; break;
1702 case 3: prop = PAD_PROP::FIDUCIAL_GLBL; break;
1703 case 4: prop = PAD_PROP::TESTPOINT; break;
1704 case 5: prop = PAD_PROP::HEATSINK; break;
1705 case 6: prop = PAD_PROP::MECHANICAL; break;
1706 case 7: prop = PAD_PROP::CASTELLATED; break;
1707 case 8: prop = PAD_PROP::PRESSFIT; break;
1708 }
1709
1710 return prop;
1711}
1712
1713
1715{
1716 if( m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_CIRCLE )
1717 {
1718 m_holeXLabel->SetLabel( _( "Diameter:" ) );
1719 m_holeY.Show( false );
1720 }
1721 else
1722 {
1723 m_holeXLabel->SetLabel( _( "Hole size X:" ) );
1724 m_holeY.Show( true );
1725 }
1726
1727 m_holeXLabel->GetParent()->Layout();
1728}
1729
1730
1732{
1733 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CIRCLE
1735 {
1736 m_sizeXLabel->SetLabel( _( "Diameter:" ) );
1737 m_sizeY.Show( false );
1739 m_minTrackWidthHint->SetLabel( _( "d" ) );
1740 m_stLenPercentHint->SetLabel( _( "d" ) );
1741 m_stWidthPercentHint->SetLabel( _( "d" ) );
1742 }
1743 else
1744 {
1745 m_sizeXLabel->SetLabel( _( "Pad size X:" ) );
1746 m_sizeY.Show( true );
1748 m_minTrackWidthHint->SetLabel( _( "w" ) );
1749 m_stLenPercentHint->SetLabel( _( "w" ) );
1750 m_stWidthPercentHint->SetLabel( _( "w" ) );
1751 }
1752
1753 m_sizeXLabel->GetParent()->Layout();
1754 resetSize();
1755 Layout();
1756 m_MainSizer->Fit( this );
1757}
1758
1759
1761{
1762 if( !Validate() )
1763 return false;
1764
1765 if( !m_panelGeneral->Validate() )
1766 return false;
1767
1768 if( !m_localSettingsPanel->Validate() )
1769 return false;
1770
1771 if( !m_spokeWidth.Validate( 0, INT_MAX ) )
1772 return false;
1773
1774 switch( m_cbPadstackMode->GetSelection() )
1775 {
1776 default:
1777 case 0: aPad->Padstack().SetMode( PADSTACK::MODE::NORMAL ); break;
1778 case 1: aPad->Padstack().SetMode( PADSTACK::MODE::FRONT_INNER_BACK ); break;
1779 case 2: aPad->Padstack().SetMode( PADSTACK::MODE::CUSTOM ); break;
1780 }
1781
1782 aPad->SetAttribute( code_type[m_padType->GetSelection()] );
1783 aPad->SetShape( m_editLayer, code_shape[m_PadShapeSelector->GetSelection()] );
1784
1787 else
1789
1790 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::CUSTOM )
1792
1793 aPad->GetTeardropParams().m_Enabled = m_cbTeardrops->GetValue();
1800 aPad->GetTeardropParams().m_CurvedEdges = m_curvedEdges->GetValue();
1802
1803 // Read pad clearances values:
1804 if( m_clearance.IsNull() )
1805 aPad->SetLocalClearance( {} );
1806 else
1807 aPad->SetLocalClearance( m_clearance.GetIntValue() );
1808
1809 if( m_maskMargin.IsNull() )
1810 aPad->SetLocalSolderMaskMargin( {} );
1811 else
1812 aPad->SetLocalSolderMaskMargin( m_maskMargin.GetIntValue() );
1813
1814 if( m_pasteMargin.IsNull() )
1815 aPad->SetLocalSolderPasteMargin( {} );
1816 else
1817 aPad->SetLocalSolderPasteMargin( m_pasteMargin.GetIntValue() );
1818
1819 if( m_pasteMarginRatio.IsNull() )
1821 else
1822 aPad->SetLocalSolderPasteMarginRatio( m_pasteMarginRatio.GetDoubleValue() / 100.0 );
1823
1824 if( m_spokeWidth.IsNull() )
1826 else
1827 aPad->SetLocalThermalSpokeWidthOverride( m_spokeWidth.GetIntValue() );
1828
1829 if( m_thermalGap.IsNull() )
1830 aPad->SetLocalThermalGapOverride( {} );
1831 else
1832 aPad->SetLocalThermalGapOverride( m_thermalGap.GetIntValue() );
1833
1834 aPad->SetThermalSpokeAngle( m_spokeAngle.GetAngleValue() );
1835
1836 // And rotation
1837 aPad->SetOrientation( m_pad_orientation.GetAngleValue() );
1838
1839 switch( m_ZoneConnectionChoice->GetSelection() )
1840 {
1841 default:
1842 case 0: aPad->SetLocalZoneConnection( ZONE_CONNECTION::INHERITED ); break;
1843 case 1: aPad->SetLocalZoneConnection( ZONE_CONNECTION::FULL ); break;
1844 case 2: aPad->SetLocalZoneConnection( ZONE_CONNECTION::THERMAL ); break;
1845 case 3: aPad->SetLocalZoneConnection( ZONE_CONNECTION::NONE ); break;
1846 }
1847
1848 VECTOR2I pos( m_posX.GetIntValue(), m_posY.GetIntValue() );
1849
1850 if( FOOTPRINT* fp = aPad->GetParentFootprint() )
1851 {
1852 pos -= fp->GetPosition();
1853 RotatePoint( pos, -fp->GetOrientation() );
1854 }
1855
1856 aPad->SetPosition( pos );
1857
1858 if( m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_CIRCLE )
1859 {
1861 aPad->SetDrillSize( VECTOR2I( m_holeX.GetIntValue(), m_holeX.GetIntValue() ) );
1862 }
1863 else
1864 {
1866 aPad->SetDrillSize( VECTOR2I( m_holeX.GetIntValue(), m_holeY.GetIntValue() ) );
1867 }
1868
1869 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::CIRCLE )
1870 aPad->SetSize( m_editLayer, VECTOR2I( m_sizeX.GetIntValue(), m_sizeX.GetIntValue() ) );
1871 else
1872 aPad->SetSize( m_editLayer, VECTOR2I( m_sizeX.GetIntValue(), m_sizeY.GetIntValue() ) );
1873
1874 // For a trapezoid, test delta value (be sure delta is not too large for pad size)
1875 // remember DeltaSize.x is the Y size variation
1876 bool error = false;
1877 VECTOR2I delta( 0, 0 );
1878
1879 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::TRAPEZOID )
1880 {
1881 // For a trapezoid, only one of delta.x or delta.y is not 0, depending on axis.
1882 if( m_trapAxisCtrl->GetSelection() == 0 )
1883 delta.x = m_trapDelta.GetIntValue();
1884 else
1885 delta.y = m_trapDelta.GetIntValue();
1886
1887 if( delta.x < 0 && delta.x < -aPad->GetSize( m_editLayer ).y )
1888 {
1889 delta.x = -aPad->GetSize( m_editLayer ).y + 2;
1890 error = true;
1891 }
1892
1893 if( delta.x > 0 && delta.x > aPad->GetSize( m_editLayer ).y )
1894 {
1895 delta.x = aPad->GetSize( m_editLayer ).y - 2;
1896 error = true;
1897 }
1898
1899 if( delta.y < 0 && delta.y < -aPad->GetSize( m_editLayer ).x )
1900 {
1901 delta.y = -aPad->GetSize( m_editLayer ).x + 2;
1902 error = true;
1903 }
1904
1905 if( delta.y > 0 && delta.y > aPad->GetSize( m_editLayer ).x )
1906 {
1907 delta.y = aPad->GetSize( m_editLayer ).x - 2;
1908 error = true;
1909 }
1910 }
1911
1912 aPad->SetDelta( m_editLayer, delta );
1913
1914 if( m_offsetShapeOpt->GetValue() )
1915 aPad->SetOffset( m_editLayer, VECTOR2I( m_offsetX.GetIntValue(), m_offsetY.GetIntValue() ) );
1916 else
1917 aPad->SetOffset( m_editLayer, VECTOR2I() );
1918
1919 // Read pad length die
1920 if( m_padToDieOpt->GetValue() )
1921 aPad->SetPadToDieLength( m_padToDie.GetIntValue() );
1922 else
1923 aPad->SetPadToDieLength( 0 );
1924
1925 if( m_padToDieDelayOpt->GetValue() )
1926 aPad->SetPadToDieDelay( m_padToDieDelay.GetIntValue() );
1927 else
1928 aPad->SetPadToDieDelay( 0 );
1929
1930 aPad->SetNumber( m_padNumCtrl->GetValue() );
1931 aPad->SetNetCode( m_padNetSelector->GetSelectedNetcode() );
1932
1933 int chamfers = 0;
1934
1935 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_RECT )
1936 {
1937 if( m_cbTopLeft->GetValue() )
1938 chamfers |= RECT_CHAMFER_TOP_LEFT;
1939
1940 if( m_cbTopRight->GetValue() )
1941 chamfers |= RECT_CHAMFER_TOP_RIGHT;
1942
1943 if( m_cbBottomLeft->GetValue() )
1944 chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1945
1946 if( m_cbBottomRight->GetValue() )
1947 chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1948 }
1949 else if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT )
1950 {
1951 if( m_cbTopLeft1->GetValue() )
1952 chamfers |= RECT_CHAMFER_TOP_LEFT;
1953
1954 if( m_cbTopRight1->GetValue() )
1955 chamfers |= RECT_CHAMFER_TOP_RIGHT;
1956
1957 if( m_cbBottomLeft1->GetValue() )
1958 chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1959
1960 if( m_cbBottomRight1->GetValue() )
1961 chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1962 }
1963
1964 aPad->SetChamferPositions( m_editLayer, chamfers );
1965
1966 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::CUSTOM )
1967 {
1968 // The pad custom has a "anchor pad" (a basic shape: round or rect pad)
1969 // that is the minimal area of this pad, and is useful to ensure a hole
1970 // diameter is acceptable, and is used in Gerber files as flashed area
1971 // reference
1973 aPad->SetSize( m_editLayer, VECTOR2I( m_sizeX.GetIntValue(), m_sizeX.GetIntValue() ) );
1974 }
1975
1976 // Define the way the clearance area is defined in zones. Since all non-custom pad
1977 // shapes are convex to begin with, this really only makes any difference for custom
1978 // pad shapes.
1979 aPad->SetCustomShapeInZoneOpt( m_ZoneCustomPadShape->GetSelection() == 0 ?
1982
1983 switch( aPad->GetAttribute() )
1984 {
1985 case PAD_ATTRIB::PTH:
1986 break;
1987
1988 case PAD_ATTRIB::CONN:
1989 case PAD_ATTRIB::SMD:
1990 // SMD and PAD_ATTRIB::CONN has no hole.
1991 // basically, SMD and PAD_ATTRIB::CONN are same type of pads
1992 // PAD_ATTRIB::CONN has just a default non technical layers that differs from SMD
1993 // and are intended to be used in virtual edge board connectors
1994 // However we can accept a non null offset,
1995 // mainly to allow complex pads build from a set of basic pad shapes
1996 aPad->SetDrillSize( VECTOR2I( 0, 0 ) );
1997 break;
1998
1999 case PAD_ATTRIB::NPTH:
2000 // Mechanical purpose only:
2001 // no net name, no pad name allowed
2002 aPad->SetNumber( wxEmptyString );
2004 break;
2005
2006 default:
2007 wxFAIL_MSG( wxT( "DIALOG_PAD_PROPERTIES::transferDataToPad: unknown pad type" ) );
2008 break;
2009 }
2010
2011 if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::ROUNDRECT )
2012 {
2013 aPad->SetRoundRectRadiusRatio( m_editLayer, m_cornerRatio.GetDoubleValue() / 100.0 );
2014 }
2015 else if( aPad->GetShape( m_editLayer ) == PAD_SHAPE::CHAMFERED_RECT )
2016 {
2018 {
2019 aPad->SetChamferRectRatio( m_editLayer, m_mixedChamferRatio.GetDoubleValue() / 100.0 );
2020 aPad->SetRoundRectRadiusRatio( m_editLayer, m_mixedCornerRatio.GetDoubleValue() / 100.0 );
2021 }
2022 else // Choice is CHOICE_SHAPE_CHAMFERED_RECT, no rounded corner
2023 {
2024 aPad->SetChamferRectRatio( m_editLayer, m_chamferRatio.GetDoubleValue() / 100.0 );
2026 }
2027 }
2028
2030
2031 LSET padLayerMask = LSET();
2032 int copperLayersChoice = m_rbCopperLayersSel->GetSelection();
2033
2035
2036 switch( m_padType->GetSelection() )
2037 {
2038 case PTH_DLG_TYPE:
2039 switch( copperLayersChoice )
2040 {
2041 case 0:
2042 // All copper layers
2043 padLayerMask |= LSET::AllCuMask();
2044 break;
2045
2046 case 1:
2047 // Front, back and connected
2048 padLayerMask |= LSET::AllCuMask();
2050 break;
2051
2052 case 2:
2053 // Connected only
2054 padLayerMask |= LSET::AllCuMask();
2056 break;
2057
2058 case 3:
2059 // No copper layers
2060 break;
2061 }
2062
2063 break;
2064
2065 case NPTH_DLG_TYPE:
2066 switch( copperLayersChoice )
2067 {
2068 case 0: padLayerMask.set( F_Cu ).set( B_Cu ); break;
2069 case 1: padLayerMask.set( F_Cu ); break;
2070 case 2: padLayerMask.set( B_Cu ); break;
2071 default: break;
2072 }
2073
2074 break;
2075
2076 case SMD_DLG_TYPE:
2077 case CONN_DLG_TYPE:
2078 switch( copperLayersChoice )
2079 {
2080 case 0: padLayerMask.set( F_Cu ); break;
2081 case 1: padLayerMask.set( B_Cu ); break;
2082 }
2083
2084 break;
2085
2086 case APERTURE_DLG_TYPE:
2087 // no copper layers
2088 break;
2089 }
2090
2091 if( m_layerFrontAdhesive->GetValue() )
2092 padLayerMask.set( F_Adhes );
2093
2094 if( m_layerBackAdhesive->GetValue() )
2095 padLayerMask.set( B_Adhes );
2096
2097 if( m_layerFrontPaste->GetValue() )
2098 padLayerMask.set( F_Paste );
2099
2100 if( m_layerBackPaste->GetValue() )
2101 padLayerMask.set( B_Paste );
2102
2103 if( m_layerFrontSilk->GetValue() )
2104 padLayerMask.set( F_SilkS );
2105
2106 if( m_layerBackSilk->GetValue() )
2107 padLayerMask.set( B_SilkS );
2108
2109 if( m_layerFrontMask->GetValue() )
2110 padLayerMask.set( F_Mask );
2111
2112 if( m_layerBackMask->GetValue() )
2113 padLayerMask.set( B_Mask );
2114
2115 if( m_layerECO1->GetValue() )
2116 padLayerMask.set( Eco1_User );
2117
2118 if( m_layerECO2->GetValue() )
2119 padLayerMask.set( Eco2_User );
2120
2121 if( m_layerUserDwgs->GetValue() )
2122 padLayerMask.set( Dwgs_User );
2123
2124 aPad->SetLayerSet( padLayerMask );
2125
2126 return !error;
2127}
2128
2129
2130void DIALOG_PAD_PROPERTIES::OnOffsetCheckbox( wxCommandEvent& event )
2131{
2132 if( m_offsetShapeOpt->GetValue() )
2133 {
2134 m_offsetX.SetValue( m_previewPad->GetOffset( m_editLayer ).x );
2135 m_offsetY.SetValue( m_previewPad->GetOffset( m_editLayer ).y );
2136 }
2137
2138 // Show/hide controls depending on m_offsetShapeOpt being enabled
2139 m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
2140 m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
2141
2142 for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
2143 m_notebook->GetPage( i )->Layout();
2144
2145 OnValuesChanged( event );
2146}
2147
2148
2150{
2151 if( m_padToDieOpt->GetValue() && m_currentPad )
2152 m_padToDie.SetValue( m_currentPad->GetPadToDieLength() );
2153
2154 OnValuesChanged( event );
2155}
2156
2157
2159{
2160 if( m_padToDieDelayOpt->GetValue() && m_currentPad )
2161 m_padToDieDelay.SetValue( m_currentPad->GetPadToDieDelay() );
2162
2163 OnValuesChanged( event );
2164}
2165
2166
2167void DIALOG_PAD_PROPERTIES::onModify( wxSpinDoubleEvent& aEvent )
2168{
2169 if( m_initialized )
2170 OnModify();
2171}
2172
2173
2174void DIALOG_PAD_PROPERTIES::onModify( wxCommandEvent& aEvent )
2175{
2176 if( m_initialized )
2177 OnModify();
2178}
2179
2180
2181void DIALOG_PAD_PROPERTIES::OnValuesChanged( wxCommandEvent& event )
2182{
2183 if( m_initialized )
2184 {
2186 return;
2187
2188 // If the pad size has changed, update the displayed values for rounded rect pads.
2191
2192 redraw();
2193 OnModify();
2194 }
2195}
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:81
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:365
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:2638
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:62
@ DRCE_PADSTACK_INVALID
Definition drc_item.h:63
@ DRCE_PAD_TH_WITH_NO_HOLE
Definition drc_item.h:84
#define _(s)
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:413
static constexpr EDA_ANGLE ANGLE_45
Definition eda_angle.h:412
#define BRIGHTENED
item is drawn with a bright contour
#define SELECTED
Item was manually selected by the user.
@ 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:253
@ LAYER_LOCKED_ITEM_SHADOW
Shadow layer for locked items.
Definition layer_ids.h:306
@ LAYER_NON_PLATEDHOLES
Draw usual through hole vias.
Definition layer_ids.h:238
@ LAYER_PAD_PLATEDHOLES
to draw pad holes (plated)
Definition layer_ids.h:270
@ LAYER_PAD_HOLEWALLS
Definition layer_ids.h:296
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
@ B_Adhes
Definition layer_ids.h:103
@ Dwgs_User
Definition layer_ids.h:107
@ F_Paste
Definition layer_ids.h:104
@ F_Adhes
Definition layer_ids.h:102
@ B_Mask
Definition layer_ids.h:98
@ B_Cu
Definition layer_ids.h:65
@ Eco1_User
Definition layer_ids.h:109
@ F_Mask
Definition layer_ids.h:97
@ B_Paste
Definition layer_ids.h:105
@ F_SilkS
Definition layer_ids.h:100
@ Eco2_User
Definition layer_ids.h:110
@ B_SilkS
Definition layer_ids.h:101
@ F_Cu
Definition layer_ids.h:64
This file contains miscellaneous commonly used macros and functions.
@ 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