95 return static_cast<FOOTPRINT*
>( aItem )->GetBoundingBox(
false );
101template<
typename T >
103 std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aLocked,
111 if( aLocked.size() >= 1 )
113 for(
const std::pair<BOARD_ITEM*, BOX2I>& item : aLocked )
115 if( item.second.Contains( curPos ) )
116 return aGetValue( item );
119 return aGetValue( aLocked.front() );
122 for(
const std::pair<BOARD_ITEM*, BOX2I>& item : aItems )
124 if( item.second.Contains( curPos ) )
125 return aGetValue( item );
128 return aGetValue( aItems.front() );
132template<
typename T >
134 std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aLockedItems,
141 for(
int i = aCollector.
GetCount() - 1; i >= 0; --i )
146 aCollector.
Remove( item );
152 bool differentParents =
false;
154 ||
m_frame->GetPcbNewSettings()->m_AllowFreePads;
158 if( !item->IsBOARD_ITEM() )
171 currentParent = parent;
172 else if( parent != currentParent )
173 differentParents =
true;
177 []( std::vector<std::pair<BOARD_ITEM*, BOX2I>>& list,
BOARD_ITEM* item,
FOOTPRINT* parentFp )
179 BOARD_ITEM* listItem = parentFp ? parentFp : item;
181 for(
const auto& [candidate, bbox] : list )
183 if( candidate == listItem )
187 list.emplace_back( std::make_pair( listItem,
getBoundingBox( item ) ) );
192 if( !item->IsBOARD_ITEM() )
197 if( boardItem->
Type() ==
PCB_PAD_T && ( !allowFreePads || ( allPads && differentParents ) ) )
201 if( parentFp && parentFp->
IsLocked() )
202 addToList( aLockedItems, boardItem, parentFp );
204 addToList( aItemsToAlign, boardItem, parentFp );
210 addToList( aLockedItems, boardItem,
nullptr );
212 addToList( aItemsToAlign, boardItem,
nullptr );
215 std::sort( aItemsToAlign.begin(), aItemsToAlign.end(), aCompare );
216 std::sort( aLockedItems.begin(), aLockedItems.end(), aCompare );
218 return aItemsToAlign.size();
224 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
225 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
228 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
230 return ( lhs.second.GetTop() < rhs.second.GetTop() );
238 int targetTop =
selectTarget( itemsToAlign, locked_items,
239 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
241 return aVal.second.GetTop();
245 for(
const auto& [item, bbox] : itemsToAlign )
247 if( item->GetParent() && item->GetParent()->IsSelected() )
250 int difference = targetTop - bbox.GetTop();
253 item->Move(
VECTOR2I( 0, difference ) );
256 commit.
Push(
_(
"Align to Top" ) );
263 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
264 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
267 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs)
269 return ( lhs.second.GetBottom() > rhs.second.GetBottom() );
277 int targetBottom =
selectTarget( itemsToAlign, locked_items,
278 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
280 return aVal.second.GetBottom();
284 for(
const auto& [item, bbox] : itemsToAlign )
286 if( item->GetParent() && item->GetParent()->IsSelected() )
289 int difference = targetBottom - bbox.GetBottom();
292 item->Move(
VECTOR2I( 0, difference ) );
295 commit.
Push(
_(
"Align to Bottom" ) );
313 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
314 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
317 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
319 return ( lhs.second.GetLeft() < rhs.second.GetLeft() );
327 int targetLeft =
selectTarget( itemsToAlign, locked_items,
328 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
330 return aVal.second.GetLeft();
334 for(
const auto& [item, bbox] : itemsToAlign )
336 if( item->GetParent() && item->GetParent()->IsSelected() )
339 int difference = targetLeft - bbox.GetLeft();
342 item->Move(
VECTOR2I( difference, 0 ) );
345 commit.
Push(
_(
"Align to Left" ) );
363 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
364 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
367 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
369 return ( lhs.second.GetRight() > rhs.second.GetRight() );
377 int targetRight =
selectTarget( itemsToAlign, locked_items,
378 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
380 return aVal.second.GetRight();
384 for(
const auto& [item, bbox] : itemsToAlign )
386 if( item->GetParent() && item->GetParent()->IsSelected() )
389 int difference = targetRight - bbox.GetRight();
392 item->Move(
VECTOR2I( difference, 0 ) );
395 commit.
Push(
_(
"Align to Right" ) );
402 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
403 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
406 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
408 return ( lhs.second.Centre().x < rhs.second.Centre().x );
417 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
419 return aVal.second.Centre().x;
423 for(
const auto& [item, bbox] : itemsToAlign )
425 if( item->GetParent() && item->GetParent()->IsSelected() )
428 int difference = targetX - bbox.Centre().x;
431 item->Move(
VECTOR2I( difference, 0 ) );
434 commit.
Push(
_(
"Align to Middle" ) );
441 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
442 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
445 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
447 return ( lhs.second.Centre().y < rhs.second.Centre().y );
456 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
458 return aVal.second.Centre().y;
462 for(
const auto& [item, bbox] : itemsToAlign )
464 if( item->GetParent() && item->GetParent()->IsSelected() )
467 int difference = targetY - bbox.Centre().y;
470 item->Move(
VECTOR2I( 0, difference ) );
473 commit.
Push(
_(
"Align to Center" ) );
494 if( selection.
Size() < 3 )
499 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToDistribute;
503 if( !item->IsBOARD_ITEM() )
507 itemsToDistribute.emplace_back( std::make_pair( boardItem,
getBoundingBox( boardItem ) ) );
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
Execute the changes.
COMMIT & Stage(EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE) override
Add a change of the item aItem of type aChangeType to the change list.
Abstract interface for BOARD_ITEMs capable of storing other items inside.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
bool IsLocked() const override
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
FOOTPRINT * GetParentFootprint() const
int GetCount() const
Return the number of objects in the list.
void Remove(int aIndex)
Remove the item at aIndex (first position is 0).
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_MARKER_T
class PCB_MARKER, a marker used to show something
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
@ PCB_PAD_T
class PAD, a pad in a footprint
VECTOR2< int32_t > VECTOR2I