97 return static_cast<FOOTPRINT*
>( aItem )->GetBoundingBox(
false );
103template<
typename T >
105 std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aLocked,
113 if( aLocked.size() >= 1 )
115 for(
const std::pair<BOARD_ITEM*, BOX2I>& item : aLocked )
117 if( item.second.Contains( curPos ) )
118 return aGetValue( item );
121 return aGetValue( aLocked.front() );
124 for(
const std::pair<BOARD_ITEM*, BOX2I>& item : aItems )
126 if( item.second.Contains( curPos ) )
127 return aGetValue( item );
130 return aGetValue( aItems.front() );
134template<
typename T >
136 std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aLockedItems,
143 for(
int i = aCollector.
GetCount() - 1; i >= 0; --i )
148 aCollector.
Remove( item );
154 bool differentParents =
false;
156 ||
m_frame->GetPcbNewSettings()->m_AllowFreePads;
160 if( !item->IsBOARD_ITEM() )
173 currentParent = parent;
174 else if( parent != currentParent )
175 differentParents =
true;
179 []( std::vector<std::pair<BOARD_ITEM*, BOX2I>>& list,
BOARD_ITEM* item,
FOOTPRINT* parentFp )
181 BOARD_ITEM* listItem = parentFp ? parentFp : item;
183 for(
const auto& [candidate, bbox] : list )
185 if( candidate == listItem )
189 list.emplace_back( std::make_pair( listItem,
getBoundingBox( item ) ) );
199 if( boardItem->
Type() ==
PCB_PAD_T && ( !allowFreePads || ( allPads && differentParents ) ) )
203 if( parentFp && parentFp->
IsLocked() )
204 addToList( aLockedItems, boardItem, parentFp );
206 addToList( aItemsToAlign, boardItem, parentFp );
212 addToList( aLockedItems, boardItem,
nullptr );
214 addToList( aItemsToAlign, boardItem,
nullptr );
217 std::sort( aItemsToAlign.begin(), aItemsToAlign.end(), aCompare );
218 std::sort( aLockedItems.begin(), aLockedItems.end(), aCompare );
220 return aItemsToAlign.size();
226 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
227 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
230 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
232 return ( lhs.second.GetTop() < rhs.second.GetTop() );
240 int targetTop =
selectTarget( itemsToAlign, locked_items,
241 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
243 return aVal.second.GetTop();
247 for(
const auto& [item, bbox] : itemsToAlign )
249 if( item->GetParent() && item->GetParent()->IsSelected() )
252 int difference = targetTop - bbox.GetTop();
255 item->Move(
VECTOR2I( 0, difference ) );
258 commit.
Push(
_(
"Align to Top" ) );
265 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
266 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
269 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs)
271 return ( lhs.second.GetBottom() > rhs.second.GetBottom() );
279 int targetBottom =
selectTarget( itemsToAlign, locked_items,
280 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
282 return aVal.second.GetBottom();
286 for(
const auto& [item, bbox] : itemsToAlign )
288 if( item->GetParent() && item->GetParent()->IsSelected() )
291 int difference = targetBottom - bbox.GetBottom();
294 item->Move(
VECTOR2I( 0, difference ) );
297 commit.
Push(
_(
"Align to Bottom" ) );
315 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
316 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
319 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
321 return ( lhs.second.GetLeft() < rhs.second.GetLeft() );
329 int targetLeft =
selectTarget( itemsToAlign, locked_items,
330 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
332 return aVal.second.GetLeft();
336 for(
const auto& [item, bbox] : itemsToAlign )
338 if( item->GetParent() && item->GetParent()->IsSelected() )
341 int difference = targetLeft - bbox.GetLeft();
344 item->Move(
VECTOR2I( difference, 0 ) );
347 commit.
Push(
_(
"Align to Left" ) );
365 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
366 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
369 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
371 return ( lhs.second.GetRight() > rhs.second.GetRight() );
379 int targetRight =
selectTarget( itemsToAlign, locked_items,
380 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
382 return aVal.second.GetRight();
386 for(
const auto& [item, bbox] : itemsToAlign )
388 if( item->GetParent() && item->GetParent()->IsSelected() )
391 int difference = targetRight - bbox.GetRight();
394 item->Move(
VECTOR2I( difference, 0 ) );
397 commit.
Push(
_(
"Align to Right" ) );
404 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
405 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
408 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
410 return ( lhs.second.Centre().x < rhs.second.Centre().x );
419 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
421 return aVal.second.Centre().x;
425 for(
const auto& [item, bbox] : itemsToAlign )
427 if( item->GetParent() && item->GetParent()->IsSelected() )
430 int difference = targetX - bbox.Centre().x;
433 item->Move(
VECTOR2I( difference, 0 ) );
436 commit.
Push(
_(
"Align to Middle" ) );
443 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
444 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
447 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
449 return ( lhs.second.Centre().y < rhs.second.Centre().y );
458 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
460 return aVal.second.Centre().y;
464 for(
const auto& [item, bbox] : itemsToAlign )
466 if( item->GetParent() && item->GetParent()->IsSelected() )
469 int difference = targetY - bbox.Centre().y;
472 item->Move(
VECTOR2I( 0, difference ) );
475 commit.
Push(
_(
"Align to Center" ) );
496 if( selection.
Size() < 3 )
501 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToDistribute;
505 if( !item->IsBOARD_ITEM() )
509 itemsToDistribute.emplace_back( std::make_pair( boardItem,
getBoundingBox( boardItem ) ) );
533 commit.
Push( commitMsg );
539 std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aItems,
547 std::sort( aItems.begin(), aItems.end(),
548 [&](
const std::pair<BOARD_ITEM*, BOX2I>& a,
const std::pair<BOARD_ITEM*, BOX2I>& b )
550 return aIsXAxis ? a.second.GetLeft() < b.second.GetLeft()
551 : a.second.GetTop() < b.second.GetTop();
555 std::vector<std::pair<int, int>> itemSpans;
556 itemSpans.reserve( aItems.size() );
558 for(
const auto& [item, box] : aItems )
560 const int start = aIsXAxis ? box.GetLeft() : box.GetTop();
561 const int end = aIsXAxis ? box.GetRight() : box.GetBottom();
562 itemSpans.emplace_back( start,
end );
569 for(
size_t i = 1; i < aItems.size() - 1; ++i )
571 const auto& [item, box] = aItems[i];
572 const int delta = deltas[i];
579 item->Move( deltaVec );
586 std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aItems,
590 aItems.begin(), aItems.end(),
591 [&](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
593 const int lhsPos = aIsXAxis ? lhs.second.Centre().x : lhs.second.Centre().y;
594 const int rhsPos = aIsXAxis ? rhs.second.Centre().x : rhs.second.Centre().y;
595 return lhsPos < rhsPos;
598 std::vector<int> itemCenters;
599 itemCenters.reserve( aItems.size() );
601 for(
const auto& [item, box] : aItems )
603 itemCenters.push_back( aIsXAxis ? box.Centre().x : box.Centre().y );
609 for(
size_t i = 1; i < aItems.size() - 1; ++i )
611 const auto& [item, box] = aItems[i];
612 const int delta = deltas[i];
619 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_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
@ PCB_PAD_T
class PAD, a pad in a footprint
VECTOR2< int32_t > VECTOR2I