43 m_selectionTool( nullptr ),
44 m_placementMenu( nullptr ),
59 m_frame = getEditFrame<PCB_BASE_FRAME>();
95 std::vector<std::pair<BOARD_ITEM*, BOX2I>> rects;
99 if( !item->IsBOARD_ITEM() )
107 rects.emplace_back( std::make_pair( footprint, footprint->
GetBoundingBox(
false ) ) );
111 rects.emplace_back( std::make_pair( boardItem, boardItem->
GetBoundingBox() ) );
119template<
typename T >
121 std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aLocked,
129 if( aLocked.size() >= 1 )
131 for(
const std::pair<BOARD_ITEM*, BOX2I>& item : aLocked )
133 if( item.second.Contains( curPos ) )
134 return aGetValue( item );
137 return aGetValue( aLocked.front() );
140 for(
const std::pair<BOARD_ITEM*, BOX2I>& item : aItems )
142 if( item.second.Contains( curPos ) )
143 return aGetValue( item );
146 return aGetValue( aItems.front() );
150template<
typename T >
152 std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aLockedItems,
159 for(
int i = aCollector.
GetCount() - 1; i >= 0; --i )
161 BOARD_ITEM* item = aCollector[i];
163 if( item->Type() == PCB_MARKER_T )
164 aCollector.Remove( item );
168 std::vector<BOARD_ITEM*> lockedItems;
169 std::vector<BOARD_ITEM*> itemsToAlign;
173 if( !item->IsBOARD_ITEM() )
184 itemsToAlign.push_back( boardItem );
186 lockedItems.push_back( boardItem );
190 itemsToAlign.push_back( boardItem );
196 std::sort( aItemsToAlign.begin(), aItemsToAlign.end(), aCompare );
197 std::sort( aLockedItems.begin(), aLockedItems.end(), aCompare );
199 return aItemsToAlign.size();
205 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
206 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
209 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
211 return ( lhs.second.GetTop() < rhs.second.GetTop() );
219 int targetTop =
selectTarget( itemsToAlign, locked_items,
220 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
222 return aVal.second.GetTop();
226 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
229 int difference = targetTop - i.second.GetTop();
242 commit.
Push(
_(
"Align to Top" ) );
249 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
250 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
253 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs)
255 return ( lhs.second.GetBottom() > rhs.second.GetBottom() );
263 int targetBottom =
selectTarget( itemsToAlign, locked_items,
264 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
266 return aVal.second.GetBottom();
270 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
272 int difference = targetBottom - i.second.GetBottom();
286 commit.
Push(
_(
"Align to Bottom" ) );
304 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
305 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
308 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
310 return ( lhs.second.GetLeft() < rhs.second.GetLeft() );
318 int targetLeft =
selectTarget( itemsToAlign, locked_items,
319 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
321 return aVal.second.GetLeft();
325 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
327 int difference = targetLeft - i.second.GetLeft();
341 commit.
Push(
_(
"Align to Left" ) );
359 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
360 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
363 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
365 return ( lhs.second.GetRight() > rhs.second.GetRight() );
373 int targetRight =
selectTarget( itemsToAlign, locked_items,
374 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
376 return aVal.second.GetRight();
380 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
382 int difference = targetRight - i.second.GetRight();
396 commit.
Push(
_(
"Align to Right" ) );
403 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
404 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
407 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
409 return ( lhs.second.Centre().x < rhs.second.Centre().x );
418 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
420 return aVal.second.Centre().x;
424 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
426 int difference = targetX - i.second.Centre().x;
440 commit.
Push(
_(
"Align to Middle" ) );
447 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
448 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
451 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
453 return ( lhs.second.Centre().y < rhs.second.Centre().y );
462 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
464 return aVal.second.Centre().y;
468 for(
const std::pair<BOARD_ITEM*, BOX2I>& i : itemsToAlign )
470 int difference = targetY - i.second.Centre().y;
484 commit.
Push(
_(
"Align to Center" ) );
503 if( selection.
Size() < 3 )
508 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToDistribute =
GetBoundingBoxes( selection );
531 commit.
Push( commitMsg );
537 std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aItems,
545 std::sort( aItems.begin(), aItems.end(),
546 [&](
const std::pair<BOARD_ITEM*, BOX2I>& a,
const std::pair<BOARD_ITEM*, BOX2I>& b )
548 return aIsXAxis ? a.second.GetLeft() < b.second.GetLeft()
549 : a.second.GetTop() < b.second.GetTop();
553 std::vector<std::pair<int, int>> itemSpans;
554 itemSpans.reserve( aItems.size() );
556 for(
const auto& [item, box] : aItems )
558 const int start = aIsXAxis ? box.GetLeft() : box.GetTop();
559 const int end = aIsXAxis ? box.GetRight() : box.GetBottom();
560 itemSpans.emplace_back( start, end );
567 for(
size_t i = 1; i < aItems.size() - 1; ++i )
569 const auto& [item, box] = aItems[i];
570 const int delta = deltas[i];
577 item->Move( deltaVec );
584 std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aItems,
588 aItems.begin(), aItems.end(),
589 [&](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
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;
596 std::vector<int> itemCenters;
597 itemCenters.reserve( aItems.size() );
599 for(
const auto& [item, box] : aItems )
601 itemCenters.push_back( aIsXAxis ? box.Centre().x : box.Centre().y );
607 for(
size_t i = 1; i < aItems.size() - 1; ++i )
609 const auto& [item, box] = aItems[i];
610 const int delta = deltas[i];
617 item->Move( deltaVec );
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 alignTop
static TOOL_ACTION distributeHorizontallyGaps
static TOOL_ACTION distributeHorizontallyCenters
static TOOL_ACTION alignRight
static TOOL_ACTION alignBottom
static TOOL_ACTION alignLeft
static TOOL_ACTION alignCenterX
static TOOL_ACTION distributeVerticallyGaps
static TOOL_ACTION distributeVerticallyCenters
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.
std::vector< int > GetDeltasForDistributeByGaps(const std::vector< std::pair< int, int > > &aItemExtents)
Given a list of 'n' item spans (e.g.
std::vector< int > GetDeltasForDistributeByPoints(const std::vector< int > &aItemPositions)
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
VECTOR2< int32_t > VECTOR2I