43 m_selectionTool( nullptr ),
44 m_placementMenu( nullptr ),
59 m_frame = getEditFrame<PCB_BASE_FRAME>();
90 std::vector<std::pair<BOARD_ITEM*, BOX2I>> rects;
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;
175 itemsToAlign.push_back( boardItem );
179 lockedItems.push_back( boardItem );
183 itemsToAlign.push_back( boardItem );
188 std::sort( aItemsToAlign.begin(), aItemsToAlign.end(), aCompare );
189 std::sort( aLockedItems.begin(), aLockedItems.end(), aCompare );
191 return aItemsToAlign.size();
197 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
198 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
201 [](
const std::pair<BOARD_ITEM*, BOX2I>
left,
const std::pair<BOARD_ITEM*, BOX2I>
right)
203 return (
left.second.GetTop() <
right.second.GetTop() );
211 int targetTop =
selectTarget( itemsToAlign, locked_items,
212 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
214 return aVal.second.GetTop();
218 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
221 int difference = targetTop - i.second.GetTop();
234 commit.
Push(
_(
"Align to top" ) );
242 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
243 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
246 [](
const std::pair<BOARD_ITEM*, BOX2I>
left,
const std::pair<BOARD_ITEM*, BOX2I>
right)
248 return (
left.second.GetBottom() >
right.second.GetBottom() );
256 int targetBottom =
selectTarget( itemsToAlign, locked_items,
257 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
259 return aVal.second.GetBottom();
263 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
265 int difference = targetBottom - i.second.GetBottom();
279 commit.
Push(
_(
"Align to bottom" ) );
302 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
303 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
306 [](
const std::pair<BOARD_ITEM*, BOX2I>
left,
const std::pair<BOARD_ITEM*, BOX2I>
right)
308 return (
left.second.GetLeft() <
right.second.GetLeft() );
316 int targetLeft =
selectTarget( itemsToAlign, locked_items,
317 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
319 return aVal.second.GetLeft();
323 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
325 int difference = targetLeft - i.second.GetLeft();
339 commit.
Push(
_(
"Align to left" ) );
362 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
363 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
366 [](
const std::pair<BOARD_ITEM*, BOX2I>
left,
const std::pair<BOARD_ITEM*, BOX2I>
right)
368 return (
left.second.GetRight() >
right.second.GetRight() );
376 int targetRight =
selectTarget( itemsToAlign, locked_items,
377 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
379 return aVal.second.GetRight();
383 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
385 int difference = targetRight - i.second.GetRight();
399 commit.
Push(
_(
"Align to right" ) );
407 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
408 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
411 [](
const std::pair<BOARD_ITEM*, BOX2I>
left,
const std::pair<BOARD_ITEM*, BOX2I>
right)
413 return (
left.second.Centre().x <
right.second.Centre().x );
422 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
424 return aVal.second.Centre().x;
428 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
430 int difference = targetX - i.second.Centre().x;
444 commit.
Push(
_(
"Align to middle" ) );
452 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
453 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
456 [](
const std::pair<BOARD_ITEM*, BOX2I>
left,
const std::pair<BOARD_ITEM*, BOX2I>
right)
458 return (
left.second.Centre().y <
right.second.Centre().y );
467 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
469 return aVal.second.Centre().y;
473 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
475 int difference = targetY - i.second.Centre().y;
489 commit.
Push(
_(
"Align to center" ) );
501 for(
int i = aCollector.
GetCount() - 1; i >= 0; --i )
503 BOARD_ITEM* item = aCollector[i];
505 if( item->Type() == PCB_MARKER_T )
506 aCollector.Remove( item );
511 if( selection.
Size() <= 1 )
515 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToDistribute =
GetBoundingBoxes( selection );
518 std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
519 [] (
const std::pair<BOARD_ITEM*, BOX2I>
left,
520 const std::pair<BOARD_ITEM*, BOX2I>
right)
522 return ( left.second.GetRight() > right.second.GetRight() );
525 BOARD_ITEM* lastItem = itemsToDistribute.begin()->first;
526 const int maxRight = itemsToDistribute.begin()->second.GetRight();
529 std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
530 [] (
const std::pair<BOARD_ITEM*, BOX2I>
left,
531 const std::pair<BOARD_ITEM*, BOX2I>
right)
533 return ( left.second.GetX() < right.second.GetX() );
536 const int minX = itemsToDistribute.begin()->second.GetX();
537 int totalGap = maxRight - minX;
540 for(
const auto& [ item, rect ] : itemsToDistribute )
541 totalWidth += rect.GetWidth();
543 if( totalGap < totalWidth )
550 totalGap -= totalWidth;
554 commit.
Push(
_(
"Distribute horizontally" ) );
565 const int itemGap = totalGap / ( aItems.size() - 1 );
566 int targetX = aItems.begin()->second.GetX();
568 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : aItems )
573 if( lastItem == item )
583 int difference = targetX - i.second.
GetX();
586 targetX += ( i.second.GetWidth() + itemGap );
594 std::sort( aItems.begin(), aItems.end(),
595 [] (
const std::pair<BOARD_ITEM*, BOX2I>
left,
const std::pair<BOARD_ITEM*, BOX2I>
right)
597 return ( left.second.Centre().x < right.second.Centre().x );
600 const int totalGap = ( aItems.end() - 1 )->second.Centre().x
601 - aItems.begin()->second.Centre().x;
602 const int itemGap = totalGap / ( aItems.size() - 1 );
603 int targetX = aItems.begin()->second.Centre().x;
605 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : aItems )
616 int difference = targetX - i.second.Centre().x;
619 targetX += ( itemGap );
630 for(
int i = aCollector.
GetCount() - 1; i >= 0; --i )
632 BOARD_ITEM* item = aCollector[i];
634 if( item->Type() == PCB_MARKER_T )
635 aCollector.Remove( item );
640 if( selection.
Size() <= 1 )
644 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToDistribute =
GetBoundingBoxes( selection );
647 std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
648 [] (
const std::pair<BOARD_ITEM*, BOX2I>
left,
const std::pair<BOARD_ITEM*, BOX2I>
right)
650 return ( left.second.GetBottom() > right.second.GetBottom() );
653 BOARD_ITEM* lastItem = itemsToDistribute.begin()->first;
654 const int maxBottom = itemsToDistribute.begin()->second.GetBottom();
657 std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
658 [] (
const std::pair<BOARD_ITEM*, BOX2I>
left,
const std::pair<BOARD_ITEM*, BOX2I>
right)
660 return ( left.second.Centre().y < right.second.Centre().y );
663 int minY = itemsToDistribute.begin()->second.GetY();
664 int totalGap = maxBottom - minY;
667 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToDistribute )
668 totalHeight += i.second.GetHeight();
670 if( totalGap < totalHeight )
677 totalGap -= totalHeight;
681 commit.
Push(
_(
"Distribute vertically" ) );
692 const int itemGap = totalGap / ( aItems.size() - 1 );
693 int targetY = aItems.begin()->second.GetY();
695 for( std::pair<BOARD_ITEM*, BOX2I>& i : aItems )
700 if( lastItem == item )
710 int difference = targetY - i.second.
GetY();
713 targetY += ( i.second.GetHeight() + itemGap );
721 std::sort( aItems.begin(), aItems.end(),
722 [] (
const std::pair<BOARD_ITEM*, BOX2I>
left,
const std::pair<BOARD_ITEM*, BOX2I>
right)
724 return ( left.second.Centre().y < right.second.Centre().y );
727 const int totalGap = ( aItems.end() - 1 )->second.Centre().y
728 - aItems.begin()->second.Centre().y;
729 const int itemGap = totalGap / ( aItems.size() - 1 );
730 int targetY = aItems.begin()->second.Centre().y;
732 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : aItems )
743 int difference = targetY - i.second.Centre().y;
746 targetY += ( itemGap );
COMMIT & Stage(EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_SCREEN *aScreen=nullptr) override
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
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