KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pad_tool.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20
21#include "pad_tool.h"
22
23#include <algorithm>
24#include <memory>
25#include <optional>
26#include <unordered_map>
27
28#include <kiid.h>
29#include <pcb_painter.h>
30#include <kiplatform/ui.h>
31#include <macros.h>
33#include <view/view_controls.h>
34#include <tool/tool_manager.h>
37#include <board_item.h>
38#include <collectors.h>
39#include <footprint.h>
40#include <pcb_shape.h>
41#include <pad.h>
42#include <pad_utils.h>
43#include <pcbnew_settings.h>
44#include <string_utils.h>
45#include <board_commit.h>
48#include <tools/pcb_actions.h>
52#include <tools/edit_tool.h>
54#include <widgets/wx_infobar.h>
55
56
58
59
61{
62public:
73
75
90 PAD GetMasterPad( TYPE aType, const FOOTPRINT* aFootprint, const PAD* aSelectedPad ) const
91 {
92 std::vector<const PAD*> fpPads;
93
94 if( aFootprint )
95 {
96 fpPads.assign( aFootprint->Pads().begin(), aFootprint->Pads().end() );
97
98 const auto reverseNumberSorter =
99 []( const PAD* a, const PAD* b )
100 {
101 return StrNumCmp( a->GetNumber(), b->GetNumber() ) > 0;
102 };
103
104 // Sort the pads in reverse number order (we want to avoid choosing pin 1, usually)
105 std::sort( fpPads.begin(), fpPads.end(), reverseNumberSorter );
106 }
107
108 // Resolve the most recent pad type if the requested type is AUTO.
109 // Note that the selection-copy logic is only used for AUTO. If the user uses,
110 // say, THT explicitly, then we don't try to copy the selection.
111 if( aType == TYPE::AUTO )
112 {
113 aType = resolveAutoType( fpPads, aSelectedPad );
114
115 // If the type came from the selected pad, that pad is the template as well.
116 if( aSelectedPad && TypeFromPad( *aSelectedPad ) == aType )
117 return *aSelectedPad;
118 }
119
120 // See if the most recently created pad of the requested type can still be found
121 if( auto lastRealPadIt = m_lastRealPadsForType.find( aType ); lastRealPadIt != m_lastRealPadsForType.end() )
122 {
123 for( const PAD* pad : fpPads )
124 {
125 if( pad->m_Uuid == lastRealPadIt->second )
126 {
127 // Check it still has this type
128 std::optional<TYPE> padType = TypeFromPad( *pad );
129 if( !padType || *padType != aType )
130 break;
131
132 return *pad;
133 }
134 }
135 }
136
137 // If that doesn't work, look in the current footprint for ideas
138 if( aFootprint )
139 {
140 for( const PAD* pad : fpPads )
141 {
142 std::optional<TYPE> padType = TypeFromPad( *pad );
143
144 // If this pad is the one we're looking for
145 if( padType && *padType == aType )
146 {
147 return *pad;
148 }
149 }
150 }
151
152 // If we still don't have a master pad, fall back to a constructed default
153 return *MakeDefaultPad( aType );
154 }
155
159 std::unique_ptr<PAD> MakeDefaultPad( PAD_MASTER_PROVIDER::TYPE aMasterType ) const
160 {
161 std::unique_ptr<PAD> pad = std::make_unique<PAD>( nullptr );
162
163 pad->SetPadstackMode( PADSTACK::MODE::NORMAL );
164 pad->SetThermalSpokeAngle( ANGLE_90 );
165
166 switch( aMasterType )
167 {
168 case PAD_MASTER_PROVIDER::TYPE::THT:
169 {
170 pad->SetAttribute( PAD_ATTRIB::PTH );
171 pad->SetLayerSet( PAD::PTHMask() );
173
177 } );
178
179 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
180 pad->SetDrillSize( VECTOR2D{
183 } );
184 break;
185 }
186 case PAD_MASTER_PROVIDER::TYPE::SMD:
187 {
188 pad->SetAttribute( PAD_ATTRIB::SMD );
189 pad->SetLayerSet( PAD::SMDMask() );
190
192
196 } );
197 // No drill for SMD pads
198 break;
199 }
200 case PAD_MASTER_PROVIDER::TYPE::NPTH:
201 {
202 pad->SetAttribute( PAD_ATTRIB::NPTH );
203 pad->SetLayerSet( PAD::UnplatedHoleMask() );
205
206 const VECTOR2D size = VECTOR2D{
209 };
210 pad->SetSize( PADSTACK::ALL_LAYERS, size );
211 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
212 pad->SetDrillSize( size );
213
214 break;
215 }
216 case PAD_MASTER_PROVIDER::TYPE::PASTE:
217 case PAD_MASTER_PROVIDER::TYPE::MASK:
218 {
219 pad->SetAttribute( PAD_ATTRIB::SMD );
220
221 if( aMasterType == PAD_MASTER_PROVIDER::TYPE::PASTE )
222 pad->SetLayerSet( PAD::ApertureMask() );
223 else
224 pad->SetLayerSet( LSET{ F_Mask } );
225
230 } );
231 break;
232 }
233 case PAD_MASTER_PROVIDER::TYPE::CONNECTOR:
234 {
235 pad->SetAttribute( PAD_ATTRIB::CONN );
236 pad->SetLayerSet( PAD::ConnSMDMask() );
237
242 } );
243 break;
244 }
245 // No Default: handle every case explicitly
246 case PAD_MASTER_PROVIDER::TYPE::AUTO:
247 {
248 wxFAIL_MSG( "AUTO pad type should not be used for default pad creation" );
249 break;
250 }
251 }
252
253 // Set an IPC-standard rouding radius when useful
254 if( pad->GetShape( PADSTACK::ALL_LAYERS ) == PAD_SHAPE::ROUNDRECT )
255 {
257 pad->SetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS, newRadius );
258 }
259
260 return pad;
261 }
262
268 void RecordNewMasterPad( const PAD& aPlacedPad )
269 {
270 std::optional<TYPE> padType = TypeFromPad( aPlacedPad );
271
272 // Don't update the MRU records if the pad type could not be determined.
273 if( !padType )
274 return;
275
276 m_lastType = *padType;
277 m_lastRealPadsForType[*padType] = aPlacedPad.m_Uuid;
278 }
279
280 static TYPE TypeFromAction( const TOOL_EVENT& aEvent )
281 {
282 if( aEvent.IsAction( &PCB_ACTIONS::placeThtPad ) )
283 return TYPE::THT;
284 if( aEvent.IsAction( &PCB_ACTIONS::placeSmdPad ) )
285 return TYPE::SMD;
286 if( aEvent.IsAction( &PCB_ACTIONS::placeNpthPad ) )
287 return TYPE::NPTH;
289 return TYPE::PASTE;
290
291 return TYPE::AUTO;
292 }
293
299 static std::optional<TYPE> TypeFromPad( const PAD& aPad )
300 {
301 if( aPad.GetAttribute() == PAD_ATTRIB::PTH )
302 return TYPE::THT;
303 if( aPad.GetAttribute() == PAD_ATTRIB::SMD )
304 {
305 if( aPad.IsAperturePad() )
306 {
307 if( ( aPad.GetLayerSet() & LSET{ F_Paste, B_Paste } ).any() )
308 return TYPE::PASTE;
309
310 if( ( aPad.GetLayerSet() & LSET{ F_Mask, B_Mask } ).any() )
311 return TYPE::MASK;
312
313 // Weird case: an aperture pad with no paste or mask layers
314 return std::nullopt;
315 }
316
317 return TYPE::SMD;
318 }
319 if( aPad.GetAttribute() == PAD_ATTRIB::CONN )
320 return TYPE::CONNECTOR;
321 if( aPad.GetAttribute() == PAD_ATTRIB::NPTH )
322 return TYPE::NPTH;
323
324 return std::nullopt;
325 }
326
327private:
338 TYPE resolveAutoType( const std::vector<const PAD*>& aFpPads, const PAD* aSelectedPad ) const
339 {
340 if( aSelectedPad )
341 {
342 std::optional<TYPE> selectedType = TypeFromPad( *aSelectedPad );
343 if( selectedType )
344 return *selectedType;
345 }
346
347 if( m_lastType != TYPE::AUTO )
348 return m_lastType;
349
350 for( const PAD* pad : aFpPads )
351 {
352 if( std::optional<TYPE> padType = TypeFromPad( *pad ) )
353 return *padType;
354 }
355
356 return TYPE::THT;
357 }
358
359 // Persistent store of the last real pad's ID for each type.
360 // Note that the pad with this UUID may not exist in the current footprint,
361 // or may no longer have the recorded type.
362 std::unordered_map<TYPE, KIID> m_lastRealPadsForType;
363
365 TYPE m_lastType = PAD_MASTER_PROVIDER::TYPE::AUTO;
366};
367
368
370 PCB_TOOL_BASE( "pcbnew.PadTool" ),
374 m_bufferPad( std::make_unique<PAD>( nullptr ) )
375{
376 // Seed the paste buffer with a sensible default at startup.
377 m_bufferPad->ImportSettingsFrom( *m_masterPadProvider->MakeDefaultPad( PAD_MASTER_PROVIDER::TYPE::THT ) );
378}
379
380
384
385
387{
388 m_masterPadProvider->RecordNewMasterPad( aPad );
389}
390
391
393{
394 if( aReason == MODEL_RELOAD )
395 m_lastPadNumber = wxT( "1" );
396
397 if( board() && board()->ResolveItem( m_editPad ) == DELETED_BOARD_ITEM::GetInstance() )
398 {
399 PCB_DISPLAY_OPTIONS opts = frame()->GetDisplayOptions();
400
402 {
404 frame()->SetDisplayOptions( opts );
405 }
406
407 frame()->GetInfoBar()->Dismiss();
408
410 }
411}
412
413
415{
416 static const std::vector<KICAD_T> padTypes = { PCB_PAD_T };
417
418 PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
419
420 if( selTool )
421 {
422 // Add context menu entries that are displayed when selection tool is active
423 CONDITIONAL_MENU& menu = selTool->GetToolMenu().GetMenu();
424
428
429 auto explodeCondition =
430 [this]( const SELECTION& aSel )
431 {
432 return m_editPad == niluuid && aSel.Size() == 1 && aSel[0]->Type() == PCB_PAD_T;
433 };
434
435 auto recombineCondition =
436 [this]( const SELECTION& aSel )
437 {
438 return m_editPad != niluuid;
439 };
440
441 menu.AddSeparator( 400 );
442
444 {
447 menu.AddItem( PCB_ACTIONS::recombinePad, recombineCondition, 400 );
448 menu.AddItem( PCB_ACTIONS::explodePad, explodeCondition, 400 );
449 }
450
451 menu.AddItem( PCB_ACTIONS::copyPadSettings, singlePadSel, 400 );
452 menu.AddItem( PCB_ACTIONS::applyPadSettings, padSel, 400 );
453 menu.AddItem( PCB_ACTIONS::pushPadSettings, singlePadSel, 400 );
454 }
455
456 auto& ctxMenu = m_menu->GetMenu();
457
458 // cancel current tool goes in main context menu at the top if present
460 ctxMenu.AddSeparator( 1 );
461
468
469 // Finally, add the standard zoom/grid items
470 getEditFrame<PCB_BASE_FRAME>()->AddStandardSubMenus( *m_menu.get() );
471
472 return true;
473}
474
475
477{
478 PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
479 const PCB_SELECTION& selection = selTool->GetSelection();
480
481 BOARD_COMMIT commit( frame() );
482
483 // for every selected pad, paste global settings
484 for( EDA_ITEM* item : selection )
485 {
486 if( item->Type() == PCB_PAD_T )
487 {
488 commit.Modify( item );
489 static_cast<PAD&>( *item ).ImportSettingsFrom( *m_bufferPad );
490 }
491 }
492
493 commit.Push( _( "Paste Pad Properties" ) );
494
496 frame()->Refresh();
497
498 return 0;
499}
500
501
503{
504 PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
505 const PCB_SELECTION& selection = selTool->GetSelection();
506
507 // can only copy from a single pad
508 if( selection.Size() == 1 )
509 {
510 EDA_ITEM* item = selection[0];
511
512 if( item->Type() == PCB_PAD_T )
513 {
514 const PAD& selPad = static_cast<const PAD&>( *item );
515
516 // Store the settings in the buffer pad for paste
517 m_bufferPad->ImportSettingsFrom( selPad );
518
519 // And push into the master pad provider for future use
520 m_masterPadProvider->RecordNewMasterPad( selPad );
521 }
522 }
523
524 return 0;
525}
526
527
528static void doPushPadProperties( BOARD& board, const PAD& aSrcPad, BOARD_COMMIT& commit, bool aSameFootprints,
529 bool aPadShapeFilter, bool aPadSizeFilter, bool aPadOrientFilter, bool aPadLayerFilter,
530 bool aPadTypeFilter )
531{
532 const FOOTPRINT* refFootprint = aSrcPad.GetParentFootprint();
533
534 EDA_ANGLE srcPadAngle = aSrcPad.GetOrientation() - refFootprint->GetOrientation();
535
536 for( FOOTPRINT* footprint : board.Footprints() )
537 {
538 if( !aSameFootprints && ( footprint != refFootprint ) )
539 continue;
540
541 if( footprint->GetFPID() != refFootprint->GetFPID() )
542 continue;
543
544 for( PAD* pad : footprint->Pads() )
545 {
546 if( aPadShapeFilter )
547 {
548 bool shapesMatch = true;
549
550 // Compare in both directions to catch all potentialy unique layer defintions
551 pad->Padstack().ForEachUniqueLayer(
552 [&]( PCB_LAYER_ID aLayer )
553 {
554 if( pad->GetShape( aLayer ) != aSrcPad.GetShape( aLayer ) )
555 shapesMatch = false;
556 } );
557
559 [&]( PCB_LAYER_ID aLayer )
560 {
561 if( aSrcPad.GetShape( aLayer ) != pad->GetShape( aLayer ) )
562 shapesMatch = false;
563 } );
564
565 if( !shapesMatch )
566 continue;
567 }
568
569 EDA_ANGLE padAngle = pad->GetOrientation() - footprint->GetOrientation();
570
571 if( aPadSizeFilter && ( pad->GetSize( PADSTACK::ALL_LAYERS ) != aSrcPad.GetSize( PADSTACK::ALL_LAYERS ) ) )
572 continue;
573
574 if( aPadOrientFilter && ( padAngle != srcPadAngle ) )
575 continue;
576
577 if( aPadLayerFilter && ( pad->GetLayerSet() != aSrcPad.GetLayerSet() ) )
578 continue;
579
580 if( aPadTypeFilter && ( pad->GetAttribute() != aSrcPad.GetAttribute() ) )
581 continue;
582
583 // Special-case for aperture pads
584 if( aPadTypeFilter && pad->GetAttribute() == PAD_ATTRIB::CONN )
585 {
586 if( pad->IsAperturePad() != aSrcPad.IsAperturePad() )
587 continue;
588 }
589
590 commit.Modify( pad );
591
592 // Apply source pad settings to this pad
593 pad->ImportSettingsFrom( aSrcPad );
594 }
595 }
596}
597
598
600{
601 PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
602 const PCB_SELECTION& selection = selTool->GetSelection();
603
604 if( selection.Size() == 1 && selection[0]->Type() == PCB_PAD_T )
605 {
606 PAD* srcPad = static_cast<PAD*>( selection[0] );
607
608 if( FOOTPRINT* footprint = srcPad->GetParentFootprint() )
609 {
610 frame()->SetMsgPanel( footprint );
611
613 int dialogRet = dlg.ShowModal();
614
615 if( dialogRet == wxID_CANCEL )
616 return 0;
617
618 const bool edit_Same_Modules = (dialogRet == 1);
619
620 BOARD_COMMIT commit( frame() );
621
622 doPushPadProperties( *getModel<BOARD>(), *srcPad, commit, edit_Same_Modules, dlg.GetPadShapeFilter(),
624 dlg.GetPadTypeFilter() );
625
626 commit.Push( _( "Push Pad Settings" ) );
627
629 frame()->Refresh();
630 }
631 }
632
633 return 0;
634}
635
636
643static std::optional<SEQUENTIAL_PAD_ENUMERATION_PARAMS> GetSequentialPadNumberingParams( wxWindow* aFrame )
644{
645 // Persistent settings for the pad enumeration dialog.
646 static SEQUENTIAL_PAD_ENUMERATION_PARAMS s_lastUsedParams;
647
648 DIALOG_ENUM_PADS settingsDlg( aFrame, s_lastUsedParams );
649
650 if( settingsDlg.ShowModal() != wxID_OK )
651 return std::nullopt;
652
653 return s_lastUsedParams;
654}
655
656
658{
660 return 0;
661
662 if( !board()->GetFirstFootprint() || board()->GetFirstFootprint()->Pads().empty() )
663 return 0;
664
665 GENERAL_COLLECTOR collector;
666 GENERAL_COLLECTORS_GUIDE guide = frame()->GetCollectorsGuide();
667 guide.SetIgnoreFPTextOnBack( true );
668 guide.SetIgnoreFPTextOnFront( true );
669 guide.SetIgnoreFPValues( true );
670 guide.SetIgnoreFPReferences( true );
671
672 const std::optional<SEQUENTIAL_PAD_ENUMERATION_PARAMS> params = GetSequentialPadNumberingParams( frame() );
673
674 // Cancelled or otherwise failed to get any useful parameters
675 if( !params )
676 return 0;
677
678 int seqPadNum = params->m_start_number;
679
680 std::deque<int> storedPadNumbers;
681 std::map<wxString, std::pair<int, wxString>> oldNumbers;
682
684
685 SCOPED_TOOL_PUSHER raii( frame(), aEvent );
686
687 VECTOR2I oldMousePos; // store the previous mouse cursor position, during mouse drag
688 std::list<PAD*> selectedPads;
689 BOARD_COMMIT commit( frame() );
690 bool isFirstPoint = true; // make sure oldMousePos is initialized at least once
691 std::deque<PAD*> pads = board()->GetFirstFootprint()->Pads();
692 MAGNETIC_SETTINGS mag_settings;
693
694 mag_settings.graphics = false;
695 mag_settings.tracks = MAGNETIC_OPTIONS::NO_EFFECT;
697
698 PCB_GRID_HELPER grid( m_toolMgr, &mag_settings );
699
700 grid.SetSnap( true );
701 grid.SetUseGrid( false );
702
703 auto setCursor =
704 [&]()
705 {
707 };
708
709 KIGFX::VIEW* view = m_toolMgr->GetView();
710 RENDER_SETTINGS* settings = view->GetPainter()->GetSettings();
711 const std::set<int>& activeLayers = settings->GetHighContrastLayers();
712 bool isHighContrast = settings->GetHighContrast();
713
714 view->SyncLayerVisibilityCache(); // Required for ViewGetLOD() calls.
715
716 auto checkVisibility =
717 [&]( BOARD_ITEM* item )
718 {
719 if( !view->IsVisible( item ) )
720 return false;
721
722 for( PCB_LAYER_ID layer : item->GetLayerSet() )
723 {
724 if( ( isHighContrast && activeLayers.count( layer ) ) || view->IsLayerVisible( layer ) )
725 {
726 if( item->ViewGetLOD( layer, view ) < view->GetScale() )
727 return true;
728 }
729 }
730
731 return false;
732 };
733
734 for( PAD* pad : board()->GetFirstFootprint()->Pads() )
735 {
736 if( checkVisibility( pad ) )
737 pads.push_back( pad );
738 }
739
740 Activate();
741 // Must be done after Activate() so that it gets set into the correct context
742 getViewControls()->ShowCursor( true );
744 // Set initial cursor
745 setCursor();
746
747 STATUS_TEXT_POPUP statusPopup( frame() );
748
749 // Callable lambda to construct the pad number string for the given value
750 const auto constructPadNumber =
751 [&]( int aValue )
752 {
753 return wxString::Format( wxT( "%s%d" ), params->m_prefix.value_or( "" ), aValue );
754 };
755
756 // Callable lambda to set the popup text for the given pad value
757 const auto setPopupTextForValue =
758 [&]( int aValue )
759 {
760 const wxString msg = _( "Click on pad %s\n"
761 "Press <esc> to cancel all; double-click to finish" );
762 statusPopup.SetText( wxString::Format( msg, constructPadNumber( aValue ) ) );
763 };
764
765 setPopupTextForValue( seqPadNum );
766 statusPopup.Popup();
767 statusPopup.Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, 20 ) );
768 canvas()->SetStatusPopup( statusPopup.GetPanel() );
769
770 while( TOOL_EVENT* evt = Wait() )
771 {
772 setCursor();
773
775 VECTOR2I cursorPos = grid.SnapToPad( mousePos, pads );
776 getViewControls()->ForceCursorPosition( true, cursorPos );
777
778 if( evt->IsCancelInteractive() )
779 {
781 commit.Revert();
782 break;
783 }
784 else if( evt->IsActivate() )
785 {
786 commit.Push( _( "Renumber Pads" ) );
787 break;
788 }
789 else if( evt->IsDrag( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) )
790 {
791 selectedPads.clear();
792
793 // Be sure the old cursor mouse position was initialized:
794 if( isFirstPoint )
795 {
796 oldMousePos = mousePos;
797 isFirstPoint = false;
798 }
799
800 // wxWidgets deliver mouse move events not frequently enough, resulting in skipping
801 // pads if the user moves cursor too fast. To solve it, create a line that approximates
802 // the mouse move and search pads that are on the line.
803 int distance = ( mousePos - oldMousePos ).EuclideanNorm();
804 // Search will be made every 0.1 mm:
805 int segments = distance / int( 0.1 * pcbIUScale.IU_PER_MM ) + 1;
806 const VECTOR2I line_step( ( mousePos - oldMousePos ) / segments );
807
808 collector.Empty();
809
810 for( int j = 0; j < segments; ++j )
811 {
812 VECTOR2I testpoint( mousePos.x - j * line_step.x, mousePos.y - j * line_step.y );
813 collector.Collect( board(), { PCB_PAD_T }, testpoint, guide );
814
815 for( int i = 0; i < collector.GetCount(); ++i )
816 {
817 PAD* pad = static_cast<PAD*>( collector[i] );
818
819 if( pad->CanHaveNumber() && checkVisibility( pad ) )
820 selectedPads.push_back( pad );
821 }
822 }
823
824 selectedPads.unique();
825
826 for( PAD* pad : selectedPads )
827 {
828 // If pad was not selected, then enumerate it
829 if( !pad->IsSelected() )
830 {
831 commit.Modify( pad );
832
833 // Rename pad and store the old name
834 int newval;
835
836 if( storedPadNumbers.size() > 0 )
837 {
838 newval = storedPadNumbers.front();
839 storedPadNumbers.pop_front();
840 }
841 else
842 {
843 newval = seqPadNum;
844 seqPadNum += params->m_step;
845 }
846
847 const wxString newNumber = constructPadNumber( newval );
848 oldNumbers[newNumber] = { newval, pad->GetNumber() };
849 pad->SetNumber( newNumber );
850 SetLastPadNumber( newNumber );
851 pad->SetSelected();
852 getView()->Update( pad );
853
854 // Ensure the popup text shows the correct next value
855 if( storedPadNumbers.size() > 0 )
856 newval = storedPadNumbers.front();
857 else
858 newval = seqPadNum;
859
860 setPopupTextForValue( newval );
861 }
862
863 // ... or restore the old name if it was enumerated and clicked again
864 else if( pad->IsSelected() && evt->IsClick( BUT_LEFT ) )
865 {
866 auto it = oldNumbers.find( pad->GetNumber() );
867 wxASSERT( it != oldNumbers.end() );
868
869 if( it != oldNumbers.end() )
870 {
871 storedPadNumbers.push_back( it->second.first );
872 pad->SetNumber( it->second.second );
873 SetLastPadNumber( it->second.second );
874 oldNumbers.erase( it );
875
876 const int newval = storedPadNumbers.front();
877 setPopupTextForValue( newval );
878 }
879
880 pad->ClearSelected();
881 getView()->Update( pad );
882 }
883 }
884 }
885 else if( evt->IsDblClick( BUT_LEFT ) || evt->IsAction( &ACTIONS::cursorDblClick ) )
886 {
887 commit.Push( _( "Renumber Pads" ) );
888 break;
889 }
890 else if( evt->IsClick( BUT_RIGHT ) )
891 {
892 m_menu->ShowContextMenu( selection() );
893 }
894 else
895 {
896 evt->SetPassEvent();
897 }
898
899 // Prepare the next loop by updating the old cursor mouse position
900 // to this last mouse cursor position
901 oldMousePos = mousePos;
902 statusPopup.Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, 20 ) );
903 }
904
905 for( PAD* p : board()->GetFirstFootprint()->Pads() )
906 {
907 p->ClearSelected();
908 getView()->Update( p );
909 }
910
911 canvas()->SetStatusPopup( nullptr );
912 statusPopup.Hide();
913
916 return 0;
917}
918
919
920int PAD_TOOL::PlacePad( const TOOL_EVENT& aEvent )
921{
922 // When creating a new pad (in FP editor) we can use a new pad number or the last entered pad number
923 // neednewPadNumber = true to create a new pad number, false to use the last entered pad number
924 static bool neednewPadNumber;
925
927 return 0;
928
929 if( !board()->GetFirstFootprint() )
930 return 0;
931
932 struct PAD_PLACER : public INTERACTIVE_PLACER_BASE
933 {
934 PAD_PLACER( PAD_TOOL* aPadTool, PCB_BASE_EDIT_FRAME* aFrame, PAD_MASTER_PROVIDER& aMasterPadProvider,
935 PAD_MASTER_PROVIDER::TYPE aMasterType, std::unique_ptr<PAD> aSelectedPadCopy ) :
936 m_padTool( aPadTool ),
937 m_gridHelper( aPadTool->GetManager(), aFrame->GetMagneticItemsSettings() ),
938 m_masterPadProvider( aMasterPadProvider ),
939 m_masterPadType( aMasterType ),
940 m_selectedPadCopy( std::move( aSelectedPadCopy ) )
941 {
942 m_frame = aFrame;
943 m_board = aFrame->GetBoard();
944
945 neednewPadNumber = true; // Use a new pad number when creating a pad by default
946 }
947
948 ~PAD_PLACER() = default;
949
950 std::unique_ptr<BOARD_ITEM> CreateItem() override
951 {
952 std::unique_ptr<PAD> pad = std::make_unique<PAD>( m_board->GetFirstFootprint() );
953
954 const PAD master = m_masterPadProvider.GetMasterPad( m_masterPadType, m_board->GetFirstFootprint(),
955 m_selectedPadCopy.get() );
956
957 pad->ImportSettingsFrom( master );
958
959 if( pad->CanHaveNumber() )
960 {
961 wxString padNumber = m_padTool->GetLastPadNumber();
962
963 // Use the last entered pad number when recreating a pad without using the
964 // previously created pad, and a new number when creating a really new pad
965 if( neednewPadNumber )
966 padNumber = m_board->GetFirstFootprint()->GetNextPadNumber( padNumber );
967
968 pad->SetNumber( padNumber );
969 m_padTool->SetLastPadNumber( padNumber );
970
971 // If a pad is recreated and the previously created was not placed, use
972 // the last entered pad number
973 neednewPadNumber = false;
974 }
975
976 return pad;
977 }
978
979 bool PlaceItem( BOARD_ITEM *aItem, BOARD_COMMIT& aCommit ) override
980 {
981 PAD* pad = dynamic_cast<PAD*>( aItem );
982 // We are using this pad number.
983 // therefore use a new pad number for a newly created pad
984 neednewPadNumber = true;
985
986 if( pad )
987 {
988 m_masterPadProvider.RecordNewMasterPad( *pad );
989 aCommit.Add( aItem );
990 return true;
991 }
992
993 return false;
994 }
995
996 void SnapItem( BOARD_ITEM *aItem ) override
997 {
998 m_gridHelper.SetSnap( !( m_modifiers & MD_SHIFT ) );
999 m_gridHelper.SetUseGrid( !( m_modifiers & MD_CTRL ) );
1000
1001 if( !m_gridHelper.GetSnap() )
1002 return;
1003
1004 MAGNETIC_SETTINGS* settings = m_frame->GetMagneticItemsSettings();
1005 PAD* pad = static_cast<PAD*>( aItem );
1006 VECTOR2I position = m_padTool->getViewControls()->GetMousePosition();
1007 KIGFX::VIEW_CONTROLS* viewControls = m_padTool->getViewControls();
1008 std::vector<BOARD_ITEM*> ignored_items( 1, pad );
1009
1010 if( settings->pads == MAGNETIC_OPTIONS::NO_EFFECT )
1011 {
1012 PADS& pads = m_board->GetFirstFootprint()->Pads();
1013 ignored_items.insert( ignored_items.end(), pads.begin(), pads.end() );
1014 }
1015
1016 if( !settings->graphics )
1017 {
1018 DRAWINGS& graphics = m_board->GetFirstFootprint()->GraphicalItems();
1019 ignored_items.insert( ignored_items.end(), graphics.begin(), graphics.end() );
1020 }
1021
1022 VECTOR2I cursorPos = m_gridHelper.ResolveSnap( position, LSET::AllLayersMask(),
1023 GRID_CURRENT, ignored_items ).position;
1024 viewControls->ForceCursorPosition( true, cursorPos );
1025 aItem->SetPosition( cursorPos );
1026 }
1027
1028 PAD_TOOL* m_padTool;
1029 PCB_GRID_HELPER m_gridHelper;
1031 PAD_MASTER_PROVIDER::TYPE m_masterPadType;
1032 std::unique_ptr<PAD> m_selectedPadCopy;
1033 };
1034
1035 const PAD_MASTER_PROVIDER::TYPE masterPadType = PAD_MASTER_PROVIDER::TypeFromAction( aEvent );
1036
1037 // The interactive placement helper clears the selection, so do this beforehand.
1038 std::unique_ptr<PAD> selectedPad;
1039
1040 if( PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>() )
1041 {
1042 for( const EDA_ITEM* item : selTool->GetSelection() )
1043 {
1044 // Choose a pad from the selection if available
1045 if( item->Type() == PCB_PAD_T )
1046 {
1047 selectedPad = std::make_unique<PAD>( *static_cast<const PAD*>( item ) );
1048 break;
1049 }
1050 }
1051 }
1052
1053 PAD_PLACER placer( this, frame(), *m_masterPadProvider, masterPadType, std::move( selectedPad ) );
1054
1055 doInteractiveItemPlacement( aEvent, &placer, _( "Place pad" ),
1057
1058 return 0;
1059}
1060
1061
1062int PAD_TOOL::EditPad( const TOOL_EVENT& aEvent )
1063{
1064 if( !m_isFootprintEditor )
1065 return 0;
1066
1067 Activate();
1068
1069 KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( view()->GetPainter() );
1070 PCB_RENDER_SETTINGS* settings = painter->GetSettings();
1071 PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
1072
1073 if( m_editPad != niluuid )
1074 {
1075 if( PAD* pad = dynamic_cast<PAD*>( frame()->ResolveItem( m_editPad ) ) )
1076 {
1077 BOARD_COMMIT commit( frame() );
1078 commit.Modify( pad );
1079
1080 std::vector<PCB_SHAPE*> mergedShapes = RecombinePad( pad, false );
1081
1082 for( PCB_SHAPE* shape : mergedShapes )
1083 commit.Remove( shape );
1084
1085 commit.Push( _( "Edit Pad" ) );
1086 }
1087
1089 }
1090 else if( selection.Size() == 1 && selection[0]->Type() == PCB_PAD_T )
1091 {
1092 PAD* pad = static_cast<PAD*>( selection[0] );
1093 BOARD_COMMIT commit( frame() );
1094
1095 commit.Modify( pad );
1096 explodePad( pad, commit );
1097 commit.Push( _( "Edit Pad" ) );
1098
1099 m_toolMgr->RunAction( ACTIONS::selectionClear );
1100 frame()->SetActiveLayer( pad->GetPrincipalLayer() );
1101
1102 settings->m_PadEditModePad = pad;
1104 }
1105
1106 if( m_editPad == niluuid )
1108
1109 return 0;
1110}
1111
1112
1114{
1115 PAD* flaggedPad = nullptr;
1116 KIID flaggedPadId = niluuid;
1117
1118 for( FOOTPRINT* fp : board()->Footprints() )
1119 {
1120 for( PAD* pad : fp->Pads() )
1121 {
1122 if( pad->IsEntered() )
1123 {
1124 flaggedPad = pad;
1125 flaggedPadId = pad->m_Uuid;
1126 break;
1127 }
1128 }
1129 }
1130
1131 if( flaggedPadId != m_editPad )
1132 {
1133 KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( view()->GetPainter() );
1134 PCB_RENDER_SETTINGS* settings = painter->GetSettings();
1135
1136 m_editPad = flaggedPadId;
1137 settings->m_PadEditModePad = flaggedPad;
1138
1139 if( flaggedPad )
1141 else
1143 }
1144
1145 return 0;
1146}
1147
1148
1150{
1151 PCB_DISPLAY_OPTIONS opts = frame()->GetDisplayOptions();
1152 WX_INFOBAR* infoBar = frame()->GetInfoBar();
1153 wxString msg;
1154
1156 [&]( KIGFX::VIEW_ITEM* aItem ) -> bool
1157 {
1158 return dynamic_cast<PAD*>( aItem ) != nullptr;
1159 } );
1160
1162
1164 {
1166 frame()->SetDisplayOptions( opts );
1167 }
1168
1169 if( PCB_ACTIONS::explodePad.GetHotKey() == PCB_ACTIONS::recombinePad.GetHotKey() )
1170 {
1171 msg.Printf( _( "Pad Edit Mode. Press %s again to exit." ),
1173 }
1174 else
1175 {
1176 msg.Printf( _( "Pad Edit Mode. Press %s to exit." ),
1178 }
1179
1180 infoBar->RemoveAllButtons();
1181 infoBar->ShowMessage( msg, wxICON_INFORMATION );
1182}
1183
1184
1186{
1187 KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( view()->GetPainter() );
1188 PCB_RENDER_SETTINGS* settings = painter->GetSettings();
1189 PCB_DISPLAY_OPTIONS opts = frame()->GetDisplayOptions();
1190
1191 settings->m_PadEditModePad = nullptr;
1192
1194 {
1196 frame()->SetDisplayOptions( opts );
1197 }
1198
1199 // Note: KIGFX::REPAINT isn't enough for things that go from invisible to visible as
1200 // they won't be found in the view layer's itemset for re-painting.
1202 [&]( KIGFX::VIEW_ITEM* aItem ) -> bool
1203 {
1204 return dynamic_cast<PAD*>( aItem ) != nullptr;
1205 } );
1206
1207 // Refresh now (otherwise there's an uncomfortably long pause while the infoBar
1208 // closes before refresh).
1209 canvas()->ForceRefresh();
1210
1211 frame()->GetInfoBar()->Dismiss();
1212}
1213
1214
1216{
1217 auto explodePrimitives =
1218 [&]( PCB_LAYER_ID padstackStorageLayer, PCB_LAYER_ID targetBoardLayer )
1219 {
1220 if( aPad->GetShape( padstackStorageLayer ) == PAD_SHAPE::CUSTOM )
1221 {
1222 for( const std::shared_ptr<PCB_SHAPE>& primitive : aPad->GetPrimitives( padstackStorageLayer ) )
1223 {
1224 PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( primitive->Duplicate( true, &aCommit ) );
1225
1226 shape->SetParent( board()->GetFirstFootprint() );
1227 shape->Rotate( VECTOR2I( 0, 0 ), aPad->GetOrientation() );
1228 shape->Move( aPad->ShapePos( padstackStorageLayer ) );
1229 shape->SetLayer( targetBoardLayer );
1230
1231 if( shape->IsProxyItem() && shape->GetShape() == SHAPE_T::SEGMENT )
1232 {
1233 if( aPad->GetLocalThermalSpokeWidthOverride().has_value() )
1234 shape->SetWidth( aPad->GetLocalThermalSpokeWidthOverride().value() );
1235 else
1237 }
1238
1239 aCommit.Add( shape );
1240 }
1241
1242 aPad->SetShape( padstackStorageLayer, aPad->GetAnchorPadShape( padstackStorageLayer ) );
1243 aPad->DeletePrimitivesList( padstackStorageLayer );
1244 }
1245 };
1246
1247 if( aPad->Padstack().Mode() == PADSTACK::MODE::NORMAL )
1248 {
1249 explodePrimitives( PADSTACK::ALL_LAYERS, aPad->GetPrincipalLayer() );
1250 }
1251 else
1252 {
1254 [&]( PCB_LAYER_ID layer )
1255 {
1256 explodePrimitives( layer, layer );
1257 } );
1258 }
1259
1260 aPad->SetFlags( ENTERED );
1261 m_editPad = aPad->m_Uuid;
1262}
1263
1264
1265std::vector<PCB_SHAPE*> PAD_TOOL::RecombinePad( PAD* aPad, bool aIsDryRun )
1266{
1267 int maxError = board()->GetDesignSettings().m_MaxError;
1268
1269 // Don't leave an object in the point editor that might no longer exist after recombining.
1270 m_toolMgr->RunAction( ACTIONS::selectionClear );
1271
1272 return aPad->Recombine( aIsDryRun, maxError );
1273}
1274
1275
1276int PAD_TOOL::PadTable( const TOOL_EVENT& aEvent )
1277{
1279 return 0;
1280
1282
1283 if( !footprint )
1284 return 0;
1285
1287 dlg.ShowQuasiModal();
1288
1289 return 0;
1290}
1291
1292
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:128
#define DEFAULT_PAD_DRILL_DIAMETER_MM
#define DEFAULT_PAD_APERTURE_WIDTH_MM
#define DEFAULT_PAD_THT_WIDTH_MM
#define DEFAULT_PAD_APERTURE_HEIGHT_MM
#define DEFAULT_PAD_SMD_WIDTH_MM
#define DEFAULT_PAD_SMD_HEIGHT_MM
#define DEFAULT_PAD_THT_HEIGHT_MM
HIGH_CONTRAST_MODE
Determine how inactive layers should be displayed.
@ NORMAL
Inactive layers are shown normally (no high-contrast mode)
@ DIMMED
Inactive layers are dimmed (old high-contrast mode)
static TOOL_ACTION cancelInteractive
Definition actions.h:68
static TOOL_ACTION cursorDblClick
Definition actions.h:177
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:220
void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
void Revert() override
Revert the commit by restoring the modified items state.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:85
FOOTPRINT * GetParentFootprint() const
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:411
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition board.h:713
const FOOTPRINTS & Footprints() const
Definition board.h:465
BOARD_DESIGN_SETTINGS & GetDesignSettings()
Definition board.cpp:1290
void Empty()
Clear the list.
Definition collector.h:87
int GetCount() const
Return the number of objects in the list.
Definition collector.h:79
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Remove a new item from the model.
Definition commit.h:86
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:102
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
Definition commit.h:74
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Add a menu entry to run a TOOL_ACTION on selected items.
void AddSeparator(int aOrder=ANY_ORDER)
Add a separator to the menu.
static DELETED_BOARD_ITEM * GetInstance()
Definition board_item.h:641
Dialog for enumerating pads.
int ShowModal() override
void ForceRefresh()
Force a redraw.
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
void SetStatusPopup(wxWindow *aPopup)
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
virtual void SetPosition(const VECTOR2I &aPos)
Definition eda_item.h:349
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition eda_item.h:158
const KIID m_Uuid
Definition eda_item.h:599
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:153
SHAPE_T GetShape() const
Definition eda_shape.h:177
static const TOOL_EVENT SelectedItemsModified
Selected item had a property changed (except movement)
Definition actions.h:353
static const TOOL_EVENT UndoRedoPostEvent
Definition actions.h:370
EDA_ANGLE GetOrientation() const
Definition footprint.h:382
std::deque< PAD * > & Pads()
Definition footprint.h:355
const LIB_ID & GetFPID() const
Definition footprint.h:417
A general implementation of a COLLECTORS_GUIDE.
Definition collectors.h:320
void SetIgnoreFPTextOnFront(bool ignore)
Definition collectors.h:413
void SetIgnoreFPTextOnBack(bool ignore)
Definition collectors.h:407
void SetIgnoreFPReferences(bool ignore)
Definition collectors.h:455
void SetIgnoreFPValues(bool ignore)
Definition collectors.h:449
Used when the right click button is pressed, or when the select tool is in effect.
Definition collectors.h:203
void Collect(BOARD_ITEM *aItem, const std::vector< KICAD_T > &aScanList, const VECTOR2I &aRefPos, const COLLECTORS_GUIDE &aGuide)
Scan a BOARD_ITEM using this class's Inspector method, which does the collection.
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:94
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
const std::set< int > GetHighContrastLayers() const
Returns the set of currently high-contrast layers.
An interface for classes handling user events controlling the view behavior such as zooming,...
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Place the cursor immediately at a given point.
virtual void ShowCursor(bool aEnabled)
Enable or disables display of cursor.
virtual VECTOR2D GetMousePosition(bool aWorldCoordinates=true) const =0
Return the current mouse pointer position.
An abstract base class for deriving all objects that can be added to a VIEW.
Definition view_item.h:82
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:68
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:2631
PAINTER * GetPainter() const
Return the painter object used by the view for drawing VIEW_ITEM objects.
Definition view.h:242
void UpdateAllItemsConditionally(int aUpdateFlags, std::function< bool(VIEW_ITEM *)> aCondition)
Update items in the view according to the given flags and condition.
Definition view.cpp:2492
Definition kiid.h:46
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static const LSET & AllLayersMask()
Definition lset.cpp:637
void ForEachUniqueLayer(const std::function< void(PCB_LAYER_ID)> &aMethod) const
Runs the given callable for each active unique copper layer in this padstack, meaning F_Cu for MODE::...
@ NORMAL
Shape is the same on all layers.
Definition padstack.h:170
MODE Mode() const
Definition padstack.h:346
static constexpr PCB_LAYER_ID ALL_LAYERS
! The layer identifier to use for the single defintion on normal padstacks
Definition padstack.h:179
PAD GetMasterPad(TYPE aType, const FOOTPRINT *aFootprint, const PAD *aSelectedPad) const
Get the master pad for the given type, footprint, and selected pad.
Definition pad_tool.cpp:90
TYPE resolveAutoType(const std::vector< const PAD * > &aFpPads, const PAD *aSelectedPad) const
Resolve the type a TYPE::AUTO request actually wants.
Definition pad_tool.cpp:338
std::unordered_map< TYPE, KIID > m_lastRealPadsForType
Definition pad_tool.cpp:362
PAD_MASTER_PROVIDER()=default
std::unique_ptr< PAD > MakeDefaultPad(PAD_MASTER_PROVIDER::TYPE aMasterType) const
Create a default pad for the given master pad type when there is no more obvious source.
Definition pad_tool.cpp:159
TYPE m_lastType
Persistent store of the last pad type.
Definition pad_tool.cpp:365
static std::optional< TYPE > TypeFromPad(const PAD &aPad)
Determine the master pad type from the given pad.
Definition pad_tool.cpp:299
void RecordNewMasterPad(const PAD &aPlacedPad)
Record the given pad as the most recently placed pad of its type.
Definition pad_tool.cpp:268
static TYPE TypeFromAction(const TOOL_EVENT &aEvent)
Definition pad_tool.cpp:280
void RecordMasterPad(const PAD &aPad)
Record aPad as the template for the next pad of its type placed.
Definition pad_tool.cpp:386
void Reset(RESET_REASON aReason) override
React to model/view changes.
Definition pad_tool.cpp:392
int OnUndoRedo(const TOOL_EVENT &aEvent)
HIGH_CONTRAST_MODE m_previousHighContrastMode
Definition pad_tool.h:103
void setTransitions() override
Bind handlers to corresponding TOOL_ACTIONs.
int EditPad(const TOOL_EVENT &aEvent)
Enter/exit WYSIWYG pad shape editing.
void ExitPadEditMode()
KIID m_editPad
Definition pad_tool.h:104
std::unique_ptr< PAD_MASTER_PROVIDER > m_masterPadProvider
When pads are created this provides the master pad settings.
Definition pad_tool.h:107
int copyPadSettings(const TOOL_EVENT &aEvent)
Copy pad settings from a pad to the tool's buffer pad.
Definition pad_tool.cpp:502
void enterPadEditMode()
int pastePadProperties(const TOOL_EVENT &aEvent)
Apply pad settings from the buffer pad to a pad.
Definition pad_tool.cpp:476
int PlacePad(const TOOL_EVENT &aEvent)
Place a pad in footprint editor.
Definition pad_tool.cpp:920
int EnumeratePads(const TOOL_EVENT &aEvent)
Tool for quick pad enumeration.
Definition pad_tool.cpp:657
void explodePad(PAD *aPad, BOARD_COMMIT &aCommit)
std::unique_ptr< PAD > m_bufferPad
The "buffer" pad that holds the settings applied by "Paste Pad Properties".
Definition pad_tool.h:110
int PadTable(const TOOL_EVENT &aEvent)
bool Init() override
Basic initialization.
Definition pad_tool.cpp:414
void SetLastPadNumber(const wxString &aPadNumber)
Definition pad_tool.h:67
std::vector< PCB_SHAPE * > RecombinePad(PAD *aPad, bool aIsDryRun)
Recombine an exploded pad (or one produced with overlapping polygons in an older version).
bool InPadEditMode()
Definition pad_tool.h:63
wxString m_lastPadNumber
Definition pad_tool.h:101
int pushPadSettings(const TOOL_EVENT &aEvent)
Push pad settings from a pad to other pads on board or footprint.
Definition pad_tool.cpp:599
Definition pad.h:61
bool IsAperturePad() const
Definition pad.h:567
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition pad.h:557
const std::vector< std::shared_ptr< PCB_SHAPE > > & GetPrimitives(PCB_LAYER_ID aLayer) const
Accessor to the basic shape list for custom-shaped pads.
Definition pad.h:375
PAD_ATTRIB GetAttribute() const
Definition pad.h:560
static LSET PTHMask()
layer set for a through hole pad
Definition pad.cpp:615
const wxString & GetNumber() const
Definition pad.h:143
void SetShape(PCB_LAYER_ID aLayer, PAD_SHAPE aShape)
Set the new shape of this pad.
Definition pad.h:196
std::vector< PCB_SHAPE * > Recombine(bool aIsDryRun, int aMaxError)
Recombines the pad with other graphical shapes in the footprint.
Definition pad.cpp:3242
PCB_LAYER_ID GetPrincipalLayer() const
Definition pad.cpp:664
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
Definition pad.cpp:636
void DeletePrimitivesList(PCB_LAYER_ID aLayer=UNDEFINED_LAYER)
Clear the basic shapes list.
Definition pad.cpp:3552
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
Definition pad.h:205
VECTOR2I GetSize(PCB_LAYER_ID aLayer) const
Definition pad.cpp:297
void ImportSettingsFrom(const PAD &aMasterPad)
Import the pad settings from aMasterPad.
Definition pad.cpp:3022
const PADSTACK & Padstack() const
Definition pad.h:331
static LSET ConnSMDMask()
layer set for a SMD pad on Front layer used for edge board connectors
Definition pad.cpp:629
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition pad.cpp:1795
static LSET ApertureMask()
layer set for an aperture pad
Definition pad.cpp:643
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition pad.cpp:622
std::optional< int > GetLocalThermalSpokeWidthOverride() const
Definition pad.h:741
VECTOR2I ShapePos(PCB_LAYER_ID aLayer) const
Definition pad.cpp:1906
PAD_SHAPE GetAnchorPadShape(PCB_LAYER_ID aLayer) const
Definition pad.h:219
static TOOL_ACTION recombinePad
static TOOL_ACTION enumeratePads
Tool for quick pad enumeration.
static TOOL_ACTION placePasteAperturePad
static TOOL_ACTION pushPadSettings
Copy the current pad's settings to other pads in the footprint or on the board.
static TOOL_ACTION mirrorH
Mirroring of selected items.
static TOOL_ACTION copyPadSettings
Copy the selected pad's settings to the board design settings.
static TOOL_ACTION placePad
Activation of the drawing tool (placing a PAD)
static TOOL_ACTION placeNpthPad
static TOOL_ACTION padTable
static TOOL_ACTION properties
Activation of the edit tool.
static TOOL_ACTION explodePad
static TOOL_ACTION applyPadSettings
Copy the default pad settings to the selected pad.
static TOOL_ACTION placeThtPad
static TOOL_ACTION placeSmdPad
static TOOL_ACTION mirrorV
static TOOL_ACTION flip
Flipping of selected objects.
static TOOL_ACTION rotateCw
Rotation of selected objects.
static TOOL_ACTION rotateCcw
Common, abstract interface for edit frames.
virtual MAGNETIC_SETTINGS * GetMagneticItemsSettings()
BOARD * GetBoard() const
HIGH_CONTRAST_MODE m_ContrastModeDisplay
How inactive layers are displayed.
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the KIGFX::VIEW instance used in the panel.
The selection tool: currently supports:
PCB_SELECTION & GetSelection()
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
void SetWidth(int aWidth) override
bool IsProxyItem() const override
Definition pcb_shape.h:155
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void Move(const VECTOR2I &aMoveVector) override
Move this object.
T * frame() const
KIGFX::PCB_VIEW * view() const
PCB_TOOL_BASE(TOOL_ID aId, const std::string &aName)
Constructor.
BOARD * board() const
PCB_DRAW_PANEL_GAL * canvas() const
@ IPO_FLIP
Handle flip action in the loop by calling the item's flip method.
@ IPO_ROTATE
Handle the rotate action in the loop by calling the item's rotate method.
@ IPO_SINGLE_CLICK
Create an item immediately on placement starting, otherwise show the pencil cursor until the item is ...
@ IPO_REPEAT
Allow repeat placement of the item.
void doInteractiveItemPlacement(const TOOL_EVENT &aTool, INTERACTIVE_PLACER_BASE *aPlacer, const wxString &aCommitMessage, int aOptions=IPO_ROTATE|IPO_FLIP|IPO_REPEAT)
Helper function for performing a common interactive idiom: wait for a left click, place an item there...
const PCB_SELECTION & selection() const
FOOTPRINT * footprint() const
static SELECTION_CONDITION HasType(KICAD_T aType)
Create a functor that tests if among the selected items there is at least one of a given type.
static SELECTION_CONDITION Count(int aNumber)
Create a functor that tests if the number of selected items is equal to the value given as parameter.
static bool ShowAlways(const SELECTION &aSelection)
The default condition function (always returns true).
static SELECTION_CONDITION OnlyTypes(std::vector< KICAD_T > aTypes)
Create a functor that tests if the selected items are only of given types.
wxWindow * GetPanel()
virtual void Popup(wxWindow *aFocus=nullptr)
virtual void Move(const wxPoint &aWhere)
Extension of STATUS_POPUP for displaying a single line text.
void SetText(const wxString &aText)
Display a text.
TOOL_MANAGER * GetManager() const
Return the instance of TOOL_MANAGER that takes care of the tool.
Definition tool_base.h:142
T * getEditFrame() const
Return the application window object, casted to requested user type.
Definition tool_base.h:182
T * getModel() const
Return the model object if it matches the requested type.
Definition tool_base.h:195
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition tool_base.cpp:40
TOOL_MANAGER * m_toolMgr
Definition tool_base.h:220
KIGFX::VIEW * getView() const
Return the instance of KIGFX::VIEW object used in the application.
Definition tool_base.cpp:34
RESET_REASON
Determine the reason of reset for a tool.
Definition tool_base.h:74
@ MODEL_RELOAD
Model changes (the sheet for a schematic)
Definition tool_base.h:76
Generic, UI-independent tool event.
Definition tool_event.h:167
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
TOOL_MENU & GetToolMenu()
std::unique_ptr< TOOL_MENU > m_menu
The functions below are not yet implemented - their interface may change.
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Suspend execution of the tool until an event specified in aEventList arrives.
void Activate()
Run the tool.
CONDITIONAL_MENU & GetMenu()
Definition tool_menu.cpp:40
A modified version of the wxInfoBar class that allows us to:
Definition wx_infobar.h:76
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
void ShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION) override
Show the info bar with the provided message and icon.
@ ARROW
Definition cursors.h:43
@ BULLSEYE
Definition cursors.h:55
static bool empty(const wxTextEntryBase *aCtrl)
#define _(s)
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:450
#define ENTERED
indicates a group has been entered
@ SEGMENT
Definition eda_shape.h:56
static const std::vector< KICAD_T > padTypes
@ GRID_CURRENT
Definition grid_helper.h:57
wxString KeyNameFromKeyCode(int aKeycode, bool *aIsFound)
Return the key name from the key code.
NORMAL
Follows standard pretty-printing rules.
KIID niluuid(0)
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ F_Mask
Definition layer_ids.h:93
This file contains miscellaneous commonly used macros and functions.
@ REPAINT
Item needs to be redrawn.
Definition view_item.h:54
@ ALL
All except INITIAL_ADD.
Definition view_item.h:55
wxPoint GetMousePosition()
Returns the mouse position in screen coordinates.
Definition wxgtk/ui.cpp:958
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:35
STL namespace.
static void doPushPadProperties(BOARD &board, const PAD &aSrcPad, BOARD_COMMIT &commit, bool aSameFootprints, bool aPadShapeFilter, bool aPadSizeFilter, bool aPadOrientFilter, bool aPadLayerFilter, bool aPadTypeFilter)
Definition pad_tool.cpp:528
static std::optional< SEQUENTIAL_PAD_ENUMERATION_PARAMS > GetSequentialPadNumberingParams(wxWindow *aFrame)
Prompts the user for parameters for sequential pad numbering.
Definition pad_tool.cpp:643
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition padstack.h:102
@ SMD
Smd pad, appears on the solder paste layer (default)
Definition padstack.h:98
@ PTH
Plated through hole pad.
Definition padstack.h:97
@ CONN
Like smd, does not appear on the solder paste layer (default) Note: also has a special attribute in G...
Definition padstack.h:99
@ ROUNDRECT
Definition padstack.h:56
@ RECTANGLE
Definition padstack.h:53
#define DEFAULT_PAD_NPTH_DIAMETER_MM
std::deque< PAD * > PADS
std::deque< BOARD_ITEM * > DRAWINGS
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
std::function< bool(const SELECTION &)> SELECTION_CONDITION
Functor type that checks a specific condition for selected items.
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.
MAGNETIC_OPTIONS tracks
MAGNETIC_OPTIONS pads
Parameters for sequential pad numbering.
@ MD_CTRL
Definition tool_event.h:140
@ MD_SHIFT
Definition tool_event.h:139
@ BUT_LEFT
Definition tool_event.h:128
@ BUT_RIGHT
Definition tool_event.h:129
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition typeinfo.h:79
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708
VECTOR2< double > VECTOR2D
Definition vector2d.h:707
#define ZONE_THERMAL_RELIEF_COPPER_WIDTH_MM
Definition zones.h:29