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 <ratsnest_data.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::unselectItem( "pcbnew.InteractiveSelection.UnselectItem",
74  AS_GLOBAL, 0,
75  "", "" ); // No description, it is not supposed to be shown anywhere
76 
77 TOOL_ACTION PCB_ACTIONS::selectionClear( "pcbnew.InteractiveSelection.Clear",
78  AS_GLOBAL, 0,
79  "", "" ); // No description, it is not supposed to be shown anywhere
80 
81 TOOL_ACTION PCB_ACTIONS::selectConnection( "pcbnew.InteractiveSelection.SelectConnection",
82  AS_GLOBAL, 'U',
83  _( "Trivial Connection" ), _( "Selects a connection between two junctions." ) );
84 
85 TOOL_ACTION PCB_ACTIONS::selectCopper( "pcbnew.InteractiveSelection.SelectCopper",
86  AS_GLOBAL, 'I',
87  _( "Copper Connection" ), _( "Selects whole copper connection." ) );
88 
89 TOOL_ACTION PCB_ACTIONS::selectNet( "pcbnew.InteractiveSelection.SelectNet",
90  AS_GLOBAL, 0,
91  _( "Whole Net" ), _( "Selects all tracks & vias belonging to the same net." ) );
92 
93 TOOL_ACTION PCB_ACTIONS::selectOnSheetFromEeschema( "pcbnew.InteractiveSelection.SelectOnSheet",
94  AS_GLOBAL, 0,
95  _( "Sheet" ), _( "Selects all modules and tracks in the schematic sheet" ) );
96 
97 TOOL_ACTION PCB_ACTIONS::selectSameSheet( "pcbnew.InteractiveSelection.SelectSameSheet",
98  AS_GLOBAL, 0,
99  _( "Items in Same Hierarchical Sheet" ),
100  _( "Selects all modules and tracks in the same schematic sheet" ) );
101 
102 TOOL_ACTION PCB_ACTIONS::find( "pcbnew.InteractiveSelection.Find",
103  AS_GLOBAL, 0, //TOOL_ACTION::LegacyHotKey( HK_FIND_ITEM ), // handled by wxWidgets
104  _( "Find Item" ),_( "Searches the document for an item" ), find_xpm );
105 
106 TOOL_ACTION PCB_ACTIONS::findMove( "pcbnew.InteractiveSelection.FindMove",
108 
109 TOOL_ACTION PCB_ACTIONS::filterSelection( "pcbnew.InteractiveSelection.FilterSelection",
110  AS_GLOBAL, 0,
111  _( "Filter Selection" ), _( "Filter the types of items in the selection" ),
112  nullptr );
113 
114 
115 
117 {
118 public:
120  {
121  SetTitle( _( "Select..." ) );
122 
124 
125  AppendSeparator();
126 
129  Add( PCB_ACTIONS::selectNet );
131  }
132 
133 private:
134 
135  void update() override
136  {
137  using S_C = SELECTION_CONDITIONS;
138 
139  const auto& selection = getToolManager()->GetTool<SELECTION_TOOL>()->GetSelection();
140 
141  bool connItem = ( S_C::OnlyType( PCB_VIA_T ) || S_C::OnlyType( PCB_TRACE_T ) )( selection );
142  bool sheetSelEnabled = ( S_C::OnlyType( PCB_MODULE_T ) )( selection );
143 
144  Enable( getMenuId( PCB_ACTIONS::selectNet ), connItem );
145  Enable( getMenuId( PCB_ACTIONS::selectCopper ), connItem );
146  Enable( getMenuId( PCB_ACTIONS::selectConnection ), connItem );
147  Enable( getMenuId( PCB_ACTIONS::selectSameSheet ), sheetSelEnabled );
148  }
149 
150  CONTEXT_MENU* create() const override
151  {
152  return new SELECT_MENU();
153  }
154 };
155 
156 
161 {
162 public:
164 };
165 
166 
168  PCB_TOOL( "pcbnew.InteractiveSelection" ),
169  m_frame( NULL ), m_additive( false ), m_subtractive( false ),
170  m_multiple( false ),
171  m_locked( true ), m_menu( *this ),
172  m_priv( std::make_unique<PRIV>() )
173 {
174 
175 }
176 
177 
179 {
180  getView()->Remove( &m_selection );
181 }
182 
183 
185 {
186  auto selectMenu = std::make_shared<SELECT_MENU>();
187  selectMenu->SetTool( this );
188  m_menu.AddSubMenu( selectMenu );
189 
190  auto& menu = m_menu.GetMenu();
191 
192  menu.AddMenu( selectMenu.get(), false, SELECTION_CONDITIONS::NotEmpty );
193  // only show separator if there is a Select menu to show above it
194  menu.AddSeparator( SELECTION_CONDITIONS::NotEmpty, 1000 );
195 
196  m_menu.AddStandardSubMenus( *getEditFrame<PCB_BASE_FRAME>() );
197 
198  return true;
199 }
200 
201 
203 {
204  m_frame = getEditFrame<PCB_BASE_FRAME>();
205  m_locked = true;
206 
207  if( aReason == TOOL_BASE::MODEL_RELOAD )
208  {
209  // Remove pointers to the selected items from containers
210  // without changing their properties (as they are already deleted
211  // while a new board is loaded)
212  m_selection.Clear();
213  getView()->GetPainter()->GetSettings()->SetHighlight( false );
214  }
215  else
216  // Restore previous properties of selected items and remove them from containers
217  clearSelection();
218 
219  // Reinsert the VIEW_GROUP, in case it was removed from the VIEW
220  getView()->Remove( &m_selection );
221  getView()->Add( &m_selection );
222 }
223 
224 
225 int SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
226 {
227  // Main loop: keep receiving events
228  while( OPT_TOOL_EVENT evt = Wait() )
229  {
230  // Should selected items be added to the current selection or
231  // become the new selection (discarding previously selected items)
232  m_additive = evt->Modifier( MD_SHIFT );
233 
234  // Should selected items be REMOVED from the current selection?
235  // This will be ignored if the SHIFT modifier is pressed
236  m_subtractive = !m_additive && evt->Modifier( MD_CTRL );
237 
238  // single click? Select single object
239  if( evt->IsClick( BUT_LEFT ) )
240  {
241  if( evt->Modifier( MD_CTRL ) && !m_editModules )
242  {
244  }
245  else
246  {
247  if( !m_additive )
248  clearSelection();
249 
250  selectPoint( evt->Position() );
251  }
252  }
253 
254  // right click? if there is any object - show the context menu
255  else if( evt->IsClick( BUT_RIGHT ) )
256  {
257  bool emptySelection = m_selection.Empty();
258 
259  if( emptySelection )
260  selectPoint( evt->Position() );
261 
263  }
264 
265  // double click? Display the properties window
266  else if( evt->IsDblClick( BUT_LEFT ) )
267  {
268  if( m_selection.Empty() )
269  selectPoint( evt->Position() );
270 
272  }
273 
274  // drag with LMB? Select multiple objects (or at least draw a selection box) or drag them
275  else if( evt->IsDrag( BUT_LEFT ) )
276  {
277  if( m_additive || m_subtractive )
278  {
279  selectMultiple();
280  }
281  else if( m_selection.Empty() )
282  {
283  // There is nothing selected, so try to select something
284  if( !selectCursor() )
285  {
286  // If nothings has been selected or user wants to select more
287  // draw the selection box
288  selectMultiple();
289  }
290  else
291  {
292  m_toolMgr->InvokeTool( "pcbnew.InteractiveEdit" );
293  }
294  }
295 
296  else
297  {
298  // Check if dragging has started within any of selected items bounding box
299  if( selectionContains( evt->Position() ) )
300  {
301  // Yes -> run the move tool and wait till it finishes
302  m_toolMgr->InvokeTool( "pcbnew.InteractiveEdit" );
303  }
304  else
305  {
306  // No -> clear the selection list
307  clearSelection();
308  }
309  }
310  }
311 
312  else if( evt->IsCancel() || evt->Action() == TA_UNDO_REDO_PRE )
313  {
314  clearSelection();
315  }
316 
317  else if( evt->Action() == TA_CONTEXT_MENU_CLOSED )
318  {
319  m_menu.CloseContextMenu( evt );
320  }
321  }
322 
323  // This tool is supposed to be active forever
324  assert( false );
325 
326  return 0;
327 }
328 
329 
331 {
332  return m_selection;
333 }
334 
335 
337 {
338  if ( m_selection.Empty() )
339  {
341  m_selection.SetIsHover( true );
342  }
343  else
344  {
345  m_selection.SetIsHover( false );
346  }
347 
348  // Be careful with iterators: items can be removed from list
349  // that invalidate iterators.
350  for( unsigned ii = 0; ii < m_selection.GetSize(); ii++ )
351  {
352  EDA_ITEM* item = m_selection[ii];
353 
354  if( ( aFlags & SELECTION_EDITABLE ) && item->Type() == PCB_MARKER_T )
355  {
356  unselect( static_cast<BOARD_ITEM *>( item ) );
357  }
358  }
359 
360  if ( aFlags & SELECTION_SANITIZE_PADS )
362 
363  return m_selection;
364 }
365 
366 
368 {
369  if( aItem->IsSelected() )
370  {
371  unselect( aItem );
372 
373  // Inform other potentially interested tools
375  }
376  else
377  {
378  if( !m_additive )
379  clearSelection();
380 
381  // Prevent selection of invisible or inactive items
382  if( selectable( aItem ) )
383  {
384  select( aItem );
385 
386  // Inform other potentially interested tools
388  }
389  }
390 
392 }
393 
394 
395 bool SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag )
396 {
397  BOARD_ITEM* item;
399  GENERAL_COLLECTOR collector;
400 
401  collector.Collect( board(),
403  wxPoint( aWhere.x, aWhere.y ), guide );
404 
405  bool anyCollected = collector.GetCount() != 0;
406 
407  // Remove unselectable items
408  for( int i = collector.GetCount() - 1; i >= 0; --i )
409  {
410  if( !selectable( collector[i] ) || ( aOnDrag && collector[i]->IsLocked() ) )
411  collector.Remove( i );
412  }
413 
414  switch( collector.GetCount() )
415  {
416  case 0:
417  if( !m_additive && anyCollected )
418  clearSelection();
419 
420  return false;
421 
422  case 1:
423  toggleSelection( collector[0] );
424 
425  return true;
426 
427  default:
428  // Apply some ugly heuristics to avoid disambiguation menus whenever possible
429  guessSelectionCandidates( collector );
430 
431  // Let's see if there is still disambiguation in selection..
432  if( collector.GetCount() == 1 )
433  {
434  toggleSelection( collector[0] );
435 
436  return true;
437  }
438  else if( collector.GetCount() > 1 )
439  {
440  if( aOnDrag )
442 
443  item = disambiguationMenu( &collector );
444 
445  if( item )
446  {
447  toggleSelection( item );
448 
449  return true;
450  }
451  }
452  break;
453  }
454 
455  return false;
456 }
457 
458 
459 bool SELECTION_TOOL::selectCursor( bool aSelectAlways )
460 {
461  if( aSelectAlways || m_selection.Empty() )
462  {
463  clearSelection();
464  selectPoint( getViewControls()->GetCursorPosition() );
465  }
466 
467  return !m_selection.Empty();
468 }
469 
470 
472 {
473  bool cancelled = false; // Was the tool cancelled while it was running?
474  m_multiple = true; // Multiple selection mode is active
475  KIGFX::VIEW* view = getView();
476  getViewControls()->SetAutoPan( true );
477 
479  view->Add( &area );
480 
481  while( OPT_TOOL_EVENT evt = Wait() )
482  {
483  if( evt->IsCancel() )
484  {
485  cancelled = true;
486  break;
487  }
488 
489  if( evt->IsDrag( BUT_LEFT ) )
490  {
491 
492  // Start drawing a selection box
493  area.SetOrigin( evt->DragOrigin() );
494  area.SetEnd( evt->Position() );
495  area.SetAdditive( m_additive );
497 
498  view->SetVisible( &area, true );
499  view->Update( &area );
500  }
501 
502  if( evt->IsMouseUp( BUT_LEFT ) )
503  {
504  // End drawing the selection box
505  view->SetVisible( &area, false );
506 
507  // Mark items within the selection box as selected
508  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
509 
510  // Filter the view items based on the selection box
511  BOX2I selectionBox = area.ViewBBox();
512  view->Query( selectionBox, selectedItems ); // Get the list of selected items
513 
514  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR>::iterator it, it_end;
515 
516  int width = area.GetEnd().x - area.GetOrigin().x;
517  int height = area.GetEnd().y - area.GetOrigin().y;
518 
519  // Construct an EDA_RECT to determine BOARD_ITEM selection
520  EDA_RECT selectionRect( wxPoint( area.GetOrigin().x, area.GetOrigin().y ),
521  wxSize( width, height ) );
522 
523  selectionRect.Normalize();
524 
525  for( it = selectedItems.begin(), it_end = selectedItems.end(); it != it_end; ++it )
526  {
527  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( it->first );
528 
529  if( !item || !selectable( item ) )
530  continue;
531 
532  /* Selection mode depends on direction of drag-selection:
533  * Left > Right : Select objects that are fully enclosed by selection
534  * Right > Left : Select objects that are crossed by selection
535  */
536 
537  if( width >= 0 )
538  {
539  if( selectionBox.Contains( item->ViewBBox() ) )
540  {
541  if( m_subtractive )
542  unselect( item );
543  else
544  select( item );
545  }
546  }
547  else
548  {
549  if( item->HitTest( selectionRect, false ) )
550  {
551  if( m_subtractive )
552  unselect( item );
553  else
554  select( item );
555  }
556 
557  }
558  }
559 
560  if( m_selection.Size() == 1 )
561  m_frame->SetCurItem( static_cast<BOARD_ITEM*>( m_selection.Front() ) );
562  else
563  m_frame->SetCurItem( NULL );
564 
565  // Inform other potentially interested tools
566  if( !m_selection.Empty() )
568 
569  break; // Stop waiting for events
570  }
571  }
572 
573  // Stop drawing the selection box
574  view->Remove( &area );
575  m_multiple = false; // Multiple selection mode is inactive
576  getViewControls()->SetAutoPan( false );
577 
578  return cancelled;
579 }
580 
581 
583 {
589  Go( &SELECTION_TOOL::find, PCB_ACTIONS::find.MakeEvent() );
598 }
599 
600 
602 {
603  if( !m_locked || m_editModules )
604  return SELECTION_UNLOCKED;
605 
606  bool containsLocked = false;
607 
608  // Check if the selection contains locked items
609  for( const auto& item : m_selection )
610  {
611  switch( item->Type() )
612  {
613  case PCB_MODULE_T:
614  if( static_cast<MODULE*>( item )->IsLocked() )
615  containsLocked = true;
616  break;
617 
618  case PCB_MODULE_EDGE_T:
619  case PCB_MODULE_TEXT_T:
620  if( static_cast<MODULE*>( item->GetParent() )->IsLocked() )
621  containsLocked = true;
622  break;
623 
624  default: // suppress warnings
625  break;
626  }
627  }
628 
629  if( containsLocked )
630  {
631  if( IsOK( m_frame, _( "Selection contains locked items. Do you want to continue?" ) ) )
632  {
633  m_locked = false;
635  }
636  else
637  return SELECTION_LOCKED;
638  }
639 
640  m_locked = false;
641 
642  return SELECTION_UNLOCKED;
643 }
644 
645 
647 {
648  bool sanitize = (bool) aEvent.Parameter<intptr_t>();
649 
650  if( m_selection.Empty() ) // Try to find an item that could be modified
651  {
652  selectCursor( true );
653 
654  if( CheckLock() == SELECTION_LOCKED )
655  {
656  clearSelection();
657  return 0;
658  }
659  }
660 
661  if( sanitize )
663 
664  return 0;
665 }
666 
667 
669 {
670  clearSelection();
671 
672  return 0;
673 }
674 
676 {
677  // Check if there is an item to be selected
678  BOARD_ITEM* item = aEvent.Parameter<BOARD_ITEM*>();
679 
680  if( item )
681  {
682  select( item );
683 
684  // Inform other potentially interested tools
686  }
687 
688  return 0;
689 }
690 
691 
693 {
694  // Check if there is an item to be selected
695  BOARD_ITEM* item = aEvent.Parameter<BOARD_ITEM*>();
696 
697  if( item )
698  {
699  unselect( item );
700 
701  // Inform other potentially interested tools
703  }
704 
705  return 0;
706 }
707 
708 
710 {
711  if( !selectCursor() )
712  return 0;
713 
714  // copy the selection, since we're going to iterate and modify
715  auto selection = m_selection.GetItems();
716 
717  for( auto item : selection )
718  {
719  // only TRACK items can be checked for trivial connections
720  if( item->Type() == PCB_TRACE_T || item->Type() == PCB_VIA_T )
721  {
722  TRACK& trackItem = static_cast<TRACK&>( *item );
723  selectAllItemsConnectedToTrack( trackItem );
724  }
725  }
726 
727  // Inform other potentially interested tools
728  if( m_selection.Size() > 0 )
730 
731  return 0;
732 }
733 
734 
736 {
737  if( !selectCursor() )
738  return 0;
739 
740  // copy the selection, since we're going to iterate and modify
741  auto selection = m_selection.GetItems();
742 
743  for( auto i : selection )
744  {
745  auto item = static_cast<BOARD_ITEM*>( i );
746  // only connected items can be traversed in the ratsnest
747  if( item->IsConnected() )
748  {
749  auto& connItem = static_cast<BOARD_CONNECTED_ITEM&>( *item );
750 
751  selectAllItemsConnectedToItem( connItem );
752  }
753  }
754 
755  // Inform other potentially interested tools
756  if( m_selection.Size() > 0 )
758 
759  return 0;
760 }
761 
762 
764 {
765  int segmentCount;
766  TRACK* trackList = board()->MarkTrace( &aSourceTrack, &segmentCount,
767  nullptr, nullptr, true );
768 
769  for( int i = 0; i < segmentCount; ++i )
770  {
771  select( trackList );
772  trackList = trackList->Next();
773  }
774 }
775 
776 
778 {
779  RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest();
780  std::list<BOARD_CONNECTED_ITEM*> itemsList;
781  ratsnest->GetConnectedItems( &aSourceItem, itemsList, (RN_ITEM_TYPE)( RN_TRACKS | RN_VIAS ) );
782 
783  for( BOARD_CONNECTED_ITEM* i : itemsList )
784  select( i );
785 }
786 
787 
789 {
790  RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest();
791  std::list<BOARD_CONNECTED_ITEM*> itemsList;
792 
793  ratsnest->GetNetItems( aNetCode, itemsList, (RN_ITEM_TYPE)( RN_TRACKS | RN_VIAS ) );
794 
795  for( BOARD_CONNECTED_ITEM* i : itemsList )
796  select( i );
797 }
798 
799 
801 {
802  if( !selectCursor() )
803  return 0;
804 
805  // copy the selection, since we're going to iterate and modify
806  auto selection = m_selection.GetItems();
807 
808  for( auto i : selection )
809  {
810  auto item = static_cast<BOARD_ITEM*>( i );
811  // only connected items get a net code
812  if( item->IsConnected() )
813  {
814  auto& connItem = static_cast<BOARD_CONNECTED_ITEM&>( *item );
815 
816  selectAllItemsOnNet( connItem.GetNetCode() );
817  }
818  }
819 
820  // Inform other potentially interested tools
821  if( m_selection.Size() > 0 )
823 
824  return 0;
825 }
826 
827 
828 void SELECTION_TOOL::selectAllItemsOnSheet( wxString& aSheetpath )
829 {
830  auto modules = board()->m_Modules.GetFirst();
831  std::list<MODULE*> modList;
832 
833  // store all modules that are on that sheet
834  for( MODULE* mitem = modules; mitem; mitem = mitem->Next() )
835  {
836  if( mitem != NULL && mitem->GetPath().Contains( aSheetpath ) )
837  {
838  modList.push_back( mitem );
839  }
840  }
841 
842  //Generate a list of all pads, and of all nets they belong to.
843  std::list<int> netcodeList;
844  for( MODULE* mmod : modList )
845  {
846  for( D_PAD* pad = mmod->Pads().GetFirst(); pad; pad = pad->Next() )
847  {
848  if( pad->IsConnected() )
849  {
850  netcodeList.push_back( pad->GetNetCode() );
851  }
852  }
853  }
854 
855  // remove all duplicates
856  netcodeList.sort();
857  netcodeList.unique();
858 
859  // now we need to find all modules that are connected to each of these nets
860  // then we need to determine if these modules are in the list of modules
861  // belonging to this sheet ( modList )
862  RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest();
863  std::list<int> removeCodeList;
864  for( int netCode : netcodeList )
865  {
866  std::list<BOARD_CONNECTED_ITEM*> netPads;
867  ratsnest->GetNetItems( netCode, netPads, (RN_ITEM_TYPE)( RN_PADS ) );
868  for( BOARD_CONNECTED_ITEM* mitem : netPads )
869  {
870  bool found = ( std::find( modList.begin(), modList.end(), mitem->GetParent() ) != modList.end() );
871  if( !found )
872  {
873  // if we cannot find the module of the pad in the modList
874  // then we can assume that that module is not located in the same
875  // schematic, therefore invalidate this netcode.
876  removeCodeList.push_back( netCode );
877  break;
878  }
879  }
880  }
881 
882  // remove all duplicates
883  removeCodeList.sort();
884  removeCodeList.unique();
885 
886  for( int removeCode : removeCodeList )
887  {
888  netcodeList.remove( removeCode );
889  }
890 
891  std::list<BOARD_CONNECTED_ITEM*> localConnectionList;
892  for( int netCode : netcodeList )
893  {
894  ratsnest->GetNetItems( netCode, localConnectionList, (RN_ITEM_TYPE)( RN_TRACKS | RN_VIAS ) );
895  }
896 
897  for( BOARD_ITEM* i : modList )
898  {
899  if( i != NULL )
900  select( i );
901  }
902  for( BOARD_CONNECTED_ITEM* i : localConnectionList )
903  {
904  if( i != NULL )
905  select( i );
906  }
907 }
908 
910 {
911  //Should recalculate the view to zoom in on the selection
912  auto selectionBox = m_selection.ViewBBox();
913  auto canvas = m_frame->GetGalCanvas();
914  auto view = getView();
915 
916  VECTOR2D screenSize = view->ToWorld( canvas->GetClientSize(), false );
917 
918  if( !( selectionBox.GetWidth() == 0 ) || !( selectionBox.GetHeight() == 0 ) )
919  {
920  VECTOR2D vsize = selectionBox.GetSize();
921  double scale = view->GetScale() / std::max( fabs( vsize.x / screenSize.x ),
922  fabs( vsize.y / screenSize.y ) );
923  view->SetScale( scale );
924  view->SetCenter( selectionBox.Centre() );
925  view->Add( &m_selection );
926  }
927 
929 }
930 
931 
933 {
934  clearSelection();
935  wxString* sheetpath = aEvent.Parameter<wxString*>();
936 
937  selectAllItemsOnSheet( *sheetpath );
938 
940 
941  if( m_selection.Size() > 0 )
943 
944 
945  return 0;
946 }
947 
948 
950 {
951  if( !selectCursor( true ) )
952  return 0;
953 
954  // this function currently only supports modules since they are only
955  // on one sheet.
956  auto item = m_selection.Front();
957 
958  if( !item )
959  return 0;
960 
961  if( item->Type() != PCB_MODULE_T )
962  return 0;
963 
964  auto mod = dynamic_cast<MODULE*>( item );
965 
966  clearSelection();
967 
968  // get the lowest subsheet name for this.
969  wxString sheetPath = mod->GetPath();
970  sheetPath = sheetPath.BeforeLast( '/' );
971  sheetPath = sheetPath.AfterLast( '/' );
972 
973  selectAllItemsOnSheet( sheetPath );
974 
975  // Inform other potentially interested tools
976  if( m_selection.Size() > 0 )
978 
979  return 0;
980 }
981 
982 
984 {
985  clearSelection();
986 
987  if( aItem )
988  {
989  select( aItem );
990  EDA_RECT bbox = aItem->GetBoundingBox();
991  BOX2D viewport( VECTOR2D( bbox.GetOrigin() ), VECTOR2D( bbox.GetSize() ) );
992  getView()->SetViewport( viewport );
993 
994  // Inform other potentially interested tools
996  }
997 
999 }
1000 
1001 
1002 int SELECTION_TOOL::find( const TOOL_EVENT& aEvent )
1003 {
1004  DIALOG_FIND dlg( m_frame );
1005  dlg.EnableWarp( false );
1006  dlg.SetCallback( std::bind( &SELECTION_TOOL::findCallback, this, _1 ) );
1007  dlg.ShowModal();
1008 
1009  return 0;
1010 }
1011 
1012 
1014 {
1016 
1017  if( module )
1018  {
1019  clearSelection();
1020  toggleSelection( module );
1021 
1022  // Place event on module origin first, so the generic anchor snap
1023  // doesn't just choose the closest pin for us
1024  // Don't warp the view - we want the component to
1025  // "teleport" to cursor, not move to the components position
1026  getViewControls()->ForceCursorPosition( true, module->GetPosition() );
1027 
1028  // pick the component up and start moving
1029  m_toolMgr->InvokeTool( "pcbnew.InteractiveEdit" );
1030  }
1031 
1032  return 0;
1033 }
1034 
1035 
1044 static bool itemIsIncludedByFilter( const BOARD_ITEM& aItem,
1045  const BOARD& aBoard,
1046  const LSET& aTechnlLayerMask,
1047  const DIALOG_BLOCK_OPTIONS::OPTIONS& aBlockOpts )
1048 {
1049  bool include = true;
1050  const PCB_LAYER_ID layer = aItem.GetLayer();
1051 
1052  // can skip without even checking item type
1053  if( !aBlockOpts.includeItemsOnInvisibleLayers
1054  && !aBoard.IsLayerVisible( layer ) )
1055  {
1056  include = false;
1057  }
1058 
1059  // if the item needsto be checked agains the options
1060  if( include )
1061  {
1062  switch( aItem.Type() )
1063  {
1064  case PCB_MODULE_T:
1065  {
1066  const auto& module = static_cast<const MODULE&>( aItem );
1067 
1068  include = aBlockOpts.includeModules;
1069 
1070  if( include && !aBlockOpts.includeLockedModules )
1071  {
1072  include = !module.IsLocked();
1073  }
1074 
1075  break;
1076  }
1077  case PCB_TRACE_T:
1078  {
1079  include = aBlockOpts.includeTracks;
1080  break;
1081  }
1082  case PCB_ZONE_AREA_T:
1083  {
1084  include = aBlockOpts.includeZones;
1085  break;
1086  }
1087  case PCB_LINE_T:
1088  case PCB_TARGET_T:
1089  case PCB_DIMENSION_T:
1090  {
1091  include = aTechnlLayerMask[layer];
1092  break;
1093  }
1094  case PCB_TEXT_T:
1095  {
1096  include = aBlockOpts.includePcbTexts
1097  && aTechnlLayerMask[layer];
1098  break;
1099  }
1100  default:
1101  {
1102  // no filterering, just select it
1103  break;
1104  }
1105  }
1106  }
1107 
1108  return include;
1109 }
1110 
1111 
1117 {
1118  LSET layerMask( Edge_Cuts );
1119 
1120  if( blockOpts.includeItemsOnTechLayers )
1121  layerMask.set();
1122 
1123  if( !blockOpts.includeBoardOutlineLayer )
1124  layerMask.set( Edge_Cuts, false );
1125 
1126  return layerMask;
1127 }
1128 
1129 
1131 {
1132  auto& opts = m_priv->m_filterOpts;
1133  DIALOG_BLOCK_OPTIONS dlg( m_frame, opts, false, _( "Filter selection" ) );
1134 
1135  const int cmd = dlg.ShowModal();
1136 
1137  if( cmd != wxID_OK )
1138  return 0;
1139 
1140  const auto& board = *getModel<BOARD>();
1141  const auto layerMask = getFilteredLayerSet( opts );
1142 
1143  // copy current selection
1144  auto selection = m_selection.GetItems();
1145 
1146  // clear current selection
1147  clearSelection();
1148 
1149  // copy selection items from the saved selection
1150  // according to the dialog options
1151  for( auto i : selection )
1152  {
1153  auto item = static_cast<BOARD_ITEM*>( i );
1154  bool include = itemIsIncludedByFilter( *item, board, layerMask, opts );
1155 
1156  if( include )
1157  {
1158  select( item );
1159  }
1160  }
1161  return 0;
1162 }
1163 
1164 
1166 {
1167  if( m_selection.Empty() )
1168  return;
1169 
1170  for( auto item : m_selection )
1171  unselectVisually( static_cast<BOARD_ITEM*>( item ) );
1172 
1173  m_selection.Clear();
1174 
1175  m_frame->SetCurItem( NULL );
1176  m_locked = true;
1177 
1178  // Inform other potentially interested tools
1180 }
1181 
1182 
1184 {
1185  BOARD_ITEM* current = NULL;
1186  PCB_BRIGHT_BOX brightBox;
1187  CONTEXT_MENU menu;
1188 
1189  getView()->Add( &brightBox );
1190 
1191  int limit = std::min( 10, aCollector->GetCount() );
1192 
1193  for( int i = 0; i < limit; ++i )
1194  {
1195  wxString text;
1196  BOARD_ITEM* item = ( *aCollector )[i];
1197  text = item->GetSelectMenuText();
1198  menu.Add( text, i + 1 );
1199  }
1200 
1201  menu.SetTitle( _( "Clarify selection" ) );
1202  menu.DisplayTitle( true );
1203  SetContextMenu( &menu, CMENU_NOW );
1204 
1205  while( OPT_TOOL_EVENT evt = Wait() )
1206  {
1207  if( evt->Action() == TA_CONTEXT_MENU_UPDATE )
1208  {
1209  if( current )
1210  current->ClearBrightened();
1211 
1212  int id = *evt->GetCommandId();
1213 
1214  // User has pointed an item, so show it in a different way
1215  if( id > 0 && id <= limit )
1216  {
1217  current = ( *aCollector )[id - 1];
1218  current->SetBrightened();
1219  }
1220  else
1221  {
1222  current = NULL;
1223  }
1224  }
1225  else if( evt->Action() == TA_CONTEXT_MENU_CHOICE )
1226  {
1227  boost::optional<int> id = evt->GetCommandId();
1228 
1229  // User has selected an item, so this one will be returned
1230  if( id && ( *id > 0 ) )
1231  current = ( *aCollector )[*id - 1];
1232  else
1233  current = NULL;
1234 
1235  break;
1236  }
1237 
1238  // Draw a mark to show which item is available to be selected
1239  if( current && current->IsBrightened() )
1240  {
1241  brightBox.SetItem( current );
1242  getView()->SetVisible( &brightBox, true );
1243 // getView()->Hide( &brightBox, false );
1244  getView()->Update( &brightBox, KIGFX::GEOMETRY );
1246  }
1247  }
1248 
1249  getView()->Remove( &brightBox );
1250 
1251 
1252  return current;
1253 }
1254 
1255 
1257 {
1258  int count = aCollector->GetPrimaryCount(); // try to use preferred layer
1259 
1260  if( 0 == count )
1261  count = aCollector->GetCount();
1262 
1263  for( int i = 0; i < count; ++i )
1264  {
1265  if( ( *aCollector )[i]->Type() != PCB_MODULE_T )
1266  return NULL;
1267  }
1268 
1269  // All are modules, now find smallest MODULE
1270  int minDim = 0x7FFFFFFF;
1271  int minNdx = 0;
1272 
1273  for( int i = 0; i < count; ++i )
1274  {
1275  MODULE* module = (MODULE*) ( *aCollector )[i];
1276 
1277  int lx = module->GetBoundingBox().GetWidth();
1278  int ly = module->GetBoundingBox().GetHeight();
1279 
1280  int lmin = std::min( lx, ly );
1281 
1282  if( lmin < minDim )
1283  {
1284  minDim = lmin;
1285  minNdx = i;
1286  }
1287  }
1288 
1289  return (*aCollector)[minNdx];
1290 }
1291 
1292 
1293 bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const
1294 {
1295  // Is high contrast mode enabled?
1296  bool highContrast = getView()->GetPainter()->GetSettings()->GetHighContrast();
1297 
1298  if( highContrast )
1299  {
1300  bool onActive = false; // Is the item on any of active layers?
1301  int layers[KIGFX::VIEW::VIEW_MAX_LAYERS], layers_count;
1302 
1303  // Filter out items that do not belong to active layers
1304  const std::set<unsigned int>& activeLayers = getView()->GetPainter()->
1305  GetSettings()->GetActiveLayers();
1306  aItem->ViewGetLayers( layers, layers_count );
1307 
1308  for( int i = 0; i < layers_count; ++i )
1309  {
1310  if( activeLayers.count( layers[i] ) > 0 ) // Item is on at least one of the active layers
1311  {
1312  onActive = true;
1313  break;
1314  }
1315  }
1316 
1317  if( !onActive ) // We do not want to select items that are in the background
1318  return false;
1319  }
1320 
1321  switch( aItem->Type() )
1322  {
1323  case PCB_VIA_T:
1324  {
1325  // For vias it is enough if only one of layers is visible
1326  PCB_LAYER_ID top, bottom;
1327 
1328  static_cast<const VIA*>( aItem )->LayerPair( &top, &bottom );
1329 
1330  return board()->IsLayerVisible( top ) || board()->IsLayerVisible( bottom );
1331  }
1332  break;
1333 
1334  case PCB_MODULE_T:
1335 
1336  // In the module editor, we do not want to select the module itself
1337  // rather, the module sub-components should be selected individually
1338  if( m_editModules )
1339  {
1340  return false;
1341  }
1342 
1343  if( aItem->IsOnLayer( F_Cu ) && board()->IsElementVisible( LAYER_MOD_FR ) )
1344  return !m_editModules;
1345 
1346  if( aItem->IsOnLayer( B_Cu ) && board()->IsElementVisible( LAYER_MOD_BK ) )
1347  return !m_editModules;
1348 
1349  return false;
1350 
1351  break;
1352 
1353  case PCB_MODULE_TEXT_T:
1354  if( m_multiple && !m_editModules )
1355  return false;
1356 
1357  return view()->IsVisible( aItem ) && board()->IsLayerVisible( aItem->GetLayer() );
1358 
1359  case PCB_MODULE_EDGE_T:
1360  case PCB_PAD_T:
1361  {
1362  // Multiple selection is only allowed in modedit mode
1363  // In pcbnew, you have to select subparts of modules
1364  // one-by-one, rather than with a drag selection.
1365  // This is so you can pick up items under an (unlocked)
1366  // module without also moving the module's sub-parts.
1367  if( m_multiple && !m_editModules )
1368  return false;
1369 
1370  // When editing modules, it's allowed to select them, even when
1371  // locked, since you already have to explicitly activate the
1372  // module editor to get to this stage
1373  if ( !m_editModules )
1374  {
1375  MODULE* mod = static_cast<const D_PAD*>( aItem )->GetParent();
1376  if( mod && mod->IsLocked() )
1377  return false;
1378  }
1379 
1380  break;
1381  }
1382 
1383  // These are not selectable
1384  case NOT_USED:
1385  case TYPE_NOT_INIT:
1386  return false;
1387 
1388  default: // Suppress warnings
1389  break;
1390  }
1391 
1392  // All other items are selected only if the layer on which they exist is visible
1393  return board()->IsLayerVisible( aItem->GetLayer() );
1394 }
1395 
1397 {
1398  if( aItem->IsSelected() )
1399  {
1400  return;
1401  }
1402 
1403  if( aItem->Type() == PCB_PAD_T )
1404  {
1405  MODULE* module = static_cast<MODULE*>( aItem->GetParent() );
1406 
1407  if( m_selection.Contains( module ) )
1408  return;
1409  }
1410 
1411  m_selection.Add( aItem );
1412  selectVisually( aItem );
1413 
1414 
1415  if( m_selection.Size() == 1 )
1416  {
1417  // Set as the current item, so the information about selection is displayed
1418  m_frame->SetCurItem( aItem, true );
1419  }
1420  else if( m_selection.Size() == 2 ) // Check only for 2, so it will not be
1421  { // called for every next selected item
1422  // If multiple items are selected, do not show the information about the selected item
1423  m_frame->SetCurItem( NULL, true );
1424  }
1425 }
1426 
1427 
1429 {
1430  if( !aItem->IsSelected() )
1431  return;
1432 
1433  m_selection.Remove( aItem );
1434  unselectVisually( aItem );
1435 
1436  if( m_selection.Empty() )
1437  {
1438  m_frame->SetCurItem( NULL );
1439  m_locked = true;
1440  }
1441 }
1442 
1443 
1445 {
1446  // Hide the original item, so it is shown only on overlay
1447  aItem->SetSelected();
1448  view()->Hide( aItem, true );
1449  view()->Update( aItem, KIGFX::GEOMETRY );
1450 
1451  // Modules are treated in a special way - when they are selected, we have to
1452  // unselect all the parts that make the module, not the module itself
1453 
1454  if( aItem->Type() == PCB_MODULE_T )
1455  {
1456  static_cast<MODULE*>( aItem )->RunOnChildren( [&] ( BOARD_ITEM* item )
1457  {
1458  item->SetSelected();
1459  view()->Hide( item, true );
1460  view()->Update( item, KIGFX::GEOMETRY );
1461  } );
1462  }
1463 
1464  view()->Update( &m_selection );
1465 }
1466 
1467 
1469 {
1470  // Restore original item visibility
1471  aItem->ClearSelected();
1472  view()->Hide( aItem, false );
1473  view()->Update( aItem, KIGFX::ALL );
1474 
1475  // Modules are treated in a special way - when they are selected, we have to
1476  // unselect all the parts that make the module, not the module itself
1477 
1478  if( aItem->Type() == PCB_MODULE_T )
1479  {
1480  static_cast<MODULE*>( aItem )->RunOnChildren( [&] ( BOARD_ITEM* item )
1481  {
1482  item->ClearSelected();
1483  view()->Hide( item, false );
1484  view()->Update( item, KIGFX::ALL );
1485  });
1486  }
1487 
1488  view()->Update( &m_selection );
1489 }
1490 
1491 
1492 bool SELECTION_TOOL::selectionContains( const VECTOR2I& aPoint ) const
1493 {
1494  const unsigned GRIP_MARGIN = 20;
1495  VECTOR2D margin = getView()->ToWorld( VECTOR2D( GRIP_MARGIN, GRIP_MARGIN ), false );
1496 
1497  // Check if the point is located within any of the currently selected items bounding boxes
1498  for( auto item : m_selection )
1499  {
1500  BOX2I itemBox = item->ViewBBox();
1501  itemBox.Inflate( margin.x, margin.y ); // Give some margin for gripping an item
1502 
1503  if( itemBox.Contains( aPoint ) )
1504  return true;
1505  }
1506 
1507  return false;
1508 }
1509 
1510 
1511 static EDA_RECT getRect( const BOARD_ITEM* aItem )
1512 {
1513  if( aItem->Type() == PCB_MODULE_T )
1514  return static_cast<const MODULE*>( aItem )->GetFootprintRect();
1515 
1516  return aItem->GetBoundingBox();
1517 }
1518 
1519 
1520 static double calcArea( const BOARD_ITEM* aItem )
1521 {
1522  if( aItem->Type() == PCB_TRACE_T )
1523  {
1524  const TRACK* t = static_cast<const TRACK*>( aItem );
1525  return ( t->GetWidth() + t->GetLength() ) * t->GetWidth();
1526  }
1527 
1528  return getRect( aItem ).GetArea();
1529 }
1530 
1531 
1532 static double calcMinArea( GENERAL_COLLECTOR& aCollector, KICAD_T aType )
1533 {
1534  double best = std::numeric_limits<double>::max();
1535 
1536  if( !aCollector.GetCount() )
1537  return 0.0;
1538 
1539  for( int i = 0; i < aCollector.GetCount(); i++ )
1540  {
1541  BOARD_ITEM* item = aCollector[i];
1542  if( item->Type() == aType )
1543  best = std::min( best, calcArea( item ) );
1544  }
1545 
1546  return best;
1547 }
1548 
1549 
1550 static double calcMaxArea( GENERAL_COLLECTOR& aCollector, KICAD_T aType )
1551 {
1552  double best = 0.0;
1553 
1554  for( int i = 0; i < aCollector.GetCount(); i++ )
1555  {
1556  BOARD_ITEM* item = aCollector[i];
1557  if( item->Type() == aType )
1558  best = std::max( best, calcArea( item ) );
1559  }
1560 
1561  return best;
1562 }
1563 
1564 
1565 static inline double calcCommonArea( const BOARD_ITEM* aItem, const BOARD_ITEM* aOther )
1566 {
1567  if( !aItem || !aOther )
1568  return 0;
1569 
1570  return getRect( aItem ).Common( getRect( aOther ) ).GetArea();
1571 }
1572 
1573 
1574 double calcRatio( double a, double b )
1575 {
1576  if( a == 0.0 && b == 0.0 )
1577  return 1.0;
1578 
1579  if( b == 0.0 )
1581 
1582  return a / b;
1583 }
1584 
1585 
1586 // todo: explain the selection heuristics
1588 {
1589  std::set<BOARD_ITEM*> rejected;
1590 
1591  const double footprintAreaRatio = 0.2;
1592  const double modulePadMinCoverRatio = 0.45;
1593  const double padViaAreaRatio = 0.5;
1594  const double trackViaLengthRatio = 2.0;
1595  const double trackTrackLengthRatio = 0.3;
1596  const double textToFeatureMinRatio = 0.2;
1597  const double textToFootprintMinRatio = 0.4;
1598  // If the common area of two compared items is above the following threshold, they cannot
1599  // be rejected (it means they overlap and it might be hard to pick one by selecting
1600  // its unique area).
1601  const double commonAreaRatio = 0.6;
1602 
1603  PCB_LAYER_ID actLayer = m_frame->GetActiveLayer();
1604 
1605  LSET silkLayers( 2, B_SilkS, F_SilkS );
1606 
1607  if( silkLayers[actLayer] )
1608  {
1609  std::set<BOARD_ITEM*> preferred;
1610 
1611  for( int i = 0; i < aCollector.GetCount(); ++i )
1612  {
1613  BOARD_ITEM* item = aCollector[i];
1614  KICAD_T type = item->Type();
1615 
1616  if( ( type == PCB_MODULE_TEXT_T || type == PCB_TEXT_T || type == PCB_LINE_T )
1617  && silkLayers[item->GetLayer()] )
1618  {
1619  preferred.insert( item );
1620  }
1621  }
1622 
1623  if( preferred.size() != 0 )
1624  {
1625  aCollector.Empty();
1626 
1627  for( BOARD_ITEM* item : preferred )
1628  aCollector.Append( item );
1629  return;
1630  }
1631  }
1632 
1633  if( aCollector.CountType( PCB_MODULE_TEXT_T ) > 0 )
1634  {
1635  for( int i = 0; i < aCollector.GetCount(); ++i )
1636  {
1637  if( TEXTE_MODULE* txt = dyn_cast<TEXTE_MODULE*>( aCollector[i] ) )
1638  {
1639  double textArea = calcArea( txt );
1640 
1641  for( int j = 0; j < aCollector.GetCount(); ++j )
1642  {
1643  if( i == j )
1644  continue;
1645 
1646  BOARD_ITEM* item = aCollector[j];
1647  double itemArea = calcArea( item );
1648  double areaRatio = calcRatio( textArea, itemArea );
1649  double commonArea = calcCommonArea( txt, item );
1650  double itemCommonRatio = calcRatio( commonArea, itemArea );
1651  double txtCommonRatio = calcRatio( commonArea, textArea );
1652 
1653  if( item->Type() == PCB_MODULE_T && areaRatio < textToFootprintMinRatio &&
1654  itemCommonRatio < commonAreaRatio )
1655  rejected.insert( item );
1656 
1657  switch( item->Type() )
1658  {
1659  case PCB_TRACE_T:
1660  case PCB_PAD_T:
1661  case PCB_LINE_T:
1662  case PCB_VIA_T:
1663  case PCB_MODULE_T:
1664  if( areaRatio > textToFeatureMinRatio && txtCommonRatio < commonAreaRatio )
1665  rejected.insert( txt );
1666  break;
1667  default:
1668  break;
1669  }
1670  }
1671  }
1672  }
1673  }
1674 
1675  if( aCollector.CountType( PCB_MODULE_T ) > 0 )
1676  {
1677  double minArea = calcMinArea( aCollector, PCB_MODULE_T );
1678  double maxArea = calcMaxArea( aCollector, PCB_MODULE_T );
1679 
1680  if( calcRatio( minArea, maxArea ) <= footprintAreaRatio )
1681  {
1682  for( int i = 0; i < aCollector.GetCount(); ++i )
1683  {
1684  if( MODULE* mod = dyn_cast<MODULE*>( aCollector[i] ) )
1685  {
1686  double normalizedArea = calcRatio( calcArea( mod ), maxArea );
1687 
1688  if( normalizedArea > footprintAreaRatio )
1689  rejected.insert( mod );
1690  }
1691  }
1692  }
1693  }
1694 
1695  if( aCollector.CountType( PCB_PAD_T ) > 0 )
1696  {
1697  for( int i = 0; i < aCollector.GetCount(); ++i )
1698  {
1699  if( D_PAD* pad = dyn_cast<D_PAD*>( aCollector[i] ) )
1700  {
1701  double ratio = pad->GetParent()->PadCoverageRatio();
1702 
1703  if( ratio < modulePadMinCoverRatio )
1704  rejected.insert( pad->GetParent() );
1705  }
1706  }
1707  }
1708 
1709  if( aCollector.CountType( PCB_VIA_T ) > 0 )
1710  {
1711  for( int i = 0; i < aCollector.GetCount(); ++i )
1712  {
1713  if( VIA* via = dyn_cast<VIA*>( aCollector[i] ) )
1714  {
1715  double viaArea = calcArea( via );
1716 
1717  for( int j = 0; j < aCollector.GetCount(); ++j )
1718  {
1719  if( i == j )
1720  continue;
1721 
1722  BOARD_ITEM* item = aCollector[j];
1723  double areaRatio = calcRatio( viaArea, calcArea( item ) );
1724 
1725  if( item->Type() == PCB_MODULE_T && areaRatio < modulePadMinCoverRatio )
1726  rejected.insert( item );
1727 
1728  if( item->Type() == PCB_PAD_T && areaRatio < padViaAreaRatio )
1729  rejected.insert( item );
1730 
1731  if( TRACK* track = dyn_cast<TRACK*>( item ) )
1732  {
1733  if( track->GetNetCode() != via->GetNetCode() )
1734  continue;
1735 
1736  double lenRatio = (double) ( track->GetLength() + track->GetWidth() ) /
1737  (double) via->GetWidth();
1738 
1739  if( lenRatio > trackViaLengthRatio )
1740  rejected.insert( track );
1741  }
1742  }
1743  }
1744  }
1745  }
1746 
1747  int nTracks = aCollector.CountType( PCB_TRACE_T );
1748 
1749  if( nTracks > 0 )
1750  {
1751  double maxLength = 0.0;
1752  double minLength = std::numeric_limits<double>::max();
1753  double maxArea = 0.0;
1754  const TRACK* maxTrack = nullptr;
1755 
1756  for( int i = 0; i < aCollector.GetCount(); ++i )
1757  {
1758  if( TRACK* track = dyn_cast<TRACK*>( aCollector[i] ) )
1759  {
1760  maxLength = std::max( track->GetLength(), maxLength );
1761  maxLength = std::max( (double) track->GetWidth(), maxLength );
1762 
1763  minLength = std::min( std::max( track->GetLength(), (double) track->GetWidth() ), minLength );
1764 
1765  double area = track->GetLength() * track->GetWidth();
1766 
1767  if( area > maxArea )
1768  {
1769  maxArea = area;
1770  maxTrack = track;
1771  }
1772  }
1773  }
1774 
1775  if( maxLength > 0.0 && minLength / maxLength < trackTrackLengthRatio && nTracks > 1 )
1776  {
1777  for( int i = 0; i < aCollector.GetCount(); ++i )
1778  {
1779  if( TRACK* track = dyn_cast<TRACK*>( aCollector[i] ) )
1780  {
1781  double ratio = std::max( (double) track->GetWidth(), track->GetLength() ) / maxLength;
1782 
1783  if( ratio > trackTrackLengthRatio )
1784  rejected.insert( track );
1785  }
1786  }
1787  }
1788 
1789  for( int j = 0; j < aCollector.GetCount(); ++j )
1790  {
1791  if( MODULE* mod = dyn_cast<MODULE*>( aCollector[j] ) )
1792  {
1793  double ratio = calcRatio( maxArea, mod->GetFootprintRect().GetArea() );
1794 
1795  if( ratio < modulePadMinCoverRatio && calcCommonArea( maxTrack, mod ) < commonAreaRatio )
1796  rejected.insert( mod );
1797  }
1798  }
1799  }
1800 
1801  if( (unsigned) aCollector.GetCount() > rejected.size() ) // do not remove everything
1802  {
1803  for( BOARD_ITEM* item : rejected )
1804  {
1805  aCollector.Remove( item );
1806  }
1807  }
1808 }
1809 
1810 
1812 {
1813  getView()->Update( &m_selection );
1814 
1815  return 0;
1816 }
1817 
1818 
1820 {
1821  std::set<BOARD_ITEM*> rejected;
1822  std::set<BOARD_ITEM*> added;
1823 
1824  if( !m_editModules )
1825  {
1826  for( auto i : m_selection )
1827  {
1828  auto item = static_cast<BOARD_ITEM*>( i );
1829  if( item->Type() == PCB_PAD_T )
1830  {
1831  MODULE* mod = static_cast<MODULE*>( item->GetParent() );
1832 
1833  // case 1: module (or its pads) are locked
1834  if( mod && ( mod->PadsLocked() || mod->IsLocked() ) )
1835  {
1836  rejected.insert( item );
1837 
1838  if( !mod->IsLocked() && !mod->IsSelected() )
1839  added.insert( mod );
1840  }
1841 
1842  // case 2: multi-item selection contains both the module and its pads - remove the pads
1843  if( mod && m_selection.Contains( mod ) )
1844  rejected.insert( item );
1845  }
1846  }
1847  }
1848 
1849  if( !rejected.empty() )
1850  {
1851  for( BOARD_ITEM* item : rejected )
1852  unselect( item );
1853 
1854  // Inform other potentially interested tools
1856  }
1857 
1858  if( !added.empty() )
1859  {
1860  for( BOARD_ITEM* item : added )
1861  select( item );
1862 
1863  // Inform other potentially interested tools
1865  }
1866 
1867  return true;
1868 }
1869 
1870 
1871 // TODO(JE) Only works for BOARD_ITEM
1873 {
1874  return static_cast<VECTOR2I>( GetBoundingBox().GetPosition() );
1875 }
1876 
1877 
1879 {
1880  return static_cast<VECTOR2I>( GetBoundingBox().Centre() );
1881 }
1882 
1883 
1885 {
1886  EDA_RECT bbox;
1887 
1888  bbox = Front()->GetBoundingBox();
1889  auto i = m_items.begin();
1890  ++i;
1891 
1892  for( ; i != m_items.end(); ++i )
1893  {
1894  bbox.Merge( (*i)->GetBoundingBox() );
1895  }
1896 
1897  return bbox;
1898 }
1899 
1900 
1901 EDA_ITEM* SELECTION::GetTopLeftItem( bool onlyModules ) const
1902 {
1903  BOARD_ITEM* topLeftItem = nullptr;
1904  BOARD_ITEM* currentItem;
1905 
1906  wxPoint pnt;
1907 
1908  // find the leftmost (smallest x coord) and highest (smallest y with the smallest x) item in the selection
1909  for( auto item : m_items )
1910  {
1911  currentItem = static_cast<BOARD_ITEM*>( item );
1912  pnt = currentItem->GetPosition();
1913 
1914  if( ( currentItem->Type() != PCB_MODULE_T ) && onlyModules )
1915  {
1916  continue;
1917  }
1918  else
1919  {
1920  if( topLeftItem == nullptr )
1921  {
1922  topLeftItem = currentItem;
1923  }
1924  else if( ( pnt.x < topLeftItem->GetPosition().x ) ||
1925  ( ( topLeftItem->GetPosition().x == pnt.x ) &&
1926  ( pnt.y < topLeftItem->GetPosition().y ) ) )
1927  {
1928  topLeftItem = currentItem;
1929  }
1930  }
1931  }
1932 
1933  return static_cast<EDA_ITEM*>( topLeftItem );
1934 }
1935 
1936 
1938 {
1939  return GetTopLeftItem( true );
1940 }
1941 
1942 
1944 {
1945  EDA_RECT eda_bbox;
1946 
1947  if( Size() == 1 )
1948  {
1949  eda_bbox = Front()->GetBoundingBox();
1950  }
1951  else if( Size() > 1 )
1952  {
1953  eda_bbox = Front()->GetBoundingBox();
1954  auto i = m_items.begin();
1955  ++i;
1956 
1957  for( ; i != m_items.end(); ++i )
1958  {
1959  eda_bbox.Merge( (*i)->GetBoundingBox() );
1960  }
1961  }
1962 
1963  return BOX2I( eda_bbox.GetOrigin(), eda_bbox.GetSize() );
1964 }
1965 
1966 
1968 {
1969  std::vector<VIEW_ITEM*> items;
1970 
1971  for( auto item : m_items )
1972  {
1973  items.push_back( item );
1974 
1975  if( item->Type() == PCB_MODULE_T )
1976  {
1977  MODULE* module = static_cast<MODULE*>( item );
1978  module->RunOnChildren( [&] ( BOARD_ITEM* bitem ) { items.push_back( bitem ); } );
1979  }
1980  }
1981 
1982  return items;
1983 }
1984 
1985 
1986 const TOOL_EVENT SELECTION_TOOL::SelectedEvent( TC_MESSAGE, TA_ACTION, "pcbnew.InteractiveSelection.selected" );
1987 const TOOL_EVENT SELECTION_TOOL::UnselectedEvent( TC_MESSAGE, TA_ACTION, "pcbnew.InteractiveSelection.unselected" );
1988 const TOOL_EVENT SELECTION_TOOL::ClearedEvent( TC_MESSAGE, TA_ACTION, "pcbnew.InteractiveSelection.cleared" );
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)
Function Hide() Temporarily hides the item in the view (e.g.
Definition: view.cpp:1352
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:108
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:160
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
Class RN_DATA.
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:143
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:59
Class that computes missing connections on a PCB.
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:68
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
int find(const TOOL_EVENT &aEvent)
Find an item.
MODULE * Next() const
Definition: class_module.h:99
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:96
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
void SetCurItem(BOARD_ITEM *aItem, bool aDisplayInfo=true)
Function SetCurItem sets the currently selected item and displays it in the MsgPanel.
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:62
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.
Layers have changed.
Definition: view_item.h:59
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...
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:99
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:259
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:351
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:575
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:640
void GetNetItems(int aNetCode, std::list< BOARD_CONNECTED_ITEM * > &aOutput, RN_ITEM_TYPE aTypes=RN_ALL) const
Function GetNetItems() Adds all items that belong to a certain net to a list.
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
D_PAD * Next() const
Definition: class_pad.h:106
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.
RN_ITEM_TYPE
Types of items that are handled by the class
Definition: ratsnest_data.h:53
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:65
All active tools
Definition: tool_event.h:138
Class PCB_TOOL.
Definition: pcb_tool.h:45
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
void Update(VIEW_ITEM *aItem)
Function Update() For dynamic VIEWs, informs the associated VIEW that the graphical representation of...
Definition: view.cpp:1379
bool IsLocked() const override
Function IsLocked.
Definition: class_module.h:223
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:112
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:77
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:342
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 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:71
#define max(a, b)
Definition: auxiliary.h:86
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:166
std::set< EDA_ITEM * > m_items
Set of selected items.
Definition: selection.h:175
DLIST< MODULE > m_Modules
Definition: class_board.h:243
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)
Function SetVisible() Sets the item visibility.
Definition: view.cpp:1331
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:803
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:60
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:354
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
void GetConnectedItems(const BOARD_CONNECTED_ITEM *aItem, std::list< BOARD_CONNECTED_ITEM * > &aOutput, RN_ITEM_TYPE aTypes=RN_ALL) const
Function GetConnectedItems() Adds items that are connected together to a list.
Class GENERAL_COLLECTORS_GUIDE is a general implementation of a COLLECTORS_GUIDE. ...
Definition: collectors.h:378
bool IsVisible(const VIEW_ITEM *aItem) const
Function IsVisible() Returns information if the item is visible (or not).
Definition: view.cpp:1371
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
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:139
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:111
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.
#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:74
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:440
BOARD * board() const
Definition: pcb_tool.h:110
static double calcMinArea(GENERAL_COLLECTOR &aCollector, KICAD_T aType)
virtual void Remove(EDA_ITEM *aItem)
Definition: selection.h:76