41 m_selectionTool( nullptr ),
42 m_placementMenu( nullptr ),
57 m_frame = getEditFrame<PCB_BASE_FRAME>();
88 std::vector<std::pair<BOARD_ITEM*, BOX2I>> rects;
94 wxCHECK2( boardItem,
continue );
99 rects.emplace_back( std::make_pair( footprint,
104 rects.emplace_back( std::make_pair( boardItem, boardItem->
GetBoundingBox() ) );
112template<
typename T >
114 std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aLocked,
122 if( aLocked.size() >= 1 )
124 for(
const std::pair<BOARD_ITEM*, BOX2I>& item : aLocked )
126 if( item.second.Contains( curPos ) )
127 return aGetValue( item );
130 return aGetValue( aLocked.front() );
133 for(
const std::pair<BOARD_ITEM*, BOX2I>& item : aItems )
135 if( item.second.Contains( curPos ) )
136 return aGetValue( item );
139 return aGetValue( aItems.front() );
143template<
typename T >
145 std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aLockedItems,
152 for(
int i = aCollector.
GetCount() - 1; i >= 0; --i )
154 BOARD_ITEM* item = aCollector[i];
156 if( item->Type() == PCB_MARKER_T )
157 aCollector.Remove( item );
161 std::vector<BOARD_ITEM*> lockedItems;
162 std::vector<BOARD_ITEM*> itemsToAlign;
167 wxCHECK2( boardItem,
continue );
175 itemsToAlign.push_back( boardItem );
177 lockedItems.push_back( boardItem );
180 itemsToAlign.push_back( boardItem );
185 std::sort( aItemsToAlign.begin(), aItemsToAlign.end(), aCompare );
186 std::sort( aLockedItems.begin(), aLockedItems.end(), aCompare );
188 return aItemsToAlign.size();
194 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
195 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
198 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
200 return ( lhs.second.GetTop() < rhs.second.GetTop() );
208 int targetTop =
selectTarget( itemsToAlign, locked_items,
209 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
211 return aVal.second.GetTop();
215 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
218 int difference = targetTop - i.second.GetTop();
231 commit.
Push(
_(
"Align to Top" ) );
238 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
239 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
242 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs)
244 return ( lhs.second.GetBottom() > rhs.second.GetBottom() );
252 int targetBottom =
selectTarget( itemsToAlign, locked_items,
253 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
255 return aVal.second.GetBottom();
259 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
261 int difference = targetBottom - i.second.GetBottom();
275 commit.
Push(
_(
"Align to Bottom" ) );
293 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
294 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
297 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
299 return ( lhs.second.GetLeft() < rhs.second.GetLeft() );
307 int targetLeft =
selectTarget( itemsToAlign, locked_items,
308 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
310 return aVal.second.GetLeft();
314 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
316 int difference = targetLeft - i.second.GetLeft();
330 commit.
Push(
_(
"Align to Left" ) );
348 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
349 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
352 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
354 return ( lhs.second.GetRight() > rhs.second.GetRight() );
362 int targetRight =
selectTarget( itemsToAlign, locked_items,
363 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
365 return aVal.second.GetRight();
369 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
371 int difference = targetRight - i.second.GetRight();
385 commit.
Push(
_(
"Align to Right" ) );
392 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
393 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
396 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
398 return ( lhs.second.Centre().x < rhs.second.Centre().x );
407 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
409 return aVal.second.Centre().x;
413 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
415 int difference = targetX - i.second.Centre().x;
429 commit.
Push(
_(
"Align to Middle" ) );
436 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
437 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
440 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
442 return ( lhs.second.Centre().y < rhs.second.Centre().y );
451 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
453 return aVal.second.Centre().y;
457 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
459 int difference = targetY - i.second.Centre().y;
473 commit.
Push(
_(
"Align to Center" ) );
484 for(
int i = aCollector.
GetCount() - 1; i >= 0; --i )
486 BOARD_ITEM* item = aCollector[i];
488 if( item->Type() == PCB_MARKER_T )
489 aCollector.Remove( item );
494 if( selection.
Size() <= 1 )
498 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToDistribute =
GetBoundingBoxes( selection );
501 std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
502 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
504 return ( lhs.second.GetRight() > rhs.second.GetRight() );
507 BOARD_ITEM* lastItem = itemsToDistribute.begin()->first;
508 const int maxRight = itemsToDistribute.begin()->second.GetRight();
511 std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
512 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
514 return ( lhs.second.GetX() < rhs.second.GetX() );
517 const int minX = itemsToDistribute.begin()->second.GetX();
518 int totalGap = maxRight - minX;
521 for(
const auto& [ item, rect ] : itemsToDistribute )
522 totalWidth += rect.GetWidth();
524 if( totalGap < totalWidth )
531 totalGap -= totalWidth;
535 commit.
Push(
_(
"Distribute Horizontally" ) );
545 const int itemGap = totalGap / ( aItems.size() - 1 );
546 int targetX = aItems.begin()->second.GetX();
548 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : aItems )
553 if( lastItem == item )
563 int difference = targetX - i.second.
GetX();
566 targetX += ( i.second.GetWidth() + itemGap );
574 std::sort( aItems.begin(), aItems.end(),
575 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
577 return ( lhs.second.Centre().x < rhs.second.Centre().x );
580 const int totalGap = ( aItems.end()-1 )->second.Centre().x - aItems.begin()->second.Centre().x;
581 const int itemGap = totalGap / ( aItems.size() - 1 );
582 int targetX = aItems.begin()->second.Centre().x;
584 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : aItems )
595 int difference = targetX - i.second.Centre().x;
598 targetX += ( itemGap );
609 for(
int i = aCollector.
GetCount() - 1; i >= 0; --i )
611 BOARD_ITEM* item = aCollector[i];
613 if( item->Type() == PCB_MARKER_T )
614 aCollector.Remove( item );
619 if( selection.
Size() <= 1 )
623 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToDistribute =
GetBoundingBoxes( selection );
626 std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
627 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
629 return ( lhs.second.GetBottom() > rhs.second.GetBottom() );
632 BOARD_ITEM* lastItem = itemsToDistribute.begin()->first;
633 const int maxBottom = itemsToDistribute.begin()->second.GetBottom();
636 std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
637 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
639 return ( lhs.second.Centre().y < rhs.second.Centre().y );
642 int minY = itemsToDistribute.begin()->second.GetY();
643 int totalGap = maxBottom - minY;
646 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToDistribute )
647 totalHeight += i.second.GetHeight();
649 if( totalGap < totalHeight )
656 totalGap -= totalHeight;
660 commit.
Push(
_(
"Distribute Vertically" ) );
670 const int itemGap = totalGap / ( aItems.size() - 1 );
671 int targetY = aItems.begin()->second.GetY();
673 for( std::pair<BOARD_ITEM*, BOX2I>& i : aItems )
678 if( lastItem == item )
688 int difference = targetY - i.second.
GetY();
691 targetY += ( i.second.GetHeight() + itemGap );
699 std::sort( aItems.begin(), aItems.end(),
700 [] (
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs)
702 return ( lhs.second.Centre().y < rhs.second.Centre().y );
705 const int totalGap = ( aItems.end() - 1 )->second.Centre().y
706 - aItems.begin()->second.Centre().y;
707 const int itemGap = totalGap / ( aItems.size() - 1 );
708 int targetY = aItems.begin()->second.Centre().y;
710 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : aItems )
721 int difference = targetY - i.second.Centre().y;
724 targetY += ( itemGap );
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...
virtual void Move(const VECTOR2I &aMoveVector)
Move this object.
virtual bool IsLocked() const
BOARD_ITEM_CONTAINER * GetParent() const
int GetCount() const
Return the number of objects in the list.
bool IsType(FRAME_T aType) const
A base class for most all the KiCad significant classes used in schematics and boards.
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
KICAD_T Type() const
Returns the type of object.
Used when the right click button is pressed, or when the select tool is in effect.
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
static TOOL_ACTION distributeVertically
static TOOL_ACTION alignTop
static TOOL_ACTION alignRight
static TOOL_ACTION alignBottom
static TOOL_ACTION alignLeft
static TOOL_ACTION distributeHorizontally
static TOOL_ACTION alignCenterX
static TOOL_ACTION alignCenterY
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.
Class that computes missing connections on a PCB.
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
@ PCB_PAD_T
class PAD, a pad in a footprint