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 (C) 2017-2024 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, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24
25#include "pad_tool.h"
26#include "pcb_painter.h"
27#include <kiplatform/ui.h>
28#include <macros.h>
30#include <view/view_controls.h>
31#include <tool/tool_manager.h>
33#include <board_item.h>
34#include <footprint.h>
35#include <pcb_shape.h>
36#include <pad.h>
37#include <pcbnew_settings.h>
38#include <board_commit.h>
40#include <tools/pcb_actions.h>
44#include <tools/edit_tool.h>
46#include <widgets/wx_infobar.h>
47
48
50
51
53 PCB_TOOL_BASE( "pcbnew.PadTool" ),
54 m_previousHighContrastMode( HIGH_CONTRAST_MODE::NORMAL ),
55 m_editPad( niluuid )
56{}
57
58
60{}
61
62
64{
65 if( aReason == MODEL_RELOAD )
66 m_lastPadNumber = wxT( "1" );
67
68 if( board() && board()->GetItem( m_editPad ) == DELETED_BOARD_ITEM::GetInstance() )
69 {
71
73 {
75 frame()->SetDisplayOptions( opts );
76 }
77
78 frame()->GetInfoBar()->Dismiss();
79
81 }
82}
83
84
86{
87 static const std::vector<KICAD_T> padTypes = { PCB_PAD_T };
88
90
91 if( selTool )
92 {
93 // Add context menu entries that are displayed when selection tool is active
94 CONDITIONAL_MENU& menu = selTool->GetToolMenu().GetMenu();
95
99
100 auto explodeCondition =
101 [&]( const SELECTION& aSel )
102 {
103 return m_editPad == niluuid && aSel.Size() == 1 && aSel[0]->Type() == PCB_PAD_T;
104 };
105
106 auto recombineCondition =
107 [&]( const SELECTION& aSel )
108 {
109 return m_editPad != niluuid;
110 };
111
112 menu.AddSeparator( 400 );
113
115 {
117 menu.AddItem( PCB_ACTIONS::recombinePad, recombineCondition, 400 );
118 menu.AddItem( PCB_ACTIONS::explodePad, explodeCondition, 400 );
119 }
120
121 menu.AddItem( PCB_ACTIONS::copyPadSettings, singlePadSel, 400 );
122 menu.AddItem( PCB_ACTIONS::applyPadSettings, padSel, 400 );
123 menu.AddItem( PCB_ACTIONS::pushPadSettings, singlePadSel, 400 );
124 }
125
126 auto& ctxMenu = m_menu.GetMenu();
127
128 // cancel current tool goes in main context menu at the top if present
130 ctxMenu.AddSeparator( 1 );
131
138
139 // Finally, add the standard zoom/grid items
140 getEditFrame<PCB_BASE_FRAME>()->AddStandardSubMenus( m_menu );
141
142 return true;
143}
144
145
147{
149 const PCB_SELECTION& selection = selTool->GetSelection();
150 const PAD* masterPad = frame()->GetDesignSettings().m_Pad_Master.get();
151
152 BOARD_COMMIT commit( frame() );
153
154 // for every selected pad, paste global settings
155 for( EDA_ITEM* item : selection )
156 {
157 if( item->Type() == PCB_PAD_T )
158 {
159 commit.Modify( item );
160 static_cast<PAD&>( *item ).ImportSettingsFrom( *masterPad );
161 }
162 }
163
164 commit.Push( _( "Paste Pad Properties" ) );
165
167 frame()->Refresh();
168
169 return 0;
170}
171
172
174{
176 const PCB_SELECTION& selection = selTool->GetSelection();
177
178 // can only copy from a single pad
179 if( selection.Size() == 1 )
180 {
181 EDA_ITEM* item = selection[0];
182
183 if( item->Type() == PCB_PAD_T )
184 {
185 const PAD& selPad = static_cast<const PAD&>( *item );
186 frame()->GetDesignSettings().m_Pad_Master->ImportSettingsFrom( selPad );
187 }
188 }
189
190 return 0;
191}
192
193
194static void doPushPadProperties( BOARD& board, const PAD& aSrcPad, BOARD_COMMIT& commit,
195 bool aSameFootprints, bool aPadShapeFilter, bool aPadOrientFilter,
196 bool aPadLayerFilter, bool aPadTypeFilter )
197{
198 const FOOTPRINT* refFootprint = aSrcPad.GetParentFootprint();
199
200 EDA_ANGLE srcPadAngle = aSrcPad.GetOrientation() - refFootprint->GetOrientation();
201
202 for( FOOTPRINT* footprint : board.Footprints() )
203 {
204 if( !aSameFootprints && ( footprint != refFootprint ) )
205 continue;
206
207 if( footprint->GetFPID() != refFootprint->GetFPID() )
208 continue;
209
210 for( PAD* pad : footprint->Pads() )
211 {
212 if( aPadShapeFilter && ( pad->GetShape() != aSrcPad.GetShape() ) )
213 continue;
214
215 EDA_ANGLE padAngle = pad->GetOrientation() - footprint->GetOrientation();
216
217 if( aPadOrientFilter && ( padAngle != srcPadAngle ) )
218 continue;
219
220 if( aPadLayerFilter && ( pad->GetLayerSet() != aSrcPad.GetLayerSet() ) )
221 continue;
222
223 if( aPadTypeFilter && ( pad->GetAttribute() != aSrcPad.GetAttribute() ) )
224 continue;
225
226 // Special-case for aperture pads
227 if( aPadTypeFilter && pad->GetAttribute() == PAD_ATTRIB::CONN )
228 {
229 if( pad->IsAperturePad() != aSrcPad.IsAperturePad() )
230 continue;
231 }
232
233 commit.Modify( pad );
234
235 // Apply source pad settings to this pad
236 pad->ImportSettingsFrom( aSrcPad );
237 }
238 }
239}
240
241
243{
245 const PCB_SELECTION& selection = selTool->GetSelection();
246
247 if( selection.Size() == 1 && selection[0]->Type() == PCB_PAD_T )
248 {
249 PAD* srcPad = static_cast<PAD*>( selection[0] );
250
251 if( FOOTPRINT* footprint = srcPad->GetParentFootprint() )
252 {
254
256 int dialogRet = dlg.ShowModal();
257
258 if( dialogRet == wxID_CANCEL )
259 return 0;
260
261 const bool edit_Same_Modules = (dialogRet == 1);
262
263 BOARD_COMMIT commit( frame() );
264
265 doPushPadProperties( *getModel<BOARD>(), *srcPad, commit, edit_Same_Modules,
270
271 commit.Push( _( "Push Pad Settings" ) );
272
274 frame()->Refresh();
275 }
276 }
277
278 return 0;
279}
280
281
288static std::optional<SEQUENTIAL_PAD_ENUMERATION_PARAMS>
290{
291 // Persistent settings for the pad enumeration dialog.
292 static SEQUENTIAL_PAD_ENUMERATION_PARAMS s_lastUsedParams;
293
294 DIALOG_ENUM_PADS settingsDlg( aFrame, s_lastUsedParams );
295
296 if( settingsDlg.ShowModal() != wxID_OK )
297 return std::nullopt;
298
299 return s_lastUsedParams;
300}
301
302
304{
306 return 0;
307
308 if( !board()->GetFirstFootprint() || board()->GetFirstFootprint()->Pads().empty() )
309 return 0;
310
311 GENERAL_COLLECTOR collector;
313 guide.SetIgnoreMTextsMarkedNoShow( true );
314 guide.SetIgnoreMTextsOnBack( true );
315 guide.SetIgnoreMTextsOnFront( true );
316 guide.SetIgnoreModulesVals( true );
317 guide.SetIgnoreModulesRefs( true );
318
319 const std::optional<SEQUENTIAL_PAD_ENUMERATION_PARAMS> params =
321
322 // Cancelled or otherwise failed to get any useful parameters
323 if( !params )
324 return 0;
325
326 int seqPadNum = params->m_start_number;
327
328 std::deque<int> storedPadNumbers;
329 std::map<wxString, std::pair<int, wxString>> oldNumbers;
330
332
333 frame()->PushTool( aEvent );
334
335 VECTOR2I oldCursorPos; // store the previous mouse cursor position, during mouse drag
336 std::list<PAD*> selectedPads;
337 BOARD_COMMIT commit( frame() );
338 bool isFirstPoint = true; // make sure oldCursorPos is initialized at least once
339 PADS pads = board()->GetFirstFootprint()->Pads();
340
341 MAGNETIC_SETTINGS mag_settings;
342 mag_settings.graphics = false;
343 mag_settings.tracks = MAGNETIC_OPTIONS::NO_EFFECT;
344 mag_settings.pads = MAGNETIC_OPTIONS::CAPTURE_ALWAYS;
345 PCB_GRID_HELPER grid( m_toolMgr, &mag_settings );
346
347 grid.SetSnap( true );
348 grid.SetUseGrid( false );
349
350 auto setCursor =
351 [&]()
352 {
353 canvas()->SetCurrentCursor( KICURSOR::BULLSEYE );
354 };
355
356 Activate();
357 // Must be done after Activate() so that it gets set into the correct context
358 getViewControls()->ShowCursor( true );
360 // Set initial cursor
361 setCursor();
362
363 STATUS_TEXT_POPUP statusPopup( frame() );
364
365 // Callable lambda to construct the pad number string for the given value
366 const auto constructPadNumber =
367 [&]( int aValue )
368 {
369 return wxString::Format( wxT( "%s%d" ), params->m_prefix.value_or( "" ), aValue );
370 };
371
372 // Callable lambda to set the popup text for the given pad value
373 const auto setPopupTextForValue =
374 [&]( int aValue )
375 {
376 const wxString msg = _( "Click on pad %s\n"
377 "Press <esc> to cancel all; double-click to finish" );
378 statusPopup.SetText( wxString::Format( msg, constructPadNumber( aValue ) ) );
379 };
380
381 setPopupTextForValue( seqPadNum );
382 statusPopup.Popup();
383 statusPopup.Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, 20 ) );
384 canvas()->SetStatusPopup( statusPopup.GetPanel() );
385
386 while( TOOL_EVENT* evt = Wait() )
387 {
388 setCursor();
389
390 VECTOR2I cursorPos = grid.AlignToNearestPad( getViewControls()->GetMousePosition(), pads );
391 getViewControls()->ForceCursorPosition( true, cursorPos );
392
393 if( evt->IsCancelInteractive() )
394 {
396 commit.Revert();
397
398 frame()->PopTool( aEvent );
399 break;
400 }
401 else if( evt->IsActivate() )
402 {
403 commit.Push( _( "Renumber Pads" ) );
404
405 frame()->PopTool( aEvent );
406 break;
407 }
408 else if( evt->IsDrag( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) )
409 {
410 selectedPads.clear();
411
412 // Be sure the old cursor mouse position was initialized:
413 if( isFirstPoint )
414 {
415 oldCursorPos = cursorPos;
416 isFirstPoint = false;
417 }
418
419 // wxWidgets deliver mouse move events not frequently enough, resulting in skipping
420 // pads if the user moves cursor too fast. To solve it, create a line that approximates
421 // the mouse move and search pads that are on the line.
422 int distance = ( cursorPos - oldCursorPos ).EuclideanNorm();
423 // Search will be made every 0.1 mm:
424 int segments = distance / int( 0.1 * pcbIUScale.IU_PER_MM ) + 1;
425 const VECTOR2I line_step( ( cursorPos - oldCursorPos ) / segments );
426
427 collector.Empty();
428
429 for( int j = 0; j < segments; ++j )
430 {
431 VECTOR2I testpoint( cursorPos.x - j * line_step.x, cursorPos.y - j * line_step.y );
432 collector.Collect( board(), { PCB_PAD_T }, testpoint, guide );
433
434 for( int i = 0; i < collector.GetCount(); ++i )
435 {
436 PAD* pad = static_cast<PAD*>( collector[i] );
437
438 if( !pad->IsAperturePad() )
439 selectedPads.push_back( pad );
440 }
441 }
442
443 selectedPads.unique();
444
445 for( PAD* pad : selectedPads )
446 {
447 // If pad was not selected, then enumerate it
448 if( !pad->IsSelected() )
449 {
450 commit.Modify( pad );
451
452 // Rename pad and store the old name
453 int newval;
454
455 if( storedPadNumbers.size() > 0 )
456 {
457 newval = storedPadNumbers.front();
458 storedPadNumbers.pop_front();
459 }
460 else
461 {
462 newval = seqPadNum;
463 seqPadNum += params->m_step;
464 }
465
466 const wxString newNumber = constructPadNumber( newval );
467 oldNumbers[newNumber] = { newval, pad->GetNumber() };
468 pad->SetNumber( newNumber );
469 SetLastPadNumber( newNumber );
470 pad->SetSelected();
471 getView()->Update( pad );
472
473 // Ensure the popup text shows the correct next value
474 if( storedPadNumbers.size() > 0 )
475 newval = storedPadNumbers.front();
476 else
477 newval = seqPadNum;
478
479 setPopupTextForValue( newval );
480 }
481
482 // ... or restore the old name if it was enumerated and clicked again
483 else if( pad->IsSelected() && evt->IsClick( BUT_LEFT ) )
484 {
485 auto it = oldNumbers.find( pad->GetNumber() );
486 wxASSERT( it != oldNumbers.end() );
487
488 if( it != oldNumbers.end() )
489 {
490 storedPadNumbers.push_back( it->second.first );
491 pad->SetNumber( it->second.second );
492 SetLastPadNumber( it->second.second );
493 oldNumbers.erase( it );
494
495 const int newval = storedPadNumbers.front();
496 setPopupTextForValue( newval );
497 }
498
499 pad->ClearSelected();
500 getView()->Update( pad );
501 }
502 }
503 }
504 else if( evt->IsDblClick( BUT_LEFT ) )
505 {
506 commit.Push( _( "Renumber Pads" ) );
507 frame()->PopTool( aEvent );
508 break;
509 }
510 else if( evt->IsClick( BUT_RIGHT ) )
511 {
513 }
514 else
515 {
516 evt->SetPassEvent();
517 }
518
519 // Prepare the next loop by updating the old cursor mouse position
520 // to this last mouse cursor position
521 oldCursorPos = getViewControls()->GetCursorPosition();
522 statusPopup.Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, 20 ) );
523 }
524
525 for( PAD* p : board()->GetFirstFootprint()->Pads() )
526 {
527 p->ClearSelected();
528 getView()->Update( p );
529 }
530
531 canvas()->SetStatusPopup( nullptr );
532 statusPopup.Hide();
533
534 canvas()->SetCurrentCursor( KICURSOR::ARROW );
536 return 0;
537}
538
539
540int PAD_TOOL::PlacePad( const TOOL_EVENT& aEvent )
541{
542 // When creating a new pad (in FP editor) we can use a new pad number
543 // or the last entered pad number
544 // neednewPadNumber = true to create a new pad number, false to use the last
545 // entered pad number
546 static bool neednewPadNumber;
547
549 return 0;
550
551 if( !board()->GetFirstFootprint() )
552 return 0;
553
554 struct PAD_PLACER : public INTERACTIVE_PLACER_BASE
555 {
556 PAD_PLACER( PAD_TOOL* aPadTool )
557 {
558 neednewPadNumber = true; // Use a new pad number when creatin a pad by default
559 m_padTool = aPadTool;
560 }
561
562 virtual ~PAD_PLACER()
563 {
564 }
565
566 std::unique_ptr<BOARD_ITEM> CreateItem() override
567 {
568 PAD* pad = new PAD( m_board->GetFirstFootprint() );
569 PAD* master = m_frame->GetDesignSettings().m_Pad_Master.get();
570
571 pad->ImportSettingsFrom( *master );
572
573 // If the footprint type and master pad type directly conflict then make some
574 // adjustments. Otherwise assume the user set what they wanted.
575 // Note also a HEATSINK pad (thermal via) is allowed in SMD footprint
576 if( ( m_board->GetFirstFootprint()->GetAttributes() & FP_SMD )
577 && master->GetAttribute() == PAD_ATTRIB::PTH )
578 {
579 if( pad->GetProperty() != PAD_PROP::HEATSINK )
580 {
581 pad->SetAttribute( PAD_ATTRIB::SMD );
582 pad->SetShape( PAD_SHAPE::ROUNDRECT );
583 pad->SetSizeX( 1.5 * pad->GetSizeY() );
584 pad->SetLayerSet( PAD::SMDMask() );
585 }
586 }
587 else if( ( m_board->GetFirstFootprint()->GetAttributes() & FP_THROUGH_HOLE )
588 && master->GetAttribute() == PAD_ATTRIB::SMD )
589 {
590 pad->SetAttribute( PAD_ATTRIB::PTH );
591 pad->SetShape( PAD_SHAPE::CIRCLE );
592 pad->SetSize( VECTOR2I( pad->GetSizeX(), pad->GetSizeX() ) );
593
594 // Gives an acceptable drill size: it cannot be 0, but from pad master
595 // it is currently 0, therefore change it:
596 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
597 int hole_size = pad->GetSizeX() / 2;
598 pad->SetDrillSize( VECTOR2I( hole_size, hole_size ) );
599
600 pad->SetLayerSet( PAD::PTHMask() );
601 }
602
603 if( pad->CanHaveNumber() )
604 {
605 wxString padNumber = m_padTool->GetLastPadNumber();
606
607 // Use the last entered pad number when recreating a pad without using the
608 // previously created pad, and a new number when creating a really new pad
609 if( neednewPadNumber )
610 padNumber = m_board->GetFirstFootprint()->GetNextPadNumber( padNumber );
611
612 pad->SetNumber( padNumber );
613 m_padTool->SetLastPadNumber( padNumber );
614
615 // If a pad is recreated and the previously created was not placed, use
616 // the last entered pad number
617 neednewPadNumber = false;
618 }
619
620 return std::unique_ptr<BOARD_ITEM>( pad );
621 }
622
623 bool PlaceItem( BOARD_ITEM *aItem, BOARD_COMMIT& aCommit ) override
624 {
625 PAD* pad = dynamic_cast<PAD*>( aItem );
626 // We are using this pad number.
627 // therefore use a new pad number for a newly created pad
628 neednewPadNumber = true;
629
630 if( pad )
631 {
632 m_frame->GetDesignSettings().m_Pad_Master->ImportSettingsFrom( *pad );
633 aCommit.Add( aItem );
634 return true;
635 }
636
637 return false;
638 }
639
640 PAD_TOOL* m_padTool;
641 };
642
643 PAD_PLACER placer( this );
644
645 doInteractiveItemPlacement( aEvent, &placer, _( "Place pad" ),
647
648 return 0;
649}
650
651
652int PAD_TOOL::EditPad( const TOOL_EVENT& aEvent )
653{
655 return 0;
656
657 Activate();
658
659 KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( view()->GetPainter() );
660 PCB_RENDER_SETTINGS* settings = painter->GetSettings();
662
663 if( m_editPad != niluuid )
664 {
665 PAD* pad = dynamic_cast<PAD*>( frame()->GetItem( m_editPad ) );
666
667 if( pad )
668 {
669 BOARD_COMMIT commit( frame() );
670 commit.Modify( pad );
671
672 std::vector<PCB_SHAPE*> mergedShapes = RecombinePad( pad, false );
673
674 for( PCB_SHAPE* shape : mergedShapes )
675 commit.Remove( shape );
676
677 commit.Push( _( "Edit Pad" ) );
678 }
679
681 }
682 else if( selection.Size() == 1 && selection[0]->Type() == PCB_PAD_T )
683 {
684 PCB_LAYER_ID layer;
685 PAD* pad = static_cast<PAD*>( selection[0] );
686 BOARD_COMMIT commit( frame() );
687
688 commit.Modify( pad );
689 explodePad( pad, &layer, commit );
690 commit.Push( _( "Edit Pad" ) );
691
693 frame()->SetActiveLayer( layer );
694
695 settings->m_PadEditModePad = pad;
697 }
698
699 if( m_editPad == niluuid )
701
702 return 0;
703}
704
705
707{
708 PAD* flaggedPad = nullptr;
709 KIID flaggedPadId = niluuid;
710
711 for( FOOTPRINT* fp : board()->Footprints() )
712 {
713 for( PAD* pad : fp->Pads() )
714 {
715 if( pad->IsEntered() )
716 {
717 flaggedPad = pad;
718 flaggedPadId = pad->m_Uuid;
719 break;
720 }
721 }
722 }
723
724 if( flaggedPadId != m_editPad )
725 {
726 KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( view()->GetPainter() );
727 PCB_RENDER_SETTINGS* settings = painter->GetSettings();
728
729 m_editPad = flaggedPadId;
730 settings->m_PadEditModePad = flaggedPad;
731
732 if( flaggedPad )
734 else
736 }
737
738 return 0;
739}
740
741
743{
745 WX_INFOBAR* infoBar = frame()->GetInfoBar();
746 wxString msg;
747
749 [&]( KIGFX::VIEW_ITEM* aItem ) -> bool
750 {
751 return dynamic_cast<PAD*>( aItem ) != nullptr;
752 } );
753
755
756 if( opts.m_ContrastModeDisplay == HIGH_CONTRAST_MODE::NORMAL )
757 {
758 opts.m_ContrastModeDisplay = HIGH_CONTRAST_MODE::DIMMED;
759 frame()->SetDisplayOptions( opts );
760 }
761
762 if( PCB_ACTIONS::explodePad.GetHotKey() == PCB_ACTIONS::recombinePad.GetHotKey() )
763 {
764 msg.Printf( _( "Pad Edit Mode. Press %s again to exit." ),
766 }
767 else
768 {
769 msg.Printf( _( "Pad Edit Mode. Press %s to exit." ),
771 }
772
773 infoBar->RemoveAllButtons();
774 infoBar->ShowMessage( msg, wxICON_INFORMATION );
775}
776
777
779{
780 KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( view()->GetPainter() );
781 PCB_RENDER_SETTINGS* settings = painter->GetSettings();
783
784 settings->m_PadEditModePad = nullptr;
785
787 {
789 frame()->SetDisplayOptions( opts );
790 }
791
792 // Note: KIGFX::REPAINT isn't enough for things that go from invisible to visible as
793 // they won't be found in the view layer's itemset for re-painting.
795 [&]( KIGFX::VIEW_ITEM* aItem ) -> bool
796 {
797 return dynamic_cast<PAD*>( aItem ) != nullptr;
798 } );
799
800 // Refresh now (otherwise there's an uncomfortably long pause while the infoBar
801 // closes before refresh).
802 canvas()->ForceRefresh();
803
804 frame()->GetInfoBar()->Dismiss();
805}
806
807
808void PAD_TOOL::explodePad( PAD* aPad, PCB_LAYER_ID* aLayer, BOARD_COMMIT& aCommit )
809{
810 if( aPad->IsOnLayer( F_Cu ) )
811 *aLayer = F_Cu;
812 else if( aPad->IsOnLayer( B_Cu ) )
813 *aLayer = B_Cu;
814 else
815 *aLayer = aPad->GetLayerSet().UIOrder().front();
816
817 if( aPad->GetShape() == PAD_SHAPE::CUSTOM )
818 {
819 for( const std::shared_ptr<PCB_SHAPE>& primitive : aPad->GetPrimitives() )
820 {
821 PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( primitive->Duplicate() );
822
823 shape->SetParent( board()->GetFirstFootprint() );
824 shape->Rotate( VECTOR2I( 0, 0 ), aPad->GetOrientation() );
825 shape->Move( aPad->ShapePos() );
826 shape->SetLayer( *aLayer );
827
828 if( shape->IsProxyItem() && shape->GetShape() == SHAPE_T::SEGMENT )
829 {
830 if( aPad->GetThermalSpokeWidth() )
831 shape->SetWidth( aPad->GetThermalSpokeWidth() );
832 else
834 }
835
836 aCommit.Add( shape );
837 }
838
839 aPad->SetShape( aPad->GetAnchorPadShape() );
840 aPad->DeletePrimitivesList();
841 }
842
843 aPad->SetFlags( ENTERED );
844 m_editPad = aPad->m_Uuid;
845}
846
847
848std::vector<PCB_SHAPE*> PAD_TOOL::RecombinePad( PAD* aPad, bool aIsDryRun )
849{
850 int maxError = board()->GetDesignSettings().m_MaxError;
851
852 // Don't leave an object in the point editor that might no longer exist after recombining.
854
855 return aPad->Recombine( aIsDryRun, maxError );
856}
857
858
860{
864
867
870
872}
@ NORMAL
Use all material properties from model file.
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
HIGH_CONTRAST_MODE
Determine how inactive layers should be displayed.
static TOOL_ACTION cancelInteractive
Definition: actions.h:65
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
virtual void Revert() override
std::unique_ptr< PAD > m_Pad_Master
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:264
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:289
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition: board.h:447
const FOOTPRINTS & Footprints() const
Definition: board.h:330
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:874
void Empty()
Clear the list.
Definition: collector.h:89
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:81
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been removed.
Definition: commit.h:92
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Create an undo entry for an item that has been already modified.
Definition: commit.h:105
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
Definition: commit.h:80
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:448
Dialog for enumerating pads.
WX_INFOBAR * GetInfoBar()
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
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:89
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:127
const KIID m_Uuid
Definition: eda_item.h:489
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:104
SHAPE_T GetShape() const
Definition: eda_shape.h:125
void SetWidth(int aWidth)
Definition: eda_shape.h:114
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition: actions.h:277
static const TOOL_EVENT UndoRedoPostEvent
Definition: actions.h:294
EDA_ANGLE GetOrientation() const
Definition: footprint.h:216
PADS & Pads()
Definition: footprint.h:195
const LIB_ID & GetFPID() const
Definition: footprint.h:237
A general implementation of a COLLECTORS_GUIDE.
Definition: collectors.h:324
void SetIgnoreMTextsMarkedNoShow(bool ignore)
Definition: collectors.h:410
void SetIgnoreModulesRefs(bool ignore)
Definition: collectors.h:464
void SetIgnoreModulesVals(bool ignore)
Definition: collectors.h:458
void SetIgnoreMTextsOnFront(bool ignore)
Definition: collectors.h:422
void SetIgnoreMTextsOnBack(bool ignore)
Definition: collectors.h:416
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:207
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.
Definition: collectors.cpp:482
Contains methods for drawing PCB-specific items.
Definition: pcb_painter.h:175
virtual PCB_RENDER_SETTINGS * GetSettings() override
Return a pointer to current settings that are going to be used when drawing items.
Definition: pcb_painter.h:180
PCB specific render settings.
Definition: pcb_painter.h:78
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.
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
An abstract base class for deriving all objects that can be added to a VIEW.
Definition: view_item.h:84
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:1687
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:221
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:1573
Definition: kiid.h:49
LSEQ UIOrder() const
Definition: lset.cpp:865
Tool relating to pads and pad settings.
Definition: pad_tool.h:37
void Reset(RESET_REASON aReason) override
Basic initialization.
Definition: pad_tool.cpp:63
int OnUndoRedo(const TOOL_EVENT &aEvent)
Definition: pad_tool.cpp:706
HIGH_CONTRAST_MODE m_previousHighContrastMode
Definition: pad_tool.h:99
void explodePad(PAD *aPad, PCB_LAYER_ID *aLayer, BOARD_COMMIT &aCommit)
Definition: pad_tool.cpp:808
~PAD_TOOL()
React to model/view changes.
Definition: pad_tool.cpp:59
void setTransitions() override
< Bind handlers to corresponding TOOL_ACTIONs.
Definition: pad_tool.cpp:859
int EditPad(const TOOL_EVENT &aEvent)
Enter/exit WYSIWYG pad shape editing.
Definition: pad_tool.cpp:652
void ExitPadEditMode()
Definition: pad_tool.cpp:778
KIID m_editPad
Definition: pad_tool.h:100
int copyPadSettings(const TOOL_EVENT &aEvent)
Push pad settings from a pad to other pads on board or footprint.
Definition: pad_tool.cpp:173
void enterPadEditMode()
Definition: pad_tool.cpp:742
int pastePadProperties(const TOOL_EVENT &aEvent)
Copy pad settings from a pad to the board design settings.
Definition: pad_tool.cpp:146
int PlacePad(const TOOL_EVENT &aEvent)
Place a pad in footprint editor.
Definition: pad_tool.cpp:540
int EnumeratePads(const TOOL_EVENT &aEvent)
Tool for quick pad enumeration.
Definition: pad_tool.cpp:303
PAD_TOOL()
Definition: pad_tool.cpp:52
bool Init() override
Init() is called once upon a registration of the tool.
Definition: pad_tool.cpp:85
void SetLastPadNumber(const wxString &aPadNumber)
Definition: pad_tool.h:69
std::vector< PCB_SHAPE * > RecombinePad(PAD *aPad, bool aIsDryRun)
Recombine an exploded pad (or one produced with overlapping polygons in an older version).
Definition: pad_tool.cpp:848
wxString m_lastPadNumber
Definition: pad_tool.h:97
int pushPadSettings(const TOOL_EVENT &aEvent)
Definition: pad_tool.cpp:242
Definition: pad.h:54
bool IsAperturePad() const
Definition: pad.h:402
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pad.h:392
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Test to see if this object is on the given layer.
Definition: pad.h:698
PAD_ATTRIB GetAttribute() const
Definition: pad.h:395
static LSET PTHMask()
layer set for a through hole pad
Definition: pad.cpp:286
void DeletePrimitivesList()
Clear the basic shapes list.
const std::vector< std::shared_ptr< PCB_SHAPE > > & GetPrimitives() const
Accessor to the basic shape list for custom-shaped pads.
Definition: pad.h:318
std::vector< PCB_SHAPE * > Recombine(bool aIsDryRun, int aMaxError)
Recombines the pad with other graphical shapes in the footprint.
Definition: pad.cpp:1912
VECTOR2I ShapePos() const
Definition: pad.cpp:896
void ImportSettingsFrom(const PAD &aMasterPad)
Import the pad settings from aMasterPad.
Definition: pad.cpp:1691
PAD_SHAPE GetShape() const
Definition: pad.h:193
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition: pad.h:359
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: pad.cpp:293
void SetShape(PAD_SHAPE aShape)
Set the new shape of this pad.
Definition: pad.h:184
int GetThermalSpokeWidth() const
Definition: pad.h:555
PAD_SHAPE GetAnchorPadShape() const
Definition: pad.h:206
static TOOL_ACTION recombinePad
Definition: pcb_actions.h:475
static TOOL_ACTION enumeratePads
Tool for quick pad enumeration.
Definition: pcb_actions.h:478
static TOOL_ACTION pushPadSettings
Copy the current pad's settings to other pads in the footprint or on the board.
Definition: pcb_actions.h:498
static TOOL_ACTION mirrorH
Mirroring of selected items.
Definition: pcb_actions.h:139
static TOOL_ACTION copyPadSettings
Copy the selected pad's settings to the board design settings.
Definition: pcb_actions.h:492
static TOOL_ACTION placePad
Activation of the drawing tool (placing a PAD)
Definition: pcb_actions.h:472
static TOOL_ACTION properties
Activation of the edit tool.
Definition: pcb_actions.h:176
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:68
static TOOL_ACTION explodePad
Definition: pcb_actions.h:474
static TOOL_ACTION applyPadSettings
Copy the default pad settings to the selected pad.
Definition: pcb_actions.h:495
static TOOL_ACTION mirrorV
Definition: pcb_actions.h:140
static TOOL_ACTION flip
Flipping of selected objects.
Definition: pcb_actions.h:136
static TOOL_ACTION rotateCw
Rotation of selected objects.
Definition: pcb_actions.h:132
static TOOL_ACTION rotateCcw
Definition: pcb_actions.h:133
const PCB_DISPLAY_OPTIONS & GetDisplayOptions() const
Display options control the way tracks, vias, outlines and other things are shown (for instance solid...
EDA_ITEM * GetItem(const KIID &aId) const override
Fetch an item by KIID.
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Returns the BOARD_DESIGN_SETTINGS for the open project.
void SetDisplayOptions(const PCB_DISPLAY_OPTIONS &aOptions, bool aRefresh=true)
Updates the current display options from the given options struct.
GENERAL_COLLECTORS_GUIDE GetCollectorsGuide()
virtual void SetActiveLayer(PCB_LAYER_ID aLayer)
HIGH_CONTRAST_MODE m_ContrastModeDisplay
How inactive layers are displayed.
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #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.
Definition: pcb_shape.cpp:526
bool IsProxyItem() const override
Definition: pcb_shape.h:110
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition: pcb_shape.cpp:317
void Move(const VECTOR2I &aMoveVector) override
Move this object.
Definition: pcb_shape.cpp:455
KIGFX::PCB_VIEW * view() const
PCB_BASE_EDIT_FRAME * frame() const
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.
bool m_isFootprintEditor
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.
int Size() const
Returns the number of selected parts.
Definition: selection.h:116
wxWindow * GetPanel()
Definition: status_popup.h:63
virtual void Popup(wxWindow *aFocus=nullptr)
virtual void Move(const wxPoint &aWhere)
Extension of STATUS_POPUP for displaying a single line text.
Definition: status_popup.h:84
void SetText(const wxString &aText)
Display a text.
virtual void PopTool(const TOOL_EVENT &aEvent)
Pops a tool from the stack.
virtual void PushTool(const TOOL_EVENT &aEvent)
NB: the definition of "tool" is different at the user level.
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:42
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:218
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
@ MODEL_RELOAD
Model changes (the sheet for a schematic)
Definition: tool_base.h:80
Generic, UI-independent tool event.
Definition: tool_event.h:167
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()
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.
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagate an event to tools that requested events of matching type(s).
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:150
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:44
void ShowContextMenu(SELECTION &aSelection)
Helper function to set and immediately show a CONDITIONAL_MENU in concert with the given SELECTION.
Definition: tool_menu.cpp:57
A modified version of the wxInfoBar class that allows us to:
Definition: wx_infobar.h:75
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
Definition: wx_infobar.cpp:304
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Definition: wx_infobar.cpp:190
void ShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION) override
Show the info bar with the provided message and icon.
Definition: wx_infobar.cpp:154
static bool empty(const wxTextEntryBase *aCtrl)
#define _(s)
#define ENTERED
indicates a group has been entered
static const std::vector< KICAD_T > padTypes
Definition: edit_tool.cpp:76
@ FP_SMD
Definition: footprint.h:75
@ FP_THROUGH_HOLE
Definition: footprint.h:74
wxString KeyNameFromKeyCode(int aKeycode, bool *aIsFound)
Return the key name from the key code.
KIID niluuid(0)
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ B_Cu
Definition: layer_ids.h:95
@ F_Cu
Definition: layer_ids.h:64
This file contains miscellaneous commonly used macros and functions.
@ REPAINT
Item needs to be redrawn.
Definition: view_item.h:57
@ ALL
All except INITIAL_ADD.
Definition: view_item.h:58
wxPoint GetMousePosition()
Returns the mouse position in screen coordinates.
Definition: wxgtk/ui.cpp:611
static void doPushPadProperties(BOARD &board, const PAD &aSrcPad, BOARD_COMMIT &commit, bool aSameFootprints, bool aPadShapeFilter, bool aPadOrientFilter, bool aPadLayerFilter, bool aPadTypeFilter)
Definition: pad_tool.cpp:194
static std::optional< SEQUENTIAL_PAD_ENUMERATION_PARAMS > GetSequentialPadNumberingParams(wxWindow *aFrame)
Prompts the user for parameters for sequential pad numbering.
Definition: pad_tool.cpp:289
@ CONN
Like smd, does not appear on the solder paste layer (default) Note: also has a special attribute in G...
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.
const double IU_PER_MM
Definition: base_units.h:76
constexpr int mmToIU(double mm) const
Definition: base_units.h:88
MAGNETIC_OPTIONS tracks
MAGNETIC_OPTIONS pads
Parameters for sequential pad numbering.
@ BUT_LEFT
Definition: tool_event.h:131
@ BUT_RIGHT
Definition: tool_event.h:132
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:673
#define ZONE_THERMAL_RELIEF_COPPER_WIDTH_MM
Definition: zones.h:34