KiCad PCB EDA Suite
selection_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) 2013-2017 CERN
5  * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
6  * @author Maciej Suminski <maciej.suminski@cern.ch>
7  * Copyright (C) 2018-2020 KiCad Developers, see AUTHORS.txt for contributors.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, you may find one here:
21  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22  * or you may search the http://www.gnu.org website for the version 2 license,
23  * or you may write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26 
27 #include <limits>
28 #include <functional>
29 using namespace std::placeholders;
30 #include <class_board.h>
31 #include <class_board_item.h>
32 #include <class_track.h>
33 #include <class_module.h>
34 #include <class_edge_mod.h>
35 #include <class_drawsegment.h>
36 #include <class_zone.h>
37 #include <collectors.h>
38 #include <confirm.h>
39 #include <dialog_find.h>
41 #include <class_draw_panel_gal.h>
42 #include <view/view_controls.h>
44 #include <painter.h>
45 #include <bitmaps.h>
46 #include <tool/tool_event.h>
47 #include <tool/tool_manager.h>
48 #include <router/router_tool.h>
50 #include <footprint_viewer_frame.h>
51 #include <id.h>
52 #include "tool_event_utils.h"
53 #include "selection_tool.h"
54 #include "pcb_bright_box.h"
55 #include "pcb_actions.h"
56 
57 #include "kicad_plugin.h"
58 
59 
60 class SELECT_MENU : public ACTION_MENU
61 {
62 public:
64  ACTION_MENU( true )
65  {
66  SetTitle( _( "Select" ) );
67  SetIcon( options_generic_xpm );
68 
70 
71  AppendSeparator();
72 
76  }
77 
78 private:
79 
80  void update() override
81  {
82  using S_C = SELECTION_CONDITIONS;
83 
84  const auto& selection = getToolManager()->GetTool<SELECTION_TOOL>()->GetSelection();
85 
86  bool connItem = S_C::OnlyTypes( GENERAL_COLLECTOR::Tracks )( selection );
87  bool sheetSelEnabled = ( S_C::OnlyType( PCB_MODULE_T ) )( selection );
88 
89  Enable( getMenuId( PCB_ACTIONS::selectNet ), connItem );
90  Enable( getMenuId( PCB_ACTIONS::selectConnection ), connItem );
91  Enable( getMenuId( PCB_ACTIONS::selectSameSheet ), sheetSelEnabled );
92  }
93 
94  ACTION_MENU* create() const override
95  {
96  return new SELECT_MENU();
97  }
98 };
99 
100 
105 {
106 public:
108 };
109 
110 
112  PCB_TOOL_BASE( "pcbnew.InteractiveSelection" ),
113  m_frame( NULL ),
114  m_additive( false ),
115  m_subtractive( false ),
116  m_exclusive_or( false ),
117  m_multiple( false ),
118  m_skip_heuristics( false ),
119  m_locked( true ),
120  m_priv( std::make_unique<PRIV>() )
121 {
122 }
123 
124 
126 {
127  getView()->Remove( &m_selection );
128 }
129 
130 
132 {
133  auto frame = getEditFrame<PCB_BASE_FRAME>();
134 
137  {
139  return true;
140  }
141 
142  auto selectMenu = std::make_shared<SELECT_MENU>();
143  selectMenu->SetTool( this );
144  m_menu.AddSubMenu( selectMenu );
145 
146  auto& menu = m_menu.GetMenu();
147 
148  menu.AddMenu( selectMenu.get(), SELECTION_CONDITIONS::NotEmpty );
149  menu.AddSeparator( 1000 );
150 
151  if( frame )
153 
154  return true;
155 }
156 
157 
159 {
160  m_frame = getEditFrame<PCB_BASE_FRAME>();
161  m_locked = true;
162 
163  if( aReason == TOOL_BASE::MODEL_RELOAD )
164  {
165  // Deselect any item being currently in edit, to avoid unexpected behavior
166  // and remove pointers to the selected items from containers
167  // without changing their properties (as they are already deleted
168  // while a new board is loaded)
169  ClearSelection( true );
170 
171  getView()->GetPainter()->GetSettings()->SetHighlight( false );
172  }
173  else
174  {
175  // Restore previous properties of selected items and remove them from containers
176  ClearSelection( true );
177  }
178 
179  // Reinsert the VIEW_GROUP, in case it was removed from the VIEW
180  view()->Remove( &m_selection );
181  view()->Add( &m_selection );
182 }
183 
184 
185 int SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
186 {
187  // Main loop: keep receiving events
188  while( TOOL_EVENT* evt = Wait() )
189  {
190  if( m_frame->ToolStackIsEmpty() )
191  m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
192 
193  bool dragAlwaysSelects = getEditFrame<PCB_BASE_FRAME>()->GetDragSelects();
195 
196  // OSX uses CTRL for context menu, and SHIFT is exclusive-or
197 #ifdef __WXOSX_MAC__
198  if( evt->Modifier( MD_SHIFT ) )
199  m_exclusive_or = true;
200 #else
201  if( evt->Modifier( MD_SHIFT ) && evt->Modifier( MD_CTRL ) )
202  m_subtractive = true;
203  else if( evt->Modifier( MD_SHIFT ) )
204  m_additive = true;
205  else if( evt->Modifier( MD_CTRL ) )
206  m_exclusive_or = true;
207 #endif
208 
209  // Is the user requesting that the selection list include all possible
210  // items without removing less likely selection candidates
211  m_skip_heuristics = !!evt->Modifier( MD_ALT );
212 
213  // Single click? Select single object
214  if( evt->IsClick( BUT_LEFT ) )
215  {
216  m_frame->FocusOnItem( nullptr );
217 
218  selectPoint( evt->Position() );
219  }
220 
221  // right click? if there is any object - show the context menu
222  else if( evt->IsClick( BUT_RIGHT ) )
223  {
224  bool selectionCancelled = false;
225 
226  if( m_selection.Empty() ||
227  !m_selection.GetBoundingBox().Contains( wxPoint( evt->Position() ) ) )
228  {
229  ClearSelection();
230  selectPoint( evt->Position(), false, &selectionCancelled );
231  m_selection.SetIsHover( true );
232  }
233 
234  if( !selectionCancelled )
236  }
237 
238  // double click? Display the properties window
239  else if( evt->IsDblClick( BUT_LEFT ) )
240  {
241  m_frame->FocusOnItem( nullptr );
242 
243  if( m_selection.Empty() )
244  selectPoint( evt->Position() );
245 
247  }
248 
249  // drag with LMB? Select multiple objects (or at least draw a selection box) or drag them
250  else if( evt->IsDrag( BUT_LEFT ) )
251  {
252  m_frame->FocusOnItem( nullptr );
253 
254  if( m_additive || m_subtractive || m_exclusive_or || dragAlwaysSelects )
255  {
256  selectMultiple();
257  }
258  else
259  {
260  // selection is empty? try to start dragging the item under the point where drag
261  // started
262  if( m_selection.Empty() && selectCursor() )
263  m_selection.SetIsHover( true );
264 
265  // Check if dragging has started within any of selected items bounding box
266  if( selectionContains( evt->Position() ) )
267  {
268  // Yes -> run the move tool and wait till it finishes
270  }
271  else
272  {
273  // No -> drag a selection box
274  selectMultiple();
275  }
276  }
277  }
278 
279  else if( evt->IsCancel() )
280  {
281  m_frame->FocusOnItem( nullptr );
282 
283  ClearSelection();
284 
285  if( evt->FirstResponder() == this )
287  }
288 
289  else if( evt->Action() == TA_UNDO_REDO_PRE )
290  {
291  ClearSelection();
292  }
293 
294  else
295  evt->SetPassEvent();
296  }
297 
298  return 0;
299 }
300 
301 
303 {
304  return m_selection;
305 }
306 
307 
309  std::vector<BOARD_ITEM*>* aFiltered,
310  bool aConfirmLockedItems )
311 {
312  bool selectionEmpty = m_selection.Empty();
313  m_selection.SetIsHover( selectionEmpty );
314 
315  if( selectionEmpty )
316  {
317  m_toolMgr->RunAction( PCB_ACTIONS::selectionCursor, true, aClientFilter );
319  }
320 
321  if ( aConfirmLockedItems && CheckLock() == SELECTION_LOCKED )
322  {
323  ClearSelection();
324  return m_selection;
325  }
326 
327  if( aClientFilter )
328  {
329  GENERAL_COLLECTOR collector;
330 
331  for( auto item : m_selection )
332  collector.Append( item );
333 
334  aClientFilter( VECTOR2I(), collector );
335 
336  /*
337  * The first step is to find the items that may have been added by the client filter
338  * This can happen if the locked pads select the module instead
339  */
340  std::vector<EDA_ITEM*> new_items;
341  std::set_difference( collector.begin(), collector.end(),
343  std::back_inserter( new_items ) );
344 
348  std::vector<EDA_ITEM*> diff;
349  std::set_difference( m_selection.begin(), m_selection.end(),
350  collector.begin(), collector.end(),
351  std::back_inserter( diff ) );
352 
353  if( aFiltered )
354  {
355  for( auto item : diff )
356  aFiltered->push_back( static_cast<BOARD_ITEM*>( item ) );
357  }
358 
363  for( auto item : diff )
364  unhighlight( static_cast<BOARD_ITEM*>( item ), SELECTED, &m_selection );
365 
366  for( auto item : new_items )
367  highlight( static_cast<BOARD_ITEM*>( item ), SELECTED, &m_selection );
368 
370  }
371 
372  return m_selection;
373 }
374 
375 
377 {
378  GENERAL_COLLECTORS_GUIDE guide( board()->GetVisibleLayers(),
379  (PCB_LAYER_ID) view()->GetTopLayer(), view() );
380 
381  // account for the globals
382  guide.SetIgnoreMTextsMarkedNoShow( ! board()->IsElementVisible( LAYER_MOD_TEXT_INVISIBLE ) );
383  guide.SetIgnoreMTextsOnBack( ! board()->IsElementVisible( LAYER_MOD_TEXT_BK ) );
384  guide.SetIgnoreMTextsOnFront( ! board()->IsElementVisible( LAYER_MOD_TEXT_FR ) );
385  guide.SetIgnoreModulesOnBack( ! board()->IsElementVisible( LAYER_MOD_BK ) );
386  guide.SetIgnoreModulesOnFront( ! board()->IsElementVisible( LAYER_MOD_FR ) );
387  guide.SetIgnorePadsOnBack( ! board()->IsElementVisible( LAYER_PAD_BK ) );
388  guide.SetIgnorePadsOnFront( ! board()->IsElementVisible( LAYER_PAD_FR ) );
389  guide.SetIgnoreThroughHolePads( ! board()->IsElementVisible( LAYER_PADS_TH ) );
390  guide.SetIgnoreModulesVals( ! board()->IsElementVisible( LAYER_MOD_VALUES ) );
391  guide.SetIgnoreModulesRefs( ! board()->IsElementVisible( LAYER_MOD_REFERENCES ) );
392  guide.SetIgnoreThroughVias( ! board()->IsElementVisible( LAYER_VIA_THROUGH ) );
393  guide.SetIgnoreBlindBuriedVias( ! board()->IsElementVisible( LAYER_VIA_BBLIND ) );
394  guide.SetIgnoreMicroVias( ! board()->IsElementVisible( LAYER_VIA_MICROVIA ) );
395  guide.SetIgnoreTracks( ! board()->IsElementVisible( LAYER_TRACKS ) );
396 
397  return guide;
398 }
399 
400 
401 bool SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag,
402  bool* aSelectionCancelledFlag,
403  CLIENT_SELECTION_FILTER aClientFilter )
404 {
406  GENERAL_COLLECTOR collector;
407  auto& displayOpts = m_frame->GetDisplayOptions();
408  bool cleared = false;
409 
410  guide.SetIgnoreZoneFills( displayOpts.m_DisplayZonesMode != 0 );
411 
412  collector.Collect( board(),
414  wxPoint( aWhere.x, aWhere.y ), guide );
415 
416  // Remove unselectable items
417  for( int i = collector.GetCount() - 1; i >= 0; --i )
418  {
419  if( !Selectable( collector[ i ] ) || ( aOnDrag && collector[i]->IsLocked() ) )
420  collector.Remove( i );
421  }
422 
424 
425  // Allow the client to do tool- or action-specific filtering to see if we
426  // can get down to a single item
427  if( aClientFilter )
428  aClientFilter( aWhere, collector );
429 
430  // Apply some ugly heuristics to avoid disambiguation menus whenever possible
431  if( collector.GetCount() > 1 && !m_skip_heuristics )
432  {
433  GuessSelectionCandidates( collector, aWhere );
434  }
435 
436  // If still more than one item we're going to have to ask the user.
437  if( collector.GetCount() > 1 )
438  {
439  if( aOnDrag )
441 
442  if( !doSelectionMenu( &collector, _( "Clarify Selection" ) ) )
443  {
444  if( aSelectionCancelledFlag )
445  *aSelectionCancelledFlag = true;
446 
447  return false;
448  }
449  }
450 
452  {
453  if( m_selection.GetSize() > 0 )
454  {
455  // Don't fire an event now as it will end up redundant if we fire a SelectedEvent
456  // or an UnselectedEvent.
457  cleared = true;
458  ClearSelection( true );
459  }
460  }
461 
462  if( collector.GetCount() == 1 )
463  {
464  BOARD_ITEM* item = collector[ 0 ];
465 
466  if( m_subtractive || ( m_exclusive_or && item->IsSelected() ) )
467  {
468  unselect( item );
470  return false;
471  }
472  else
473  {
474  select( item );
476  return true;
477  }
478  }
479 
480  if( cleared )
482 
483  return false;
484 }
485 
486 
487 bool SELECTION_TOOL::selectCursor( bool aForceSelect, CLIENT_SELECTION_FILTER aClientFilter )
488 {
489  if( aForceSelect || m_selection.Empty() )
490  {
491  ClearSelection( true /*quiet mode*/ );
492  selectPoint( getViewControls()->GetCursorPosition( false ), false, NULL, aClientFilter );
493  }
494 
495  return !m_selection.Empty();
496 }
497 
498 
500 {
501  bool cancelled = false; // Was the tool cancelled while it was running?
502  m_multiple = true; // Multiple selection mode is active
503  KIGFX::VIEW* view = getView();
504 
506  view->Add( &area );
507 
508  bool anyAdded = false;
509  bool anySubtracted = false;
510 
511  while( TOOL_EVENT* evt = Wait() )
512  {
513  if( evt->IsCancelInteractive() || evt->IsActivate() )
514  {
515  cancelled = true;
516  break;
517  }
518 
519  if( evt->IsDrag( BUT_LEFT ) )
520  {
522  {
523  if( m_selection.GetSize() > 0 )
524  {
525  anySubtracted = true;
526  ClearSelection( true /*quiet mode*/ );
527  }
528  }
529 
530  // Start drawing a selection box
531  area.SetOrigin( evt->DragOrigin() );
532  area.SetEnd( evt->Position() );
533  area.SetAdditive( m_additive );
536 
537  view->SetVisible( &area, true );
538  view->Update( &area );
539  getViewControls()->SetAutoPan( true );
540  }
541 
542  if( evt->IsMouseUp( BUT_LEFT ) )
543  {
544  getViewControls()->SetAutoPan( false );
545 
546  // End drawing the selection box
547  view->SetVisible( &area, false );
548 
549  // Mark items within the selection box as selected
550  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
551 
552  // Filter the view items based on the selection box
553  BOX2I selectionBox = area.ViewBBox();
554  view->Query( selectionBox, selectedItems ); // Get the list of selected items
555 
556  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR>::iterator it, it_end;
557 
558  int width = area.GetEnd().x - area.GetOrigin().x;
559  int height = area.GetEnd().y - area.GetOrigin().y;
560 
561  /* Selection mode depends on direction of drag-selection:
562  * Left > Right : Select objects that are fully enclosed by selection
563  * Right > Left : Select objects that are crossed by selection
564  */
565  bool windowSelection = width >= 0 ? true : false;
566 
567  if( view->IsMirroredX() )
568  windowSelection = !windowSelection;
569 
570  // Construct an EDA_RECT to determine BOARD_ITEM selection
571  EDA_RECT selectionRect( (wxPoint) area.GetOrigin(), wxSize( width, height ) );
572 
573  selectionRect.Normalize();
574 
575  for( it = selectedItems.begin(), it_end = selectedItems.end(); it != it_end; ++it )
576  {
577  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( it->first );
578 
579  if( !item || !Selectable( item ) )
580  continue;
581 
582  if( item->HitTest( selectionRect, windowSelection ) )
583  {
584  if( m_subtractive || ( m_exclusive_or && item->IsSelected() ) )
585  {
586  unselect( item );
587  anySubtracted = true;
588  }
589  else
590  {
591  select( item );
592  anyAdded = true;
593  }
594  }
595  }
596 
597  m_selection.SetIsHover( false );
598 
599  // Inform other potentially interested tools
600  if( anyAdded )
602  else if( anySubtracted )
604 
605  break; // Stop waiting for events
606  }
607  }
608 
609  getViewControls()->SetAutoPan( false );
610 
611  // Stop drawing the selection box
612  view->Remove( &area );
613  m_multiple = false; // Multiple selection mode is inactive
614 
615  if( !cancelled )
617 
618  return cancelled;
619 }
620 
621 
623 {
624  if( !m_locked || m_editModules )
625  return SELECTION_UNLOCKED;
626 
627  bool containsLocked = false;
628 
629  // Check if the selection contains locked items
630  for( const auto& item : m_selection )
631  {
632  switch( item->Type() )
633  {
634  case PCB_MODULE_T:
635  if( static_cast<MODULE*>( item )->IsLocked() )
636  containsLocked = true;
637  break;
638 
639  case PCB_MODULE_EDGE_T:
640  case PCB_MODULE_TEXT_T:
641  if( static_cast<MODULE*>( item->GetParent() )->IsLocked() )
642  containsLocked = true;
643  break;
644 
645  default: // suppress warnings
646  break;
647  }
648  }
649 
650  if( containsLocked )
651  {
652  if( IsOK( m_frame, _( "Selection contains locked items. Do you want to continue?" ) ) )
653  {
654  m_locked = false;
656  }
657  else
658  return SELECTION_LOCKED;
659  }
660 
661  return SELECTION_UNLOCKED;
662 }
663 
664 
666 {
668 
669  selectCursor( false, aClientFilter );
670 
671  return 0;
672 }
673 
674 
676 {
677  ClearSelection();
678 
679  return 0;
680 }
681 
682 
684 {
685  std::vector<BOARD_ITEM*>* items = aEvent.Parameter<std::vector<BOARD_ITEM*>*>();
686 
687  if( items )
688  {
689  // Perform individual selection of each item before processing the event.
690  for( auto item : *items )
691  select( item );
692 
694  }
695 
696  return 0;
697 }
698 
699 
701 {
702  AddItemToSel( aEvent.Parameter<BOARD_ITEM*>() );
703  return 0;
704 }
705 
706 
707 void SELECTION_TOOL::AddItemToSel( BOARD_ITEM* aItem, bool aQuietMode )
708 {
709  if( aItem )
710  {
711  select( aItem );
712 
713  // Inform other potentially interested tools
714  if( !aQuietMode )
716  }
717 }
718 
719 
721 {
722  std::vector<BOARD_ITEM*>* items = aEvent.Parameter<std::vector<BOARD_ITEM*>*>();
723 
724  if( items )
725  {
726  // Perform individual unselection of each item before processing the event
727  for( auto item : *items )
728  unselect( item );
729 
731  }
732 
733  return 0;
734 }
735 
736 
738 {
739  RemoveItemFromSel( aEvent.Parameter<BOARD_ITEM*>() );
740  return 0;
741 }
742 
743 
744 void SELECTION_TOOL::RemoveItemFromSel( BOARD_ITEM* aItem, bool aQuietMode )
745 {
746  if( aItem )
747  {
748  unselect( aItem );
749 
750  // Inform other potentially interested tools
752  }
753 }
754 
755 
757 {
758  highlight( aItem, BRIGHTENED );
759 }
760 
761 
763 {
764  unhighlight( aItem, BRIGHTENED );
765 }
766 
767 
768 void connectedItemFilter( const VECTOR2I&, GENERAL_COLLECTOR& aCollector )
769 {
770  // Narrow the collection down to a single BOARD_CONNECTED_ITEM for each represented net.
771  // All other items types are removed.
772  std::set<int> representedNets;
773 
774  for( int i = aCollector.GetCount() - 1; i >= 0; i-- )
775  {
776  BOARD_CONNECTED_ITEM* item = dynamic_cast<BOARD_CONNECTED_ITEM*>( aCollector[i] );
777  if( !item )
778  aCollector.Remove( i );
779  else if ( representedNets.count( item->GetNetCode() ) )
780  aCollector.Remove( i );
781  else
782  representedNets.insert( item->GetNetCode() );
783  }
784 }
785 
786 
788 {
789  unsigned initialCount = 0;
790 
791  for( auto item : m_selection.GetItems() )
792  {
793  if( dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
794  initialCount++;
795  }
796 
797  if( initialCount == 0 )
799 
800  for( KICAD_T stopCondition : { PCB_VIA_T, PCB_PAD_T, EOT } )
801  {
802  // copy the selection, since we're going to iterate and modify
803  std::deque<EDA_ITEM*> selectedItems = m_selection.GetItems();
804 
805  // We use the BUSY flag to mark connections
806  for( EDA_ITEM* item : selectedItems )
807  item->SetState( BUSY, false );
808 
809  for( EDA_ITEM* item : selectedItems )
810  {
811  TRACK* trackItem = dynamic_cast<TRACK*>( item );
812 
813  // Track items marked BUSY have already been visited
814  if( trackItem && !trackItem->GetState( BUSY ) )
815  selectConnectedTracks( *trackItem, stopCondition );
816  }
817 
818  if( m_selection.GetItems().size() > initialCount )
819  break;
820  }
821 
822  // Inform other potentially interested tools
823  if( m_selection.Size() > 0 )
825 
826  return 0;
827 }
828 
829 
831  KICAD_T aStopCondition )
832 {
833  constexpr KICAD_T types[] = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T, EOT };
834 
835  auto connectivity = board()->GetConnectivity();
836  auto connectedItems = connectivity->GetConnectedItems( &aStartItem, types );
837 
838  std::map<wxPoint, std::vector<TRACK*>> trackMap;
839  std::map<wxPoint, VIA*> viaMap;
840  std::map<wxPoint, D_PAD*> padMap;
841 
842  // Build maps of connected items
843  for( BOARD_CONNECTED_ITEM* item : connectedItems )
844  {
845  switch( item->Type() )
846  {
847  case PCB_TRACE_T:
848  {
849  TRACK* track = static_cast<TRACK*>( item );
850  trackMap[ track->GetStart() ].push_back( track );
851  trackMap[ track->GetEnd() ].push_back( track );
852  }
853  break;
854  case PCB_VIA_T:
855  {
856  VIA* via = static_cast<VIA*>( item );
857  viaMap[ via->GetStart() ] = via;
858  }
859  break;
860  case PCB_PAD_T:
861  {
862  D_PAD* pad = static_cast<D_PAD*>( item );
863  padMap[ pad->GetPosition() ] = pad;
864  }
865  break;
866  default:
867  break;
868  }
869 
870  item->SetState( SKIP_STRUCT, false );
871  }
872 
873  std::vector<wxPoint> activePts;
874 
875  // Set up the initial active points
876  switch( aStartItem.Type() )
877  {
878  case PCB_TRACE_T:
879  activePts.push_back( static_cast<TRACK*>( &aStartItem )->GetStart() );
880  activePts.push_back( static_cast<TRACK*>( &aStartItem )->GetEnd() );
881  break;
882  case PCB_VIA_T:
883  activePts.push_back( static_cast<TRACK*>( &aStartItem )->GetStart() );
884  break;
885  case PCB_PAD_T:
886  activePts.push_back( aStartItem.GetPosition() );
887  break;
888  default:
889  break;
890  }
891 
892  bool expand = true;
893 
894  // Iterative push from all active points
895  while( expand )
896  {
897  expand = false;
898 
899  for( int i = activePts.size() - 1; i >= 0; --i )
900  {
901  wxPoint pt = activePts[i];
902 
903  if( trackMap[ pt ].size() > 2 && aStopCondition == SCH_JUNCTION_T )
904  {
905  activePts.erase( activePts.begin() + i );
906  continue;
907  }
908 
909  if( padMap.count( pt ) && aStopCondition != EOT )
910  {
911  activePts.erase( activePts.begin() + i );
912  continue;
913  }
914 
915  for( TRACK* track : trackMap[ pt ] )
916  {
917  if( track->GetState( SKIP_STRUCT ) )
918  continue;
919 
920  track->SetState( SKIP_STRUCT, true );
921  select( track );
922 
923  if( track->GetStart() == pt )
924  activePts.push_back( track->GetEnd() );
925  else
926  activePts.push_back( track->GetStart() );
927 
928  expand = true;
929  }
930 
931  if( viaMap.count( pt ) && !viaMap[ pt ]->IsSelected() )
932  select( viaMap[ pt ] );
933 
934  activePts.erase( activePts.begin() + i );
935  }
936  }
937 }
938 
939 
941 {
942  constexpr KICAD_T types[] = { PCB_TRACE_T, PCB_VIA_T, EOT };
943  auto connectivity = board()->GetConnectivity();
944 
945  for( BOARD_CONNECTED_ITEM* item : connectivity->GetNetItems( aNetCode, types ) )
946  select( item );
947 }
948 
949 
951 {
952  if( !selectCursor() )
953  return 0;
954 
955  // copy the selection, since we're going to iterate and modify
956  auto selection = m_selection.GetItems();
957 
958  for( EDA_ITEM* i : selection )
959  {
960  BOARD_CONNECTED_ITEM* connItem = dynamic_cast<BOARD_CONNECTED_ITEM*>( i );
961 
962  if( connItem )
963  selectAllItemsOnNet( connItem->GetNetCode() );
964  }
965 
966  // Inform other potentially interested tools
967  if( m_selection.Size() > 0 )
969 
970  return 0;
971 }
972 
973 
974 void SELECTION_TOOL::selectAllItemsOnSheet( wxString& aSheetID )
975 {
976  KIID uuid( aSheetID );
977  std::list<MODULE*> modList;
978 
979  // store all modules that are on that sheet
980  for( MODULE* module : board()->Modules() )
981  {
982  if( module == nullptr )
983  continue;
984 
985  for( const KIID& pathStep : module->GetPath() )
986  {
987  if( pathStep == uuid )
988  {
989  modList.push_back( module );
990  break;
991  }
992  }
993  }
994 
995  //Generate a list of all pads, and of all nets they belong to.
996  std::list<int> netcodeList;
997  std::list<D_PAD*> padList;
998  for( MODULE* mmod : modList )
999  {
1000  for( D_PAD* pad : mmod->Pads() )
1001  {
1002  if( pad->IsConnected() )
1003  {
1004  netcodeList.push_back( pad->GetNetCode() );
1005  padList.push_back( pad );
1006  }
1007  }
1008  }
1009  // remove all duplicates
1010  netcodeList.sort();
1011  netcodeList.unique();
1012 
1013  // auto select trivial connections segments which are launched from the pads
1014  std::list<TRACK*> launchTracks;
1015 
1016  for( D_PAD* pad : padList )
1017  selectConnectedTracks( *pad, EOT );
1018 
1019  // now we need to find all modules that are connected to each of these nets
1020  // then we need to determine if these modules are in the list of modules
1021  // belonging to this sheet ( modList )
1022  std::list<int> removeCodeList;
1023  constexpr KICAD_T padType[] = { PCB_PAD_T, EOT };
1024 
1025  for( int netCode : netcodeList )
1026  {
1027  for( BOARD_CONNECTED_ITEM* mitem : board()->GetConnectivity()->GetNetItems( netCode, padType ) )
1028  {
1029  if( mitem->Type() == PCB_PAD_T)
1030  {
1031  bool found = std::find( modList.begin(), modList.end(), mitem->GetParent() ) != modList.end();
1032 
1033  if( !found )
1034  {
1035  // if we cannot find the module of the pad in the modList
1036  // then we can assume that that module is not located in the same
1037  // schematic, therefore invalidate this netcode.
1038  removeCodeList.push_back( netCode );
1039  break;
1040  }
1041  }
1042  }
1043  }
1044 
1045  // remove all duplicates
1046  removeCodeList.sort();
1047  removeCodeList.unique();
1048 
1049  for( int removeCode : removeCodeList )
1050  {
1051  netcodeList.remove( removeCode );
1052  }
1053 
1054  std::list<BOARD_CONNECTED_ITEM*> localConnectionList;
1055  constexpr KICAD_T trackViaType[] = { PCB_TRACE_T, PCB_VIA_T, EOT };
1056 
1057  for( int netCode : netcodeList )
1058  {
1059  for( BOARD_CONNECTED_ITEM* item : board()->GetConnectivity()->GetNetItems( netCode, trackViaType ) )
1060  localConnectionList.push_back( item );
1061  }
1062 
1063  for( BOARD_ITEM* i : modList )
1064  {
1065  if( i != NULL )
1066  select( i );
1067  }
1068 
1069  for( BOARD_CONNECTED_ITEM* i : localConnectionList )
1070  {
1071  if( i != NULL )
1072  select( i );
1073  }
1074 }
1075 
1076 
1078 {
1079  //Should recalculate the view to zoom in on the selection
1080  auto selectionBox = m_selection.ViewBBox();
1081  auto view = getView();
1082 
1083  VECTOR2D screenSize = view->ToWorld( m_frame->GetCanvas()->GetClientSize(), false );
1084  screenSize.x = std::max( 10.0, screenSize.x );
1085  screenSize.y = std::max( 10.0, screenSize.y );
1086 
1087  if( selectionBox.GetWidth() != 0 || selectionBox.GetHeight() != 0 )
1088  {
1089  VECTOR2D vsize = selectionBox.GetSize();
1090  double scale = view->GetScale() / std::max( fabs( vsize.x / screenSize.x ),
1091  fabs( vsize.y / screenSize.y ) );
1092  view->SetScale( scale );
1093  view->SetCenter( selectionBox.Centre() );
1094  view->Add( &m_selection );
1095  }
1096 
1098 }
1099 
1100 
1102 {
1103  ClearSelection( true /*quiet mode*/ );
1104  wxString* sheetID = aEvent.Parameter<wxString*>();
1105 
1106  selectAllItemsOnSheet( *sheetID );
1107 
1108  zoomFitSelection();
1109 
1110  if( m_selection.Size() > 0 )
1112 
1113  return 0;
1114 }
1115 
1116 
1118 {
1119  if( !selectCursor( true ) )
1120  return 0;
1121 
1122  // this function currently only supports modules since they are only
1123  // on one sheet.
1124  auto item = m_selection.Front();
1125 
1126  if( !item )
1127  return 0;
1128 
1129  if( item->Type() != PCB_MODULE_T )
1130  return 0;
1131 
1132  auto mod = dynamic_cast<MODULE*>( item );
1133 
1134  if( mod->GetPath().empty() )
1135  return 0;
1136 
1137  ClearSelection( true /*quiet mode*/ );
1138 
1139  // get the lowest subsheet name for this.
1140  wxString sheetID = mod->GetPath().back().AsString();
1141 
1142  selectAllItemsOnSheet( sheetID );
1143 
1144  // Inform other potentially interested tools
1145  if( m_selection.Size() > 0 )
1147 
1148  return 0;
1149 }
1150 
1151 
1153 {
1154  bool cleared = false;
1155 
1156  if( m_selection.GetSize() > 0 )
1157  {
1158  // Don't fire an event now; most of the time it will be redundant as we're about to
1159  // fire a SelectedEvent.
1160  cleared = true;
1161  ClearSelection( true /*quiet mode*/ );
1162  }
1163 
1164  if( aItem )
1165  {
1166  select( aItem );
1167  m_frame->FocusOnLocation( aItem->GetPosition() );
1168 
1169  // Inform other potentially interested tools
1171  }
1172  else if( cleared )
1173  {
1175  }
1176 
1178 }
1179 
1180 
1181 int SELECTION_TOOL::find( const TOOL_EVENT& aEvent )
1182 {
1183  DIALOG_FIND dlg( m_frame );
1184  dlg.SetCallback( std::bind( &SELECTION_TOOL::findCallback, this, _1 ) );
1185  dlg.ShowModal();
1186 
1187  return 0;
1188 }
1189 
1190 
1198 static bool itemIsIncludedByFilter( const BOARD_ITEM& aItem, const BOARD& aBoard,
1199  const DIALOG_FILTER_SELECTION::OPTIONS& aFilterOptions )
1200 {
1201  bool include = true;
1202  const PCB_LAYER_ID layer = aItem.GetLayer();
1203 
1204  // if the item needs to be checked against the options
1205  if( include )
1206  {
1207  switch( aItem.Type() )
1208  {
1209  case PCB_MODULE_T:
1210  {
1211  const auto& module = static_cast<const MODULE&>( aItem );
1212 
1213  include = aFilterOptions.includeModules;
1214 
1215  if( include && !aFilterOptions.includeLockedModules )
1216  {
1217  include = !module.IsLocked();
1218  }
1219 
1220  break;
1221  }
1222  case PCB_TRACE_T:
1223  case PCB_ARC_T:
1224  {
1225  include = aFilterOptions.includeTracks;
1226  break;
1227  }
1228  case PCB_VIA_T:
1229  {
1230  include = aFilterOptions.includeVias;
1231  break;
1232  }
1233  case PCB_ZONE_AREA_T:
1234  {
1235  include = aFilterOptions.includeZones;
1236  break;
1237  }
1238  case PCB_LINE_T:
1239  case PCB_TARGET_T:
1240  case PCB_DIMENSION_T:
1241  {
1242  if( layer == Edge_Cuts )
1243  include = aFilterOptions.includeBoardOutlineLayer;
1244  else
1245  include = aFilterOptions.includeItemsOnTechLayers;
1246  break;
1247  }
1248  case PCB_TEXT_T:
1249  {
1250  include = aFilterOptions.includePcbTexts;
1251  break;
1252  }
1253  default:
1254  {
1255  // no filtering, just select it
1256  break;
1257  }
1258  }
1259  }
1260 
1261  return include;
1262 }
1263 
1264 
1266 {
1267  const BOARD& board = *getModel<BOARD>();
1268  DIALOG_FILTER_SELECTION::OPTIONS& opts = m_priv->m_filterOpts;
1269  DIALOG_FILTER_SELECTION dlg( m_frame, opts );
1270 
1271  const int cmd = dlg.ShowModal();
1272 
1273  if( cmd != wxID_OK )
1274  return 0;
1275 
1276  // copy current selection
1277  std::deque<EDA_ITEM*> selection = m_selection.GetItems();
1278 
1279  ClearSelection( true /*quiet mode*/ );
1280 
1281  // re-select items from the saved selection according to the dialog options
1282  for( EDA_ITEM* i : selection )
1283  {
1284  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( i );
1285  bool include = itemIsIncludedByFilter( *item, board, opts );
1286 
1287  if( include )
1288  select( item );
1289  }
1290 
1292 
1293  return 0;
1294 }
1295 
1296 
1297 void SELECTION_TOOL::ClearSelection( bool aQuietMode )
1298 {
1299  if( m_selection.Empty() )
1300  return;
1301 
1302  while( m_selection.GetSize() )
1303  unhighlight( static_cast<BOARD_ITEM*>( m_selection.Front() ), SELECTED, &m_selection );
1304 
1305  view()->Update( &m_selection );
1306 
1307  m_selection.SetIsHover( false );
1309 
1310  m_locked = true;
1311 
1312  // Inform other potentially interested tools
1313  if( !aQuietMode )
1314  {
1317  }
1318 }
1319 
1320 
1322 {
1323  m_selection.Clear();
1324 
1325  INSPECTOR_FUNC inspector = [&] ( EDA_ITEM* item, void* testData )
1326  {
1327  if( item->IsSelected() )
1328  {
1329  EDA_ITEM* parent = item->GetParent();
1330 
1331  // Flags on module children might be set only because the parent is selected.
1332  if( parent && parent->Type() == PCB_MODULE_T && parent->IsSelected() )
1333  return SEARCH_RESULT::CONTINUE;
1334 
1335  highlight( (BOARD_ITEM*) item, SELECTED, &m_selection );
1336  }
1337 
1338  return SEARCH_RESULT::CONTINUE;
1339  };
1340 
1341  board()->Visit( inspector, nullptr, m_editModules ? GENERAL_COLLECTOR::ModuleItems
1343 }
1344 
1345 
1347 {
1348  GENERAL_COLLECTOR* collector = aEvent.Parameter<GENERAL_COLLECTOR*>();
1349 
1350  doSelectionMenu( collector, wxEmptyString );
1351 
1352  return 0;
1353 }
1354 
1355 
1356 bool SELECTION_TOOL::doSelectionMenu( GENERAL_COLLECTOR* aCollector, const wxString& aTitle )
1357 {
1358  BOARD_ITEM* current = nullptr;
1359  PCBNEW_SELECTION highlightGroup;
1360  ACTION_MENU menu( true );
1361 
1362  highlightGroup.SetLayer( LAYER_SELECT_OVERLAY );
1363  getView()->Add( &highlightGroup );
1364 
1365  int limit = std::min( 9, aCollector->GetCount() );
1366 
1367  for( int i = 0; i < limit; ++i )
1368  {
1369  wxString text;
1370  BOARD_ITEM* item = ( *aCollector )[i];
1371  text = item->GetSelectMenuText( m_frame->GetUserUnits() );
1372 
1373  wxString menuText = wxString::Format("&%d. %s", i + 1, text );
1374  menu.Add( menuText, i + 1, item->GetMenuImage() );
1375  }
1376 
1377  if( aTitle.Length() )
1378  menu.SetTitle( aTitle );
1379 
1380  menu.SetIcon( info_xpm );
1381  menu.DisplayTitle( true );
1382  SetContextMenu( &menu, CMENU_NOW );
1383 
1384  while( TOOL_EVENT* evt = Wait() )
1385  {
1386  if( evt->Action() == TA_CHOICE_MENU_UPDATE )
1387  {
1388  if( current )
1389  unhighlight( current, BRIGHTENED, &highlightGroup );
1390 
1391  int id = *evt->GetCommandId();
1392 
1393  // User has pointed an item, so show it in a different way
1394  if( id > 0 && id <= limit )
1395  {
1396  current = ( *aCollector )[id - 1];
1397  highlight( current, BRIGHTENED, &highlightGroup );
1398  }
1399  else
1400  {
1401  current = NULL;
1402  }
1403  }
1404  else if( evt->Action() == TA_CHOICE_MENU_CHOICE )
1405  {
1406  if( current )
1407  unhighlight( current, BRIGHTENED, &highlightGroup );
1408 
1409  OPT<int> id = evt->GetCommandId();
1410 
1411  // User has selected an item, so this one will be returned
1412  if( id && ( *id > 0 ) )
1413  current = ( *aCollector )[*id - 1];
1414  else
1415  current = NULL;
1416 
1417  break;
1418  }
1419  }
1420  getView()->Remove( &highlightGroup );
1421 
1422  if( current )
1423  {
1424  aCollector->Empty();
1425  aCollector->Append( current );
1426  return true;
1427  }
1428 
1429  return false;
1430 }
1431 
1432 
1434 {
1435  int count = aCollector->GetPrimaryCount(); // try to use preferred layer
1436 
1437  if( 0 == count )
1438  count = aCollector->GetCount();
1439 
1440  for( int i = 0; i < count; ++i )
1441  {
1442  if( ( *aCollector )[i]->Type() != PCB_MODULE_T )
1443  return NULL;
1444  }
1445 
1446  // All are modules, now find smallest MODULE
1447  int minDim = 0x7FFFFFFF;
1448  int minNdx = 0;
1449 
1450  for( int i = 0; i < count; ++i )
1451  {
1452  MODULE* module = (MODULE*) ( *aCollector )[i];
1453 
1454  int lx = module->GetFootprintRect().GetWidth();
1455  int ly = module->GetFootprintRect().GetHeight();
1456 
1457  int lmin = std::min( lx, ly );
1458 
1459  if( lmin < minDim )
1460  {
1461  minDim = lmin;
1462  minNdx = i;
1463  }
1464  }
1465 
1466  return (*aCollector)[minNdx];
1467 }
1468 
1469 
1470 bool SELECTION_TOOL::Selectable( const BOARD_ITEM* aItem, bool checkVisibilityOnly ) const
1471 {
1472  // Is high contrast mode enabled?
1473  bool highContrast = getView()->GetPainter()->GetSettings()->GetHighContrast();
1474 
1475  int layers[KIGFX::VIEW::VIEW_MAX_LAYERS], layers_count;
1476 
1477  // Filter out items that do not belong to active layers
1478  std::set<unsigned int> activeLayers = getView()->GetPainter()->GetSettings()->GetActiveLayers();
1479 
1480  aItem->ViewGetLayers( layers, layers_count );
1481 
1482  if( highContrast )
1483  {
1484  bool onActive = false; // Is the item on any of active layers?
1485 
1486  for( int i = 0; i < layers_count; ++i )
1487  {
1488  if( activeLayers.count( layers[i] ) > 0 ) // Item is on at least one of the active layers
1489  {
1490  onActive = true;
1491  break;
1492  }
1493  }
1494 
1495  if( !onActive ) // We do not want to select items that are in the background
1496  {
1497  return false;
1498  }
1499  }
1500 
1501  switch( aItem->Type() )
1502  {
1503  case PCB_ZONE_AREA_T:
1504  {
1505  // Check to see if this keepout is part of a footprint
1506  // If it is, and we are not editing the footprint, it should not be selectable
1507  const bool zoneInFootprint =
1508  aItem->GetParent() != nullptr && aItem->GetParent()->Type() == PCB_MODULE_T;
1509  if( zoneInFootprint && !m_editModules && !checkVisibilityOnly )
1510  return false;
1511 
1512  // Keepout zones can exist on multiple layers!
1513  {
1514  auto* zone = static_cast<const ZONE_CONTAINER*>( aItem );
1515 
1516  if( zone->GetIsKeepout() )
1517  {
1518  auto zoneLayers = zone->GetLayerSet().Seq();
1519 
1520  for( unsigned int i = 0; i < zoneLayers.size(); i++ )
1521  {
1522  if( board()->IsLayerVisible( zoneLayers[i] ) )
1523  {
1524  return true;
1525  }
1526  }
1527 
1528  // No active layers selected!
1529  return false;
1530  }
1531  }
1532  }
1533  break;
1534 
1535  case PCB_TRACE_T:
1536  case PCB_ARC_T:
1537  {
1538  if( !board()->IsElementVisible( LAYER_TRACKS ) )
1539  return false;
1540  }
1541  break;
1542 
1543  case PCB_VIA_T:
1544  {
1545  const VIA* via = static_cast<const VIA*>( aItem );
1546 
1547  // Check if appropriate element layer is visible
1548  switch( via->GetViaType() )
1549  {
1550  case VIATYPE::THROUGH:
1552  return false;
1553  break;
1554 
1555  case VIATYPE::BLIND_BURIED:
1557  return false;
1558  break;
1559 
1560  case VIATYPE::MICROVIA:
1562  return false;
1563  break;
1564 
1565  default:
1566  wxFAIL;
1567  return false;
1568  }
1569 
1570  // For vias it is enough if only one of its layers is visible
1571  return ( board()->GetVisibleLayers() & via->GetLayerSet() ).any();
1572  }
1573 
1574  case PCB_MODULE_T:
1575  {
1576  // In modedit, we do not want to select the module itself.
1577  if( m_editModules )
1578  return false;
1579 
1580  // Allow selection of footprints if some part of the footprint is visible.
1581 
1582  MODULE* module = const_cast<MODULE*>( static_cast<const MODULE*>( aItem ) );
1583 
1584  for( auto item : module->GraphicalItems() )
1585  {
1586  if( Selectable( item, true ) )
1587  return true;
1588  }
1589 
1590  for( auto pad : module->Pads() )
1591  {
1592  if( Selectable( pad, true ) )
1593  return true;
1594  }
1595 
1596  for( auto zone : module->Zones() )
1597  {
1598  if( Selectable( zone, true ) )
1599  return true;
1600  }
1601 
1602  return false;
1603  }
1604 
1605  case PCB_MODULE_TEXT_T:
1606  // Multiple selection is only allowed in modedit mode. In pcbnew, you have to select
1607  // module subparts one by one, rather than with a drag selection. This is so you can
1608  // pick up items under an (unlocked) module without also moving the module's sub-parts.
1609  if( !m_editModules && !checkVisibilityOnly )
1610  {
1611  if( m_multiple )
1612  return false;
1613  }
1614 
1615  if( !m_editModules && !view()->IsVisible( aItem ) )
1616  return false;
1617 
1618  break;
1619 
1620  case PCB_MODULE_EDGE_T:
1621  case PCB_PAD_T:
1622  {
1623  // Multiple selection is only allowed in modedit mode. In pcbnew, you have to select
1624  // module subparts one by one, rather than with a drag selection. This is so you can
1625  // pick up items under an (unlocked) module without also moving the module's sub-parts.
1626  if( !m_editModules && !checkVisibilityOnly )
1627  {
1628  if( m_multiple )
1629  return false;
1630  }
1631 
1632  if( aItem->Type() == PCB_PAD_T )
1633  {
1634  auto pad = static_cast<const D_PAD*>( aItem );
1635 
1636  // In pcbnew, locked modules prevent individual pad selection.
1637  // In modedit, we don't enforce this as the module is assumed to be edited by design.
1638  if( !m_editModules && !checkVisibilityOnly )
1639  {
1640  if( pad->GetParent() && pad->GetParent()->IsLocked() )
1641  return false;
1642  }
1643 
1644  // Check render mode (from the Items tab) first
1645  switch( pad->GetAttribute() )
1646  {
1647  case PAD_ATTRIB_STANDARD:
1649  if( !board()->IsElementVisible( LAYER_PADS_TH ) )
1650  return false;
1651  break;
1652 
1653  case PAD_ATTRIB_CONN:
1654  case PAD_ATTRIB_SMD:
1655  if( pad->IsOnLayer( F_Cu ) && !board()->IsElementVisible( LAYER_PAD_FR ) )
1656  return false;
1657  else if( pad->IsOnLayer( B_Cu ) && !board()->IsElementVisible( LAYER_PAD_BK ) )
1658  return false;
1659  break;
1660  }
1661 
1662  // Otherwise, pads are selectable if any draw layer is visible
1663 
1664  // Shortcut: check copper layer visibility
1665  if( board()->IsLayerVisible( F_Cu ) && pad->IsOnLayer( F_Cu ) )
1666  return true;
1667 
1668  if( board()->IsLayerVisible( B_Cu ) && pad->IsOnLayer( B_Cu ) )
1669  return true;
1670 
1671  // Now check the non-copper layers
1672 
1673  bool draw_layer_visible = false;
1674 
1675  int pad_layers[KIGFX::VIEW::VIEW_MAX_LAYERS], pad_layers_count;
1676  pad->ViewGetLayers( pad_layers, pad_layers_count );
1677 
1678  for( int i = 0; i < pad_layers_count; ++i )
1679  {
1680  // NOTE: Only checking the regular layers (not GAL meta-layers)
1681  if( ( ( pad_layers[i] < PCB_LAYER_ID_COUNT ) &&
1682  board()->IsLayerVisible( static_cast<PCB_LAYER_ID>( pad_layers[i] ) ) ) )
1683  {
1684  draw_layer_visible = true;
1685  }
1686  }
1687 
1688  return draw_layer_visible;
1689  }
1690 
1691  break;
1692  }
1693 
1694 
1695  case PCB_MARKER_T: // Always selectable
1696  return true;
1697 
1698  // These are not selectable
1699  case NOT_USED:
1700  case TYPE_NOT_INIT:
1701  return false;
1702 
1703  default: // Suppress warnings
1704  break;
1705  }
1706 
1707  // All other items are selected only if the layer on which they exist is visible
1708  return board()->IsLayerVisible( aItem->GetLayer() )
1709  && aItem->ViewGetLOD( aItem->GetLayer(), view() ) < view()->GetScale();
1710 }
1711 
1712 
1714 {
1715  if( aItem->IsSelected() )
1716  {
1717  return;
1718  }
1719 
1720  if( aItem->Type() == PCB_PAD_T )
1721  {
1722  MODULE* module = static_cast<MODULE*>( aItem->GetParent() );
1723 
1724  if( m_selection.Contains( module ) )
1725  return;
1726  }
1727 
1728  highlight( aItem, SELECTED, &m_selection );
1729 }
1730 
1731 
1733 {
1734  unhighlight( aItem, SELECTED, &m_selection );
1735 
1736  if( m_selection.Empty() )
1737  m_locked = true;
1738 }
1739 
1740 
1741 void SELECTION_TOOL::highlight( BOARD_ITEM* aItem, int aMode, PCBNEW_SELECTION* aGroup )
1742 {
1743  if( aMode == SELECTED )
1744  aItem->SetSelected();
1745  else if( aMode == BRIGHTENED )
1746  aItem->SetBrightened();
1747 
1748  if( aGroup )
1749  {
1750  // Hide the original item, so it is shown only on overlay
1751  view()->Hide( aItem, true );
1752 
1753  aGroup->Add( aItem );
1754  }
1755 
1756  // Modules are treated in a special way - when they are highlighted, we have to
1757  // highlight all the parts that make the module, not the module itself
1758  if( aItem->Type() == PCB_MODULE_T )
1759  {
1760  static_cast<MODULE*>( aItem )->RunOnChildren( [&] ( BOARD_ITEM* item )
1761  {
1762  if( aMode == SELECTED )
1763  item->SetSelected();
1764  else if( aMode == BRIGHTENED )
1765  {
1766  item->SetBrightened();
1767 
1768  if( aGroup )
1769  aGroup->Add( item );
1770  }
1771 
1772  if( aGroup )
1773  view()->Hide( item, true );
1774  });
1775  }
1776 
1777  view()->Update( aItem );
1778 
1779  // Many selections are very temporal and updating the display each time just
1780  // creates noise.
1781  if( aMode == BRIGHTENED )
1783 }
1784 
1785 
1786 void SELECTION_TOOL::unhighlight( BOARD_ITEM* aItem, int aMode, PCBNEW_SELECTION* aGroup )
1787 {
1788  if( aMode == SELECTED )
1789  aItem->ClearSelected();
1790  else if( aMode == BRIGHTENED )
1791  aItem->ClearBrightened();
1792 
1793  if( aGroup )
1794  {
1795  aGroup->Remove( aItem );
1796 
1797  // Restore original item visibility
1798  view()->Hide( aItem, false );
1799  }
1800 
1801  // Modules are treated in a special way - when they are highlighted, we have to
1802  // highlight all the parts that make the module, not the module itself
1803  if( aItem->Type() == PCB_MODULE_T )
1804  {
1805  static_cast<MODULE*>( aItem )->RunOnChildren( [&] ( BOARD_ITEM* item )
1806  {
1807  if( aMode == SELECTED )
1808  item->ClearSelected();
1809  else if( aMode == BRIGHTENED )
1810  item->ClearBrightened();
1811 
1812  // N.B. if we clear the selection flag for sub-elements, we need to also
1813  // remove the element from the selection group (if it exists)
1814  if( aGroup )
1815  {
1816  aGroup->Remove( item );
1817 
1818  view()->Hide( item, false );
1819  view()->Update( item );
1820  }
1821  });
1822  }
1823 
1824  view()->Update( aItem );
1825 
1826  // Many selections are very temporal and updating the display each time just
1827  // creates noise.
1828  if( aMode == BRIGHTENED )
1830 }
1831 
1832 
1833 bool SELECTION_TOOL::selectionContains( const VECTOR2I& aPoint ) const
1834 {
1835  const unsigned GRIP_MARGIN = 20;
1836  VECTOR2I margin = getView()->ToWorld( VECTOR2I( GRIP_MARGIN, GRIP_MARGIN ), false );
1837 
1838  // Check if the point is located within any of the currently selected items bounding boxes
1839  for( auto item : m_selection )
1840  {
1841  BOX2I itemBox = item->ViewBBox();
1842  itemBox.Inflate( margin.x, margin.y ); // Give some margin for gripping an item
1843 
1844  if( itemBox.Contains( aPoint ) )
1845  return true;
1846  }
1847 
1848  return false;
1849 }
1850 
1851 
1852 static EDA_RECT getRect( const BOARD_ITEM* aItem )
1853 {
1854  if( aItem->Type() == PCB_MODULE_T )
1855  return static_cast<const MODULE*>( aItem )->GetFootprintRect();
1856 
1857  return aItem->GetBoundingBox();
1858 }
1859 
1860 
1861 static double calcArea( const BOARD_ITEM* aItem )
1862 {
1863  if( aItem->Type() == PCB_TRACE_T )
1864  {
1865  const TRACK* t = static_cast<const TRACK*>( aItem );
1866  return ( t->GetWidth() + t->GetLength() ) * t->GetWidth();
1867  }
1868 
1869  return getRect( aItem ).GetArea();
1870 }
1871 
1872 
1873 /*static double calcMinArea( GENERAL_COLLECTOR& aCollector, KICAD_T aType )
1874 {
1875  double best = std::numeric_limits<double>::max();
1876 
1877  if( !aCollector.GetCount() )
1878  return 0.0;
1879 
1880  for( int i = 0; i < aCollector.GetCount(); i++ )
1881  {
1882  BOARD_ITEM* item = aCollector[i];
1883  if( item->Type() == aType )
1884  best = std::min( best, calcArea( item ) );
1885  }
1886 
1887  return best;
1888 }*/
1889 
1890 
1891 static double calcMaxArea( GENERAL_COLLECTOR& aCollector, KICAD_T aType )
1892 {
1893  double best = 0.0;
1894 
1895  for( int i = 0; i < aCollector.GetCount(); i++ )
1896  {
1897  BOARD_ITEM* item = aCollector[i];
1898  if( item->Type() == aType )
1899  best = std::max( best, calcArea( item ) );
1900  }
1901 
1902  return best;
1903 }
1904 
1905 
1906 static inline double calcCommonArea( const BOARD_ITEM* aItem, const BOARD_ITEM* aOther )
1907 {
1908  if( !aItem || !aOther )
1909  return 0;
1910 
1911  return getRect( aItem ).Common( getRect( aOther ) ).GetArea();
1912 }
1913 
1914 
1915 double calcRatio( double a, double b )
1916 {
1917  if( a == 0.0 && b == 0.0 )
1918  return 1.0;
1919 
1920  if( b == 0.0 )
1921  return std::numeric_limits<double>::max();
1922 
1923  return a / b;
1924 }
1925 
1926 
1927 // The general idea here is that if the user clicks directly on a small item inside a larger
1928 // one, then they want the small item. The quintessential case of this is clicking on a pad
1929 // within a footprint, but we also apply it for text within a footprint, footprints within
1930 // larger footprints, and vias within either larger pads or longer tracks.
1931 //
1932 // These "guesses" presume there is area within the larger item to click in to select it. If
1933 // an item is mostly covered by smaller items within it, then the guesses are inappropriate as
1934 // there might not be any area left to click to select the larger item. In this case we must
1935 // leave the items in the collector and bring up a Selection Clarification menu.
1936 //
1937 // We currently check for pads and text mostly covering a footprint, but we don’t check for
1938 // smaller footprints mostly covering a larger footprint.
1939 //
1941  const VECTOR2I& aWhere ) const
1942 {
1943  std::set<BOARD_ITEM*> preferred;
1944  std::set<BOARD_ITEM*> rejected;
1945  std::set<BOARD_ITEM*> forced;
1946  wxPoint where( aWhere.x, aWhere.y );
1947 
1948  // footprints which are below this percentage of the largest footprint will be considered
1949  // for selection; all others will not
1950  constexpr double footprintToFootprintMinRatio = 0.20;
1951  // pads which are below this percentage of their parent's area will exclude their parent
1952  constexpr double padToFootprintMinRatio = 0.45;
1953  // footprints containing items with items-to-footprint area ratio higher than this will be
1954  // forced to stay on the list
1955  constexpr double footprintMaxCoverRatio = 0.90;
1956  constexpr double viaToPadMinRatio = 0.50;
1957  constexpr double trackViaLengthRatio = 2.0;
1958  constexpr double trackTrackLengthRatio = 0.3;
1959  constexpr double textToFeatureMinRatio = 0.2;
1960  constexpr double textToFootprintMinRatio = 0.4;
1961  // If the common area of two compared items is above the following threshold, they cannot
1962  // be rejected (it means they overlap and it might be hard to pick one by selecting
1963  // its unique area).
1964  constexpr double commonAreaRatio = 0.6;
1965 
1966  PCB_LAYER_ID activeLayer = (PCB_LAYER_ID) view()->GetTopLayer();
1967  LSET silkLayers( 2, B_SilkS, F_SilkS );
1968 
1969  if( silkLayers[activeLayer] )
1970  {
1971  for( int i = 0; i < aCollector.GetCount(); ++i )
1972  {
1973  BOARD_ITEM* item = aCollector[i];
1974  KICAD_T type = item->Type();
1975 
1976  if( ( type == PCB_MODULE_TEXT_T || type == PCB_TEXT_T || type == PCB_LINE_T )
1977  && silkLayers[item->GetLayer()] )
1978  {
1979  preferred.insert( item );
1980  }
1981  }
1982 
1983  if( preferred.size() > 0 )
1984  {
1985  aCollector.Empty();
1986 
1987  for( BOARD_ITEM* item : preferred )
1988  aCollector.Append( item );
1989  return;
1990  }
1991  }
1992 
1993  // Zone edges are very specific; zone fills much less so.
1994  if( aCollector.CountType( PCB_ZONE_AREA_T ) > 0 )
1995  {
1996  for( int i = aCollector.GetCount() - 1; i >= 0; i-- )
1997  {
1998  if( aCollector[i]->Type() == PCB_ZONE_AREA_T )
1999  {
2000  auto zone = static_cast<ZONE_CONTAINER*>( aCollector[i] );
2001 
2002  if( zone->HitTestForEdge( where, 5 * aCollector.GetGuide()->OnePixelInIU() ) )
2003  preferred.insert( zone );
2004  else
2005  rejected.insert( zone );
2006  }
2007  }
2008 
2009  if( preferred.size() > 0 )
2010  {
2011  aCollector.Empty();
2012 
2013  for( BOARD_ITEM* item : preferred )
2014  aCollector.Append( item );
2015  return;
2016  }
2017  }
2018 
2019  if( aCollector.CountType( PCB_MODULE_TEXT_T ) > 0 )
2020  {
2021  for( int i = 0; i < aCollector.GetCount(); ++i )
2022  {
2023  if( TEXTE_MODULE* txt = dyn_cast<TEXTE_MODULE*>( aCollector[i] ) )
2024  {
2025  double textArea = calcArea( txt );
2026 
2027  for( int j = 0; j < aCollector.GetCount(); ++j )
2028  {
2029  if( i == j )
2030  continue;
2031 
2032  BOARD_ITEM* item = aCollector[j];
2033  double itemArea = calcArea( item );
2034  double areaRatio = calcRatio( textArea, itemArea );
2035  double commonArea = calcCommonArea( txt, item );
2036  double itemCommonRatio = calcRatio( commonArea, itemArea );
2037  double txtCommonRatio = calcRatio( commonArea, textArea );
2038 
2039  if( item->Type() == PCB_MODULE_T )
2040  {
2041  // when text area is small compared to an overlapping footprint,
2042  // then it's a clear sign the text is the selection target
2043  if( areaRatio < textToFootprintMinRatio && itemCommonRatio < commonAreaRatio )
2044  rejected.insert( item );
2045  }
2046 
2047  switch( item->Type() )
2048  {
2049  case PCB_TRACE_T:
2050  case PCB_ARC_T:
2051  case PCB_PAD_T:
2052  case PCB_LINE_T:
2053  case PCB_VIA_T:
2054  case PCB_MODULE_T:
2055  if( areaRatio > textToFeatureMinRatio && txtCommonRatio < commonAreaRatio )
2056  rejected.insert( txt );
2057  break;
2058  default:
2059  break;
2060  }
2061  }
2062  }
2063  }
2064  }
2065 
2066  if( aCollector.CountType( PCB_MODULE_EDGE_T ) + aCollector.CountType( PCB_LINE_T ) > 1 )
2067  {
2068  // Prefer exact hits to sloppy ones
2069  int accuracy = KiROUND( 5 * aCollector.GetGuide()->OnePixelInIU() );
2070  bool found = false;
2071 
2072  for( int dist = 0; dist < accuracy; ++dist )
2073  {
2074  for( int i = 0; i < aCollector.GetCount(); ++i )
2075  {
2076  if( DRAWSEGMENT* drawSegment = dynamic_cast<DRAWSEGMENT*>( aCollector[i] ) )
2077  {
2078  if( drawSegment->HitTest( where, dist ) )
2079  {
2080  found = true;
2081  break;
2082  }
2083  }
2084  }
2085 
2086  if( found )
2087  {
2088  // throw out everything that is more sloppy than what we found
2089  for( int i = 0; i < aCollector.GetCount(); ++i )
2090  {
2091  if( DRAWSEGMENT* drawSegment = dynamic_cast<DRAWSEGMENT*>( aCollector[i] ) )
2092  {
2093  if( !drawSegment->HitTest( where, dist ) )
2094  rejected.insert( drawSegment );
2095  }
2096  }
2097 
2098  // we're done now
2099  break;
2100  }
2101  }
2102  }
2103 
2104  if( aCollector.CountType( PCB_PAD_T ) > 0 )
2105  {
2106  for( int i = 0; i < aCollector.GetCount(); ++i )
2107  {
2108  if( D_PAD* pad = dyn_cast<D_PAD*>( aCollector[i] ) )
2109  {
2110  MODULE* parent = pad->GetParent();
2111  double ratio = calcRatio( calcArea( pad ), calcArea( parent ) );
2112 
2113  // when pad area is small compared to the parent footprint,
2114  // then it is a clear sign the pad is the selection target
2115  if( ratio < padToFootprintMinRatio )
2116  rejected.insert( pad->GetParent() );
2117  }
2118  }
2119  }
2120 
2121  if( aCollector.CountType( PCB_MODULE_T ) > 0 )
2122  {
2123  double maxArea = calcMaxArea( aCollector, PCB_MODULE_T );
2124  BOX2D viewportD = getView()->GetViewport();
2125  BOX2I viewport( VECTOR2I( viewportD.GetPosition() ), VECTOR2I( viewportD.GetSize() ) );
2126  double maxCoverRatio = footprintMaxCoverRatio;
2127 
2128  // MODULE::CoverageRatio() doesn't take zone handles & borders into account so just
2129  // use a more aggressive cutoff point if zones are involved.
2130  if( aCollector.CountType( PCB_ZONE_AREA_T ) )
2131  maxCoverRatio /= 2;
2132 
2133  for( int i = 0; i < aCollector.GetCount(); ++i )
2134  {
2135  if( MODULE* mod = dyn_cast<MODULE*>( aCollector[i] ) )
2136  {
2137  // filter out components larger than the viewport
2138  if( mod->ViewBBox().Contains( viewport ) )
2139  rejected.insert( mod );
2140  // footprints completely covered with other features have no other
2141  // means of selection, so must be kept
2142  else if( mod->CoverageRatio( aCollector ) > maxCoverRatio )
2143  rejected.erase( mod );
2144  // if a footprint is much smaller than the largest overlapping
2145  // footprint then it should be considered for selection
2146  else if( calcRatio( calcArea( mod ), maxArea ) <= footprintToFootprintMinRatio )
2147  continue;
2148  // reject ALL OTHER footprints if there's still something else left
2149  // to select
2150  else if( (int)( rejected.size() + 1 ) < aCollector.GetCount() )
2151  rejected.insert( mod );
2152  }
2153  }
2154  }
2155 
2156  if( aCollector.CountType( PCB_VIA_T ) > 0 )
2157  {
2158  for( int i = 0; i < aCollector.GetCount(); ++i )
2159  {
2160  if( VIA* via = dyn_cast<VIA*>( aCollector[i] ) )
2161  {
2162  double viaArea = calcArea( via );
2163 
2164  for( int j = 0; j < aCollector.GetCount(); ++j )
2165  {
2166  if( i == j )
2167  continue;
2168 
2169  BOARD_ITEM* item = aCollector[j];
2170  double areaRatio = calcRatio( viaArea, calcArea( item ) );
2171 
2172  if( item->Type() == PCB_MODULE_T && areaRatio < padToFootprintMinRatio )
2173  rejected.insert( item );
2174 
2175  if( item->Type() == PCB_PAD_T && areaRatio < viaToPadMinRatio )
2176  rejected.insert( item );
2177 
2178  if( TRACK* track = dyn_cast<TRACK*>( item ) )
2179  {
2180  if( track->GetNetCode() != via->GetNetCode() )
2181  continue;
2182 
2183  double lenRatio = (double) ( track->GetLength() + track->GetWidth() ) /
2184  (double) via->GetWidth();
2185 
2186  if( lenRatio > trackViaLengthRatio )
2187  rejected.insert( track );
2188  }
2189  }
2190  }
2191  }
2192  }
2193 
2194  int nTracks = aCollector.CountType( PCB_TRACE_T );
2195 
2196  if( nTracks > 0 )
2197  {
2198  double maxLength = 0.0;
2199  double minLength = std::numeric_limits<double>::max();
2200  double maxArea = 0.0;
2201  const TRACK* maxTrack = nullptr;
2202 
2203  for( int i = 0; i < aCollector.GetCount(); ++i )
2204  {
2205  if( TRACK* track = dyn_cast<TRACK*>( aCollector[i] ) )
2206  {
2207  maxLength = std::max( track->GetLength(), maxLength );
2208  maxLength = std::max( (double) track->GetWidth(), maxLength );
2209 
2210  minLength = std::min( std::max( track->GetLength(), (double) track->GetWidth() ), minLength );
2211 
2212  double area = track->GetLength() * track->GetWidth();
2213 
2214  if( area > maxArea )
2215  {
2216  maxArea = area;
2217  maxTrack = track;
2218  }
2219  }
2220  }
2221 
2222  if( maxLength > 0.0 && minLength / maxLength < trackTrackLengthRatio && nTracks > 1 )
2223  {
2224  for( int i = 0; i < aCollector.GetCount(); ++i )
2225  {
2226  if( TRACK* track = dyn_cast<TRACK*>( aCollector[i] ) )
2227  {
2228  double ratio = std::max( (double) track->GetWidth(), track->GetLength() ) / maxLength;
2229 
2230  if( ratio > trackTrackLengthRatio )
2231  rejected.insert( track );
2232  }
2233  }
2234  }
2235 
2236  for( int j = 0; j < aCollector.GetCount(); ++j )
2237  {
2238  if( MODULE* mod = dyn_cast<MODULE*>( aCollector[j] ) )
2239  {
2240  double ratio = calcRatio( maxArea, mod->GetFootprintRect().GetArea() );
2241 
2242  if( ratio < padToFootprintMinRatio && calcCommonArea( maxTrack, mod ) < commonAreaRatio )
2243  rejected.insert( mod );
2244  }
2245  }
2246  }
2247 
2248  if( (unsigned) aCollector.GetCount() > rejected.size() ) // do not remove everything
2249  {
2250  for( BOARD_ITEM* item : rejected )
2251  {
2252  aCollector.Remove( item );
2253  }
2254  }
2255 }
2256 
2257 
2259 {
2260  getView()->Update( &m_selection );
2261 
2262  return 0;
2263 }
2264 
2265 
2267 {
2268  ACTION_MENU* actionMenu = aEvent.Parameter<ACTION_MENU*>();
2269  CONDITIONAL_MENU* conditionalMenu = dynamic_cast<CONDITIONAL_MENU*>( actionMenu );
2270 
2271  if( conditionalMenu )
2272  conditionalMenu->Evaluate( m_selection );
2273 
2274  if( actionMenu )
2275  actionMenu->UpdateAll();
2276 
2277  return 0;
2278 }
2279 
2280 
2282 {
2284 
2288 
2294 
2295  Go( &SELECTION_TOOL::find, ACTIONS::find.MakeEvent() );
2296 
2303 }
2304 
2305 
static TOOL_ACTION selectItems
Selects a list of items (specified as the event parameter)
Definition: pcb_actions.h:80
void Empty()
Function Empty sets the list to empty.
Definition: collector.h:109
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:73
static TOOL_ACTION selectionActivate
Activation of the selection tool.
Definition: pcb_actions.h:67
void GuessSelectionCandidates(GENERAL_COLLECTOR &aCollector, const VECTOR2I &aWhere) const
Function guessSelectionCandidates() Tries to guess best selection candidates in case multiple items a...
void Hide(VIEW_ITEM *aItem, bool aHide=true)
Temporarily hides the item in the view (e.g.
Definition: view.cpp:1507
void AddMenu(ACTION_MENU *aMenu, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Function AddMenu()
void ClearReferencePoint()
Definition: selection.h:249
int UnselectItem(const TOOL_EVENT &aEvent)
Item unselection event handler.
int Main(const TOOL_EVENT &aEvent)
Function Main()
int UpdateMenu(const TOOL_EVENT &aEvent)
Pass the selection to a conditional menu for updating.
void AddStandardSubMenus(TOOL_MENU &aMenu)
Function CreateBasicMenu.
void SetIgnoreTracks(bool ignore)
Definition: collectors.h:607
wxMenuItem * Add(const wxString &aLabel, int aId, const BITMAP_OPAQUE *aIcon)
Function Add() Adds a wxWidgets-style entry to the menu.
to draw blind/buried vias
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
DIALOG_FILTER_SELECTION::OPTIONS m_filterOpts
static const TOOL_EVENT SelectedEvent
Definition: actions.h:201
BOX2D GetViewport() const
Function GetViewport() Returns the current viewport visible area rectangle.
Definition: view.cpp:538
void SetEnd(VECTOR2I aEnd)
Set the current end of the rectangle (the corner that moves with the cursor.
TOOL_MENU m_menu
functions below are not yet implemented - their interface may change
static EDA_RECT getRect(const BOARD_ITEM *aItem)
virtual void Clear() override
Function Clear() Removes all the stored items from the group.
Definition: selection.h:94
void ForceRefresh()
Function ForceRefresh() Forces a redraw.
int GetNetCode() const
Function GetNetCode.
static double calcCommonArea(const BOARD_ITEM *aItem, const BOARD_ITEM *aOther)
std::function< SEARCH_RESULT(EDA_ITEM *aItem, void *aTestData) > INSPECTOR_FUNC
Typedef INSPECTOR is used to inspect and possibly collect the (search) results of iterating over a li...
Definition: base_struct.h:83
static const KICAD_T AllBoardItems[]
A scan list for all editable board items.
Definition: collectors.h:267
void SetIgnoreBlindBuriedVias(bool ignore)
Definition: collectors.h:601
static const KICAD_T Tracks[]
A scan list for only TRACKS.
Definition: collectors.h:313
static const int dist[10][10]
Definition: ar_matrix.cpp:326
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
virtual LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
BOARD * board() const
std::unique_ptr< PRIV > m_priv
like PAD_STANDARD, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:66
bool IsSelected() const
Definition: base_struct.h:225
Model changes (required full reload)
Definition: tool_base.h:81
multilayer pads, usually with holes
static const TOOL_EVENT UnselectedEvent
Definition: actions.h:202
int selectSameSheet(const TOOL_EVENT &aEvent)
Selects all modules belonging to same hierarchical sheet as the selected footprint.
virtual void Update(VIEW_ITEM *aItem, int aUpdateFlags) override
For dynamic VIEWs, informs the associated VIEW that the graphical representation of this item has cha...
Definition: pcb_view.cpp:91
ACTION_MENU.
Definition: action_menu.h:43
This file is part of the common library.
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
VECTOR2D ToWorld(const VECTOR2D &aCoord, bool aAbsolute=true) const
Function ToWorld() Converts a screen space point/vector to a point/vector in world space coordinates.
Definition: view.cpp:475
void SetOrigin(VECTOR2I aOrigin)
Set the origin of the rectange (the fixed corner)
void ClearSelected()
Definition: base_struct.h:235
const BITMAP_OPAQUE options_generic_xpm[1]
void SetCurrentCursor(wxStockCursor aStockCursorID)
Function SetCurrentCursor Set the current cursor shape for this panel.
const wxPoint & GetStart() const
Definition: class_track.h:111
VIEW_CONTROLS class definition.
void Collect(BOARD_ITEM *aItem, const KICAD_T aScanList[], const wxPoint &aRefPos, const COLLECTORS_GUIDE &aGuide)
Scan a BOARD_ITEM using this class's Inspector method, which does the collection.
Definition: collectors.cpp:535
Classes BOARD_ITEM and BOARD_CONNECTED_ITEM.
virtual double OnePixelInIU() const =0
void SetIgnoreModulesVals(bool ignore)
Definition: collectors.h:589
void SetIgnoreMicroVias(bool ignore)
Definition: collectors.h:604
SELECTION_TOOL.
void SetIgnoreModulesOnBack(bool ignore)
Definition: collectors.h:559
SELECTION_LOCK_FLAGS CheckLock()
Checks if the user has agreed to modify locked items for the given selection.
static TOOL_ACTION unselectItem
Definition: pcb_actions.h:77
#define SKIP_STRUCT
flag indicating that the structure should be ignored
Definition: base_struct.h:131
virtual unsigned int ViewGetLOD(int aLayer, VIEW *aView) const
Function ViewGetLOD() Returns the level of detail (LOD) of the item.
Definition: view_item.h:140
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
CONDITIONAL_MENU & GetMenu()
Function GetMenu.
Definition: tool_menu.cpp:46
the 3d code uses this value
Definition: typeinfo.h:80
static TOOL_ACTION selectNet
Selects all connections belonging to a single net.
Definition: pcb_actions.h:91
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:218
ITER end()
Definition: selection.h:61
static TOOL_ACTION unselectItems
Definition: pcb_actions.h:81
const GENERAL_COLLECTORS_GUIDE getCollectorsGuide() const
int find(const TOOL_EVENT &aEvent)
Find an item.
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:62
class ZONE_CONTAINER, a zone area
Definition: typeinfo.h:102
virtual void Remove(VIEW_ITEM *aItem)
Function Remove() Removes a VIEW_ITEM from the view.
Definition: view.cpp:376
static TOOL_ACTION properties
Activation of the edit tool.
Definition: pcb_actions.h:120
virtual void ViewGetLayers(int aLayers[], int &aCount) const override
Function ViewGetLayers() Returns the all the layers within the VIEW the object is painted on.
ITER begin()
Definition: collector.h:91
int GetWidth() const
Definition: eda_rect.h:119
int UnselectItems(const TOOL_EVENT &aEvent)
Multiple item unselection event handler
PADS & Pads()
Definition: class_module.h:173
void SetBrightened()
Definition: base_struct.h:233
PCBNEW_SELECTION m_selection
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
void SetIgnoreModulesRefs(bool ignore)
Definition: collectors.h:595
LSET GetVisibleLayers() const
Function GetVisibleLayers is a proxy function that calls the correspondent function in m_BoardSetting...
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:139
static TOOL_ACTION selectionMenu
Runs a selection menu to select from a list of items.
Definition: pcb_actions.h:84
static TOOL_ACTION selectConnection
Selects tracks between junctions or expands an existing selection to pads or the entire connection.
Definition: pcb_actions.h:88
class ARC, an arc track segment on a copper layer
Definition: typeinfo.h:98
Class that groups generic conditions for selected items.
void SetExclusiveOr(bool aExclusiveOr)
show modules values (when texts are visibles)
Template specialization to enable wxStrings for certain containers (e.g. unordered_map)
Definition: bitmap.cpp:56
EDA_RECT GetFootprintRect() const
Function GetFootprintRect() Returns the area of the module footprint excluding any text.
ITER end()
Definition: collector.h:92
EDA_RECT Common(const EDA_RECT &aRect) const
Function Common returns the area that is common with another rectangle.
class D_PAD, a pad in a footprint
Definition: typeinfo.h:90
#define BUSY
Pcbnew: flag indicating that the structure has.
Definition: base_struct.h:140
void UpdateAll()
Function UpdateAll() Runs update handlers for the menu and its submenus.
const KIID_PATH & GetPath() const
Definition: class_module.h:228
Struct that will be set with the result of the user choices in the dialog.
DRAWINGS & GraphicalItems()
Definition: class_module.h:183
const COLLECTORS_GUIDE * GetGuide()
Definition: collectors.h:347
void SetContextMenu(ACTION_MENU *aMenu, CONTEXT_MENU_TRIGGER aTrigger=CMENU_BUTTON)
Function SetContextMenu()
static TOOL_ACTION find
Definition: actions.h:78
void(* CLIENT_SELECTION_FILTER)(const VECTOR2I &, GENERAL_COLLECTOR &)
VECTOR2< int > VECTOR2I
Definition: vector2d.h:594
int CountType(KICAD_T aType)
Function CountType counts the number of items matching aType.
Definition: collector.h:216
bool selectionContains(const VECTOR2I &aPoint) const
Function selectionContains()
const PCB_DISPLAY_OPTIONS & GetDisplayOptions() const
Function GetDisplayOptions returns the display options current in use Display options are relative to...
static double calcArea(const BOARD_ITEM *aItem)
BOARD_CONNECTED_ITEM is a base class derived from BOARD_ITEM for items that can be connected and have...
static bool NotEmpty(const SELECTION &aSelection)
Function NotEmpty Tests if there are any items selected.
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Function Go()
void select(BOARD_ITEM *aItem)
Function select() Takes necessary action mark an item as selected.
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
bool Contains(const wxPoint &aPoint) const
Function Contains.
void Remove(int aIndex)
Function Remove removes the item at aIndex (first position is 0);.
Definition: collector.h:129
virtual void Remove(VIEW_ITEM *aItem) override
Function Remove() Removes a VIEW_ITEM from the view.
Definition: pcb_view.cpp:74
search types array terminator (End Of Types)
Definition: typeinfo.h:82
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:78
static const TOOL_EVENT SelectedItemsModified
Definition: actions.h:205
PAINTER * GetPainter() const
Function GetPainter() Returns the painter object used by the view for drawing VIEW_ITEMS.
Definition: view.h:199
static constexpr int VIEW_MAX_LAYERS
maximum number of layers that may be shown
Definition: view.h:701
Definitions for tracks, vias and zones.
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96
void SetIsHover(bool aIsHover)
Definition: selection.h:65
BOARD_ITEM * pickSmallestComponent(GENERAL_COLLECTOR *aCollector)
Function pickSmallestComponent() Allows one to find the smallest (in terms of bounding box area) item...
Private implementation of firewalled private data.
virtual void Add(EDA_ITEM *aItem)
Definition: selection.h:75
void highlight(BOARD_ITEM *aItem, int aHighlightMode, PCBNEW_SELECTION *aGroup=nullptr)
Function highlight() Highlights the item visually.
PCBNEW_SELECTION & GetSelection()
Function GetSelection()
void ClearBrightened()
Definition: base_struct.h:237
void Append(EDA_ITEM *item)
Function Append adds an item to the end of the list.
Definition: collector.h:119
void SetAdditive(bool aAdditive)
show modules on front
PCB_BASE_EDIT_FRAME * frame() const
virtual bool HitTest(const wxPoint &aPosition, int aAccuracy=0) const
Function HitTest tests if aPosition is contained within or on the bounding box of an item.
Definition: base_struct.h:332
void findCallback(BOARD_ITEM *aItem)
Find dialog callback.
SEARCH_RESULT Visit(INSPECTOR inspector, void *testData, const KICAD_T scanTypes[]) override
Function Visit may be re-implemented for each derived class in order to handle all the types given by...
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:100
int filterSelection(const TOOL_EVENT &aEvent)
Invoke filter dialog and modify current selection
#define SELECTED
Definition: base_struct.h:127
int expandConnection(const TOOL_EVENT &aEvent)
Expands the current track selection to the next boundary (junctions, pads, or all)
ITER begin()
Definition: selection.h:60
Definition: common.h:65
class MODULE, a footprint
Definition: typeinfo.h:89
bool selectPoint(const VECTOR2I &aWhere, bool aOnDrag=false, bool *aSelectionCancelledFlag=NULL, CLIENT_SELECTION_FILTER aClientFilter=NULL)
Function selectPoint() Selects an item pointed by the parameter aWhere.
bool selectCursor(bool aForceSelect=false, CLIENT_SELECTION_FILTER aClientFilter=NULL)
Function selectCursor() Selects an item under the cursor unless there is something already selected o...
PCB_LAYER_ID
A quick note on layer IDs:
void UnbrightenItem(BOARD_ITEM *aItem)
LSET is a set of PCB_LAYER_IDs.
const PCBNEW_SELECTION & selection() const
void SetCenter(const VECTOR2D &aCenter)
Function SetCenter() Sets the center point of the VIEW (i.e.
Definition: view.cpp:604
static double calcMaxArea(GENERAL_COLLECTOR &aCollector, KICAD_T aType)
#define NULL
void SetSelected()
Definition: base_struct.h:231
void SetIgnoreMTextsOnBack(bool ignore)
Definition: collectors.h:547
int updateSelection(const TOOL_EVENT &aEvent)
Event handler to update the selection VIEW_ITEM.
void SetHighlight(bool aEnabled, int aNetcode=-1, bool aHighlightItems=false)
Function SetHighlight Turns on/off highlighting - it may be done for the active layer,...
Definition: painter.h:136
void SetIgnorePadsOnFront(bool ignore)
Definition: collectors.h:577
int ClearSelection(const TOOL_EVENT &aEvent)
Clear current selection event handler.
void MarkTargetDirty(int aTarget)
Function MarkTargetDirty() Sets or clears target 'dirty' flag.
Definition: view.h:585
bool selectMultiple()
Function selectMultiple() Handles drawing a selection box that allows one to select many items at the...
void selectAllItemsOnNet(int aNetCode)
Selects all items with the given net code.
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagates an event to tools that requested events of matching type(s).
bool IsVisible(const VIEW_ITEM *aItem) const
Returns information if the item is visible (or not).
Definition: view.cpp:1526
void SetIgnoreMTextsOnFront(bool ignore)
Definition: collectors.h:553
void connectedItemFilter(const VECTOR2I &, GENERAL_COLLECTOR &aCollector)
SELECTION_LOCK_FLAGS
Definition: selection.h:278
T Parameter() const
Function Parameter() Returns a non-standard parameter assigned to the event.
Definition: tool_event.h:435
virtual int GetTopLayer() const
Definition: view.cpp:851
void SetIcon(const BITMAP_OPAQUE *aIcon)
Function SetIcon() Assigns an icon for the entry.
Definition: action_menu.cpp:68
bool Contains(const Vec &aPoint) const
Function Contains.
Definition: box2.h:150
to draw usual through hole vias
TOOL_EVENT.
Definition: tool_event.h:171
void AddItemToSel(BOARD_ITEM *aItem, bool aQuietMode=false)
bool Contains(EDA_ITEM *aItem) const
Definition: selection.h:112
const BOX2I ViewBBox() const override
Function ViewBBox() returns the bounding box of the item covering all its layers.
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:306
const std::deque< EDA_ITEM * > GetItems() const
Definition: selection.h:131
KIGFX::PCB_VIEW * view() const
#define BRIGHTENED
item is drawn with a bright contour
Definition: base_struct.h:143
void RemoveItemFromSel(BOARD_ITEM *aItem, bool aQuietMode=false)
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
EDA_ITEM * GetParent() const
Definition: base_struct.h:217
PCB_BASE_FRAME * m_frame
Items that may change while the view stays the same (noncached)
Definition: definitions.h:50
static const TOOL_EVENT ClearedEvent
Definition: actions.h:203
int SelectionMenu(const TOOL_EVENT &aEvent)
Function SelectionMenu() Shows a popup menu to trim the COLLECTOR passed as aEvent's parameter down t...
double GetArea() const
Function GetArea returns the area of the rectangle.
static TOOL_ACTION updateMenu
Definition: actions.h:162
int selectSheetContents(const TOOL_EVENT &aEvent)
Selects all modules belonging to same sheet, from Eeschema, using crossprobing
void SetIgnoreMTextsMarkedNoShow(bool ignore)
Definition: collectors.h:541
virtual void Update(VIEW_ITEM *aItem, int aUpdateFlags)
For dynamic VIEWs, informs the associated VIEW that the graphical representation of this item has cha...
Definition: view.cpp:1540
int SelectItem(const TOOL_EVENT &aEvent)
Item selection event handler.
Like smd, does not appear on the solder paste layer (default) note also has a special attribute in Ge...
Definition: pad_shapes.h:63
class DIMENSION, a dimension (graphic item)
Definition: typeinfo.h:100
const BITMAP_OPAQUE info_xpm[1]
Definition: info.cpp:75
virtual void SetLayer(int aLayer)
Function SetLayer() Sets layer used to draw the group.
Definition: view_group.h:115
static TOOL_ACTION hideDynamicRatsnest
Definition: pcb_actions.h:421
const MODULE_ZONE_CONTAINERS & Zones() const
Definition: class_module.h:188
int GetHeight() const
Definition: eda_rect.h:120
KIGFX::VIEW * getView() const
Function getView()
Definition: tool_base.cpp:36
virtual void SetAutoPan(bool aEnabled)
Function SetAutoPan Turns on/off auto panning (this feature is used when there is a tool active (eg.
int selectNet(const TOOL_EVENT &aEvent)
Selects all copper connections belonging to the same net(s) as the items in the selection.
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:120
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:101
virtual const wxPoint GetPosition() const =0
static TOOL_ACTION drag
Definition: pcb_actions.h:104
bool IsMirroredX() const
Function IsMirroredX() Returns true if view is flipped across the X axis.
Definition: view.h:230
static TOOL_ACTION clearHighlight
Definition: pcb_actions.h:408
void SetSubtractive(bool aSubtractive)
const Vec & GetPosition() const
Definition: box2.h:193
bool IsElementVisible(GAL_LAYER_ID aLayer) const
Function IsElementVisible tests whether a given element category is visible.
virtual unsigned int GetSize() const override
Function GetSize() Returns the number of stored items.
Definition: selection.h:99
virtual void SetScale(double aScale, VECTOR2D aAnchor={ 0, 0 })
Function SetScale() Sets the scaling factor, zooming around a given anchor point.
Definition: view.cpp:578
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:93
static TOOL_ACTION filterSelection
Filters the items in the current selection (invokes dialog)
Definition: pcb_actions.h:100
void Normalize()
Function Normalize ensures that the height ant width are positive.
void SetCallback(boost::function< void(BOARD_ITEM *)> aCallback)
Function to be called on each found event.
Definition: dialog_find.h:62
bool GetHighContrast() const
Function GetHighContrast Returns information about high contrast display mode.
Definition: painter.h:158
virtual RENDER_SETTINGS * GetSettings()=0
Function GetSettings Returns pointer to current settings that are going to be used when drawing items...
static bool itemIsIncludedByFilter(const BOARD_ITEM &aItem, const BOARD &aBoard, const DIALOG_FILTER_SELECTION::OPTIONS &aFilterOptions)
Function itemIsIncludedByFilter()
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:301
bool IsLayerVisible(PCB_LAYER_ID aLayer) const
Function IsLayerVisible is a proxy function that calls the correspondent function in m_BoardSettings ...
Definition: class_board.h:431
class MARKER_PCB, a marker used to show something
Definition: typeinfo.h:99
const int scale
void SetTitle(const wxString &aTitle) override
Function SetTitle() Sets title for the menu.
Definition: action_menu.cpp:86
smd pads, front layer
PCBNEW_SELECTION & RequestSelection(CLIENT_SELECTION_FILTER aClientFilter, std::vector< BOARD_ITEM * > *aFiltered=nullptr, bool aConfirmLockedItems=false)
Function RequestSelection()
void SetState(int type, int state)
Definition: base_struct.h:246
int GetWidth() const
Definition: class_track.h:105
bool ToolStackIsEmpty()
bool IsType(FRAME_T aType) const
Class to handle a graphic segment.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
static TOOL_ACTION selectOnSheetFromEeschema
Selects all components on sheet from Eeschema crossprobing.
Definition: pcb_actions.h:94
BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:163
MODULE * module() const
#define _(s)
Definition: 3d_actions.cpp:33
static const KICAD_T ModuleItems[]
A scan list for primary module items.
Definition: collectors.h:308
bool Selectable(const BOARD_ITEM *aItem, bool checkVisibilityOnly=false) const
Function selectable() Checks conditions for an item to be selected.
void SetIgnoreModulesOnFront(bool ignore)
Definition: collectors.h:565
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:240
void SetIgnoreThroughVias(bool ignore)
Definition: collectors.h:598
virtual wxString GetSelectMenuText(EDA_UNITS aUnits) const
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
void AddSubMenu(std::shared_ptr< ACTION_MENU > aSubMenu)
Function CreateSubMenu.
Definition: tool_menu.cpp:52
void unselect(BOARD_ITEM *aItem)
Function unselect() Takes necessary action mark an item as unselected.
static TOOL_ACTION selectItem
Selects an item (specified as the event parameter).
Definition: pcb_actions.h:76
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
int Size() const
Returns the number of selected parts.
Definition: selection.h:126
VIATYPE GetViaType() const
Definition: class_track.h:416
currently selected items overlay
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:61
void RebuildSelection()
Rebuilds the selection from the EDA_ITEMs' selection flags.
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: base_struct.h:166
double calcRatio(double a, double b)
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:78
const wxPoint & GetEnd() const
Definition: class_track.h:108
boost::optional< T > OPT
Definition: optional.h:7
virtual double GetLength() const
Function GetLength returns the length of the track using the hypotenuse calculation.
Definition: class_track.h:141
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Sets the item visibility.
Definition: view.cpp:1486
int SelectItems(const TOOL_EVENT &aEvent)
Multiple item selection event handler
ACTION_MENU * create() const override
Returns an instance of this class. It has to be overridden in inheriting classes.
void zoomFitSelection()
Zooms the screen to center and fit the current selection.
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1) override
Function Add() Adds a VIEW_ITEM to the view.
Definition: pcb_view.cpp:58
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Function Add() Adds a VIEW_ITEM to the view.
Definition: view.cpp:346
const Vec & GetSize() const
Definition: box2.h:188
virtual int Query(const BOX2I &aRect, std::vector< LAYER_ITEM_PAIR > &aResult) const
Function Query() Finds all visible items that touch or are within the rectangle aRect.
Definition: view.cpp:452
Module description (excepted pads)
void selectConnectedTracks(BOARD_CONNECTED_ITEM &aSourceItem, KICAD_T aStopCondition)
Selects connecteed tracks and vias.
virtual const EDA_RECT GetBoundingBox() const
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:42
VIEW.
Definition: view.h:61
bool doSelectionMenu(GENERAL_COLLECTOR *aItems, const wxString &aTitle)
Allows the selection of a single item from a list via pop-up menu.
A general implementation of a COLLECTORS_GUIDE.
Definition: collectors.h:385
void BrightenItem(BOARD_ITEM *aItem)
const wxPoint GetPosition() const override
Definition: class_pad.h:241
double GetScale() const
Function GetScale()
Definition: view.h:257
EDGE_MODULE class definition.
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
BOARD_ITEM_CONTAINER * GetParent() const
void FocusOnLocation(const wxPoint &aPos)
Useful to focus on a particular location, in find functions Move the graphic cursor (crosshair cursor...
void selectAllItemsOnSheet(wxString &aSheetID)
Selects all items with the given sheet timestamp name (the sheet path)
virtual BITMAP_DEF GetMenuImage() const
Function GetMenuImage returns a pointer to an image to be used in menus.
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
int GetState(int type) const
Definition: base_struct.h:241
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:283
EDA_RECT GetBoundingBox() const
Definition: selection.h:155
void ShowContextMenu(SELECTION &aSelection)
Function ShowContextMenu.
Definition: tool_menu.cpp:59
void FocusOnItem(BOARD_ITEM *aItem)
void setTransitions() override
Sets up handlers for various events.
int CursorSelection(const TOOL_EVENT &aEvent)
Select a single item under cursor event handler.
static TOOL_ACTION selectionCursor
Select a single item under the cursor position.
Definition: pcb_actions.h:70
void SetIgnoreThroughHolePads(bool ignore)
Definition: collectors.h:583
void unhighlight(BOARD_ITEM *aItem, int aHighlightMode, PCBNEW_SELECTION *aGroup=nullptr)
Function unhighlight() Unhighlights the item visually.
show modules references (when texts are visibles)
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
void SetIgnoreZoneFills(bool ignore)
Definition: collectors.h:610
void update() override
Update menu state stub.
EDA_ITEM * Front() const
Definition: selection.h:183
KICAD_T Type() const
Function Type()
Definition: base_struct.h:212
const std::set< unsigned int > GetActiveLayers()
Function GetActiveLayers() Returns the set of currently active layers.
Definition: painter.h:84
static TOOL_ACTION selectSameSheet
Selects all components on the same sheet as the selected footprint.
Definition: pcb_actions.h:97
void SetIgnorePadsOnBack(bool ignore)
Definition: collectors.h:571
void DisplayTitle(bool aDisplay=true)
Function DisplayTitle() Decides whether a title for a pop up menu should be displayed.
Definition: action_menu.cpp:97
virtual const BOX2I ViewBBox() const override
Function ViewBBox() Returns the bounding box for all stored items covering all its layers.
Definition: selection.h:142
virtual void Remove(EDA_ITEM *aItem)
Definition: selection.h:86