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 <tool/tool_manager.h>
29 
30 #include <pcb_edit_frame.h>
31 #include <class_board.h>
32 #include <ratsnest_data.h>
33 #include <board_commit.h>
34 #include <bitmaps.h>
35 
36 #include <confirm.h>
37 #include <menus_helpers.h>
38 
39 // Placement tool
40 TOOL_ACTION PCB_ACTIONS::alignTop( "pcbnew.AlignAndDistribute.alignTop",
41  AS_GLOBAL, 0,
42  _( "Align to Top" ),
43  _( "Aligns selected items to the top edge" ), align_items_top_xpm );
44 
45 TOOL_ACTION PCB_ACTIONS::alignBottom( "pcbnew.AlignAndDistribute.alignBottom",
46  AS_GLOBAL, 0,
47  _( "Align to Bottom" ),
48  _( "Aligns selected items to the bottom edge" ), align_items_bottom_xpm );
49 
50 TOOL_ACTION PCB_ACTIONS::alignLeft( "pcbnew.AlignAndDistribute.alignLeft",
51  AS_GLOBAL, 0,
52  _( "Align to Left" ),
53  _( "Aligns selected items to the left edge" ), align_items_left_xpm );
54 
55 TOOL_ACTION PCB_ACTIONS::alignRight( "pcbnew.AlignAndDistribute.alignRight",
56  AS_GLOBAL, 0,
57  _( "Align to Right" ),
58  _( "Aligns selected items to the right edge" ), align_items_right_xpm );
59 
60 TOOL_ACTION PCB_ACTIONS::alignCenterX( "pcbnew.AlignAndDistribute.alignCenterX",
61  AS_GLOBAL, 0,
62  _( "Align to Middle" ),
63  _( "Aligns selected items to the vertical center" ), align_items_middle_xpm );
64 
65 TOOL_ACTION PCB_ACTIONS::alignCenterY( "pcbnew.AlignAndDistribute.alignCenterY",
66  AS_GLOBAL, 0,
67  _( "Align to Center" ),
68  _( "Aligns selected items to the horizontal center" ), align_items_center_xpm );
69 
70 TOOL_ACTION PCB_ACTIONS::distributeHorizontally( "pcbnew.AlignAndDistribute.distributeHorizontally",
71  AS_GLOBAL, 0,
72  _( "Distribute Horizontally" ),
73  _( "Distributes selected items along the horizontal axis" ), distribute_horizontal_xpm );
74 
75 TOOL_ACTION PCB_ACTIONS::distributeVertically( "pcbnew.AlignAndDistribute.distributeVertically",
76  AS_GLOBAL, 0,
77  _( "Distribute Vertically" ),
78  _( "Distributes selected items along the vertical axis" ), distribute_vertical_xpm );
79 
80 
82  TOOL_INTERACTIVE( "pcbnew.Placement" ), m_selectionTool( NULL ), m_placementMenu( NULL )
83 {
84 }
85 
87 {
88  delete m_placementMenu;
89 }
90 
91 
93 {
94  // Find the selection tool, so they can cooperate
95  m_selectionTool = static_cast<SELECTION_TOOL*>( m_toolMgr->FindTool( "pcbnew.InteractiveSelection" ) );
96 
97  if( !m_selectionTool )
98  {
99  DisplayError( NULL, wxT( "pcbnew.InteractiveSelection tool is not available" ) );
100  return false;
101  }
102 
103  // Create a context menu and make it available through selection tool
105  m_placementMenu->SetIcon( align_items_xpm );
106  m_placementMenu->SetTitle( _( "Align/Distribute" ) );
107 
108  // Add all align/distribute commands
115  m_placementMenu->AppendSeparator();
118 
121 
122  return true;
123 }
124 
125 
126 bool SortLeftmostX( const std::pair<BOARD_ITEM*, EDA_RECT> left, const std::pair<BOARD_ITEM*, EDA_RECT> right)
127 {
128  return ( left.second.GetX() < right.second.GetX() );
129 }
130 
131 
132 bool SortRightmostX( const std::pair<BOARD_ITEM*, EDA_RECT> left, const std::pair<BOARD_ITEM*, EDA_RECT> right)
133 {
134  return ( left.second.GetRight() > right.second.GetRight() );
135 }
136 
137 
138 bool SortTopmostY( const std::pair<BOARD_ITEM*, EDA_RECT> left, const std::pair<BOARD_ITEM*, EDA_RECT> right)
139 {
140  return ( left.second.GetY() < right.second.GetY() );
141 }
142 
143 
144 bool SortCenterX( const std::pair<BOARD_ITEM*, EDA_RECT> left, const std::pair<BOARD_ITEM*, EDA_RECT> right)
145 {
146  return ( left.second.GetCenter().x < right.second.GetCenter().x );
147 }
148 
149 
150 bool SortCenterY( const std::pair<BOARD_ITEM*, EDA_RECT> left, const std::pair<BOARD_ITEM*, EDA_RECT> right)
151 {
152  return ( left.second.GetCenter().y < right.second.GetCenter().y );
153 }
154 
155 
156 bool SortBottommostY( const std::pair<BOARD_ITEM*, EDA_RECT> left, const std::pair<BOARD_ITEM*, EDA_RECT> right)
157 {
158  return ( left.second.GetBottom() > right.second.GetBottom() );
159 }
160 
161 
163 {
164  const SELECTION& selection = sel;
165 
166  ALIGNMENT_RECTS rects;
167 
168  for( auto item : selection )
169  {
170  BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
171 
172  if( item->Type() == PCB_MODULE_T )
173  {
174  rects.emplace_back( std::make_pair( boardItem, static_cast<MODULE*>( item )->GetFootprintRect() ) );
175  }
176  else
177  {
178  rects.emplace_back( std::make_pair( boardItem, item->GetBoundingBox() ) );
179  }
180  }
181  return rects;
182 }
183 
184 
186 {
187  std::set<BOARD_ITEM*> rejected;
188  for( auto i : selection )
189  {
190  auto item = static_cast<BOARD_ITEM*>( i );
191  if( item->Type() == PCB_PAD_T )
192  {
193  MODULE* mod = static_cast<MODULE*>( item->GetParent() );
194 
195  // selection contains both the module and its pads - remove the pads
196  if( mod && selection.Contains( mod ) )
197  rejected.insert( item );
198  }
199  }
200 
201  for( BOARD_ITEM* item : rejected )
202  selection.Remove( item );
203 }
204 
205 
207 {
208  SELECTION moving_items( selection );
209 
210  // Remove the anchor from the list
211  moving_items.Remove( moving_items.Front() );
212 
213  bool containsLocked = false;
214 
215  // Check if the selection contains locked items
216  for( const auto& item : moving_items )
217  {
218  switch ( item->Type() )
219  {
220  case PCB_MODULE_T:
221  if( static_cast< MODULE* >( item )->IsLocked() )
222  containsLocked = true;
223  break;
224 
225  case PCB_PAD_T:
226  case PCB_MODULE_EDGE_T:
227  case PCB_MODULE_TEXT_T:
228  if( static_cast< MODULE* >( item->GetParent() )->IsLocked() )
229  containsLocked = true;
230  break;
231 
232  default: // suppress warnings
233  break;
234  }
235  }
236 
237  if( containsLocked )
238  {
239  if( IsOK( getEditFrame< PCB_EDIT_FRAME >(),
240  _( "Selection contains locked items. Do you want to continue?" ) ) )
241  {
243  }
244  else
245  return SELECTION_LOCKED;
246  }
247 
248  return SELECTION_UNLOCKED;
249 }
250 
251 
253 {
254  auto frame = getEditFrame<PCB_BASE_FRAME>();
256 
257  if( selection.Size() <= 1 )
258  return 0;
259 
260  filterPadsWithModules( selection );
261 
262  auto itemsToAlign = GetBoundingBoxes( selection );
263  std::sort( itemsToAlign.begin(), itemsToAlign.end(), SortTopmostY );
264  if( checkLockedStatus( selection ) == SELECTION_LOCKED )
265  return 0;
266 
267  BOARD_COMMIT commit( frame );
268  commit.StageItems( selection, CHT_MODIFY );
269 
270  // after sorting, the fist item acts as the target for all others
271  const int targetTop = itemsToAlign.begin()->second.GetY();
272 
273  // Move the selected items
274  for( auto& i : itemsToAlign )
275  {
276  int difference = targetTop - i.second.GetY();
277  BOARD_ITEM* item = i.first;
278 
279  // Don't move a pad by itself unless editing the footprint
280  if( item->Type() == PCB_PAD_T && frame->IsType( FRAME_PCB ) )
281  item = item->GetParent();
282 
283  item->Move( wxPoint( 0, difference ) );
284  }
285 
286  commit.Push( _( "Align to top" ) );
287 
288  return 0;
289 }
290 
291 
293 {
294  auto frame = getEditFrame<PCB_BASE_FRAME>();
296 
297  if( selection.Size() <= 1 )
298  return 0;
299 
300  filterPadsWithModules( selection );
301 
302  auto itemsToAlign = GetBoundingBoxes( selection );
303  std::sort( itemsToAlign.begin(), itemsToAlign.end(), SortBottommostY );
304  if( checkLockedStatus( selection ) == SELECTION_LOCKED )
305  return 0;
306 
307  BOARD_COMMIT commit( frame );
308  commit.StageItems( selection, CHT_MODIFY );
309 
310  // after sorting, the fist item acts as the target for all others
311  const int targetBottom = itemsToAlign.begin()->second.GetBottom();
312 
313  // Move the selected items
314  for( auto& i : itemsToAlign )
315  {
316  int difference = targetBottom - i.second.GetBottom();
317  BOARD_ITEM* item = i.first;
318 
319  // Don't move a pad by itself unless editing the footprint
320  if( item->Type() == PCB_PAD_T && frame->IsType( FRAME_PCB ) )
321  item = item->GetParent();
322 
323  item->Move( wxPoint( 0, difference ) );
324  }
325 
326  commit.Push( _( "Align to bottom" ) );
327 
328  return 0;
329 }
330 
331 
333 {
334  // Because this tool uses bounding boxes and they aren't mirrored even when
335  // the view is mirrored, we need to call the other one if mirrored.
336  if( getView()->IsMirroredX() )
337  {
338  return doAlignRight();
339  }
340  else
341  {
342  return doAlignLeft();
343  }
344 }
345 
346 
348 {
349  auto frame = getEditFrame<PCB_BASE_FRAME>();
351 
352  if( selection.Size() <= 1 )
353  return 0;
354 
355  filterPadsWithModules( selection );
356 
357  auto itemsToAlign = GetBoundingBoxes( selection );
358  std::sort( itemsToAlign.begin(), itemsToAlign.end(), SortLeftmostX );
359  if( checkLockedStatus( selection ) == SELECTION_LOCKED )
360  return 0;
361 
362  BOARD_COMMIT commit( frame );
363  commit.StageItems( selection, CHT_MODIFY );
364 
365  // after sorting, the fist item acts as the target for all others
366  const int targetLeft = itemsToAlign.begin()->second.GetX();
367 
368  // Move the selected items
369  for( auto& i : itemsToAlign )
370  {
371  int difference = targetLeft - i.second.GetX();
372  BOARD_ITEM* item = i.first;
373 
374  // Don't move a pad by itself unless editing the footprint
375  if( item->Type() == PCB_PAD_T && frame->IsType( FRAME_PCB ) )
376  item = item->GetParent();
377 
378  item->Move( wxPoint( difference, 0 ) );
379  }
380 
381  commit.Push( _( "Align to left" ) );
382 
383  return 0;
384 }
385 
386 
388 {
389  // Because this tool uses bounding boxes and they aren't mirrored even when
390  // the view is mirrored, we need to call the other one if mirrored.
391  if( getView()->IsMirroredX() )
392  {
393  return doAlignLeft();
394  }
395  else
396  {
397  return doAlignRight();
398  }
399 }
400 
401 
403 {
404  auto frame = getEditFrame<PCB_BASE_FRAME>();
406 
407  if( selection.Size() <= 1 )
408  return 0;
409 
410  filterPadsWithModules( selection );
411 
412  auto itemsToAlign = GetBoundingBoxes( selection );
413  std::sort( itemsToAlign.begin(), itemsToAlign.end(), SortRightmostX );
414  if( checkLockedStatus( selection ) == SELECTION_LOCKED )
415  return 0;
416 
417  BOARD_COMMIT commit( frame );
418  commit.StageItems( selection, CHT_MODIFY );
419 
420  // after sorting, the fist item acts as the target for all others
421  const int targetRight = itemsToAlign.begin()->second.GetRight();
422 
423  // Move the selected items
424  for( auto& i : itemsToAlign )
425  {
426  int difference = targetRight - i.second.GetRight();
427  BOARD_ITEM* item = i.first;
428 
429  // Don't move a pad by itself unless editing the footprint
430  if( item->Type() == PCB_PAD_T && frame->IsType( FRAME_PCB ) )
431  item = item->GetParent();
432 
433  item->Move( wxPoint( difference, 0 ) );
434  }
435 
436  commit.Push( _( "Align to right" ) );
437 
438  return 0;
439 }
440 
441 
443 {
444  auto frame = getEditFrame<PCB_BASE_FRAME>();
446 
447  if( selection.Size() <= 1 )
448  return 0;
449 
450  filterPadsWithModules( selection );
451 
452  auto itemsToAlign = GetBoundingBoxes( selection );
453  std::sort( itemsToAlign.begin(), itemsToAlign.end(), SortCenterX );
454  if( checkLockedStatus( selection ) == SELECTION_LOCKED )
455  return 0;
456 
457  BOARD_COMMIT commit( frame );
458  commit.StageItems( selection, CHT_MODIFY );
459 
460  // after sorting use the center x coordinate of the leftmost item as a target
461  // for all other items
462  const int targetX = itemsToAlign.begin()->second.GetCenter().x;
463 
464  // Move the selected items
465  for( auto& i : itemsToAlign )
466  {
467  int difference = targetX - i.second.GetCenter().x;
468  BOARD_ITEM* item = i.first;
469 
470  // Don't move a pad by itself unless editing the footprint
471  if( item->Type() == PCB_PAD_T && frame->IsType( FRAME_PCB ) )
472  item = item->GetParent();
473 
474  item->Move( wxPoint( difference, 0 ) );
475  }
476 
477  commit.Push( _( "Align to middle" ) );
478 
479  return 0;
480 }
481 
482 
484 {
485  auto frame = getEditFrame<PCB_BASE_FRAME>();
487 
488  if( selection.Size() <= 1 )
489  return 0;
490 
491  filterPadsWithModules( selection );
492 
493  auto itemsToAlign = GetBoundingBoxes( selection );
494  std::sort( itemsToAlign.begin(), itemsToAlign.end(), SortCenterY );
495  if( checkLockedStatus( selection ) == SELECTION_LOCKED )
496  return 0;
497 
498  BOARD_COMMIT commit( frame );
499  commit.StageItems( selection, CHT_MODIFY );
500 
501  // after sorting use the center y coordinate of the top-most item as a target
502  // for all other items
503  const int targetY = itemsToAlign.begin()->second.GetCenter().y;
504 
505  // Move the selected items
506  for( auto& i : itemsToAlign )
507  {
508  int difference = targetY - i.second.GetCenter().y;
509  BOARD_ITEM* item = i.first;
510 
511  // Don't move a pad by itself unless editing the footprint
512  if( item->Type() == PCB_PAD_T && frame->IsType( FRAME_PCB ) )
513  item = item->GetParent();
514 
515  item->Move( wxPoint( 0, difference ) );
516  }
517 
518  commit.Push( _( "Align to center" ) );
519 
520  return 0;
521 }
522 
523 
525 {
526  auto frame = getEditFrame<PCB_BASE_FRAME>();
529 
530  if( selection.Size() <= 1 )
531  return 0;
532 
534  return 0;
535 
536  BOARD_COMMIT commit( frame );
537  commit.StageItems( selection, CHT_MODIFY );
538 
539  auto itemsToDistribute = GetBoundingBoxes( selection );
540 
541  // find the last item by reverse sorting
542  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(), SortRightmostX );
543  const auto lastItem = itemsToDistribute.begin()->first;
544 
545  const auto maxRight = itemsToDistribute.begin()->second.GetRight();
546 
547  // sort to get starting order
548  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(), SortLeftmostX );
549  const auto minX = itemsToDistribute.begin()->second.GetX();
550  auto totalGap = maxRight - minX;
551  int totalWidth = 0;
552 
553  for( auto& i : itemsToDistribute )
554  {
555  totalWidth += i.second.GetWidth();
556  }
557 
558  if( totalGap < totalWidth )
559  {
560  // the width of the items exceeds the gap (overlapping items) -> use center point spacing
561  doDistributeCentersHorizontally( itemsToDistribute );
562  }
563  else
564  {
565  totalGap -= totalWidth;
566  doDistributeGapsHorizontally( itemsToDistribute, lastItem, totalGap );
567  }
568 
569  commit.Push( _( "Distribute horizontally" ) );
570 
571  return 0;
572 }
573 
574 
576  const BOARD_ITEM* lastItem, int totalGap ) const
577 {
578  const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 );
579  auto targetX = itemsToDistribute.begin()->second.GetX();
580 
581  for( auto& i : itemsToDistribute )
582  {
583  // cover the corner case where the last item is wider than the previous item and gap
584  if( lastItem == i.first )
585  continue;
586 
587  int difference = targetX - i.second.GetX();
588  i.first->Move( wxPoint( difference, 0 ) );
589  targetX += ( i.second.GetWidth() + itemGap );
590  }
591 }
592 
593 
595 {
596  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(), SortCenterX );
597  const auto totalGap = ( itemsToDistribute.end()-1 )->second.GetCenter().x
598  - itemsToDistribute.begin()->second.GetCenter().x;
599  const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 );
600  auto targetX = itemsToDistribute.begin()->second.GetCenter().x;
601 
602  for( auto& i : itemsToDistribute )
603  {
604  int difference = targetX - i.second.GetCenter().x;
605  i.first->Move( wxPoint( difference, 0 ) );
606  targetX += ( itemGap );
607  }
608 }
609 
610 
612 {
613  auto frame = getEditFrame<PCB_BASE_FRAME>();
616 
617  if( selection.Size() <= 1 )
618  return 0;
619 
621  return 0;
622 
623  BOARD_COMMIT commit( frame );
624  commit.StageItems( selection, CHT_MODIFY );
625 
626  auto itemsToDistribute = GetBoundingBoxes( selection );
627 
628  // find the last item by reverse sorting
629  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(), SortBottommostY );
630  const auto maxBottom = itemsToDistribute.begin()->second.GetBottom();
631  const auto lastItem = itemsToDistribute.begin()->first;
632 
633  // sort to get starting order
634  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(), SortTopmostY );
635  auto minY = itemsToDistribute.begin()->second.GetY();
636 
637  auto totalGap = maxBottom - minY;
638  int totalHeight = 0;
639 
640  for( auto& i : itemsToDistribute )
641  {
642  totalHeight += i.second.GetHeight();
643  }
644 
645  if( totalGap < totalHeight )
646  {
647  // the width of the items exceeds the gap (overlapping items) -> use center point spacing
648  doDistributeCentersVertically( itemsToDistribute );
649  }
650  else
651  {
652  totalGap -= totalHeight;
653  doDistributeGapsVertically( itemsToDistribute, lastItem, totalGap );
654  }
655 
656  commit.Push( _( "Distribute vertically" ) );
657 
658  return 0;
659 }
660 
661 
663  const BOARD_ITEM* lastItem, int totalGap ) const
664 {
665  const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 );
666  auto targetY = itemsToDistribute.begin()->second.GetY();
667 
668  for( auto& i : itemsToDistribute )
669  {
670  // cover the corner case where the last item is wider than the previous item and gap
671  if( lastItem == i.first )
672  continue;
673 
674  int difference = targetY - i.second.GetY();
675  i.first->Move( wxPoint( 0, difference ) );
676  targetY += ( i.second.GetHeight() + itemGap );
677  }
678 }
679 
680 
682 {
683  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(), SortCenterY );
684  const auto totalGap = ( itemsToDistribute.end()-1 )->second.GetCenter().y
685  - itemsToDistribute.begin()->second.GetCenter().y;
686  const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 );
687  auto targetY = itemsToDistribute.begin()->second.GetCenter().y;
688 
689  for( auto& i : itemsToDistribute )
690  {
691  int difference = targetY - i.second.GetCenter().y;
692  i.first->Move( wxPoint( 0, difference ) );
693  targetY += ( itemGap );
694  }
695 }
696 
697 
699 {
706 
709 }
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:235
KICAD_T Type() const
Function Type()
Definition: base_struct.h:209
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.
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.
SELECTION_LOCK_FLAGS CheckLock()
Checks if the user has agreed to modify locked items for the given selection.
Class that computes missing connections on a PCB.
void filterPadsWithModules(SELECTION &selection)
Remove pads from a multi-unit select that also includes the pads&#39; parents.
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...
EDA_ITEM * Front() const
Definition: selection.h:147
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:241
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:247
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()
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
static TOOL_ACTION alignBottom
Align items to the bottom edge of selection bounding box.
Definition: pcb_actions.h:229
wxMenuItem * Add(const wxString &aLabel, int aId, const BITMAP_OPAQUE *aIcon=NULL)
Function Add() Adds an entry to the menu.
static TOOL_ACTION distributeHorizontally
Distributes items evenly along the horizontal axis.
Definition: pcb_actions.h:244
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:162
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:232
SELECTION & RequestSelection(int aFlags=SELECTION_DEFAULT, CLIENT_SELECTION_FILTER aClientFilter=NULL)
Function RequestSelection()
void Remove(BOARD_ITEM *aItem) override
>
static TOOL_ACTION alignTop
Align items to the top edge of selection bounding box.
Definition: pcb_actions.h:226
All active tools
Definition: tool_event.h:138
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.
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:93
void AddMenu(CONTEXT_MENU *aMenu, bool aExpand=false, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Function AddMenu()
void setTransitions() override
Sets up handlers for various events.
void SetTitle(const wxString &aTitle) override
Function SetTitle() Sets title for the context menu.
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.
int checkLockedStatus(const SELECTION &selection) const
Check a selection to ensure locks are valid for alignment.
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...
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
static TOOL_ACTION alignCenterX
Align items to the middle of selection bounding box.
Definition: pcb_actions.h:238
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:185
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Function IsOK displays a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:233
bool SortCenterX(const std::pair< BOARD_ITEM *, EDA_RECT > left, const std::pair< BOARD_ITEM *, EDA_RECT > right)
#define mod(a, n)
Definition: greymap.cpp:24
bool SortTopmostY(const std::pair< BOARD_ITEM *, EDA_RECT > left, const std::pair< BOARD_ITEM *, EDA_RECT > right)
virtual void Remove(EDA_ITEM *aItem)
Definition: selection.h:79