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 "pcb_selection_tool.h"
28 
29 #include <ratsnest/ratsnest_data.h>
30 #include <tool/tool_manager.h>
31 
32 #include <pcb_edit_frame.h>
33 #include <board.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  m_frame = getEditFrame<PCB_BASE_FRAME>();
58 
59  // Create a context menu and make it available through selection tool
60  m_placementMenu = new ACTION_MENU( true );
61  m_placementMenu->SetTool( this );
63  m_placementMenu->SetTitle( _( "Align/Distribute" ) );
64 
65  // Add all align/distribute commands
69 
70  m_placementMenu->AppendSeparator();
74 
75  m_placementMenu->AppendSeparator();
78 
81 
82  return true;
83 }
84 
85 
86 template <class T>
88 {
89  ALIGNMENT_RECTS rects;
90 
91  for( EDA_ITEM* item : aItems )
92  {
93  BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
94 
95  if( item->Type() == PCB_FOOTPRINT_T )
96  {
97  FOOTPRINT* footprint = static_cast<FOOTPRINT*>( item );
98  rects.emplace_back( std::make_pair( boardItem,
99  footprint->GetBoundingBox( false, false ) ) );
100  }
101  else
102  {
103  rects.emplace_back( std::make_pair( boardItem, item->GetBoundingBox() ) );
104  }
105  }
106 
107  return rects;
108 }
109 
110 
111 template< typename T >
113  T aGetValue )
114 {
115  wxPoint curPos = (wxPoint) getViewControls()->GetCursorPosition();
116 
117  // Prefer locked items to unlocked items.
118  // Secondly, prefer items under the cursor to other items.
119 
120  if( aLocked.size() >= 1 )
121  {
122  for( const ALIGNMENT_RECT& item : aLocked )
123  {
124  if( item.second.Contains( curPos ) )
125  return aGetValue( item );
126  }
127 
128  return aGetValue( aLocked.front() );
129  }
130 
131  for( const ALIGNMENT_RECT& item : aItems )
132  {
133  if( item.second.Contains( curPos ) )
134  return aGetValue( item );
135  }
136 
137  return aGetValue( aItems.front() );
138 }
139 
140 
141 template< typename T >
143  ALIGNMENT_RECTS& aLockedItems, T aCompare )
144 {
146  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
147  {
148  // Iterate from the back so we don't have to worry about removals.
149  for( int i = aCollector.GetCount() - 1; i >= 0; --i )
150  {
151  BOARD_ITEM* item = aCollector[i];
152 
153  if( item->Type() == PCB_MARKER_T )
154  aCollector.Remove( item );
155  }
156  } );
157 
158  std::vector<BOARD_ITEM*> lockedItems;
159  std::vector<BOARD_ITEM*> itemsToAlign;
160 
161  for( EDA_ITEM* item : selection )
162  {
163  BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
164 
165  if( boardItem->IsLocked() )
166  {
167  // Locking a pad but not the footprint means that we align the footprint using
168  // the pad position. So we test for footprint locking here
169  if( m_frame->IsType( FRAME_PCB_EDITOR ) && boardItem->Type() == PCB_PAD_T
170  && !boardItem->GetParent()->IsLocked() )
171  {
172  itemsToAlign.push_back( boardItem );
173  }
174  else
175  {
176  lockedItems.push_back( boardItem );
177  }
178  }
179  else
180  itemsToAlign.push_back( boardItem );
181  }
182 
183  aItemsToAlign = GetBoundingBoxes( itemsToAlign );
184  aLockedItems = GetBoundingBoxes( lockedItems );
185  std::sort( aItemsToAlign.begin(), aItemsToAlign.end(), aCompare );
186  std::sort( aLockedItems.begin(), aLockedItems.end(), aCompare );
187 
188  return aItemsToAlign.size();
189 }
190 
191 
193 {
194  ALIGNMENT_RECTS itemsToAlign;
195  ALIGNMENT_RECTS locked_items;
196 
197  if( !GetSelections( itemsToAlign, locked_items,
198  []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
199  {
200  return ( left.second.GetTop() < right.second.GetTop() );
201  } ) )
202  {
203  return 0;
204  }
205 
206  BOARD_COMMIT commit( m_frame );
207 
208  int targetTop = selectTarget( itemsToAlign, locked_items,
209  []( const ALIGNMENT_RECT& aVal )
210  {
211  return aVal.second.GetTop();
212  } );
213 
214  // Move the selected items
215  for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToAlign )
216  {
217  int difference = targetTop - i.second.GetTop();
218  BOARD_ITEM* item = i.first;
219 
220  // Don't move a pad by itself unless editing the footprint
221  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
222  item = item->GetParent();
223 
224  commit.Stage( item, CHT_MODIFY );
225  item->Move( wxPoint( 0, difference ) );
226  }
227 
228  commit.Push( _( "Align to top" ) );
229 
230  return 0;
231 }
232 
233 
235 {
236  ALIGNMENT_RECTS itemsToAlign;
237  ALIGNMENT_RECTS locked_items;
238 
239  if( !GetSelections( itemsToAlign, locked_items,
240  []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
241  {
242  return ( left.second.GetBottom() < right.second.GetBottom() );
243  } ) )
244  {
245  return 0;
246  }
247 
248  BOARD_COMMIT commit( m_frame );
249 
250  int targetBottom = selectTarget( itemsToAlign, locked_items,
251  []( const ALIGNMENT_RECT& aVal )
252  {
253  return aVal.second.GetBottom();
254  } );
255 
256  // Move the selected items
257  for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToAlign )
258  {
259  int difference = targetBottom - i.second.GetBottom();
260  BOARD_ITEM* item = i.first;
261 
262  // Don't move a pad by itself unless editing the footprint
263  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
264  item = item->GetParent();
265 
266  commit.Stage( item, CHT_MODIFY );
267  item->Move( wxPoint( 0, difference ) );
268  }
269 
270  commit.Push( _( "Align to bottom" ) );
271 
272  return 0;
273 }
274 
275 
277 {
278  // Because this tool uses bounding boxes and they aren't mirrored even when
279  // the view is mirrored, we need to call the other one if mirrored.
280  if( getView()->IsMirroredX() )
281  {
282  return doAlignRight();
283  }
284  else
285  {
286  return doAlignLeft();
287  }
288 }
289 
290 
292 {
293  ALIGNMENT_RECTS itemsToAlign;
294  ALIGNMENT_RECTS locked_items;
295 
296  if( !GetSelections( itemsToAlign, locked_items,
297  []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
298  {
299  return ( left.second.GetLeft() < right.second.GetLeft() );
300  } ) )
301  {
302  return 0;
303  }
304 
305  BOARD_COMMIT commit( m_frame );
306 
307  int targetLeft = selectTarget( itemsToAlign, locked_items,
308  []( const ALIGNMENT_RECT& aVal )
309  {
310  return aVal.second.GetLeft();
311  } );
312 
313  // Move the selected items
314  for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToAlign )
315  {
316  int difference = targetLeft - i.second.GetLeft();
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 && m_frame->IsType( FRAME_PCB_EDITOR ) )
321  item = item->GetParent();
322 
323  commit.Stage( item, CHT_MODIFY );
324  item->Move( wxPoint( difference, 0 ) );
325  }
326 
327  commit.Push( _( "Align to left" ) );
328 
329  return 0;
330 }
331 
332 
334 {
335  // Because this tool uses bounding boxes and they aren't mirrored even when
336  // the view is mirrored, we need to call the other one if mirrored.
337  if( getView()->IsMirroredX() )
338  {
339  return doAlignLeft();
340  }
341  else
342  {
343  return doAlignRight();
344  }
345 }
346 
347 
349 {
350  ALIGNMENT_RECTS itemsToAlign;
351  ALIGNMENT_RECTS locked_items;
352 
353  if( !GetSelections( itemsToAlign, locked_items,
354  []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
355  {
356  return ( left.second.GetRight() < right.second.GetRight() );
357  } ) )
358  {
359  return 0;
360  }
361 
362  BOARD_COMMIT commit( m_frame );
363 
364  int targetRight = selectTarget( itemsToAlign, locked_items,
365  []( const ALIGNMENT_RECT& aVal )
366  {
367  return aVal.second.GetRight();
368  } );
369 
370  // Move the selected items
371  for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToAlign )
372  {
373  int difference = targetRight - i.second.GetRight();
374  BOARD_ITEM* item = i.first;
375 
376  // Don't move a pad by itself unless editing the footprint
377  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
378  item = item->GetParent();
379 
380  commit.Stage( item, CHT_MODIFY );
381  item->Move( wxPoint( difference, 0 ) );
382  }
383 
384  commit.Push( _( "Align to right" ) );
385 
386  return 0;
387 }
388 
389 
391 {
392  ALIGNMENT_RECTS itemsToAlign;
393  ALIGNMENT_RECTS locked_items;
394 
395  if( !GetSelections( itemsToAlign, locked_items,
396  []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
397  {
398  return ( left.second.GetCenter().x < right.second.GetCenter().x );
399  } ) )
400  {
401  return 0;
402  }
403 
404  BOARD_COMMIT commit( m_frame );
405 
406  int targetX = selectTarget( itemsToAlign, locked_items,
407  []( const ALIGNMENT_RECT& aVal )
408  {
409  return aVal.second.GetCenter().x;
410  } );
411 
412  // Move the selected items
413  for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToAlign )
414  {
415  int difference = targetX - i.second.GetCenter().x;
416  BOARD_ITEM* item = i.first;
417 
418  // Don't move a pad by itself unless editing the footprint
419  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
420  item = item->GetParent();
421 
422  commit.Stage( item, CHT_MODIFY );
423  item->Move( wxPoint( difference, 0 ) );
424  }
425 
426  commit.Push( _( "Align to middle" ) );
427 
428  return 0;
429 }
430 
431 
433 {
434  ALIGNMENT_RECTS itemsToAlign;
435  ALIGNMENT_RECTS locked_items;
436 
437  if( !GetSelections( itemsToAlign, locked_items,
438  []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
439  {
440  return ( left.second.GetCenter().y < right.second.GetCenter().y );
441  } ) )
442  {
443  return 0;
444  }
445 
446  BOARD_COMMIT commit( m_frame );
447 
448  int targetY = selectTarget( itemsToAlign, locked_items,
449  []( const ALIGNMENT_RECT& aVal )
450  {
451  return aVal.second.GetCenter().y;
452  } );
453 
454  // Move the selected items
455  for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToAlign )
456  {
457  int difference = targetY - i.second.GetCenter().y;
458  BOARD_ITEM* item = i.first;
459 
460  // Don't move a pad by itself unless editing the footprint
461  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
462  item = item->GetParent();
463 
464  commit.Stage( item, CHT_MODIFY );
465  item->Move( wxPoint( 0, difference ) );
466  }
467 
468  commit.Push( _( "Align to center" ) );
469 
470  return 0;
471 }
472 
473 
475 {
477  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
478  {
479  // Iterate from the back so we don't have to worry about removals.
480  for( int i = aCollector.GetCount() - 1; i >= 0; --i )
481  {
482  BOARD_ITEM* item = aCollector[i];
483 
484  if( item->Type() == PCB_MARKER_T )
485  aCollector.Remove( item );
486  }
487  },
488  m_frame->IsType( FRAME_PCB_EDITOR ) /* prompt user regarding locked items */ );
489 
490  if( selection.Size() <= 1 )
491  return 0;
492 
493  BOARD_COMMIT commit( m_frame );
494  ALIGNMENT_RECTS itemsToDistribute = GetBoundingBoxes( selection );
495 
496  // find the last item by reverse sorting
497  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
498  [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
499  {
500  return ( left.second.GetRight() > right.second.GetRight() );
501  } );
502 
503  BOARD_ITEM* lastItem = itemsToDistribute.begin()->first;
504  const int maxRight = itemsToDistribute.begin()->second.GetRight();
505 
506  // sort to get starting order
507  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
508  [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
509  {
510  return ( left.second.GetX() < right.second.GetX() );
511  } );
512 
513  const int minX = itemsToDistribute.begin()->second.GetX();
514  int totalGap = maxRight - minX;
515  int totalWidth = 0;
516 
517  for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToDistribute )
518  totalWidth += i.second.GetWidth();
519 
520  if( totalGap < totalWidth )
521  {
522  // the width of the items exceeds the gap (overlapping items) -> use center point spacing
523  doDistributeCentersHorizontally( itemsToDistribute, commit );
524  }
525  else
526  {
527  totalGap -= totalWidth;
528  doDistributeGapsHorizontally( itemsToDistribute, commit, lastItem, totalGap );
529  }
530 
531  commit.Push( _( "Distribute horizontally" ) );
532 
533  return 0;
534 }
535 
536 
538  BOARD_COMMIT& aCommit,
539  const BOARD_ITEM* lastItem,
540  int totalGap ) const
541 {
542  const int itemGap = totalGap / ( itemsToDistribute.size() - 1 );
543  int targetX = itemsToDistribute.begin()->second.GetX();
544 
545  for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToDistribute )
546  {
547  BOARD_ITEM* item = i.first;
548 
549  // cover the corner case where the last item is wider than the previous item and gap
550  if( lastItem == item )
551  continue;
552 
553  // Don't move a pad by itself unless editing the footprint
554  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
555  item = item->GetParent();
556 
557  int difference = targetX - i.second.GetX();
558  aCommit.Stage( item, CHT_MODIFY );
559  item->Move( wxPoint( difference, 0 ) );
560  targetX += ( i.second.GetWidth() + itemGap );
561  }
562 }
563 
564 
566  BOARD_COMMIT& aCommit ) const
567 {
568  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
569  [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
570  {
571  return ( left.second.GetCenter().x < right.second.GetCenter().x );
572  } );
573 
574  const int totalGap = ( itemsToDistribute.end()-1 )->second.GetCenter().x
575  - itemsToDistribute.begin()->second.GetCenter().x;
576  const int itemGap = totalGap / ( itemsToDistribute.size() - 1 );
577  int targetX = itemsToDistribute.begin()->second.GetCenter().x;
578 
579  for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToDistribute )
580  {
581  BOARD_ITEM* item = i.first;
582 
583  // Don't move a pad by itself unless editing the footprint
584  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
585  item = item->GetParent();
586 
587  int difference = targetX - i.second.GetCenter().x;
588  aCommit.Stage( item, CHT_MODIFY );
589  item->Move( wxPoint( difference, 0 ) );
590  targetX += ( itemGap );
591  }
592 }
593 
594 
596 {
598  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
599  {
600  // Iterate from the back so we don't have to worry about removals.
601  for( int i = aCollector.GetCount() - 1; i >= 0; --i )
602  {
603  BOARD_ITEM* item = aCollector[i];
604 
605  if( item->Type() == PCB_MARKER_T )
606  aCollector.Remove( item );
607  }
608  },
609  m_frame->IsType( FRAME_PCB_EDITOR ) /* prompt user regarding locked items */ );
610 
611  if( selection.Size() <= 1 )
612  return 0;
613 
614  BOARD_COMMIT commit( m_frame );
615  ALIGNMENT_RECTS itemsToDistribute = GetBoundingBoxes( selection );
616 
617  // find the last item by reverse sorting
618  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
619  [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
620  {
621  return ( left.second.GetBottom() > right.second.GetBottom() );
622  } );
623 
624  BOARD_ITEM* lastItem = itemsToDistribute.begin()->first;
625  const int maxBottom = itemsToDistribute.begin()->second.GetBottom();
626 
627  // sort to get starting order
628  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
629  [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
630  {
631  return ( left.second.GetCenter().y < right.second.GetCenter().y );
632  } );
633 
634  int minY = itemsToDistribute.begin()->second.GetY();
635  int totalGap = maxBottom - minY;
636  int totalHeight = 0;
637 
638  for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToDistribute )
639  totalHeight += i.second.GetHeight();
640 
641  if( totalGap < totalHeight )
642  {
643  // the width of the items exceeds the gap (overlapping items) -> use center point spacing
644  doDistributeCentersVertically( itemsToDistribute, commit );
645  }
646  else
647  {
648  totalGap -= totalHeight;
649  doDistributeGapsVertically( itemsToDistribute, commit, lastItem, totalGap );
650  }
651 
652  commit.Push( _( "Distribute vertically" ) );
653 
654  return 0;
655 }
656 
657 
659  BOARD_COMMIT& aCommit,
660  const BOARD_ITEM* lastItem,
661  int totalGap ) const
662 {
663  const int itemGap = totalGap / ( itemsToDistribute.size() - 1 );
664  int targetY = itemsToDistribute.begin()->second.GetY();
665 
666  for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToDistribute )
667  {
668  BOARD_ITEM* item = i.first;
669 
670  // cover the corner case where the last item is wider than the previous item and gap
671  if( lastItem == item )
672  continue;
673 
674  // Don't move a pad by itself unless editing the footprint
675  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
676  item = item->GetParent();
677 
678  int difference = targetY - i.second.GetY();
679  aCommit.Stage( item, CHT_MODIFY );
680  item->Move( wxPoint( 0, difference ) );
681  targetY += ( i.second.GetHeight() + itemGap );
682  }
683 }
684 
685 
687  BOARD_COMMIT& aCommit ) const
688 {
689  std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
690  [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
691  {
692  return ( left.second.GetCenter().y < right.second.GetCenter().y );
693  } );
694 
695  const int totalGap = ( itemsToDistribute.end()-1 )->second.GetCenter().y
696  - itemsToDistribute.begin()->second.GetCenter().y;
697  const int itemGap = totalGap / ( itemsToDistribute.size() - 1 );
698  int targetY = itemsToDistribute.begin()->second.GetCenter().y;
699 
700  for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToDistribute )
701  {
702  BOARD_ITEM* item = i.first;
703 
704  // Don't move a pad by itself unless editing the footprint
705  if( item->Type() == PCB_PAD_T && m_frame->IsType( FRAME_PCB_EDITOR ) )
706  item = item->GetParent();
707 
708  int difference = targetY - i.second.GetCenter().y;
709  aCommit.Stage( item, CHT_MODIFY );
710  item->Move( wxPoint( 0, difference ) );
711  targetY += ( itemGap );
712  }
713 }
714 
715 
717 {
724 
727 }
static TOOL_ACTION alignRight
Definition: pcb_actions.h:228
void AddMenu(ACTION_MENU *aMenu, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Add a submenu to the menu.
int AlignLeft(const TOOL_EVENT &aEvent)
Sets X coordinate of the selected items to the value of the left-most selected item X coordinate.
wxMenuItem * Add(const wxString &aLabel, int aId, const BITMAP_OPAQUE *aIcon)
Add a wxWidgets-style entry to the menu.
int selectTarget(ALIGNMENT_RECTS &aItems, ALIGNMENT_RECTS &aLocked, T aGetValue)
int AlignCenterY(const TOOL_EVENT &aEvent)
Set the y coordinate of the midpoint of each of the selected items to the value of the y coordinate o...
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:45
This file is part of the common library.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:82
PCB_SELECTION_TOOL * m_selectionTool
int AlignCenterX(const TOOL_EVENT &aEvent)
Set the x coordinate of the midpoint of each of the selected items to the value of the x coordinate o...
static SELECTION_CONDITION MoreThan(int aNumber)
Create a functor that tests if the number of selected items is greater than the value given as parame...
virtual ~ALIGN_DISTRIBUTE_TOOL()
ACTION_MENU * m_placementMenu
Class that computes missing connections on a PCB.
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:46
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:215
static TOOL_ACTION alignCenterY
Definition: pcb_actions.h:230
TOOL_MENU & GetToolMenu()
int AlignBottom(const TOOL_EVENT &aEvent)
Sets Y coordinate of the selected items to the value of the bottom-most selected item Y coordinate.
class PAD, a pad in a footprint
Definition: typeinfo.h:89
static TOOL_ACTION distributeVertically
Definition: pcb_actions.h:232
void doDistributeCentersHorizontally(ALIGNMENT_RECTS &itemsToDistribute, BOARD_COMMIT &aCommit) const
Distribute selected items using an even spacing between the centers of their bounding boxes.
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
void Remove(int aIndex)
Remove the item at aIndex (first position is 0).
Definition: collector.h:115
static TOOL_ACTION alignBottom
Definition: pcb_actions.h:226
void SetTool(TOOL_INTERACTIVE *aTool)
Set a tool that is the creator of the menu.
static TOOL_ACTION distributeHorizontally
Definition: pcb_actions.h:231
ALIGNMENT_RECTS GetBoundingBoxes(const T &aItems)
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:87
int DistributeHorizontally(const TOOL_EVENT &aEvent)
Distribute the selected items along the X axis.
int doAlignRight()
Align selected items using the right edge of their bounding boxes to the right-most item.
void doDistributeGapsHorizontally(ALIGNMENT_RECTS &itemsToDistribute, BOARD_COMMIT &aCommit, const BOARD_ITEM *lastItem, int totalGap) const
Distributes selected items using an even spacing between their bounding boxes.
int doAlignLeft()
Sets X coordinate of the selected items to the value of the left-most selected item X coordinate.
int GetY() const
Definition: board_item.h:103
#define NULL
std::vector< ALIGNMENT_RECT > ALIGNMENT_RECTS
virtual void Move(const wxPoint &aMoveVector)
Move this object.
Definition: board_item.h:277
const BITMAP_OPAQUE align_items_xpm[1]
Definition: align_items.cpp:21
int AlignTop(const TOOL_EVENT &aEvent)
Set Y coordinate of the selected items to the value of the top-most selected item Y coordinate.
void SetIcon(const BITMAP_OPAQUE *aIcon)
Assign an icon for the entry.
Definition: action_menu.cpp:71
Generic, UI-independent tool event.
Definition: tool_event.h:173
int DistributeVertically(const TOOL_EVENT &aEvent)
Distribute the selected items along the Y axis.
static TOOL_ACTION alignLeft
Definition: pcb_actions.h:227
virtual wxPoint GetCenter() const
This defaults to the center of the bounding box if not overridden.
Definition: board_item.h:114
static TOOL_ACTION alignTop
Definition: pcb_actions.h:225
void doDistributeGapsVertically(ALIGNMENT_RECTS &itemsToDistribute, BOARD_COMMIT &aCommit, const BOARD_ITEM *lastItem, int totalGap) const
Distributes selected items using an even spacing between their bounding boxes.
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
class FOOTPRINT, a footprint
Definition: typeinfo.h:88
void doDistributeCentersVertically(ALIGNMENT_RECTS &itemsToDistribute, BOARD_COMMIT &aCommit) const
Distribute selected items using an even spacing between the centers of their bounding boxes.
virtual bool IsLocked() const
Definition: board_item.h:249
class MARKER_PCB, a marker used to show something
Definition: typeinfo.h:98
void SetTitle(const wxString &aTitle) override
Set title for the menu.
Definition: action_menu.cpp:89
PCB_SELECTION & RequestSelection(CLIENT_SELECTION_FILTER aClientFilter, bool aConfirmLockedItems=false)
Return the current selection set, filtered according to aFlags and aClientFilter.
int GetX() const
Definition: board_item.h:97
PCB_BASE_FRAME * m_frame
bool IsType(FRAME_T aType) const
#define _(s)
Definition: 3d_actions.cpp:33
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:241
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
const EDA_RECT GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: footprint.cpp:630
int Size() const
Returns the number of selected parts.
Definition: selection.h:128
The selection tool: currently supports:
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:149
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true) override
Revert the commit by restoring the modified items state.
int AlignRight(const TOOL_EVENT &aEvent)
Sets X coordinate of the selected items to the value of the right-most selected item X coordinate.
virtual const EDA_RECT GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:89
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:42
bool Init() override
Init() is called once upon a registration of the tool.
BOARD_ITEM_CONTAINER * GetParent() const
Definition: board_item.h:168
static TOOL_ACTION alignCenterX
Definition: pcb_actions.h:229
size_t GetSelections(ALIGNMENT_RECTS &aItemsToAlign, ALIGNMENT_RECTS &aLockedItems, T aCompare)
Populate two vectors with the sorted selection and sorted locked items.
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
COMMIT & Stage(EDA_ITEM *aItem, CHANGE_TYPE aChangeType) override
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:162