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, _( "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 template <class T>
132 {
133  ALIGNMENT_RECTS rects;
134 
135  for( auto item : sel )
136  {
137  BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
138 
139  if( item->Type() == PCB_MODULE_T )
140  rects.emplace_back( std::make_pair( boardItem, static_cast<MODULE*>( item )->GetFootprintRect() ) );
141  else
142  rects.emplace_back( std::make_pair( boardItem, item->GetBoundingBox() ) );
143  }
144 
145  return rects;
146 }
147 
148 
149 template< typename T >
151 {
152  wxPoint curPos( getViewControls()->GetCursorPosition().x, getViewControls()->GetCursorPosition().y );
153 
154  // after sorting, the fist item acts as the target for all others
155  // unless we have a locked item, in which case we use that for the target
156  int target = !aLocked.size() ? aGetValue( aItems.front() ): aGetValue( aLocked.front() );
157 
158  // Iterate through both lists to find if we are mouse-over on one of the items.
159  for( auto sel = aLocked.begin(); sel != aItems.end(); sel++ )
160  {
161  // If there are locked items, prefer aligning to them over
162  // aligning to the cursor as they do not move
163  if( sel == aLocked.end() )
164  {
165  if( aLocked.size() == 0 )
166  {
167  sel = aItems.begin();
168  continue;
169  }
170 
171  break;
172  }
173 
174  // We take the first target that overlaps our cursor.
175  // This is deterministic because we assume sorted arrays
176  if( sel->second.Contains( curPos ) )
177  {
178  target = aGetValue( *sel );
179  break;
180  }
181  }
182 
183  return target;
184 }
185 
186 
187 template< typename T >
189 {
190 
192  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
193  { EditToolSelectionFilter( aCollector, EXCLUDE_TRANSIENTS ); } );
194 
195  if( selection.Size() <= 1 )
196  return 0;
197 
198  std::vector<BOARD_ITEM*> lockedItems;
199  selection = m_selectionTool->RequestSelection(
200  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
201  { EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED ); }, &lockedItems );
202 
203  aItems = GetBoundingBoxes( selection );
204  aLocked = GetBoundingBoxes( lockedItems );
205  std::sort( aItems.begin(), aItems.end(), aCompare );
206  std::sort( aLocked.begin(), aLocked.end(), aCompare );
207 
208  return aItems.size();
209 }
210 
211 
213 {
214  ALIGNMENT_RECTS itemsToAlign;
215  ALIGNMENT_RECTS locked_items;
216 
217  if( !GetSelections( itemsToAlign, locked_items, []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
218  { return ( left.second.GetTop() < right.second.GetTop() ); } ) )
219  return 0;
220 
221  BOARD_COMMIT commit( m_frame );
223  auto targetTop = selectTarget( itemsToAlign, locked_items, []( const ALIGNMENT_RECT& aVal )
224  { return aVal.second.GetTop(); } );
225 
226  // Move the selected items
227  for( auto& i : itemsToAlign )
228  {
229  int difference = targetTop - i.second.GetTop();
230  BOARD_ITEM* item = i.first;
231 
232  // Don't move a pad by itself unless editing the footprint
233  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB ) )
234  item = item->GetParent();
235 
236  item->Move( wxPoint( 0, difference ) );
237  }
238 
239  commit.Push( _( "Align to top" ) );
240 
241  return 0;
242 }
243 
244 
246 {
247  ALIGNMENT_RECTS itemsToAlign;
248  ALIGNMENT_RECTS locked_items;
249 
250  if( !GetSelections( itemsToAlign, locked_items, []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
251  { return ( left.second.GetBottom() < right.second.GetBottom() ); } ) )
252  return 0;
253 
254  BOARD_COMMIT commit( m_frame );
256  auto targetBottom = selectTarget( itemsToAlign, locked_items, []( const ALIGNMENT_RECT& aVal )
257  { return aVal.second.GetBottom(); } );
258 
259  // Move the selected items
260  for( auto& i : itemsToAlign )
261  {
262  int difference = targetBottom - i.second.GetBottom();
263  BOARD_ITEM* item = i.first;
264 
265  // Don't move a pad by itself unless editing the footprint
266  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB ) )
267  item = item->GetParent();
268 
269  item->Move( wxPoint( 0, difference ) );
270  }
271 
272  commit.Push( _( "Align to bottom" ) );
273 
274  return 0;
275 }
276 
277 
279 {
280  // Because this tool uses bounding boxes and they aren't mirrored even when
281  // the view is mirrored, we need to call the other one if mirrored.
282  if( getView()->IsMirroredX() )
283  {
284  return doAlignRight();
285  }
286  else
287  {
288  return doAlignLeft();
289  }
290 }
291 
292 
294 {
295  ALIGNMENT_RECTS itemsToAlign;
296  ALIGNMENT_RECTS locked_items;
297 
298  if( !GetSelections( itemsToAlign, locked_items, []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
299  { return ( left.second.GetLeft() < right.second.GetLeft() ); } ) )
300  return 0;
301 
302  BOARD_COMMIT commit( m_frame );
304  auto targetLeft = selectTarget( itemsToAlign, locked_items, []( const ALIGNMENT_RECT& aVal )
305  { return aVal.second.GetLeft(); } );
306 
307  // Move the selected items
308  for( auto& i : itemsToAlign )
309  {
310  int difference = targetLeft - i.second.GetLeft();
311  BOARD_ITEM* item = i.first;
312 
313  // Don't move a pad by itself unless editing the footprint
314  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB ) )
315  item = item->GetParent();
316 
317  item->Move( wxPoint( difference, 0 ) );
318  }
319 
320  commit.Push( _( "Align to left" ) );
321 
322  return 0;
323 }
324 
325 
327 {
328  // Because this tool uses bounding boxes and they aren't mirrored even when
329  // the view is mirrored, we need to call the other one if mirrored.
330  if( getView()->IsMirroredX() )
331  {
332  return doAlignLeft();
333  }
334  else
335  {
336  return doAlignRight();
337  }
338 }
339 
340 
342 {
343  ALIGNMENT_RECTS itemsToAlign;
344  ALIGNMENT_RECTS locked_items;
345 
346  if( !GetSelections( itemsToAlign, locked_items, []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
347  { return ( left.second.GetRight() < right.second.GetRight() ); } ) )
348  return 0;
349 
350  BOARD_COMMIT commit( m_frame );
352  auto targetRight = selectTarget( itemsToAlign, locked_items, []( const ALIGNMENT_RECT& aVal )
353  { return aVal.second.GetRight(); } );
354 
355  // Move the selected items
356  for( auto& i : itemsToAlign )
357  {
358  int difference = targetRight - i.second.GetRight();
359  BOARD_ITEM* item = i.first;
360 
361  // Don't move a pad by itself unless editing the footprint
362  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB ) )
363  item = item->GetParent();
364 
365  item->Move( wxPoint( difference, 0 ) );
366  }
367 
368  commit.Push( _( "Align to right" ) );
369 
370  return 0;
371 }
372 
373 
375 {
376  ALIGNMENT_RECTS itemsToAlign;
377  ALIGNMENT_RECTS locked_items;
378 
379  if( !GetSelections( itemsToAlign, locked_items, []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
380  { return ( left.second.GetCenter().x < right.second.GetCenter().x ); } ) )
381  return 0;
382 
383  BOARD_COMMIT commit( m_frame );
385  auto targetX = selectTarget( itemsToAlign, locked_items, []( const ALIGNMENT_RECT& aVal )
386  { return aVal.second.GetCenter().x; } );
387 
388  // Move the selected items
389  for( auto& i : itemsToAlign )
390  {
391  int difference = targetX - i.second.GetCenter().x;
392  BOARD_ITEM* item = i.first;
393 
394  // Don't move a pad by itself unless editing the footprint
395  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB ) )
396  item = item->GetParent();
397 
398  item->Move( wxPoint( difference, 0 ) );
399  }
400 
401  commit.Push( _( "Align to middle" ) );
402 
403  return 0;
404 }
405 
406 
408 {
409  ALIGNMENT_RECTS itemsToAlign;
410  ALIGNMENT_RECTS locked_items;
411 
412  if( !GetSelections( itemsToAlign, locked_items, []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
413  { return ( left.second.GetCenter().y < right.second.GetCenter().y ); } ) )
414  return 0;
415 
416  BOARD_COMMIT commit( m_frame );
418  auto targetY = selectTarget( itemsToAlign, locked_items, []( const ALIGNMENT_RECT& aVal )
419  { return aVal.second.GetCenter().y; } );
420 
421  // Move the selected items
422  for( auto& i : itemsToAlign )
423  {
424  int difference = targetY - i.second.GetCenter().y;
425  BOARD_ITEM* item = i.first;
426 
427  // Don't move a pad by itself unless editing the footprint
428  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB ) )
429  item = item->GetParent();
430 
431  item->Move( wxPoint( 0, difference ) );
432  }
433 
434  commit.Push( _( "Align to center" ) );
435 
436  return 0;
437 }
438 
439 
441 {
443  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
445 
446  if( selection.Size() <= 1 )
447  return 0;
448 
449  BOARD_COMMIT commit( m_frame );
450  commit.StageItems( selection, CHT_MODIFY );
451 
452  auto itemsToDistribute = GetBoundingBoxes( selection );
453 
454  // find the last item by reverse sorting
455  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
456  [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
457  { return ( left.second.GetRight() > right.second.GetRight() ); } );
458  const auto lastItem = itemsToDistribute.begin()->first;
459 
460  const auto maxRight = itemsToDistribute.begin()->second.GetRight();
461 
462  // sort to get starting order
463  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
464  [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
465  { return ( left.second.GetX() < right.second.GetX() ); } );
466  const auto minX = itemsToDistribute.begin()->second.GetX();
467  auto totalGap = maxRight - minX;
468  int totalWidth = 0;
469 
470  for( auto& i : itemsToDistribute )
471  {
472  totalWidth += i.second.GetWidth();
473  }
474 
475  if( totalGap < totalWidth )
476  {
477  // the width of the items exceeds the gap (overlapping items) -> use center point spacing
478  doDistributeCentersHorizontally( itemsToDistribute );
479  }
480  else
481  {
482  totalGap -= totalWidth;
483  doDistributeGapsHorizontally( itemsToDistribute, lastItem, totalGap );
484  }
485 
486  commit.Push( _( "Distribute horizontally" ) );
487 
488  return 0;
489 }
490 
491 
493  const BOARD_ITEM* lastItem, int totalGap ) const
494 {
495  const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 );
496  auto targetX = itemsToDistribute.begin()->second.GetX();
497 
498  for( auto& i : itemsToDistribute )
499  {
500  BOARD_ITEM* item = i.first;
501 
502  // cover the corner case where the last item is wider than the previous item and gap
503  if( lastItem == item )
504  continue;
505 
506  // Don't move a pad by itself unless editing the footprint
507  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB ) )
508  item = item->GetParent();
509 
510  int difference = targetX - i.second.GetX();
511  item->Move( wxPoint( difference, 0 ) );
512  targetX += ( i.second.GetWidth() + itemGap );
513  }
514 }
515 
516 
518 {
519  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
520  [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
521  { return ( left.second.GetCenter().x < right.second.GetCenter().x ); } );
522  const auto totalGap = ( itemsToDistribute.end()-1 )->second.GetCenter().x
523  - itemsToDistribute.begin()->second.GetCenter().x;
524  const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 );
525  auto targetX = itemsToDistribute.begin()->second.GetCenter().x;
526 
527  for( auto& i : itemsToDistribute )
528  {
529  BOARD_ITEM* item = i.first;
530 
531  // Don't move a pad by itself unless editing the footprint
532  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB ) )
533  item = item->GetParent();
534 
535  int difference = targetX - i.second.GetCenter().x;
536  item->Move( wxPoint( difference, 0 ) );
537  targetX += ( itemGap );
538  }
539 }
540 
541 
543 {
545  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector )
547 
548  if( selection.Size() <= 1 )
549  return 0;
550 
551  BOARD_COMMIT commit( m_frame );
552  commit.StageItems( selection, CHT_MODIFY );
553 
554  auto itemsToDistribute = GetBoundingBoxes( selection );
555 
556  // find the last item by reverse sorting
557  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
558  [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
559  { return ( left.second.GetBottom() > right.second.GetBottom() ); } );
560  const auto maxBottom = itemsToDistribute.begin()->second.GetBottom();
561  const auto lastItem = itemsToDistribute.begin()->first;
562 
563  // sort to get starting order
564  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
565  [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
566  { return ( left.second.GetCenter().y < right.second.GetCenter().y ); } );
567  auto minY = itemsToDistribute.begin()->second.GetY();
568 
569  auto totalGap = maxBottom - minY;
570  int totalHeight = 0;
571 
572  for( auto& i : itemsToDistribute )
573  {
574  totalHeight += i.second.GetHeight();
575  }
576 
577  if( totalGap < totalHeight )
578  {
579  // the width of the items exceeds the gap (overlapping items) -> use center point spacing
580  doDistributeCentersVertically( itemsToDistribute );
581  }
582  else
583  {
584  totalGap -= totalHeight;
585  doDistributeGapsVertically( itemsToDistribute, lastItem, totalGap );
586  }
587 
588  commit.Push( _( "Distribute vertically" ) );
589 
590  return 0;
591 }
592 
593 
595  const BOARD_ITEM* lastItem, int totalGap ) const
596 {
597  const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 );
598  auto targetY = itemsToDistribute.begin()->second.GetY();
599 
600  for( auto& i : itemsToDistribute )
601  {
602  BOARD_ITEM* item = i.first;
603 
604  // cover the corner case where the last item is wider than the previous item and gap
605  if( lastItem == item )
606  continue;
607 
608  // Don't move a pad by itself unless editing the footprint
609  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB ) )
610  item = item->GetParent();
611 
612  int difference = targetY - i.second.GetY();
613  i.first->Move( wxPoint( 0, difference ) );
614  targetY += ( i.second.GetHeight() + itemGap );
615  }
616 }
617 
618 
620 {
621  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
622  [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
623  { return ( left.second.GetCenter().y < right.second.GetCenter().y ); } );
624  const auto totalGap = ( itemsToDistribute.end()-1 )->second.GetCenter().y
625  - itemsToDistribute.begin()->second.GetCenter().y;
626  const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 );
627  auto targetY = itemsToDistribute.begin()->second.GetCenter().y;
628 
629  for( auto& i : itemsToDistribute )
630  {
631  BOARD_ITEM* item = i.first;
632 
633  // Don't move a pad by itself unless editing the footprint
634  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB ) )
635  item = item->GetParent();
636 
637  int difference = targetY - i.second.GetCenter().y;
638  item->Move( wxPoint( 0, difference ) );
639  targetY += ( itemGap );
640  }
641 }
642 
643 
645 {
652 
655 }
static TOOL_ACTION alignRight
Align items to the right edge of selection bounding box.
Definition: pcb_actions.h:243
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...
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 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...
This file is part of the common library.
SELECTION & RequestSelection(CLIENT_SELECTION_FILTER aClientFilter, std::vector< BOARD_ITEM * > *aFiltered=NULL)
Function RequestSelection()
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:249
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
Distributes items evenly along the vertical axis.
Definition: pcb_actions.h:255
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()
ALIGNMENT_RECTS GetBoundingBoxes(const T &sel)
static TOOL_ACTION alignBottom
Align items to the bottom edge of selection bounding box.
Definition: pcb_actions.h:237
static TOOL_ACTION distributeHorizontally
Distributes items evenly along the horizontal axis.
Definition: pcb_actions.h:252
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...
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...
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:240
SELECTION & GetSelection()
Function GetSelection()
static TOOL_ACTION alignTop
Align items to the top edge of selection bounding box.
Definition: pcb_actions.h:234
All active tools
Definition: tool_event.h:144
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:41
#define EXCLUDE_TRANSIENTS
Definition: edit_tool.h:48
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.
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...
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()
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:245
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:46
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:246
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:245