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 // Placement tool
41 TOOL_ACTION PCB_ACTIONS::alignTop( "pcbnew.AlignAndDistribute.alignTop",
42  AS_GLOBAL, 0,
43  _( "Align to Top" ),
44  _( "Aligns selected items to the top edge" ), align_items_top_xpm );
45 
46 TOOL_ACTION PCB_ACTIONS::alignBottom( "pcbnew.AlignAndDistribute.alignBottom",
47  AS_GLOBAL, 0,
48  _( "Align to Bottom" ),
49  _( "Aligns selected items to the bottom edge" ), align_items_bottom_xpm );
50 
51 TOOL_ACTION PCB_ACTIONS::alignLeft( "pcbnew.AlignAndDistribute.alignLeft",
52  AS_GLOBAL, 0,
53  _( "Align to Left" ),
54  _( "Aligns selected items to the left edge" ), align_items_left_xpm );
55 
56 TOOL_ACTION PCB_ACTIONS::alignRight( "pcbnew.AlignAndDistribute.alignRight",
57  AS_GLOBAL, 0,
58  _( "Align to Right" ),
59  _( "Aligns selected items to the right edge" ), align_items_right_xpm );
60 
61 TOOL_ACTION PCB_ACTIONS::alignCenterX( "pcbnew.AlignAndDistribute.alignCenterX",
62  AS_GLOBAL, 0,
63  _( "Align to Middle" ),
64  _( "Aligns selected items to the vertical center" ), align_items_middle_xpm );
65 
66 TOOL_ACTION PCB_ACTIONS::alignCenterY( "pcbnew.AlignAndDistribute.alignCenterY",
67  AS_GLOBAL, 0,
68  _( "Align to Center" ),
69  _( "Aligns selected items to the horizontal center" ), align_items_center_xpm );
70 
71 TOOL_ACTION PCB_ACTIONS::distributeHorizontally( "pcbnew.AlignAndDistribute.distributeHorizontally",
72  AS_GLOBAL, 0,
73  _( "Distribute Horizontally" ),
74  _( "Distributes selected items along the horizontal axis" ), distribute_horizontal_xpm );
75 
76 TOOL_ACTION PCB_ACTIONS::distributeVertically( "pcbnew.AlignAndDistribute.distributeVertically",
77  AS_GLOBAL, 0,
78  _( "Distribute Vertically" ),
79  _( "Distributes selected items along the vertical axis" ), distribute_vertical_xpm );
80 
81 
83  TOOL_INTERACTIVE( "pcbnew.Placement" ), m_selectionTool( NULL ), m_placementMenu( NULL ),
84  m_frame( NULL )
85 {
86 }
87 
89 {
90  delete m_placementMenu;
91 }
92 
93 
95 {
96  // Find the selection tool, so they can cooperate
97  m_selectionTool = static_cast<SELECTION_TOOL*>( m_toolMgr->FindTool( "pcbnew.InteractiveSelection" ) );
98 
99  if( !m_selectionTool )
100  {
101  DisplayError( NULL, wxT( "pcbnew.InteractiveSelection tool is not available" ) );
102  return false;
103  }
104 
105  m_frame = getEditFrame<PCB_BASE_FRAME>();
106 
107  // Create a context menu and make it available through selection tool
109  m_placementMenu->SetIcon( align_items_xpm );
110  m_placementMenu->SetTitle( _( "Align/Distribute" ) );
111 
112  // Add all align/distribute commands
113  m_placementMenu->Add( PCB_ACTIONS::alignTop );
114  m_placementMenu->Add( PCB_ACTIONS::alignBottom );
115  m_placementMenu->Add( PCB_ACTIONS::alignLeft );
116  m_placementMenu->Add( PCB_ACTIONS::alignRight );
117  m_placementMenu->Add( PCB_ACTIONS::alignCenterX );
118  m_placementMenu->Add( PCB_ACTIONS::alignCenterY );
119  m_placementMenu->AppendSeparator();
120  m_placementMenu->Add( PCB_ACTIONS::distributeHorizontally );
121  m_placementMenu->Add( PCB_ACTIONS::distributeVertically );
122 
123  m_selectionTool->GetToolMenu().GetMenu().AddMenu( m_placementMenu, false,
125 
126  return true;
127 }
128 
129 
130 bool SortLeftmostX( const std::pair<BOARD_ITEM*, EDA_RECT> left, const std::pair<BOARD_ITEM*, EDA_RECT> right)
131 {
132  return ( left.second.GetX() < right.second.GetX() );
133 }
134 
135 
136 bool SortRightmostX( const std::pair<BOARD_ITEM*, EDA_RECT> left, const std::pair<BOARD_ITEM*, EDA_RECT> right)
137 {
138  return ( left.second.GetRight() > right.second.GetRight() );
139 }
140 
141 
142 bool SortTopmostY( const std::pair<BOARD_ITEM*, EDA_RECT> left, const std::pair<BOARD_ITEM*, EDA_RECT> right)
143 {
144  return ( left.second.GetY() < right.second.GetY() );
145 }
146 
147 
148 bool SortCenterX( const std::pair<BOARD_ITEM*, EDA_RECT> left, const std::pair<BOARD_ITEM*, EDA_RECT> right)
149 {
150  return ( left.second.GetCenter().x < right.second.GetCenter().x );
151 }
152 
153 
154 bool SortCenterY( const std::pair<BOARD_ITEM*, EDA_RECT> left, const std::pair<BOARD_ITEM*, EDA_RECT> right)
155 {
156  return ( left.second.GetCenter().y < right.second.GetCenter().y );
157 }
158 
159 
160 bool SortBottommostY( const std::pair<BOARD_ITEM*, EDA_RECT> left, const std::pair<BOARD_ITEM*, EDA_RECT> right)
161 {
162  return ( left.second.GetBottom() > right.second.GetBottom() );
163 }
164 
165 
167 {
168  const SELECTION& selection = sel;
169 
170  ALIGNMENT_RECTS rects;
171 
172  for( auto item : selection )
173  {
174  BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
175 
176  if( item->Type() == PCB_MODULE_T )
177  {
178  rects.emplace_back( std::make_pair( boardItem, static_cast<MODULE*>( item )->GetFootprintRect() ) );
179  }
180  else
181  {
182  rects.emplace_back( std::make_pair( boardItem, item->GetBoundingBox() ) );
183  }
184  }
185  return rects;
186 }
187 
188 
190 {
192  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
194 
195  if( selection.Size() <= 1 )
196  return 0;
197 
198  auto itemsToAlign = GetBoundingBoxes( selection );
199  std::sort( itemsToAlign.begin(), itemsToAlign.end(), SortTopmostY );
200 
201  BOARD_COMMIT commit( m_frame );
202  commit.StageItems( selection, CHT_MODIFY );
203 
204  // after sorting, the fist item acts as the target for all others
205  const int targetTop = itemsToAlign.begin()->second.GetY();
206 
207  // Move the selected items
208  for( auto& i : itemsToAlign )
209  {
210  int difference = targetTop - i.second.GetY();
211  BOARD_ITEM* item = i.first;
212 
213  // Don't move a pad by itself unless editing the footprint
214  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB ) )
215  item = item->GetParent();
216 
217  item->Move( wxPoint( 0, difference ) );
218  }
219 
220  commit.Push( _( "Align to top" ) );
221 
222  return 0;
223 }
224 
225 
227 {
229  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
231 
232  if( selection.Size() <= 1 )
233  return 0;
234 
235  auto itemsToAlign = GetBoundingBoxes( selection );
236  std::sort( itemsToAlign.begin(), itemsToAlign.end(), SortBottommostY );
237 
238  BOARD_COMMIT commit( m_frame );
239  commit.StageItems( selection, CHT_MODIFY );
240 
241  // after sorting, the fist item acts as the target for all others
242  const int targetBottom = itemsToAlign.begin()->second.GetBottom();
243 
244  // Move the selected items
245  for( auto& i : itemsToAlign )
246  {
247  int difference = targetBottom - i.second.GetBottom();
248  BOARD_ITEM* item = i.first;
249 
250  // Don't move a pad by itself unless editing the footprint
251  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB ) )
252  item = item->GetParent();
253 
254  item->Move( wxPoint( 0, difference ) );
255  }
256 
257  commit.Push( _( "Align to bottom" ) );
258 
259  return 0;
260 }
261 
262 
264 {
265  // Because this tool uses bounding boxes and they aren't mirrored even when
266  // the view is mirrored, we need to call the other one if mirrored.
267  if( getView()->IsMirroredX() )
268  {
269  return doAlignRight();
270  }
271  else
272  {
273  return doAlignLeft();
274  }
275 }
276 
277 
279 {
281  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
283 
284  if( selection.Size() <= 1 )
285  return 0;
286 
287  auto itemsToAlign = GetBoundingBoxes( selection );
288  std::sort( itemsToAlign.begin(), itemsToAlign.end(), SortLeftmostX );
289 
290  BOARD_COMMIT commit( m_frame );
291  commit.StageItems( selection, CHT_MODIFY );
292 
293  // after sorting, the fist item acts as the target for all others
294  const int targetLeft = itemsToAlign.begin()->second.GetX();
295 
296  // Move the selected items
297  for( auto& i : itemsToAlign )
298  {
299  int difference = targetLeft - i.second.GetX();
300  BOARD_ITEM* item = i.first;
301 
302  // Don't move a pad by itself unless editing the footprint
303  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB ) )
304  item = item->GetParent();
305 
306  item->Move( wxPoint( difference, 0 ) );
307  }
308 
309  commit.Push( _( "Align to left" ) );
310 
311  return 0;
312 }
313 
314 
316 {
317  // Because this tool uses bounding boxes and they aren't mirrored even when
318  // the view is mirrored, we need to call the other one if mirrored.
319  if( getView()->IsMirroredX() )
320  {
321  return doAlignLeft();
322  }
323  else
324  {
325  return doAlignRight();
326  }
327 }
328 
329 
331 {
333  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
335 
336  if( selection.Size() <= 1 )
337  return 0;
338 
339  auto itemsToAlign = GetBoundingBoxes( selection );
340  std::sort( itemsToAlign.begin(), itemsToAlign.end(), SortRightmostX );
341 
342  BOARD_COMMIT commit( m_frame );
343  commit.StageItems( selection, CHT_MODIFY );
344 
345  // after sorting, the fist item acts as the target for all others
346  const int targetRight = itemsToAlign.begin()->second.GetRight();
347 
348  // Move the selected items
349  for( auto& i : itemsToAlign )
350  {
351  int difference = targetRight - i.second.GetRight();
352  BOARD_ITEM* item = i.first;
353 
354  // Don't move a pad by itself unless editing the footprint
355  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB ) )
356  item = item->GetParent();
357 
358  item->Move( wxPoint( difference, 0 ) );
359  }
360 
361  commit.Push( _( "Align to right" ) );
362 
363  return 0;
364 }
365 
366 
368 {
370  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
372 
373  if( selection.Size() <= 1 )
374  return 0;
375 
376  auto itemsToAlign = GetBoundingBoxes( selection );
377  std::sort( itemsToAlign.begin(), itemsToAlign.end(), SortCenterX );
378 
379  BOARD_COMMIT commit( m_frame );
380  commit.StageItems( selection, CHT_MODIFY );
381 
382  // after sorting use the center x coordinate of the leftmost item as a target
383  // for all other items
384  const int targetX = itemsToAlign.begin()->second.GetCenter().x;
385 
386  // Move the selected items
387  for( auto& i : itemsToAlign )
388  {
389  int difference = targetX - i.second.GetCenter().x;
390  BOARD_ITEM* item = i.first;
391 
392  // Don't move a pad by itself unless editing the footprint
393  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB ) )
394  item = item->GetParent();
395 
396  item->Move( wxPoint( difference, 0 ) );
397  }
398 
399  commit.Push( _( "Align to middle" ) );
400 
401  return 0;
402 }
403 
404 
406 {
408  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
410 
411  if( selection.Size() <= 1 )
412  return 0;
413 
414  auto itemsToAlign = GetBoundingBoxes( selection );
415  std::sort( itemsToAlign.begin(), itemsToAlign.end(), SortCenterY );
416 
417  BOARD_COMMIT commit( m_frame );
418  commit.StageItems( selection, CHT_MODIFY );
419 
420  // after sorting use the center y coordinate of the top-most item as a target
421  // for all other items
422  const int targetY = itemsToAlign.begin()->second.GetCenter().y;
423 
424  // Move the selected items
425  for( auto& i : itemsToAlign )
426  {
427  int difference = targetY - i.second.GetCenter().y;
428  BOARD_ITEM* item = i.first;
429 
430  // Don't move a pad by itself unless editing the footprint
431  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB ) )
432  item = item->GetParent();
433 
434  item->Move( wxPoint( 0, difference ) );
435  }
436 
437  commit.Push( _( "Align to center" ) );
438 
439  return 0;
440 }
441 
442 
444 {
446  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
448 
449  if( selection.Size() <= 1 )
450  return 0;
451 
452  BOARD_COMMIT commit( m_frame );
453  commit.StageItems( selection, CHT_MODIFY );
454 
455  auto itemsToDistribute = GetBoundingBoxes( selection );
456 
457  // find the last item by reverse sorting
458  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(), SortRightmostX );
459  const auto lastItem = itemsToDistribute.begin()->first;
460 
461  const auto maxRight = itemsToDistribute.begin()->second.GetRight();
462 
463  // sort to get starting order
464  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(), SortLeftmostX );
465  const auto minX = itemsToDistribute.begin()->second.GetX();
466  auto totalGap = maxRight - minX;
467  int totalWidth = 0;
468 
469  for( auto& i : itemsToDistribute )
470  {
471  totalWidth += i.second.GetWidth();
472  }
473 
474  if( totalGap < totalWidth )
475  {
476  // the width of the items exceeds the gap (overlapping items) -> use center point spacing
477  doDistributeCentersHorizontally( itemsToDistribute );
478  }
479  else
480  {
481  totalGap -= totalWidth;
482  doDistributeGapsHorizontally( itemsToDistribute, lastItem, totalGap );
483  }
484 
485  commit.Push( _( "Distribute horizontally" ) );
486 
487  return 0;
488 }
489 
490 
492  const BOARD_ITEM* lastItem, int totalGap ) const
493 {
494  const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 );
495  auto targetX = itemsToDistribute.begin()->second.GetX();
496 
497  for( auto& i : itemsToDistribute )
498  {
499  BOARD_ITEM* item = i.first;
500 
501  // cover the corner case where the last item is wider than the previous item and gap
502  if( lastItem == item )
503  continue;
504 
505  // Don't move a pad by itself unless editing the footprint
506  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB ) )
507  item = item->GetParent();
508 
509  int difference = targetX - i.second.GetX();
510  item->Move( wxPoint( difference, 0 ) );
511  targetX += ( i.second.GetWidth() + itemGap );
512  }
513 }
514 
515 
517 {
518  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(), SortCenterX );
519  const auto totalGap = ( itemsToDistribute.end()-1 )->second.GetCenter().x
520  - itemsToDistribute.begin()->second.GetCenter().x;
521  const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 );
522  auto targetX = itemsToDistribute.begin()->second.GetCenter().x;
523 
524  for( auto& i : itemsToDistribute )
525  {
526  BOARD_ITEM* item = i.first;
527 
528  // Don't move a pad by itself unless editing the footprint
529  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB ) )
530  item = item->GetParent();
531 
532  int difference = targetX - i.second.GetCenter().x;
533  item->Move( wxPoint( difference, 0 ) );
534  targetX += ( itemGap );
535  }
536 }
537 
538 
540 {
542  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
544 
545  if( selection.Size() <= 1 )
546  return 0;
547 
548  BOARD_COMMIT commit( m_frame );
549  commit.StageItems( selection, CHT_MODIFY );
550 
551  auto itemsToDistribute = GetBoundingBoxes( selection );
552 
553  // find the last item by reverse sorting
554  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(), SortBottommostY );
555  const auto maxBottom = itemsToDistribute.begin()->second.GetBottom();
556  const auto lastItem = itemsToDistribute.begin()->first;
557 
558  // sort to get starting order
559  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(), SortTopmostY );
560  auto minY = itemsToDistribute.begin()->second.GetY();
561 
562  auto totalGap = maxBottom - minY;
563  int totalHeight = 0;
564 
565  for( auto& i : itemsToDistribute )
566  {
567  totalHeight += i.second.GetHeight();
568  }
569 
570  if( totalGap < totalHeight )
571  {
572  // the width of the items exceeds the gap (overlapping items) -> use center point spacing
573  doDistributeCentersVertically( itemsToDistribute );
574  }
575  else
576  {
577  totalGap -= totalHeight;
578  doDistributeGapsVertically( itemsToDistribute, lastItem, totalGap );
579  }
580 
581  commit.Push( _( "Distribute vertically" ) );
582 
583  return 0;
584 }
585 
586 
588  const BOARD_ITEM* lastItem, int totalGap ) const
589 {
590  const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 );
591  auto targetY = itemsToDistribute.begin()->second.GetY();
592 
593  for( auto& i : itemsToDistribute )
594  {
595  BOARD_ITEM* item = i.first;
596 
597  // cover the corner case where the last item is wider than the previous item and gap
598  if( lastItem == item )
599  continue;
600 
601  // Don't move a pad by itself unless editing the footprint
602  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB ) )
603  item = item->GetParent();
604 
605  int difference = targetY - i.second.GetY();
606  i.first->Move( wxPoint( 0, difference ) );
607  targetY += ( i.second.GetHeight() + itemGap );
608  }
609 }
610 
611 
613 {
614  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(), SortCenterY );
615  const auto totalGap = ( itemsToDistribute.end()-1 )->second.GetCenter().y
616  - itemsToDistribute.begin()->second.GetCenter().y;
617  const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 );
618  auto targetY = itemsToDistribute.begin()->second.GetCenter().y;
619 
620  for( auto& i : itemsToDistribute )
621  {
622  BOARD_ITEM* item = i.first;
623 
624  // Don't move a pad by itself unless editing the footprint
625  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB ) )
626  item = item->GetParent();
627 
628  int difference = targetY - i.second.GetCenter().y;
629  item->Move( wxPoint( 0, difference ) );
630  targetY += ( itemGap );
631  }
632 }
633 
634 
636 {
643 
646 }
bool SortRightmostX(const std::pair< BOARD_ITEM *, EDA_RECT > left, const std::pair< BOARD_ITEM *, EDA_RECT > right)
static TOOL_ACTION alignRight
Align items to the right edge of selection bounding box.
Definition: pcb_actions.h:238
KICAD_T Type() const
Function Type()
Definition: base_struct.h:201
int AlignLeft(const TOOL_EVENT &aEvent)
Function AlignLeft() Sets X coordinate of the selected items to the value of the left-most selected i...
bool SortLeftmostX(const std::pair< BOARD_ITEM *, EDA_RECT > left, const std::pair< BOARD_ITEM *, EDA_RECT > right)
BOARD_ITEM_CONTAINER * GetParent() const
virtual const EDA_RECT GetBoundingBox() const
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes...
TOOL_BASE * FindTool(int aId) const
Function FindTool() Searches for a tool with given ID.
SELECTION & RequestSelection(CLIENT_SELECTION_FILTER aClientFilter)
Function RequestSelection()
int AlignCenterY(const TOOL_EVENT &aEvent)
Function AlignCenterX() Sets the y coordinate of the midpoint of each of the selected items to the va...
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...
Class CONTEXT_MENU.
Definition: context_menu.h:44
virtual ~ALIGN_DISTRIBUTE_TOOL()
Class SELECTION_TOOL.
Class BOARD to handle a board.
Class that computes missing connections on a PCB.
CONDITIONAL_MENU & GetMenu()
Function GetMenu.
Definition: tool_menu.cpp:49
void doDistributeCentersHorizontally(ALIGNMENT_RECTS &itemsToDistribute) const
Distributes selected items using an even spacing between the centers of their bounding boxes...
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:215
static TOOL_ACTION alignCenterY
Align items to the center of selection bounding box.
Definition: pcb_actions.h:244
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
std::vector< std::pair< BOARD_ITEM *, EDA_RECT > > ALIGNMENT_RECTS
static TOOL_ACTION distributeVertically
Distributes items evenly along the vertical axis.
Definition: pcb_actions.h:250
ALIGNMENT_RECTS GetBoundingBoxes(const SELECTION &sel)
void doDistributeCentersVertically(ALIGNMENT_RECTS &itemsToDistribute) const
Distributes selected items using an even spacing between the centers of their bounding boxes...
CONTEXT_MENU * m_placementMenu
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Function Go()
static TOOL_ACTION alignBottom
Align items to the bottom edge of selection bounding box.
Definition: pcb_actions.h:232
static TOOL_ACTION distributeHorizontally
Distributes items evenly along the horizontal axis.
Definition: pcb_actions.h:247
int DistributeHorizontally(const TOOL_EVENT &aEvent)
Function DistributeHorizontally() Distributes the selected items along the X axis.
void doDistributeGapsVertically(ALIGNMENT_RECTS &itemsToDistribute, const BOARD_ITEM *lastItem, int totalGap) const
Distributes selected items using an even spacing between their bounding boxes.
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...
bool SortBottommostY(const std::pair< BOARD_ITEM *, EDA_RECT > left, const std::pair< BOARD_ITEM *, EDA_RECT > right)
bool SortCenterY(const std::pair< BOARD_ITEM *, EDA_RECT > left, const std::pair< BOARD_ITEM *, EDA_RECT > right)
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...
Class TOOL_EVENT.
Definition: tool_event.h:168
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
Align items to the left edge of selection bounding box.
Definition: pcb_actions.h:235
static TOOL_ACTION alignTop
Align items to the top edge of selection bounding box.
Definition: pcb_actions.h:229
All active tools
Definition: tool_event.h:144
#define EXCLUDE_TRANSIENTS
Definition: edit_tool.h:47
KIGFX::VIEW * getView() const
Function getView()
Definition: tool_base.cpp:35
void SetIcon(const BITMAP_OPAQUE *aIcon)
Function SetIcon() Assigns an icon for the entry.
PCB_BASE_FRAME * m_frame
void AddMenu(CONTEXT_MENU *aMenu, bool aExpand=false, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Function AddMenu()
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:242
void setTransitions() override
Sets up handlers for various events.
Class TOOL_ACTION.
Definition: tool_action.h:46
size_t i
Definition: json11.cpp:597
void doDistributeGapsHorizontally(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...
int Size() const
Returns the number of selected parts.
Definition: selection.h:122
bool IsType(FRAME_T aType) const
#define EXCLUDE_LOCKED
Function EditToolSelectionFilter.
Definition: edit_tool.h:45
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
void EditToolSelectionFilter(GENERAL_COLLECTOR &aCollector, int aFlags)
Definition: edit_tool.cpp:173
static TOOL_ACTION alignCenterX
Align items to the middle of selection bounding box.
Definition: pcb_actions.h:241
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:245
bool SortCenterX(const std::pair< BOARD_ITEM *, EDA_RECT > left, const std::pair< BOARD_ITEM *, EDA_RECT > right)
bool SortTopmostY(const std::pair< BOARD_ITEM *, EDA_RECT > left, const std::pair< BOARD_ITEM *, EDA_RECT > right)