KiCad PCB EDA Suite
Loading...
Searching...
No Matches
placement_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) 2014-2016 CERN
5 * Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Maciej Suminski <[email protected]>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25#include "tool/selection.h"
26#include "placement_tool.h"
27#include "pcb_actions.h"
28#include "pcb_selection_tool.h"
29
31#include <tool/tool_manager.h>
32
33#include <board.h>
34#include <board_commit.h>
35#include <bitmaps.h>
36#include <pcb_edit_frame.h>
37#include <geometry/distribute.h>
38#include <view/view_controls.h>
39
40
42 TOOL_INTERACTIVE( "pcbnew.Placement" ),
43 m_selectionTool( nullptr ),
44 m_placementMenu( nullptr ),
45 m_frame( nullptr )
46{
47}
48
50{
51 delete m_placementMenu;
52}
53
54
56{
57 // Find the selection tool, so they can cooperate
59 m_frame = getEditFrame<PCB_BASE_FRAME>();
60
61 // Create a context menu and make it available through selection tool
63 m_placementMenu->SetIcon( BITMAPS::align_items );
64 m_placementMenu->SetTitle( _( "Align/Distribute" ) );
65
66 const auto canAlign = SELECTION_CONDITIONS::MoreThan( 1 );
67 const auto canDistribute = SELECTION_CONDITIONS::MoreThan( 2 );
68
69 // Add all align/distribute commands
73
74 m_placementMenu->AddSeparator( canAlign );
78
79 m_placementMenu->AddSeparator( canDistribute );
84
87
88 return true;
89}
90
91
92template <class T>
93std::vector<std::pair<BOARD_ITEM*, BOX2I>> GetBoundingBoxes( const T& aItems )
94{
95 std::vector<std::pair<BOARD_ITEM*, BOX2I>> rects;
96
97 for( EDA_ITEM* item : aItems )
98 {
99 if( !item->IsBOARD_ITEM() )
100 continue;
101
102 BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
103
104 if( boardItem->Type() == PCB_FOOTPRINT_T )
105 {
106 FOOTPRINT* footprint = static_cast<FOOTPRINT*>( boardItem );
107 rects.emplace_back( std::make_pair( footprint, footprint->GetBoundingBox( false ) ) );
108 }
109 else
110 {
111 rects.emplace_back( std::make_pair( boardItem, boardItem->GetBoundingBox() ) );
112 }
113 }
114
115 return rects;
116}
117
118
119template< typename T >
120int ALIGN_DISTRIBUTE_TOOL::selectTarget( std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aItems,
121 std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aLocked,
122 T aGetValue )
123{
125
126 // Prefer locked items to unlocked items.
127 // Secondly, prefer items under the cursor to other items.
128
129 if( aLocked.size() >= 1 )
130 {
131 for( const std::pair<BOARD_ITEM*, BOX2I>& item : aLocked )
132 {
133 if( item.second.Contains( curPos ) )
134 return aGetValue( item );
135 }
136
137 return aGetValue( aLocked.front() );
138 }
139
140 for( const std::pair<BOARD_ITEM*, BOX2I>& item : aItems )
141 {
142 if( item.second.Contains( curPos ) )
143 return aGetValue( item );
144 }
145
146 return aGetValue( aItems.front() );
147}
148
149
150template< typename T >
151size_t ALIGN_DISTRIBUTE_TOOL::GetSelections( std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aItemsToAlign,
152 std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aLockedItems,
153 T aCompare )
154{
156 []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
157 {
158 // Iterate from the back so we don't have to worry about removals.
159 for( int i = aCollector.GetCount() - 1; i >= 0; --i )
160 {
161 BOARD_ITEM* item = aCollector[i];
162
163 if( item->Type() == PCB_MARKER_T )
164 aCollector.Remove( item );
165 }
166 } );
167
168 std::vector<BOARD_ITEM*> lockedItems;
169 std::vector<BOARD_ITEM*> itemsToAlign;
170
171 for( EDA_ITEM* item : selection )
172 {
173 if( !item->IsBOARD_ITEM() )
174 continue;
175
176 BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
177
178 // We do not lock items in the footprint editor
179 if( boardItem->IsLocked() && m_frame->IsType( FRAME_PCB_EDITOR ) )
180 {
181 // Locking a pad but not the footprint means that we align the footprint using
182 // the pad position. So we test for footprint locking here
183 if( boardItem->Type() == PCB_PAD_T && !boardItem->GetParent()->IsLocked() )
184 itemsToAlign.push_back( boardItem );
185 else
186 lockedItems.push_back( boardItem );
187 }
188 else
189 {
190 itemsToAlign.push_back( boardItem );
191 }
192 }
193
194 aItemsToAlign = GetBoundingBoxes( itemsToAlign );
195 aLockedItems = GetBoundingBoxes( lockedItems );
196 std::sort( aItemsToAlign.begin(), aItemsToAlign.end(), aCompare );
197 std::sort( aLockedItems.begin(), aLockedItems.end(), aCompare );
198
199 return aItemsToAlign.size();
200}
201
202
204{
205 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
206 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
207
208 if( !GetSelections( itemsToAlign, locked_items,
209 []( const std::pair<BOARD_ITEM*, BOX2I>& lhs, const std::pair<BOARD_ITEM*, BOX2I>& rhs )
210 {
211 return ( lhs.second.GetTop() < rhs.second.GetTop() );
212 } ) )
213 {
214 return 0;
215 }
216
217 BOARD_COMMIT commit( m_frame );
218
219 int targetTop = selectTarget( itemsToAlign, locked_items,
220 []( const std::pair<BOARD_ITEM*, BOX2I>& aVal )
221 {
222 return aVal.second.GetTop();
223 } );
224
225 // Move the selected items
226 for( const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
227 {
228 BOARD_ITEM* item = i.first;
229 int difference = targetTop - i.second.GetTop();
230
231 if( item->GetParent() && item->GetParent()->IsSelected() )
232 continue;
233
234 // Don't move a pad by itself unless editing the footprint
235 if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
236 item = item->GetParent();
237
238 commit.Stage( item, CHT_MODIFY );
239 item->Move( VECTOR2I( 0, difference ) );
240 }
241
242 commit.Push( _( "Align to Top" ) );
243 return 0;
244}
245
246
248{
249 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
250 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
251
252 if( !GetSelections( itemsToAlign, locked_items,
253 []( const std::pair<BOARD_ITEM*, BOX2I>& lhs, const std::pair<BOARD_ITEM*, BOX2I>& rhs)
254 {
255 return ( lhs.second.GetBottom() > rhs.second.GetBottom() );
256 } ) )
257 {
258 return 0;
259 }
260
261 BOARD_COMMIT commit( m_frame );
262
263 int targetBottom = selectTarget( itemsToAlign, locked_items,
264 []( const std::pair<BOARD_ITEM*, BOX2I>& aVal )
265 {
266 return aVal.second.GetBottom();
267 } );
268
269 // Move the selected items
270 for( const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
271 {
272 int difference = targetBottom - i.second.GetBottom();
273 BOARD_ITEM* item = i.first;
274
275 if( item->GetParent() && item->GetParent()->IsSelected() )
276 continue;
277
278 // Don't move a pad by itself unless editing the footprint
279 if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
280 item = item->GetParent();
281
282 commit.Stage( item, CHT_MODIFY );
283 item->Move( VECTOR2I( 0, difference ) );
284 }
285
286 commit.Push( _( "Align to Bottom" ) );
287 return 0;
288}
289
290
292{
293 // Because this tool uses bounding boxes and they aren't mirrored even when
294 // the view is mirrored, we need to call the other one if mirrored.
295 if( getView()->IsMirroredX() )
296 return doAlignRight();
297 else
298 return doAlignLeft();
299}
300
301
303{
304 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
305 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
306
307 if( !GetSelections( itemsToAlign, locked_items,
308 []( const std::pair<BOARD_ITEM*, BOX2I>& lhs, const std::pair<BOARD_ITEM*, BOX2I>& rhs )
309 {
310 return ( lhs.second.GetLeft() < rhs.second.GetLeft() );
311 } ) )
312 {
313 return 0;
314 }
315
316 BOARD_COMMIT commit( m_frame );
317
318 int targetLeft = selectTarget( itemsToAlign, locked_items,
319 []( const std::pair<BOARD_ITEM*, BOX2I>& aVal )
320 {
321 return aVal.second.GetLeft();
322 } );
323
324 // Move the selected items
325 for( const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
326 {
327 int difference = targetLeft - i.second.GetLeft();
328 BOARD_ITEM* item = i.first;
329
330 if( item->GetParent() && item->GetParent()->IsSelected() )
331 continue;
332
333 // Don't move a pad by itself unless editing the footprint
334 if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
335 item = item->GetParent();
336
337 commit.Stage( item, CHT_MODIFY );
338 item->Move( VECTOR2I( difference, 0 ) );
339 }
340
341 commit.Push( _( "Align to Left" ) );
342 return 0;
343}
344
345
347{
348 // Because this tool uses bounding boxes and they aren't mirrored even when
349 // the view is mirrored, we need to call the other one if mirrored.
350 if( getView()->IsMirroredX() )
351 return doAlignLeft();
352 else
353 return doAlignRight();
354}
355
356
358{
359 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
360 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
361
362 if( !GetSelections( itemsToAlign, locked_items,
363 []( const std::pair<BOARD_ITEM*, BOX2I>& lhs, const std::pair<BOARD_ITEM*, BOX2I>& rhs )
364 {
365 return ( lhs.second.GetRight() > rhs.second.GetRight() );
366 } ) )
367 {
368 return 0;
369 }
370
371 BOARD_COMMIT commit( m_frame );
372
373 int targetRight = selectTarget( itemsToAlign, locked_items,
374 []( const std::pair<BOARD_ITEM*, BOX2I>& aVal )
375 {
376 return aVal.second.GetRight();
377 } );
378
379 // Move the selected items
380 for( const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
381 {
382 int difference = targetRight - i.second.GetRight();
383 BOARD_ITEM* item = i.first;
384
385 if( item->GetParent() && item->GetParent()->IsSelected() )
386 continue;
387
388 // Don't move a pad by itself unless editing the footprint
389 if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
390 item = item->GetParent();
391
392 commit.Stage( item, CHT_MODIFY );
393 item->Move( VECTOR2I( difference, 0 ) );
394 }
395
396 commit.Push( _( "Align to Right" ) );
397 return 0;
398}
399
400
402{
403 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
404 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
405
406 if( !GetSelections( itemsToAlign, locked_items,
407 []( const std::pair<BOARD_ITEM*, BOX2I>& lhs, const std::pair<BOARD_ITEM*, BOX2I>& rhs )
408 {
409 return ( lhs.second.Centre().x < rhs.second.Centre().x );
410 } ) )
411 {
412 return 0;
413 }
414
415 BOARD_COMMIT commit( m_frame );
416
417 int targetX = selectTarget( itemsToAlign, locked_items,
418 []( const std::pair<BOARD_ITEM*, BOX2I>& aVal )
419 {
420 return aVal.second.Centre().x;
421 } );
422
423 // Move the selected items
424 for( const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
425 {
426 int difference = targetX - i.second.Centre().x;
427 BOARD_ITEM* item = i.first;
428
429 if( item->GetParent() && item->GetParent()->IsSelected() )
430 continue;
431
432 // Don't move a pad by itself unless editing the footprint
433 if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
434 item = item->GetParent();
435
436 commit.Stage( item, CHT_MODIFY );
437 item->Move( VECTOR2I( difference, 0 ) );
438 }
439
440 commit.Push( _( "Align to Middle" ) );
441 return 0;
442}
443
444
446{
447 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
448 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
449
450 if( !GetSelections( itemsToAlign, locked_items,
451 []( const std::pair<BOARD_ITEM*, BOX2I>& lhs, const std::pair<BOARD_ITEM*, BOX2I>& rhs )
452 {
453 return ( lhs.second.Centre().y < rhs.second.Centre().y );
454 } ) )
455 {
456 return 0;
457 }
458
459 BOARD_COMMIT commit( m_frame );
460
461 int targetY = selectTarget( itemsToAlign, locked_items,
462 []( const std::pair<BOARD_ITEM*, BOX2I>& aVal )
463 {
464 return aVal.second.Centre().y;
465 } );
466
467 // Move the selected items
468 for( const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
469 {
470 int difference = targetY - i.second.Centre().y;
471 BOARD_ITEM* item = i.first;
472
473 if( item->GetParent() && item->GetParent()->IsSelected() )
474 continue;
475
476 // Don't move a pad by itself unless editing the footprint
477 if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
478 item = item->GetParent();
479
480 commit.Stage( item, CHT_MODIFY );
481 item->Move( VECTOR2I( 0, difference ) );
482 }
483
484 commit.Push( _( "Align to Center" ) );
485 return 0;
486}
487
488
490{
492 []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector,
493 PCB_SELECTION_TOOL* sTool )
494 {
495 sTool->FilterCollectorForMarkers( aCollector );
496 sTool->FilterCollectorForHierarchy( aCollector, true );
497 sTool->FilterCollectorForFreePads( aCollector );
498 },
499 m_frame->IsType( FRAME_PCB_EDITOR ) /* prompt user regarding locked items */
500 );
501
502 // Need at least 3 items to distribute - one at each end and at least on in the middle
503 if( selection.Size() < 3 )
504 return 0;
505
506 BOARD_COMMIT commit( m_frame );
507 wxString commitMsg;
508 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToDistribute = GetBoundingBoxes( selection );
509
511 {
512 doDistributeCenters( true, itemsToDistribute, commit );
514 }
516 {
517 doDistributeGaps( true, itemsToDistribute, commit );
519 }
521 {
522 doDistributeCenters( false, itemsToDistribute, commit );
524 }
525 else
526 {
527 doDistributeGaps( false, itemsToDistribute, commit );
529 }
530
531 commit.Push( commitMsg );
532 return 0;
533}
534
535
537 std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aItems,
538 BOARD_COMMIT& aCommit ) const
539{
540 // Sort by start position.
541 // This is a simple way to get the items in a sensible order but it's not perfect.
542 // It will fail if, say, there's a huge items that's bigger than the total span of
543 // all the other items, but at that point a gap-equalising algorithm probably isn't
544 // well-defined anyway.
545 std::sort( aItems.begin(), aItems.end(),
546 [&]( const std::pair<BOARD_ITEM*, BOX2I>& a, const std::pair<BOARD_ITEM*, BOX2I>& b )
547 {
548 return aIsXAxis ? a.second.GetLeft() < b.second.GetLeft()
549 : a.second.GetTop() < b.second.GetTop();
550 } );
551
552 // Consruct list of item spans in the relevant axis
553 std::vector<std::pair<int, int>> itemSpans;
554 itemSpans.reserve( aItems.size() );
555
556 for( const auto& [item, box] : aItems )
557 {
558 const int start = aIsXAxis ? box.GetLeft() : box.GetTop();
559 const int end = aIsXAxis ? box.GetRight() : box.GetBottom();
560 itemSpans.emplace_back( start, end );
561 }
562
563 // Get the deltas needed to distribute the items evenly
564 const std::vector<int> deltas = GetDeltasForDistributeByGaps( itemSpans );
565
566 // Apply the deltas to the items
567 for( size_t i = 1; i < aItems.size() - 1; ++i )
568 {
569 const auto& [item, box] = aItems[i];
570 const int delta = deltas[i];
571
572 if( delta != 0 )
573 {
574 const VECTOR2I deltaVec = aIsXAxis ? VECTOR2I( delta, 0 ) : VECTOR2I( 0, delta );
575
576 aCommit.Stage( item, CHT_MODIFY );
577 item->Move( deltaVec );
578 }
579 }
580}
581
582
584 std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aItems,
585 BOARD_COMMIT& aCommit ) const
586{
587 std::sort(
588 aItems.begin(), aItems.end(),
589 [&]( const std::pair<BOARD_ITEM*, BOX2I>& lhs, const std::pair<BOARD_ITEM*, BOX2I>& rhs )
590 {
591 const int lhsPos = aIsXAxis ? lhs.second.Centre().x : lhs.second.Centre().y;
592 const int rhsPos = aIsXAxis ? rhs.second.Centre().x : rhs.second.Centre().y;
593 return lhsPos < rhsPos;
594 } );
595
596 std::vector<int> itemCenters;
597 itemCenters.reserve( aItems.size() );
598
599 for( const auto& [item, box] : aItems )
600 {
601 itemCenters.push_back( aIsXAxis ? box.Centre().x : box.Centre().y );
602 }
603
604 const std::vector<int> deltas = GetDeltasForDistributeByPoints( itemCenters );
605
606 // Apply the deltas to the items
607 for( size_t i = 1; i < aItems.size() - 1; ++i )
608 {
609 const auto& [item, box] = aItems[i];
610 const int delta = deltas[i];
611
612 if ( delta != 0)
613 {
614 const VECTOR2I deltaVec = aIsXAxis ? VECTOR2I( delta, 0 ) : VECTOR2I( 0, delta );
615
616 aCommit.Stage( item, CHT_MODIFY );
617 item->Move( deltaVec );
618 }
619 }
620}
621
622
624{
631
640}
void SetTitle(const wxString &aTitle) override
Set title for the menu.
Definition: action_menu.cpp:92
void SetIcon(BITMAPS aIcon)
Assign an icon for the entry.
Definition: action_menu.cpp:78
int AlignBottom(const TOOL_EVENT &aEvent)
Sets Y coordinate of the selected items to the value of the bottom-most selected item Y coordinate.
int DistributeItems(const TOOL_EVENT &aEvent)
Distribute the selected items in some way.
PCB_SELECTION_TOOL * m_selectionTool
size_t GetSelections(std::vector< std::pair< BOARD_ITEM *, BOX2I > > &aItemsToAlign, std::vector< std::pair< BOARD_ITEM *, BOX2I > > &aLockedItems, T aCompare)
Populate two vectors with the sorted selection and sorted locked items.
int AlignCenterX(const TOOL_EVENT &aEvent)
Set the x coordinate of the midpoint of each of the selected items to the value of the x coordinate o...
PCB_BASE_FRAME * m_frame
int AlignTop(const TOOL_EVENT &aEvent)
Set Y coordinate of the selected items to the value of the top-most selected item Y coordinate.
int doAlignLeft()
Sets X coordinate of the selected items to the value of the left-most selected item X coordinate.
CONDITIONAL_MENU * m_placementMenu
void doDistributeCenters(bool aIsXAxis, std::vector< std::pair< BOARD_ITEM *, BOX2I > > &aItems, BOARD_COMMIT &aCommit) const
Distribute selected items using an even spacing between the centers of their bounding boxes.
int selectTarget(std::vector< std::pair< BOARD_ITEM *, BOX2I > > &aItems, std::vector< std::pair< BOARD_ITEM *, BOX2I > > &aLocked, T aGetValue)
int AlignCenterY(const TOOL_EVENT &aEvent)
Set the y coordinate of the midpoint of each of the selected items to the value of the y coordinate o...
int AlignRight(const TOOL_EVENT &aEvent)
Sets X coordinate of the selected items to the value of the right-most selected item X coordinate.
void doDistributeGaps(bool aIsXAxis, std::vector< std::pair< BOARD_ITEM *, BOX2I > > &aItems, BOARD_COMMIT &aCommit) const
Distributes selected items using an even spacing between their bounding boxe in the x or y axis.
virtual ~ALIGN_DISTRIBUTE_TOOL()
bool Init() override
Init() is called once upon a registration of the tool.
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
int doAlignRight()
Align selected items using the right edge of their bounding boxes to the right-most item.
int AlignLeft(const TOOL_EVENT &aEvent)
Sets X coordinate of the selected items to the value of the left-most selected item X coordinate.
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
COMMIT & Stage(EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_SCREEN *aScreen=nullptr) override
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
virtual void Move(const VECTOR2I &aMoveVector)
Move this object.
Definition: board_item.h:342
virtual bool IsLocked() const
Definition: board_item.cpp:75
BOARD_ITEM_CONTAINER * GetParent() const
Definition: board_item.h:215
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:81
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.
bool IsType(FRAME_T aType) const
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:89
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:77
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
bool IsSelected() const
Definition: eda_item.h:110
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: footprint.cpp:1252
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:202
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
static TOOL_ACTION alignTop
Definition: pcb_actions.h:315
static TOOL_ACTION distributeHorizontallyGaps
Definition: pcb_actions.h:322
static TOOL_ACTION distributeHorizontallyCenters
Definition: pcb_actions.h:321
static TOOL_ACTION alignRight
Definition: pcb_actions.h:318
static TOOL_ACTION alignBottom
Definition: pcb_actions.h:316
static TOOL_ACTION alignLeft
Definition: pcb_actions.h:317
static TOOL_ACTION alignCenterX
Definition: pcb_actions.h:319
static TOOL_ACTION distributeVerticallyGaps
Definition: pcb_actions.h:324
static TOOL_ACTION distributeVerticallyCenters
Definition: pcb_actions.h:323
static TOOL_ACTION alignCenterY
Definition: pcb_actions.h:320
The selection tool: currently supports:
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, bool aForcePromotion=false) const
Check the "allow free pads" setting and if disabled, replace any pads in the collector with their par...
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.
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...
int Size() const
Returns the number of selected parts.
Definition: selection.h:116
TOOL_EVENT MakeEvent() const
Return the event associated with the action (i.e.
wxString GetFriendlyName() const
Return the translated user-friendly name of the action.
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
Generic, UI-independent tool event.
Definition: tool_event.h:167
bool Matches(const TOOL_EVENT &aEvent) const
Test whether two events match in terms of category & action or command.
Definition: tool_event.h:384
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()
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:44
@ CHT_MODIFY
Definition: commit.h:44
std::vector< int > GetDeltasForDistributeByGaps(const std::vector< std::pair< int, int > > &aItemExtents)
Given a list of 'n' item spans (e.g.
Definition: distribute.cpp:25
std::vector< int > GetDeltasForDistributeByPoints(const std::vector< int > &aItemPositions)
Definition: distribute.cpp:67
#define _(s)
@ FRAME_PCB_EDITOR
Definition: frame_type.h:42
std::vector< std::pair< BOARD_ITEM *, BOX2I > > GetBoundingBoxes(const T &aItems)
Class that computes missing connections on a PCB.
constexpr int delta
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition: typeinfo.h:86
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:691