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 <pcbnew_settings.h>
47 #include <tool/tool_event.h>
48 #include <tool/tool_manager.h>
49 #include <router/router_tool.h>
51 #include <footprint_viewer_frame.h>
52 #include <id.h>
53 #include "tool_event_utils.h"
54 #include "selection_tool.h"
55 #include "pcb_bright_box.h"
56 #include "pcb_actions.h"
57 
58 #include "kicad_plugin.h"
59 
60 
61 class SELECT_MENU : public ACTION_MENU
62 {
63 public:
65  ACTION_MENU( true )
66  {
67  SetTitle( _( "Select" ) );
68  SetIcon( options_generic_xpm );
69 
71 
72  AppendSeparator();
73 
77  }
78 
79 private:
80 
81  void update() override
82  {
83  using S_C = SELECTION_CONDITIONS;
84 
85  const auto& selection = getToolManager()->GetTool<SELECTION_TOOL>()->GetSelection();
86 
87  bool connItem = S_C::OnlyTypes( GENERAL_COLLECTOR::Tracks )( selection );
88  bool sheetSelEnabled = ( S_C::OnlyType( PCB_MODULE_T ) )( selection );
89 
90  Enable( getMenuId( PCB_ACTIONS::selectNet ), connItem );
91  Enable( getMenuId( PCB_ACTIONS::selectConnection ), connItem );
92  Enable( getMenuId( PCB_ACTIONS::selectSameSheet ), sheetSelEnabled );
93  }
94 
95  ACTION_MENU* create() const override
96  {
97  return new SELECT_MENU();
98  }
99 };
100 
101 
106 {
107 public:
109 };
110 
111 
113  PCB_TOOL_BASE( "pcbnew.InteractiveSelection" ),
114  m_frame( NULL ),
115  m_additive( false ),
116  m_subtractive( false ),
117  m_exclusive_or( false ),
118  m_multiple( false ),
119  m_skip_heuristics( false ),
120  m_locked( true ),
121  m_priv( std::make_unique<PRIV>() )
122 {
123  m_filter.lockedItems = true;
124  m_filter.footprints = true;
125  m_filter.text = true;
126  m_filter.tracks = true;
127  m_filter.vias = true;
128  m_filter.pads = true;
129  m_filter.graphics = true;
130  m_filter.zones = true;
131  m_filter.keepouts = true;
132  m_filter.dimensions = true;
133  m_filter.otherItems = true;
134 }
135 
136 
138 {
139  getView()->Remove( &m_selection );
140 }
141 
142 
144 {
145  auto frame = getEditFrame<PCB_BASE_FRAME>();
146 
149  {
151  return true;
152  }
153 
154  auto selectMenu = std::make_shared<SELECT_MENU>();
155  selectMenu->SetTool( this );
156  m_menu.AddSubMenu( selectMenu );
157 
158  auto& menu = m_menu.GetMenu();
159 
160  menu.AddMenu( selectMenu.get(), SELECTION_CONDITIONS::NotEmpty );
161  menu.AddSeparator( 1000 );
162 
163  if( frame )
165 
166  return true;
167 }
168 
169 
171 {
172  m_frame = getEditFrame<PCB_BASE_FRAME>();
173  m_locked = true;
174 
175  if( aReason == TOOL_BASE::MODEL_RELOAD )
176  {
177  // Deselect any item being currently in edit, to avoid unexpected behavior
178  // and remove pointers to the selected items from containers
179  // without changing their properties (as they are already deleted
180  // while a new board is loaded)
181  ClearSelection( true );
182 
183  getView()->GetPainter()->GetSettings()->SetHighlight( false );
184  }
185  else
186  {
187  // Restore previous properties of selected items and remove them from containers
188  ClearSelection( true );
189  }
190 
191  // Reinsert the VIEW_GROUP, in case it was removed from the VIEW
192  view()->Remove( &m_selection );
193  view()->Add( &m_selection );
194 }
195 
196 
197 int SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
198 {
199  // Main loop: keep receiving events
200  while( TOOL_EVENT* evt = Wait() )
201  {
202  if( m_frame->ToolStackIsEmpty() )
203  m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
204 
205  bool dragAlwaysSelects = getEditFrame<PCB_BASE_FRAME>()->GetDragSelects();
206  TRACK_DRAG_ACTION dragAction = getEditFrame<PCB_BASE_FRAME>()->Settings().m_TrackDragAction;
208 
209  // OSX uses CTRL for context menu, and SHIFT is exclusive-or
210 #ifdef __WXOSX_MAC__
211  if( evt->Modifier( MD_SHIFT ) )
212  m_exclusive_or = true;
213 #else
214  if( evt->Modifier( MD_SHIFT ) && evt->Modifier( MD_CTRL ) )
215  m_subtractive = true;
216  else if( evt->Modifier( MD_SHIFT ) )
217  m_additive = true;
218  else if( evt->Modifier( MD_CTRL ) )
219  m_exclusive_or = true;
220 #endif
221 
222  // Is the user requesting that the selection list include all possible
223  // items without removing less likely selection candidates
224  m_skip_heuristics = !!evt->Modifier( MD_ALT );
225 
226  // Single click? Select single object
227  if( evt->IsClick( BUT_LEFT ) )
228  {
229  m_frame->FocusOnItem( nullptr );
230 
231  selectPoint( evt->Position() );
232  }
233 
234  // right click? if there is any object - show the context menu
235  else if( evt->IsClick( BUT_RIGHT ) )
236  {
237  bool selectionCancelled = false;
238 
239  if( m_selection.Empty() ||
240  !m_selection.GetBoundingBox().Contains( wxPoint( evt->Position() ) ) )
241  {
242  ClearSelection();
243  selectPoint( evt->Position(), false, &selectionCancelled );
244  m_selection.SetIsHover( true );
245  }
246 
247  if( !selectionCancelled )
249  }
250 
251  // double click? Display the properties window
252  else if( evt->IsDblClick( BUT_LEFT ) )
253  {
254  m_frame->FocusOnItem( nullptr );
255 
256  if( m_selection.Empty() )
257  selectPoint( evt->Position() );
258 
260  }
261 
262  // drag with LMB? Select multiple objects (or at least draw a selection box) or drag them
263  else if( evt->IsDrag( BUT_LEFT ) )
264  {
265  m_frame->FocusOnItem( nullptr );
266 
267  if( m_additive || m_subtractive || m_exclusive_or || dragAlwaysSelects )
268  {
269  selectMultiple();
270  }
271  else
272  {
273  // selection is empty? try to start dragging the item under the point where drag
274  // started
275  if( m_selection.Empty() && selectCursor() )
276  m_selection.SetIsHover( true );
277 
278  // Check if dragging has started within any of selected items bounding box
279  if( selectionContains( evt->Position() ) )
280  {
281  // Yes -> run the move tool and wait till it finishes
282  TRACK* track = dynamic_cast<TRACK*>( m_selection.GetItem( 0 ) );
283 
284  if( track && dragAction == TRACK_DRAG_ACTION::DRAG )
286  else if( track && dragAction == TRACK_DRAG_ACTION::DRAG_FREE_ANGLE )
288  else
290  }
291  else
292  {
293  // No -> drag a selection box
294  selectMultiple();
295  }
296  }
297  }
298 
299  else if( evt->IsCancel() )
300  {
301  m_frame->FocusOnItem( nullptr );
302 
303  ClearSelection();
304 
305  if( evt->FirstResponder() == this )
307  }
308 
309  else if( evt->Action() == TA_UNDO_REDO_PRE )
310  {
311  ClearSelection();
312  }
313 
314  else
315  evt->SetPassEvent();
316  }
317 
318  return 0;
319 }
320 
321 
323 {
324  return m_selection;
325 }
326 
327 
329  std::vector<BOARD_ITEM*>* aFiltered,
330  bool aConfirmLockedItems )
331 {
332  bool selectionEmpty = m_selection.Empty();
333  m_selection.SetIsHover( selectionEmpty );
334 
335  if( selectionEmpty )
336  {
337  m_toolMgr->RunAction( PCB_ACTIONS::selectionCursor, true, aClientFilter );
339  }
340 
341  if ( aConfirmLockedItems && CheckLock() == SELECTION_LOCKED )
342  {
343  ClearSelection();
344  return m_selection;
345  }
346 
347  if( aClientFilter )
348  {
349  GENERAL_COLLECTOR collector;
350 
351  for( auto item : m_selection )
352  collector.Append( item );
353 
354  aClientFilter( VECTOR2I(), collector );
355 
356  /*
357  * The first step is to find the items that may have been added by the client filter
358  * This can happen if the locked pads select the module instead
359  */
360  std::vector<EDA_ITEM*> new_items;
361  std::set_difference( collector.begin(), collector.end(),
363  std::back_inserter( new_items ) );
364 
368  std::vector<EDA_ITEM*> diff;
369  std::set_difference( m_selection.begin(), m_selection.end(),
370  collector.begin(), collector.end(),
371  std::back_inserter( diff ) );
372 
373  if( aFiltered )
374  {
375  for( auto item : diff )
376  aFiltered->push_back( static_cast<BOARD_ITEM*>( item ) );
377  }
378 
383  for( auto item : diff )
384  unhighlight( static_cast<BOARD_ITEM*>( item ), SELECTED, &m_selection );
385 
386  for( auto item : new_items )
387  highlight( static_cast<BOARD_ITEM*>( item ), SELECTED, &m_selection );
388 
390  }
391 
392  return m_selection;
393 }
394 
395 
397 {
398  GENERAL_COLLECTORS_GUIDE guide( board()->GetVisibleLayers(),
399  (PCB_LAYER_ID) view()->GetTopLayer(), view() );
400 
401  // account for the globals
402  guide.SetIgnoreMTextsMarkedNoShow( ! board()->IsElementVisible( LAYER_MOD_TEXT_INVISIBLE ) );
403  guide.SetIgnoreMTextsOnBack( ! board()->IsElementVisible( LAYER_MOD_TEXT_BK ) );
404  guide.SetIgnoreMTextsOnFront( ! board()->IsElementVisible( LAYER_MOD_TEXT_FR ) );
405  guide.SetIgnoreModulesOnBack( ! board()->IsElementVisible( LAYER_MOD_BK ) );
406  guide.SetIgnoreModulesOnFront( ! board()->IsElementVisible( LAYER_MOD_FR ) );
407  guide.SetIgnorePadsOnBack( ! board()->IsElementVisible( LAYER_PAD_BK ) );
408  guide.SetIgnorePadsOnFront( ! board()->IsElementVisible( LAYER_PAD_FR ) );
409  guide.SetIgnoreThroughHolePads( ! board()->IsElementVisible( LAYER_PADS_TH ) );
410  guide.SetIgnoreModulesVals( ! board()->IsElementVisible( LAYER_MOD_VALUES ) );
411  guide.SetIgnoreModulesRefs( ! board()->IsElementVisible( LAYER_MOD_REFERENCES ) );
412  guide.SetIgnoreThroughVias( ! board()->IsElementVisible( LAYER_VIA_THROUGH ) );
413  guide.SetIgnoreBlindBuriedVias( ! board()->IsElementVisible( LAYER_VIA_BBLIND ) );
414  guide.SetIgnoreMicroVias( ! board()->IsElementVisible( LAYER_VIA_MICROVIA ) );
415  guide.SetIgnoreTracks( ! board()->IsElementVisible( LAYER_TRACKS ) );
416 
417  return guide;
418 }
419 
420 
421 bool SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag,
422  bool* aSelectionCancelledFlag,
423  CLIENT_SELECTION_FILTER aClientFilter )
424 {
426  GENERAL_COLLECTOR collector;
427  auto& displayOpts = m_frame->GetDisplayOptions();
428 
429  guide.SetIgnoreZoneFills( displayOpts.m_DisplayZonesMode != 0 );
430 
431  collector.Collect( board(),
433  wxPoint( aWhere.x, aWhere.y ), guide );
434 
435  // Remove unselectable items
436  for( int i = collector.GetCount() - 1; i >= 0; --i )
437  {
438  if( !Selectable( collector[ i ] ) || ( aOnDrag && collector[i]->IsLocked() ) )
439  collector.Remove( i );
440  }
441 
443 
444  // Allow the client to do tool- or action-specific filtering to see if we
445  // can get down to a single item
446  if( aClientFilter )
447  aClientFilter( aWhere, collector );
448 
449  // Apply the stateful filter
450  filterCollectedItems( collector );
451 
452  // Apply some ugly heuristics to avoid disambiguation menus whenever possible
453  if( collector.GetCount() > 1 && !m_skip_heuristics )
454  {
455  GuessSelectionCandidates( collector, aWhere );
456  }
457 
458  // If still more than one item we're going to have to ask the user.
459  if( collector.GetCount() > 1 )
460  {
461  if( aOnDrag )
463 
464  if( !doSelectionMenu( &collector, _( "Clarify Selection" ) ) )
465  {
466  if( aSelectionCancelledFlag )
467  *aSelectionCancelledFlag = true;
468 
469  return false;
470  }
471  }
472 
473  bool anyAdded = false;
474  bool anySubtracted = false;
475 
477  {
478  if( m_selection.GetSize() > 0 )
479  {
480  ClearSelection( true /*quiet mode*/ );
481  anySubtracted = true;
482  }
483  }
484 
485  if( collector.GetCount() > 0 )
486  {
487  for( int i = 0; i < collector.GetCount(); ++i )
488  {
489  if( m_subtractive || ( m_exclusive_or && collector[i]->IsSelected() ) )
490  {
491  unselect( collector[i] );
492  anySubtracted = true;
493  }
494  else
495  {
496  select( collector[i] );
497  anyAdded = true;
498  }
499  }
500  }
501 
502  if( anyAdded )
503  {
505  return true;
506  }
507  else if( anySubtracted )
508  {
510  return true;
511  }
512 
513  return false;
514 }
515 
516 
517 bool SELECTION_TOOL::selectCursor( bool aForceSelect, CLIENT_SELECTION_FILTER aClientFilter )
518 {
519  if( aForceSelect || m_selection.Empty() )
520  {
521  ClearSelection( true /*quiet mode*/ );
522  selectPoint( getViewControls()->GetCursorPosition( false ), false, NULL, aClientFilter );
523  }
524 
525  return !m_selection.Empty();
526 }
527 
528 
530 {
531  bool cancelled = false; // Was the tool cancelled while it was running?
532  m_multiple = true; // Multiple selection mode is active
533  KIGFX::VIEW* view = getView();
534 
536  view->Add( &area );
537 
538  bool anyAdded = false;
539  bool anySubtracted = false;
540 
541  while( TOOL_EVENT* evt = Wait() )
542  {
543  if( evt->IsCancelInteractive() || evt->IsActivate() )
544  {
545  cancelled = true;
546  break;
547  }
548 
549  if( evt->IsDrag( BUT_LEFT ) )
550  {
552  {
553  if( m_selection.GetSize() > 0 )
554  {
555  anySubtracted = true;
556  ClearSelection( true /*quiet mode*/ );
557  }
558  }
559 
560  // Start drawing a selection box
561  area.SetOrigin( evt->DragOrigin() );
562  area.SetEnd( evt->Position() );
563  area.SetAdditive( m_additive );
566 
567  view->SetVisible( &area, true );
568  view->Update( &area );
569  getViewControls()->SetAutoPan( true );
570  }
571 
572  if( evt->IsMouseUp( BUT_LEFT ) )
573  {
574  getViewControls()->SetAutoPan( false );
575 
576  // End drawing the selection box
577  view->SetVisible( &area, false );
578 
579  // Mark items within the selection box as selected
580  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
581 
582  // Filter the view items based on the selection box
583  BOX2I selectionBox = area.ViewBBox();
584  view->Query( selectionBox, selectedItems ); // Get the list of selected items
585 
586  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR>::iterator it, it_end;
587 
588  int width = area.GetEnd().x - area.GetOrigin().x;
589  int height = area.GetEnd().y - area.GetOrigin().y;
590 
591  /* Selection mode depends on direction of drag-selection:
592  * Left > Right : Select objects that are fully enclosed by selection
593  * Right > Left : Select objects that are crossed by selection
594  */
595  bool windowSelection = width >= 0 ? true : false;
596 
597  if( view->IsMirroredX() )
598  windowSelection = !windowSelection;
599 
600  // Construct an EDA_RECT to determine BOARD_ITEM selection
601  EDA_RECT selectionRect( (wxPoint) area.GetOrigin(), wxSize( width, height ) );
602 
603  selectionRect.Normalize();
604 
605  for( it = selectedItems.begin(), it_end = selectedItems.end(); it != it_end; ++it )
606  {
607  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( it->first );
608 
609  if( !item || !Selectable( item ) || !itemPassesFilter( item ) )
610  continue;
611 
612  if( item->HitTest( selectionRect, windowSelection ) )
613  {
614  if( m_subtractive || ( m_exclusive_or && item->IsSelected() ) )
615  {
616  unselect( item );
617  anySubtracted = true;
618  }
619  else
620  {
621  select( item );
622  anyAdded = true;
623  }
624  }
625  }
626 
627  m_selection.SetIsHover( false );
628 
629  // Inform other potentially interested tools
630  if( anyAdded )
632  else if( anySubtracted )
634 
635  break; // Stop waiting for events
636  }
637  }
638 
639  getViewControls()->SetAutoPan( false );
640 
641  // Stop drawing the selection box
642  view->Remove( &area );
643  m_multiple = false; // Multiple selection mode is inactive
644 
645  if( !cancelled )
647 
648  return cancelled;
649 }
650 
651 
653 {
654  if( !m_locked || m_editModules )
655  return SELECTION_UNLOCKED;
656 
657  bool containsLocked = false;
658 
659  // Check if the selection contains locked items
660  for( const auto& item : m_selection )
661  {
662  switch( item->Type() )
663  {
664  case PCB_MODULE_T:
665  if( static_cast<MODULE*>( item )->IsLocked() )
666  containsLocked = true;
667  break;
668 
669  case PCB_MODULE_EDGE_T:
670  case PCB_MODULE_TEXT_T:
672  if( static_cast<MODULE*>( item->GetParent() )->IsLocked() )
673  containsLocked = true;
674  break;
675 
676  default: // suppress warnings
677  break;
678  }
679  }
680 
681  if( containsLocked )
682  {
683  if( IsOK( m_frame, _( "Selection contains locked items. Do you want to continue?" ) ) )
684  {
685  m_locked = false;
687  }
688  else
689  return SELECTION_LOCKED;
690  }
691 
692  return SELECTION_UNLOCKED;
693 }
694 
695 
697 {
699 
700  selectCursor( false, aClientFilter );
701 
702  return 0;
703 }
704 
705 
707 {
708  ClearSelection();
709 
710  return 0;
711 }
712 
713 
715 {
716  std::vector<BOARD_ITEM*>* items = aEvent.Parameter<std::vector<BOARD_ITEM*>*>();
717 
718  if( items )
719  {
720  // Perform individual selection of each item before processing the event.
721  for( auto item : *items )
722  select( item );
723 
725  }
726 
727  return 0;
728 }
729 
730 
732 {
733  AddItemToSel( aEvent.Parameter<BOARD_ITEM*>() );
734  return 0;
735 }
736 
737 
738 void SELECTION_TOOL::AddItemToSel( BOARD_ITEM* aItem, bool aQuietMode )
739 {
740  if( aItem )
741  {
742  select( aItem );
743 
744  // Inform other potentially interested tools
745  if( !aQuietMode )
747  }
748 }
749 
750 
752 {
753  std::vector<BOARD_ITEM*>* items = aEvent.Parameter<std::vector<BOARD_ITEM*>*>();
754 
755  if( items )
756  {
757  // Perform individual unselection of each item before processing the event
758  for( auto item : *items )
759  unselect( item );
760 
762  }
763 
764  return 0;
765 }
766 
767 
769 {
770  RemoveItemFromSel( aEvent.Parameter<BOARD_ITEM*>() );
771  return 0;
772 }
773 
774 
775 void SELECTION_TOOL::RemoveItemFromSel( BOARD_ITEM* aItem, bool aQuietMode )
776 {
777  if( aItem )
778  {
779  unselect( aItem );
780 
781  // Inform other potentially interested tools
783  }
784 }
785 
786 
788 {
789  highlight( aItem, BRIGHTENED );
790 }
791 
792 
794 {
795  unhighlight( aItem, BRIGHTENED );
796 }
797 
798 
799 void connectedItemFilter( const VECTOR2I&, GENERAL_COLLECTOR& aCollector )
800 {
801  // Narrow the collection down to a single BOARD_CONNECTED_ITEM for each represented net.
802  // All other items types are removed.
803  std::set<int> representedNets;
804 
805  for( int i = aCollector.GetCount() - 1; i >= 0; i-- )
806  {
807  BOARD_CONNECTED_ITEM* item = dynamic_cast<BOARD_CONNECTED_ITEM*>( aCollector[i] );
808  if( !item )
809  aCollector.Remove( i );
810  else if ( representedNets.count( item->GetNetCode() ) )
811  aCollector.Remove( i );
812  else
813  representedNets.insert( item->GetNetCode() );
814  }
815 }
816 
817 
819 {
820  unsigned initialCount = 0;
821 
822  for( auto item : m_selection.GetItems() )
823  {
824  if( dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
825  initialCount++;
826  }
827 
828  if( initialCount == 0 )
830 
831  for( STOP_CONDITION stopCondition : { STOP_AT_JUNCTION, STOP_AT_PAD, STOP_NEVER } )
832  {
833  // copy the selection, since we're going to iterate and modify
834  std::deque<EDA_ITEM*> selectedItems = m_selection.GetItems();
835 
836  for( EDA_ITEM* item : selectedItems )
837  item->ClearTempFlags();
838 
839  for( EDA_ITEM* item : selectedItems )
840  {
841  TRACK* trackItem = dynamic_cast<TRACK*>( item );
842 
843  // Track items marked SKIP_STRUCT have already been visited
844  if( trackItem && !( trackItem->GetFlags() & SKIP_STRUCT ) )
845  selectConnectedTracks( *trackItem, stopCondition );
846  }
847 
848  if( m_selection.GetItems().size() > initialCount )
849  break;
850  }
851 
852  // Inform other potentially interested tools
853  if( m_selection.Size() > 0 )
855 
856  return 0;
857 }
858 
859 
861  STOP_CONDITION aStopCondition )
862 {
863  constexpr KICAD_T types[] = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T, EOT };
864 
865  auto connectivity = board()->GetConnectivity();
866  auto connectedItems = connectivity->GetConnectedItems( &aStartItem, types );
867 
868  std::map<wxPoint, std::vector<TRACK*>> trackMap;
869  std::map<wxPoint, VIA*> viaMap;
870  std::map<wxPoint, D_PAD*> padMap;
871 
872  // Build maps of connected items
873  for( BOARD_CONNECTED_ITEM* item : connectedItems )
874  {
875  switch( item->Type() )
876  {
877  case PCB_TRACE_T:
878  {
879  TRACK* track = static_cast<TRACK*>( item );
880  trackMap[ track->GetStart() ].push_back( track );
881  trackMap[ track->GetEnd() ].push_back( track );
882  }
883  break;
884  case PCB_VIA_T:
885  {
886  VIA* via = static_cast<VIA*>( item );
887  viaMap[ via->GetStart() ] = via;
888  }
889  break;
890  case PCB_PAD_T:
891  {
892  D_PAD* pad = static_cast<D_PAD*>( item );
893  padMap[ pad->GetPosition() ] = pad;
894  }
895  break;
896  default:
897  break;
898  }
899 
900  item->SetFlags( SKIP_STRUCT );
901  }
902 
903  std::vector<wxPoint> activePts;
904 
905  // Set up the initial active points
906  switch( aStartItem.Type() )
907  {
908  case PCB_TRACE_T:
909  activePts.push_back( static_cast<TRACK*>( &aStartItem )->GetStart() );
910  activePts.push_back( static_cast<TRACK*>( &aStartItem )->GetEnd() );
911  break;
912  case PCB_VIA_T:
913  activePts.push_back( static_cast<TRACK*>( &aStartItem )->GetStart() );
914  break;
915  case PCB_PAD_T:
916  activePts.push_back( aStartItem.GetPosition() );
917  break;
918  default:
919  break;
920  }
921 
922  bool expand = true;
923 
924  // Iterative push from all active points
925  while( expand )
926  {
927  expand = false;
928 
929  for( int i = activePts.size() - 1; i >= 0; --i )
930  {
931  wxPoint pt = activePts[i];
932 
933  if( trackMap[ pt ].size() > 2 && aStopCondition == STOP_AT_JUNCTION )
934  {
935  activePts.erase( activePts.begin() + i );
936  continue;
937  }
938 
939  if( padMap.count( pt ) && aStopCondition != STOP_NEVER )
940  {
941  activePts.erase( activePts.begin() + i );
942  continue;
943  }
944 
945  for( TRACK* track : trackMap[ pt ] )
946  {
947  if( track->GetState( SKIP_STRUCT ) )
948  continue;
949 
950  track->SetState( SKIP_STRUCT, true );
951  select( track );
952 
953  if( track->GetStart() == pt )
954  activePts.push_back( track->GetEnd() );
955  else
956  activePts.push_back( track->GetStart() );
957 
958  expand = true;
959  }
960 
961  if( viaMap.count( pt ) && !viaMap[ pt ]->IsSelected() )
962  select( viaMap[ pt ] );
963 
964  activePts.erase( activePts.begin() + i );
965  }
966  }
967 }
968 
969 
971 {
972  constexpr KICAD_T types[] = { PCB_TRACE_T, PCB_VIA_T, EOT };
973  auto connectivity = board()->GetConnectivity();
974 
975  for( BOARD_CONNECTED_ITEM* item : connectivity->GetNetItems( aNetCode, types ) )
976  select( item );
977 }
978 
979 
981 {
982  if( !selectCursor() )
983  return 0;
984 
985  // copy the selection, since we're going to iterate and modify
986  auto selection = m_selection.GetItems();
987 
988  for( EDA_ITEM* i : selection )
989  {
990  BOARD_CONNECTED_ITEM* connItem = dynamic_cast<BOARD_CONNECTED_ITEM*>( i );
991 
992  if( connItem )
993  selectAllItemsOnNet( connItem->GetNetCode() );
994  }
995 
996  // Inform other potentially interested tools
997  if( m_selection.Size() > 0 )
999 
1000  return 0;
1001 }
1002 
1003 
1004 void SELECTION_TOOL::selectAllItemsOnSheet( wxString& aSheetPath )
1005 {
1006  std::list<MODULE*> modList;
1007 
1008  // store all modules that are on that sheet path
1009  for( MODULE* module : board()->Modules() )
1010  {
1011  if( module == nullptr )
1012  continue;
1013 
1014  wxString footprint_path = module->GetPath().AsString().BeforeLast('/');
1015 
1016  if( aSheetPath.IsEmpty() )
1017  aSheetPath += '/';
1018 
1019  if( footprint_path == aSheetPath )
1020  modList.push_back( module );
1021  }
1022 
1023  //Generate a list of all pads, and of all nets they belong to.
1024  std::list<int> netcodeList;
1025  std::list<D_PAD*> padList;
1026  for( MODULE* mmod : modList )
1027  {
1028  for( D_PAD* pad : mmod->Pads() )
1029  {
1030  if( pad->IsConnected() )
1031  {
1032  netcodeList.push_back( pad->GetNetCode() );
1033  padList.push_back( pad );
1034  }
1035  }
1036  }
1037  // remove all duplicates
1038  netcodeList.sort();
1039  netcodeList.unique();
1040 
1041  // auto select trivial connections segments which are launched from the pads
1042  std::list<TRACK*> launchTracks;
1043 
1044  for( D_PAD* pad : padList )
1046 
1047  // now we need to find all modules that are connected to each of these nets
1048  // then we need to determine if these modules are in the list of modules
1049  // belonging to this sheet ( modList )
1050  std::list<int> removeCodeList;
1051  constexpr KICAD_T padType[] = { PCB_PAD_T, EOT };
1052 
1053  for( int netCode : netcodeList )
1054  {
1055  for( BOARD_CONNECTED_ITEM* mitem : board()->GetConnectivity()->GetNetItems( netCode, padType ) )
1056  {
1057  if( mitem->Type() == PCB_PAD_T)
1058  {
1059  bool found = std::find( modList.begin(), modList.end(), mitem->GetParent() ) != modList.end();
1060 
1061  if( !found )
1062  {
1063  // if we cannot find the module of the pad in the modList
1064  // then we can assume that that module is not located in the same
1065  // schematic, therefore invalidate this netcode.
1066  removeCodeList.push_back( netCode );
1067  break;
1068  }
1069  }
1070  }
1071  }
1072 
1073  // remove all duplicates
1074  removeCodeList.sort();
1075  removeCodeList.unique();
1076 
1077  for( int removeCode : removeCodeList )
1078  {
1079  netcodeList.remove( removeCode );
1080  }
1081 
1082  std::list<BOARD_CONNECTED_ITEM*> localConnectionList;
1083  constexpr KICAD_T trackViaType[] = { PCB_TRACE_T, PCB_VIA_T, EOT };
1084 
1085  for( int netCode : netcodeList )
1086  {
1087  for( BOARD_CONNECTED_ITEM* item : board()->GetConnectivity()->GetNetItems( netCode, trackViaType ) )
1088  localConnectionList.push_back( item );
1089  }
1090 
1091  for( BOARD_ITEM* i : modList )
1092  {
1093  if( i != NULL )
1094  select( i );
1095  }
1096 
1097  for( BOARD_CONNECTED_ITEM* i : localConnectionList )
1098  {
1099  if( i != NULL )
1100  select( i );
1101  }
1102 }
1103 
1104 
1106 {
1107  //Should recalculate the view to zoom in on the selection
1108  auto selectionBox = m_selection.GetBoundingBox();
1109  auto view = getView();
1110 
1111  VECTOR2D screenSize = view->ToWorld( m_frame->GetCanvas()->GetClientSize(), false );
1112  screenSize.x = std::max( 10.0, screenSize.x );
1113  screenSize.y = std::max( 10.0, screenSize.y );
1114 
1115  if( selectionBox.GetWidth() != 0 || selectionBox.GetHeight() != 0 )
1116  {
1117  VECTOR2D vsize = selectionBox.GetSize();
1118  double scale = view->GetScale() / std::max( fabs( vsize.x / screenSize.x ),
1119  fabs( vsize.y / screenSize.y ) );
1120  view->SetScale( scale );
1121  view->SetCenter( selectionBox.Centre() );
1122  view->Add( &m_selection );
1123  }
1124 
1126 }
1127 
1128 
1130 {
1131  ClearSelection( true /*quiet mode*/ );
1132  wxString sheetPath = *aEvent.Parameter<wxString*>();
1133 
1134  selectAllItemsOnSheet( sheetPath );
1135 
1136  zoomFitSelection();
1137 
1138  if( m_selection.Size() > 0 )
1140 
1141  return 0;
1142 }
1143 
1144 
1146 {
1147  if( !selectCursor( true ) )
1148  return 0;
1149 
1150  // this function currently only supports modules since they are only
1151  // on one sheet.
1152  auto item = m_selection.Front();
1153 
1154  if( !item )
1155  return 0;
1156 
1157  if( item->Type() != PCB_MODULE_T )
1158  return 0;
1159 
1160  auto mod = dynamic_cast<MODULE*>( item );
1161 
1162  if( mod->GetPath().empty() )
1163  return 0;
1164 
1165  ClearSelection( true /*quiet mode*/ );
1166 
1167  // get the sheet path only.
1168  wxString sheetPath = mod->GetPath().AsString().BeforeLast( '/' );
1169 
1170  if( sheetPath.IsEmpty() )
1171  sheetPath += '/';
1172 
1173  selectAllItemsOnSheet( sheetPath );
1174 
1175  // Inform other potentially interested tools
1176  if( m_selection.Size() > 0 )
1178 
1179  return 0;
1180 }
1181 
1182 
1184 {
1185  bool cleared = false;
1186 
1187  if( m_selection.GetSize() > 0 )
1188  {
1189  // Don't fire an event now; most of the time it will be redundant as we're about to
1190  // fire a SelectedEvent.
1191  cleared = true;
1192  ClearSelection( true /*quiet mode*/ );
1193  }
1194 
1195  if( aItem )
1196  {
1197  select( aItem );
1198  m_frame->FocusOnLocation( aItem->GetPosition() );
1199 
1200  // Inform other potentially interested tools
1202  }
1203  else if( cleared )
1204  {
1206  }
1207 
1209 }
1210 
1211 
1212 int SELECTION_TOOL::find( const TOOL_EVENT& aEvent )
1213 {
1214  DIALOG_FIND dlg( m_frame );
1215  dlg.SetCallback( std::bind( &SELECTION_TOOL::findCallback, this, _1 ) );
1216  dlg.ShowModal();
1217 
1218  return 0;
1219 }
1220 
1221 
1229 static bool itemIsIncludedByFilter( const BOARD_ITEM& aItem, const BOARD& aBoard,
1230  const DIALOG_FILTER_SELECTION::OPTIONS& aFilterOptions )
1231 {
1232  bool include = true;
1233  const PCB_LAYER_ID layer = aItem.GetLayer();
1234 
1235  // if the item needs to be checked against the options
1236  if( include )
1237  {
1238  switch( aItem.Type() )
1239  {
1240  case PCB_MODULE_T:
1241  {
1242  const auto& module = static_cast<const MODULE&>( aItem );
1243 
1244  include = aFilterOptions.includeModules;
1245 
1246  if( include && !aFilterOptions.includeLockedModules )
1247  {
1248  include = !module.IsLocked();
1249  }
1250 
1251  break;
1252  }
1253  case PCB_TRACE_T:
1254  case PCB_ARC_T:
1255  {
1256  include = aFilterOptions.includeTracks;
1257  break;
1258  }
1259  case PCB_VIA_T:
1260  {
1261  include = aFilterOptions.includeVias;
1262  break;
1263  }
1264  case PCB_ZONE_AREA_T:
1265  {
1266  include = aFilterOptions.includeZones;
1267  break;
1268  }
1269  case PCB_LINE_T:
1270  case PCB_TARGET_T:
1271  case PCB_DIMENSION_T:
1272  {
1273  if( layer == Edge_Cuts )
1274  include = aFilterOptions.includeBoardOutlineLayer;
1275  else
1276  include = aFilterOptions.includeItemsOnTechLayers;
1277  break;
1278  }
1279  case PCB_TEXT_T:
1280  {
1281  include = aFilterOptions.includePcbTexts;
1282  break;
1283  }
1284  default:
1285  {
1286  // no filtering, just select it
1287  break;
1288  }
1289  }
1290  }
1291 
1292  return include;
1293 }
1294 
1295 
1297 {
1298  const BOARD& board = *getModel<BOARD>();
1299  DIALOG_FILTER_SELECTION::OPTIONS& opts = m_priv->m_filterOpts;
1300  DIALOG_FILTER_SELECTION dlg( m_frame, opts );
1301 
1302  const int cmd = dlg.ShowModal();
1303 
1304  if( cmd != wxID_OK )
1305  return 0;
1306 
1307  // copy current selection
1308  std::deque<EDA_ITEM*> selection = m_selection.GetItems();
1309 
1310  ClearSelection( true /*quiet mode*/ );
1311 
1312  // re-select items from the saved selection according to the dialog options
1313  for( EDA_ITEM* i : selection )
1314  {
1315  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( i );
1316  bool include = itemIsIncludedByFilter( *item, board, opts );
1317 
1318  if( include )
1319  select( item );
1320  }
1321 
1323 
1324  return 0;
1325 }
1326 
1327 
1329 {
1330  if( aCollector.GetCount() == 0 )
1331  return;
1332 
1333  std::set<BOARD_ITEM*> rejected;
1334 
1335  for( EDA_ITEM* i : aCollector )
1336  {
1337  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( i );
1338 
1339  if( !itemPassesFilter( item ) )
1340  rejected.insert( item );
1341  }
1342 
1343  for( BOARD_ITEM* item : rejected )
1344  aCollector.Remove( item );
1345 }
1346 
1347 
1349 {
1350  if( aItem->IsLocked() && !m_filter.lockedItems )
1351  return false;
1352 
1353  switch( aItem->Type() )
1354  {
1355  case PCB_MODULE_T:
1356  if( !m_filter.footprints )
1357  return false;
1358 
1359  break;
1360 
1361  case PCB_PAD_T:
1362  if( !m_filter.pads )
1363  return false;
1364 
1365  break;
1366 
1367  case PCB_TRACE_T:
1368  case PCB_ARC_T:
1369  if( !m_filter.tracks )
1370  return false;
1371 
1372  break;
1373 
1374  case PCB_VIA_T:
1375  if( !m_filter.vias )
1376  return false;
1377 
1378  break;
1379 
1380  case PCB_ZONE_AREA_T:
1381  {
1382  ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( aItem );
1383 
1384  if( ( !m_filter.zones && !zone->GetIsKeepout() )
1385  || ( !m_filter.keepouts && zone->GetIsKeepout() ) )
1386  {
1387  return false;
1388  }
1389 
1390  break;
1391  }
1392  case PCB_LINE_T:
1393  case PCB_TARGET_T:
1394  if( !m_filter.graphics )
1395  return false;
1396 
1397  break;
1398 
1399  case PCB_MODULE_TEXT_T:
1400  case PCB_TEXT_T:
1401  if( !m_filter.text )
1402  return false;
1403 
1404  break;
1405 
1406  case PCB_DIMENSION_T:
1407  if( !m_filter.dimensions )
1408  return false;
1409 
1410  break;
1411 
1412  default:
1413  if( !m_filter.otherItems )
1414  return false;
1415  }
1416 
1417  return true;
1418 }
1419 
1420 
1421 void SELECTION_TOOL::ClearSelection( bool aQuietMode )
1422 {
1423  if( m_selection.Empty() )
1424  return;
1425 
1426  while( m_selection.GetSize() )
1427  unhighlight( static_cast<BOARD_ITEM*>( m_selection.Front() ), SELECTED, &m_selection );
1428 
1429  view()->Update( &m_selection );
1430 
1431  m_selection.SetIsHover( false );
1433 
1434  m_locked = true;
1435 
1436  // Inform other potentially interested tools
1437  if( !aQuietMode )
1438  {
1441  }
1442 }
1443 
1444 
1446 {
1447  m_selection.Clear();
1448 
1449  INSPECTOR_FUNC inspector = [&] ( EDA_ITEM* item, void* testData )
1450  {
1451  if( item->IsSelected() )
1452  {
1453  EDA_ITEM* parent = item->GetParent();
1454 
1455  // Flags on module children might be set only because the parent is selected.
1456  if( parent && parent->Type() == PCB_MODULE_T && parent->IsSelected() )
1457  return SEARCH_RESULT::CONTINUE;
1458 
1459  highlight( (BOARD_ITEM*) item, SELECTED, &m_selection );
1460  }
1461 
1462  return SEARCH_RESULT::CONTINUE;
1463  };
1464 
1465  board()->Visit( inspector, nullptr, m_editModules ? GENERAL_COLLECTOR::ModuleItems
1467 }
1468 
1469 
1471 {
1472  GENERAL_COLLECTOR* collector = aEvent.Parameter<GENERAL_COLLECTOR*>();
1473 
1474  doSelectionMenu( collector, wxEmptyString );
1475 
1476  return 0;
1477 }
1478 
1479 
1480 bool SELECTION_TOOL::doSelectionMenu( GENERAL_COLLECTOR* aCollector, const wxString& aTitle )
1481 {
1482  BOARD_ITEM* current = nullptr;
1483  PCBNEW_SELECTION highlightGroup;
1484  ACTION_MENU menu( true );
1485  bool selectAll = false;
1486 
1487  highlightGroup.SetLayer( LAYER_SELECT_OVERLAY );
1488  getView()->Add( &highlightGroup );
1489 
1490  int limit = std::min( 9, aCollector->GetCount() );
1491 
1492  for( int i = 0; i < limit; ++i )
1493  {
1494  wxString text;
1495  BOARD_ITEM* item = ( *aCollector )[i];
1496  text = item->GetSelectMenuText( m_frame->GetUserUnits() );
1497 
1498  wxString menuText = wxString::Format( "&%d. %s\t%d", i + 1, text, i + 1 );
1499  menu.Add( menuText, i + 1, item->GetMenuImage() );
1500  }
1501 
1502  menu.AppendSeparator();
1503  menu.Add( _( "Select &All\tA" ), limit + 1, net_highlight_xpm );
1504 
1505  if( aTitle.Length() )
1506  menu.SetTitle( aTitle );
1507 
1508  menu.SetIcon( info_xpm );
1509  menu.DisplayTitle( true );
1510  SetContextMenu( &menu, CMENU_NOW );
1511 
1512  while( TOOL_EVENT* evt = Wait() )
1513  {
1514  if( evt->Action() == TA_CHOICE_MENU_UPDATE )
1515  {
1516  if( selectAll )
1517  {
1518  for( int i = 0; i < aCollector->GetCount(); ++i )
1519  unhighlight( ( *aCollector )[i], BRIGHTENED, &highlightGroup );
1520  }
1521  else if( current )
1522  unhighlight( current, BRIGHTENED, &highlightGroup );
1523 
1524  int id = *evt->GetCommandId();
1525 
1526  // User has pointed an item, so show it in a different way
1527  if( id > 0 && id <= limit )
1528  {
1529  current = ( *aCollector )[id - 1];
1530  highlight( current, BRIGHTENED, &highlightGroup );
1531  }
1532  else
1533  current = nullptr;
1534 
1535  // User has pointed on the "Select All" option
1536  if( id == limit + 1 )
1537  {
1538  for( int i = 0; i < aCollector->GetCount(); ++i )
1539  highlight( ( *aCollector )[i], BRIGHTENED, &highlightGroup );
1540  selectAll = true;
1541  }
1542  else
1543  selectAll = false;
1544  }
1545  else if( evt->Action() == TA_CHOICE_MENU_CHOICE )
1546  {
1547  if( selectAll )
1548  {
1549  for( int i = 0; i < aCollector->GetCount(); ++i )
1550  unhighlight( ( *aCollector )[i], BRIGHTENED, &highlightGroup );
1551  }
1552  else if( current )
1553  unhighlight( current, BRIGHTENED, &highlightGroup );
1554 
1555  OPT<int> id = evt->GetCommandId();
1556 
1557  // User has selected the "Select All" option
1558  if( id == limit + 1 )
1559  {
1560  selectAll = true;
1561  current = nullptr;
1562  }
1563  // User has selected an item, so this one will be returned
1564  else if( id && ( *id > 0 ) && ( *id <= limit ) )
1565  {
1566  selectAll = false;
1567  current = ( *aCollector )[*id - 1];
1568  }
1569  else
1570  {
1571  selectAll = false;
1572  current = nullptr;
1573  }
1574 
1575  break;
1576  }
1577  }
1578  getView()->Remove( &highlightGroup );
1579 
1580  if( selectAll )
1581  return true;
1582  else if( current )
1583  {
1584  aCollector->Empty();
1585  aCollector->Append( current );
1586  return true;
1587  }
1588 
1589  return false;
1590 }
1591 
1592 
1594 {
1595  int count = aCollector->GetPrimaryCount(); // try to use preferred layer
1596 
1597  if( 0 == count )
1598  count = aCollector->GetCount();
1599 
1600  for( int i = 0; i < count; ++i )
1601  {
1602  if( ( *aCollector )[i]->Type() != PCB_MODULE_T )
1603  return NULL;
1604  }
1605 
1606  // All are modules, now find smallest MODULE
1607  int minDim = 0x7FFFFFFF;
1608  int minNdx = 0;
1609 
1610  for( int i = 0; i < count; ++i )
1611  {
1612  MODULE* module = (MODULE*) ( *aCollector )[i];
1613 
1614  int lx = module->GetFootprintRect().GetWidth();
1615  int ly = module->GetFootprintRect().GetHeight();
1616 
1617  int lmin = std::min( lx, ly );
1618 
1619  if( lmin < minDim )
1620  {
1621  minDim = lmin;
1622  minNdx = i;
1623  }
1624  }
1625 
1626  return (*aCollector)[minNdx];
1627 }
1628 
1629 
1630 bool SELECTION_TOOL::Selectable( const BOARD_ITEM* aItem, bool checkVisibilityOnly ) const
1631 {
1632  const RENDER_SETTINGS* settings = getView()->GetPainter()->GetSettings();
1633 
1634  if( settings->GetHighContrast() )
1635  {
1636  int itemLayers[KIGFX::VIEW::VIEW_MAX_LAYERS], layers_count;
1637  std::set<unsigned int> activeLayers = settings->GetActiveLayers();
1638 
1639  aItem->ViewGetLayers( itemLayers, layers_count );
1640 
1641  bool onActive = false; // Is the item on any of active layers?
1642 
1643  for( int i = 0; i < layers_count; ++i )
1644  {
1645  if( activeLayers.count( itemLayers[i] ) > 0 ) // Item is on at least one of the active layers
1646  {
1647  onActive = true;
1648  break;
1649  }
1650  }
1651 
1652  if( !onActive ) // We do not want to select items that are in the background
1653  {
1654  return false;
1655  }
1656  }
1657 
1658  switch( aItem->Type() )
1659  {
1660  case PCB_ZONE_AREA_T:
1662  {
1663  // Check to see if this keepout is part of a footprint
1664  // If it is, and we are not editing the footprint, it should not be selectable
1665  const bool zoneInFootprint =
1666  aItem->GetParent() != nullptr && aItem->GetParent()->Type() == PCB_MODULE_T;
1667  if( zoneInFootprint && !m_editModules && !checkVisibilityOnly )
1668  return false;
1669 
1670  // zones can exist on multiple layers!
1671  {
1672  auto* zone = static_cast<const ZONE_CONTAINER*>( aItem );
1673  auto zoneLayers = zone->GetLayerSet().Seq();
1674 
1675  for( unsigned int i = 0; i < zoneLayers.size(); i++ )
1676  {
1677  if( board()->IsLayerVisible( zoneLayers[i] ) )
1678  {
1679  return true;
1680  }
1681  }
1682 
1683  // No active layers selected!
1684  return false;
1685  }
1686  }
1687  break;
1688 
1689  case PCB_TRACE_T:
1690  case PCB_ARC_T:
1691  {
1692  if( !board()->IsElementVisible( LAYER_TRACKS ) )
1693  return false;
1694  }
1695  break;
1696 
1697  case PCB_VIA_T:
1698  {
1699  const VIA* via = static_cast<const VIA*>( aItem );
1700 
1701  // Check if appropriate element layer is visible
1702  switch( via->GetViaType() )
1703  {
1704  case VIATYPE::THROUGH:
1706  return false;
1707  break;
1708 
1709  case VIATYPE::BLIND_BURIED:
1711  return false;
1712  break;
1713 
1714  case VIATYPE::MICROVIA:
1716  return false;
1717  break;
1718 
1719  default:
1720  wxFAIL;
1721  return false;
1722  }
1723 
1724  // For vias it is enough if only one of its layers is visible
1725  return ( board()->GetVisibleLayers() & via->GetLayerSet() ).any();
1726  }
1727 
1728  case PCB_MODULE_T:
1729  {
1730  // In modedit, we do not want to select the module itself.
1731  if( m_editModules )
1732  return false;
1733 
1734  // Allow selection of footprints if some part of the footprint is visible.
1735 
1736  MODULE* module = const_cast<MODULE*>( static_cast<const MODULE*>( aItem ) );
1737 
1738  for( auto item : module->GraphicalItems() )
1739  {
1740  if( Selectable( item, true ) )
1741  return true;
1742  }
1743 
1744  for( auto pad : module->Pads() )
1745  {
1746  if( Selectable( pad, true ) )
1747  return true;
1748  }
1749 
1750  for( auto zone : module->Zones() )
1751  {
1752  if( Selectable( zone, true ) )
1753  return true;
1754  }
1755 
1756  return false;
1757  }
1758 
1759  case PCB_MODULE_TEXT_T:
1760  // Multiple selection is only allowed in modedit mode. In pcbnew, you have to select
1761  // module subparts one by one, rather than with a drag selection. This is so you can
1762  // pick up items under an (unlocked) module without also moving the module's sub-parts.
1763  if( !m_editModules && !checkVisibilityOnly )
1764  {
1765  if( m_multiple && !settings->GetHighContrast() )
1766  return false;
1767  }
1768 
1769  if( !m_editModules && !view()->IsVisible( aItem ) )
1770  return false;
1771 
1772  break;
1773 
1774  case PCB_MODULE_EDGE_T:
1775  case PCB_PAD_T:
1776  {
1777  // Multiple selection is only allowed in modedit mode. In pcbnew, you have to select
1778  // module subparts one by one, rather than with a drag selection. This is so you can
1779  // pick up items under an (unlocked) module without also moving the module's sub-parts.
1780  if( !m_editModules && !checkVisibilityOnly )
1781  {
1782  if( m_multiple )
1783  return false;
1784  }
1785 
1786  if( aItem->Type() == PCB_PAD_T )
1787  {
1788  auto pad = static_cast<const D_PAD*>( aItem );
1789 
1790  // In pcbnew, locked modules prevent individual pad selection.
1791  // In modedit, we don't enforce this as the module is assumed to be edited by design.
1792  if( !m_editModules && !checkVisibilityOnly )
1793  {
1794  if( pad->GetParent() && pad->GetParent()->IsLocked() )
1795  return false;
1796  }
1797 
1798  // Check render mode (from the Items tab) first
1799  switch( pad->GetAttribute() )
1800  {
1801  case PAD_ATTRIB_STANDARD:
1803  if( !board()->IsElementVisible( LAYER_PADS_TH ) )
1804  return false;
1805  break;
1806 
1807  case PAD_ATTRIB_CONN:
1808  case PAD_ATTRIB_SMD:
1809  if( pad->IsOnLayer( F_Cu ) && !board()->IsElementVisible( LAYER_PAD_FR ) )
1810  return false;
1811  else if( pad->IsOnLayer( B_Cu ) && !board()->IsElementVisible( LAYER_PAD_BK ) )
1812  return false;
1813  break;
1814  }
1815 
1816  // Otherwise, pads are selectable if any draw layer is visible
1817 
1818  // Shortcut: check copper layer visibility
1819  if( board()->IsLayerVisible( F_Cu ) && pad->IsOnLayer( F_Cu ) )
1820  return true;
1821 
1822  if( board()->IsLayerVisible( B_Cu ) && pad->IsOnLayer( B_Cu ) )
1823  return true;
1824 
1825  // Now check the non-copper layers
1826 
1827  bool draw_layer_visible = false;
1828 
1829  int pad_layers[KIGFX::VIEW::VIEW_MAX_LAYERS], pad_layers_count;
1830  pad->ViewGetLayers( pad_layers, pad_layers_count );
1831 
1832  for( int i = 0; i < pad_layers_count; ++i )
1833  {
1834  // NOTE: Only checking the regular layers (not GAL meta-layers)
1835  if( ( ( pad_layers[i] < PCB_LAYER_ID_COUNT ) &&
1836  board()->IsLayerVisible( static_cast<PCB_LAYER_ID>( pad_layers[i] ) ) ) )
1837  {
1838  draw_layer_visible = true;
1839  }
1840  }
1841 
1842  return draw_layer_visible;
1843  }
1844 
1845  break;
1846  }
1847 
1848 
1849  case PCB_MARKER_T: // Always selectable
1850  return true;
1851 
1852  // These are not selectable
1853  case NOT_USED:
1854  case TYPE_NOT_INIT:
1855  return false;
1856 
1857  default: // Suppress warnings
1858  break;
1859  }
1860 
1861  // All other items are selected only if the layer on which they exist is visible
1862  return board()->IsLayerVisible( aItem->GetLayer() )
1863  && aItem->ViewGetLOD( aItem->GetLayer(), view() ) < view()->GetScale();
1864 }
1865 
1866 
1868 {
1869  if( aItem->IsSelected() )
1870  {
1871  return;
1872  }
1873 
1874  if( aItem->Type() == PCB_PAD_T )
1875  {
1876  MODULE* module = static_cast<MODULE*>( aItem->GetParent() );
1877 
1878  if( m_selection.Contains( module ) )
1879  return;
1880  }
1881 
1882  highlight( aItem, SELECTED, &m_selection );
1883 }
1884 
1885 
1887 {
1888  unhighlight( aItem, SELECTED, &m_selection );
1889 
1890  if( m_selection.Empty() )
1891  m_locked = true;
1892 }
1893 
1894 
1895 void SELECTION_TOOL::highlight( BOARD_ITEM* aItem, int aMode, PCBNEW_SELECTION* aGroup )
1896 {
1897  if( aMode == SELECTED )
1898  aItem->SetSelected();
1899  else if( aMode == BRIGHTENED )
1900  aItem->SetBrightened();
1901 
1902  if( aGroup )
1903  {
1904  // Hide the original item, so it is shown only on overlay
1905  view()->Hide( aItem, true );
1906 
1907  aGroup->Add( aItem );
1908  }
1909 
1910  // Modules are treated in a special way - when they are highlighted, we have to
1911  // highlight all the parts that make the module, not the module itself
1912  if( aItem->Type() == PCB_MODULE_T )
1913  {
1914  static_cast<MODULE*>( aItem )->RunOnChildren( [&] ( BOARD_ITEM* item )
1915  {
1916  if( aMode == SELECTED )
1917  item->SetSelected();
1918  else if( aMode == BRIGHTENED )
1919  {
1920  item->SetBrightened();
1921 
1922  if( aGroup )
1923  aGroup->Add( item );
1924  }
1925 
1926  if( aGroup )
1927  view()->Hide( item, true );
1928  });
1929  }
1930 
1931  view()->Update( aItem );
1932 
1933  // Many selections are very temporal and updating the display each time just
1934  // creates noise.
1935  if( aMode == BRIGHTENED )
1937 }
1938 
1939 
1940 void SELECTION_TOOL::unhighlight( BOARD_ITEM* aItem, int aMode, PCBNEW_SELECTION* aGroup )
1941 {
1942  if( aMode == SELECTED )
1943  aItem->ClearSelected();
1944  else if( aMode == BRIGHTENED )
1945  aItem->ClearBrightened();
1946 
1947  if( aGroup )
1948  {
1949  aGroup->Remove( aItem );
1950 
1951  // Restore original item visibility
1952  view()->Hide( aItem, false );
1953  }
1954 
1955  // Modules are treated in a special way - when they are highlighted, we have to
1956  // highlight all the parts that make the module, not the module itself
1957  if( aItem->Type() == PCB_MODULE_T )
1958  {
1959  static_cast<MODULE*>( aItem )->RunOnChildren( [&] ( BOARD_ITEM* item )
1960  {
1961  if( aMode == SELECTED )
1962  item->ClearSelected();
1963  else if( aMode == BRIGHTENED )
1964  item->ClearBrightened();
1965 
1966  // N.B. if we clear the selection flag for sub-elements, we need to also
1967  // remove the element from the selection group (if it exists)
1968  if( aGroup )
1969  {
1970  aGroup->Remove( item );
1971 
1972  view()->Hide( item, false );
1973  view()->Update( item );
1974  }
1975  });
1976  }
1977 
1978  view()->Update( aItem );
1979 
1980  // Many selections are very temporal and updating the display each time just
1981  // creates noise.
1982  if( aMode == BRIGHTENED )
1984 }
1985 
1986 
1987 bool SELECTION_TOOL::selectionContains( const VECTOR2I& aPoint ) const
1988 {
1989  const unsigned GRIP_MARGIN = 20;
1990  VECTOR2I margin = getView()->ToWorld( VECTOR2I( GRIP_MARGIN, GRIP_MARGIN ), false );
1991 
1992  // Check if the point is located within any of the currently selected items bounding boxes
1993  for( auto item : m_selection )
1994  {
1995  BOX2I itemBox = item->ViewBBox();
1996  itemBox.Inflate( margin.x, margin.y ); // Give some margin for gripping an item
1997 
1998  if( itemBox.Contains( aPoint ) )
1999  return true;
2000  }
2001 
2002  return false;
2003 }
2004 
2005 
2006 static EDA_RECT getRect( const BOARD_ITEM* aItem )
2007 {
2008  if( aItem->Type() == PCB_MODULE_T )
2009  return static_cast<const MODULE*>( aItem )->GetFootprintRect();
2010 
2011  return aItem->GetBoundingBox();
2012 }
2013 
2014 
2015 static double calcArea( const BOARD_ITEM* aItem )
2016 {
2017  if( aItem->Type() == PCB_TRACE_T )
2018  {
2019  const TRACK* t = static_cast<const TRACK*>( aItem );
2020  return ( t->GetWidth() + t->GetLength() ) * t->GetWidth();
2021  }
2022 
2023  return getRect( aItem ).GetArea();
2024 }
2025 
2026 
2027 /*static double calcMinArea( GENERAL_COLLECTOR& aCollector, KICAD_T aType )
2028 {
2029  double best = std::numeric_limits<double>::max();
2030 
2031  if( !aCollector.GetCount() )
2032  return 0.0;
2033 
2034  for( int i = 0; i < aCollector.GetCount(); i++ )
2035  {
2036  BOARD_ITEM* item = aCollector[i];
2037  if( item->Type() == aType )
2038  best = std::min( best, calcArea( item ) );
2039  }
2040 
2041  return best;
2042 }*/
2043 
2044 
2045 static double calcMaxArea( GENERAL_COLLECTOR& aCollector, KICAD_T aType )
2046 {
2047  double best = 0.0;
2048 
2049  for( int i = 0; i < aCollector.GetCount(); i++ )
2050  {
2051  BOARD_ITEM* item = aCollector[i];
2052  if( item->Type() == aType )
2053  best = std::max( best, calcArea( item ) );
2054  }
2055 
2056  return best;
2057 }
2058 
2059 
2060 static inline double calcCommonArea( const BOARD_ITEM* aItem, const BOARD_ITEM* aOther )
2061 {
2062  if( !aItem || !aOther )
2063  return 0;
2064 
2065  return getRect( aItem ).Common( getRect( aOther ) ).GetArea();
2066 }
2067 
2068 
2069 double calcRatio( double a, double b )
2070 {
2071  if( a == 0.0 && b == 0.0 )
2072  return 1.0;
2073 
2074  if( b == 0.0 )
2075  return std::numeric_limits<double>::max();
2076 
2077  return a / b;
2078 }
2079 
2080 
2081 // The general idea here is that if the user clicks directly on a small item inside a larger
2082 // one, then they want the small item. The quintessential case of this is clicking on a pad
2083 // within a footprint, but we also apply it for text within a footprint, footprints within
2084 // larger footprints, and vias within either larger pads or longer tracks.
2085 //
2086 // These "guesses" presume there is area within the larger item to click in to select it. If
2087 // an item is mostly covered by smaller items within it, then the guesses are inappropriate as
2088 // there might not be any area left to click to select the larger item. In this case we must
2089 // leave the items in the collector and bring up a Selection Clarification menu.
2090 //
2091 // We currently check for pads and text mostly covering a footprint, but we don’t check for
2092 // smaller footprints mostly covering a larger footprint.
2093 //
2095  const VECTOR2I& aWhere ) const
2096 {
2097  std::set<BOARD_ITEM*> preferred;
2098  std::set<BOARD_ITEM*> rejected;
2099  std::set<BOARD_ITEM*> forced;
2100  wxPoint where( aWhere.x, aWhere.y );
2101 
2102  // footprints which are below this percentage of the largest footprint will be considered
2103  // for selection; all others will not
2104  constexpr double footprintToFootprintMinRatio = 0.20;
2105  // pads which are below this percentage of their parent's area will exclude their parent
2106  constexpr double padToFootprintMinRatio = 0.45;
2107  // footprints containing items with items-to-footprint area ratio higher than this will be
2108  // forced to stay on the list
2109  constexpr double footprintMaxCoverRatio = 0.90;
2110  constexpr double viaToPadMinRatio = 0.50;
2111  constexpr double trackViaLengthRatio = 2.0;
2112  constexpr double trackTrackLengthRatio = 0.3;
2113  constexpr double textToFeatureMinRatio = 0.2;
2114  constexpr double textToFootprintMinRatio = 0.4;
2115  // If the common area of two compared items is above the following threshold, they cannot
2116  // be rejected (it means they overlap and it might be hard to pick one by selecting
2117  // its unique area).
2118  constexpr double commonAreaRatio = 0.6;
2119 
2120  PCB_LAYER_ID activeLayer = (PCB_LAYER_ID) view()->GetTopLayer();
2121  LSET silkLayers( 2, B_SilkS, F_SilkS );
2122 
2123  if( silkLayers[activeLayer] )
2124  {
2125  for( int i = 0; i < aCollector.GetCount(); ++i )
2126  {
2127  BOARD_ITEM* item = aCollector[i];
2128  KICAD_T type = item->Type();
2129 
2130  if( ( type == PCB_MODULE_TEXT_T || type == PCB_TEXT_T || type == PCB_LINE_T )
2131  && silkLayers[item->GetLayer()] )
2132  {
2133  preferred.insert( item );
2134  }
2135  }
2136 
2137  if( preferred.size() > 0 )
2138  {
2139  aCollector.Empty();
2140 
2141  for( BOARD_ITEM* item : preferred )
2142  aCollector.Append( item );
2143  return;
2144  }
2145  }
2146 
2147  // Zone edges are very specific; zone fills much less so.
2148  if( aCollector.CountType( PCB_ZONE_AREA_T ) > 0 )
2149  {
2150  for( int i = aCollector.GetCount() - 1; i >= 0; i-- )
2151  {
2152  if( aCollector[i]->Type() == PCB_ZONE_AREA_T )
2153  {
2154  auto zone = static_cast<ZONE_CONTAINER*>( aCollector[i] );
2155 
2156  if( zone->HitTestForEdge( where, 5 * aCollector.GetGuide()->OnePixelInIU() ) )
2157  preferred.insert( zone );
2158  else
2159  rejected.insert( zone );
2160  }
2161  }
2162 
2163  if( preferred.size() > 0 )
2164  {
2165  aCollector.Empty();
2166 
2167  for( BOARD_ITEM* item : preferred )
2168  aCollector.Append( item );
2169  return;
2170  }
2171  }
2172 
2173  if( aCollector.CountType( PCB_MODULE_TEXT_T ) > 0 )
2174  {
2175  for( int i = 0; i < aCollector.GetCount(); ++i )
2176  {
2177  if( TEXTE_MODULE* txt = dyn_cast<TEXTE_MODULE*>( aCollector[i] ) )
2178  {
2179  double textArea = calcArea( txt );
2180 
2181  for( int j = 0; j < aCollector.GetCount(); ++j )
2182  {
2183  if( i == j )
2184  continue;
2185 
2186  BOARD_ITEM* item = aCollector[j];
2187  double itemArea = calcArea( item );
2188  double areaRatio = calcRatio( textArea, itemArea );
2189  double commonArea = calcCommonArea( txt, item );
2190  double itemCommonRatio = calcRatio( commonArea, itemArea );
2191  double txtCommonRatio = calcRatio( commonArea, textArea );
2192 
2193  if( item->Type() == PCB_MODULE_T )
2194  {
2195  // when text area is small compared to an overlapping footprint,
2196  // then it's a clear sign the text is the selection target
2197  if( areaRatio < textToFootprintMinRatio && itemCommonRatio < commonAreaRatio )
2198  rejected.insert( item );
2199  }
2200 
2201  switch( item->Type() )
2202  {
2203  case PCB_TRACE_T:
2204  case PCB_ARC_T:
2205  case PCB_PAD_T:
2206  case PCB_LINE_T:
2207  case PCB_VIA_T:
2208  case PCB_MODULE_T:
2209  if( areaRatio > textToFeatureMinRatio && txtCommonRatio < commonAreaRatio )
2210  rejected.insert( txt );
2211  break;
2212  default:
2213  break;
2214  }
2215  }
2216  }
2217  }
2218  }
2219 
2220  if( aCollector.CountType( PCB_MODULE_EDGE_T ) + aCollector.CountType( PCB_LINE_T ) > 1 )
2221  {
2222  // Prefer exact hits to sloppy ones
2223  int accuracy = KiROUND( 5 * aCollector.GetGuide()->OnePixelInIU() );
2224  bool found = false;
2225 
2226  for( int dist = 0; dist < accuracy; ++dist )
2227  {
2228  for( int i = 0; i < aCollector.GetCount(); ++i )
2229  {
2230  if( DRAWSEGMENT* drawSegment = dynamic_cast<DRAWSEGMENT*>( aCollector[i] ) )
2231  {
2232  if( drawSegment->HitTest( where, dist ) )
2233  {
2234  found = true;
2235  break;
2236  }
2237  }
2238  }
2239 
2240  if( found )
2241  {
2242  // throw out everything that is more sloppy than what we found
2243  for( int i = 0; i < aCollector.GetCount(); ++i )
2244  {
2245  if( DRAWSEGMENT* drawSegment = dynamic_cast<DRAWSEGMENT*>( aCollector[i] ) )
2246  {
2247  if( !drawSegment->HitTest( where, dist ) )
2248  rejected.insert( drawSegment );
2249  }
2250  }
2251 
2252  // we're done now
2253  break;
2254  }
2255  }
2256  }
2257 
2258  if( aCollector.CountType( PCB_PAD_T ) > 0 )
2259  {
2260  for( int i = 0; i < aCollector.GetCount(); ++i )
2261  {
2262  if( D_PAD* pad = dyn_cast<D_PAD*>( aCollector[i] ) )
2263  {
2264  MODULE* parent = pad->GetParent();
2265  double ratio = calcRatio( calcArea( pad ), calcArea( parent ) );
2266 
2267  // when pad area is small compared to the parent footprint,
2268  // then it is a clear sign the pad is the selection target
2269  if( ratio < padToFootprintMinRatio )
2270  rejected.insert( pad->GetParent() );
2271  }
2272  }
2273  }
2274 
2275  bool hasNonModules = false;
2276 
2277  for( int i = 0; i < aCollector.GetCount(); ++i )
2278  {
2279  if( aCollector[i]->Type() != PCB_MODULE_T )
2280  {
2281  hasNonModules = true;
2282  break;
2283  }
2284  }
2285 
2286  if( aCollector.CountType( PCB_MODULE_T ) > 0 )
2287  {
2288  double maxArea = calcMaxArea( aCollector, PCB_MODULE_T );
2289  BOX2D viewportD = getView()->GetViewport();
2290  BOX2I viewport( VECTOR2I( viewportD.GetPosition() ), VECTOR2I( viewportD.GetSize() ) );
2291  double maxCoverRatio = footprintMaxCoverRatio;
2292 
2293  // MODULE::CoverageRatio() doesn't take zone handles & borders into account so just
2294  // use a more aggressive cutoff point if zones are involved.
2295  if( aCollector.CountType( PCB_ZONE_AREA_T ) )
2296  maxCoverRatio /= 2;
2297 
2298  for( int i = 0; i < aCollector.GetCount(); ++i )
2299  {
2300  if( MODULE* mod = dyn_cast<MODULE*>( aCollector[i] ) )
2301  {
2302  // filter out components larger than the viewport
2303  if( mod->ViewBBox().Contains( viewport ) )
2304  rejected.insert( mod );
2305  // footprints completely covered with other features have no other
2306  // means of selection, so must be kept
2307  else if( mod->CoverageRatio( aCollector ) > maxCoverRatio )
2308  rejected.erase( mod );
2309  // if a footprint is much smaller than the largest overlapping
2310  // footprint then it should be considered for selection
2311  else if( calcRatio( calcArea( mod ), maxArea ) <= footprintToFootprintMinRatio )
2312  continue;
2313  // reject ALL OTHER footprints if there's still something else left
2314  // to select
2315  else if( hasNonModules )
2316  rejected.insert( mod );
2317  }
2318  }
2319  }
2320 
2321  if( aCollector.CountType( PCB_VIA_T ) > 0 )
2322  {
2323  for( int i = 0; i < aCollector.GetCount(); ++i )
2324  {
2325  if( VIA* via = dyn_cast<VIA*>( aCollector[i] ) )
2326  {
2327  double viaArea = calcArea( via );
2328 
2329  for( int j = 0; j < aCollector.GetCount(); ++j )
2330  {
2331  if( i == j )
2332  continue;
2333 
2334  BOARD_ITEM* item = aCollector[j];
2335  double areaRatio = calcRatio( viaArea, calcArea( item ) );
2336 
2337  if( item->Type() == PCB_MODULE_T && areaRatio < padToFootprintMinRatio )
2338  rejected.insert( item );
2339 
2340  if( item->Type() == PCB_PAD_T && areaRatio < viaToPadMinRatio )
2341  rejected.insert( item );
2342 
2343  if( TRACK* track = dyn_cast<TRACK*>( item ) )
2344  {
2345  if( track->GetNetCode() != via->GetNetCode() )
2346  continue;
2347 
2348  double lenRatio = (double) ( track->GetLength() + track->GetWidth() ) /
2349  (double) via->GetWidth();
2350 
2351  if( lenRatio > trackViaLengthRatio )
2352  rejected.insert( track );
2353  }
2354  }
2355  }
2356  }
2357  }
2358 
2359  int nTracks = aCollector.CountType( PCB_TRACE_T );
2360 
2361  if( nTracks > 0 )
2362  {
2363  double maxLength = 0.0;
2364  double minLength = std::numeric_limits<double>::max();
2365  double maxArea = 0.0;
2366  const TRACK* maxTrack = nullptr;
2367 
2368  for( int i = 0; i < aCollector.GetCount(); ++i )
2369  {
2370  if( TRACK* track = dyn_cast<TRACK*>( aCollector[i] ) )
2371  {
2372  maxLength = std::max( track->GetLength(), maxLength );
2373  maxLength = std::max( (double) track->GetWidth(), maxLength );
2374 
2375  minLength = std::min( std::max( track->GetLength(), (double) track->GetWidth() ), minLength );
2376 
2377  double area = track->GetLength() * track->GetWidth();
2378 
2379  if( area > maxArea )
2380  {
2381  maxArea = area;
2382  maxTrack = track;
2383  }
2384  }
2385  }
2386 
2387  if( maxLength > 0.0 && minLength / maxLength < trackTrackLengthRatio && nTracks > 1 )
2388  {
2389  for( int i = 0; i < aCollector.GetCount(); ++i )
2390  {
2391  if( TRACK* track = dyn_cast<TRACK*>( aCollector[i] ) )
2392  {
2393  double ratio = std::max( (double) track->GetWidth(), track->GetLength() ) / maxLength;
2394 
2395  if( ratio > trackTrackLengthRatio )
2396  rejected.insert( track );
2397  }
2398  }
2399  }
2400 
2401  for( int j = 0; j < aCollector.GetCount(); ++j )
2402  {
2403  if( MODULE* mod = dyn_cast<MODULE*>( aCollector[j] ) )
2404  {
2405  double ratio = calcRatio( maxArea, mod->GetFootprintRect().GetArea() );
2406 
2407  if( ratio < padToFootprintMinRatio && calcCommonArea( maxTrack, mod ) < commonAreaRatio )
2408  rejected.insert( mod );
2409  }
2410  }
2411  }
2412 
2413  if( (unsigned) aCollector.GetCount() > rejected.size() ) // do not remove everything
2414  {
2415  for( BOARD_ITEM* item : rejected )
2416  {
2417  aCollector.Remove( item );
2418  }
2419  }
2420 }
2421 
2422 
2424 {
2425  getView()->Update( &m_selection );
2426 
2427  return 0;
2428 }
2429 
2430 
2432 {
2433  ACTION_MENU* actionMenu = aEvent.Parameter<ACTION_MENU*>();
2434  CONDITIONAL_MENU* conditionalMenu = dynamic_cast<CONDITIONAL_MENU*>( actionMenu );
2435 
2436  if( conditionalMenu )
2437  conditionalMenu->Evaluate( m_selection );
2438 
2439  if( actionMenu )
2440  actionMenu->UpdateAll();
2441 
2442  return 0;
2443 }
2444 
2445 
2447 {
2449 
2453 
2459 
2460  Go( &SELECTION_TOOL::find, ACTIONS::find.MakeEvent() );
2461 
2468 }
static TOOL_ACTION selectItems
Selects a list of items (specified as the event parameter)
Definition: pcb_actions.h:69
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:62
static TOOL_ACTION selectionActivate
Activation of the selection tool.
Definition: pcb_actions.h:56
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:250
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
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:61
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:202
void selectAllItemsOnSheet(wxString &aSheetPath)
Selects all items with the given sheet timestamp/UUID name (the sheet path) The path of the root shee...
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:95
void ForceRefresh()
Function ForceRefresh() Forces a redraw.
int GetNetCode() const
Function GetNetCode.
static double calcCommonArea(const BOARD_ITEM *aItem, const BOARD_ITEM *aOther)
bool otherItems
Anything not fitting one of the above categories.
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:80
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
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:85
RENDER_SETTINGS Contains all the knowledge about how graphical objects are drawn on any output surfac...
bool IsSelected() const
Definition: base_struct.h:203
Model changes (required full reload)
Definition: tool_base.h:82
multilayer pads, usually with holes
static const TOOL_EVENT UnselectedEvent
Definition: actions.h:203
int selectSameSheet(const TOOL_EVENT &aEvent)
Selects all modules belonging to same hierarchical sheet as the selected footprint (same sheet path).
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:44
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:211
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:118
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:539
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:66
#define SKIP_STRUCT
flag indicating that the structure should be ignored
Definition: base_struct.h:128
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:80
static TOOL_ACTION dragFreeAngle
Definition: pcb_actions.h:133
Select the entire net.
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:219
ITER end()
Definition: selection.h:62
static TOOL_ACTION unselectItems
Definition: pcb_actions.h:70
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:81
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:109
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:169
void SetBrightened()
Definition: base_struct.h:209
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:140
static TOOL_ACTION selectionMenu
Runs a selection menu to select from a list of items.
Definition: pcb_actions.h:73
static TOOL_ACTION selectConnection
Selects tracks between junctions or expands an existing selection to pads or the entire connection.
Definition: pcb_actions.h:77
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
static TOOL_ACTION drag45Degree
Definition: pcb_actions.h:132
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
void UpdateAll()
Function UpdateAll() Runs update handlers for the menu and its submenus.
const KIID_PATH & GetPath() const
Definition: class_module.h:224
Struct that will be set with the result of the user choices in the dialog.
DRAWINGS & GraphicalItems()
Definition: class_module.h:179
const COLLECTORS_GUIDE * GetGuide()
Definition: collectors.h:347
void SetContextMenu(ACTION_MENU *aMenu, CONTEXT_MENU_TRIGGER aTrigger=CMENU_BUTTON)
Function SetContextMenu()
Stop at any place where more than two traces meet.
const BITMAP_OPAQUE net_highlight_xpm[1]
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 Display options control the way tracks, vias, outlines and other things ar...
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
TRACK_DRAG_ACTION
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:206
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
A single base class (TRACK) represents both tracks and vias, with subclasses for curved tracks (ARC) ...
bool itemPassesFilter(BOARD_ITEM *aItem)
Returns true if the given item passes the current SELECTION_FILTER_OPTIONS
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96
void SetIsHover(bool aIsHover)
Definition: selection.h:66
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:76
void highlight(BOARD_ITEM *aItem, int aHighlightMode, PCBNEW_SELECTION *aGroup=nullptr)
Function highlight() Highlights the item visually.
PCBNEW_SELECTION & GetSelection()
Function GetSelection()
virtual const wxPoint GetPosition() const
Definition: base_struct.h:337
void ClearBrightened()
Definition: base_struct.h:212
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:307
double dist(const double ax, const double ay, const double bx, const double by)
Definition: delauney.h:168
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:124
int expandConnection(const TOOL_EVENT &aEvent)
Expands the current track selection to the next boundary (junctions, pads, or all)
ITER begin()
Definition: selection.h:61
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
bool text
Text (free or attached to a footprint)
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:232
static double calcMaxArea(GENERAL_COLLECTOR &aCollector, KICAD_T aType)
#define NULL
void SetSelected()
Definition: base_struct.h:208
void SetIgnoreMTextsOnBack(bool ignore)
Definition: collectors.h:547
int updateSelection(const TOOL_EVENT &aEvent)
Event handler to update the selection VIEW_ITEM.
bool dimensions
Dimension items.
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
void selectConnectedTracks(BOARD_CONNECTED_ITEM &aSourceItem, STOP_CONDITION aStopCondition)
Selects connecteed tracks and vias.
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
bool keepouts
Keepout zones.
bool graphics
Graphic lines, shapes, polygons.
void SetIgnoreMTextsOnFront(bool ignore)
Definition: collectors.h:553
void connectedItemFilter(const VECTOR2I &, GENERAL_COLLECTOR &aCollector)
SELECTION_LOCK_FLAGS
Definition: selection.h:279
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:70
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:113
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:355
const std::deque< EDA_ITEM * > GetItems() const
Definition: selection.h:132
KIGFX::PCB_VIEW * view() const
Stop when reaching a pad.
bool ToolStackIsEmpty()
Definition: tools_holder.h:84
#define BRIGHTENED
item is drawn with a bright contour
Definition: base_struct.h:139
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:195
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:204
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.
bool tracks
Copper tracks.
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 KIGFX::VIEW_ITEM * GetItem(unsigned int aIdx) const override
Definition: selection.h:105
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
bool zones
Copper zones.
int SelectItem(const TOOL_EVENT &aEvent)
Item selection event handler.
const std::set< unsigned int > GetActiveLayers() const
Function GetActiveLayers() Returns the set of currently active layers.
Like smd, does not appear on the solder paste layer (default) note also has a special attribute in Ge...
Definition: pad_shapes.h:82
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:418
bool footprints
Allow selecting entire footprints.
const MODULE_ZONE_CONTAINERS & Zones() const
Definition: class_module.h:184
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 GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:702
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:121
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:101
bool pads
Footprint pads.
static TOOL_ACTION drag
Definition: pcb_actions.h:93
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:404
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:100
bool vias
Vias (all types>
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:89
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
virtual RENDER_SETTINGS * GetSettings()=0
Function GetAdapter 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 ...
virtual bool IsLocked() const
Function IsLocked.
bool lockedItems
Allow selecting locked items.
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:88
smd pads, front layer
PCBNEW_SELECTION & RequestSelection(CLIENT_SELECTION_FILTER aClientFilter, std::vector< BOARD_ITEM * > *aFiltered=nullptr, bool aConfirmLockedItems=false)
Function RequestSelection()
int GetWidth() const
Definition: class_track.h:112
bool IsType(FRAME_T aType) const
void SetHighlight(bool aEnabled, int aNetcode=-1, bool aMulti=false)
Function SetHighlight Turns on/off highlighting - it may be done for the active layer or the specifie...
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:83
BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:180
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
wxString AsString() const
Definition: common.h:137
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:65
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
int Size() const
Returns the number of selected parts.
Definition: selection.h:127
VIATYPE GetViaType() const
Definition: class_track.h:368
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:68
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:159
double calcRatio(double a, double b)
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:79
const wxPoint & GetEnd() const
Definition: class_track.h:115
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:148
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
SELECTION_FILTER_OPTIONS m_filter
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
virtual const EDA_RECT GetBoundingBox() const
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
Definition: base_struct.cpp:95
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:42
class ZONE_CONTAINER, managed by a footprint
Definition: typeinfo.h:95
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:161
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
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:234
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...
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.
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:156
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:59
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:184
void filterCollectedItems(GENERAL_COLLECTOR &aCollector)
Applies the SELECTION_FILTER_OPTIONS to a collection of items
KICAD_T Type() const
Function Type()
Definition: base_struct.h:193
static TOOL_ACTION selectSameSheet
Selects all components on the same sheet as the selected footprint.
Definition: pcb_actions.h:86
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:99
virtual void Remove(EDA_ITEM *aItem)
Definition: selection.h:87