KiCad PCB EDA Suite
edit_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) 2013-2017 CERN
5 * Copyright (C) 2017-2022 KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Maciej Suminski <[email protected]>
7 * @author Tomasz Wlostowski <[email protected]>
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 <advanced_config.h>
28#include <limits>
29#include <board.h>
31#include <footprint.h>
32#include <fp_shape.h>
33#include <fp_textbox.h>
34#include <pcb_group.h>
35#include <pcb_target.h>
36#include <pcb_text.h>
37#include <pcb_textbox.h>
38#include <collectors.h>
39#include <pcb_edit_frame.h>
41#include <kiway.h>
42#include <array_creator.h>
43#include <status_popup.h>
45#include <tool/tool_manager.h>
46#include <tools/pcb_actions.h>
48#include <tools/edit_tool.h>
52#include <tools/pad_tool.h>
53#include <view/view_controls.h>
56#include <bitmaps.h>
57#include <cassert>
58#include <functional>
59using namespace std::placeholders;
60#include "kicad_clipboard.h"
61#include <wx/hyperlink.h>
62#include <router/router_tool.h>
66#include <board_commit.h>
67#include <zone_filler.h>
68
69const unsigned int EDIT_TOOL::COORDS_PADDING = pcbIUScale.mmToIU( 20 );
70
72 PCB_TOOL_BASE( "pcbnew.InteractiveEdit" ),
73 m_selectionTool( nullptr ),
74 m_dragging( false )
75{
76}
77
78
80{
81 m_dragging = false;
82
83 m_statusPopup = std::make_unique<STATUS_TEXT_POPUP>( getEditFrame<PCB_BASE_EDIT_FRAME>() );
84
85 if( aReason != RUN )
86 m_commit.reset( new BOARD_COMMIT( this ) );
87}
88
89
91 CONDITIONAL_MENU( aTool )
92{
94 SetTitle( _( "Positioning Tools" ) );
95
99}
100
101
103{
104 // Find the selection tool, so they can cooperate
106
107 auto positioningToolsSubMenu = std::make_shared<POSITIONING_TOOLS_MENU>( this );
108 m_selectionTool->GetToolMenu().RegisterSubMenu( positioningToolsSubMenu );
109
110 auto propertiesCondition =
111 [&]( const SELECTION& aSel )
112 {
113 if( aSel.GetSize() == 0 )
114 {
116 {
119
120 if( ds && ds->HitTestDrawingSheetItems( getView(), cursor ) )
121 return true;
122 }
123
124 return false;
125 }
126
127 if( aSel.GetSize() == 1 )
128 return true;
129
130 for( EDA_ITEM* item : aSel )
131 {
132 if( !dynamic_cast<PCB_TRACK*>( item ) )
133 return false;
134 }
135
136 return true;
137 };
138
139 auto inFootprintEditor =
140 [ this ]( const SELECTION& aSelection )
141 {
142 return m_isFootprintEditor;
143 };
144
145 auto singleFootprintCondition = SELECTION_CONDITIONS::OnlyTypes( { PCB_FOOTPRINT_T } )
147
148 auto noActiveToolCondition =
149 [ this ]( const SELECTION& aSelection )
150 {
151 return frame()->ToolStackIsEmpty();
152 };
153
154 auto notMovingCondition =
155 [ this ]( const SELECTION& aSelection )
156 {
159 };
160
161 auto noItemsCondition =
162 [ this ]( const SELECTION& aSelections ) -> bool
163 {
164 return frame()->GetBoard() && !frame()->GetBoard()->IsEmpty();
165 };
166
167 static std::vector<KICAD_T> connectedTypes = { PCB_TRACE_T,
168 PCB_ARC_T,
169 PCB_VIA_T,
170 PCB_PAD_T,
171 PCB_ZONE_T };
172
173 static std::vector<KICAD_T> unroutableTypes = { PCB_TRACE_T,
174 PCB_ARC_T,
175 PCB_VIA_T,
176 PCB_PAD_T,
178
179 static std::vector<KICAD_T> trackTypes = { PCB_TRACE_T,
180 PCB_ARC_T,
181 PCB_VIA_T };
182
183
184 // Add context menu entries that are displayed when selection tool is active
186
188 && notMovingCondition );
190 && SELECTION_CONDITIONS::OnlyTypes( unroutableTypes ) );
192 && notMovingCondition );
194 && SELECTION_CONDITIONS::OnlyTypes( trackTypes ) );
209
210 menu.AddItem( PCB_ACTIONS::properties, propertiesCondition );
211
214
215 // Footprint actions
216 menu.AddSeparator();
217 menu.AddItem( PCB_ACTIONS::editFpInFpEditor, singleFootprintCondition );
218 menu.AddItem( PCB_ACTIONS::updateFootprint, singleFootprintCondition );
219 menu.AddItem( PCB_ACTIONS::changeFootprint, singleFootprintCondition );
220
221 // Add the submenu for the special positioning tools
222 menu.AddSeparator( 100 );
223 menu.AddMenu( positioningToolsSubMenu.get(), SELECTION_CONDITIONS::NotEmpty, 100 );
224
225 menu.AddSeparator( 150 );
228
229 // Selection tool handles the context menu for some other tools, such as the Picker.
230 // Don't add things like Paste when another tool is active.
231 menu.AddItem( ACTIONS::paste, noActiveToolCondition, 150 );
232 menu.AddItem( ACTIONS::pasteSpecial, noActiveToolCondition && !inFootprintEditor, 150 );
235
236 menu.AddSeparator( 150 );
237 menu.AddItem( ACTIONS::selectAll, noItemsCondition, 150 );
238
239 return true;
240}
241
242
244{
245 // GetAndPlace makes sense only in board editor, although it is also called
246 // in fpeditor, that shares the same EDIT_TOOL list
247 if( !getEditFrame<PCB_BASE_FRAME>()->IsType( FRAME_PCB_EDITOR ) )
248 return 0;
249
251 FOOTPRINT* fp = getEditFrame<PCB_BASE_FRAME>()->GetFootprintFromBoardByReference();
252
253 if( fp )
254 {
256 m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, (void*) fp );
257
258 selectionTool->GetSelection().SetReferencePoint( fp->GetPosition() );
260 }
261
262 return 0;
263}
264
265
266bool EDIT_TOOL::invokeInlineRouter( int aDragMode )
267{
269
270 if( !theRouter )
271 return false;
272
273 // don't allow switch from moving to dragging
274 if( m_dragging )
275 {
276 wxBell();
277 return false;
278 }
279
280 // make sure we don't accidentally invoke inline routing mode while the router is already
281 // active!
282 if( theRouter->IsToolActive() )
283 return false;
284
285 if( theRouter->CanInlineDrag( aDragMode ) )
286 {
288 static_cast<intptr_t>( aDragMode ) );
289 return true;
290 }
291
292 return false;
293}
294
295
297{
299
300 return router && router->RoutingInProgress();
301}
302
303
304int EDIT_TOOL::Drag( const TOOL_EVENT& aEvent )
305{
306 if( !m_toolMgr->GetTool<ROUTER_TOOL>() )
307 return false; // don't drag when no router tool (i.e. fp editor)
308
310 return false; // don't drag when router is already active
311
312 int mode = PNS::DM_ANY;
313
314 if( aEvent.IsAction( &PCB_ACTIONS::dragFreeAngle ) )
315 mode |= PNS::DM_FREE_ANGLE;
316
318 []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
319 {
320 sTool->FilterCollectorForFreePads( aCollector );
321 sTool->FilterCollectorForHierarchy( aCollector, true );
322
323 if( aCollector.GetCount() > 1 )
324 sTool->GuessSelectionCandidates( aCollector, aPt );
325
326 /*
327 * If we have a knee between two segments, or a via attached to two segments,
328 * then drop the selection to a single item.
329 */
330
331 std::vector<PCB_TRACK*> tracks;
332 std::vector<PCB_TRACK*> vias;
333
334 for( EDA_ITEM* item : aCollector )
335 {
336 if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( item ) )
337 {
338 if( track->Type() == PCB_VIA_T )
339 vias.push_back( track );
340 else
341 tracks.push_back( track );
342 }
343 }
344
345 auto connected = []( PCB_TRACK* track, const VECTOR2I& pt )
346 {
347 return track->GetStart() == pt || track->GetEnd() == pt;
348 };
349
350 if( tracks.size() == 2 && vias.size() == 0 )
351 {
352 if( connected( tracks[0], tracks[1]->GetStart() )
353 || connected( tracks[0], tracks[1]->GetEnd() ) )
354 {
355 aCollector.Remove( tracks[1] );
356 }
357 }
358 else if( tracks.size() == 2 && vias.size() == 1 )
359 {
360 if( connected( tracks[0], vias[0]->GetPosition() )
361 && connected( tracks[1], vias[0]->GetPosition() ) )
362 {
363 aCollector.Remove( tracks[0] );
364 aCollector.Remove( tracks[1] );
365 }
366 }
367 },
368 true /* prompt user regarding locked items */ );
369
370 if( selection.Empty() )
371 return 0;
372
373 if( selection.Size() == 1 && selection.Front()->Type() == PCB_ARC_T )
374 {
375 // TODO: This really should be done in PNS to ensure DRC is maintained, but for now
376 // it allows interactive editing of an arc track
377 return DragArcTrack( aEvent );
378 }
379 else
380 {
381 invokeInlineRouter( mode );
382 }
383
384 return 0;
385}
386
387
389{
391
392 if( selection.Size() != 1 || selection.Front()->Type() != PCB_ARC_T )
393 return 0;
394
395 PCB_ARC* theArc = static_cast<PCB_ARC*>( selection.Front() );
396 EDA_ANGLE maxTangentDeviation( ADVANCED_CFG::GetCfg().m_MaxTangentAngleDeviation, DEGREES_T );
397
398 if( theArc->GetAngle() + maxTangentDeviation >= ANGLE_180 )
399 {
400 wxString msg = wxString::Format( _( "Unable to resize arc tracks of %s or greater." ),
401 EDA_UNIT_UTILS::UI::MessageTextFromValue( ANGLE_180 - maxTangentDeviation ) );
402 frame()->ShowInfoBarError( msg );
403
404 return 0; // don't bother with > 180 degree arcs
405 }
406
408
409 Activate();
410 // Must be done after Activate() so that it gets set into the correct context
411 controls->ShowCursor( true );
412 controls->SetAutoPan( true );
413
414 bool restore_state = false;
415 VECTOR2I arcCenter = theArc->GetCenter();
416 SEG tanStart = SEG( arcCenter, theArc->GetStart() ).PerpendicularSeg( theArc->GetStart() );
417 SEG tanEnd = SEG( arcCenter, theArc->GetEnd() ).PerpendicularSeg( theArc->GetEnd() );
418
419 //Ensure the tangent segments are in the correct orientation
420 OPT_VECTOR2I tanIntersect = tanStart.IntersectLines( tanEnd );
421
422 if( !tanIntersect )
423 return 0;
424
425 tanStart.A = *tanIntersect;
426 tanStart.B = theArc->GetStart();
427 tanEnd.A = *tanIntersect;
428 tanEnd.B = theArc->GetEnd();
429
430 auto getUniqueTrackAtAnchorCollinear =
431 [&]( const VECTOR2I& aAnchor, const SEG& aCollinearSeg ) -> PCB_TRACK*
432 {
433 std::shared_ptr<CONNECTIVITY_DATA> conn = board()->GetConnectivity();
434
435 // Allow items at a distance within the width of the arc track
436 int allowedDeviation = theArc->GetWidth();
437
438 std::vector<BOARD_CONNECTED_ITEM*> itemsOnAnchor;
439
440 for( int i = 0; i < 3; i++ )
441 {
442 itemsOnAnchor = conn->GetConnectedItemsAtAnchor( theArc, aAnchor,
445 allowedDeviation );
446 allowedDeviation /= 2;
447
448 if( itemsOnAnchor.size() == 1 )
449 break;
450 }
451
452 PCB_TRACK* retval = nullptr;
453
454 if( itemsOnAnchor.size() == 1 && itemsOnAnchor.front()->Type() == PCB_TRACE_T )
455 {
456 retval = static_cast<PCB_TRACK*>( itemsOnAnchor.front() );
457 SEG trackSeg( retval->GetStart(), retval->GetEnd() );
458
459 // Allow deviations in colinearity as defined in ADVANCED_CFG
460 if( trackSeg.Angle( aCollinearSeg ) > maxTangentDeviation )
461 retval = nullptr;
462 }
463
464 if( !retval )
465 {
466 retval = new PCB_TRACK( theArc->GetParent() );
467 retval->SetStart( aAnchor );
468 retval->SetEnd( aAnchor );
469 retval->SetNet( theArc->GetNet() );
470 retval->SetLayer( theArc->GetLayer() );
471 retval->SetWidth( theArc->GetWidth() );
472 retval->SetLocked( theArc->IsLocked() );
473 retval->SetFlags( IS_NEW );
474 getView()->Add( retval );
475 }
476
477 return retval;
478 };
479
480 PCB_TRACK* trackOnStart = getUniqueTrackAtAnchorCollinear( theArc->GetStart(), tanStart);
481 PCB_TRACK* trackOnEnd = getUniqueTrackAtAnchorCollinear( theArc->GetEnd(), tanEnd );
482
483 // Make copies of items to be edited
484 PCB_ARC* theArcCopy = new PCB_ARC( *theArc );
485 PCB_TRACK* trackOnStartCopy = new PCB_TRACK( *trackOnStart );
486 PCB_TRACK* trackOnEndCopy = new PCB_TRACK( *trackOnEnd );
487
488 if( trackOnStart->GetLength() != 0 )
489 {
490 tanStart.A = trackOnStart->GetStart();
491 tanStart.B = trackOnStart->GetEnd();
492 }
493
494 if( trackOnEnd->GetLength() != 0 )
495 {
496 tanEnd.A = trackOnEnd->GetStart();
497 tanEnd.B = trackOnEnd->GetEnd();
498 }
499
500 // Recalculate intersection point
501 if( tanIntersect = tanStart.IntersectLines( tanEnd ); !tanIntersect )
502 return 0;
503
504 auto isTrackStartClosestToArcStart =
505 [&]( PCB_TRACK* aTrack ) -> bool
506 {
507 double trackStartToArcStart = GetLineLength( aTrack->GetStart(), theArc->GetStart() );
508 double trackEndToArcStart = GetLineLength( aTrack->GetEnd(), theArc->GetStart() );
509
510 return trackStartToArcStart < trackEndToArcStart;
511 };
512
513 bool isStartTrackOnStartPt = isTrackStartClosestToArcStart( trackOnStart );
514 bool isEndTrackOnStartPt = isTrackStartClosestToArcStart( trackOnEnd );
515
516 // Calculate constraints
517 //======================
518 // maxTanCircle is the circle with maximum radius that is tangent to the two adjacent straight
519 // tracks and whose tangent points are constrained within the original tracks and their
520 // projected intersection points.
521 //
522 // The cursor will be constrained first within the isosceles triangle formed by the segments
523 // cSegTanStart, cSegTanEnd and cSegChord. After that it will be constrained to be outside
524 // maxTanCircle.
525 //
526 //
527 // ____________ <-cSegTanStart
528 // / * . ' *
529 // cSegTanEnd-> / * . ' *
530 // /* . ' <-cSegChord *
531 // /. '
532 // /* *
533 //
534 // * c * <-maxTanCircle
535 //
536 // * *
537 //
538 // * *
539 // * *
540 // * *
541 //
542
543 auto getFurthestPointToTanInterstect =
544 [&]( VECTOR2I& aPointA, VECTOR2I& aPointB ) -> VECTOR2I
545 {
546 if( ( aPointA - *tanIntersect ).EuclideanNorm()
547 > ( aPointB - *tanIntersect ).EuclideanNorm() )
548 {
549 return aPointA;
550 }
551 else
552 {
553 return aPointB;
554 }
555 };
556
557 CIRCLE maxTanCircle;
558 VECTOR2I tanStartPoint = getFurthestPointToTanInterstect( tanStart.A, tanStart.B );
559 VECTOR2I tanEndPoint = getFurthestPointToTanInterstect( tanEnd.A, tanEnd.B );
560 VECTOR2I tempTangentPoint = tanEndPoint;
561
562 if( getFurthestPointToTanInterstect( tanStartPoint, tanEndPoint ) == tanEndPoint )
563 tempTangentPoint = tanStartPoint;
564
565 maxTanCircle.ConstructFromTanTanPt( tanStart, tanEnd, tempTangentPoint );
566 VECTOR2I maxTanPtStart = tanStart.LineProject( maxTanCircle.Center );
567 VECTOR2I maxTanPtEnd = tanEnd.LineProject( maxTanCircle.Center );
568
569 SEG cSegTanStart( maxTanPtStart, *tanIntersect );
570 SEG cSegTanEnd( maxTanPtEnd, *tanIntersect );
571 SEG cSegChord( maxTanPtStart, maxTanPtEnd );
572
573 int cSegTanStartSide = cSegTanStart.Side( theArc->GetMid() );
574 int cSegTanEndSide = cSegTanEnd.Side( theArc->GetMid() );
575 int cSegChordSide = cSegChord.Side( theArc->GetMid() );
576
577 bool eatFirstMouseUp = true;
578
579 // Start the tool loop
580 while( TOOL_EVENT* evt = Wait() )
581 {
583
584 // Constrain cursor within the isosceles triangle
585 if( cSegTanStartSide != cSegTanStart.Side( m_cursor )
586 || cSegTanEndSide != cSegTanEnd.Side( m_cursor )
587 || cSegChordSide != cSegChord.Side( m_cursor ) )
588 {
589 std::vector<VECTOR2I> possiblePoints;
590
591 possiblePoints.push_back( cSegTanEnd.NearestPoint( m_cursor ) );
592 possiblePoints.push_back( cSegChord.NearestPoint( m_cursor ) );
593
594 VECTOR2I closest = cSegTanStart.NearestPoint( m_cursor );
595
596 for( VECTOR2I candidate : possiblePoints )
597 {
598 if( ( candidate - m_cursor ).SquaredEuclideanNorm()
599 < ( closest - m_cursor ).SquaredEuclideanNorm() )
600 {
601 closest = candidate;
602 }
603 }
604
605 m_cursor = closest;
606 }
607
608 // Constrain cursor to be outside maxTanCircle
609 if( ( m_cursor - maxTanCircle.Center ).EuclideanNorm() < maxTanCircle.Radius )
610 m_cursor = maxTanCircle.NearestPoint( m_cursor );
611
613
614 // Calculate resulting object coordinates
615 CIRCLE circlehelper;
616 circlehelper.ConstructFromTanTanPt( cSegTanStart, cSegTanEnd, m_cursor );
617
618 VECTOR2I newCenter = circlehelper.Center;
619 VECTOR2I newStart = cSegTanStart.LineProject( newCenter );
620 VECTOR2I newEnd = cSegTanEnd.LineProject( newCenter );
621 VECTOR2I newMid = CalcArcMid( newStart, newEnd, newCenter );
622
623 // Update objects
624 theArc->SetStart( newStart );
625 theArc->SetEnd( newEnd );
626 theArc->SetMid( newMid );
627
628 if( isStartTrackOnStartPt )
629 trackOnStart->SetStart( newStart );
630 else
631 trackOnStart->SetEnd( newStart );
632
633 if( isEndTrackOnStartPt )
634 trackOnEnd->SetStart( newEnd );
635 else
636 trackOnEnd->SetEnd( newEnd );
637
638 // Update view
639 getView()->Update( trackOnStart );
640 getView()->Update( trackOnEnd );
641 getView()->Update( theArc );
642
643 // Handle events
644 if( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) )
645 {
646 eatFirstMouseUp = false;
647 }
648 else if( evt->IsCancelInteractive() || evt->IsActivate() )
649 {
650 restore_state = true; // Canceling the tool means that items have to be restored
651 break; // Finish
652 }
653 else if( evt->IsAction( &ACTIONS::undo ) )
654 {
655 restore_state = true; // Perform undo locally
656 break; // Finish
657 }
658 else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT )
659 || evt->IsDblClick( BUT_LEFT ) )
660 {
661 // Eat mouse-up/-click events that leaked through from the lock dialog
662 if( eatFirstMouseUp && evt->Parameter<intptr_t>() != ACTIONS::CURSOR_CLICK )
663 {
664 eatFirstMouseUp = false;
665 continue;
666 }
667
668 break; // Finish
669 }
670 }
671
672 // Ensure we only do one commit operation on each object
673 auto processTrack =
674 [&]( PCB_TRACK* aTrack, PCB_TRACK* aTrackCopy, int aMaxLengthIU ) -> bool
675 {
676 if( aTrack->IsNew() )
677 {
678 getView()->Remove( aTrack );
679
680 if( aTrack->GetLength() <= aMaxLengthIU )
681 {
682 delete aTrack;
683 delete aTrackCopy;
684 aTrack = nullptr;
685 aTrackCopy = nullptr;
686 return false;
687 }
688 else
689 {
690 m_commit->Add( aTrack );
691 delete aTrackCopy;
692 aTrackCopy = nullptr;
693 return true;
694 }
695 }
696 else if( aTrack->GetLength() <= aMaxLengthIU )
697 {
698 aTrack->SwapData( aTrackCopy ); //restore the original before notifying COMMIT
699 m_commit->Remove( aTrack );
700 delete aTrackCopy;
701 aTrackCopy = nullptr;
702 return false;
703 }
704 else
705 {
706 m_commit->Modified( aTrack, aTrackCopy );
707 }
708
709 return true;
710 };
711
712 // Amend the end points of the arc if we delete the joining tracks
713 VECTOR2I newStart = trackOnStart->GetStart();
714 VECTOR2I newEnd = trackOnEnd->GetStart();
715
716 if( isStartTrackOnStartPt )
717 newStart = trackOnStart->GetEnd();
718
719 if( isEndTrackOnStartPt )
720 newEnd = trackOnEnd->GetEnd();
721
722 int maxLengthIU =
723 KiROUND( ADVANCED_CFG::GetCfg().m_MaxTrackLengthToKeep * pcbIUScale.IU_PER_MM );
724
725 if( !processTrack( trackOnStart, trackOnStartCopy, maxLengthIU ) )
726 theArc->SetStart( newStart );
727
728 if( !processTrack( trackOnEnd, trackOnEndCopy, maxLengthIU ) )
729 theArc->SetEnd( newEnd );
730
731 processTrack( theArc, theArcCopy, 0 ); // only delete the arc if start and end points coincide
732
733 // Should we commit?
734 if( restore_state )
735 m_commit->Revert();
736 else
737 m_commit->Push( _( "Drag Arc Track" ) );
738
739 return 0;
740}
741
742
744{
746 []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
747 {
748 // Iterate from the back so we don't have to worry about removals.
749 for( int i = aCollector.GetCount() - 1; i >= 0; --i )
750 {
751 BOARD_ITEM* item = aCollector[ i ];
752
753 if( !dynamic_cast<PCB_TRACK*>( item ) )
754 aCollector.Remove( item );
755 }
756 },
757 true /* prompt user regarding locked items */ );
758
759 for( EDA_ITEM* item : selection )
760 {
761 if( item->Type() == PCB_VIA_T )
762 {
763 PCB_VIA* via = static_cast<PCB_VIA*>( item );
764
765 m_commit->Modify( via );
766
767 int new_width;
768 int new_drill;
769
770 if( via->GetViaType() == VIATYPE::MICROVIA )
771 {
772 NETCLASS* netClass = via->GetEffectiveNetClass();
773
774 new_width = netClass->GetuViaDiameter();
775 new_drill = netClass->GetuViaDrill();
776 }
777 else
778 {
779 new_width = board()->GetDesignSettings().GetCurrentViaSize();
780 new_drill = board()->GetDesignSettings().GetCurrentViaDrill();
781 }
782
783 via->SetDrill( new_drill );
784 via->SetWidth( new_width );
785 }
786 else if( item->Type() == PCB_TRACE_T || item->Type() == PCB_ARC_T )
787 {
788 PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( item );
789
790 wxCHECK( track, 0 );
791
792 m_commit->Modify( track );
793
794 int new_width = board()->GetDesignSettings().GetCurrentTrackWidth();
795 track->SetWidth( new_width );
796 }
797 }
798
799 m_commit->Push( _( "Edit track width/via size" ) );
800
801 if( selection.IsHover() )
802 {
804
805 // Notify other tools of the changes -- This updates the visual ratsnest
807 }
808
809 return 0;
810}
811
812
814{
815 // Store last used fillet radius to allow pressing "enter" if repeat fillet is required
816 static long long filletRadiusIU = 0;
817
819 []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
820 {
821 // Iterate from the back so we don't have to worry about removals.
822 for( int i = aCollector.GetCount() - 1; i >= 0; --i )
823 {
824 BOARD_ITEM* item = aCollector[i];
825
826 if( !dynamic_cast<PCB_TRACK*>( item ) )
827 aCollector.Remove( item );
828 }
829 },
830 true /* prompt user regarding locked items */ );
831
832 if( selection.Size() < 2 )
833 {
834 frame()->ShowInfoBarMsg( _( "At least two straight track segments must be selected." ) );
835 return 0;
836 }
837
838 WX_UNIT_ENTRY_DIALOG dia( frame(), _( "Enter fillet radius:" ), _( "Fillet Tracks" ),
839 filletRadiusIU );
840
841 if( dia.ShowModal() == wxID_CANCEL )
842 return 0;
843
844 filletRadiusIU = dia.GetValue();
845
846 if( filletRadiusIU == 0 )
847 {
848 frame()->ShowInfoBarMsg( _( "A radius of zero was entered.\n"
849 "The fillet operation was not performed." ) );
850 return 0;
851 }
852
853 struct FILLET_OP
854 {
855 PCB_TRACK* t1;
856 PCB_TRACK* t2;
857 // Start point of track is modified after PCB_ARC is added, otherwise the end point:
858 bool t1Start = true;
859 bool t2Start = true;
860 };
861
862 std::vector<FILLET_OP> filletOperations;
863 bool operationPerformedOnAtLeastOne = false;
864 bool didOneAttemptFail = false;
865 std::set<PCB_TRACK*> processedTracks;
866
867 for( EDA_ITEM* item : selection )
868 {
869 PCB_TRACK* track = dyn_cast<PCB_TRACK*>( item );
870
871 if( !track || track->Type() != PCB_TRACE_T || track->GetLength() == 0 )
872 {
873 continue;
874 }
875
876 auto processFilletOp =
877 [&]( bool aStartPoint )
878 {
879 std::shared_ptr<CONNECTIVITY_DATA> c = board()->GetConnectivity();
880 VECTOR2I anchor = aStartPoint ? track->GetStart()
881 : track->GetEnd();
882 std::vector<BOARD_CONNECTED_ITEM*> itemsOnAnchor;
883
884 itemsOnAnchor = c->GetConnectedItemsAtAnchor( track, anchor,
887
888 if( itemsOnAnchor.size() > 0
889 && selection.Contains( itemsOnAnchor.at( 0 ) )
890 && itemsOnAnchor.at( 0 )->Type() == PCB_TRACE_T )
891 {
892 PCB_TRACK* trackOther = dyn_cast<PCB_TRACK*>( itemsOnAnchor.at( 0 ) );
893
894 // Make sure we don't fillet the same pair of tracks twice
895 if( processedTracks.find( trackOther ) == processedTracks.end() )
896 {
897 if( itemsOnAnchor.size() == 1 )
898 {
899 FILLET_OP filletOp;
900 filletOp.t1 = track;
901 filletOp.t2 = trackOther;
902 filletOp.t1Start = aStartPoint;
903 filletOp.t2Start = track->IsPointOnEnds( filletOp.t2->GetStart() );
904 filletOperations.push_back( filletOp );
905 }
906 else
907 {
908 // User requested to fillet these two tracks but not possible as
909 // there are other elements connected at that point
910 didOneAttemptFail = true;
911 }
912 }
913 }
914 };
915
916 processFilletOp( true ); // on the start point of track
917 processFilletOp( false ); // on the end point of track
918
919 processedTracks.insert( track );
920 }
921
922 std::vector<BOARD_ITEM*> itemsToAddToSelection;
923
924 for( FILLET_OP filletOp : filletOperations )
925 {
926 PCB_TRACK* track1 = filletOp.t1;
927 PCB_TRACK* track2 = filletOp.t2;
928
929 bool trackOnStart = track1->IsPointOnEnds( track2->GetStart() );
930 bool trackOnEnd = track1->IsPointOnEnds( track2->GetEnd() );
931
932 if( trackOnStart && trackOnEnd )
933 continue; // Ignore duplicate tracks
934
935 if( ( trackOnStart || trackOnEnd ) && track1->GetLayer() == track2->GetLayer() )
936 {
937 SEG t1Seg( track1->GetStart(), track1->GetEnd() );
938 SEG t2Seg( track2->GetStart(), track2->GetEnd() );
939
940 if( t1Seg.ApproxCollinear( t2Seg ) )
941 continue;
942
943 SHAPE_ARC sArc( t1Seg, t2Seg, filletRadiusIU );
944 VECTOR2I t1newPoint, t2newPoint;
945
946 auto setIfPointOnSeg =
947 []( VECTOR2I& aPointToSet, SEG aSegment, VECTOR2I aVecToTest )
948 {
949 VECTOR2I segToVec = aSegment.NearestPoint( aVecToTest ) - aVecToTest;
950
951 // Find out if we are on the segment (minimum precision)
953 {
954 aPointToSet.x = aVecToTest.x;
955 aPointToSet.y = aVecToTest.y;
956 return true;
957 }
958
959 return false;
960 };
961
962 //Do not draw a fillet if the end points of the arc are not within the track segments
963 if( !setIfPointOnSeg( t1newPoint, t1Seg, sArc.GetP0() )
964 && !setIfPointOnSeg( t2newPoint, t2Seg, sArc.GetP0() ) )
965 {
966 didOneAttemptFail = true;
967 continue;
968 }
969
970 if( !setIfPointOnSeg( t1newPoint, t1Seg, sArc.GetP1() )
971 && !setIfPointOnSeg( t2newPoint, t2Seg, sArc.GetP1() ) )
972 {
973 didOneAttemptFail = true;
974 continue;
975 }
976
977 PCB_ARC* tArc = new PCB_ARC( frame()->GetBoard(), &sArc );
978 tArc->SetLayer( track1->GetLayer() );
979 tArc->SetWidth( track1->GetWidth() );
980 tArc->SetNet( track1->GetNet() );
981 tArc->SetLocked( track1->IsLocked() );
982 m_commit->Add( tArc );
983 itemsToAddToSelection.push_back( tArc );
984
985 m_commit->Modify( track1 );
986 m_commit->Modify( track2 );
987
988 if( filletOp.t1Start )
989 track1->SetStart( t1newPoint );
990 else
991 track1->SetEnd( t1newPoint );
992
993 if( filletOp.t2Start )
994 track2->SetStart( t2newPoint );
995 else
996 track2->SetEnd( t2newPoint );
997
998 operationPerformedOnAtLeastOne = true;
999 }
1000 }
1001
1002 m_commit->Push( _( "Fillet Tracks" ) );
1003
1004 //select the newly created arcs
1005 for( BOARD_ITEM* item : itemsToAddToSelection )
1007
1008 if( !operationPerformedOnAtLeastOne )
1009 frame()->ShowInfoBarMsg( _( "Unable to fillet the selected track segments." ) );
1010 else if( didOneAttemptFail )
1011 frame()->ShowInfoBarMsg( _( "Some of the track segments could not be filleted." ) );
1012
1013 return 0;
1014}
1015
1016
1018{
1019 PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
1021 []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
1022 {
1023 } );
1024
1025 // Tracks & vias are treated in a special way:
1027 {
1029 dlg.ShowQuasiModal(); // QuasiModal required for NET_SELECTOR
1030 }
1031 else if( selection.Size() == 1 )
1032 {
1033 // Display properties dialog
1034 BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.Front() );
1035
1036 // Do not handle undo buffer, it is done by the properties dialogs
1037 editFrame->OnEditItemRequest( item );
1038
1039 // Notify other tools of the changes
1041 }
1042 else if( selection.Size() == 0 && getView()->IsLayerVisible( LAYER_DRAWINGSHEET ) )
1043 {
1044 DS_PROXY_VIEW_ITEM* ds = editFrame->GetCanvas()->GetDrawingSheet();
1045 VECTOR2D cursorPos = getViewControls()->GetCursorPosition( false );
1046
1047 if( ds && ds->HitTestDrawingSheetItems( getView(), cursorPos ) )
1049 else
1051 }
1052
1053 if( selection.IsHover() )
1054 {
1056 }
1057 else
1058 {
1059 // Check for items becoming invisible and drop them from the selection.
1060
1061 PCB_SELECTION selCopy = selection;
1062 LSET visible = editFrame->GetBoard()->GetVisibleLayers();
1063
1064 for( EDA_ITEM* eda_item : selCopy )
1065 {
1066 BOARD_ITEM* item = static_cast<BOARD_ITEM*>( eda_item );
1067
1068 if( !( item->GetLayerSet() & visible ).any() )
1070 }
1071 }
1072
1073 return 0;
1074}
1075
1076
1077int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
1078{
1079 if( isRouterActive() )
1080 {
1081 wxBell();
1082 return 0;
1083 }
1084
1085 PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
1086
1087 // Be sure that there is at least one item that we can modify. If nothing was selected before,
1088 // try looking for the stuff under mouse cursor (i.e. KiCad old-style hover selection)
1090 []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
1091 {
1092 sTool->FilterCollectorForHierarchy( aCollector, true );
1093 sTool->FilterCollectorForMarkers( aCollector );
1094 },
1095 // Prompt user regarding locked items if in board editor and in free-pad-mode (if
1096 // we're not in free-pad mode we delay this until the second RequestSelection()).
1098
1099 if( selection.Empty() )
1100 return 0;
1101
1102 std::optional<VECTOR2I> oldRefPt;
1103 bool is_hover = selection.IsHover(); // N.B. This must be saved before the second
1104 // call to RequestSelection() below
1105
1107 oldRefPt = selection.GetReferencePoint();
1108
1109 // Now filter out pads if not in free pads mode. We cannot do this in the first
1110 // RequestSelection() as we need the reference point when a pad is the selection front.
1112 {
1114 []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
1115 {
1116 sTool->FilterCollectorForMarkers( aCollector );
1117 sTool->FilterCollectorForHierarchy( aCollector, true );
1118 sTool->FilterCollectorForFreePads( aCollector );
1119 },
1120 true /* prompt user regarding locked items */ );
1121 }
1122
1123 // Did we filter everything out? If so, don't try to operate further
1124 if( selection.Empty() )
1125 return 0;
1126
1128
1130 EDA_ANGLE rotateAngle = TOOL_EVT_UTILS::GetEventRotationAngle( *editFrame, aEvent );
1131
1132 // Calculate view bounding box
1133 BOX2I viewBBox = selection.Front()->ViewBBox();
1134
1135 for( EDA_ITEM* item : selection )
1136 viewBBox.Merge( item->ViewBBox() );
1137
1138 // Check if the view bounding box will go out of bounds
1139 VECTOR2D rotPos = viewBBox.GetPosition();
1140 VECTOR2D rotEnd = viewBBox.GetEnd();
1141
1142 RotatePoint( &rotPos.x, &rotPos.y, refPt.x, refPt.y, rotateAngle );
1143 RotatePoint( &rotEnd.x, &rotEnd.y, refPt.x, refPt.y, rotateAngle );
1144
1145 typedef std::numeric_limits<int> coord_limits;
1146
1147 int max = coord_limits::max() - COORDS_PADDING;
1148 int min = -max;
1149
1150 bool outOfBounds = rotPos.x < min || rotPos.x > max || rotPos.y < min || rotPos.y > max
1151 || rotEnd.x < min || rotEnd.x > max || rotEnd.y < min || rotEnd.y > max;
1152
1153 if( !outOfBounds )
1154 {
1155 // When editing footprints, all items have the same parent
1156 if( IsFootprintEditor() )
1157 m_commit->Modify( selection.Front() );
1158
1159 for( EDA_ITEM* item : selection )
1160 {
1161 if( !item->IsNew() && !IsFootprintEditor() )
1162 {
1163 m_commit->Modify( item );
1164
1165 // If rotating a group, record position of all the descendants for undo
1166 if( item->Type() == PCB_GROUP_T )
1167 {
1168 static_cast<PCB_GROUP*>( item )->RunOnDescendants( [&]( BOARD_ITEM* bItem )
1169 {
1170 m_commit->Modify( bItem );
1171 });
1172 }
1173 }
1174
1175 static_cast<BOARD_ITEM*>( item )->Rotate( refPt, rotateAngle );
1176 }
1177
1178 if( !m_dragging )
1179 m_commit->Push( _( "Rotate" ) );
1180
1181 if( is_hover && !m_dragging )
1183
1185
1186 if( m_dragging )
1188 }
1189
1190 // Restore the old reference so any mouse dragging that occurs doesn't make the selection jump
1191 // to this now invalid reference
1192 if( oldRefPt )
1193 selection.SetReferencePoint( *oldRefPt );
1194 else
1196
1197 return 0;
1198}
1199
1200
1204static VECTOR2I mirrorPointX( const VECTOR2I& aPoint, const VECTOR2I& aMirrorPoint )
1205{
1206 VECTOR2I mirrored = aPoint;
1207
1208 mirrored.x -= aMirrorPoint.x;
1209 mirrored.x = -mirrored.x;
1210 mirrored.x += aMirrorPoint.x;
1211
1212 return mirrored;
1213}
1214
1215
1219static VECTOR2I mirrorPointY( const VECTOR2I& aPoint, const VECTOR2I& aMirrorPoint )
1220{
1221 VECTOR2I mirrored = aPoint;
1222
1223 mirrored.y -= aMirrorPoint.y;
1224 mirrored.y = -mirrored.y;
1225 mirrored.y += aMirrorPoint.y;
1226
1227 return mirrored;
1228}
1229
1230
1234static void mirrorPadX( PAD& aPad, const VECTOR2I& aMirrorPoint )
1235{
1236 if( aPad.GetShape() == PAD_SHAPE::CUSTOM )
1237 aPad.FlipPrimitives( true ); // mirror primitives left to right
1238
1239 VECTOR2I tmpPt = mirrorPointX( aPad.GetPosition(), aMirrorPoint );
1240 aPad.SetPosition( tmpPt );
1241
1242 aPad.SetX0( aPad.GetPosition().x );
1243
1244 tmpPt = aPad.GetOffset();
1245 tmpPt.x = -tmpPt.x;
1246 aPad.SetOffset( tmpPt );
1247
1248 auto tmpz = aPad.GetDelta();
1249 tmpz.x = -tmpz.x;
1250 aPad.SetDelta( tmpz );
1251
1252 aPad.SetOrientation( -aPad.GetOrientation() );
1253}
1254
1255
1259static void mirrorPadY( PAD& aPad, const VECTOR2I& aMirrorPoint )
1260{
1261 if( aPad.GetShape() == PAD_SHAPE::CUSTOM )
1262 aPad.FlipPrimitives( false ); // mirror primitives top to bottom
1263
1264 VECTOR2I tmpPt = mirrorPointY( aPad.GetPosition(), aMirrorPoint );
1265 aPad.SetPosition( tmpPt );
1266
1267 aPad.SetY0( aPad.GetPosition().y );
1268
1269 tmpPt = aPad.GetOffset();
1270 tmpPt.y = -tmpPt.y;
1271 aPad.SetOffset( tmpPt );
1272
1273 auto tmpz = aPad.GetDelta();
1274 tmpz.y = -tmpz.y;
1275 aPad.SetDelta( tmpz );
1276
1277 aPad.SetOrientation( -aPad.GetOrientation() );
1278}
1279
1280
1281int EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
1282{
1283 if( isRouterActive() )
1284 {
1285 wxBell();
1286 return 0;
1287 }
1288
1290 []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
1291 {
1292 sTool->FilterCollectorForMarkers( aCollector );
1293 sTool->FilterCollectorForHierarchy( aCollector, true );
1294 sTool->FilterCollectorForFreePads( aCollector );
1295 },
1296 !m_dragging /* prompt user regarding locked items */ );
1297
1298 if( selection.Empty() )
1299 return 0;
1300
1302 VECTOR2I mirrorPoint = selection.GetReferencePoint();
1303
1304 // When editing footprints, all items have the same parent
1305 if( IsFootprintEditor() )
1306 m_commit->Modify( selection.Front() );
1307
1308 // Set the mirroring options.
1309 // Unfortunately, the mirror function do not have the same parameter for all items
1310 // So we need these 2 parameters to avoid mistakes
1311 bool mirrorLeftRight = true;
1312 bool mirrorAroundXaxis = false;
1313
1314 if( aEvent.IsAction( &PCB_ACTIONS::mirrorV ) )
1315 {
1316 mirrorLeftRight = false;
1317 mirrorAroundXaxis = true;
1318 }
1319
1320 for( EDA_ITEM* item : selection )
1321 {
1322 // only modify items we can mirror
1323 switch( item->Type() )
1324 {
1325 case PCB_FP_SHAPE_T:
1326 case PCB_SHAPE_T:
1327 case PCB_FP_TEXT_T:
1328 case PCB_TEXT_T:
1329 case PCB_FP_TEXTBOX_T:
1330 case PCB_TEXTBOX_T:
1331 case PCB_FP_ZONE_T:
1332 case PCB_ZONE_T:
1333 case PCB_PAD_T:
1334 case PCB_TRACE_T:
1335 case PCB_ARC_T:
1336 case PCB_VIA_T:
1337 if( !item->IsNew() && !IsFootprintEditor() )
1338 m_commit->Modify( item );
1339
1340 break;
1341
1342 default:
1343 continue;
1344 }
1345
1346 // modify each object as necessary
1347 switch( item->Type() )
1348 {
1349 case PCB_FP_SHAPE_T:
1350 case PCB_SHAPE_T:
1351 static_cast<PCB_SHAPE*>( item )->Mirror( mirrorPoint, mirrorAroundXaxis );
1352 break;
1353
1354 case PCB_FP_ZONE_T:
1355 case PCB_ZONE_T:
1356 static_cast<FP_ZONE*>( item )->Mirror( mirrorPoint, mirrorLeftRight );
1357 break;
1358
1359 case PCB_FP_TEXT_T:
1360 static_cast<FP_TEXT*>( item )->Mirror( mirrorPoint, mirrorAroundXaxis );
1361 break;
1362
1363 case PCB_TEXT_T:
1364 static_cast<PCB_TEXT*>( item )->Mirror( mirrorPoint, mirrorAroundXaxis );
1365 break;
1366
1367 case PCB_FP_TEXTBOX_T:
1368 static_cast<FP_TEXTBOX*>( item )->Mirror( mirrorPoint, mirrorAroundXaxis );
1369 break;
1370
1371 case PCB_TEXTBOX_T:
1372 static_cast<PCB_TEXTBOX*>( item )->Mirror( mirrorPoint, mirrorAroundXaxis );
1373 break;
1374
1375 case PCB_PAD_T:
1376 if( mirrorLeftRight )
1377 mirrorPadX( *static_cast<PAD*>( item ), mirrorPoint );
1378 else
1379 mirrorPadY( *static_cast<PAD*>( item ), mirrorPoint );
1380
1381 break;
1382
1383 case PCB_TRACE_T:
1384 case PCB_ARC_T:
1385 case PCB_VIA_T:
1386 static_cast<PCB_TRACK*>( item )->Mirror( mirrorPoint, mirrorAroundXaxis );
1387 break;
1388
1389 default:
1390 // it's likely the commit object is wrong if you get here
1391 // Unsure if PCB_GROUP_T needs special attention here.
1392 assert( false );
1393 break;
1394 }
1395 }
1396
1397 if( !m_dragging )
1398 m_commit->Push( _( "Mirror" ) );
1399
1400 if( selection.IsHover() && !m_dragging )
1402
1404
1405 if( m_dragging )
1407
1408 return 0;
1409}
1410
1411
1412int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent )
1413{
1414 if( isRouterActive() )
1415 {
1416 wxBell();
1417 return 0;
1418 }
1419
1421 []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
1422 {
1423 sTool->FilterCollectorForMarkers( aCollector );
1424 sTool->FilterCollectorForHierarchy( aCollector, true );
1425 sTool->FilterCollectorForFreePads( aCollector );
1426 },
1427 !m_dragging /* prompt user regarding locked items */ );
1428
1429 if( selection.Empty() )
1430 return 0;
1431
1432 std::optional<VECTOR2I> oldRefPt;
1433
1435 oldRefPt = selection.GetReferencePoint();
1436
1438
1439 // Flip around the anchor for footprints, and the bounding box center for board items
1440 VECTOR2I refPt = IsFootprintEditor() ? VECTOR2I( 0, 0 ) : selection.GetCenter();
1441
1442 // If only one item selected, flip around the selection or item anchor point (instead
1443 // of the bounding box center) to avoid moving the item anchor
1444 if( selection.GetSize() == 1 )
1445 {
1447 refPt = selection.GetReferencePoint();
1448 else
1449 refPt = static_cast<BOARD_ITEM*>( selection.GetItem( 0 ) )->GetPosition();
1450 }
1451
1452 bool leftRight = frame()->GetPcbNewSettings()->m_FlipLeftRight;
1453
1454 // When editing footprints, all items have the same parent
1455 if( IsFootprintEditor() )
1456 m_commit->Modify( selection.Front() );
1457
1458 for( EDA_ITEM* item : selection )
1459 {
1460 if( !item->IsNew() && !IsFootprintEditor() )
1461 m_commit->Modify( item );
1462
1463 if( item->Type() == PCB_GROUP_T )
1464 {
1465 static_cast<PCB_GROUP*>( item )->RunOnDescendants( [&]( BOARD_ITEM* bItem )
1466 {
1467 m_commit->Modify( bItem );
1468 });
1469 }
1470
1471 static_cast<BOARD_ITEM*>( item )->Flip( refPt, leftRight );
1472 }
1473
1474 if( !m_dragging )
1475 m_commit->Push( _( "Change Side / Flip" ) );
1476
1477 if( selection.IsHover() && !m_dragging )
1479
1481
1482 if( m_dragging )
1484
1485 // Restore the old reference so any mouse dragging that occurs doesn't make the selection jump
1486 // to this now invalid reference
1487 if( oldRefPt )
1488 selection.SetReferencePoint( *oldRefPt );
1489 else
1491
1492 return 0;
1493}
1494
1495
1496int EDIT_TOOL::Remove( const TOOL_EVENT& aEvent )
1497{
1498 PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
1499
1500 if( isRouterActive() )
1501 {
1503 return 0;
1504 }
1505
1506 editFrame->PushTool( aEvent );
1507
1508 std::vector<BOARD_ITEM*> lockedItems;
1509 Activate();
1510
1511 // get a copy instead of reference (as we're going to clear the selection before removing items)
1512 PCB_SELECTION selectionCopy;
1515
1516 // If we are in a "Cut" operation, then the copied selection exists already and we want to
1517 // delete exactly that; no more, no fewer. Any filtering for locked items must be done in
1518 // the copyToClipboard() routine.
1519 if( isCut )
1520 {
1521 selectionCopy = m_selectionTool->GetSelection();
1522 }
1523 else
1524 {
1525 // When not in free-pad mode we normally auto-promote selected pads to their parent
1526 // footprints. But this is probably a little too dangerous for a destructive operation,
1527 // so we just do the promotion but not the deletion (allowing for a second delete to do
1528 // it if that's what the user wanted).
1529 selectionCopy = m_selectionTool->RequestSelection(
1530 []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
1531 {
1532 } );
1533
1534 size_t beforeFPCount = selectionCopy.CountType( PCB_FOOTPRINT_T );
1535
1537 []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
1538 {
1539 sTool->FilterCollectorForFreePads( aCollector );
1540 } );
1541
1542 if( !selectionCopy.IsHover()
1543 && m_selectionTool->GetSelection().CountType( PCB_FOOTPRINT_T ) > beforeFPCount )
1544 {
1545 wxBell();
1546 canvas()->Refresh();
1547 editFrame->PopTool( aEvent );
1548 return 0;
1549 }
1550
1551 // In "alternative" mode, we expand selected track items to their full connection.
1552 if( isAlt && ( selectionCopy.HasType( PCB_TRACE_T ) || selectionCopy.HasType( PCB_VIA_T ) ) )
1553 {
1555 }
1556
1557 // Finally run RequestSelection() one more time to find out what user wants to do about
1558 // locked objects.
1559 selectionCopy = m_selectionTool->RequestSelection(
1560 []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
1561 {
1562 sTool->FilterCollectorForFreePads( aCollector );
1563 },
1564 true /* prompt user regarding locked items */ );
1565 }
1566
1567 // As we are about to remove items, they have to be removed from the selection first
1569
1570 for( EDA_ITEM* item : selectionCopy )
1571 {
1572 PCB_GROUP* parentGroup = static_cast<BOARD_ITEM*>( item )->GetParentGroup();
1573
1574 if( parentGroup )
1575 {
1576 m_commit->Modify( parentGroup );
1577 parentGroup->RemoveItem( static_cast<BOARD_ITEM*>( item ) );
1578 }
1579
1580 switch( item->Type() )
1581 {
1582 case PCB_FP_TEXT_T:
1583 {
1584 FP_TEXT* text = static_cast<FP_TEXT*>( item );
1585 FOOTPRINT* parent = static_cast<FOOTPRINT*>( item->GetParent() );
1586
1587 switch( text->GetType() )
1588 {
1591 m_commit->Modify( parent );
1592 text->SetVisible( false );
1593 getView()->Update( text );
1594 break;
1596 m_commit->Modify( parent );
1597 getView()->Remove( text );
1598 parent->Remove( text );
1599 break;
1600 default:
1601 wxFAIL; // Shouldn't get here
1602 break;
1603 }
1604
1605 break;
1606 }
1607
1608 case PCB_FP_TEXTBOX_T:
1609 {
1610 FP_TEXTBOX* textbox = static_cast<FP_TEXTBOX*>( item );
1611 FOOTPRINT* parent = static_cast<FOOTPRINT*>( item->GetParent() );
1612
1613 m_commit->Modify( parent );
1614 getView()->Remove( textbox );
1615 parent->Remove( textbox );
1616 break;
1617 }
1618
1619 case PCB_PAD_T:
1620 if( IsFootprintEditor() || frame()->GetPcbNewSettings()->m_AllowFreePads )
1621 {
1622 PAD* pad = static_cast<PAD*>( item );
1623 FOOTPRINT* parent = static_cast<FOOTPRINT*>( item->GetParent() );
1624
1625 m_commit->Modify( parent );
1626 getView()->Remove( pad );
1627 parent->Remove( pad );
1628 }
1629
1630 break;
1631
1632 case PCB_FP_ZONE_T:
1633 {
1634 FP_ZONE* zone = static_cast<FP_ZONE*>( item );
1635 FOOTPRINT* parent = static_cast<FOOTPRINT*>( item->GetParent() );
1636
1637 m_commit->Modify( parent );
1638 getView()->Remove( zone );
1639 parent->Remove( zone );
1640 break;
1641 }
1642
1643 case PCB_ZONE_T:
1644 // We process the zones special so that cutouts can be deleted when the delete tool
1645 // is called from inside a cutout when the zone is selected.
1646 {
1647 // Only interact with cutouts when deleting and a single item is selected
1648 if( !isCut && selectionCopy.GetSize() == 1 )
1649 {
1651 ZONE* zone = static_cast<ZONE*>( item );
1652
1653 int outlineIdx, holeIdx;
1654
1655 if( zone->HitTestCutout( curPos, &outlineIdx, &holeIdx ) )
1656 {
1657 // Remove the cutout
1658 m_commit->Modify( zone );
1659 zone->RemoveCutout( outlineIdx, holeIdx );
1660 zone->UnFill();
1661
1662 // TODO Refill zone when KiCad supports auto re-fill
1663
1664 // Update the display
1665 zone->HatchBorder();
1666 canvas()->Refresh();
1667
1668 // Restore the selection on the original zone
1670
1671 break;
1672 }
1673 }
1674
1675 // Remove the entire zone otherwise
1676 m_commit->Remove( item );
1677 break;
1678 }
1679
1680 case PCB_GROUP_T:
1681 {
1682 PCB_GROUP* group = static_cast<PCB_GROUP*>( item );
1683
1684 auto removeItem =
1685 [&]( BOARD_ITEM* bItem )
1686 {
1687 if( bItem->GetParent() && bItem->GetParent()->Type() == PCB_FOOTPRINT_T )
1688 {
1689 // Silently ignore delete of Reference or Value if they happen to be
1690 // in group.
1691 if( bItem->Type() == PCB_FP_TEXT_T )
1692 {
1693 FP_TEXT* textItem = static_cast<FP_TEXT*>( bItem );
1694
1695 if( textItem->GetType() != FP_TEXT::TEXT_is_DIVERS )
1696 return;
1697 }
1698 else if( bItem->Type() == PCB_PAD_T )
1699 {
1700 if( !IsFootprintEditor()
1702 {
1703 return;
1704 }
1705 }
1706
1707 m_commit->Modify( bItem->GetParent() );
1708 getView()->Remove( bItem );
1709 bItem->GetParent()->Remove( bItem );
1710 }
1711 else
1712 {
1713 m_commit->Remove( bItem );
1714 }
1715 };
1716
1717 removeItem( group );
1718
1719 group->RunOnDescendants( [&]( BOARD_ITEM* aDescendant )
1720 {
1721 removeItem( aDescendant );
1722 });
1723 break;
1724 }
1725
1726 default:
1727 m_commit->Remove( item );
1728 break;
1729 }
1730 }
1731
1732 // If the entered group has been emptied then leave it.
1733 PCB_GROUP* enteredGroup = m_selectionTool->GetEnteredGroup();
1734
1735 if( enteredGroup && enteredGroup->GetItems().empty() )
1737
1738 if( isCut )
1739 m_commit->Push( _( "Cut" ) );
1740 else
1741 m_commit->Push( _( "Delete" ) );
1742
1743 editFrame->PopTool( aEvent );
1744 return 0;
1745}
1746
1747
1749{
1750 if( isRouterActive() )
1751 {
1752 wxBell();
1753 return 0;
1754 }
1755
1757 []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
1758 {
1759 sTool->FilterCollectorForMarkers( aCollector );
1760 sTool->FilterCollectorForHierarchy( aCollector, true );
1761 },
1762 true /* prompt user regarding locked items */ );
1763
1764 if( selection.Empty() )
1765 return 0;
1766
1767 VECTOR2I translation;
1768 EDA_ANGLE rotation;
1771
1772 // TODO: Implement a visible bounding border at the edge
1773 BOX2I sel_box = selection.GetBoundingBox();
1774
1775 DIALOG_MOVE_EXACT dialog( frame(), translation, rotation, rotationAnchor, sel_box );
1776 int ret = dialog.ShowModal();
1777
1778 if( ret == wxID_OK )
1779 {
1780 EDA_ANGLE angle = rotation;
1782 VECTOR2I selCenter( rp.x, rp.y );
1783
1784 // Make sure the rotation is from the right reference point
1785 selCenter += translation;
1786
1787 if( !frame()->GetPcbNewSettings()->m_Display.m_DisplayInvertYAxis )
1788 rotation = -rotation;
1789
1790 // When editing footprints, all items have the same parent
1791 if( IsFootprintEditor() )
1792 m_commit->Modify( selection.Front() );
1793
1794 for( EDA_ITEM* selItem : selection )
1795 {
1796 BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selItem );
1797
1798 if( !item->IsNew() && !IsFootprintEditor() )
1799 {
1800 m_commit->Modify( item );
1801
1802 if( item->Type() == PCB_GROUP_T )
1803 {
1804 PCB_GROUP* group = static_cast<PCB_GROUP*>( item );
1805
1806 group->RunOnDescendants( [&]( BOARD_ITEM* bItem )
1807 {
1808 m_commit->Modify( bItem );
1809 });
1810 }
1811 }
1812
1813 if( !item->GetParent() || !item->GetParent()->IsSelected() )
1814 item->Move( translation );
1815
1816 switch( rotationAnchor )
1817 {
1819 item->Rotate( item->GetPosition(), angle );
1820 break;
1822 item->Rotate( selCenter, angle );
1823 break;
1825 item->Rotate( frame()->GetScreen()->m_LocalOrigin, angle );
1826 break;
1829 break;
1830 }
1831
1832 if( !m_dragging )
1833 getView()->Update( item );
1834 }
1835
1836 m_commit->Push( _( "Move exact" ) );
1837
1838 if( selection.IsHover() )
1840
1842
1843 if( m_dragging )
1845 }
1846
1847 return 0;
1848}
1849
1850
1852{
1853 if( isRouterActive() )
1854 {
1855 wxBell();
1856 return 0;
1857 }
1858
1859 bool increment = aEvent.IsAction( &PCB_ACTIONS::duplicateIncrement );
1860
1861 // Be sure that there is at least one item that we can modify
1863 []( const VECTOR2I&, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
1864 {
1865 sTool->FilterCollectorForMarkers( aCollector );
1866 sTool->FilterCollectorForHierarchy( aCollector, true );
1867 } );
1868
1869 if( selection.Empty() )
1870 return 0;
1871
1872 // we have a selection to work on now, so start the tool process
1873 PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
1874
1875 // If the selection was given a hover, we do not keep the selection after completion
1876 bool is_hover = selection.IsHover();
1877
1878 std::vector<BOARD_ITEM*> new_items;
1879 new_items.reserve( selection.Size() );
1880
1881 // Each selected item is duplicated and pushed to new_items list
1882 // Old selection is cleared, and new items are then selected.
1883 for( EDA_ITEM* item : selection )
1884 {
1885 BOARD_ITEM* dupe_item = nullptr;
1886 BOARD_ITEM* orig_item = static_cast<BOARD_ITEM*>( item );
1887
1889 {
1890 FOOTPRINT* parentFootprint = editFrame->GetBoard()->GetFirstFootprint();
1891 dupe_item = parentFootprint->DuplicateItem( orig_item );
1892
1893 if( increment && dupe_item->Type() == PCB_PAD_T
1894 && static_cast<PAD*>( dupe_item )->CanHaveNumber() )
1895 {
1896 PAD_TOOL* padTool = m_toolMgr->GetTool<PAD_TOOL>();
1897 wxString padNumber = padTool->GetLastPadNumber();
1898 padNumber = parentFootprint->GetNextPadNumber( padNumber );
1899 padTool->SetLastPadNumber( padNumber );
1900 static_cast<PAD*>( dupe_item )->SetNumber( padNumber );
1901 }
1902 }
1903 else if( orig_item->GetParent() && orig_item->GetParent()->Type() == PCB_FOOTPRINT_T )
1904 {
1905 FOOTPRINT* parentFootprint = static_cast<FOOTPRINT*>( orig_item->GetParent() );
1906
1907 m_commit->Modify( parentFootprint );
1908 dupe_item = parentFootprint->DuplicateItem( orig_item, true /* add to parent */ );
1909 }
1910 else
1911 {
1912 switch( orig_item->Type() )
1913 {
1914 case PCB_FOOTPRINT_T:
1915 case PCB_TEXT_T:
1916 case PCB_TEXTBOX_T:
1917 case PCB_BITMAP_T:
1918 case PCB_SHAPE_T:
1919 case PCB_TRACE_T:
1920 case PCB_ARC_T:
1921 case PCB_VIA_T:
1922 case PCB_ZONE_T:
1923 case PCB_TARGET_T:
1924 case PCB_DIM_ALIGNED_T:
1925 case PCB_DIM_CENTER_T:
1926 case PCB_DIM_RADIAL_T:
1928 case PCB_DIM_LEADER_T:
1929 dupe_item = orig_item->Duplicate();
1930 break;
1931
1932 case PCB_GROUP_T:
1933 dupe_item = static_cast<PCB_GROUP*>( orig_item )->DeepDuplicate();
1934 break;
1935
1936 default:
1937 wxASSERT_MSG( false, wxString::Format( wxT( "Unhandled item type %d" ),
1938 orig_item->Type() ) );
1939 break;
1940 }
1941 }
1942
1943 if( dupe_item )
1944 {
1945 if( dupe_item->Type() == PCB_GROUP_T )
1946 {
1947 static_cast<PCB_GROUP*>( dupe_item )->RunOnDescendants(
1948 [&]( BOARD_ITEM* bItem )
1949 {
1950 m_commit->Add( bItem );
1951 });
1952 }
1953
1954 // Clear the selection flag here, otherwise the PCB_SELECTION_TOOL
1955 // will not properly select it later on
1956 dupe_item->ClearSelected();
1957
1958 new_items.push_back( dupe_item );
1959 m_commit->Add( dupe_item );
1960 }
1961 }
1962
1963 // Clear the old selection first
1965
1966 // Select the new items
1967 m_toolMgr->RunAction( PCB_ACTIONS::selectItems, true, &new_items );
1968
1969 // record the new items as added
1970 if( !selection.Empty() )
1971 {
1972 editFrame->DisplayToolMsg( wxString::Format( _( "Duplicated %d item(s)" ),
1973 (int) new_items.size() ) );
1974
1975 // TODO(ISM): This line can't be used to activate the tool until we allow multiple
1976 // activations.
1977 // m_toolMgr->RunAction( PCB_ACTIONS::move, true );
1978 // Instead we have to create the event and call the tool's function
1979 // directly
1980
1981 // If items were duplicated, pick them up
1982 // this works well for "dropping" copies around and pushes the commit
1984 Move( evt );
1985
1986 // Deslect the duplicated item if we originally started as a hover selection
1987 if( is_hover )
1989 }
1990
1991 return 0;
1992}
1993
1994
1996{
1997 if( isRouterActive() )
1998 {
1999 wxBell();
2000 return 0;
2001 }
2002
2003 // Be sure that there is at least one item that we can modify
2005 []( const VECTOR2I&, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
2006 {
2007 sTool->FilterCollectorForMarkers( aCollector );
2008 sTool->FilterCollectorForHierarchy( aCollector, true );
2009 } );
2010
2011 if( selection.Empty() )
2012 return 0;
2013
2014 // we have a selection to work on now, so start the tool process
2015 PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>();
2016 ARRAY_CREATOR array_creator( *editFrame, m_isFootprintEditor, selection, m_toolMgr );
2017 array_creator.Invoke();
2018
2019 return 0;
2020}
2021
2022
2024 PCB_SELECTION_TOOL* sTool )
2025{
2026 for( int i = aCollector.GetCount() - 1; i >= 0; i-- )
2027 {
2028 BOARD_ITEM* item = static_cast<BOARD_ITEM*>( aCollector[i] );
2029
2030 if( item->Type() != PCB_PAD_T )
2031 aCollector.Remove( i );
2032 }
2033}
2034
2035
2037 PCB_SELECTION_TOOL* sTool )
2038{
2039 for( int i = aCollector.GetCount() - 1; i >= 0; i-- )
2040 {
2041 BOARD_ITEM* item = static_cast<BOARD_ITEM*>( aCollector[i] );
2042
2043 if( item->Type() != PCB_FOOTPRINT_T )
2044 aCollector.Remove( i );
2045 }
2046}
2047
2048
2050{
2051 if( m_dragging && aSelection.HasReferencePoint() )
2052 return false;
2053
2054 // Can't modify an empty group
2055 if( aSelection.Empty() )
2056 return false;
2057
2058 // When there is only one item selected, the reference point is its position...
2059 if( aSelection.Size() == 1 )
2060 {
2061 auto item = static_cast<BOARD_ITEM*>( aSelection.Front() );
2062 auto pos = item->GetPosition();
2063 aSelection.SetReferencePoint( VECTOR2I( pos.x, pos.y ) );
2064 }
2065 // ...otherwise modify items with regard to the grid-snapped center position
2066 else
2067 {
2068 PCB_GRID_HELPER grid( m_toolMgr, frame()->GetMagneticItemsSettings() );
2069 aSelection.SetReferencePoint( grid.BestSnapAnchor( aSelection.GetCenter(), nullptr ) );
2070 }
2071
2072 return true;
2073}
2074
2075
2076bool EDIT_TOOL::pickReferencePoint( const wxString& aTooltip, const wxString& aSuccessMessage,
2077 const wxString& aCanceledMessage, VECTOR2I& aReferencePoint )
2078{
2080 std::optional<VECTOR2I> pickedPoint;
2081 bool done = false;
2082
2083 m_statusPopup->SetText( aTooltip );
2084
2086 picker->SetSnapping( true );
2087
2088 picker->SetClickHandler(
2089 [&]( const VECTOR2D& aPoint ) -> bool
2090 {
2091 pickedPoint = aPoint;
2092
2093 if( !aSuccessMessage.empty() )
2094 {
2095 m_statusPopup->SetText( aSuccessMessage );
2096 m_statusPopup->Expire( 800 );
2097 }
2098 else
2099 {
2100 m_statusPopup->Hide();
2101 }
2102
2103 return false; // we don't need any more points
2104 } );
2105
2106 picker->SetMotionHandler(
2107 [&]( const VECTOR2D& aPos )
2108 {
2109 m_statusPopup->Move( wxGetMousePosition() + wxPoint( 20, -50 ) );
2110 } );
2111
2112 picker->SetCancelHandler(
2113 [&]()
2114 {
2115 if( !aCanceledMessage.empty() )
2116 {
2117 m_statusPopup->SetText( aCanceledMessage );
2118 m_statusPopup->Expire( 800 );
2119 }
2120 else
2121 {
2122 m_statusPopup->Hide();
2123 }
2124 } );
2125
2126 picker->SetFinalizeHandler(
2127 [&]( const int& aFinalState )
2128 {
2129 done = true;
2130 } );
2131
2132 m_statusPopup->Move( wxGetMousePosition() + wxPoint( 20, -50 ) );
2133 m_statusPopup->Popup();
2134 canvas()->SetStatusPopup( m_statusPopup->GetPanel() );
2135
2136 std::string tool = "";
2137 m_toolMgr->RunAction( ACTIONS::pickerTool, true, &tool );
2138
2139 while( !done )
2140 {
2141 // Pass events unless we receive a null event, then we must shut down
2142 if( TOOL_EVENT* evt = Wait() )
2143 evt->SetPassEvent();
2144 else
2145 break;
2146 }
2147
2148 // Ensure statusPopup is hidden after use and before deleting it:
2149 canvas()->SetStatusPopup( nullptr );
2150 m_statusPopup->Hide();
2151
2152 if( pickedPoint )
2153 aReferencePoint = *pickedPoint;
2154
2155 return pickedPoint.has_value();
2156}
2157
2158
2160{
2161 CLIPBOARD_IO io;
2163 getEditFrame<PCB_BASE_EDIT_FRAME>()->GetMagneticItemsSettings() );
2164 TOOL_EVENT selectReferencePoint( aEvent.Category(), aEvent.Action(),
2165 "pcbnew.InteractiveEdit.selectReferencePoint",
2167
2168 frame()->PushTool( selectReferencePoint );
2169 Activate();
2170
2172 []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
2173 {
2174 for( int i = aCollector.GetCount() - 1; i >= 0; --i )
2175 {
2176 BOARD_ITEM* item = aCollector[i];
2177
2178 // We can't copy both a footprint and its text in the same operation, so if
2179 // both are selected, remove the text
2180 if( item->Type() == PCB_FP_TEXT_T && aCollector.HasItem( item->GetParent() ) )
2181 aCollector.Remove( item );
2182 }
2183 },
2184
2185 // Prompt user regarding locked items.
2186 aEvent.IsAction( &ACTIONS::cut ) && !m_isFootprintEditor );
2187
2188 if( !selection.Empty() )
2189 {
2190 std::vector<BOARD_ITEM*> items;
2191
2192 for( EDA_ITEM* item : selection )
2193 items.push_back( static_cast<BOARD_ITEM*>( item ) );
2194
2195 VECTOR2I refPoint;
2196
2198 {
2199 if( !pickReferencePoint( _( "Select reference point for the copy..." ),
2200 _( "Selection copied" ),
2201 _( "Copy canceled" ),
2202 refPoint ) )
2203 {
2204 frame()->PopTool( selectReferencePoint );
2205 return 0;
2206 }
2207 }
2208 else
2209 {
2210 refPoint = grid.BestDragOrigin( getViewControls()->GetCursorPosition(), items );
2211 }
2212
2213 selection.SetReferencePoint( refPoint );
2214
2215 io.SetBoard( board() );
2217 frame()->SetStatusText( _( "Selection copied" ) );
2218 }
2219
2220 frame()->PopTool( selectReferencePoint );
2221
2222 return 0;
2223}
2224
2225
2227{
2228 if( !copyToClipboard( aEvent ) )
2229 {
2230 // N.B. Setting the CUT flag prevents lock filtering as we only want to delete the items
2231 // that were copied to the clipboard, no more, no fewer. Filtering for locked item, if
2232 // any will be done in the copyToClipboard() routine
2233 TOOL_EVENT evt = aEvent;
2235 Remove( evt );
2236 }
2237
2238 return 0;
2239}
2240
2241
2243{
2245 Go( &EDIT_TOOL::Move, PCB_ACTIONS::move.MakeEvent() );
2251 Go( &EDIT_TOOL::Flip, PCB_ACTIONS::flip.MakeEvent() );
2252 Go( &EDIT_TOOL::Remove, ACTIONS::doDelete.MakeEvent() );
2260 Go( &EDIT_TOOL::Mirror, PCB_ACTIONS::mirrorH.MakeEvent() );
2261 Go( &EDIT_TOOL::Mirror, PCB_ACTIONS::mirrorV.MakeEvent() );
2262 Go( &EDIT_TOOL::Swap, PCB_ACTIONS::swap.MakeEvent() );
2266
2269 Go( &EDIT_TOOL::cutToClipboard, ACTIONS::cut.MakeEvent() );
2270}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
@ special_tools
static TOOL_ACTION paste
Definition: actions.h:69
static TOOL_ACTION copy
Definition: actions.h:68
static TOOL_ACTION pickerTool
Definition: actions.h:158
static TOOL_ACTION pasteSpecial
Definition: actions.h:70
static TOOL_ACTION pageSettings
Definition: actions.h:56
@ CURSOR_CLICK
Definition: actions.h:190
static TOOL_ACTION undo
Definition: actions.h:65
static TOOL_ACTION duplicate
Definition: actions.h:72
static TOOL_ACTION doDelete
Definition: actions.h:73
REMOVE_FLAGS
Definition: actions.h:194
static TOOL_ACTION cut
Definition: actions.h:67
static TOOL_ACTION selectAll
Definition: actions.h:71
void SetTitle(const wxString &aTitle) override
Set title for the menu.
Definition: action_menu.cpp:87
void SetIcon(BITMAPS aIcon)
Assign an icon for the entry.
Definition: action_menu.cpp:73
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
VECTOR2D m_LocalOrigin
Relative Screen cursor coordinate (on grid) in user units.
Definition: base_screen.h:90
NETINFO_ITEM * GetNet() const
Return #NET_INFO object for a given item.
void SetNet(NETINFO_ITEM *aNetInfo)
Set a NET_INFO object for the item.
const VECTOR2I & GetAuxOrigin()
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:50
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:167
virtual void SetLocked(bool aLocked)
Definition: board_item.h:241
virtual void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle)
Rotate this object.
Definition: board_item.cpp:228
virtual BOARD_ITEM * Duplicate() const
Create a copy of this BOARD_ITEM.
Definition: board_item.cpp:160
virtual void Move(const VECTOR2I &aMoveVector)
Move this object.
Definition: board_item.h:253
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:201
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:172
virtual bool IsLocked() const
Definition: board_item.cpp:65
BOARD_ITEM_CONTAINER * GetParent() const
Definition: board_item.h:150
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:514
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition: board.h:397
bool IsEmpty() const
Definition: board.h:355
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:617
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:424
const Vec & GetPosition() const
Definition: box2.h:184
const Vec GetEnd() const
Definition: box2.h:185
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:588
Represent basic circle geometry with utility geometry functions.
Definition: circle.h:33
VECTOR2I Center
Public to make access simpler.
Definition: circle.h:116
int Radius
Public to make access simpler.
Definition: circle.h:115
CIRCLE & ConstructFromTanTanPt(const SEG &aLineA, const SEG &aLineB, const VECTOR2I &aP)
Construct this circle such that it is tangent to the given segments and passes through the given poin...
Definition: circle.cpp:51
VECTOR2I NearestPoint(const VECTOR2I &aP) const
Compute the point on the circumference of the circle that is the closest to aP.
Definition: circle.cpp:197
void SaveSelection(const PCB_SELECTION &selected, bool isFootprintEditor)
void SetBoard(BOARD *aBoard)
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:81
void Remove(int aIndex)
Remove the item at aIndex (first position is 0).
Definition: collector.h:109
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.
void AddMenu(ACTION_MENU *aMenu, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Add a submenu to the menu.
int ShowQuasiModal()
bool HitTestDrawingSheetItems(KIGFX::VIEW *aView, const VECTOR2I &aPosition)
void ShowInfoBarMsg(const wxString &aMsg, bool aShowCloseButton=false)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an info icon on the left of...
void ShowInfoBarError(const wxString &aErrorMsg, bool aShowCloseButton=false, WX_INFOBAR::MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an error icon on the left o...
void DisplayToolMsg(const wxString &msg) override
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
void SetStatusPopup(wxWindow *aPopup)
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
virtual VECTOR2I GetPosition() const
Definition: eda_item.h:249
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:142
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
void ClearSelected()
Definition: eda_item.h:121
bool IsSelected() const
Definition: eda_item.h:107
virtual const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: eda_item.cpp:254
bool IsNew() const
Definition: eda_item.h:103
bool isRouterActive() const
Definition: edit_tool.cpp:296
int Drag(const TOOL_EVENT &aEvent)
Invoke the PNS router to drag tracks or do an offline resizing of an arc track if a single arc track ...
Definition: edit_tool.cpp:304
int Flip(const TOOL_EVENT &aEvent)
Rotate currently selected items.
Definition: edit_tool.cpp:1412
int Duplicate(const TOOL_EVENT &aEvent)
Duplicate the current selection and starts a move action.
Definition: edit_tool.cpp:1851
int Swap(const TOOL_EVENT &aEvent)
Swap currently selected items' positions.
int PackAndMoveFootprints(const TOOL_EVENT &aEvent)
Try to fit selected footprints inside a minimal area and start movement.
int Mirror(const TOOL_EVENT &aEvent)
Mirror the current selection.
Definition: edit_tool.cpp:1281
int MoveWithReference(const TOOL_EVENT &aEvent)
Move an item but with a reference point selected first.
int CreateArray(const TOOL_EVENT &aEvent)
Create an array of the selected items, invoking the array editor dialog to set the options.
Definition: edit_tool.cpp:1995
bool pickReferencePoint(const wxString &aTooltip, const wxString &aSuccessMessage, const wxString &aCanceledMessage, VECTOR2I &aReferencePoint)
Definition: edit_tool.cpp:2076
bool Init() override
Init() is called once upon a registration of the tool.
Definition: edit_tool.cpp:102
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
Definition: edit_tool.cpp:79
bool m_dragging
Definition: edit_tool.h:209
int MoveExact(const TOOL_EVENT &aEvent)
Invoke a dialog box to allow moving of the item by an exact amount.
Definition: edit_tool.cpp:1748
int Move(const TOOL_EVENT &aEvent)
Main loop in which events are handled.
static const unsigned int COORDS_PADDING
Definition: edit_tool.h:214
std::unique_ptr< BOARD_COMMIT > m_commit
Definition: edit_tool.h:208
bool updateModificationPoint(PCB_SELECTION &aSelection)
Definition: edit_tool.cpp:2049
std::unique_ptr< STATUS_TEXT_POPUP > m_statusPopup
Definition: edit_tool.h:212
int DragArcTrack(const TOOL_EVENT &aTrack)
Drag-resize an arc (and change end points of connected straight segments).
Definition: edit_tool.cpp:388
int copyToClipboard(const TOOL_EVENT &aEvent)
Send the current selection to the clipboard by formatting it as a fake pcb see #AppendBoardFromClipbo...
Definition: edit_tool.cpp:2159
int Remove(const TOOL_EVENT &aEvent)
Delete currently selected items.
Definition: edit_tool.cpp:1496
int cutToClipboard(const TOOL_EVENT &aEvent)
Cut the current selection to the clipboard by formatting it as a fake pcb see #AppendBoardFromClipboa...
Definition: edit_tool.cpp:2226
static void PadFilter(const VECTOR2I &, GENERAL_COLLECTOR &aCollector, PCB_SELECTION_TOOL *sTool)
A selection filter which prunes the selection to contain only items of type PCB_PAD_T.
Definition: edit_tool.cpp:2023
VECTOR2I m_cursor
Definition: edit_tool.h:210
bool invokeInlineRouter(int aDragMode)
Definition: edit_tool.cpp:266
void setTransitions() override
< Set up handlers for various events.
Definition: edit_tool.cpp:2242
int ChangeTrackWidth(const TOOL_EVENT &aEvent)
Definition: edit_tool.cpp:743
int GetAndPlace(const TOOL_EVENT &aEvent)
Definition: edit_tool.cpp:243
int FilletTracks(const TOOL_EVENT &aEvent)
Fillet (i.e.
Definition: edit_tool.cpp:813
PCB_SELECTION_TOOL * m_selectionTool
Definition: edit_tool.h:207
int MoveIndividually(const TOOL_EVENT &aEvent)
Move a selection of items one-at-a-time.
int Properties(const TOOL_EVENT &aEvent)
Display properties window for the selected object.
Definition: edit_tool.cpp:1017
static void FootprintFilter(const VECTOR2I &, GENERAL_COLLECTOR &aCollector, PCB_SELECTION_TOOL *sTool)
A selection filter which prunes the selection to contain only items of type #PCB_MODULE_T.
Definition: edit_tool.cpp:2036
int Rotate(const TOOL_EVENT &aEvent)
Rotate currently selected items.
Definition: edit_tool.cpp:1077
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition: actions.h:210
void Remove(BOARD_ITEM *aItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition: footprint.cpp:609
BOARD_ITEM * DuplicateItem(const BOARD_ITEM *aItem, bool aAddToFootprint=false)
Duplicate a given item within the footprint, optionally adding it to the board.
Definition: footprint.cpp:1832
wxString GetNextPadNumber(const wxString &aLastPadName) const
Return the next available pad number in the footprint.
Definition: footprint.cpp:1944
@ TEXT_is_REFERENCE
Definition: fp_text.h:49
@ TEXT_is_DIVERS
Definition: fp_text.h:51
@ TEXT_is_VALUE
Definition: fp_text.h:50
TEXT_TYPE GetType() const
Definition: fp_text.h:120
A specialization of ZONE for use in footprints.
Definition: zone.h:897
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:204
static const std::vector< KICAD_T > DraggableItems
A scan list for items that can be dragged.
Definition: collectors.h:270
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.
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
virtual VECTOR2D GetMousePosition(bool aWorldCoordinates=true) const =0
Return the current mouse pointer position.
virtual void SetAutoPan(bool aEnabled)
Turn on/off auto panning (this feature is used when there is a tool active (eg.
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:316
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:346
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:1574
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:410
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:530
A collection of nets and the parameters used to route or test these nets.
Definition: netclass.h:47
int GetuViaDrill() const
Definition: netclass.h:92
int GetuViaDiameter() const
Definition: netclass.h:88
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:58
void SetX0(int x)
Definition: pad.h:248
void FlipPrimitives(bool aFlipLeftRight)
Flip (mirror) the primitives left to right or top to bottom, around the anchor position in custom pad...
Definition: pad.cpp:739
VECTOR2I GetPosition() const override
Definition: pad.h:196
void SetOffset(const VECTOR2I &aOffset)
Definition: pad.h:267
void SetY0(int y)
Definition: pad.h:247
const VECTOR2I & GetOffset() const
Definition: pad.h:268
void SetDelta(const VECTOR2I &aSize)
Definition: pad.h:257
void SetPosition(const VECTOR2I &aPos) override
Definition: pad.h:190
const VECTOR2I & GetDelta() const
Definition: pad.h:258
PAD_SHAPE GetShape() const
Definition: pad.h:188
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition: pad.h:364
void SetOrientation(const EDA_ANGLE &aAngle)
Set the rotation angle of the pad.
Definition: pad.cpp:672
static TOOL_ACTION drag45Degree
Definition: pcb_actions.h:162
static TOOL_ACTION duplicateIncrement
Activation of the duplication tool with incrementing (e.g. pad number)
Definition: pcb_actions.h:151
static TOOL_ACTION routerUndoLastSegment
Definition: pcb_actions.h:218
static TOOL_ACTION changeTrackWidth
Update selected tracks & vias to the current track & via dimensions.
Definition: pcb_actions.h:139
static TOOL_ACTION unrouteSelected
Removes all tracks from the selected items to the first pad.
Definition: pcb_actions.h:83
static TOOL_ACTION mirrorH
Mirroring of selected items.
Definition: pcb_actions.h:129
static TOOL_ACTION updateFootprint
Definition: pcb_actions.h:356
static TOOL_ACTION breakTrack
Break a single track into two segments at the cursor.
Definition: pcb_actions.h:160
static TOOL_ACTION getAndPlace
Find an item and start moving.
Definition: pcb_actions.h:506
static TOOL_ACTION properties
Activation of the edit tool.
Definition: pcb_actions.h:145
static TOOL_ACTION editFpInFpEditor
Definition: pcb_actions.h:378
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:59
static TOOL_ACTION moveWithReference
move with a reference point
Definition: pcb_actions.h:116
static TOOL_ACTION swap
Swapping of selected items.
Definition: pcb_actions.h:133
static TOOL_ACTION moveExact
Activation of the exact move tool.
Definition: pcb_actions.h:148
static TOOL_ACTION selectConnection
Select tracks between junctions or expands an existing selection to pads or the entire connection.
Definition: pcb_actions.h:80
static TOOL_ACTION assignNetClass
Definition: pcb_actions.h:332
static TOOL_ACTION packAndMoveFootprints
Pack and start moving selected footprints.
Definition: pcb_actions.h:136
static TOOL_ACTION copyWithReference
copy command with manual reference point selection
Definition: pcb_actions.h:119
static TOOL_ACTION dragFreeAngle
Definition: pcb_actions.h:163
static TOOL_ACTION inspectClearance
Definition: pcb_actions.h:484
static TOOL_ACTION updateLocalRatsnest
Definition: pcb_actions.h:500
static TOOL_ACTION deleteFull
Definition: pcb_actions.h:155
static TOOL_ACTION moveIndividually
move items one-by-one
Definition: pcb_actions.h:113
static TOOL_ACTION selectItem
Select an item (specified as the event parameter).
Definition: pcb_actions.h:62
static TOOL_ACTION filletTracks
Fillet (i.e. adds an arc tangent to) all selected straight tracks by a user defined radius.
Definition: pcb_actions.h:142
static TOOL_ACTION footprintProperties
Definition: pcb_actions.h:412
static TOOL_ACTION changeFootprint
Definition: pcb_actions.h:358
static TOOL_ACTION routerInlineDrag
Activation of the Push and Shove router (inline dragging mode)
Definition: pcb_actions.h:238
static TOOL_ACTION positionRelative
Activation of the position relative tool.
Definition: pcb_actions.h:261
static TOOL_ACTION move
move or drag an item
Definition: pcb_actions.h:110
static TOOL_ACTION mirrorV
Definition: pcb_actions.h:130
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
Definition: pcb_actions.h:66
static TOOL_ACTION flip
Flipping of selected objects.
Definition: pcb_actions.h:126
static TOOL_ACTION createArray
Tool for creating an array of objects.
Definition: pcb_actions.h:427
static TOOL_ACTION rotateCw
Rotation of selected objects.
Definition: pcb_actions.h:122
static TOOL_ACTION rotateCcw
Definition: pcb_actions.h:123
void SetMid(const VECTOR2I &aMid)
Definition: pcb_track.h:273
EDA_ANGLE GetAngle() const
Definition: pcb_track.cpp:1100
const VECTOR2I & GetMid() const
Definition: pcb_track.h:274
virtual VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition: pcb_track.h:283
Common, abstract interface for edit frames.
virtual void OnEditItemRequest(BOARD_ITEM *aItem)=0
Install the corresponding dialog editor for the given item.
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
PCBNEW_SETTINGS * GetPcbNewSettings() const
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
BOARD * GetBoard() const
DS_PROXY_VIEW_ITEM * GetDrawingSheet() const
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:51
std::unordered_set< BOARD_ITEM * > & GetItems()
Definition: pcb_group.h:68
bool RemoveItem(BOARD_ITEM *aItem)
Remove item from group.
Definition: pcb_group.cpp:51
Generic tool for picking an item.
The selection tool: currently supports:
void GuessSelectionCandidates(GENERAL_COLLECTOR &aCollector, const VECTOR2I &aWhere) const
Try to guess best selection candidates in case multiple items are clicked, by doing some brain-dead h...
void FilterCollectorForMarkers(GENERAL_COLLECTOR &aCollector) const
Drop any PCB_MARKERs from the collector.
PCB_SELECTION & RequestSelection(CLIENT_SELECTION_FILTER aClientFilter, bool aConfirmLockedItems=false)
Return the current selection, filtered according to aClientFilter.
void FilterCollectorForFreePads(GENERAL_COLLECTOR &aCollector) const
Check the "allow free pads" setting and if disabled, replace any pads in the collector with their par...
PCB_GROUP * GetEnteredGroup()
void FilterCollectorForHierarchy(GENERAL_COLLECTOR &aCollector, bool aMultiselect) const
In general we don't want to select both a parent and any of it's children.
PCB_SELECTION & GetSelection()
void ExitGroup(bool aSelectGroup=false)
Leave the currently-entered group.
bool IsFootprintEditor() const
PCB_BASE_EDIT_FRAME * frame() const
KIGFX::VIEW_CONTROLS * controls() const
BOARD * board() const
PCB_DRAW_PANEL_GAL * canvas() const
bool m_isFootprintEditor
const PCB_SELECTION & selection() const
virtual void SwapData(BOARD_ITEM *aImage) override
Swap data between aItem and aImage.
Definition: pcb_track.cpp:1066
void SetWidth(int aWidth)
Definition: pcb_track.h:104
virtual double GetLength() const
Function GetLength returns the length of the track using the hypotenuse calculation.
Definition: pcb_track.cpp:278
int GetWidth() const
Definition: pcb_track.h:105
void SetEnd(const VECTOR2I &aEnd)
Definition: pcb_track.h:107
void SetStart(const VECTOR2I &aStart)
Definition: pcb_track.h:110
const VECTOR2I & GetStart() const
Definition: pcb_track.h:111
const VECTOR2I & GetEnd() const
Definition: pcb_track.h:108
EDA_ITEM_FLAGS IsPointOnEnds(const VECTOR2I &point, int min_dist=0) const
Function IsPointOnEnds returns STARTPOINT if point if near (dist = min_dist) start point,...
Definition: pcb_track.cpp:200
void SetMotionHandler(MOTION_HANDLER aHandler)
Set a handler for mouse motion.
Definition: picker_tool.h:82
void SetClickHandler(CLICK_HANDLER aHandler)
Set a handler for mouse click event.
Definition: picker_tool.h:71
void SetSnapping(bool aSnap)
Definition: picker_tool.h:64
void SetCancelHandler(CANCEL_HANDLER aHandler)
Set a handler for cancel events (ESC or context-menu Cancel).
Definition: picker_tool.h:91
void SetFinalizeHandler(FINALIZE_HANDLER aHandler)
Set a handler for the finalize event.
Definition: picker_tool.h:102
POSITIONING_TOOLS_MENU(TOOL_INTERACTIVE *aTool)
Definition: edit_tool.cpp:90
bool RoutingInProgress()
Returns whether routing is currently active.
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
const VECTOR2I NearestPoint(const VECTOR2I &aP) const
Compute a point on the segment (this) that is closest to point aP.
Definition: seg.cpp:261
OPT_VECTOR2I IntersectLines(const SEG &aSeg) const
Compute the intersection point of lines passing through ends of (this) and aSeg.
Definition: seg.h:210
bool ApproxCollinear(const SEG &aSeg) const
Definition: seg.h:280
VECTOR2I LineProject(const VECTOR2I &aP) const
Compute the perpendicular projection point of aP on a line passing through ends of the segment.
Definition: seg.cpp:302
SEG PerpendicularSeg(const VECTOR2I &aP) const
Compute a segment perpendicular to this one, passing through point aP.
Definition: seg.cpp:199
int Side(const VECTOR2I &aP) const
Determine on which side of directed line passing via segment ends point aP lies.
Definition: seg.h:143
EDA_ANGLE Angle(const SEG &aOther) const
Determine the smallest angle between two segments.
Definition: seg.cpp:97
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 bool NotEmpty(const SELECTION &aSelection)
Test if there are any items selected.
static SELECTION_CONDITION MoreThan(int aNumber)
Create a functor that tests if the number of selected items is greater than the value given as parame...
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 RemoveItemFromSel(const TOOL_EVENT &aEvent)
int AddItemToSel(const TOOL_EVENT &aEvent)
virtual KIGFX::VIEW_ITEM * GetItem(unsigned int aIdx) const override
Definition: selection.cpp:65
VECTOR2I GetReferencePoint() const
Definition: selection.h:244
virtual VECTOR2I GetCenter() const
Returns the center point of the selection area bounding box.
Definition: selection.cpp:83
bool IsHover() const
Definition: selection.h:81
virtual unsigned int GetSize() const override
Return the number of stored items.
Definition: selection.h:97
EDA_ITEM * Front() const
Definition: selection.h:200
bool HasType(KICAD_T aType) const
Checks if there is at least one item of requested kind.
Definition: selection.cpp:134
int Size() const
Returns the number of selected parts.
Definition: selection.h:113
void ClearReferencePoint()
Definition: selection.h:257
void SetReferencePoint(const VECTOR2I &aP)
Definition: selection.h:252
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:107
bool HasReferencePoint() const
Definition: selection.h:239
size_t CountType(KICAD_T aType) const
Definition: selection.cpp:146
bool Contains(EDA_ITEM *aItem) const
Definition: selection.cpp:74
virtual BOX2I GetBoundingBox() const
Definition: selection.cpp:123
const VECTOR2I & GetP1() const
Definition: shape_arc.h:113
const VECTOR2I & GetP0() const
Definition: shape_arc.h:112
static const int MIN_PRECISION_IU
This is the minimum precision for all the points in a shape.
Definition: shape.h:128
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.
bool ToolStackIsEmpty()
Definition: tools_holder.h:128
bool IsCurrentTool(const TOOL_ACTION &aAction) const
TOOL_EVENT MakeEvent() const
Return the event associated with the action (i.e.
Definition: tool_action.cpp:72
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:214
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
bool IsToolActive() const
Definition: tool_base.cpp:31
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
@ RUN
Tool is invoked after being inactive.
Definition: tool_base.h:79
Generic, UI-independent tool event.
Definition: tool_event.h:156
T Parameter() const
Return a non-standard parameter assigned to the event.
Definition: tool_event.h:442
TOOL_ACTIONS Action() const
These give a tool a method of informing the TOOL_MANAGER that a particular event should be passed on ...
Definition: tool_event.h:233
void SetParameter(T aParam)
Set a non-standard parameter assigned to the event.
Definition: tool_event.h:460
TOOL_EVENT_CATEGORY Category() const
Returns more specific information about the type of an event.
Definition: tool_event.h:230
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
Definition: tool_event.cpp:88
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_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, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:142
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:44
void RegisterSubMenu(std::shared_ptr< ACTION_MENU > aSubMenu)
Store a submenu of this menu model.
Definition: tool_menu.cpp:50
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:293
An extension of WX_TEXT_ENTRY_DIALOG that uses UNIT_BINDER to request a dimension (e....
long long GetValue()
Returns the value in internal units.
Handle a list of polygons defining a copper zone.
Definition: zone.h:57
bool UnFill()
Removes the zone filling.
Definition: zone.cpp:206
bool HitTestCutout(const VECTOR2I &aRefPos, int *aOutlineIdx=nullptr, int *aHoleIdx=nullptr) const
Test if the given point is contained within a cutout of the zone.
Definition: zone.cpp:451
void HatchBorder()
Compute the hatch lines depending on the hatch parameters and stores it in the zone's attribute m_bor...
Definition: zone.cpp:791
void RemoveCutout(int aOutlineIdx, int aHoleIdx)
Remove a cutout from the zone.
Definition: zone.cpp:650
ROTATION_ANCHOR
@ ROTATE_AROUND_USER_ORIGIN
@ ROTATE_AROUND_SEL_CENTER
@ ROTATE_AROUND_AUX_ORIGIN
@ ROTATE_AROUND_ITEM_ANCHOR
#define _(s)
static constexpr EDA_ANGLE & ANGLE_180
Definition: eda_angle.h:416
@ DEGREES_T
Definition: eda_angle.h:31
#define IS_NEW
New item, just created.
static VECTOR2I mirrorPointY(const VECTOR2I &aPoint, const VECTOR2I &aMirrorPoint)
Mirror a point about the vertical axis passing through another point.
Definition: edit_tool.cpp:1219
static void mirrorPadX(PAD &aPad, const VECTOR2I &aMirrorPoint)
Mirror a pad in the vertical axis passing through a point (mirror left to right).
Definition: edit_tool.cpp:1234
static VECTOR2I mirrorPointX(const VECTOR2I &aPoint, const VECTOR2I &aMirrorPoint)
Mirror a point about the vertical axis passing through another point.
Definition: edit_tool.cpp:1204
static void mirrorPadY(PAD &aPad, const VECTOR2I &aMirrorPoint)
Mirror a pad in the vertical axis passing through a point (mirror left to right).
Definition: edit_tool.cpp:1259
static std::vector< KICAD_T > connectedTypes
@ FRAME_PCB_EDITOR
Definition: frame_type.h:40
@ LAYER_DRAWINGSHEET
drawingsheet frame and titleblock
Definition: layer_ids.h:217
@ LAYER_SCHEMATIC_DRAWINGSHEET
Definition: layer_ids.h:382
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:323
static ROUTER * theRouter
Definition: pns_router.cpp:58
@ DM_ANY
Definition: pns_router.h:77
@ DM_FREE_ANGLE
Definition: pns_router.h:75
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
EDA_ANGLE GetEventRotationAngle(const PCB_BASE_EDIT_FRAME &aFrame, const TOOL_EVENT &aEvent)
Function getEventRotationAngle()
BOARD * GetBoard()
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
std::optional< VECTOR2I > OPT_VECTOR2I
Definition: seg.h:39
const double IU_PER_MM
Definition: base_units.h:77
constexpr int mmToIU(double mm) const
Definition: base_units.h:89
@ AS_GLOBAL
Global action (toolbar/main menu event, global shortcut)
Definition: tool_action.h:45
@ BUT_LEFT
Definition: tool_event.h:127
const VECTOR2I CalcArcMid(const VECTOR2I &aStart, const VECTOR2I &aEnd, const VECTOR2I &aCenter, bool aMinArcAngle=true)
Return the middle point of an arc, half-way between aStart and aEnd.
Definition: trigo.cpp:163
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183
double GetLineLength(const VECTOR2I &aPointA, const VECTOR2I &aPointB)
Return the length of a line segment defined by aPointA and aPointB.
Definition: trigo.h:188
double EuclideanNorm(const VECTOR2I &vector)
Definition: trigo.h:129
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:88
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition: typeinfo.h:110
@ PCB_FP_SHAPE_T
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:94
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition: typeinfo.h:107
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:102
@ PCB_FP_TEXTBOX_T
class FP_TEXTBOX, wrapped text in a footprint
Definition: typeinfo.h:93
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition: typeinfo.h:108
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:115
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:91
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition: typeinfo.h:112
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:90
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:111
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition: typeinfo.h:86
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition: typeinfo.h:106
@ PCB_FP_ZONE_T
class ZONE, managed by a footprint
Definition: typeinfo.h:100
@ PCB_BITMAP_T
class PCB_BITMAP, bitmap on a layer
Definition: typeinfo.h:89
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
@ PCB_FP_TEXT_T
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:103
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:101
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition: typeinfo.h:109
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:80
VECTOR2< int > VECTOR2I
Definition: vector2d.h:618