KiCad PCB EDA Suite
placement_tool.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2014-2016 CERN
5  * @author Maciej Suminski <maciej.suminski@cern.ch>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 #include "tool/selection.h"
25 #include "placement_tool.h"
26 #include "pcb_actions.h"
27 #include "selection_tool.h"
28 #include "edit_tool.h"
29 #include <tool/tool_manager.h>
30 
31 #include <pcb_edit_frame.h>
32 #include <class_board.h>
33 #include <ratsnest_data.h>
34 #include <board_commit.h>
35 #include <bitmaps.h>
36 
37 #include <confirm.h>
38 #include <menus_helpers.h>
39 
40 
42  TOOL_INTERACTIVE( "pcbnew.Placement" ), m_selectionTool( NULL ), m_placementMenu( NULL ),
43  m_frame( NULL )
44 {
45 }
46 
48 {
49  delete m_placementMenu;
50 }
51 
52 
54 {
55  // Find the selection tool, so they can cooperate
57 
58  wxASSERT_MSG( m_selectionTool, _( "pcbnew.InteractiveSelection tool is not available" ) );
59 
60  m_frame = getEditFrame<PCB_BASE_FRAME>();
61 
62  // Create a context menu and make it available through selection tool
63  m_placementMenu = new ACTION_MENU( true );
64  m_placementMenu->SetTool( this );
65  m_placementMenu->SetIcon( align_items_xpm );
66  m_placementMenu->SetTitle( _( "Align/Distribute" ) );
67 
68  // Add all align/distribute commands
75 
76  m_placementMenu->AppendSeparator();
79 
82 
83  return true;
84 }
85 
86 
87 template <class T>
89 {
90  ALIGNMENT_RECTS rects;
91 
92  for( auto item : sel )
93  {
94  BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
95 
96  if( item->Type() == PCB_MODULE_T )
97  rects.emplace_back( std::make_pair( boardItem, static_cast<MODULE*>( item )->GetFootprintRect() ) );
98  else
99  rects.emplace_back( std::make_pair( boardItem, item->GetBoundingBox() ) );
100  }
101 
102  return rects;
103 }
104 
105 
106 template< typename T >
108 {
109  wxPoint curPos( getViewControls()->GetCursorPosition().x, getViewControls()->GetCursorPosition().y );
110 
111  // after sorting, the fist item acts as the target for all others
112  // unless we have a locked item, in which case we use that for the target
113  int target = !aLocked.size() ? aGetValue( aItems.front() ): aGetValue( aLocked.front() );
114 
115  // Iterate through both lists to find if we are mouse-over on one of the items.
116  for( auto sel = aLocked.begin(); sel != aItems.end(); sel++ )
117  {
118  // If there are locked items, prefer aligning to them over
119  // aligning to the cursor as they do not move
120  if( sel == aLocked.end() )
121  {
122  if( aLocked.size() == 0 )
123  {
124  sel = aItems.begin();
125  continue;
126  }
127 
128  break;
129  }
130 
131  // We take the first target that overlaps our cursor.
132  // This is deterministic because we assume sorted arrays
133  if( sel->second.Contains( curPos ) )
134  {
135  target = aGetValue( *sel );
136  break;
137  }
138  }
139 
140  return target;
141 }
142 
143 
144 template< typename T >
146 {
147 
149  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
150  { EditToolSelectionFilter( aCollector, EXCLUDE_TRANSIENTS ); } );
151 
152  if( selection.Size() <= 1 )
153  return 0;
154 
155  std::vector<BOARD_ITEM*> lockedItems;
156  selection = m_selectionTool->RequestSelection(
157  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
158  { EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED ); }, &lockedItems );
159 
160  aItems = GetBoundingBoxes( selection );
161  aLocked = GetBoundingBoxes( lockedItems );
162  std::sort( aItems.begin(), aItems.end(), aCompare );
163  std::sort( aLocked.begin(), aLocked.end(), aCompare );
164 
165  return aItems.size();
166 }
167 
168 
170 {
171  ALIGNMENT_RECTS itemsToAlign;
172  ALIGNMENT_RECTS locked_items;
173 
174  if( !GetSelections( itemsToAlign, locked_items, []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
175  { return ( left.second.GetTop() < right.second.GetTop() ); } ) )
176  return 0;
177 
178  BOARD_COMMIT commit( m_frame );
180  auto targetTop = selectTarget( itemsToAlign, locked_items, []( const ALIGNMENT_RECT& aVal )
181  { return aVal.second.GetTop(); } );
182 
183  // Move the selected items
184  for( auto& i : itemsToAlign )
185  {
186  int difference = targetTop - i.second.GetTop();
187  BOARD_ITEM* item = i.first;
188 
189  // Don't move a pad by itself unless editing the footprint
190  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
191  item = item->GetParent();
192 
193  item->Move( wxPoint( 0, difference ) );
194  }
195 
196  commit.Push( _( "Align to top" ) );
197 
198  return 0;
199 }
200 
201 
203 {
204  ALIGNMENT_RECTS itemsToAlign;
205  ALIGNMENT_RECTS locked_items;
206 
207  if( !GetSelections( itemsToAlign, locked_items, []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
208  { return ( left.second.GetBottom() < right.second.GetBottom() ); } ) )
209  return 0;
210 
211  BOARD_COMMIT commit( m_frame );
213  auto targetBottom = selectTarget( itemsToAlign, locked_items, []( const ALIGNMENT_RECT& aVal )
214  { return aVal.second.GetBottom(); } );
215 
216  // Move the selected items
217  for( auto& i : itemsToAlign )
218  {
219  int difference = targetBottom - i.second.GetBottom();
220  BOARD_ITEM* item = i.first;
221 
222  // Don't move a pad by itself unless editing the footprint
223  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
224  item = item->GetParent();
225 
226  item->Move( wxPoint( 0, difference ) );
227  }
228 
229  commit.Push( _( "Align to bottom" ) );
230 
231  return 0;
232 }
233 
234 
236 {
237  // Because this tool uses bounding boxes and they aren't mirrored even when
238  // the view is mirrored, we need to call the other one if mirrored.
239  if( getView()->IsMirroredX() )
240  {
241  return doAlignRight();
242  }
243  else
244  {
245  return doAlignLeft();
246  }
247 }
248 
249 
251 {
252  ALIGNMENT_RECTS itemsToAlign;
253  ALIGNMENT_RECTS locked_items;
254 
255  if( !GetSelections( itemsToAlign, locked_items, []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
256  { return ( left.second.GetLeft() < right.second.GetLeft() ); } ) )
257  return 0;
258 
259  BOARD_COMMIT commit( m_frame );
261  auto targetLeft = selectTarget( itemsToAlign, locked_items, []( const ALIGNMENT_RECT& aVal )
262  { return aVal.second.GetLeft(); } );
263 
264  // Move the selected items
265  for( auto& i : itemsToAlign )
266  {
267  int difference = targetLeft - i.second.GetLeft();
268  BOARD_ITEM* item = i.first;
269 
270  // Don't move a pad by itself unless editing the footprint
271  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
272  item = item->GetParent();
273 
274  item->Move( wxPoint( difference, 0 ) );
275  }
276 
277  commit.Push( _( "Align to left" ) );
278 
279  return 0;
280 }
281 
282 
284 {
285  // Because this tool uses bounding boxes and they aren't mirrored even when
286  // the view is mirrored, we need to call the other one if mirrored.
287  if( getView()->IsMirroredX() )
288  {
289  return doAlignLeft();
290  }
291  else
292  {
293  return doAlignRight();
294  }
295 }
296 
297 
299 {
300  ALIGNMENT_RECTS itemsToAlign;
301  ALIGNMENT_RECTS locked_items;
302 
303  if( !GetSelections( itemsToAlign, locked_items, []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
304  { return ( left.second.GetRight() < right.second.GetRight() ); } ) )
305  return 0;
306 
307  BOARD_COMMIT commit( m_frame );
309  auto targetRight = selectTarget( itemsToAlign, locked_items, []( const ALIGNMENT_RECT& aVal )
310  { return aVal.second.GetRight(); } );
311 
312  // Move the selected items
313  for( auto& i : itemsToAlign )
314  {
315  int difference = targetRight - i.second.GetRight();
316  BOARD_ITEM* item = i.first;
317 
318  // Don't move a pad by itself unless editing the footprint
319  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
320  item = item->GetParent();
321 
322  item->Move( wxPoint( difference, 0 ) );
323  }
324 
325  commit.Push( _( "Align to right" ) );
326 
327  return 0;
328 }
329 
330 
332 {
333  ALIGNMENT_RECTS itemsToAlign;
334  ALIGNMENT_RECTS locked_items;
335 
336  if( !GetSelections( itemsToAlign, locked_items, []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
337  { return ( left.second.GetCenter().x < right.second.GetCenter().x ); } ) )
338  return 0;
339 
340  BOARD_COMMIT commit( m_frame );
342  auto targetX = selectTarget( itemsToAlign, locked_items, []( const ALIGNMENT_RECT& aVal )
343  { return aVal.second.GetCenter().x; } );
344 
345  // Move the selected items
346  for( auto& i : itemsToAlign )
347  {
348  int difference = targetX - i.second.GetCenter().x;
349  BOARD_ITEM* item = i.first;
350 
351  // Don't move a pad by itself unless editing the footprint
352  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
353  item = item->GetParent();
354 
355  item->Move( wxPoint( difference, 0 ) );
356  }
357 
358  commit.Push( _( "Align to middle" ) );
359 
360  return 0;
361 }
362 
363 
365 {
366  ALIGNMENT_RECTS itemsToAlign;
367  ALIGNMENT_RECTS locked_items;
368 
369  if( !GetSelections( itemsToAlign, locked_items, []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
370  { return ( left.second.GetCenter().y < right.second.GetCenter().y ); } ) )
371  return 0;
372 
373  BOARD_COMMIT commit( m_frame );
375  auto targetY = selectTarget( itemsToAlign, locked_items, []( const ALIGNMENT_RECT& aVal )
376  { return aVal.second.GetCenter().y; } );
377 
378  // Move the selected items
379  for( auto& i : itemsToAlign )
380  {
381  int difference = targetY - i.second.GetCenter().y;
382  BOARD_ITEM* item = i.first;
383 
384  // Don't move a pad by itself unless editing the footprint
385  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
386  item = item->GetParent();
387 
388  item->Move( wxPoint( 0, difference ) );
389  }
390 
391  commit.Push( _( "Align to center" ) );
392 
393  return 0;
394 }
395 
396 
398 {
400  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
402 
403  if( selection.Size() <= 1 )
404  return 0;
405 
406  BOARD_COMMIT commit( m_frame );
407  commit.StageItems( selection, CHT_MODIFY );
408 
409  auto itemsToDistribute = GetBoundingBoxes( selection );
410 
411  // find the last item by reverse sorting
412  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
413  [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
414  { return ( left.second.GetRight() > right.second.GetRight() ); } );
415  const auto lastItem = itemsToDistribute.begin()->first;
416 
417  const auto maxRight = itemsToDistribute.begin()->second.GetRight();
418 
419  // sort to get starting order
420  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
421  [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
422  { return ( left.second.GetX() < right.second.GetX() ); } );
423  const auto minX = itemsToDistribute.begin()->second.GetX();
424  auto totalGap = maxRight - minX;
425  int totalWidth = 0;
426 
427  for( auto& i : itemsToDistribute )
428  {
429  totalWidth += i.second.GetWidth();
430  }
431 
432  if( totalGap < totalWidth )
433  {
434  // the width of the items exceeds the gap (overlapping items) -> use center point spacing
435  doDistributeCentersHorizontally( itemsToDistribute );
436  }
437  else
438  {
439  totalGap -= totalWidth;
440  doDistributeGapsHorizontally( itemsToDistribute, lastItem, totalGap );
441  }
442 
443  commit.Push( _( "Distribute horizontally" ) );
444 
445  return 0;
446 }
447 
448 
450  const BOARD_ITEM* lastItem, int totalGap ) const
451 {
452  const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 );
453  auto targetX = itemsToDistribute.begin()->second.GetX();
454 
455  for( auto& i : itemsToDistribute )
456  {
457  BOARD_ITEM* item = i.first;
458 
459  // cover the corner case where the last item is wider than the previous item and gap
460  if( lastItem == item )
461  continue;
462 
463  // Don't move a pad by itself unless editing the footprint
464  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
465  item = item->GetParent();
466 
467  int difference = targetX - i.second.GetX();
468  item->Move( wxPoint( difference, 0 ) );
469  targetX += ( i.second.GetWidth() + itemGap );
470  }
471 }
472 
473 
475 {
476  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
477  [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
478  { return ( left.second.GetCenter().x < right.second.GetCenter().x ); } );
479  const auto totalGap = ( itemsToDistribute.end()-1 )->second.GetCenter().x
480  - itemsToDistribute.begin()->second.GetCenter().x;
481  const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 );
482  auto targetX = itemsToDistribute.begin()->second.GetCenter().x;
483 
484  for( auto& i : itemsToDistribute )
485  {
486  BOARD_ITEM* item = i.first;
487 
488  // Don't move a pad by itself unless editing the footprint
489  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
490  item = item->GetParent();
491 
492  int difference = targetX - i.second.GetCenter().x;
493  item->Move( wxPoint( difference, 0 ) );
494  targetX += ( itemGap );
495  }
496 }
497 
498 
500 {
502  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
504 
505  if( selection.Size() <= 1 )
506  return 0;
507 
508  BOARD_COMMIT commit( m_frame );
509  commit.StageItems( selection, CHT_MODIFY );
510 
511  auto itemsToDistribute = GetBoundingBoxes( selection );
512 
513  // find the last item by reverse sorting
514  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
515  [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
516  { return ( left.second.GetBottom() > right.second.GetBottom() ); } );
517  const auto maxBottom = itemsToDistribute.begin()->second.GetBottom();
518  const auto lastItem = itemsToDistribute.begin()->first;
519 
520  // sort to get starting order
521  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
522  [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
523  { return ( left.second.GetCenter().y < right.second.GetCenter().y ); } );
524  auto minY = itemsToDistribute.begin()->second.GetY();
525 
526  auto totalGap = maxBottom - minY;
527  int totalHeight = 0;
528 
529  for( auto& i : itemsToDistribute )
530  {
531  totalHeight += i.second.GetHeight();
532  }
533 
534  if( totalGap < totalHeight )
535  {
536  // the width of the items exceeds the gap (overlapping items) -> use center point spacing
537  doDistributeCentersVertically( itemsToDistribute );
538  }
539  else
540  {
541  totalGap -= totalHeight;
542  doDistributeGapsVertically( itemsToDistribute, lastItem, totalGap );
543  }
544 
545  commit.Push( _( "Distribute vertically" ) );
546 
547  return 0;
548 }
549 
550 
552  const BOARD_ITEM* lastItem, int totalGap ) const
553 {
554  const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 );
555  auto targetY = itemsToDistribute.begin()->second.GetY();
556 
557  for( auto& i : itemsToDistribute )
558  {
559  BOARD_ITEM* item = i.first;
560 
561  // cover the corner case where the last item is wider than the previous item and gap
562  if( lastItem == item )
563  continue;
564 
565  // Don't move a pad by itself unless editing the footprint
566  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
567  item = item->GetParent();
568 
569  int difference = targetY - i.second.GetY();
570  i.first->Move( wxPoint( 0, difference ) );
571  targetY += ( i.second.GetHeight() + itemGap );
572  }
573 }
574 
575 
577 {
578  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
579  [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
580  { return ( left.second.GetCenter().y < right.second.GetCenter().y ); } );
581  const auto totalGap = ( itemsToDistribute.end()-1 )->second.GetCenter().y
582  - itemsToDistribute.begin()->second.GetCenter().y;
583  const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 );
584  auto targetY = itemsToDistribute.begin()->second.GetCenter().y;
585 
586  for( auto& i : itemsToDistribute )
587  {
588  BOARD_ITEM* item = i.first;
589 
590  // Don't move a pad by itself unless editing the footprint
591  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
592  item = item->GetParent();
593 
594  int difference = targetY - i.second.GetCenter().y;
595  item->Move( wxPoint( 0, difference ) );
596  targetY += ( itemGap );
597  }
598 }
599 
600 
602 {
609 
612 }
static TOOL_ACTION alignRight
Definition: pcb_actions.h:211
void AddMenu(ACTION_MENU *aMenu, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Function AddMenu()
int AlignLeft(const TOOL_EVENT &aEvent)
Function AlignLeft() Sets X coordinate of the selected items to the value of the left-most selected i...
wxMenuItem * Add(const wxString &aLabel, int aId, const BITMAP_OPAQUE *aIcon)
Function Add() Adds a wxWidgets-style entry to the menu.
void doDistributeGapsHorizontally(ALIGNMENT_RECTS &itemsToDistribute, const BOARD_ITEM *lastItem, int totalGap) const
Distributes selected items using an even spacing between their bounding boxes.
int selectTarget(ALIGNMENT_RECTS &aItems, ALIGNMENT_RECTS &aLocked, T aGetValue)
int AlignCenterY(const TOOL_EVENT &aEvent)
Function AlignCenterX() Sets the y coordinate of the midpoint of each of the selected items to the va...
Class ACTION_MENU.
Definition: action_menu.h:43
This file is part of the common library.
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
int AlignCenterX(const TOOL_EVENT &aEvent)
Function AlignCenterX() Sets the x coordinate of the midpoint of each of the selected items to the va...
static SELECTION_CONDITION MoreThan(int aNumber)
Function MoreThan Creates a functor that tests if the number of selected items is greater than the va...
virtual ~ALIGN_DISTRIBUTE_TOOL()
ACTION_MENU * m_placementMenu
Class SELECTION_TOOL.
void doDistributeCentersVertically(ALIGNMENT_RECTS &itemsToDistribute) const
Distributes selected items using an even spacing between the centers of their bounding boxes.
Class that computes missing connections on a PCB.
CONDITIONAL_MENU & GetMenu()
Function GetMenu.
Definition: tool_menu.cpp:46
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:219
static TOOL_ACTION alignCenterY
Definition: pcb_actions.h:213
TOOL_MENU & GetToolMenu()
int AlignBottom(const TOOL_EVENT &aEvent)
Function AlignBottom() Sets Y coordinate of the selected items to the value of the bottom-most select...
class D_PAD, a pad in a footprint
Definition: typeinfo.h:90
static TOOL_ACTION distributeVertically
Definition: pcb_actions.h:215
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Function Go()
ALIGNMENT_RECTS GetBoundingBoxes(const T &sel)
static TOOL_ACTION alignBottom
Definition: pcb_actions.h:209
void SetTool(TOOL_INTERACTIVE *aTool)
Function SetTool() Sets a tool that is the creator of the menu.
PCBNEW_SELECTION & GetSelection()
Function GetSelection()
static TOOL_ACTION distributeHorizontally
Definition: pcb_actions.h:214
int DistributeHorizontally(const TOOL_EVENT &aEvent)
Function DistributeHorizontally() Distributes the selected items along the X axis.
class MODULE, a footprint
Definition: typeinfo.h:89
int doAlignRight()
Aligns selected items using the right edge of their bounding boxes to the right-most item.
int doAlignLeft()
Sets X coordinate of the selected items to the value of the left-most selected item X coordinate.
std::vector< ALIGNMENT_RECT > ALIGNMENT_RECTS
virtual void Move(const wxPoint &aMoveVector)
Function Move move this object.
int AlignTop(const TOOL_EVENT &aEvent)
Function AlignTop() Sets Y coordinate of the selected items to the value of the top-most selected ite...
void SetIcon(const BITMAP_OPAQUE *aIcon)
Function SetIcon() Assigns an icon for the entry.
Definition: action_menu.cpp:68
Class TOOL_EVENT.
Definition: tool_event.h:171
int DistributeVertically(const TOOL_EVENT &aEvent)
Function DistributeVertically() Distributes the selected items along the Y axis.
COMMIT & StageItems(const Range &aRange, CHANGE_TYPE aChangeType)
Definition: commit.h:116
static TOOL_ACTION alignLeft
Definition: pcb_actions.h:210
void doDistributeCentersHorizontally(ALIGNMENT_RECTS &itemsToDistribute) const
Distributes selected items using an even spacing between the centers of their bounding boxes.
static TOOL_ACTION alignTop
Definition: pcb_actions.h:208
#define _(s)
KIGFX::VIEW * getView() const
Function getView()
Definition: tool_base.cpp:36
#define EXCLUDE_TRANSIENTS
Definition: edit_tool.h:55
size_t GetSelections(ALIGNMENT_RECTS &aItems, ALIGNMENT_RECTS &aLocked, T aCompare)
Function GetSelections() Populates two vectors with the sorted selection and sorted locked items Retu...
void SetTitle(const wxString &aTitle) override
Function SetTitle() Sets title for the menu.
Definition: action_menu.cpp:86
PCBNEW_SELECTION & RequestSelection(CLIENT_SELECTION_FILTER aClientFilter, std::vector< BOARD_ITEM * > *aFiltered=nullptr, bool aConfirmLockedItems=false)
Function RequestSelection()
PCB_BASE_FRAME * m_frame
bool IsType(FRAME_T aType) const
std::pair< BOARD_ITEM *, EDA_RECT > ALIGNMENT_RECT
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:240
void setTransitions() override
Sets up handlers for various events.
size_t i
Definition: json11.cpp:649
int Size() const
Returns the number of selected parts.
Definition: selection.h:125
void doDistributeGapsVertically(ALIGNMENT_RECTS &itemsToDistribute, const BOARD_ITEM *lastItem, int totalGap) const
Distributes selected items using an even spacing between their bounding boxes.
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true) override
Executes the changes.
SELECTION_TOOL * m_selectionTool
int AlignRight(const TOOL_EVENT &aEvent)
Function AlignRight() Sets X coordinate of the selected items to the value of the right-most selected...
#define EXCLUDE_LOCKED
Function EditToolSelectionFilter.
Definition: edit_tool.h:53
virtual const EDA_RECT GetBoundingBox() const
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:42
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
BOARD_ITEM_CONTAINER * GetParent() const
void EditToolSelectionFilter(GENERAL_COLLECTOR &aCollector, int aFlags)
Definition: edit_tool.cpp:60
static TOOL_ACTION alignCenterX
Definition: pcb_actions.h:212
KICAD_T Type() const
Function Type()
Definition: base_struct.h:210