93 return static_cast<FOOTPRINT*
>( aItem )->GetBoundingBox(
false );
101 std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aLocked,
109 if( aLocked.size() >= 1 )
111 for(
const std::pair<BOARD_ITEM*, BOX2I>& item : aLocked )
113 if( item.second.Contains( curPos ) )
114 return aGetValue( item );
117 return aGetValue( aLocked.front() );
120 for(
const std::pair<BOARD_ITEM*, BOX2I>& item : aItems )
122 if( item.second.Contains( curPos ) )
123 return aGetValue( item );
126 return aGetValue( aItems.front() );
130template<
typename T >
132 std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aLockedItems,
139 for(
int i = aCollector.
GetCount() - 1; i >= 0; --i )
144 aCollector.
Remove( item );
150 bool differentParents =
false;
152 ||
m_frame->GetPcbNewSettings()->m_AllowFreePads;
156 if( !item->IsBOARD_ITEM() )
169 currentParent = parent;
170 else if( parent != currentParent )
171 differentParents =
true;
175 []( std::vector<std::pair<BOARD_ITEM*, BOX2I>>& list,
BOARD_ITEM* item,
FOOTPRINT* parentFp )
177 BOARD_ITEM* listItem = parentFp ? parentFp : item;
179 for(
const auto& [candidate, bbox] : list )
181 if( candidate == listItem )
185 list.emplace_back( std::make_pair( listItem,
getBoundingBox( item ) ) );
195 if( boardItem->
Type() ==
PCB_PAD_T && ( !allowFreePads || ( allPads && differentParents ) ) )
199 if( parentFp && parentFp->
IsLocked() )
200 addToList( aLockedItems, boardItem, parentFp );
202 addToList( aItemsToAlign, boardItem, parentFp );
208 addToList( aLockedItems, boardItem,
nullptr );
210 addToList( aItemsToAlign, boardItem,
nullptr );
213 std::sort( aItemsToAlign.begin(), aItemsToAlign.end(), aCompare );
214 std::sort( aLockedItems.begin(), aLockedItems.end(), aCompare );
216 return aItemsToAlign.size();
222 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
223 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
226 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
228 return ( lhs.second.GetTop() < rhs.second.GetTop() );
236 int targetTop =
selectTarget( itemsToAlign, locked_items,
237 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
239 return aVal.second.GetTop();
243 for(
const auto& [item, bbox] : itemsToAlign )
245 if( item->GetParent() && item->GetParent()->IsSelected() )
248 int difference = targetTop - bbox.GetTop();
251 item->Move(
VECTOR2I( 0, difference ) );
254 commit.
Push(
_(
"Align to Top" ) );
261 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
262 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
265 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs)
267 return ( lhs.second.GetBottom() > rhs.second.GetBottom() );
275 int targetBottom =
selectTarget( itemsToAlign, locked_items,
276 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
278 return aVal.second.GetBottom();
282 for(
const auto& [item, bbox] : itemsToAlign )
284 if( item->GetParent() && item->GetParent()->IsSelected() )
287 int difference = targetBottom - bbox.GetBottom();
290 item->Move(
VECTOR2I( 0, difference ) );
293 commit.
Push(
_(
"Align to Bottom" ) );
311 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
312 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
315 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
317 return ( lhs.second.GetLeft() < rhs.second.GetLeft() );
325 int targetLeft =
selectTarget( itemsToAlign, locked_items,
326 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
328 return aVal.second.GetLeft();
332 for(
const auto& [item, bbox] : itemsToAlign )
334 if( item->GetParent() && item->GetParent()->IsSelected() )
337 int difference = targetLeft - bbox.GetLeft();
340 item->Move(
VECTOR2I( difference, 0 ) );
343 commit.
Push(
_(
"Align to Left" ) );
361 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
362 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
365 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
367 return ( lhs.second.GetRight() > rhs.second.GetRight() );
375 int targetRight =
selectTarget( itemsToAlign, locked_items,
376 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
378 return aVal.second.GetRight();
382 for(
const auto& [item, bbox] : itemsToAlign )
384 if( item->GetParent() && item->GetParent()->IsSelected() )
387 int difference = targetRight - bbox.GetRight();
390 item->Move(
VECTOR2I( difference, 0 ) );
393 commit.
Push(
_(
"Align to Right" ) );
400 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
401 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
404 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
406 return ( lhs.second.Centre().x < rhs.second.Centre().x );
415 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
417 return aVal.second.Centre().x;
421 for(
const auto& [item, bbox] : itemsToAlign )
423 if( item->GetParent() && item->GetParent()->IsSelected() )
426 int difference = targetX - bbox.Centre().x;
429 item->Move(
VECTOR2I( difference, 0 ) );
432 commit.
Push(
_(
"Align to Middle" ) );
439 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToAlign;
440 std::vector<std::pair<BOARD_ITEM*, BOX2I>> locked_items;
443 [](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
445 return ( lhs.second.Centre().y < rhs.second.Centre().y );
454 [](
const std::pair<BOARD_ITEM*, BOX2I>& aVal )
456 return aVal.second.Centre().y;
460 for(
const auto& [item, bbox] : itemsToAlign )
462 if( item->GetParent() && item->GetParent()->IsSelected() )
465 int difference = targetY - bbox.Centre().y;
468 item->Move(
VECTOR2I( 0, difference ) );
471 commit.
Push(
_(
"Align to Center" ) );
492 if( selection.
Size() < 3 )
497 std::vector<std::pair<BOARD_ITEM*, BOX2I>> itemsToDistribute;
501 if( !item->IsBOARD_ITEM() )
505 itemsToDistribute.emplace_back( std::make_pair( boardItem,
getBoundingBox( boardItem ) ) );
529 commit.
Push( commitMsg );
535 std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aItems,
543 std::sort( aItems.begin(), aItems.end(),
544 [&](
const std::pair<BOARD_ITEM*, BOX2I>& a,
const std::pair<BOARD_ITEM*, BOX2I>& b )
546 return aIsXAxis ? a.second.GetLeft() < b.second.GetLeft()
547 : a.second.GetTop() < b.second.GetTop();
551 std::vector<std::pair<int, int>> itemSpans;
552 itemSpans.reserve( aItems.size() );
554 for(
const auto& [item, box] : aItems )
556 const int start = aIsXAxis ? box.GetLeft() : box.GetTop();
557 const int end = aIsXAxis ? box.GetRight() : box.GetBottom();
558 itemSpans.emplace_back( start,
end );
565 for(
size_t i = 1; i < aItems.size() - 1; ++i )
567 const auto& [item, box] = aItems[i];
568 const int delta = deltas[i];
575 item->Move( deltaVec );
582 std::vector<std::pair<BOARD_ITEM*, BOX2I>>& aItems,
586 aItems.begin(), aItems.end(),
587 [&](
const std::pair<BOARD_ITEM*, BOX2I>& lhs,
const std::pair<BOARD_ITEM*, BOX2I>& rhs )
589 const int lhsPos = aIsXAxis ? lhs.second.Centre().x : lhs.second.Centre().y;
590 const int rhsPos = aIsXAxis ? rhs.second.Centre().x : rhs.second.Centre().y;
591 return lhsPos < rhsPos;
594 std::vector<int> itemCenters;
595 itemCenters.reserve( aItems.size() );
597 for(
const auto& [item, box] : aItems )
599 itemCenters.push_back( aIsXAxis ? box.Centre().x : box.Centre().y );
605 for(
size_t i = 1; i < aItems.size() - 1; ++i )
607 const auto& [item, box] = aItems[i];
608 const int delta = deltas[i];
615 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