KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_pad_properties.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2013 Dick Hollenbeck, [email protected]
6 * Copyright (C) 2008-2013 Wayne Stambaugh <[email protected]>
7 * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27#include <base_units.h>
28#include <bitmaps.h>
29#include <board_commit.h>
30#include <board.h>
32#include <footprint.h>
33#include <confirm.h>
34#include <core/arraydim.h>
35#include <convert_basic_shapes_to_polygon.h> // for enum RECT_CHAMFER_POSITIONS definition
39#include <macros.h>
40#include <pad.h>
41#include <pcb_base_frame.h>
43#include <pcb_painter.h>
44#include <pcbnew_settings.h>
46#include <view/view_controls.h>
48#include <tool/tool_manager.h>
49#include <tools/pad_tool.h>
50#include <advanced_config.h> // for pad property feature management
51#include <wx/choicdlg.h>
52
54
55// list of pad shapes, ordered like the pad shape wxChoice in dialog.
57{
64 PAD_SHAPE::CHAMFERED_RECT, // choice = CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT
65 PAD_SHAPE::CUSTOM, // choice = CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
66 PAD_SHAPE::CUSTOM // choice = PAD_SHAPE::CUSTOM_RECT_ANCHOR
67};
68
69
70// the ordered index of the pad shape wxChoice in dialog.
71// keep it consistent with code_shape[] and dialog strings
73{
83};
84
85
87{
92 PAD_ATTRIB::SMD // Aperture pad :type SMD with no copper layers,
93 // only on tech layers (usually only on paste layer
94};
95
96
97// These define have the same value as the m_PadType wxChoice GetSelected() return value
98#define PTH_DLG_TYPE 0
99#define SMD_DLG_TYPE 1
100#define CONN_DLG_TYPE 2
101#define NPTH_DLG_TYPE 3
102#define APERTURE_DLG_TYPE 4
103
104
106{
107 DIALOG_PAD_PROPERTIES dlg( this, aPad );
108
109 dlg.ShowQuasiModal();
110}
111
112
115 m_parent( aParent ),
116 m_canUpdate( false ),
117 m_posX( aParent, m_posXLabel, m_posXCtrl, m_posXUnits ),
118 m_posY( aParent, m_posYLabel, m_posYCtrl, m_posYUnits ),
119 m_sizeX( aParent, m_sizeXLabel, m_sizeXCtrl, m_sizeXUnits ),
120 m_sizeY( aParent, m_sizeYLabel, m_sizeYCtrl, m_sizeYUnits ),
121 m_offsetX( aParent, m_offsetXLabel, m_offsetXCtrl, m_offsetXUnits ),
122 m_offsetY( aParent, m_offsetYLabel, m_offsetYCtrl, m_offsetYUnits ),
123 m_padToDie( aParent, m_padToDieLabel, m_padToDieCtrl, m_padToDieUnits ),
124 m_trapDelta( aParent, m_trapDeltaLabel, m_trapDeltaCtrl, m_trapDeltaUnits ),
125 m_cornerRadius( aParent, m_cornerRadiusLabel, m_cornerRadiusCtrl, m_cornerRadiusUnits ),
126 m_cornerRatio( aParent, m_cornerRatioLabel, m_cornerRatioCtrl, m_cornerRatioUnits ),
127 m_chamferRatio( aParent, m_chamferRatioLabel, m_chamferRatioCtrl, m_chamferRatioUnits ),
128 m_mixedCornerRatio( aParent, m_mixedCornerRatioLabel, m_mixedCornerRatioCtrl,
129 m_mixedCornerRatioUnits ),
130 m_mixedChamferRatio( aParent, m_mixedChamferRatioLabel, m_mixedChamferRatioCtrl,
131 m_mixedChamferRatioUnits ),
132 m_holeX( aParent, m_holeXLabel, m_holeXCtrl, m_holeXUnits ),
133 m_holeY( aParent, m_holeYLabel, m_holeYCtrl, m_holeYUnits ),
134 m_clearance( aParent, m_clearanceLabel, m_clearanceCtrl, m_clearanceUnits ),
135 m_maskMargin( aParent, m_maskMarginLabel, m_maskMarginCtrl, m_maskMarginUnits ),
136 m_pasteMargin( aParent, m_pasteMarginLabel, m_pasteMarginCtrl, m_pasteMarginUnits ),
137 m_pasteMarginRatio( aParent, m_pasteMarginRatioLabel, m_pasteMarginRatioCtrl,
138 m_pasteMarginRatioUnits ),
139 m_thermalGap( aParent, m_thermalGapLabel, m_thermalGapCtrl, m_thermalGapUnits ),
140 m_spokeWidth( aParent, m_spokeWidthLabel, m_spokeWidthCtrl, m_spokeWidthUnits ),
141 m_spokeAngle( aParent, m_spokeAngleLabel, m_spokeAngleCtrl, m_spokeAngleUnits ),
142 m_pad_orientation( aParent, m_PadOrientText, m_cb_padrotation, m_orientationUnits ),
143 m_teardropMaxLenSetting( aParent, m_stMaxLen, m_tcTdMaxLen, m_stMaxLenUnits ),
144 m_teardropMaxHeightSetting( aParent, m_stTdMaxSize, m_tcMaxHeight, m_stMaxHeightUnits )
145{
146 SetName( PAD_PROPERTIES_DLG_NAME );
147 m_isFpEditor = dynamic_cast<FOOTPRINT_EDIT_FRAME*>( aParent ) != nullptr;
148
149 m_currentPad = aPad; // aPad can be NULL, if the dialog is called
150 // from the footprint editor to set default pad setup
151
153
154 // Configure display origin transforms
157
160
162
163 m_FlippedWarningIcon->SetBitmap( KiBitmap( BITMAPS::dialog_warning ) );
164 m_nonCopperWarningIcon->SetBitmap( KiBitmap( BITMAPS::dialog_warning ) );
165 m_legacyTeardropsIcon->SetBitmap( KiBitmap( BITMAPS::dialog_warning ) );
166
168 m_previewPad = new PAD( (FOOTPRINT*) nullptr );
169
170 if( aPad )
171 {
172 SetTitle( _( "Pad Properties" ) );
173
174 *m_previewPad = *aPad;
177 }
178 else
179 {
180 SetTitle( _( "Default Pad Properties for Add Pad Tool" ) );
181
184 }
185
186 if( m_isFpEditor )
187 {
188 m_padNetLabel->Show( false );
189 m_padNetSelector->Show( false );
190 }
191
192 m_FlippedWarningSizer->Show( false );
193
194 // Pad needs to have a parent for painting; use the parent board for its design settings
195 if( !m_previewPad->GetParent() )
197
198 m_cornerRatio.SetUnits( EDA_UNITS::PERCENT );
199 m_chamferRatio.SetUnits( EDA_UNITS::PERCENT );
200 m_mixedCornerRatio.SetUnits( EDA_UNITS::PERCENT );
201 m_mixedChamferRatio.SetUnits( EDA_UNITS::PERCENT );
202 m_pad_orientation.SetUnits( EDA_UNITS::DEGREES );
204
205 m_spokeAngle.SetUnits( EDA_UNITS::DEGREES );
207
209
210 m_pasteMarginRatio.SetUnits( EDA_UNITS::PERCENT );
212
213 initValues();
214
215 wxFont infoFont = KIUI::GetInfoFont( this );
216 m_copperLayersLabel->SetFont( infoFont );
217 m_techLayersLabel->SetFont( infoFont );
218 m_parentInfo->SetFont( infoFont );
219 m_teardropShapeLabel->SetFont( infoFont );
220
221 infoFont.SetStyle( wxFONTSTYLE_ITALIC );
222 m_nonCopperNote->SetFont( infoFont );
223 m_staticTextInfoPaste->SetFont( infoFont );
224 m_staticTextPrimitiveListWarning->SetFont( infoFont );
225 m_minTrackWidthHint->SetFont( infoFont );
226
229
230 // Usually, TransferDataToWindow is called by OnInitDialog
231 // calling it here fixes all widget sizes so FinishDialogSettings can safely fix minsizes
233
234 // Initialize canvas to be able to display the dummy pad:
236
239 m_canUpdate = true;
240
241 m_padNetSelector->Connect( NET_SELECTED,
242 wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ),
243 nullptr, this );
244
245 if( m_padType->GetSelection() != PTH_DLG_TYPE && m_padType->GetSelection() != NPTH_DLG_TYPE )
246 {
247 m_gbSizerHole->Show( false );
248 m_staticline6->Show( false );
249 }
250
251 // Now all widgets have the size fixed, call FinishDialogSettings
253
254 // Update widgets
255 wxUpdateUIEvent dummyUI;
256 OnUpdateUI( dummyUI );
257
258 // Post a dummy size event to force the pad preview panel to update the
259 // view: actual size, best zoom ... after the frame is shown
260 PostSizeEvent();
261}
262
263
265{
266 m_padNetSelector->Disconnect( NET_SELECTED,
267 wxCommandEventHandler( DIALOG_PAD_PROPERTIES::OnValuesChanged ),
268 nullptr, this );
269
270 delete m_previewPad;
271 delete m_axisOrigin;
272}
273
274
275// Store the pad draw option during a session.
277
278
279void DIALOG_PAD_PROPERTIES::OnInitDialog( wxInitDialogEvent& event )
280{
281 m_selectedColor = COLOR4D( 1.0, 1.0, 1.0, 0.7 );
282
283 // Needed on some WM to be sure the pad is redrawn according to the final size
284 // of the canvas, with the right zoom factor
285 redraw();
286}
287
288
289void DIALOG_PAD_PROPERTIES::OnCancel( wxCommandEvent& event )
290{
291 // Mandatory to avoid m_panelShowPadGal trying to draw something
292 // in a non valid context during closing process:
294
295 // Now call default handler for wxID_CANCEL command event
296 event.Skip();
297}
298
299
301{
302 // Enable or disable the widgets in page managing custom shape primitives
303 m_listCtrlPrimitives->Enable( aEnable );
304 m_buttonDel->Enable( aEnable );
305 m_buttonEditShape->Enable( aEnable );
306 m_buttonAddShape->Enable( aEnable );
307 m_buttonDup->Enable( aEnable );
308 m_buttonGeometry->Enable( aEnable );
309}
310
311
313{
314 // Initialize the canvas to display the pad
315 m_padPreviewGAL = new PCB_DRAW_PANEL_GAL( m_boardViewPanel, -1, wxDefaultPosition,
316 wxDefaultSize,
319
320 m_padPreviewSizer->Add( m_padPreviewGAL, 12, wxEXPAND | wxALL, 5 );
321
322 // Show the X and Y axis. It is useful because pad shape can have an offset
323 // or be a complex shape.
324 KIGFX::COLOR4D axis_color = LIGHTBLUE;
325
327 pcbIUScale.mmToIU( 0.2 ),
330
333 m_padPreviewGAL->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
334
335 KIGFX::VIEW_CONTROLS* parentViewControls = m_parent->GetCanvas()->GetViewControls();
336 m_padPreviewGAL->GetViewControls()->ApplySettings( parentViewControls->GetSettings() );
337
338 m_padPreviewGAL->Show();
339
341
342 // fix the pad render mode (filled/not filled)
343 auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
344
345 settings->m_ForcePadSketchModeOn = m_cbShowPadOutline->IsChecked();
346 settings->SetHighContrast( false );
347 settings->m_ContrastModeDisplay = HIGH_CONTRAST_MODE::NORMAL;
348
349 // gives a non null grid size (0.001mm) because GAL layer does not like a 0 size grid:
350 double gridsize = 0.001 * pcbIUScale.IU_PER_MM;
351 view->GetGAL()->SetGridSize( VECTOR2D( gridsize, gridsize ) );
352
353 // And do not show the grid:
354 view->GetGAL()->SetGridVisibility( false );
355 view->Add( m_previewPad );
356 view->Add( m_axisOrigin );
357
359 Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_PAD_PROPERTIES::OnResize ) );
360}
361
362
364{
365 // Note: use ChangeValue() to avoid generating a wxEVT_TEXT event
367
370
373}
374
375
377{
378 if( m_previewPad->GetShape() != PAD_SHAPE::ROUNDRECT
379 && m_previewPad->GetShape() != PAD_SHAPE::CHAMFERED_RECT )
380 {
381 return;
382 }
383
384 if( m_cornerRadius.GetValue() < 0 )
385 m_cornerRadiusCtrl->ChangeValue( "0" );
386
388 {
390
393
394 redraw();
395 }
396}
397
398
400{
401 if( m_previewPad->GetShape() != PAD_SHAPE::ROUNDRECT
402 && m_previewPad->GetShape() != PAD_SHAPE::CHAMFERED_RECT )
403 {
404 return;
405 }
406
407 wxObject* ctrl = event.GetEventObject();
408 wxString value = event.GetString();
409 bool changed = false;
410
411 if( ctrl == m_cornerRatioCtrl || ctrl == m_mixedCornerRatioCtrl )
412 {
413 double ratioPercent;
414
415 if( value.ToDouble( &ratioPercent ) )
416 {
417 // Clamp ratioPercent to acceptable value (0.0 to 50.0)
418 if( ratioPercent < 0.0 )
419 {
422 }
423 else if( ratioPercent > 50.0 )
424 {
427 }
428
429 if( ctrl == m_cornerRatioCtrl )
430 m_mixedCornerRatioCtrl->ChangeValue( value );
431 else
432 m_cornerRatioCtrl->ChangeValue( value );
433
434 changed = true;
435 }
436 }
437 else if( ctrl == m_chamferRatioCtrl || ctrl == m_mixedChamferRatioCtrl )
438 {
439 double ratioPercent;
440
441 if( value.ToDouble( &ratioPercent ) )
442 {
443 // Clamp ratioPercent to acceptable value (0.0 to 50.0)
444 if( ratioPercent < 0.0 )
445 {
448 }
449 else if( ratioPercent > 50.0 )
450 {
453 }
454
455 if( ctrl == m_chamferRatioCtrl )
456 m_mixedChamferRatioCtrl->ChangeValue( value );
457 else
458 m_chamferRatioCtrl->ChangeValue( value );
459
460 changed = true;
461 }
462 }
463
464 if( changed && transferDataToPad( m_previewPad ) )
466
467 redraw();
468}
469
470
472{
473 wxString msg;
474
475 // Disable pad net name wxTextCtrl if the caller is the footprint editor
476 // because nets are living only in the board managed by the board editor
478
487 m_layerECO1->SetLabel( m_board->GetLayerName( Eco1_User ) );
488 m_layerECO2->SetLabel( m_board->GetLayerName( Eco2_User ) );
490
491 if( m_currentPad )
492 {
493 if( FOOTPRINT* footprint = m_currentPad->GetParent() )
494 {
496
497 if( footprint->IsFlipped() )
498 {
499 // flip pad (up/down) around its position
501 relPos.y = - relPos.y;
502 }
503
504 m_previewPad->SetPosition( relPos );
506
507 // Display parent footprint info
508 msg.Printf( _("Footprint %s (%s), %s, rotated %g deg"),
509 footprint->Reference().GetShownText( false ),
510 footprint->Value().GetShownText( false ),
511 footprint->IsFlipped() ? _( "back side (mirrored)" ) : _( "front side" ),
512 footprint->GetOrientation().AsDegrees() );
513
514 m_FlippedWarningSizer->Show( footprint->IsFlipped() );
515 m_parentInfo->SetLabel( msg );
516 }
517 }
518
520
521 if( m_currentPad )
522 {
523 m_padNumCtrl->SetValue( m_previewPad->GetNumber() );
524 }
525 else
526 {
528 m_padNumCtrl->SetValue( padTool->GetLastPadNumber() );
529 }
530
532
533 // Display current pad parameters units:
536
539
542
543 m_offsetShapeOpt->SetValue( m_previewPad->GetOffset() != VECTOR2I() );
546
547 if( m_previewPad->GetDelta().x )
548 {
550 m_trapAxisCtrl->SetSelection( 0 );
551 }
552 else
553 {
555 m_trapAxisCtrl->SetSelection( 1 );
556 }
557
558 m_padToDieOpt->SetValue( m_previewPad->GetPadToDieLength() != 0 );
560
569
578
580
581 if( m_curvedEdges->GetValue() )
583 else
584 m_curvePointsCtrl->SetValue( 5 );
585
587 {
588 default:
589 case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
590 case ZONE_CONNECTION::FULL: m_ZoneConnectionChoice->SetSelection( 1 ); break;
591 case ZONE_CONNECTION::THERMAL: m_ZoneConnectionChoice->SetSelection( 2 ); break;
592 case ZONE_CONNECTION::NONE: m_ZoneConnectionChoice->SetSelection( 3 ); break;
593 }
594
596 m_ZoneCustomPadShape->SetSelection( 1 );
597 else
598 m_ZoneCustomPadShape->SetSelection( 0 );
599
600 switch( m_previewPad->GetShape() )
601 {
602 default:
603 case PAD_SHAPE::CIRCLE: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_CIRCLE ); break;
604 case PAD_SHAPE::OVAL: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_OVAL ); break;
605 case PAD_SHAPE::RECT: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_RECT ); break;
606 case PAD_SHAPE::TRAPEZOID: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_TRAPEZOID ); break;
607 case PAD_SHAPE::ROUNDRECT: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_ROUNDRECT ); break;
608
609 case PAD_SHAPE::CHAMFERED_RECT:
612 else
614 break;
615
616 case PAD_SHAPE::CUSTOM:
617 if( m_previewPad->GetAnchorPadShape() == PAD_SHAPE::RECT )
619 else
621 break;
622 }
623
632
634
635 enablePrimitivePage( PAD_SHAPE::CUSTOM == m_previewPad->GetShape() );
636
637 // Type of pad selection
638 bool aperture =
639 m_previewPad->GetAttribute() == PAD_ATTRIB::SMD && m_previewPad->IsAperturePad();
640
641 if( aperture )
642 {
643 m_padType->SetSelection( APERTURE_DLG_TYPE );
644 }
645 else
646 {
647 switch( m_previewPad->GetAttribute() )
648 {
649 case PAD_ATTRIB::PTH: m_padType->SetSelection( PTH_DLG_TYPE ); break;
650 case PAD_ATTRIB::SMD: m_padType->SetSelection( SMD_DLG_TYPE ); break;
651 case PAD_ATTRIB::CONN: m_padType->SetSelection( CONN_DLG_TYPE ); break;
652 case PAD_ATTRIB::NPTH: m_padType->SetSelection( NPTH_DLG_TYPE ); break;
653 }
654 }
655
656 switch( m_previewPad->GetProperty() )
657 {
658 case PAD_PROP::NONE: m_choiceFabProperty->SetSelection( 0 ); break;
659 case PAD_PROP::BGA: m_choiceFabProperty->SetSelection( 1 ); break;
660 case PAD_PROP::FIDUCIAL_LOCAL: m_choiceFabProperty->SetSelection( 2 ); break;
661 case PAD_PROP::FIDUCIAL_GLBL: m_choiceFabProperty->SetSelection( 3 ); break;
662 case PAD_PROP::TESTPOINT: m_choiceFabProperty->SetSelection( 4 ); break;
663 case PAD_PROP::HEATSINK: m_choiceFabProperty->SetSelection( 5 ); break;
664 case PAD_PROP::CASTELLATED: m_choiceFabProperty->SetSelection( 6 ); break;
665 }
666
667 // Ensure the pad property is compatible with the pad type
668 if( m_previewPad->GetAttribute() == PAD_ATTRIB::NPTH )
669 {
670 m_choiceFabProperty->SetSelection( 0 );
671 m_choiceFabProperty->Enable( false );
672 }
673
675 m_holeShapeCtrl->SetSelection( 0 );
676 else
677 m_holeShapeCtrl->SetSelection( 1 );
678
681
682 // Update some dialog widgets state (Enable/disable options):
683 wxCommandEvent cmd_event;
684 OnPadShapeSelection( cmd_event );
685 OnOffsetCheckbox( cmd_event );
686
687 // Update basic shapes list
689}
690
691
692// A small helper function, to display coordinates:
693static wxString formatCoord( EDA_UNITS aUnits, const VECTOR2I& aCoord )
694{
695 return wxString::Format( wxT( "(X:%s Y:%s)" ),
698}
699
700
702{
703 m_listCtrlPrimitives->ClearAll();
704
705 wxListItem itemCol;
706 itemCol.SetImage(-1);
707
708 for( int ii = 0; ii < 5; ++ii )
709 m_listCtrlPrimitives->InsertColumn(ii, itemCol);
710
711 wxString bs_info[5];
712
713 for( unsigned ii = 0; ii < m_primitives.size(); ++ii )
714 {
715 const std::shared_ptr<PCB_SHAPE>& primitive = m_primitives[ii];
716
717 for( wxString& s : bs_info )
718 s.Empty();
719
720 bs_info[4] = _( "width" ) + wxS( " " )+ EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_units,
721 primitive->GetWidth() );
722
723 switch( primitive->GetShape() )
724 {
725 case SHAPE_T::SEGMENT:
726 bs_info[0] = _( "Segment" );
727 bs_info[1] = _( "from" ) + wxS( " " ) + formatCoord( m_units, primitive->GetStart() );
728 bs_info[2] = _( "to" ) + wxS( " " ) + formatCoord( m_units, primitive->GetEnd() );
729 break;
730
731 case SHAPE_T::BEZIER:
732 bs_info[0] = _( "Bezier" );
733 bs_info[1] = _( "from" ) + wxS( " " ) + formatCoord( m_units, primitive->GetStart() );
734 bs_info[2] = _( "to" ) + wxS( " " ) + formatCoord( m_units, primitive->GetEnd() );
735 break;
736
737 case SHAPE_T::ARC:
738 bs_info[0] = _( "Arc" );
739 bs_info[1] = _( "center" ) + wxS( " " ) + formatCoord( m_units, primitive->GetCenter() );
740 bs_info[2] = _( "start" ) + wxS( " " ) + formatCoord( m_units, primitive->GetStart() );
741 bs_info[3] = _( "angle" ) + wxS( " " ) + EDA_UNIT_UTILS::FormatAngle( primitive->GetArcAngle() );
742 break;
743
744 case SHAPE_T::CIRCLE:
745 if( primitive->GetWidth() )
746 bs_info[0] = _( "Ring" );
747 else
748 bs_info[0] = _( "Circle" );
749
750 bs_info[1] = _( "at" ) + wxS( " " ) + formatCoord( m_units, primitive->GetStart() );
751 bs_info[2] = _( "radius" ) + wxS( " " ) + EDA_UNIT_UTILS::UI::MessageTextFromValue( pcbIUScale, m_units,
752 primitive->GetRadius() );
753 break;
754
755 case SHAPE_T::POLY:
756 bs_info[0] = _( "Polygon" );
757 bs_info[1] = wxString::Format( _( "corners count %d" ),
758 primitive->GetPolyShape().Outline( 0 ).PointCount() );
759 break;
760
761 case SHAPE_T::RECT:
762 if( primitive->IsAnnotationProxy() )
763 bs_info[0] = _( "Number box" );
764 else
765 bs_info[0] = _( "Rectangle" );
766
767 bs_info[1] = _( "from" ) + wxS( " " ) + formatCoord( m_units, primitive->GetStart() );
768 bs_info[2] = _( "to" ) + wxS( " " ) + formatCoord( m_units, primitive->GetEnd() );
769 break;
770
771 default:
772 bs_info[0] = _( "Unknown primitive" );
773 break;
774 }
775
776 long tmp = m_listCtrlPrimitives->InsertItem( ii, bs_info[0] );
777 m_listCtrlPrimitives->SetItemData( tmp, ii );
778
779 for( int jj = 0, col = 0; jj < 5; ++jj )
780 m_listCtrlPrimitives->SetItem( tmp, col++, bs_info[jj] );
781 }
782
783 // Now columns are filled, ensure correct width of columns
784 for( unsigned ii = 0; ii < 5; ++ii )
785 m_listCtrlPrimitives->SetColumnWidth( ii, wxLIST_AUTOSIZE );
786}
787
788
789void DIALOG_PAD_PROPERTIES::OnResize( wxSizeEvent& event )
790{
791 redraw();
792 event.Skip();
793}
794
795
796void DIALOG_PAD_PROPERTIES::onChangePadMode( wxCommandEvent& event )
797{
799
801
802 // fix the pad render mode (filled/not filled)
803 auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
804
805 settings->m_ForcePadSketchModeOn = m_cbShowPadOutline->IsChecked();
806 settings->SetHighContrast( false );
807 settings->m_ContrastModeDisplay = HIGH_CONTRAST_MODE::NORMAL;
808
809 redraw();
810}
811
812
814{
815 switch( m_PadShapeSelector->GetSelection() )
816 {
820 m_shapePropsBook->SetSelection( 0 );
821 break;
822
824 m_shapePropsBook->SetSelection( 1 );
825 break;
826
828 {
829 m_shapePropsBook->SetSelection( 2 );
830
831 // A reasonable default (from IPC-7351C)
834
835 break;
836 }
837
839 m_shapePropsBook->SetSelection( 3 );
840
841 // Reasonable default
842 if( m_previewPad->GetChamferRectRatio() == 0.0 )
844
845 // Ensure the displayed value is up to date:
847
848 // A reasonable default is one corner chamfered (usual for some SMD pads).
849 if( !m_cbTopLeft->GetValue() && !m_cbTopRight->GetValue()
850 && !m_cbBottomLeft->GetValue() && !m_cbBottomRight->GetValue() )
851 {
852 m_cbTopLeft->SetValue( true );
853 m_cbTopRight->SetValue( false );
854 m_cbBottomLeft->SetValue( false );
855 m_cbBottomRight->SetValue( false );
856 }
857
858 break;
859
861 m_shapePropsBook->SetSelection( 4 );
862
863 // Reasonable defaults (corner radius from IPC-7351C)
865 && m_previewPad->GetChamferRectRatio() == 0.0 )
866 {
869
870 if( m_previewPad->GetChamferRectRatio() == 0.0 )
872 }
873
874 // Ensure the displayed values are up to date:
877 break;
878
879 case CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR: // PAD_SHAPE::CUSTOM, circular anchor
880 case CHOICE_SHAPE_CUSTOM_RECT_ANCHOR: // PAD_SHAPE::CUSTOM, rect anchor
881 m_shapePropsBook->SetSelection( 0 );
882 break;
883 }
884
885 // Note: must do this before enabling/disabling m_sizeY as we're using that as a flag to see
886 // what the last shape was.
887 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CIRCLE )
888 {
889 if( m_sizeYCtrl->IsEnabled() && m_spokeAngle.GetAngleValue() == ANGLE_90 )
891 }
892 else
893 {
894 if( !m_sizeYCtrl->IsEnabled() && m_spokeAngle.GetAngleValue() == ANGLE_45 )
896 }
897
898 // Readjust props book size
899 wxSize size = m_shapePropsBook->GetSize();
900 size.y = m_shapePropsBook->GetPage( m_shapePropsBook->GetSelection() )->GetBestSize().y;
901 m_shapePropsBook->SetMaxSize( size );
902
905
909
910 if( !m_offsetShapeOpt->IsEnabled() )
911 m_offsetShapeOpt->SetValue( false );
912
913 // Show/hide controls depending on m_offsetShapeOpt being enabled
914 m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
915 m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
916
917 bool is_custom = m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
919
920 enablePrimitivePage( is_custom );
921
924
925 for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
926 m_notebook->GetPage( i )->Layout();
927
928 // Resize the dialog if its height is too small to show all widgets:
929 if( m_MainSizer->GetSize().y < m_MainSizer->GetMinSize().y )
930 m_MainSizer->SetSizeHints( this );
931
933 redraw();
934}
935
936
938{
941 redraw();
942}
943
944
945void DIALOG_PAD_PROPERTIES::PadOrientEvent( wxCommandEvent& event )
946{
948 redraw();
949}
950
951
953{
954 m_rbCopperLayersSel->Clear();
955
956 switch( m_padType->GetSelection() )
957 {
958 case PTH_DLG_TYPE:
959 m_rbCopperLayersSel->Append( _( "All copper layers" ) );
960 m_rbCopperLayersSel->Append( wxString::Format( _( "%s, %s and connected layers" ),
962 m_board->GetLayerName( B_Cu ) ) );
963 m_rbCopperLayersSel->Append( _( "Connected layers only" ) );
964 m_rbCopperLayersSel->Append( _( "None" ) );
965 break;
966
967 case NPTH_DLG_TYPE:
968 m_rbCopperLayersSel->Append( wxString::Format( _( "%s and %s" ),
970 m_board->GetLayerName( B_Cu ) ) );
973 m_rbCopperLayersSel->Append( _( "None" ) );
974 break;
975
976 case SMD_DLG_TYPE:
977 case CONN_DLG_TYPE:
980 break;
981
983 m_rbCopperLayersSel->Append( _( "None" ) );
984 break;
985 }
986}
987
988
989void DIALOG_PAD_PROPERTIES::PadTypeSelected( wxCommandEvent& event )
990{
991 bool hasHole = true;
992 bool hasConnection = true;
993 bool hasProperty = true;
994
995 switch( m_padType->GetSelection() )
996 {
997 case PTH_DLG_TYPE: hasHole = true; hasConnection = true; hasProperty = true; break;
998 case SMD_DLG_TYPE: hasHole = false; hasConnection = true; hasProperty = true; break;
999 case CONN_DLG_TYPE: hasHole = false; hasConnection = true; hasProperty = true; break;
1000 case NPTH_DLG_TYPE: hasHole = true; hasConnection = false; hasProperty = false; break;
1001 case APERTURE_DLG_TYPE: hasHole = false; hasConnection = false; hasProperty = true; break;
1002 }
1003
1004 // Update Layers dropdown list and selects the "best" layer set for the new pad type:
1007
1008 m_gbSizerHole->Show( hasHole );
1009 m_staticline6->Show( hasHole );
1010 if( !hasHole )
1011 {
1012 m_holeX.ChangeValue( 0 );
1013 m_holeY.ChangeValue( 0 );
1014 }
1015 else if ( m_holeX.GetValue() == 0 && m_currentPad )
1016 {
1019 }
1020
1021 if( !hasConnection )
1022 {
1023 m_padNumCtrl->ChangeValue( wxEmptyString );
1025 m_padToDieOpt->SetValue( false );
1026 }
1027 else if( m_padNumCtrl->GetValue().IsEmpty() && m_currentPad )
1028 {
1029 m_padNumCtrl->ChangeValue( m_currentPad->GetNumber() );
1031 }
1032
1033 if( !hasProperty )
1034 m_choiceFabProperty->SetSelection( 0 );
1035
1036 m_choiceFabProperty->Enable( hasProperty );
1037
1039
1040 // Layout adjustment is needed if the hole details got shown/hidden
1041 m_LeftBoxSizer->Layout();
1042 redraw();
1043}
1044
1045
1046void DIALOG_PAD_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
1047{
1048 bool hasHole = true;
1049 bool hasConnection = true;
1050
1051 switch( m_padType->GetSelection() )
1052 {
1053 case PTH_DLG_TYPE: /* PTH */ hasHole = true; hasConnection = true; break;
1054 case SMD_DLG_TYPE: /* SMD */ hasHole = false; hasConnection = true; break;
1055 case CONN_DLG_TYPE: /* CONN */ hasHole = false; hasConnection = true; break;
1056 case NPTH_DLG_TYPE: /* NPTH */ hasHole = true; hasConnection = false; break;
1057 case APERTURE_DLG_TYPE: /* Aperture */ hasHole = false; hasConnection = false; break;
1058 }
1059
1060 // Enable/disable hole controls
1061 m_holeShapeLabel->Enable( hasHole );
1062 m_holeShapeCtrl->Enable( hasHole );
1063 m_holeX.Enable( hasHole );
1064 m_holeY.Enable( hasHole && m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_OVAL );
1065
1066 // Enable/disable number and net
1067 m_padNumLabel->Enable( hasConnection );
1068 m_padNumCtrl->Enable( hasConnection );
1069
1070 if( m_padNetLabel->IsShown() )
1071 {
1072 m_padNetLabel->Enable( hasConnection && m_canEditNetName && m_currentPad );
1073 m_padNetSelector->Enable( hasConnection && m_canEditNetName && m_currentPad );
1074 }
1075
1076 // Enable/disable pad length-to-die
1077 m_padToDieOpt->Enable( hasConnection );
1078
1079 if( !m_padToDieOpt->IsEnabled() )
1080 m_padToDieOpt->SetValue( false );
1081
1082 // We can show/hide this here because it doesn't require the layout to be refreshed.
1083 // All the others have to be done in their event handlers because doing a layout here
1084 // causes infinite looping on MSW.
1085 m_padToDie.Show( m_padToDieOpt->GetValue() );
1086
1087 // Enable/disable Copper Layers control
1088 m_rbCopperLayersSel->Enable( m_padType->GetSelection() != APERTURE_DLG_TYPE );
1089
1091
1092 switch( m_padType->GetSelection() )
1093 {
1094 case PTH_DLG_TYPE:
1095 if( !cu_set.any() )
1096 m_stackupImagesBook->SetSelection( 3 );
1097 else if( !m_previewPad->GetRemoveUnconnected() )
1098 m_stackupImagesBook->SetSelection( 0 );
1099 else if( m_previewPad->GetKeepTopBottom() )
1100 m_stackupImagesBook->SetSelection( 1 );
1101 else
1102 m_stackupImagesBook->SetSelection( 2 );
1103
1104 break;
1105
1106 case NPTH_DLG_TYPE:
1107 if( cu_set.test( F_Cu ) && cu_set.test( B_Cu ) )
1108 m_stackupImagesBook->SetSelection( 4 );
1109 else if( cu_set.test( F_Cu ) )
1110 m_stackupImagesBook->SetSelection( 5 );
1111 else if( cu_set.test( B_Cu ) )
1112 m_stackupImagesBook->SetSelection( 6 );
1113 else
1114 m_stackupImagesBook->SetSelection( 7 );
1115
1116 break;
1117
1118 case SMD_DLG_TYPE:
1119 case CONN_DLG_TYPE:
1120 case APERTURE_DLG_TYPE:
1121 m_stackupImagesBook->ChangeSelection( 3 );
1122 break;
1123 }
1124
1126}
1127
1128
1130{
1131 event.Enable( !m_board->LegacyTeardrops() );
1132}
1133
1134
1136{
1137 event.Enable( !m_board->LegacyTeardrops() && m_curvedEdges->GetValue() );
1138}
1139
1140
1142{
1143 bool isOnCopperLayer = ( m_previewPad->GetLayerSet() & LSET::AllCuMask() ).any();
1144 m_nonCopperWarningBook->ChangeSelection( isOnCopperLayer ? 0 : 1 );
1145}
1146
1147
1148void DIALOG_PAD_PROPERTIES::updatePadLayersList( LSET layer_mask, bool remove_unconnected,
1149 bool keep_top_bottom )
1150{
1152
1153 switch( m_padType->GetSelection() )
1154 {
1155 case PTH_DLG_TYPE:
1156 if( !layer_mask.any() )
1157 layer_mask = PAD::PTHMask();
1158
1159 if( !( layer_mask & LSET::AllCuMask() ).any() )
1160 m_rbCopperLayersSel->SetSelection( 3 );
1161 else if( !remove_unconnected )
1162 m_rbCopperLayersSel->SetSelection( 0 );
1163 else if( keep_top_bottom )
1164 m_rbCopperLayersSel->SetSelection( 1 );
1165 else
1166 m_rbCopperLayersSel->SetSelection( 2 );
1167
1168 break;
1169
1170 case SMD_DLG_TYPE:
1171 if( !layer_mask.any() )
1172 layer_mask = PAD::SMDMask();
1173
1174 if( layer_mask.test( F_Cu ) )
1175 m_rbCopperLayersSel->SetSelection( 0 );
1176 else
1177 m_rbCopperLayersSel->SetSelection( 1 );
1178
1179 break;
1180
1181 case CONN_DLG_TYPE:
1182 if( !layer_mask.any() )
1183 layer_mask = PAD::ConnSMDMask();
1184
1185 if( layer_mask.test( F_Cu ) )
1186 m_rbCopperLayersSel->SetSelection( 0 );
1187 else
1188 m_rbCopperLayersSel->SetSelection( 1 );
1189
1190 break;
1191
1192 case NPTH_DLG_TYPE:
1193 if( !layer_mask.any() )
1194 layer_mask = PAD::UnplatedHoleMask();
1195
1196 if( layer_mask.test( F_Cu ) && layer_mask.test( B_Cu ) )
1197 m_rbCopperLayersSel->SetSelection( 0 );
1198 else if( layer_mask.test( F_Cu ) )
1199 m_rbCopperLayersSel->SetSelection( 1 );
1200 else if( layer_mask.test( B_Cu ) )
1201 m_rbCopperLayersSel->SetSelection( 2 );
1202 else
1203 m_rbCopperLayersSel->SetSelection( 3 );
1204
1205 break;
1206
1207 case APERTURE_DLG_TYPE:
1208 if( !layer_mask.any() )
1209 layer_mask = PAD::ApertureMask();
1210
1211 m_rbCopperLayersSel->SetSelection( 0 );
1212 break;
1213 }
1214
1215 m_layerFrontAdhesive->SetValue( layer_mask[F_Adhes] );
1216 m_layerBackAdhesive->SetValue( layer_mask[B_Adhes] );
1217
1218 m_layerFrontPaste->SetValue( layer_mask[F_Paste] );
1219 m_layerBackPaste->SetValue( layer_mask[B_Paste] );
1220
1221 m_layerFrontSilk->SetValue( layer_mask[F_SilkS] );
1222 m_layerBackSilk->SetValue( layer_mask[B_SilkS] );
1223
1224 m_layerFrontMask->SetValue( layer_mask[F_Mask] );
1225 m_layerBackMask->SetValue( layer_mask[B_Mask] );
1226
1227 m_layerECO1->SetValue( layer_mask[Eco1_User] );
1228 m_layerECO2->SetValue( layer_mask[Eco2_User] );
1229
1230 m_layerUserDwgs->SetValue( layer_mask[Dwgs_User] );
1231}
1232
1233
1235{
1236 bool retVal = DIALOG_SHIM::Show( aShow );
1237
1238 if( aShow )
1239 {
1240 // It *should* work to set the stackup bitmap in the constructor, but it doesn't.
1241 // wxWidgets needs to have these set when the panel is visible for some reason.
1242 // https://gitlab.com/kicad/code/kicad/-/issues/5534
1243 m_stackupImage0->SetBitmap( KiBitmap( BITMAPS::pads_reset_unused ) );
1244 m_stackupImage1->SetBitmap( KiBitmap( BITMAPS::pads_remove_unused_keep_bottom ) );
1245 m_stackupImage2->SetBitmap( KiBitmap( BITMAPS::pads_remove_unused ) );
1246 m_stackupImage4->SetBitmap( KiBitmap( BITMAPS::pads_npth_top_bottom ) );
1247 m_stackupImage5->SetBitmap( KiBitmap( BITMAPS::pads_npth_top ) );
1248 m_stackupImage6->SetBitmap( KiBitmap( BITMAPS::pads_npth_bottom ) );
1249 m_stackupImage7->SetBitmap( KiBitmap( BITMAPS::pads_npth ) );
1250
1251 Layout();
1252 }
1253
1254 return retVal;
1255}
1256
1257
1258void DIALOG_PAD_PROPERTIES::OnSetCopperLayers( wxCommandEvent& event )
1259{
1261 redraw();
1262}
1263
1264
1265void DIALOG_PAD_PROPERTIES::OnSetLayers( wxCommandEvent& event )
1266{
1268 redraw();
1269}
1270
1271
1273{
1274 bool error = !transferDataToPad( m_previewPad );
1275
1276 wxArrayString error_msgs;
1277 wxArrayString warning_msgs;
1278 VECTOR2I pad_size = m_previewPad->GetSize();
1279 VECTOR2I drill_size = m_previewPad->GetDrillSize();
1280
1281 if( m_previewPad->GetShape() == PAD_SHAPE::CUSTOM )
1282 {
1283 // allow 0-sized anchor pads
1284 }
1285 else if( m_previewPad->GetShape() == PAD_SHAPE::CIRCLE )
1286 {
1287 if( pad_size.x <= 0 )
1288 error_msgs.Add( _( "Error: Pad must have a positive size." ) );
1289 }
1290 else
1291 {
1292 if( pad_size.x <= 0 || pad_size.y <= 0 )
1293 error_msgs.Add( _( "Error: Pad must have a positive size." ) );
1294 }
1295
1296 // Test hole against pad shape
1298 {
1299 int maxError = m_board->GetDesignSettings().m_MaxError;
1300 SHAPE_POLY_SET padOutline;
1301
1302 m_previewPad->TransformShapeToPolygon( padOutline, UNDEFINED_LAYER, 0, maxError,
1303 ERROR_INSIDE );
1304
1305 if( !padOutline.Collide( m_previewPad->GetPosition() ) )
1306 {
1307 warning_msgs.Add( _( "Warning: Pad hole not inside pad shape." ) );
1308 }
1309 else if( m_previewPad->GetAttribute() == PAD_ATTRIB::PTH )
1310 {
1311 std::shared_ptr<SHAPE_SEGMENT> slot = m_previewPad->GetEffectiveHoleShape();
1312 SHAPE_POLY_SET slotOutline;
1313
1314 TransformOvalToPolygon( slotOutline, slot->GetSeg().A, slot->GetSeg().B,
1315 slot->GetWidth(), maxError, ERROR_INSIDE );
1316
1317 padOutline.BooleanSubtract( slotOutline, SHAPE_POLY_SET::PM_FAST );
1318
1319 if( padOutline.IsEmpty() )
1320 warning_msgs.Add( _( "Warning: Pad hole will leave no copper." ) );
1321 }
1322 }
1323
1324 if( m_previewPad->GetLocalClearance() < 0 )
1325 warning_msgs.Add( _( "Warning: Negative local clearance values will have no effect." ) );
1326
1327 // Some pads need a negative solder mask clearance (mainly for BGA with small pads)
1328 // However the negative solder mask clearance must not create negative mask size
1329 // Therefore test for minimal acceptable negative value
1331 {
1332 int absMargin = abs( m_previewPad->GetLocalSolderMaskMargin() );
1333
1334 if( m_previewPad->GetShape() == PAD_SHAPE::CUSTOM )
1335 {
1336 for( const std::shared_ptr<PCB_SHAPE>& shape : m_previewPad->GetPrimitives() )
1337 {
1338 BOX2I shapeBBox = shape->GetBoundingBox();
1339
1340 if( absMargin > shapeBBox.GetWidth() || absMargin > shapeBBox.GetHeight() )
1341 {
1342 warning_msgs.Add( _( "Warning: Negative solder mask clearances larger than "
1343 "some shape primitives. Results may be surprising." ) );
1344
1345 break;
1346 }
1347 }
1348 }
1349 else if( absMargin > pad_size.x || absMargin > pad_size.y )
1350 {
1351 warning_msgs.Add( _( "Warning: Negative solder mask clearance larger than pad. No "
1352 "solder mask will be generated." ) );
1353 }
1354 }
1355
1356 // Some pads need a positive solder paste clearance (mainly for BGA with small pads)
1357 // However, a positive value can create issues if the resulting shape is too big.
1358 // (like a solder paste creating a solder paste area on a neighbor pad or on the solder mask)
1359 // So we could ask for user to confirm the choice
1360 // For now we just check for disappearing paste
1361 wxSize paste_size;
1362 int paste_margin = m_previewPad->GetLocalSolderPasteMargin();
1363 double paste_ratio = m_previewPad->GetLocalSolderPasteMarginRatio();
1364
1365 paste_size.x = pad_size.x + paste_margin + KiROUND( pad_size.x * paste_ratio );
1366 paste_size.y = pad_size.y + paste_margin + KiROUND( pad_size.y * paste_ratio );
1367
1368 if( paste_size.x <= 0 || paste_size.y <= 0 )
1369 {
1370 warning_msgs.Add( _( "Warning: Negative solder paste margins larger than pad. No solder "
1371 "paste mask will be generated." ) );
1372 }
1373
1374 LSET padlayers_mask = m_previewPad->GetLayerSet();
1375
1376 if( padlayers_mask == 0 )
1377 error_msgs.Add( _( "Error: pad has no layer." ) );
1378
1379 if( !padlayers_mask[F_Cu] && !padlayers_mask[B_Cu] )
1380 {
1381 if( ( drill_size.x || drill_size.y ) && m_previewPad->GetAttribute() != PAD_ATTRIB::NPTH )
1382 {
1383 warning_msgs.Add( _( "Warning: Plated through holes should normally have a copper pad "
1384 "on at least one layer." ) );
1385 }
1386 }
1387
1388 if( error )
1389 error_msgs.Add( _( "Error: Trapazoid delta is too large." ) );
1390
1391 switch( m_previewPad->GetAttribute() )
1392 {
1393 case PAD_ATTRIB::NPTH: // Not plated, but through hole, a hole is expected
1394 case PAD_ATTRIB::PTH: // Pad through hole, a hole is also expected
1395 if( drill_size.x <= 0
1396 || ( drill_size.y <= 0 && m_previewPad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ) )
1397 {
1398 error_msgs.Add( _( "Error: Through hole pad has no hole." ) );
1399 }
1400 break;
1401
1402 case PAD_ATTRIB::CONN: // Connector pads are smd pads, just they do not have solder paste.
1403 if( padlayers_mask[B_Paste] || padlayers_mask[F_Paste] )
1404 {
1405 warning_msgs.Add( _( "Warning: Connector pads normally have no solder paste. Use a "
1406 "SMD pad instead." ) );
1407 }
1409
1410 case PAD_ATTRIB::SMD: // SMD and Connector pads (One external copper layer only)
1411 {
1412 if( drill_size.x > 0 || drill_size.y > 0 )
1413 {
1414 error_msgs.Add( _( "Error: SMD pad has a hole." ) );
1415 }
1416
1417 LSET innerlayers_mask = padlayers_mask & LSET::InternalCuMask();
1418
1419 if( ( padlayers_mask[F_Cu] && padlayers_mask[B_Cu] ) || innerlayers_mask.count() != 0 )
1420 warning_msgs.Add( _( "Warning: SMD pad has no outer layers." ) );
1421 }
1422 break;
1423 }
1424
1425 if( ( m_previewPad->GetProperty() == PAD_PROP::FIDUCIAL_GLBL || m_previewPad->GetProperty() == PAD_PROP::FIDUCIAL_LOCAL )
1426 && m_previewPad->GetAttribute() == PAD_ATTRIB::NPTH )
1427 {
1428 warning_msgs.Add( _( "Warning: Fiducial property makes no sense on NPTH pads." ) );
1429 }
1430
1431 if( m_previewPad->GetProperty() == PAD_PROP::TESTPOINT
1432 && m_previewPad->GetAttribute() == PAD_ATTRIB::NPTH )
1433 {
1434 warning_msgs.Add( _( "Warning: Testpoint property makes no sense on NPTH pads." ) );
1435 }
1436
1437 if( m_previewPad->GetProperty() == PAD_PROP::HEATSINK
1438 && m_previewPad->GetAttribute() == PAD_ATTRIB::NPTH )
1439 {
1440 warning_msgs.Add( _( "Warning: Heatsink property makes no sense of NPTH pads." ) );
1441 }
1442
1443 if( m_previewPad->GetProperty() == PAD_PROP::CASTELLATED
1444 && m_previewPad->GetAttribute() != PAD_ATTRIB::PTH )
1445 {
1446 warning_msgs.Add( _( "Warning: Castellated property is for PTH pads." ) );
1447 }
1448
1449 if( m_previewPad->GetProperty() == PAD_PROP::BGA
1450 && m_previewPad->GetAttribute() != PAD_ATTRIB::SMD )
1451 {
1452 warning_msgs.Add( _( "Warning: BGA property is for SMD pads." ) );
1453 }
1454
1455 if( m_previewPad->GetShape() == PAD_SHAPE::ROUNDRECT
1456 || m_previewPad->GetShape() == PAD_SHAPE::CHAMFERED_RECT )
1457 {
1459
1460 if( m_cornerRatio.GetDoubleValue() < 0.0 )
1461 error_msgs.Add( _( "Error: Negative corner size." ) );
1462 else if( m_cornerRatio.GetDoubleValue() > 50.0 )
1463 warning_msgs.Add( _( "Warning: Corner size will make pad circular." ) );
1464 }
1465
1466 // PADSTACKS TODO: this will need to check each layer in the pad...
1467 if( m_previewPad->GetShape() == PAD_SHAPE::CUSTOM )
1468 {
1469 SHAPE_POLY_SET mergedPolygon;
1470 m_previewPad->MergePrimitivesAsPolygon( &mergedPolygon );
1471
1472 if( mergedPolygon.OutlineCount() > 1 )
1473 error_msgs.Add( _( "Error: Custom pad shape must resolve to a single polygon." ) );
1474 }
1475
1476
1477 if( error_msgs.GetCount() || warning_msgs.GetCount() )
1478 {
1479 wxString title = error_msgs.GetCount() ? _( "Pad Properties Errors" )
1480 : _( "Pad Properties Warnings" );
1481 HTML_MESSAGE_BOX dlg( this, title );
1482
1483 wxArrayString msgs = error_msgs;
1484
1485 for( const wxString& msg : warning_msgs )
1486 msgs.Add( msg );
1487
1488 dlg.ListSet( msgs );
1489
1490 dlg.ShowModal();
1491 }
1492
1493 return error_msgs.GetCount() == 0;
1494}
1495
1496
1498{
1499 if( !m_canUpdate )
1500 return;
1501
1504
1505 // The layer used to place primitive items selected when editing custom pad shapes
1506 // we use here a layer never used in a pad:
1507 #define SELECTED_ITEMS_LAYER Dwgs_User
1508
1510 KIGFX::PCB_RENDER_SETTINGS* settings =
1511 static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
1513
1514 view->Update( m_previewPad );
1515
1516 // delete previous items if highlight list
1517 while( m_highlight.size() )
1518 {
1519 delete m_highlight.back(); // the dtor also removes item from view
1520 m_highlight.pop_back();
1521 }
1522
1523 // highlight selected primitives:
1524 long select = m_listCtrlPrimitives->GetFirstSelected();
1525
1526 while( select >= 0 )
1527 {
1528 PCB_SHAPE* dummyShape = static_cast<PCB_SHAPE*>( m_primitives[select]->Clone() );
1529 dummyShape->SetLayer( SELECTED_ITEMS_LAYER );
1530 dummyShape->Rotate( { 0, 0 }, m_previewPad->GetOrientation() );
1531 dummyShape->Move( m_previewPad->GetPosition() );
1532
1533 view->Add( dummyShape );
1534 m_highlight.push_back( dummyShape );
1535
1536 select = m_listCtrlPrimitives->GetNextSelected( select );
1537 }
1538
1539 BOX2I bbox = m_previewPad->ViewBBox();
1540
1541 if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
1542 {
1543 // The origin always goes in the middle of the canvas; we want offsetting the pad
1544 // shape to move the pad, not the hole
1545 bbox.Move( -m_previewPad->GetPosition() );
1546 int maxXExtent = std::max( abs( bbox.GetLeft() ), abs( bbox.GetRight() ) );
1547 int maxYExtent = std::max( abs( bbox.GetTop() ), abs( bbox.GetBottom() ) );
1548
1549 // Don't blow up the GAL on too-large numbers
1550 if( maxXExtent > INT_MAX / 4 )
1551 maxXExtent = INT_MAX / 4;
1552
1553 if( maxYExtent > INT_MAX / 4 )
1554 maxYExtent = INT_MAX / 4;
1555
1556 BOX2D viewBox( m_previewPad->GetPosition(), {0, 0} );
1557 BOX2D canvasBox( m_previewPad->GetPosition(), {0, 0} );
1558 viewBox.Inflate( maxXExtent * 1.4, maxYExtent * 1.4 ); // add a margin
1559 canvasBox.Inflate( maxXExtent * 2.0, maxYExtent * 2.0 );
1560
1561 view->SetBoundary( canvasBox );
1562
1563 // Autozoom
1564 view->SetViewport( viewBox );
1565
1568 }
1569}
1570
1571
1573{
1574 if( !wxDialog::TransferDataToWindow() )
1575 return false;
1576
1577 if( !m_panelGeneral->TransferDataToWindow() )
1578 return false;
1579
1580 if( !m_localSettingsPanel->TransferDataToWindow() )
1581 return false;
1582
1583 return true;
1584}
1585
1586
1588{
1589 BOARD_COMMIT commit( m_parent );
1590
1591 if( !wxDialog::TransferDataFromWindow() )
1592 return false;
1593
1594 if( !m_panelGeneral->TransferDataFromWindow() )
1595 return false;
1596
1597 if( !m_localSettingsPanel->TransferDataFromWindow() )
1598 return false;
1599
1600 if( !padValuesOK() )
1601 return false;
1602
1604 return false;
1605
1607 padTool->SetLastPadNumber( m_masterPad->GetNumber() );
1608
1609 // m_masterPad is a pattern: ensure there is no net for this pad:
1611
1612 if( !m_currentPad ) // Set current Pad parameters
1613 return true;
1614
1615 commit.Modify( m_currentPad );
1616
1617 // Update values
1621
1623
1624 VECTOR2I size = m_masterPad->GetDelta();
1625 m_currentPad->SetDelta( size );
1626
1629
1630 VECTOR2I offset = m_masterPad->GetOffset();
1631 m_currentPad->SetOffset( offset );
1632
1634
1635 if( m_masterPad->GetShape() != PAD_SHAPE::CUSTOM )
1637
1640
1644
1646
1647 int padNetcode = NETINFO_LIST::UNCONNECTED;
1648
1649 // For PAD_ATTRIB::NPTH, ensure there is no net name selected
1650 if( m_masterPad->GetAttribute() != PAD_ATTRIB::NPTH )
1651 padNetcode = m_padNetSelector->GetSelectedNetcode();
1652
1653 m_currentPad->SetNetCode( padNetcode );
1665
1667
1668 // rounded rect pads with radius ratio = 0 are in fact rect pads.
1669 // So set the right shape (and perhaps issues with a radius = 0)
1670 if( m_currentPad->GetShape() == PAD_SHAPE::ROUNDRECT &&
1672 {
1673 m_currentPad->SetShape( PAD_SHAPE::RECT );
1674 }
1675
1676 // Set the fabrication property:
1678
1679 // define the way the clearance area is defined in zones
1681
1682 VECTOR2I relPos = m_masterPad->GetPosition();
1683
1685 {
1686 // flip pad (up/down) around its position
1688 relPos.y = -relPos.y;
1689 }
1690
1691 // Must be done after flipping
1693
1695
1696 // redraw the area where the pad was
1698
1699 commit.Push( _( "Modify pad" ) );
1700
1701 return true;
1702}
1703
1704
1706{
1707 PAD_PROP prop = PAD_PROP::NONE;
1708
1709 switch( m_choiceFabProperty->GetSelection() )
1710 {
1711 case 0: prop = PAD_PROP::NONE; break;
1712 case 1: prop = PAD_PROP::BGA; break;
1713 case 2: prop = PAD_PROP::FIDUCIAL_LOCAL; break;
1714 case 3: prop = PAD_PROP::FIDUCIAL_GLBL; break;
1715 case 4: prop = PAD_PROP::TESTPOINT; break;
1716 case 5: prop = PAD_PROP::HEATSINK; break;
1717 case 6: prop = PAD_PROP::CASTELLATED; break;
1718 }
1719
1720 return prop;
1721}
1722
1724{
1725 if( m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_CIRCLE )
1726 {
1727 m_holeXLabel->SetLabel( _( "Diameter:" ) );
1728 m_holeY.Show( false );
1729 }
1730 else
1731 {
1732 m_holeXLabel->SetLabel( _( "Hole size X:" ) );
1733 m_holeY.Show( true );
1734 }
1735
1736 m_holeXLabel->GetParent()->Layout();
1737}
1738
1740{
1741 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CIRCLE
1743 {
1744 m_sizeXLabel->SetLabel( _( "Diameter:" ) );
1745 m_sizeY.Show( false );
1746 m_bitmapTeardrop->SetBitmap( KiBitmap( BITMAPS::teardrop_sizes ) );
1747 }
1748 else
1749 {
1750 m_sizeXLabel->SetLabel( _( "Pad size X:" ) );
1751 m_sizeY.Show( true );
1752 m_bitmapTeardrop->SetBitmap( KiBitmap( BITMAPS::teardrop_rect_sizes ) );
1753 }
1754
1755 m_sizeXLabel->GetParent()->Layout();
1756}
1757
1758
1760{
1761 if( !Validate() )
1762 return false;
1763
1764 if( !m_panelGeneral->Validate() )
1765 return false;
1766
1767 if( !m_localSettingsPanel->Validate() )
1768 return false;
1769
1770 if( !m_spokeWidth.Validate( 0, INT_MAX ) )
1771 return false;
1772
1773 aPad->SetAttribute( code_type[m_padType->GetSelection()] );
1774 aPad->SetShape( code_shape[m_PadShapeSelector->GetSelection()] );
1775
1777 aPad->SetAnchorPadShape( PAD_SHAPE::RECT );
1778 else
1779 aPad->SetAnchorPadShape( PAD_SHAPE::CIRCLE );
1780
1781 if( aPad->GetShape() == PAD_SHAPE::CUSTOM )
1783
1784 aPad->GetTeardropParams().m_Enabled = m_cbTeardrops->GetValue();
1791
1792 if( m_curvedEdges->GetValue() )
1794 else
1796
1798
1799 // Read pad clearances values:
1807
1808 // And rotation
1810
1811 switch( m_ZoneConnectionChoice->GetSelection() )
1812 {
1813 default:
1814 case 0: aPad->SetZoneConnection( ZONE_CONNECTION::INHERITED ); break;
1815 case 1: aPad->SetZoneConnection( ZONE_CONNECTION::FULL ); break;
1816 case 2: aPad->SetZoneConnection( ZONE_CONNECTION::THERMAL ); break;
1817 case 3: aPad->SetZoneConnection( ZONE_CONNECTION::NONE ); break;
1818 }
1819
1821
1822 if( m_holeShapeCtrl->GetSelection() == CHOICE_SHAPE_CIRCLE )
1823 {
1826 }
1827 else
1828 {
1831 }
1832
1833 if( aPad->GetShape() == PAD_SHAPE::CIRCLE )
1835 else
1837
1838 // For a trapezoid, test delta value (be sure delta is not too large for pad size)
1839 // remember DeltaSize.x is the Y size variation
1840 bool error = false;
1841 VECTOR2I delta( 0, 0 );
1842
1843 if( aPad->GetShape() == PAD_SHAPE::TRAPEZOID )
1844 {
1845 // For a trapezoid, only one of delta.x or delta.y is not 0, depending on axis.
1846 if( m_trapAxisCtrl->GetSelection() == 0 )
1848 else
1850
1851 if( delta.x < 0 && delta.x < -aPad->GetSize().y )
1852 {
1853 delta.x = -aPad->GetSize().y + 2;
1854 error = true;
1855 }
1856
1857 if( delta.x > 0 && delta.x > aPad->GetSize().y )
1858 {
1859 delta.x = aPad->GetSize().y - 2;
1860 error = true;
1861 }
1862
1863 if( delta.y < 0 && delta.y < -aPad->GetSize().x )
1864 {
1865 delta.y = -aPad->GetSize().x + 2;
1866 error = true;
1867 }
1868
1869 if( delta.y > 0 && delta.y > aPad->GetSize().x )
1870 {
1871 delta.y = aPad->GetSize().x - 2;
1872 error = true;
1873 }
1874 }
1875
1876 aPad->SetDelta( delta );
1877
1878 if( m_offsetShapeOpt->GetValue() )
1880 else
1881 aPad->SetOffset( VECTOR2I() );
1882
1883 // Read pad length die
1884 if( m_padToDieOpt->GetValue() )
1886 else
1887 aPad->SetPadToDieLength( 0 );
1888
1889 aPad->SetNumber( m_padNumCtrl->GetValue() );
1891
1892 int chamfers = 0;
1893
1894 if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_RECT )
1895 {
1896 if( m_cbTopLeft->GetValue() )
1897 chamfers |= RECT_CHAMFER_TOP_LEFT;
1898
1899 if( m_cbTopRight->GetValue() )
1900 chamfers |= RECT_CHAMFER_TOP_RIGHT;
1901
1902 if( m_cbBottomLeft->GetValue() )
1903 chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1904
1905 if( m_cbBottomRight->GetValue() )
1906 chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1907 }
1908 else if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT )
1909 {
1910 if( m_cbTopLeft1->GetValue() )
1911 chamfers |= RECT_CHAMFER_TOP_LEFT;
1912
1913 if( m_cbTopRight1->GetValue() )
1914 chamfers |= RECT_CHAMFER_TOP_RIGHT;
1915
1916 if( m_cbBottomLeft1->GetValue() )
1917 chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
1918
1919 if( m_cbBottomRight1->GetValue() )
1920 chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
1921 }
1922 aPad->SetChamferPositions( chamfers );
1923
1924 if( aPad->GetShape() == PAD_SHAPE::CUSTOM )
1925 {
1926 // The pad custom has a "anchor pad" (a basic shape: round or rect pad)
1927 // that is the minimal area of this pad, and is useful to ensure a hole
1928 // diameter is acceptable, and is used in Gerber files as flashed area
1929 // reference
1930 if( aPad->GetAnchorPadShape() == PAD_SHAPE::CIRCLE )
1932 }
1933
1934 // Define the way the clearance area is defined in zones. Since all non-custom pad
1935 // shapes are convex to begin with, this really only makes any difference for custom
1936 // pad shapes.
1937 aPad->SetCustomShapeInZoneOpt( m_ZoneCustomPadShape->GetSelection() == 0 ?
1940
1941 switch( aPad->GetAttribute() )
1942 {
1943 case PAD_ATTRIB::PTH:
1944 break;
1945
1946 case PAD_ATTRIB::CONN:
1947 case PAD_ATTRIB::SMD:
1948 // SMD and PAD_ATTRIB::CONN has no hole.
1949 // basically, SMD and PAD_ATTRIB::CONN are same type of pads
1950 // PAD_ATTRIB::CONN has just a default non technical layers that differs from SMD
1951 // and are intended to be used in virtual edge board connectors
1952 // However we can accept a non null offset,
1953 // mainly to allow complex pads build from a set of basic pad shapes
1954 aPad->SetDrillSize( VECTOR2I( 0, 0 ) );
1955 break;
1956
1957 case PAD_ATTRIB::NPTH:
1958 // Mechanical purpose only:
1959 // no net name, no pad name allowed
1960 aPad->SetNumber( wxEmptyString );
1962 break;
1963
1964 default:
1965 wxFAIL_MSG( wxT( "DIALOG_PAD_PROPERTIES::transferDataToPad: unknown pad type" ) );
1966 break;
1967 }
1968
1969 if( aPad->GetShape() == PAD_SHAPE::ROUNDRECT )
1970 {
1972 }
1973 else if( aPad->GetShape() == PAD_SHAPE::CHAMFERED_RECT )
1974 {
1976 {
1979 }
1980 else // Choice is CHOICE_SHAPE_CHAMFERED_RECT, no rounded corner
1981 {
1983 aPad->SetRoundRectRadiusRatio( 0 );
1984 }
1985 }
1986
1988
1989 LSET padLayerMask = LSET();
1990 int copperLayersChoice = m_rbCopperLayersSel->GetSelection();
1991
1992 aPad->SetRemoveUnconnected( false );
1993 aPad->SetKeepTopBottom( false );
1994
1995 switch( m_padType->GetSelection() )
1996 {
1997 case PTH_DLG_TYPE:
1998 switch( copperLayersChoice )
1999 {
2000 case 0:
2001 // All copper layers
2002 padLayerMask |= LSET::AllCuMask();
2003 break;
2004
2005 case 1:
2006 // Front, back and connected
2007 padLayerMask |= LSET::AllCuMask();
2008 aPad->SetRemoveUnconnected( true );
2009 aPad->SetKeepTopBottom( true );
2010 break;
2011
2012 case 2:
2013 // Connected only
2014 padLayerMask |= LSET::AllCuMask();
2015 aPad->SetRemoveUnconnected( true );
2016 break;
2017
2018 case 3:
2019 // No copper layers
2020 break;
2021 }
2022
2023 break;
2024
2025 case NPTH_DLG_TYPE:
2026 switch( copperLayersChoice )
2027 {
2028 case 0: padLayerMask.set( F_Cu ).set( B_Cu ); break;
2029 case 1: padLayerMask.set( F_Cu ); break;
2030 case 2: padLayerMask.set( B_Cu ); break;
2031 default: break;
2032 }
2033
2034 break;
2035
2036 case SMD_DLG_TYPE:
2037 case CONN_DLG_TYPE:
2038 switch( copperLayersChoice )
2039 {
2040 case 0: padLayerMask.set( F_Cu ); break;
2041 case 1: padLayerMask.set( B_Cu ); break;
2042 }
2043
2044 break;
2045
2046 case APERTURE_DLG_TYPE:
2047 // no copper layers
2048 break;
2049 }
2050
2051 if( m_layerFrontAdhesive->GetValue() )
2052 padLayerMask.set( F_Adhes );
2053
2054 if( m_layerBackAdhesive->GetValue() )
2055 padLayerMask.set( B_Adhes );
2056
2057 if( m_layerFrontPaste->GetValue() )
2058 padLayerMask.set( F_Paste );
2059
2060 if( m_layerBackPaste->GetValue() )
2061 padLayerMask.set( B_Paste );
2062
2063 if( m_layerFrontSilk->GetValue() )
2064 padLayerMask.set( F_SilkS );
2065
2066 if( m_layerBackSilk->GetValue() )
2067 padLayerMask.set( B_SilkS );
2068
2069 if( m_layerFrontMask->GetValue() )
2070 padLayerMask.set( F_Mask );
2071
2072 if( m_layerBackMask->GetValue() )
2073 padLayerMask.set( B_Mask );
2074
2075 if( m_layerECO1->GetValue() )
2076 padLayerMask.set( Eco1_User );
2077
2078 if( m_layerECO2->GetValue() )
2079 padLayerMask.set( Eco2_User );
2080
2081 if( m_layerUserDwgs->GetValue() )
2082 padLayerMask.set( Dwgs_User );
2083
2084 aPad->SetLayerSet( padLayerMask );
2085
2086 return !error;
2087}
2088
2089
2090void DIALOG_PAD_PROPERTIES::OnOffsetCheckbox( wxCommandEvent& event )
2091{
2092 if( m_offsetShapeOpt->GetValue() )
2093 {
2096 }
2097
2098 // Show/hide controls depending on m_offsetShapeOpt being enabled
2099 m_offsetCtrls->Show( m_offsetShapeOpt->GetValue() );
2100 m_offsetShapeOptLabel->Show( m_offsetShapeOpt->GetValue() );
2101
2102 for( size_t i = 0; i < m_notebook->GetPageCount(); ++i )
2103 m_notebook->GetPage( i )->Layout();
2104
2105 OnValuesChanged( event );
2106}
2107
2108
2110{
2111 if( m_padToDieOpt->GetValue() && m_currentPad )
2113
2114 OnValuesChanged( event );
2115}
2116
2117
2118void DIALOG_PAD_PROPERTIES::OnValuesChanged( wxCommandEvent& event )
2119{
2120 if( m_canUpdate )
2121 {
2123 return;
2124
2125 // If the pad size has changed, update the displayed values for rounded rect pads.
2127
2128 redraw();
2129 }
2130}
2131
2133{
2134 long select = m_listCtrlPrimitives->GetFirstSelected();
2135
2136 if( select < 0 )
2137 {
2138 wxMessageBox( _( "No shape selected" ) );
2139 return;
2140 }
2141
2142 std::shared_ptr<PCB_SHAPE>& shape = m_primitives[select];
2143
2144 if( shape->GetShape() == SHAPE_T::POLY )
2145 {
2146 DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, m_parent, shape.get() );
2147
2148 if( dlg.ShowModal() != wxID_OK )
2149 return;
2150
2152 }
2153
2154 else
2155 {
2156 DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, m_parent, shape.get() );
2157
2158 if( dlg.ShowModal() != wxID_OK )
2159 return;
2160
2162 }
2163
2165
2167 redraw();
2168}
2169
2170
2172{
2173 // Called on a double click on the basic shapes list
2174 // To Do: highlight the primitive(s) currently selected.
2175 redraw();
2176}
2177
2178
2180{
2181 editPrimitive();
2182}
2183
2184
2185void DIALOG_PAD_PROPERTIES::onEditPrimitive( wxCommandEvent& event )
2186{
2187 editPrimitive();
2188}
2189
2190
2191void DIALOG_PAD_PROPERTIES::onDeletePrimitive( wxCommandEvent& event )
2192{
2193 long select = m_listCtrlPrimitives->GetFirstSelected();
2194
2195 if( select < 0 )
2196 return;
2197
2198 // Multiple selections are allowed. get them and remove corresponding shapes
2199 std::vector<long> indexes;
2200 indexes.push_back( select );
2201
2202 while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2203 indexes.push_back( select );
2204
2205 // Erase all select shapes
2206 for( unsigned ii = indexes.size(); ii > 0; --ii )
2207 m_primitives.erase( m_primitives.begin() + indexes[ii-1] );
2208
2210
2212 redraw();
2213}
2214
2215
2216void DIALOG_PAD_PROPERTIES::onAddPrimitive( wxCommandEvent& event )
2217{
2218 // Ask user for shape type
2219 wxString shapelist[] = {
2220 _( "Segment" ),
2221 _( "Arc" ),
2222 _( "Bezier" ),
2223 _( "Ring/Circle" ),
2224 _( "Polygon" ),
2225 _( "Number box" ),
2226 };
2227
2228 int type = wxGetSingleChoiceIndex( _( "Shape type:" ), _( "Add Primitive" ),
2229 arrayDim( shapelist ), shapelist, 0, this );
2230
2231 // User pressed cancel
2232 if( type == -1 )
2233 return;
2234
2235 SHAPE_T listtype[] = { SHAPE_T::SEGMENT, SHAPE_T::ARC, SHAPE_T::BEZIER, SHAPE_T::CIRCLE,
2236 SHAPE_T::POLY, SHAPE_T::RECT };
2237
2238 PCB_SHAPE* primitive = new PCB_SHAPE();
2239 primitive->SetShape( listtype[type] );
2240
2241 if( type == static_cast<int>( arrayDim( shapelist ) ) - 1 )
2242 primitive->SetIsAnnotationProxy();
2243
2245 PLOT_DASH_TYPE::SOLID ) );
2246 primitive->SetFilled( true );
2247
2248 if( listtype[type] == SHAPE_T::POLY )
2249 {
2250 DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, m_parent, primitive );
2251
2252 if( dlg.ShowModal() != wxID_OK )
2253 return;
2254 }
2255 else
2256 {
2257 DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, m_parent, primitive );
2258
2259 if( dlg.ShowModal() != wxID_OK )
2260 return;
2261 }
2262
2263 m_primitives.emplace_back( primitive );
2264
2266
2268 redraw();
2269}
2270
2271
2273{
2274 long select = m_listCtrlPrimitives->GetFirstSelected();
2275
2276 if( select < 0 )
2277 {
2278 wxMessageBox( _( "No shape selected" ) );
2279 return;
2280 }
2281
2282 // Multiple selections are allowed. Build selected shapes list
2283 std::vector<std::shared_ptr<PCB_SHAPE>> shapeList;
2284 shapeList.emplace_back( m_primitives[select] );
2285
2286 while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2287 shapeList.emplace_back( m_primitives[select] );
2288
2289 DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, m_parent, shapeList, false );
2290
2291 if( dlg.ShowModal() != wxID_OK )
2292 return;
2293
2294 dlg.Transform();
2295
2297
2299 redraw();
2300}
2301
2302
2304{
2305 long select = m_listCtrlPrimitives->GetFirstSelected();
2306
2307 if( select < 0 )
2308 {
2309 wxMessageBox( _( "No shape selected" ) );
2310 return;
2311 }
2312
2313 // Multiple selections are allowed. Build selected shapes list
2314 std::vector<std::shared_ptr<PCB_SHAPE>> shapeList;
2315 shapeList.emplace_back( m_primitives[select] );
2316
2317 while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
2318 shapeList.emplace_back( m_primitives[select] );
2319
2320 DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, m_parent, shapeList, true );
2321
2322 if( dlg.ShowModal() != wxID_OK )
2323 return;
2324
2325 // Transfer new settings
2326 // save duplicates to a separate vector to avoid m_primitives reallocation,
2327 // as shapeList contains pointers to its elements
2328 std::vector<std::shared_ptr<PCB_SHAPE>> duplicates;
2329 dlg.Transform( &duplicates, dlg.GetDuplicateCount() );
2330 std::move( duplicates.begin(), duplicates.end(), std::back_inserter( m_primitives ) );
2331
2333
2335 redraw();
2336}
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:106
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
TEARDROP_PARAMETERS & GetTeardropParams()
std::unique_ptr< PAD > m_Pad_Master
int GetLineThickness(PCB_LAYER_ID aLayer) const
Return the default graphic segment thickness from the layer class for the given layer.
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:230
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:240
VECTOR2I GetFPRelativePosition() const
Definition: board_item.cpp:254
void SetFPRelativePosition(const VECTOR2I &aPos)
Definition: board_item.cpp:268
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:800
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:498
bool LegacyTeardrops() const
Definition: board.h:1160
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:728
coord_type GetTop() const
Definition: box2.h:194
coord_type GetHeight() const
Definition: box2.h:188
coord_type GetWidth() const
Definition: box2.h:187
void Move(const Vec &aMoveVector)
Move the rectangle by the aMoveVector.
Definition: box2.h:111
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:506
coord_type GetRight() const
Definition: box2.h:189
coord_type GetLeft() const
Definition: box2.h:193
const Vec & GetSize() const
Definition: box2.h:179
coord_type GetBottom() const
Definition: box2.h:190
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Create an undo entry for an item that has been already modified.
Definition: commit.h:104
A dialog to edit basic shape parameters.
bool TransferDataFromWindow() override
Transfer data out of the GUI.
A dialog to apply geometry transforms to a shape or set of shapes (move, rotate around origin,...
void Transform(std::vector< std::shared_ptr< PCB_SHAPE > > *aList=nullptr, int aDuplicateCount=0)
Apply geometric transform (rotation, move, scale) defined in dialog aDuplicate = 1 .
A dialog to edit basic polygonal shape parameters.
bool TransferDataFromWindow() override
Transfer data out of the GUI.
Class DIALOG_PAD_PROPERTIES_BASE.
void OnUpdateUINonCopperWarning(wxUpdateUIEvent &event) override
void OnInitDialog(wxInitDialogEvent &event) override
void PadTypeSelected(wxCommandEvent &event) override
void OnPadShapeSelection(wxCommandEvent &event) override
bool transferDataToPad(PAD *aPad)
Copy values from dialog field to aPad's members.
void onAddPrimitive(wxCommandEvent &event) override
bool TransferDataFromWindow() override
Updates the different parameters for the component being edited.
bool Show(bool aShow) override
std::vector< std::shared_ptr< PCB_SHAPE > > m_primitives
bool padValuesOK()
test if all values are acceptable for the pad
void onPrimitiveDClick(wxMouseEvent &event) override
Called on a double click on the basic shapes list.
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 onEditPrimitive(wxCommandEvent &event) override
void onChangePadMode(wxCommandEvent &event) override
void OnPrimitiveSelection(wxListEvent &event) override
Called on selection/deselection of a basic shape.
std::vector< PCB_SHAPE * > m_highlight
KIGFX::ORIGIN_VIEWITEM * m_axisOrigin
void OnSetCopperLayers(wxCommandEvent &event) override
void OnCancel(wxCommandEvent &event) override
void onCornerRadiusChange(wxCommandEvent &event) override
void updatePadLayersList(LSET layer_mask, bool remove_unconnected, bool keep_top_bottom)
Updates the CheckBox states in pad layers list, based on the layer_mask (if non-empty) or the default...
PAD_PROP getSelectedProperty()
Return the pad property currently selected.
void OnSetLayers(wxCommandEvent &event) override
void onCornerSizePercentChange(wxCommandEvent &event) override
void enablePrimitivePage(bool aEnable)
enable (or disable) the primitive page editor
void OnPadToDieCheckbox(wxCommandEvent &event) override
void onTeardropCurvePointsUpdateUi(wxUpdateUIEvent &event) override
void onGeometryTransform(wxCommandEvent &event) override
void onDuplicatePrimitive(wxCommandEvent &event) override
void OnDrillShapeSelected(wxCommandEvent &event) override
void onDeletePrimitive(wxCommandEvent &event) override
Event handlers of basic shapes list panel.
void OnUpdateUI(wxUpdateUIEvent &event) override
bool Show(bool show) override
EDA_UNITS m_units
Definition: dialog_shim.h:203
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:97
void SetupStandardButtons(std::map< int, wxString > aLabels={})
int ShowQuasiModal()
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
bool IsType(FRAME_T aType) const
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
KIGFX::GAL_DISPLAY_OPTIONS & GetGalDisplayOptions()
Return a reference to the gal rendering options used by GAL for rendering.
GAL_TYPE GetBackend() const
Return the type of backend currently used by GAL canvas.
void StopDrawing()
Prevent the GAL canvas from further drawing until it is recreated or StartDrawing() is called.
KIGFX::VIEW_CONTROLS * GetViewControls() const
Return a pointer to the #VIEW_CONTROLS instance used in the panel.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
void StartDrawing()
Begin drawing if it was stopped previously.
void SetStealsFocus(bool aStealsFocus)
Set whether focus is taken on certain events (mouseover, keys, etc).
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:125
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:100
void SetFilled(bool aFlag)
Definition: eda_shape.h:95
void SetShape(SHAPE_T aShape)
Definition: eda_shape.h:112
void SetIsAnnotationProxy(bool aIsProxy=true)
Definition: eda_shape.h:88
bool IsFlipped() const
Definition: footprint.h:326
void ListSet(const wxString &aList)
Add a list of items.
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103
void SetGridSize(const VECTOR2D &aGridSize)
Set the grid size.
void SetGridVisibility(bool aVisibility)
Set the visibility setting of the grid.
void SetDrawAtZero(bool aDrawFlag)
Set the draw at zero flag.
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
PCB specific render settings.
Definition: pcb_painter.h:70
void SetLayerColor(int aLayer, const COLOR4D &aColor)
Change the color used to draw a layer.
An interface for classes handling user events controlling the view behavior such as zooming,...
void ApplySettings(const VC_SETTINGS &aSettings)
Load new settings from program common settings.
const VC_SETTINGS & GetSettings() const
Apply VIEW_CONTROLS settings from an object.
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:69
void SetViewport(const BOX2D &aViewport)
Set the visible area of the VIEW.
Definition: view.cpp:520
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:314
void SetBoundary(const BOX2D &aBoundary)
Set limits for view area.
Definition: view.h:279
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:1608
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:195
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:822
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:213
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:536
static LSET InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
Definition: lset.cpp:733
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:773
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition: netinfo.h:387
void SetBoard(BOARD *aBoard)
int GetSelectedNetcode()
void SetSelectedNetcode(int aNetcode)
void SetNetInfo(NETINFO_LIST *aNetInfoList)
Tool relating to pads and pad settings.
Definition: pad_tool.h:37
void SetLastPadNumber(const wxString &aPadNumber)
Definition: pad_tool.h:66
wxString GetLastPadNumber() const
Definition: pad_tool.h:65
Definition: pad.h:59
int GetLocalClearance(wxString *aSource) const override
Return any local clearances set in the "classic" (ie: pre-rule) system.
Definition: pad.cpp:815
bool IsAperturePad() const
Definition: pad.h:400
void SetAttribute(PAD_ATTRIB aAttribute)
Definition: pad.cpp:643
void SetLayerSet(LSET aLayers) override
Definition: pad.h:389
PAD_PROP GetProperty() const
Definition: pad.h:396
bool GetRemoveUnconnected() const
Definition: pad.h:602
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: pad.h:376
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pad.h:390
const VECTOR2I & GetDrillSize() const
Definition: pad.h:258
PAD_ATTRIB GetAttribute() const
Definition: pad.h:393
void SetLocalSolderPasteMargin(int aMargin)
Definition: pad.h:416
static LSET PTHMask()
layer set for a through hole pad
Definition: pad.cpp:195
ZONE_CONNECTION GetZoneConnection() const
Definition: pad.h:515
void SetRemoveUnconnected(bool aSet)
Set the unconnected removal property.
Definition: pad.h:601
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the pad shape to a closed polygon.
Definition: pad.cpp:1594
void SetThermalGap(int aGap)
Definition: pad.h:546
void SetThermalSpokeAngle(const EDA_ANGLE &aAngle)
The orientation of the thermal spokes.
Definition: pad.h:533
const wxString & GetNumber() const
Definition: pad.h:135
void MergePrimitivesAsPolygon(SHAPE_POLY_SET *aMergedPolygon, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Merge all basic shapes to a SHAPE_POLY_SET.
double GetLocalSolderPasteMarginRatio() const
Definition: pad.h:418
int GetRoundRectCornerRadius() const
Definition: pad.cpp:329
void DeletePrimitivesList()
Clear the basic shapes list.
void SetDrillShape(PAD_DRILL_SHAPE_T aShape)
Definition: pad.h:375
VECTOR2I GetPosition() const override
Definition: pad.h:202
void SetProperty(PAD_PROP aProperty)
Definition: pad.cpp:654
const std::vector< std::shared_ptr< PCB_SHAPE > > & GetPrimitives() const
Accessor to the basic shape list for custom-shaped pads.
Definition: pad.h:321
EDA_ANGLE GetThermalSpokeAngle() const
Definition: pad.h:534
void SetOffset(const VECTOR2I &aOffset)
Definition: pad.h:264
void SetChamferRectRatio(double aChamferScale)
Has meaning only for chamfered rectangular pads.
Definition: pad.cpp:352
const VECTOR2I & GetOffset() const
Definition: pad.h:265
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
Definition: pad.cpp:216
void SetRoundRectCornerRadius(double aRadius)
Has meaning only for rounded rectangle pads.
Definition: pad.cpp:335
void SetLocalClearance(int aClearance)
Definition: pad.h:413
void SetKeepTopBottom(bool aSet)
Set whether we keep the top and bottom connections even if they are not connected.
Definition: pad.h:607
void SetNumber(const wxString &aNumber)
Set the pad number (note that it can be alphanumeric, such as the array reference "AA12").
Definition: pad.h:134
void SetZoneConnection(ZONE_CONNECTION aType)
Definition: pad.h:514
int GetLocalSolderMaskMargin() const
Definition: pad.h:408
bool GetKeepTopBottom() const
Definition: pad.h:608
CUST_PAD_SHAPE_IN_ZONE GetCustomShapeInZoneOpt() const
Definition: pad.h:212
FOOTPRINT * GetParent() const
Definition: pad.cpp:1479
void SetDelta(const VECTOR2I &aSize)
Definition: pad.h:254
bool IsOnCopperLayer() const override
Definition: pad.cpp:769
void SetPosition(const VECTOR2I &aPos) override
Definition: pad.h:196
const VECTOR2I & GetDelta() const
Definition: pad.h:255
static LSET ConnSMDMask()
layer set for a SMD pad on Front layer used for edge board connectors
Definition: pad.cpp:209
void SetDrillSize(const VECTOR2I &aSize)
Definition: pad.h:257
PAD_SHAPE GetShape() const
Definition: pad.h:194
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition: pad.h:362
EDA_ANGLE GetFPRelativeOrientation()
Definition: pad.cpp:680
void Flip(const VECTOR2I &VECTOR2I, bool aFlipLeftRight) override
Flip this object, i.e.
Definition: pad.cpp:689
static LSET ApertureMask()
layer set for an aperture pad
Definition: pad.cpp:223
virtual const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: pad.cpp:1455
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: pad.cpp:202
void SetLocalSolderPasteMarginRatio(double aRatio)
Definition: pad.h:419
void SetShape(PAD_SHAPE aShape)
Set the new shape of this pad.
Definition: pad.h:185
int GetThermalSpokeWidth() const
Definition: pad.h:524
int GetLocalSolderPasteMargin() const
Definition: pad.h:415
void SetFPRelativeOrientation(const EDA_ANGLE &aAngle)
Definition: pad.cpp:671
void SetCustomShapeInZoneOpt(CUST_PAD_SHAPE_IN_ZONE aOption)
Set the option for the custom pad shape to use as clearance area in copper zones.
Definition: pad.h:222
void SetRoundRectRadiusRatio(double aRadiusScale)
Has meaning only for rounded rectangle pads.
Definition: pad.cpp:344
void SetAnchorPadShape(PAD_SHAPE aShape)
Set the shape of the anchor pad for custom shaped pads.
Definition: pad.h:233
void SetOrientation(const EDA_ANGLE &aAngle)
Set the rotation angle of the pad.
Definition: pad.cpp:662
int GetChamferPositions() const
Definition: pad.h:587
void ReplacePrimitives(const std::vector< std::shared_ptr< PCB_SHAPE > > &aPrimitivesList)
Clear the current custom shape primitives list and import a new list.
void SetLocalSolderMaskMargin(int aMargin)
Definition: pad.h:409
void SetThermalSpokeWidth(int aWidth)
Set the width of the thermal spokes connecting the pad to a zone.
Definition: pad.h:523
void SetSize(const VECTOR2I &aSize)
Definition: pad.h:247
double GetRoundRectRadiusRatio() const
Definition: pad.h:568
int GetThermalGap() const
Definition: pad.h:547
std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const override
Return a SHAPE_SEGMENT object representing the pad's hole.
Definition: pad.cpp:406
const VECTOR2I & GetSize() const
Definition: pad.h:248
void SetChamferPositions(int aPositions)
Has meaning only for chamfered rectangular pads.
Definition: pad.h:586
PAD_SHAPE GetAnchorPadShape() const
Definition: pad.h:207
double GetChamferRectRatio() const
Definition: pad.h:577
void SetPadToDieLength(int aLength)
Definition: pad.h:405
int GetPadToDieLength() const
Definition: pad.h:406
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
void ShowPadPropertiesDialog(PAD *aPad)
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
BOARD * GetBoard() const
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Returns the BOARD_DESIGN_SETTINGS for the open project.
void UpdateColors()
Update the color settings in the painter and GAL.
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
virtual void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
Definition: pcb_shape.cpp:187
virtual void Move(const VECTOR2I &aMoveVector) override
Move this object.
Definition: pcb_shape.cpp:159
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition: pcb_shape.h:72
Represent a set of closed polygons.
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset difference For aFastMode meaning, see function booleanOp.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
bool Collide(const SHAPE *aShape, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if the boundary of shape (this) lies closer to the shape aShape than aClearance,...
int OutlineCount() const
Return the number of outlines in the set.
Simple container to manage line stroke parameters.
Definition: stroke_params.h:88
int m_CurveSegCount
number of segments to build the curved sides of a teardrop area must be > 2.
double m_BestWidthRatio
The height of a teardrop as ratio between height and size of pad/via.
int m_TdMaxLen
max allowed length for teardrops in IU. <= 0 to disable
bool m_AllowUseTwoTracks
True to create teardrops using 2 track segments if the first in too small.
int m_TdMaxWidth
max allowed height for teardrops in IU. <= 0 to disable
double m_BestLengthRatio
The length of a teardrop as ratio between length and size of pad/via.
double m_WidthtoSizeFilterRatio
The ratio (H/D) between the via/pad size and the track width max value to create a teardrop 1....
bool m_TdOnPadsInZones
A filter to exclude pads inside zone fills.
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:54
int GetIntValue()
Definition: unit_binder.h:127
virtual void ChangeDoubleValue(double aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion WITHOUT trigger...
virtual long long int GetValue()
Return the current value in Internal Units.
void Enable(bool aEnable)
Enable/disable the label, widget and units label.
virtual void SetPrecision(int aLength)
Normally not needed, but can be used to set the precision when using internal units that are floats (...
virtual void SetUnits(EDA_UNITS aUnits)
Normally not needed (as the UNIT_BINDER inherits from the parent frame), but can be used to set to DE...
virtual EDA_ANGLE GetAngleValue()
virtual void SetNegativeZero()
Definition: unit_binder.h:71
virtual double GetDoubleValue()
Return the current value in Internal Units.
virtual void SetAngleValue(const EDA_ANGLE &aValue)
virtual void ChangeAngleValue(const EDA_ANGLE &aValue)
virtual void SetDoubleValue(double aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
virtual bool Validate(double aMin, double aMax, EDA_UNITS aUnits=EDA_UNITS::UNSCALED)
Validate the control against the given range, informing the user of any errors found.
virtual void ChangeValue(int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion WITHOUT trigger...
virtual void SetValue(long long int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
void Show(bool aShow, bool aResize=false)
Show/hide the label, widget and units label.
void SetCoordType(ORIGIN_TRANSFORMS::COORD_TYPES_T aCoordType)
Set the current origin transform mode.
Definition: unit_binder.h:189
@ LIGHTBLUE
Definition: color4d.h:61
This file is part of the common library.
void TransformOvalToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
#define APERTURE_DLG_TYPE
#define CONN_DLG_TYPE
static PAD_ATTRIB code_type[]
#define SELECTED_ITEMS_LAYER
static PAD_SHAPE code_shape[]
#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
static wxString formatCoord(EDA_UNITS aUnits, const VECTOR2I &aCoord)
#define PAD_PROPERTIES_DLG_NAME
DIALOG_PAD_PROPERTIES, derived from DIALOG_PAD_PROPERTIES_BASE, created by wxFormBuilder.
#define _(s)
static constexpr EDA_ANGLE & ANGLE_45
Definition: eda_angle.h:430
static constexpr EDA_ANGLE & ANGLE_90
Definition: eda_angle.h:431
#define BRIGHTENED
item is drawn with a bright contour
#define SELECTED
Item was manually selected by the user.
SHAPE_T
Definition: eda_shape.h:41
EDA_UNITS
Definition: eda_units.h:43
@ FRAME_PCB_EDITOR
Definition: frame_type.h:40
@ ERROR_INSIDE
@ B_Adhes
Definition: layer_ids.h:97
@ Dwgs_User
Definition: layer_ids.h:109
@ F_Paste
Definition: layer_ids.h:101
@ F_Adhes
Definition: layer_ids.h:98
@ B_Mask
Definition: layer_ids.h:106
@ B_Cu
Definition: layer_ids.h:95
@ Eco1_User
Definition: layer_ids.h:111
@ F_Mask
Definition: layer_ids.h:107
@ B_Paste
Definition: layer_ids.h:100
@ F_SilkS
Definition: layer_ids.h:104
@ UNDEFINED_LAYER
Definition: layer_ids.h:60
@ Eco2_User
Definition: layer_ids.h:112
@ B_SilkS
Definition: layer_ids.h:103
@ F_Cu
Definition: layer_ids.h:64
This file contains miscellaneous commonly used macros and functions.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
wxString MessageTextFromValue(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, double aValue, bool aAddUnitsText=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
A helper to convert the double length aValue to a string in inches, millimeters, or unscaled units.
Definition: eda_units.cpp:315
std::string FormatAngle(const EDA_ANGLE &aAngle)
Converts aAngle from board units to a string appropriate for writing to file.
Definition: eda_units.cpp:134
wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:156
@ CUST_PAD_SHAPE_IN_ZONE_OUTLINE
Definition: pad.h:45
@ CUST_PAD_SHAPE_IN_ZONE_CONVEXHULL
Definition: pad.h:46
PAD_ATTRIB
The set of pad shapes, used with PAD::{Set,Get}Attribute().
Definition: pad_shapes.h:81
@ NPTH
like PAD_PTH, but not plated
@ SMD
Smd pad, appears on the solder paste layer (default)
@ PTH
Plated through hole pad.
@ CONN
Like smd, does not appear on the solder paste layer (default)
@ PAD_DRILL_SHAPE_CIRCLE
Definition: pad_shapes.h:70
@ PAD_DRILL_SHAPE_OBLONG
Definition: pad_shapes.h:71
PAD_SHAPE
The set of pad shapes, used with PAD::{Set,Get}Shape()
Definition: pad_shapes.h:35
PAD_PROP
The set of pad properties used in Gerber files (Draw files, and P&P files) to define some properties ...
Definition: pad_shapes.h:97
const double IU_PER_MM
Definition: base_units.h:77
constexpr int mmToIU(double mm) const
Definition: base_units.h:89
constexpr int delta
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85
VECTOR2< double > VECTOR2D
Definition: vector2d.h:587
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588