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) 2017 KiCad Developers, see CHANGELOG.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 #include <limits>
27 
28 #include <functional>
29 using namespace std::placeholders;
30 
31 #include <class_board.h>
32 #include <class_board_item.h>
33 #include <class_track.h>
34 #include <class_module.h>
35 #include <class_pcb_text.h>
36 #include <class_drawsegment.h>
37 
38 #include <wxPcbStruct.h>
39 #include <collectors.h>
40 #include <confirm.h>
41 #include <dialog_find.h>
42 #include <dialog_block_options.h>
43 
44 #include <class_draw_panel_gal.h>
45 #include <view/view_controls.h>
46 #include <view/view_group.h>
48 #include <painter.h>
49 #include <bitmaps.h>
50 #include <hotkeys.h>
51 
52 #include <tool/tool_event.h>
53 #include <tool/tool_manager.h>
54 #include <connectivity.h>
55 
56 #include "selection_tool.h"
57 #include "pcb_bright_box.h"
58 #include "pcb_actions.h"
59 
60 // Selection tool actions
61 TOOL_ACTION PCB_ACTIONS::selectionActivate( "pcbnew.InteractiveSelection",
62  AS_GLOBAL, 0,
63  "", "", NULL, AF_ACTIVATE ); // No description, it is not supposed to be shown anywhere
64 
65 TOOL_ACTION PCB_ACTIONS::selectionCursor( "pcbnew.InteractiveSelection.Cursor",
66  AS_GLOBAL, 0,
67  "", "" ); // No description, it is not supposed to be shown anywhere
68 
69 TOOL_ACTION PCB_ACTIONS::selectItem( "pcbnew.InteractiveSelection.SelectItem",
70  AS_GLOBAL, 0,
71  "", "" ); // No description, it is not supposed to be shown anywhere
72 
73 TOOL_ACTION PCB_ACTIONS::selectItems( "pcbnew.InteractiveSelection.SelectItems",
74  AS_GLOBAL, 0,
75  "", "" ); // No description, it is not supposed to be shown anywhere
76 
77 TOOL_ACTION PCB_ACTIONS::unselectItem( "pcbnew.InteractiveSelection.UnselectItem",
78  AS_GLOBAL, 0,
79  "", "" ); // No description, it is not supposed to be shown anywhere
80 
81 TOOL_ACTION PCB_ACTIONS::unselectItems( "pcbnew.InteractiveSelection.UnselectItems",
82  AS_GLOBAL, 0,
83  "", "" ); // No description, it is not supposed to be shown anywhere
84 
85 TOOL_ACTION PCB_ACTIONS::selectionClear( "pcbnew.InteractiveSelection.Clear",
86  AS_GLOBAL, 0,
87  "", "" ); // No description, it is not supposed to be shown anywhere
88 
89 TOOL_ACTION PCB_ACTIONS::selectConnection( "pcbnew.InteractiveSelection.SelectConnection",
91  _( "Trivial Connection" ), _( "Selects a connection between two junctions." ) );
92 
93 TOOL_ACTION PCB_ACTIONS::selectCopper( "pcbnew.InteractiveSelection.SelectCopper",
95  _( "Copper Connection" ), _( "Selects whole copper connection." ) );
96 
97 TOOL_ACTION PCB_ACTIONS::selectNet( "pcbnew.InteractiveSelection.SelectNet",
98  AS_GLOBAL, 0,
99  _( "Whole Net" ), _( "Selects all tracks & vias belonging to the same net." ) );
100 
101 TOOL_ACTION PCB_ACTIONS::selectOnSheetFromEeschema( "pcbnew.InteractiveSelection.SelectOnSheet",
102  AS_GLOBAL, 0,
103  _( "Sheet" ), _( "Selects all modules and tracks in the schematic sheet" ) );
104 
105 TOOL_ACTION PCB_ACTIONS::selectSameSheet( "pcbnew.InteractiveSelection.SelectSameSheet",
106  AS_GLOBAL, 0,
107  _( "Items in Same Hierarchical Sheet" ),
108  _( "Selects all modules and tracks in the same schematic sheet" ) );
109 
110 TOOL_ACTION PCB_ACTIONS::find( "pcbnew.InteractiveSelection.Find",
111  AS_GLOBAL, 0, //TOOL_ACTION::LegacyHotKey( HK_FIND_ITEM ), // handled by wxWidgets
112  _( "Find Item" ),_( "Searches the document for an item" ), find_xpm );
113 
114 TOOL_ACTION PCB_ACTIONS::findMove( "pcbnew.InteractiveSelection.FindMove",
116 
117 TOOL_ACTION PCB_ACTIONS::filterSelection( "pcbnew.InteractiveSelection.FilterSelection",
118  AS_GLOBAL, 0,
119  _( "Filter Selection" ), _( "Filter the types of items in the selection" ),
120  nullptr );
121 
122 
123 
125 {
126 public:
128  {
129  SetTitle( _( "Select..." ) );
130 
132 
133  AppendSeparator();
134 
137  Add( PCB_ACTIONS::selectNet );
139  }
140 
141 private:
142 
143  void update() override
144  {
145  using S_C = SELECTION_CONDITIONS;
146 
147  const auto& selection = getToolManager()->GetTool<SELECTION_TOOL>()->GetSelection();
148 
149  bool connItem = ( S_C::OnlyType( PCB_VIA_T ) || S_C::OnlyType( PCB_TRACE_T ) )( selection );
150  bool sheetSelEnabled = ( S_C::OnlyType( PCB_MODULE_T ) )( selection );
151 
152  Enable( getMenuId( PCB_ACTIONS::selectNet ), connItem );
153  Enable( getMenuId( PCB_ACTIONS::selectCopper ), connItem );
154  Enable( getMenuId( PCB_ACTIONS::selectConnection ), connItem );
155  Enable( getMenuId( PCB_ACTIONS::selectSameSheet ), sheetSelEnabled );
156  }
157 
158  CONTEXT_MENU* create() const override
159  {
160  return new SELECT_MENU();
161  }
162 };
163 
164 
169 {
170 public:
172 };
173 
174 
176  PCB_TOOL( "pcbnew.InteractiveSelection" ),
177  m_frame( NULL ), m_additive( false ), m_subtractive( false ),
178  m_multiple( false ),
179  m_locked( true ), m_menu( *this ),
180  m_priv( std::make_unique<PRIV>() )
181 {
182 
183 }
184 
185 
187 {
188  getView()->Remove( &m_selection );
189 }
190 
191 
193 {
194  auto selectMenu = std::make_shared<SELECT_MENU>();
195  selectMenu->SetTool( this );
196  m_menu.AddSubMenu( selectMenu );
197 
198  auto& menu = m_menu.GetMenu();
199 
200  menu.AddMenu( selectMenu.get(), false, SELECTION_CONDITIONS::NotEmpty );
201  // only show separator if there is a Select menu to show above it
202  menu.AddSeparator( SELECTION_CONDITIONS::NotEmpty, 1000 );
203 
204  m_menu.AddStandardSubMenus( *getEditFrame<PCB_BASE_FRAME>() );
205 
206  return true;
207 }
208 
209 
211 {
212  m_frame = getEditFrame<PCB_BASE_FRAME>();
213  m_locked = true;
214 
215  if( aReason == TOOL_BASE::MODEL_RELOAD )
216  {
217  // Remove pointers to the selected items from containers
218  // without changing their properties (as they are already deleted
219  // while a new board is loaded)
220  m_selection.Clear();
221  getView()->GetPainter()->GetSettings()->SetHighlight( false );
222  }
223  else
224  // Restore previous properties of selected items and remove them from containers
225  clearSelection();
226 
227  // Reinsert the VIEW_GROUP, in case it was removed from the VIEW
228  getView()->Remove( &m_selection );
229  getView()->Add( &m_selection );
230 }
231 
232 
233 int SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
234 {
235  // Main loop: keep receiving events
236  while( OPT_TOOL_EVENT evt = Wait() )
237  {
238  // Should selected items be added to the current selection or
239  // become the new selection (discarding previously selected items)
240  m_additive = evt->Modifier( MD_SHIFT );
241 
242  // Should selected items be REMOVED from the current selection?
243  // This will be ignored if the SHIFT modifier is pressed
244  m_subtractive = !m_additive && evt->Modifier( MD_CTRL );
245 
246  // Single click? Select single object
247  if( evt->IsClick( BUT_LEFT ) )
248  {
249  if( evt->Modifier( MD_CTRL ) && !m_editModules )
250  {
252  }
253  else
254  {
255  // If no modifier keys are pressed, clear the selection
256  if( !m_additive )
257  {
258  clearSelection();
259  }
260 
261  selectPoint( evt->Position() );
262  }
263  }
264 
265  // right click? if there is any object - show the context menu
266  else if( evt->IsClick( BUT_RIGHT ) )
267  {
268  bool emptySelection = m_selection.Empty();
269 
270  if( emptySelection )
271  selectPoint( evt->Position() );
272 
274  }
275 
276  // double click? Display the properties window
277  else if( evt->IsDblClick( BUT_LEFT ) )
278  {
279  if( m_selection.Empty() )
280  selectPoint( evt->Position() );
281 
283  }
284 
285  // drag with LMB? Select multiple objects (or at least draw a selection box) or drag them
286  else if( evt->IsDrag( BUT_LEFT ) )
287  {
288  if( m_additive || m_subtractive )
289  {
290  selectMultiple();
291  }
292  else if( m_selection.Empty() )
293  {
294  // There is nothing selected, so try to select something
295  if( !selectCursor() )
296  {
297  // If nothings has been selected or user wants to select more
298  // draw the selection box
299  selectMultiple();
300  }
301  else
302  {
303  m_toolMgr->InvokeTool( "pcbnew.InteractiveEdit" );
304  }
305  }
306 
307  else
308  {
309  // Check if dragging has started within any of selected items bounding box
310  if( selectionContains( evt->Position() ) )
311  {
312  // Yes -> run the move tool and wait till it finishes
313  m_toolMgr->InvokeTool( "pcbnew.InteractiveEdit" );
314  }
315  else
316  {
317  // No -> clear the selection list
318  clearSelection();
319  }
320  }
321  }
322 
323  else if( evt->IsCancel() || evt->Action() == TA_UNDO_REDO_PRE )
324  {
325  clearSelection();
326  }
327 
328  else if( evt->Action() == TA_CONTEXT_MENU_CLOSED )
329  {
330  m_menu.CloseContextMenu( evt );
331  }
332  }
333 
334  // This tool is supposed to be active forever
335  assert( false );
336 
337  return 0;
338 }
339 
340 
342 {
343  return m_selection;
344 }
345 
346 
348 {
349  if ( m_selection.Empty() )
350  {
352  m_selection.SetIsHover( true );
353  }
354  else
355  {
356  m_selection.SetIsHover( false );
357  }
358 
359  // Be careful with iterators: items can be removed from list
360  // that invalidate iterators.
361  for( unsigned ii = 0; ii < m_selection.GetSize(); ii++ )
362  {
363  EDA_ITEM* item = m_selection[ii];
364 
365  if( ( aFlags & SELECTION_EDITABLE ) && item->Type() == PCB_MARKER_T )
366  {
367  unselect( static_cast<BOARD_ITEM *>( item ) );
368  }
369  }
370 
371  if ( aFlags & SELECTION_SANITIZE_PADS )
373 
374  return m_selection;
375 }
376 
377 
379 {
380  if( aItem->IsSelected() )
381  {
382  unselect( aItem );
383 
384  // Inform other potentially interested tools
386  }
387  else
388  {
389  if( !m_additive )
390  clearSelection();
391 
392  // Prevent selection of invisible or inactive items
393  if( selectable( aItem ) )
394  {
395  select( aItem );
396 
397  // Inform other potentially interested tools
399  }
400  }
401 
403 }
404 
405 
406 bool SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag )
407 {
408  BOARD_ITEM* item;
410  GENERAL_COLLECTOR collector;
411 
412  collector.Collect( board(),
414  wxPoint( aWhere.x, aWhere.y ), guide );
415 
416  bool anyCollected = collector.GetCount() != 0;
417 
418  // Remove unselectable items
419  for( int i = collector.GetCount() - 1; i >= 0; --i )
420  {
421  if( !selectable( collector[i] ) || ( aOnDrag && collector[i]->IsLocked() ) )
422  collector.Remove( i );
423  }
424 
425  switch( collector.GetCount() )
426  {
427  case 0:
428  if( !m_additive && anyCollected )
429  {
430  clearSelection();
431  }
432 
433  return false;
434 
435  case 1:
436  toggleSelection( collector[0] );
437 
438  return true;
439 
440  default:
441  // Apply some ugly heuristics to avoid disambiguation menus whenever possible
442  guessSelectionCandidates( collector );
443 
444  // Let's see if there is still disambiguation in selection..
445  if( collector.GetCount() == 1 )
446  {
447  toggleSelection( collector[0] );
448 
449  return true;
450  }
451  else if( collector.GetCount() > 1 )
452  {
453  if( aOnDrag )
454  {
456  }
457 
458  item = disambiguationMenu( &collector );
459 
460  if( item )
461  {
462  toggleSelection( item );
463 
464  return true;
465  }
466  }
467  break;
468  }
469 
470  return false;
471 }
472 
473 
474 bool SELECTION_TOOL::selectCursor( bool aSelectAlways )
475 {
476  if( aSelectAlways || m_selection.Empty() )
477  {
478  clearSelection();
479  selectPoint( getViewControls()->GetCursorPosition( false ) );
480  }
481 
482  return !m_selection.Empty();
483 }
484 
485 
487 {
488  bool cancelled = false; // Was the tool cancelled while it was running?
489  m_multiple = true; // Multiple selection mode is active
490  KIGFX::VIEW* view = getView();
491  getViewControls()->SetAutoPan( true );
492 
494  view->Add( &area );
495 
496  while( OPT_TOOL_EVENT evt = Wait() )
497  {
498  if( evt->IsCancel() )
499  {
500  cancelled = true;
501  break;
502  }
503 
504  if( evt->IsDrag( BUT_LEFT ) )
505  {
506 
507  // Start drawing a selection box
508  area.SetOrigin( evt->DragOrigin() );
509  area.SetEnd( evt->Position() );
510  area.SetAdditive( m_additive );
512 
513  view->SetVisible( &area, true );
514  view->Update( &area );
515  }
516 
517  if( evt->IsMouseUp( BUT_LEFT ) )
518  {
519  // End drawing the selection box
520  view->SetVisible( &area, false );
521 
522  // Mark items within the selection box as selected
523  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
524 
525  // Filter the view items based on the selection box
526  BOX2I selectionBox = area.ViewBBox();
527  view->Query( selectionBox, selectedItems ); // Get the list of selected items
528 
529  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR>::iterator it, it_end;
530 
531  int width = area.GetEnd().x - area.GetOrigin().x;
532  int height = area.GetEnd().y - area.GetOrigin().y;
533 
534  // Construct an EDA_RECT to determine BOARD_ITEM selection
535  EDA_RECT selectionRect( wxPoint( area.GetOrigin().x, area.GetOrigin().y ),
536  wxSize( width, height ) );
537 
538  selectionRect.Normalize();
539 
540  for( it = selectedItems.begin(), it_end = selectedItems.end(); it != it_end; ++it )
541  {
542  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( it->first );
543 
544  if( !item || !selectable( item ) )
545  continue;
546 
547  /* Selection mode depends on direction of drag-selection:
548  * Left > Right : Select objects that are fully enclosed by selection
549  * Right > Left : Select objects that are crossed by selection
550  */
551 
552  if( width >= 0 )
553  {
554  if( selectionBox.Contains( item->ViewBBox() ) )
555  {
556  if( m_subtractive )
557  unselect( item );
558  else
559  select( item );
560  }
561  }
562  else
563  {
564  if( item->HitTest( selectionRect, false ) )
565  {
566  if( m_subtractive )
567  unselect( item );
568  else
569  select( item );
570  }
571 
572  }
573  }
574 
575  if( m_selection.Size() == 1 )
576  m_frame->SetCurItem( static_cast<BOARD_ITEM*>( m_selection.Front() ) );
577  else
578  m_frame->SetCurItem( NULL );
579 
580  // Inform other potentially interested tools
581  if( !m_selection.Empty() )
583 
584  break; // Stop waiting for events
585  }
586  }
587 
588  // Stop drawing the selection box
589  view->Remove( &area );
590  m_multiple = false; // Multiple selection mode is inactive
591  getViewControls()->SetAutoPan( false );
592 
593  return cancelled;
594 }
595 
596 
598 {
606  Go( &SELECTION_TOOL::find, PCB_ACTIONS::find.MakeEvent() );
615 }
616 
617 
619 {
620  if( !m_locked || m_editModules )
621  return SELECTION_UNLOCKED;
622 
623  bool containsLocked = false;
624 
625  // Check if the selection contains locked items
626  for( const auto& item : m_selection )
627  {
628  switch( item->Type() )
629  {
630  case PCB_MODULE_T:
631  if( static_cast<MODULE*>( item )->IsLocked() )
632  containsLocked = true;
633  break;
634 
635  case PCB_MODULE_EDGE_T:
636  case PCB_MODULE_TEXT_T:
637  if( static_cast<MODULE*>( item->GetParent() )->IsLocked() )
638  containsLocked = true;
639  break;
640 
641  default: // suppress warnings
642  break;
643  }
644  }
645 
646  if( containsLocked )
647  {
648  if( IsOK( m_frame, _( "Selection contains locked items. Do you want to continue?" ) ) )
649  {
650  m_locked = false;
652  }
653  else
654  return SELECTION_LOCKED;
655  }
656 
657  return SELECTION_UNLOCKED;
658 }
659 
660 
662 {
663  bool sanitize = (bool) aEvent.Parameter<intptr_t>();
664 
665  if( m_selection.Empty() ) // Try to find an item that could be modified
666  {
667  selectCursor( true );
668 
669  if( CheckLock() == SELECTION_LOCKED )
670  {
671  clearSelection();
672  return 0;
673  }
674  }
675 
676  if( sanitize )
678 
679  return 0;
680 }
681 
682 
684 {
685  clearSelection();
686 
687  return 0;
688 }
689 
690 
692 {
693  std::vector<BOARD_ITEM*>* items = aEvent.Parameter<std::vector<BOARD_ITEM*>*>();
694 
695  if( items )
696  {
697  // Perform individual selection of each item
698  // before processing the event.
699  for( auto item : *items )
700  {
701  select( item );
702  }
703 
705  }
706 
707  return 0;
708 }
709 
710 
712 {
713  // Check if there is an item to be selected
714  BOARD_ITEM* item = aEvent.Parameter<BOARD_ITEM*>();
715 
716  if( item )
717  {
718  select( item );
719 
720  // Inform other potentially interested tools
722  }
723 
724  return 0;
725 }
726 
727 
729 {
730  std::vector<BOARD_ITEM*>* items = aEvent.Parameter<std::vector<BOARD_ITEM*>*>();
731 
732  if( items )
733  {
734  // Perform individual unselection of each item
735  // before processing the event
736  for( auto item : *items )
737  {
738  unselect( item );
739  }
740 
742  }
743 
744  return 0;
745 }
746 
747 
749 {
750  // Check if there is an item to be selected
751  BOARD_ITEM* item = aEvent.Parameter<BOARD_ITEM*>();
752 
753  if( item )
754  {
755  unselect( item );
756 
757  // Inform other potentially interested tools
759  }
760 
761  return 0;
762 }
763 
764 
766 {
767  if( !selectCursor() )
768  return 0;
769 
770  // copy the selection, since we're going to iterate and modify
771  auto selection = m_selection.GetItems();
772 
773  for( auto item : selection )
774  {
775  // only TRACK items can be checked for trivial connections
776  if( item->Type() == PCB_TRACE_T || item->Type() == PCB_VIA_T )
777  {
778  TRACK& trackItem = static_cast<TRACK&>( *item );
779  selectAllItemsConnectedToTrack( trackItem );
780  }
781  }
782 
783  // Inform other potentially interested tools
784  if( m_selection.Size() > 0 )
786 
787  return 0;
788 }
789 
790 
792 {
793  if( !selectCursor() )
794  return 0;
795 
796  // copy the selection, since we're going to iterate and modify
797  auto selection = m_selection.GetItems();
798 
799  for( auto i : selection )
800  {
801  auto item = static_cast<BOARD_ITEM*>( i );
802 
803  // only connected items can be traversed in the ratsnest
804  if( item->IsConnected() )
805  {
806  auto& connItem = static_cast<BOARD_CONNECTED_ITEM&>( *item );
807 
808  selectAllItemsConnectedToItem( connItem );
809  }
810  }
811 
812  // Inform other potentially interested tools
813  if( m_selection.Size() > 0 )
815 
816  return 0;
817 }
818 
819 
821 {
822  int segmentCount;
823  TRACK* trackList = board()->MarkTrace( &aSourceTrack, &segmentCount,
824  nullptr, nullptr, true );
825 
826  for( int i = 0; i < segmentCount; ++i )
827  {
828  select( trackList );
829  trackList = trackList->Next();
830  }
831 }
832 
833 
835 {
836  constexpr KICAD_T types[] = { PCB_TRACE_T, PCB_VIA_T, EOT };
837  auto connectivity = board()->GetConnectivity();
838 
839  std::list<BOARD_CONNECTED_ITEM*> items;
840  items = connectivity->GetConnectedItems( &aSourceItem, types );
841 
842  for( auto item : connectivity->GetConnectedItems( &aSourceItem, types ) )
843  select( item );
844 }
845 
846 
848 {
849  constexpr KICAD_T types[] = { PCB_TRACE_T, PCB_VIA_T, EOT };
850  auto connectivity = board()->GetConnectivity();
851 
852  for( auto item : connectivity->GetNetItems( aNetCode, types ) )
853  select( item );
854 }
855 
856 
858 {
859  if( !selectCursor() )
860  return 0;
861 
862  // copy the selection, since we're going to iterate and modify
863  auto selection = m_selection.GetItems();
864 
865  for( auto i : selection )
866  {
867  auto item = static_cast<BOARD_ITEM*>( i );
868 
869  // only connected items get a net code
870  if( item->IsConnected() )
871  {
872  auto& connItem = static_cast<BOARD_CONNECTED_ITEM&>( *item );
873 
874  selectAllItemsOnNet( connItem.GetNetCode() );
875  }
876  }
877 
878  // Inform other potentially interested tools
879  if( m_selection.Size() > 0 )
881 
882  return 0;
883 }
884 
885 
886 void SELECTION_TOOL::selectAllItemsOnSheet( wxString& aSheetpath )
887 {
888  auto modules = board()->m_Modules.GetFirst();
889  std::list<MODULE*> modList;
890 
891  // store all modules that are on that sheet
892  for( MODULE* mitem = modules; mitem; mitem = mitem->Next() )
893  {
894  if( mitem != NULL && mitem->GetPath().Contains( aSheetpath ) )
895  {
896  modList.push_back( mitem );
897  }
898  }
899 
900  //Generate a list of all pads, and of all nets they belong to.
901  std::list<int> netcodeList;
902  for( MODULE* mmod : modList )
903  {
904  for( auto pad : mmod->Pads() )
905  {
906  if( pad->IsConnected() )
907  {
908  netcodeList.push_back( pad->GetNetCode() );
909  }
910  }
911  }
912 
913  // remove all duplicates
914  netcodeList.sort();
915  netcodeList.unique();
916 
917  // now we need to find all modules that are connected to each of these nets
918  // then we need to determine if these modules are in the list of modules
919  // belonging to this sheet ( modList )
920  std::list<int> removeCodeList;
921  constexpr KICAD_T padType[] = { PCB_PAD_T, EOT };
922 
923  for( int netCode : netcodeList )
924  {
925  for( BOARD_CONNECTED_ITEM* mitem : board()->GetConnectivity()->GetNetItems( netCode, padType ) )
926  {
927  if( mitem->Type() == PCB_PAD_T)
928  {
929  bool found = ( std::find( modList.begin(), modList.end(),
930  mitem->GetParent() ) != modList.end() );
931 
932  if( !found )
933  {
934  // if we cannot find the module of the pad in the modList
935  // then we can assume that that module is not located in the same
936  // schematic, therefore invalidate this netcode.
937  removeCodeList.push_back( netCode );
938  break;
939  }
940  }
941  }
942  }
943 
944  // remove all duplicates
945  removeCodeList.sort();
946  removeCodeList.unique();
947 
948  for( int removeCode : removeCodeList )
949  {
950  netcodeList.remove( removeCode );
951  }
952 
953  std::list<BOARD_CONNECTED_ITEM*> localConnectionList;
954  constexpr KICAD_T trackViaType[] = { PCB_TRACE_T, PCB_VIA_T, EOT };
955 
956  for( int netCode : netcodeList )
957  {
958  for( BOARD_CONNECTED_ITEM* item : board()->GetConnectivity()->GetNetItems( netCode, trackViaType ) )
959  {
960  localConnectionList.push_back( item );
961  }
962  }
963 
964  for( BOARD_ITEM* i : modList )
965  {
966  if( i != NULL )
967  select( i );
968  }
969 
970  for( BOARD_CONNECTED_ITEM* i : localConnectionList )
971  {
972  if( i != NULL )
973  select( i );
974  }
975 }
976 
977 
979 {
980  //Should recalculate the view to zoom in on the selection
981  auto selectionBox = m_selection.ViewBBox();
982  auto canvas = m_frame->GetGalCanvas();
983  auto view = getView();
984 
985  VECTOR2D screenSize = view->ToWorld( canvas->GetClientSize(), false );
986 
987  if( !( selectionBox.GetWidth() == 0 ) || !( selectionBox.GetHeight() == 0 ) )
988  {
989  VECTOR2D vsize = selectionBox.GetSize();
990  double scale = view->GetScale() / std::max( fabs( vsize.x / screenSize.x ),
991  fabs( vsize.y / screenSize.y ) );
992  view->SetScale( scale );
993  view->SetCenter( selectionBox.Centre() );
994  view->Add( &m_selection );
995  }
996 
998 }
999 
1000 
1002 {
1003  clearSelection();
1004  wxString* sheetpath = aEvent.Parameter<wxString*>();
1005 
1006  selectAllItemsOnSheet( *sheetpath );
1007 
1008  zoomFitSelection();
1009 
1010  if( m_selection.Size() > 0 )
1012 
1013  return 0;
1014 }
1015 
1016 
1018 {
1019  if( !selectCursor( true ) )
1020  return 0;
1021 
1022  // this function currently only supports modules since they are only
1023  // on one sheet.
1024  auto item = m_selection.Front();
1025 
1026  if( !item )
1027  return 0;
1028 
1029  if( item->Type() != PCB_MODULE_T )
1030  return 0;
1031 
1032  auto mod = dynamic_cast<MODULE*>( item );
1033 
1034  clearSelection();
1035 
1036  // get the lowest subsheet name for this.
1037  wxString sheetPath = mod->GetPath();
1038  sheetPath = sheetPath.BeforeLast( '/' );
1039  sheetPath = sheetPath.AfterLast( '/' );
1040 
1041  selectAllItemsOnSheet( sheetPath );
1042 
1043  // Inform other potentially interested tools
1044  if( m_selection.Size() > 0 )
1046 
1047  return 0;
1048 }
1049 
1050 
1052 {
1053  clearSelection();
1054 
1055  if( aItem )
1056  {
1057  select( aItem );
1058  EDA_RECT bbox = aItem->GetBoundingBox();
1059  BOX2D viewport( VECTOR2D( bbox.GetOrigin() ), VECTOR2D( bbox.GetSize() ) );
1060  getView()->SetViewport( viewport );
1061 
1062  // Inform other potentially interested tools
1064  }
1065 
1067 }
1068 
1069 
1070 int SELECTION_TOOL::find( const TOOL_EVENT& aEvent )
1071 {
1072  DIALOG_FIND dlg( m_frame );
1073  dlg.EnableWarp( false );
1074  dlg.SetCallback( std::bind( &SELECTION_TOOL::findCallback, this, _1 ) );
1075  dlg.ShowModal();
1076 
1077  return 0;
1078 }
1079 
1080 
1082 {
1084 
1085  if( module )
1086  {
1087  clearSelection();
1088  toggleSelection( module );
1089 
1090  // Place event on module origin first, so the generic anchor snap
1091  // doesn't just choose the closest pin for us
1092  // Don't warp the view - we want the component to
1093  // "teleport" to cursor, not move to the components position
1094  getViewControls()->ForceCursorPosition( true, module->GetPosition() );
1095 
1096  // pick the component up and start moving
1097  m_toolMgr->InvokeTool( "pcbnew.InteractiveEdit" );
1098  }
1099 
1100  return 0;
1101 }
1102 
1103 
1112 static bool itemIsIncludedByFilter( const BOARD_ITEM& aItem,
1113  const BOARD& aBoard,
1114  const LSET& aTechnlLayerMask,
1115  const DIALOG_BLOCK_OPTIONS::OPTIONS& aBlockOpts )
1116 {
1117  bool include = true;
1118  const PCB_LAYER_ID layer = aItem.GetLayer();
1119 
1120  // can skip without even checking item type
1121  if( !aBlockOpts.includeItemsOnInvisibleLayers
1122  && !aBoard.IsLayerVisible( layer ) )
1123  {
1124  include = false;
1125  }
1126 
1127  // if the item needsto be checked agains the options
1128  if( include )
1129  {
1130  switch( aItem.Type() )
1131  {
1132  case PCB_MODULE_T:
1133  {
1134  const auto& module = static_cast<const MODULE&>( aItem );
1135 
1136  include = aBlockOpts.includeModules;
1137 
1138  if( include && !aBlockOpts.includeLockedModules )
1139  {
1140  include = !module.IsLocked();
1141  }
1142 
1143  break;
1144  }
1145  case PCB_TRACE_T:
1146  {
1147  include = aBlockOpts.includeTracks;
1148  break;
1149  }
1150  case PCB_ZONE_AREA_T:
1151  {
1152  include = aBlockOpts.includeZones;
1153  break;
1154  }
1155  case PCB_LINE_T:
1156  case PCB_TARGET_T:
1157  case PCB_DIMENSION_T:
1158  {
1159  include = aTechnlLayerMask[layer];
1160  break;
1161  }
1162  case PCB_TEXT_T:
1163  {
1164  include = aBlockOpts.includePcbTexts
1165  && aTechnlLayerMask[layer];
1166  break;
1167  }
1168  default:
1169  {
1170  // no filterering, just select it
1171  break;
1172  }
1173  }
1174  }
1175 
1176  return include;
1177 }
1178 
1179 
1185 {
1186  LSET layerMask( Edge_Cuts );
1187 
1188  if( blockOpts.includeItemsOnTechLayers )
1189  layerMask.set();
1190 
1191  if( !blockOpts.includeBoardOutlineLayer )
1192  layerMask.set( Edge_Cuts, false );
1193 
1194  return layerMask;
1195 }
1196 
1197 
1199 {
1200  auto& opts = m_priv->m_filterOpts;
1201  DIALOG_BLOCK_OPTIONS dlg( m_frame, opts, false, _( "Filter selection" ) );
1202 
1203  const int cmd = dlg.ShowModal();
1204 
1205  if( cmd != wxID_OK )
1206  return 0;
1207 
1208  const auto& board = *getModel<BOARD>();
1209  const auto layerMask = getFilteredLayerSet( opts );
1210 
1211  // copy current selection
1212  auto selection = m_selection.GetItems();
1213 
1214  // clear current selection
1215  clearSelection();
1216 
1217  // copy selection items from the saved selection
1218  // according to the dialog options
1219  for( auto i : selection )
1220  {
1221  auto item = static_cast<BOARD_ITEM*>( i );
1222  bool include = itemIsIncludedByFilter( *item, board, layerMask, opts );
1223 
1224  if( include )
1225  {
1226  select( item );
1227  }
1228  }
1229  return 0;
1230 }
1231 
1232 
1234 {
1235  if( m_selection.Empty() )
1236  {
1237  return;
1238  }
1239 
1240  for( auto item : m_selection )
1241  {
1242  unselectVisually( static_cast<BOARD_ITEM*>( item ) );
1243  }
1244 
1245  m_selection.Clear();
1246 
1247  m_frame->SetCurItem( NULL );
1248  m_locked = true;
1249 
1250  // Inform other potentially interested tools
1252 }
1253 
1254 
1256 {
1257  BOARD_ITEM* current = NULL;
1258  PCB_BRIGHT_BOX brightBox;
1259  CONTEXT_MENU menu;
1260 
1261  getView()->Add( &brightBox );
1262 
1263  int limit = std::min( 9, aCollector->GetCount() );
1264 
1265  for( int i = 0; i < limit; ++i )
1266  {
1267  wxString text;
1268  BOARD_ITEM* item = ( *aCollector )[i];
1269  text = item->GetSelectMenuText();
1270 
1271  wxString menuText = wxString::Format("&%d. %s", i + 1, text );
1272  menu.Add( menuText, i + 1 );
1273  }
1274 
1275  menu.SetTitle( _( "Clarify selection" ) );
1276  menu.DisplayTitle( true );
1277  SetContextMenu( &menu, CMENU_NOW );
1278 
1279  while( OPT_TOOL_EVENT evt = Wait() )
1280  {
1281  if( evt->Action() == TA_CONTEXT_MENU_UPDATE )
1282  {
1283  if( current )
1284  current->ClearBrightened();
1285 
1286  int id = *evt->GetCommandId();
1287 
1288  // User has pointed an item, so show it in a different way
1289  if( id > 0 && id <= limit )
1290  {
1291  current = ( *aCollector )[id - 1];
1292  current->SetBrightened();
1293  }
1294  else
1295  {
1296  current = NULL;
1297  }
1298  }
1299  else if( evt->Action() == TA_CONTEXT_MENU_CHOICE )
1300  {
1301  boost::optional<int> id = evt->GetCommandId();
1302 
1303  // User has selected an item, so this one will be returned
1304  if( id && ( *id > 0 ) )
1305  current = ( *aCollector )[*id - 1];
1306  else
1307  current = NULL;
1308 
1309  break;
1310  }
1311 
1312  // Draw a mark to show which item is available to be selected
1313  if( current && current->IsBrightened() )
1314  {
1315  brightBox.SetItem( current );
1316  getView()->SetVisible( &brightBox, true );
1317 // getView()->Hide( &brightBox, false );
1318  getView()->Update( &brightBox, KIGFX::GEOMETRY );
1320  }
1321  }
1322 
1323  getView()->Remove( &brightBox );
1324 
1325 
1326  return current;
1327 }
1328 
1329 
1331 {
1332  int count = aCollector->GetPrimaryCount(); // try to use preferred layer
1333 
1334  if( 0 == count )
1335  count = aCollector->GetCount();
1336 
1337  for( int i = 0; i < count; ++i )
1338  {
1339  if( ( *aCollector )[i]->Type() != PCB_MODULE_T )
1340  return NULL;
1341  }
1342 
1343  // All are modules, now find smallest MODULE
1344  int minDim = 0x7FFFFFFF;
1345  int minNdx = 0;
1346 
1347  for( int i = 0; i < count; ++i )
1348  {
1349  MODULE* module = (MODULE*) ( *aCollector )[i];
1350 
1351  int lx = module->GetBoundingBox().GetWidth();
1352  int ly = module->GetBoundingBox().GetHeight();
1353 
1354  int lmin = std::min( lx, ly );
1355 
1356  if( lmin < minDim )
1357  {
1358  minDim = lmin;
1359  minNdx = i;
1360  }
1361  }
1362 
1363  return (*aCollector)[minNdx];
1364 }
1365 
1366 
1367 bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const
1368 {
1369  // Is high contrast mode enabled?
1370  bool highContrast = getView()->GetPainter()->GetSettings()->GetHighContrast();
1371 
1372  if( highContrast )
1373  {
1374  bool onActive = false; // Is the item on any of active layers?
1375  int layers[KIGFX::VIEW::VIEW_MAX_LAYERS], layers_count;
1376 
1377  // Filter out items that do not belong to active layers
1378  const std::set<unsigned int>& activeLayers = getView()->GetPainter()->
1379  GetSettings()->GetActiveLayers();
1380  aItem->ViewGetLayers( layers, layers_count );
1381 
1382  for( int i = 0; i < layers_count; ++i )
1383  {
1384  if( activeLayers.count( layers[i] ) > 0 ) // Item is on at least one of the active layers
1385  {
1386  onActive = true;
1387  break;
1388  }
1389  }
1390 
1391  if( !onActive ) // We do not want to select items that are in the background
1392  return false;
1393  }
1394 
1395  switch( aItem->Type() )
1396  {
1397  case PCB_VIA_T:
1398  {
1399  // For vias it is enough if only one of layers is visible
1400  PCB_LAYER_ID top, bottom;
1401 
1402  static_cast<const VIA*>( aItem )->LayerPair( &top, &bottom );
1403 
1404  return board()->IsLayerVisible( top ) || board()->IsLayerVisible( bottom );
1405  }
1406  break;
1407 
1408  case PCB_MODULE_T:
1409 
1410  // In the module editor, we do not want to select the module itself
1411  // rather, the module sub-components should be selected individually
1412  if( m_editModules )
1413  {
1414  return false;
1415  }
1416 
1417  if( aItem->IsOnLayer( F_Cu ) && board()->IsElementVisible( LAYER_MOD_FR ) )
1418  return !m_editModules;
1419 
1420  if( aItem->IsOnLayer( B_Cu ) && board()->IsElementVisible( LAYER_MOD_BK ) )
1421  return !m_editModules;
1422 
1423  return false;
1424 
1425  break;
1426 
1427  case PCB_MODULE_TEXT_T:
1428  if( m_multiple && !m_editModules )
1429  return false;
1430 
1431  return view()->IsVisible( aItem ) && board()->IsLayerVisible( aItem->GetLayer() );
1432 
1433  case PCB_MODULE_EDGE_T:
1434  case PCB_PAD_T:
1435  {
1436  // Multiple selection is only allowed in modedit mode
1437  // In pcbnew, you have to select subparts of modules
1438  // one-by-one, rather than with a drag selection.
1439  // This is so you can pick up items under an (unlocked)
1440  // module without also moving the module's sub-parts.
1441  if( m_multiple && !m_editModules )
1442  return false;
1443 
1444  // When editing modules, it's allowed to select them, even when
1445  // locked, since you already have to explicitly activate the
1446  // module editor to get to this stage
1447  if ( !m_editModules )
1448  {
1449  MODULE* mod = static_cast<const D_PAD*>( aItem )->GetParent();
1450  if( mod && mod->IsLocked() )
1451  return false;
1452  }
1453 
1454  break;
1455  }
1456 
1457  // These are not selectable
1458  case NOT_USED:
1459  case TYPE_NOT_INIT:
1460  return false;
1461 
1462  default: // Suppress warnings
1463  break;
1464  }
1465 
1466  // All other items are selected only if the layer on which they exist is visible
1467  return board()->IsLayerVisible( aItem->GetLayer() );
1468 }
1469 
1470 
1472 {
1473  if( aItem->IsSelected() )
1474  {
1475  return;
1476  }
1477 
1478  if( aItem->Type() == PCB_PAD_T )
1479  {
1480  MODULE* module = static_cast<MODULE*>( aItem->GetParent() );
1481 
1482  if( m_selection.Contains( module ) )
1483  return;
1484  }
1485 
1486  m_selection.Add( aItem );
1487  selectVisually( aItem );
1488 
1489 
1490  if( m_selection.Size() == 1 )
1491  {
1492  // Set as the current item, so the information about selection is displayed
1493  m_frame->SetCurItem( aItem, true );
1494  }
1495  else if( m_selection.Size() == 2 ) // Check only for 2, so it will not be
1496  { // called for every next selected item
1497  // If multiple items are selected, do not show the information about the selected item
1498  m_frame->SetCurItem( NULL, true );
1499  }
1500 }
1501 
1502 
1504 {
1505  if( !aItem->IsSelected() )
1506  return;
1507 
1508  m_selection.Remove( aItem );
1509  unselectVisually( aItem );
1510 
1511  if( m_selection.Empty() )
1512  {
1513  m_frame->SetCurItem( NULL );
1514  m_locked = true;
1515  }
1516 }
1517 
1518 
1520 {
1521  // Hide the original item, so it is shown only on overlay
1522  aItem->SetSelected();
1523  view()->Hide( aItem, true );
1524  view()->Update( aItem, KIGFX::COLOR );
1525 
1526  // Modules are treated in a special way - when they are selected, we have to
1527  // unselect all the parts that make the module, not the module itself
1528 
1529  if( aItem->Type() == PCB_MODULE_T )
1530  {
1531  static_cast<MODULE*>( aItem )->RunOnChildren( [&] ( BOARD_ITEM* item )
1532  {
1533  item->SetSelected();
1534  view()->Hide( item, true );
1535  view()->Update( item, KIGFX::COLOR );
1536  });
1537  }
1538 
1539  view()->Update( &m_selection );
1540 }
1541 
1542 
1544 {
1545  // Restore original item visibility
1546  aItem->ClearSelected();
1547  view()->Hide( aItem, false );
1548  view()->Update( aItem, KIGFX::COLOR );
1549 
1550  // Modules are treated in a special way - when they are selected, we have to
1551  // unselect all the parts that make the module, not the module itself
1552 
1553  if( aItem->Type() == PCB_MODULE_T )
1554  {
1555  static_cast<MODULE*>( aItem )->RunOnChildren( [&] ( BOARD_ITEM* item )
1556  {
1557  item->ClearSelected();
1558  view()->Hide( item, false );
1559  view()->Update( item, KIGFX::COLOR );
1560  });
1561  }
1562 
1563  view()->Update( &m_selection );
1564 }
1565 
1566 
1567 bool SELECTION_TOOL::selectionContains( const VECTOR2I& aPoint ) const
1568 {
1569  const unsigned GRIP_MARGIN = 20;
1570  VECTOR2D margin = getView()->ToWorld( VECTOR2D( GRIP_MARGIN, GRIP_MARGIN ), false );
1571 
1572  // Check if the point is located within any of the currently selected items bounding boxes
1573  for( auto item : m_selection )
1574  {
1575  BOX2I itemBox = item->ViewBBox();
1576  itemBox.Inflate( margin.x, margin.y ); // Give some margin for gripping an item
1577 
1578  if( itemBox.Contains( aPoint ) )
1579  return true;
1580  }
1581 
1582  return false;
1583 }
1584 
1585 
1586 static EDA_RECT getRect( const BOARD_ITEM* aItem )
1587 {
1588  if( aItem->Type() == PCB_MODULE_T )
1589  return static_cast<const MODULE*>( aItem )->GetFootprintRect();
1590 
1591  return aItem->GetBoundingBox();
1592 }
1593 
1594 
1595 static double calcArea( const BOARD_ITEM* aItem )
1596 {
1597  if( aItem->Type() == PCB_TRACE_T )
1598  {
1599  const TRACK* t = static_cast<const TRACK*>( aItem );
1600  return ( t->GetWidth() + t->GetLength() ) * t->GetWidth();
1601  }
1602 
1603  return getRect( aItem ).GetArea();
1604 }
1605 
1606 
1607 static double calcMinArea( GENERAL_COLLECTOR& aCollector, KICAD_T aType )
1608 {
1609  double best = std::numeric_limits<double>::max();
1610 
1611  if( !aCollector.GetCount() )
1612  return 0.0;
1613 
1614  for( int i = 0; i < aCollector.GetCount(); i++ )
1615  {
1616  BOARD_ITEM* item = aCollector[i];
1617  if( item->Type() == aType )
1618  best = std::min( best, calcArea( item ) );
1619  }
1620 
1621  return best;
1622 }
1623 
1624 
1625 static double calcMaxArea( GENERAL_COLLECTOR& aCollector, KICAD_T aType )
1626 {
1627  double best = 0.0;
1628 
1629  for( int i = 0; i < aCollector.GetCount(); i++ )
1630  {
1631  BOARD_ITEM* item = aCollector[i];
1632  if( item->Type() == aType )
1633  best = std::max( best, calcArea( item ) );
1634  }
1635 
1636  return best;
1637 }
1638 
1639 
1640 static inline double calcCommonArea( const BOARD_ITEM* aItem, const BOARD_ITEM* aOther )
1641 {
1642  if( !aItem || !aOther )
1643  return 0;
1644 
1645  return getRect( aItem ).Common( getRect( aOther ) ).GetArea();
1646 }
1647 
1648 
1649 double calcRatio( double a, double b )
1650 {
1651  if( a == 0.0 && b == 0.0 )
1652  return 1.0;
1653 
1654  if( b == 0.0 )
1656 
1657  return a / b;
1658 }
1659 
1660 
1661 // todo: explain the selection heuristics
1663 {
1664  std::set<BOARD_ITEM*> rejected;
1665 
1666  const double footprintAreaRatio = 0.2;
1667  const double modulePadMinCoverRatio = 0.45;
1668  const double padViaAreaRatio = 0.5;
1669  const double trackViaLengthRatio = 2.0;
1670  const double trackTrackLengthRatio = 0.3;
1671  const double textToFeatureMinRatio = 0.2;
1672  const double textToFootprintMinRatio = 0.4;
1673  // If the common area of two compared items is above the following threshold, they cannot
1674  // be rejected (it means they overlap and it might be hard to pick one by selecting
1675  // its unique area).
1676  const double commonAreaRatio = 0.6;
1677 
1678  PCB_LAYER_ID actLayer = m_frame->GetActiveLayer();
1679 
1680  LSET silkLayers( 2, B_SilkS, F_SilkS );
1681 
1682  if( silkLayers[actLayer] )
1683  {
1684  std::set<BOARD_ITEM*> preferred;
1685 
1686  for( int i = 0; i < aCollector.GetCount(); ++i )
1687  {
1688  BOARD_ITEM* item = aCollector[i];
1689  KICAD_T type = item->Type();
1690 
1691  if( ( type == PCB_MODULE_TEXT_T || type == PCB_TEXT_T || type == PCB_LINE_T )
1692  && silkLayers[item->GetLayer()] )
1693  {
1694  preferred.insert( item );
1695  }
1696  }
1697 
1698  if( preferred.size() != 0 )
1699  {
1700  aCollector.Empty();
1701 
1702  for( BOARD_ITEM* item : preferred )
1703  aCollector.Append( item );
1704  return;
1705  }
1706  }
1707 
1708  if( aCollector.CountType( PCB_MODULE_TEXT_T ) > 0 )
1709  {
1710  for( int i = 0; i < aCollector.GetCount(); ++i )
1711  {
1712  if( TEXTE_MODULE* txt = dyn_cast<TEXTE_MODULE*>( aCollector[i] ) )
1713  {
1714  double textArea = calcArea( txt );
1715 
1716  for( int j = 0; j < aCollector.GetCount(); ++j )
1717  {
1718  if( i == j )
1719  continue;
1720 
1721  BOARD_ITEM* item = aCollector[j];
1722  double itemArea = calcArea( item );
1723  double areaRatio = calcRatio( textArea, itemArea );
1724  double commonArea = calcCommonArea( txt, item );
1725  double itemCommonRatio = calcRatio( commonArea, itemArea );
1726  double txtCommonRatio = calcRatio( commonArea, textArea );
1727 
1728  if( item->Type() == PCB_MODULE_T && areaRatio < textToFootprintMinRatio &&
1729  itemCommonRatio < commonAreaRatio )
1730  rejected.insert( item );
1731 
1732  switch( item->Type() )
1733  {
1734  case PCB_TRACE_T:
1735  case PCB_PAD_T:
1736  case PCB_LINE_T:
1737  case PCB_VIA_T:
1738  case PCB_MODULE_T:
1739  if( areaRatio > textToFeatureMinRatio && txtCommonRatio < commonAreaRatio )
1740  rejected.insert( txt );
1741  break;
1742  default:
1743  break;
1744  }
1745  }
1746  }
1747  }
1748  }
1749 
1750  if( aCollector.CountType( PCB_MODULE_T ) > 0 )
1751  {
1752  double minArea = calcMinArea( aCollector, PCB_MODULE_T );
1753  double maxArea = calcMaxArea( aCollector, PCB_MODULE_T );
1754 
1755  if( calcRatio( minArea, maxArea ) <= footprintAreaRatio )
1756  {
1757  for( int i = 0; i < aCollector.GetCount(); ++i )
1758  {
1759  if( MODULE* mod = dyn_cast<MODULE*>( aCollector[i] ) )
1760  {
1761  double normalizedArea = calcRatio( calcArea( mod ), maxArea );
1762 
1763  if( normalizedArea > footprintAreaRatio )
1764  rejected.insert( mod );
1765  }
1766  }
1767  }
1768  }
1769 
1770  if( aCollector.CountType( PCB_PAD_T ) > 0 )
1771  {
1772  for( int i = 0; i < aCollector.GetCount(); ++i )
1773  {
1774  if( D_PAD* pad = dyn_cast<D_PAD*>( aCollector[i] ) )
1775  {
1776  double ratio = pad->GetParent()->PadCoverageRatio();
1777 
1778  if( ratio < modulePadMinCoverRatio )
1779  rejected.insert( pad->GetParent() );
1780  }
1781  }
1782  }
1783 
1784  if( aCollector.CountType( PCB_VIA_T ) > 0 )
1785  {
1786  for( int i = 0; i < aCollector.GetCount(); ++i )
1787  {
1788  if( VIA* via = dyn_cast<VIA*>( aCollector[i] ) )
1789  {
1790  double viaArea = calcArea( via );
1791 
1792  for( int j = 0; j < aCollector.GetCount(); ++j )
1793  {
1794  if( i == j )
1795  continue;
1796 
1797  BOARD_ITEM* item = aCollector[j];
1798  double areaRatio = calcRatio( viaArea, calcArea( item ) );
1799 
1800  if( item->Type() == PCB_MODULE_T && areaRatio < modulePadMinCoverRatio )
1801  rejected.insert( item );
1802 
1803  if( item->Type() == PCB_PAD_T && areaRatio < padViaAreaRatio )
1804  rejected.insert( item );
1805 
1806  if( TRACK* track = dyn_cast<TRACK*>( item ) )
1807  {
1808  if( track->GetNetCode() != via->GetNetCode() )
1809  continue;
1810 
1811  double lenRatio = (double) ( track->GetLength() + track->GetWidth() ) /
1812  (double) via->GetWidth();
1813 
1814  if( lenRatio > trackViaLengthRatio )
1815  rejected.insert( track );
1816  }
1817  }
1818  }
1819  }
1820  }
1821 
1822  int nTracks = aCollector.CountType( PCB_TRACE_T );
1823 
1824  if( nTracks > 0 )
1825  {
1826  double maxLength = 0.0;
1827  double minLength = std::numeric_limits<double>::max();
1828  double maxArea = 0.0;
1829  const TRACK* maxTrack = nullptr;
1830 
1831  for( int i = 0; i < aCollector.GetCount(); ++i )
1832  {
1833  if( TRACK* track = dyn_cast<TRACK*>( aCollector[i] ) )
1834  {
1835  maxLength = std::max( track->GetLength(), maxLength );
1836  maxLength = std::max( (double) track->GetWidth(), maxLength );
1837 
1838  minLength = std::min( std::max( track->GetLength(), (double) track->GetWidth() ), minLength );
1839 
1840  double area = track->GetLength() * track->GetWidth();
1841 
1842  if( area > maxArea )
1843  {
1844  maxArea = area;
1845  maxTrack = track;
1846  }
1847  }
1848  }
1849 
1850  if( maxLength > 0.0 && minLength / maxLength < trackTrackLengthRatio && nTracks > 1 )
1851  {
1852  for( int i = 0; i < aCollector.GetCount(); ++i )
1853  {
1854  if( TRACK* track = dyn_cast<TRACK*>( aCollector[i] ) )
1855  {
1856  double ratio = std::max( (double) track->GetWidth(), track->GetLength() ) / maxLength;
1857 
1858  if( ratio > trackTrackLengthRatio )
1859  rejected.insert( track );
1860  }
1861  }
1862  }
1863 
1864  for( int j = 0; j < aCollector.GetCount(); ++j )
1865  {
1866  if( MODULE* mod = dyn_cast<MODULE*>( aCollector[j] ) )
1867  {
1868  double ratio = calcRatio( maxArea, mod->GetFootprintRect().GetArea() );
1869 
1870  if( ratio < modulePadMinCoverRatio && calcCommonArea( maxTrack, mod ) < commonAreaRatio )
1871  rejected.insert( mod );
1872  }
1873  }
1874  }
1875 
1876  if( (unsigned) aCollector.GetCount() > rejected.size() ) // do not remove everything
1877  {
1878  for( BOARD_ITEM* item : rejected )
1879  {
1880  aCollector.Remove( item );
1881  }
1882  }
1883 }
1884 
1885 
1887 {
1888  getView()->Update( &m_selection );
1889 
1890  return 0;
1891 }
1892 
1893 
1895 {
1896  std::set<BOARD_ITEM*> rejected;
1897  std::set<BOARD_ITEM*> added;
1898 
1899  if( !m_editModules )
1900  {
1901  for( auto i : m_selection )
1902  {
1903  auto item = static_cast<BOARD_ITEM*>( i );
1904  if( item->Type() == PCB_PAD_T )
1905  {
1906  MODULE* mod = static_cast<MODULE*>( item->GetParent() );
1907 
1908  // case 1: module (or its pads) are locked
1909  if( mod && ( mod->PadsLocked() || mod->IsLocked() ) )
1910  {
1911  rejected.insert( item );
1912 
1913  if( !mod->IsLocked() && !mod->IsSelected() )
1914  added.insert( mod );
1915  }
1916 
1917  // case 2: multi-item selection contains both the module and its pads - remove the pads
1918  if( mod && m_selection.Contains( mod ) )
1919  rejected.insert( item );
1920  }
1921  }
1922  }
1923 
1924  if( !rejected.empty() )
1925  {
1926  for( BOARD_ITEM* item : rejected )
1927  unselect( item );
1928 
1929  // Inform other potentially interested tools
1931  }
1932 
1933  if( !added.empty() )
1934  {
1935  for( BOARD_ITEM* item : added )
1936  select( item );
1937 
1938  // Inform other potentially interested tools
1940  }
1941 
1942  return true;
1943 }
1944 
1945 
1946 // TODO(JE) Only works for BOARD_ITEM
1948 {
1949  return static_cast<VECTOR2I>( GetBoundingBox().GetPosition() );
1950 }
1951 
1952 
1954 {
1955  return static_cast<VECTOR2I>( GetBoundingBox().Centre() );
1956 }
1957 
1958 
1960 {
1961  EDA_RECT bbox;
1962 
1963  bbox = Front()->GetBoundingBox();
1964  auto i = m_items.begin();
1965  ++i;
1966 
1967  for( ; i != m_items.end(); ++i )
1968  {
1969  bbox.Merge( (*i)->GetBoundingBox() );
1970  }
1971 
1972  return bbox;
1973 }
1974 
1975 
1976 EDA_ITEM* SELECTION::GetTopLeftItem( bool onlyModules ) const
1977 {
1978  BOARD_ITEM* topLeftItem = nullptr;
1979  BOARD_ITEM* currentItem;
1980 
1981  wxPoint pnt;
1982 
1983  // find the leftmost (smallest x coord) and highest (smallest y with the smallest x) item in the selection
1984  for( auto item : m_items )
1985  {
1986  currentItem = static_cast<BOARD_ITEM*>( item );
1987  pnt = currentItem->GetPosition();
1988 
1989  if( ( currentItem->Type() != PCB_MODULE_T ) && onlyModules )
1990  {
1991  continue;
1992  }
1993  else
1994  {
1995  if( topLeftItem == nullptr )
1996  {
1997  topLeftItem = currentItem;
1998  }
1999  else if( ( pnt.x < topLeftItem->GetPosition().x ) ||
2000  ( ( topLeftItem->GetPosition().x == pnt.x ) &&
2001  ( pnt.y < topLeftItem->GetPosition().y ) ) )
2002  {
2003  topLeftItem = currentItem;
2004  }
2005  }
2006  }
2007 
2008  return static_cast<EDA_ITEM*>( topLeftItem );
2009 }
2010 
2011 
2013 {
2014  return GetTopLeftItem( true );
2015 }
2016 
2017 
2019 {
2020  EDA_RECT eda_bbox;
2021 
2022  if( Size() == 1 )
2023  {
2024  eda_bbox = Front()->GetBoundingBox();
2025  }
2026  else if( Size() > 1 )
2027  {
2028  eda_bbox = Front()->GetBoundingBox();
2029  auto i = m_items.begin();
2030  ++i;
2031 
2032  for( ; i != m_items.end(); ++i )
2033  {
2034  eda_bbox.Merge( (*i)->GetBoundingBox() );
2035  }
2036  }
2037 
2038  return BOX2I( eda_bbox.GetOrigin(), eda_bbox.GetSize() );
2039 }
2040 
2041 
2043 {
2044  std::vector<VIEW_ITEM*> items;
2045 
2046  for( auto item : m_items )
2047  {
2048  items.push_back( item );
2049 
2050  if( item->Type() == PCB_MODULE_T )
2051  {
2052  MODULE* module = static_cast<MODULE*>( item );
2053  module->RunOnChildren( [&] ( BOARD_ITEM* bitem ) { items.push_back( bitem ); } );
2054  }
2055  }
2056 
2057  return items;
2058 }
2059 
2060 
2061 const TOOL_EVENT SELECTION_TOOL::SelectedEvent( TC_MESSAGE, TA_ACTION, "pcbnew.InteractiveSelection.selected" );
2062 const TOOL_EVENT SELECTION_TOOL::UnselectedEvent( TC_MESSAGE, TA_ACTION, "pcbnew.InteractiveSelection.unselected" );
2063 const TOOL_EVENT SELECTION_TOOL::ClearedEvent( TC_MESSAGE, TA_ACTION, "pcbnew.InteractiveSelection.cleared" );
static TOOL_ACTION selectItems
Selects a list of items (specified as the event parameter)
Definition: pcb_actions.h:59
void Empty()
Function Empty sets the list to empty.
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:53
static TOOL_ACTION selectionActivate
Activation of the selection tool.
Definition: pcb_actions.h:47
void Hide(VIEW_ITEM *aItem, bool aHide=true)
Temporarily hides the item in the view (e.g.
Definition: view.cpp:1356
int GetCount() const
Function GetCount returns the number of objects in the list.
int UnselectItem(const TOOL_EVENT &aEvent)
Item unselection event handler.
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
int Main(const TOOL_EVENT &aEvent)
Function Main()
BOARD_ITEM_CONTAINER * GetParent() const
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:106
KIGFX::VIEW * view() const
Definition: pcb_tool.h:123
virtual const EDA_RECT GetBoundingBox() const
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes...
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
BOX2< VECTOR2I > BOX2I
Definition: box2.h:468
bool IsElementVisible(GAL_LAYER_ID LAYER_aPCB) const
Function IsElementVisible tests whether a given element category is visible.
void RunOnChildren(std::function< void(BOARD_ITEM *)> aFunction)
Function RunOnChildren.
bool GetHighContrast() const
Function GetHighContrast Returns information about high contrast display mode.
Definition: painter.h:161
static DIALOG_BLOCK_OPTIONS::OPTIONS blockOpts
void SetEnd(VECTOR2I aEnd)
Set the current end of the rectangle (the corner that moves with the cursor.
void zoomFitSelection(void)
Zooms the screen to center and fit the current selection.
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:81
void ForceRefresh()
Function ForceRefresh() Forces a redraw.
void SetViewport(const BOX2D &aViewport)
Function SetViewport() Sets the visible area of the VIEW.
Definition: view.cpp:513
static double calcCommonArea(const BOARD_ITEM *aItem, const BOARD_ITEM *aOther)
void Merge(const EDA_RECT &aRect)
Function Merge modifies the position and size of the rectangle in order to contain aRect...
static const KICAD_T AllBoardItems[]
A scan list for all editable board items, like PcbGeneralLocateAndDisplay()
Definition: collectors.h:241
TEXTE_PCB class definition.
SELECTION & RequestSelection(int aFlags=SELECTION_DEFAULT)
Function RequestSelection()
bool IsBrightened() const
Definition: base_struct.h:224
std::unique_ptr< PRIV > m_priv
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:417
Model changes (required full reload)
Definition: tool_base.h:83
int selectSameSheet(const TOOL_EVENT &aEvent)
Selects all modules belonging to same hierarchical sheet as the selected footprint.
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Function IsOnLayer tests to see if this object is on the given layer.
This file is part of the common library.
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class...
bool m_multiple
Flag saying if multiple selection mode is active.
void SetOrigin(VECTOR2I aOrigin)
Set the origin of the rectange (the fixed corner)
void ClearSelected()
Definition: base_struct.h:231
Class CONTEXT_MENU.
Definition: context_menu.h:44
VIEW_CONTROLS class definition.
void Collect(BOARD_ITEM *aItem, const KICAD_T aScanList[], const wxPoint &aRefPos, const COLLECTORS_GUIDE &aGuide)
Function Collect scans a BOARD_ITEM using this class's Inspector method, which does the collection...
Definition: collectors.cpp:447
Classes BOARD_ITEM and BOARD_CONNECTED_ITEM.
virtual const VIEW_GROUP::ITEMS updateDrawList() const override
void guessSelectionCandidates(GENERAL_COLLECTOR &aCollector) const
Function guessSelectionCandidates() Tries to guess best selection candidates in case multiple items a...
bool selectCursor(bool aSelectAlways=false)
Function selectCursor() Selects an item under the cursor unless there is something already selected o...
Class SELECTION_TOOL.
bool m_additive
Flag saying if items should be added to the current selection or rather replace it.
bool Contains(EDA_ITEM *aItem) const
Definition: selection.h:100
Class BOARD to handle a board.
void EnableWarp(bool aEnabled)
Definition: dialog_find.cpp:67
const wxPoint & GetPosition() const override
Definition: class_module.h:155
SELECTION_LOCK_FLAGS CheckLock()
Checks if the user has agreed to modify locked items for the given selection.
static TOOL_ACTION unselectItem
Unselects an item (specified as the event parameter).
Definition: pcb_actions.h:62
bool Contains(const Vec &aPoint) const
Function Contains.
Definition: box2.h:139
CONDITIONAL_MENU & GetMenu()
Function GetMenu.
Definition: tool_menu.cpp:49
the 3d code uses this value
Definition: typeinfo.h:92
static TOOL_ACTION selectNet
Selects all connections belonging to a single net.
Definition: pcb_actions.h:74
EDA_ITEM * Front() const
Definition: selection.h:144
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:220
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:440
static TOOL_ACTION unselectItems
Unselects a list of items (specified as the event parameter)
Definition: pcb_actions.h:65
int find(const TOOL_EVENT &aEvent)
Find an item.
MODULE * Next() const
Definition: class_module.h:100
class ZONE_CONTAINER, a zone area
Definition: typeinfo.h:114
int findMove(const TOOL_EVENT &aEvent)
Find an item and start moving.
void Remove(VIEW_ITEM *aItem)
Function Remove() Removes a VIEW_ITEM from the view.
Definition: view.cpp:341
static TOOL_ACTION properties
Activation of the edit tool.
Definition: pcb_actions.h:102
EDA_RECT Common(const EDA_RECT &aRect) const
Function Common returns the area that is common with another rectangle.
void AddSubMenu(std::shared_ptr< CONTEXT_MENU > aSubMenu)
Function CreateSubMenu.
Definition: tool_menu.cpp:55
VECTOR2I GetPosition() const
Returns the top left point of the selection area bounding box.
virtual void ViewGetLayers(int aLayers[], int &aCount) const override
Function ViewGetLayers() Returns the all the layers within the VIEW the object is painted on...
void SetCurItem(BOARD_ITEM *aItem, bool aDisplayInfo=true)
Function SetCurItem sets the currently selected item and displays it in the MsgPanel.
int UnselectItems(const TOOL_EVENT &aEvent)
Multiple item unselection event handler
show modules on back
void SetBrightened()
Definition: base_struct.h:229
OPT_TOOL_EVENT Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
int GetHeight() const
bool IsSelected() const
Definition: base_struct.h:221
virtual const wxPoint & GetPosition() const =0
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:104
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:125
static TOOL_ACTION selectConnection
Selects a connection between junctions.
Definition: pcb_actions.h:68
Class that groups generic conditions for selected items.
static int LegacyHotKey(int aHotKey)
Creates a hot key code that refers to a legacy hot key setting, instead of a particular key...
Definition: tool_action.h:174
class D_PAD, a pad in a footprint
Definition: typeinfo.h:102
void unselectVisually(BOARD_ITEM *aItem)
Function unselectVisually() Marks item as selected, but does not add it to the ITEMS_PICKED_LIST.
static const TOOL_EVENT ClearedEvent
Event sent after selection is cleared.
Visibility flag has changed.
Definition: view_item.h:56
int CountType(KICAD_T aType)
Function CountType counts the number of items matching aType.
static double calcArea(const BOARD_ITEM *aItem)
Class BOARD_CONNECTED_ITEM is a base class derived from BOARD_ITEM for items that can be connected an...
void SetScale(double aScale)
Function SetScale() Sets the scaling factor.
Definition: view.h:247
virtual wxString GetSelectMenuText() const
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
static bool NotEmpty(const SELECTION &aSelection)
Function NotEmpty Tests if there are any items selected.
int selectConnection(const TOOL_EVENT &aEvent)
Selects a trivial connection (between two junctions) of items in selection
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:106
void Remove(int aIndex)
Function Remove removes the item at aIndex (first position is 0);.
bool InvokeTool(TOOL_ID aToolId)
Function InvokeTool() Calls a tool by sending a tool activation event to tool of given ID...
search types array terminator (End Of Types)
Definition: typeinfo.h:94
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:90
static TOOL_ACTION selectionModified
Modified selection notification.
Definition: pcb_actions.h:105
Functions relatives to tracks, vias and segments used to fill zones.
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:107
Pcbnew hotkeys.
void SetIsHover(bool aIsHover)
Definition: selection.h:61
wxMenuItem * Add(const wxString &aLabel, int aId, const BITMAP_OPAQUE *aIcon=NULL)
Function Add() Adds an entry to the menu.
BOARD_ITEM * pickSmallestComponent(GENERAL_COLLECTOR *aCollector)
Function pickSmallestComponent() Allows to find the smallest (in terms of bounding box area) item fro...
Private implementation of firewalled private data.
virtual void Add(EDA_ITEM *aItem)
Definition: selection.h:71
void ClearBrightened()
Definition: base_struct.h:233
void Append(EDA_ITEM *item)
Function Append adds an item to the end of the list.
show modules on front
void findCallback(BOARD_ITEM *aItem)
Find dialog callback.
const wxPoint & GetOrigin() const
const std::set< EDA_ITEM * > GetItems() const
Definition: selection.h:117
int selectCopper(const TOOL_EVENT &aEvent)
Selects items with a continuous copper connection to items in selection
int filterSelection(const TOOL_EVENT &aEvent)
Invoke filter dialog and modify current selection
bool PadsLocked() const
Definition: class_module.h:272
Struct that will be set with the result of the user choices in the dialog.
class MODULE, a footprint
Definition: typeinfo.h:101
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes...
const BOX2I ViewBBox() const override
Function ViewBBox() Returns the bounding box for all stored items covering all its layers...
PCB_LAYER_ID
A quick note on layer IDs:
double GetArea() const
Function GetArea returns the area of the rectangle.
void AddStandardSubMenus(EDA_DRAW_FRAME &aFrame)
Function CreateBasicMenu.
Definition: tool_menu.cpp:95
GENERAL_COLLECTORS_GUIDE GetCollectorsGuide()
Function GetCollectorsGuide.
Class LSET is a set of PCB_LAYER_IDs.
bool selectable(const BOARD_ITEM *aItem) const
Function selectable() Checks conditions for an item to be selected.
void toggleSelection(BOARD_ITEM *aItem)
Function toggleSelection() Changes selection status of a given item.
void SetCenter(const VECTOR2D &aCenter)
Function SetCenter() Sets the center point of the VIEW (i.e.
Definition: view.cpp:564
static double calcMaxArea(GENERAL_COLLECTOR &aCollector, KICAD_T aType)
VECTOR2< double > VECTOR2D
Definition: vector2d.h:589
void selectAllItemsOnSheet(wxString &aSheetpath)
Selects all items with the given sheet timestamp name (the sheet path)
void SetSelected()
Definition: base_struct.h:227
static TOOL_ACTION find
Find an item.
Definition: pcb_actions.h:366
void SetItem(EDA_ITEM *aItem)
Definition: bright_box.cpp:61
int updateSelection(const TOOL_EVENT &aEvent)
Event handler to update the selection VIEW_ITEM.
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:576
bool selectMultiple()
Function selectMultiple() Handles drawing a selection box that allows to select many items at the sam...
void selectAllItemsOnNet(int aNetCode)
Selects all items with the given net code.
int selectOnSheetFromEeschema(const TOOL_EVENT &aEvent)
Selects all modules belonging to same sheet, from Eeschema, using crossprobing
SELECTION_LOCK_FLAGS
Definition: selection.h:184
Class TOOL_EVENT.
Definition: tool_event.h:162
static const int VIEW_MAX_LAYERS
maximum number of layers that may be shown
Definition: view.h:641
const BOX2I ViewBBox() const override
Function ViewBBox() returns the bounding box of the item covering all its layers. ...
BOARD_ITEM * disambiguationMenu(GENERAL_COLLECTOR *aItems)
Function disambiguationMenu() Handles the menu that allows to select one of many items in case there ...
T * GetFirst() const
Function GetFirst returns the first T* in the list without removing it, or NULL if the list is empty...
Definition: dlist.h:163
EDA_ITEM * GetTopLeftItem(bool onlyModules=false) const
SELECTION m_selection
Current state of selection.
SELECTION & GetSelection()
Function GetSelection()
void SetContextMenu(CONTEXT_MENU *aMenu, CONTEXT_MENU_TRIGGER aTrigger=CMENU_BUTTON)
Function SetContextMenu()
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
void clearSelection()
Function clearSelection() Clears the current selection.
PCB_BASE_FRAME * m_frame
Pointer to the parent frame.
Items that may change while the view stays the same (noncached)
Definition: definitions.h:43
VIEW_GROUP extends VIEW_ITEM by possibility of grouping items into a single object.
static const TOOL_EVENT UnselectedEvent
Event sent after an item is unselected.
TOOL_MENU m_menu
Menu model displayed by the tool.
EDA_RECT GetBoundingBox() const
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Function ForceCursorPosition() Places the cursor immediately at a given point.
wxPoint Centre() const
TRACK * MarkTrace(TRACK *aTrace, int *aCount, double *aTraceLength, double *aInPackageLength, bool aReorder)
Function MarkTrace marks a chain of trace segments, connected to aTrace.
PAINTER * GetPainter() const
Function GetPainter() Returns the painter object used by the view for drawing VIEW_ITEMS.
Definition: view.h:196
void selectVisually(BOARD_ITEM *aItem)
Function selectVisually() Marks item as selected, but does not add it to the ITEMS_PICKED_LIST.
static TOOL_ACTION selectCopper
Selects whole copper connection.
Definition: pcb_actions.h:71
All active tools
Definition: tool_event.h:138
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:1389
int SelectItem(const TOOL_EVENT &aEvent)
Item selection event handler.
class DIMENSION, a dimension (graphic item)
Definition: typeinfo.h:112
TOOL_SETTINGS & GetSettings()
Definition: tool_base.cpp:72
bool IsLocked() const override
Function IsLocked.
Definition: class_module.h:236
const wxPoint & GetPosition() const
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.
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:36
bool selectPoint(const VECTOR2I &aWhere, bool aOnDrag=false)
Function selectPoint() Selects an item pointed by the parameter aWhere.
static const TOOL_EVENT SelectedEvent
Event sent after an item is selected.
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:113
bool m_editModules
Definition: pcb_tool.h:128
KIGFX::VIEW * getView() const
Function getView()
Definition: tool_base.cpp:30
virtual unsigned int GetSize() const override
Function GetSize() Returns the number of stored items.
Definition: selection.h:86
std::vector< VIEW_ITEM * > ITEMS
Definition: view_group.h:45
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:105
static TOOL_ACTION filterSelection
Filters the items in the current selection (invokes dialog)
Definition: pcb_actions.h:83
void Normalize()
Function Normalize ensures that the height ant width are positive.
void SetCallback(boost::function< void(BOARD_ITEM *)> aCallback)
Definition: dialog_find.h:39
bool m_subtractive
Flag saying if items should be removed from the current selection.
virtual bool HitTest(const wxPoint &aPosition) const override
Function HitTest tests if aPosition is contained within or on the bounding area of an item...
virtual RENDER_SETTINGS * GetSettings()=0
Function GetSettings Returns pointer to current settings that are going to be used when drawing items...
Class PCB_BRIGHT_BOX.
PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:266
T Parameter() const
Function Parameter() Returns a non-standard parameter assigned to the event.
Definition: tool_event.h:373
class MARKER_PCB, a marker used to show something
Definition: typeinfo.h:111
const int scale
TRACK * Next() const
Definition: class_track.h:98
void CloseContextMenu(OPT_TOOL_EVENT &evt)
Function CloseContextMenu.
Definition: tool_menu.cpp:82
static TOOL_ACTION highlightNet
Definition: pcb_actions.h:356
void AddMenu(CONTEXT_MENU *aMenu, bool aExpand=false, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Function AddMenu()
int GetPrimaryCount()
Function GetPrimaryCount.
Definition: collectors.h:344
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
void selectAllItemsConnectedToTrack(TRACK &aSourceTrack)
Selects all items connected by copper tracks to the given TRACK.
static TOOL_ACTION selectOnSheetFromEeschema
Selects all components on sheet from Eeschema crossprobing.
Definition: pcb_actions.h:77
#define max(a, b)
Definition: auxiliary.h:86
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:169
std::set< EDA_ITEM * > m_items
Set of selected items.
Definition: selection.h:175
DLIST< MODULE > m_Modules
Definition: class_board.h:245
void SetSubtractive(bool aSubtractive)
int GetWidth() const
Definition: class_track.h:115
static const KICAD_T ModuleItems[]
A scan list for primary module items.
Definition: collectors.h:288
Class GENERAL_COLLECTOR is intended for use when the right click button is pressed, or when the plain "arrow" tool is in effect.
Definition: collectors.h:211
void SetTitle(const wxString &aTitle) override
Function SetTitle() Sets title for the context menu.
Class TOOL_ACTION.
Definition: tool_action.h:46
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:56
static SELECTION_CONDITION OnlyType(KICAD_T aType)
Function OnlyType Creates a functor that tests if the selected items are only of given type...
Class EDA_RECT handles the component boundary box.
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:151
int GetWidth() const
bool selectionContains(const VECTOR2I &aPoint) const
Function selectionContains() Checks if the given point is placed within any of selected items' boundi...
double calcRatio(double a, double b)
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:80
double GetScale() const
Function GetScale()
Definition: view.h:265
double GetLength() const
Function GetLength returns the length of the track using the hypotenuse calculation.
Definition: class_track.h:171
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Sets the item visibility.
Definition: view.cpp:1335
int SelectItems(const TOOL_EVENT &aEvent)
Multiple item selection event handler
Class SELECTION_AREA.
EDA_DRAW_PANEL_GAL * GetGalCanvas() const
Function GetGalCanvas returns a pointer to GAL-based canvas of given EDA draw frame.
Definition: draw_frame.h:817
bool m_locked
Can other tools modify locked items.
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:108
void SetTransitions() override
Sets up handlers for various events.
int Size() const
Returns the number of selected parts.
Definition: selection.h:112
MODULE * GetFootprintFromBoardByReference()
Function GetFootprintFromBoardByReference.
Definition: modules.cpp:62
void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Function Add() Adds a VIEW_ITEM to the view.
Definition: view.cpp:311
void DisplayTitle(bool aDisplay=true)
Function DisplayTitle() Decides whether a title for a pop up menu should be displayed.
static TOOL_ACTION findMove
Find an item and start moving.
Definition: pcb_actions.h:369
Module description (excepted pads)
void ProcessEvent(const TOOL_EVENT &aEvent)
Propagates an event to tools that requested events of matching type(s).
Class VIEW.
Definition: view.h:58
Class GENERAL_COLLECTORS_GUIDE is a general implementation of a COLLECTORS_GUIDE. ...
Definition: collectors.h:378
bool IsVisible(const VIEW_ITEM *aItem) const
Returns information if the item is visible (or not).
Definition: view.cpp:1375
bool SanitizeSelection()
Makes sure a group selection does not contain items that would cause conflicts when moving/rotating t...
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:103
virtual const BOX2I ViewBBox() const override
Function ViewBBox() returns the bounding box of the item covering all its layers. ...
void SetAdditive(bool aAdditive)
VECTOR2I GetCenter() const
Returns the center point of the selection area bounding box.
void SetHighlight(bool aEnabled, int aNetcode=-1)
Function SetHighlight Turns on/off highlighting - it may be done for the active layer or the specifie...
Definition: painter.h:140
const wxSize & GetSize() const
EDA_ITEM * GetTopLeftModule() const
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Function IsOK displays a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:129
void ShowContextMenu(SELECTION &aSelection)
Function ShowContextMenu.
Definition: tool_menu.cpp:62
CONTEXT_MENU * create() const override
Returns an instance of this class. It has to be overridden in inheriting classes. ...
virtual PCB_LAYER_ID GetActiveLayer() const
Function GetActiveLayer returns the active layer.
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:290
#define mod(a, n)
Definition: greymap.cpp:24
void selectAllItemsConnectedToItem(BOARD_CONNECTED_ITEM &aSourceItem)
Selects all items connected (by copper) to the given item.
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:50
static bool itemIsIncludedByFilter(const BOARD_ITEM &aItem, const BOARD &aBoard, const LSET &aTechnlLayerMask, const DIALOG_BLOCK_OPTIONS::OPTIONS &aBlockOpts)
Function itemIsIncludedByFilter()
static LSET getFilteredLayerSet(const DIALOG_BLOCK_OPTIONS::OPTIONS &blockOpts)
Gets the technical layers that are part of the given selection opts.
void update() override
Update menu state stub.
DIALOG_BLOCK_OPTIONS::OPTIONS m_filterOpts
#define min(a, b)
Definition: auxiliary.h:85
Color has changed.
Definition: view_item.h:57
static TOOL_ACTION selectSameSheet
Selects all components on the same sheet as the selected footprint.
Definition: pcb_actions.h:80
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:443
BOARD * board() const
Definition: pcb_tool.h:126
static double calcMinArea(GENERAL_COLLECTOR &aCollector, KICAD_T aType)
virtual void Remove(EDA_ITEM *aItem)
Definition: selection.h:76