KiCad PCB EDA Suite
ee_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) 2019 CERN
5  * Copyright (C) 2019-2020 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 
26 #include <class_libentry.h>
27 #include <core/typeinfo.h>
28 #include <ee_actions.h>
29 #include <ee_collectors.h>
30 #include <ee_selection_tool.h>
31 #include <eeschema_id.h> // For MAX_SELECT_ITEM_IDS
32 #include <lib_edit_frame.h>
33 #include <lib_item.h>
34 #include <lib_view_frame.h>
35 #include <math/util.h>
36 #include <menus_helpers.h>
37 #include <painter.h>
39 #include <sch_base_frame.h>
40 #include <sch_component.h>
41 #include <sch_edit_frame.h>
42 #include <sch_field.h>
43 #include <sch_item.h>
44 #include <sch_line.h>
45 #include <sch_sheet.h>
46 #include <schematic.h>
47 #include <tool/tool_event.h>
48 #include <tool/tool_manager.h>
50 #include <view/view.h>
51 #include <view/view_controls.h>
52 #include <view/view_group.h>
53 
54 
56 {
57  if( aSel.GetSize() == 1 )
58  {
59  SCH_COMPONENT* comp = dynamic_cast<SCH_COMPONENT*>( aSel.Front() );
60 
61  if( comp )
62  return !comp->GetPartRef() || !comp->GetPartRef()->IsPower();
63  }
64 
65  return false;
66 };
67 
68 
70 {
71  if( aSel.GetSize() == 1 )
72  {
73  SCH_COMPONENT* comp = dynamic_cast<SCH_COMPONENT*>( aSel.Front() );
74 
75  if( comp )
76  return comp->GetPartRef() && comp->GetPartRef()->HasConversion();
77  }
78 
79  return false;
80 };
81 
82 
84 {
85  if( aSel.GetSize() == 1 )
86  {
87  SCH_COMPONENT* comp = dynamic_cast<SCH_COMPONENT*>( aSel.Front() );
88 
89  if( comp )
90  return comp->GetPartRef() && comp->GetPartRef()->GetUnitCount() >= 2;
91  }
92 
93  return false;
94 };
95 
96 
97 #define HITTEST_THRESHOLD_PIXELS 5
98 
99 
101  TOOL_INTERACTIVE( "eeschema.InteractiveSelection" ),
102  m_frame( nullptr ),
103  m_additive( false ),
104  m_subtractive( false ),
105  m_exclusive_or( false ),
106  m_multiple( false ),
107  m_skip_heuristics( false ),
108  m_isLibEdit( false ),
109  m_isLibView( false ),
110  m_unit( 0 ),
111  m_convert( 0 )
112 {
113  m_selection.Clear();
114 }
115 
116 
118 {
119  getView()->Remove( &m_selection );
120 }
121 
123 
125 {
126  m_frame = getEditFrame<SCH_BASE_FRAME>();
127 
128  LIB_VIEW_FRAME* libViewFrame = dynamic_cast<LIB_VIEW_FRAME*>( m_frame );
129  LIB_EDIT_FRAME* libEditFrame = dynamic_cast<LIB_EDIT_FRAME*>( m_frame );
130 
131  if( libEditFrame )
132  {
133  m_isLibEdit = true;
134  m_unit = libEditFrame->GetUnit();
135  m_convert = libEditFrame->GetConvert();
136  }
137  else
138  m_isLibView = libViewFrame != nullptr;
139 
140 
141  static KICAD_T wireOrBusTypes[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT };
142  static KICAD_T connectedTypes[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T,
145 
146  auto wireSelection = E_C::MoreThan( 0 ) && E_C::OnlyType( SCH_LINE_LOCATE_WIRE_T );
147  auto busSelection = E_C::MoreThan( 0 ) && E_C::OnlyType( SCH_LINE_LOCATE_BUS_T );
148  auto wireOrBusSelection = E_C::MoreThan( 0 ) && E_C::OnlyTypes( wireOrBusTypes );
149  auto connectedSelection = E_C::MoreThan( 0 ) && E_C::OnlyTypes( connectedTypes );
150  auto sheetSelection = E_C::Count( 1 ) && E_C::OnlyType( SCH_SHEET_T );
151 
152  auto schEditCondition =
153  [this] ( const SELECTION& aSel )
154  {
155 
156  return !m_isLibEdit && !m_isLibView;
157  };
158 
159  auto belowRootSheetCondition =
160  [&]( const SELECTION& aSel )
161  {
162  SCH_EDIT_FRAME* schEditFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
163 
164  return ( schEditFrame&&
165  schEditFrame->GetCurrentSheet().Last() !=
166  &schEditFrame->Schematic().Root() );
167  };
168 
169  auto havePartCondition =
170  [&]( const SELECTION& sel )
171  {
172  return m_isLibEdit && static_cast<LIB_EDIT_FRAME*>( m_frame )->GetCurPart();
173  };
174 
175  auto& menu = m_menu.GetMenu();
176 
177  menu.AddItem( EE_ACTIONS::enterSheet, sheetSelection && EE_CONDITIONS::Idle, 1 );
178  menu.AddItem( EE_ACTIONS::explicitCrossProbe, sheetSelection && EE_CONDITIONS::Idle, 1 );
179  menu.AddItem( EE_ACTIONS::leaveSheet, belowRootSheetCondition, 1 );
180 
181  menu.AddSeparator( 100 );
182  menu.AddItem( EE_ACTIONS::drawWire, schEditCondition && EE_CONDITIONS::Empty, 100 );
183  menu.AddItem( EE_ACTIONS::drawBus, schEditCondition && EE_CONDITIONS::Empty, 100 );
184 
185  menu.AddSeparator( 100 );
187 
188  menu.AddSeparator( 100 );
190 
191  menu.AddSeparator( 200 );
192  menu.AddItem( EE_ACTIONS::selectConnection, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
193  menu.AddItem( EE_ACTIONS::placeJunction, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
194  menu.AddItem( EE_ACTIONS::placeLabel, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
195  menu.AddItem( EE_ACTIONS::placeGlobalLabel, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
196  menu.AddItem( EE_ACTIONS::placeHierLabel, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
197  menu.AddItem( EE_ACTIONS::breakWire, wireSelection && EE_CONDITIONS::Idle, 250 );
198  menu.AddItem( EE_ACTIONS::breakBus, busSelection && EE_CONDITIONS::Idle, 250 );
199  menu.AddItem( EE_ACTIONS::importSheetPin, sheetSelection && EE_CONDITIONS::Idle, 250 );
200  menu.AddItem( EE_ACTIONS::assignNetclass, connectedSelection && EE_CONDITIONS::Idle, 250 );
201 
202  menu.AddSeparator( 400 );
203  menu.AddItem( EE_ACTIONS::symbolProperties, havePartCondition && EE_CONDITIONS::Empty, 400 );
204  menu.AddItem( EE_ACTIONS::pinTable, havePartCondition && EE_CONDITIONS::Empty, 400 );
205 
206  menu.AddSeparator( 1000 );
208 
209  return true;
210 }
211 
212 
214 {
215  m_frame = getEditFrame<SCH_BASE_FRAME>();
216 
217  if( aReason == TOOL_BASE::MODEL_RELOAD )
218  {
219  // Remove pointers to the selected items from containers without changing their
220  // properties (as they are already deleted while a new sheet is loaded)
221  m_selection.Clear();
222  getView()->GetPainter()->GetSettings()->SetHighlight( false );
223 
224  LIB_EDIT_FRAME* libEditFrame = dynamic_cast<LIB_EDIT_FRAME*>( m_frame );
225  LIB_VIEW_FRAME* libViewFrame = dynamic_cast<LIB_VIEW_FRAME*>( m_frame );
226 
227  if( libEditFrame )
228  {
229  m_isLibEdit = true;
230  m_unit = libEditFrame->GetUnit();
231  m_convert = libEditFrame->GetConvert();
232  }
233  else
234  m_isLibView = libViewFrame != nullptr;
235  }
236  else
237  // Restore previous properties of selected items and remove them from containers
238  ClearSelection();
239 
240  // Reinsert the VIEW_GROUP, in case it was removed from the VIEW
241  getView()->Remove( &m_selection );
242  getView()->Add( &m_selection );
243 }
244 
245 
247 {
248  ACTION_MENU* actionMenu = aEvent.Parameter<ACTION_MENU*>();
249  CONDITIONAL_MENU* conditionalMenu = dynamic_cast<CONDITIONAL_MENU*>( actionMenu );
250 
251  if( conditionalMenu )
252  conditionalMenu->Evaluate( m_selection );
253 
254  if( actionMenu )
255  actionMenu->UpdateAll();
256 
257  return 0;
258 }
259 
260 
262 {
263  SCH_MARKER_T,
268  SCH_LINE_T,
269  SCH_BITMAP_T,
270  SCH_TEXT_T,
271  SCH_LABEL_T,
274  SCH_FIELD_T,
277  SCH_SHEET_T,
278  EOT
279 };
280 
281 
283 {
284  LIB_ARC_T,
285  LIB_CIRCLE_T,
286  LIB_TEXT_T,
289  LIB_BEZIER_T,
290  LIB_PIN_T,
291  LIB_FIELD_T,
292  EOT
293 };
294 
295 
297 {
298 
299  // Main loop: keep receiving events
300  while( TOOL_EVENT* evt = Wait() )
301  {
302  if( m_frame->ToolStackIsEmpty() )
303  m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
304 
306 
307  if( evt->Modifier( MD_SHIFT ) && evt->Modifier( MD_CTRL ) )
308  m_subtractive = true;
309  else if( evt->Modifier( MD_SHIFT ) )
310  m_additive = true;
311  else if( evt->Modifier( MD_CTRL ) )
312  m_exclusive_or = true;
313 
314  // Is the user requesting that the selection list include all possible
315  // items without removing less likely selection candidates
316  m_skip_heuristics = !!evt->Modifier( MD_ALT );
317 
318  // Single click? Select single object
319  if( evt->IsClick( BUT_LEFT ) )
320  {
321  if( auto schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
322  schframe->FocusOnItem( nullptr );
323 
324  SelectPoint( evt->Position(), EE_COLLECTOR::AllItems, nullptr, nullptr, false,
326  }
327 
328  // right click? if there is any object - show the context menu
329  else if( evt->IsClick( BUT_RIGHT ) )
330  {
331  bool selectionCancelled = false;
332 
333  if( m_selection.Empty() ||
334  !m_selection.GetBoundingBox().Contains( wxPoint( evt->Position() ) ) )
335  {
336  ClearSelection();
337  SelectPoint( evt->Position(), EE_COLLECTOR::AllItems, nullptr,
338  &selectionCancelled );
339  m_selection.SetIsHover( true );
340  }
341 
342  if( !selectionCancelled )
344  }
345 
346  // double click? Display the properties window
347  else if( evt->IsDblClick( BUT_LEFT ) )
348  {
349  if( auto schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
350  schframe->FocusOnItem( nullptr );
351 
352  if( m_selection.Empty() )
353  SelectPoint( evt->Position());
354 
355  EDA_ITEM* item = m_selection.Front();
356 
357  if( item && item->Type() == SCH_SHEET_T )
359  else
361  }
362 
363  // drag with LMB? Select multiple objects (or at least draw a selection box) or drag them
364  else if( evt->IsDrag( BUT_LEFT ) )
365  {
366  if( auto schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
367  schframe->FocusOnItem( nullptr );
368 
370  {
371  selectMultiple();
372  }
373  else
374  {
375  // selection is empty? try to start dragging the item under the point where drag
376  // started
377  if( m_isLibEdit && m_selection.Empty() )
379  else if( m_selection.Empty() )
381 
382  // Check if dragging has started within any of selected items bounding box
383  if( selectionContains( evt->Position() ) )
384  {
385  // Yes -> run the move tool and wait till it finishes
386  if( m_isLibEdit )
387  m_toolMgr->InvokeTool( "eeschema.SymbolMoveTool" );
388  else
389  m_toolMgr->InvokeTool( "eeschema.InteractiveMove" );
390  }
391  else
392  {
393  // No -> drag a selection box
394  selectMultiple();
395  }
396  }
397  }
398 
399  // context sub-menu selection? Handle unit selection or bus unfolding
400  else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CHOICE_MENU_CHOICE )
401  {
402  if( evt->GetCommandId().get() >= ID_POPUP_SCH_SELECT_UNIT_CMP
403  && evt->GetCommandId().get() <= ID_POPUP_SCH_SELECT_UNIT_CMP_MAX )
404  {
405  SCH_COMPONENT* component = dynamic_cast<SCH_COMPONENT*>( m_selection.Front() );
406  int unit = evt->GetCommandId().get() - ID_POPUP_SCH_SELECT_UNIT_CMP;
407 
408  if( component )
409  static_cast<SCH_EDIT_FRAME*>( m_frame )->SelectUnit( component, unit );
410  }
411  else if( evt->GetCommandId().get() >= ID_POPUP_SCH_UNFOLD_BUS
412  && evt->GetCommandId().get() <= ID_POPUP_SCH_UNFOLD_BUS_END )
413  {
414  wxString* net = new wxString( *evt->Parameter<wxString*>() );
416  }
417 
418  }
419 
420  else if( evt->IsCancelInteractive() )
421  {
422  if( auto schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
423  schframe->FocusOnItem( nullptr );
424 
425  ClearSelection();
426  }
427 
428  else if( evt->Action() == TA_UNDO_REDO_PRE )
429  {
430  if( auto schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
431  schframe->FocusOnItem( nullptr );
432 
433  ClearSelection();
434  }
435 
436  else
437  evt->SetPassEvent();
438  }
439 
440  return 0;
441 }
442 
443 
445 {
446  return m_selection;
447 }
448 
449 
450 bool EE_SELECTION_TOOL::SelectPoint( const VECTOR2I& aWhere, const KICAD_T* aFilterList,
451  EDA_ITEM** aItem, bool* aSelectionCancelledFlag, bool aCheckLocked, bool aAdd,
452  bool aSubtract, bool aExclusiveOr )
453 {
454  EE_COLLECTOR collector;
455 
456  collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
457 
458  if( m_isLibEdit )
459  {
460  auto part = static_cast<LIB_EDIT_FRAME*>( m_frame )->GetCurPart();
461 
462  if( !part )
463  return false;
464 
465  collector.Collect( part->GetDrawItems(), aFilterList, (wxPoint) aWhere, m_unit, m_convert );
466  }
467  else
468  collector.Collect( m_frame->GetScreen(), aFilterList, (wxPoint) aWhere, m_unit, m_convert );
469 
470  // Post-process collected items
471  for( int i = collector.GetCount() - 1; i >= 0; --i )
472  {
473  if( !Selectable( collector[ i ] ) )
474  {
475  collector.Remove( i );
476  continue;
477  }
478 
479  if( aCheckLocked && collector[ i ]->IsLocked() )
480  {
481  collector.Remove( i );
482  continue;
483  }
484 
485  // SelectPoint, unlike other selection routines, can select line ends
486  if( collector[ i ]->Type() == SCH_LINE_T )
487  {
488  SCH_LINE* line = (SCH_LINE*) collector[ i ];
489  line->ClearFlags( STARTPOINT | ENDPOINT );
490 
491  if( HitTestPoints( line->GetStartPoint(), (wxPoint) aWhere, collector.m_Threshold ) )
492  line->SetFlags( STARTPOINT );
493  else if (HitTestPoints( line->GetEndPoint(), (wxPoint) aWhere, collector.m_Threshold ) )
494  line->SetFlags( ENDPOINT );
495  else
496  line->SetFlags( STARTPOINT | ENDPOINT );
497  }
498  }
499 
501 
502  // Apply some ugly heuristics to avoid disambiguation menus whenever possible
503  if( collector.GetCount() > 1 && !m_skip_heuristics )
504  {
505  GuessSelectionCandidates( collector, aWhere );
506  }
507 
508  // If still more than one item we're going to have to ask the user.
509  if( collector.GetCount() > 1 )
510  {
511  collector.m_MenuTitle = wxEmptyString;
512  // Must call selectionMenu via RunAction() to avoid event-loop contention
513  m_toolMgr->RunAction( EE_ACTIONS::selectionMenu, true, &collector );
514 
515  if( collector.m_MenuCancelled )
516  {
517  if( aSelectionCancelledFlag )
518  *aSelectionCancelledFlag = true;
519 
520  return false;
521  }
522  }
523 
524  if( !aAdd && !aSubtract && !aExclusiveOr )
525  ClearSelection();
526 
527  bool anyAdded = false;
528  bool anySubtracted = false;
529 
530  if( collector.GetCount() > 0 )
531  {
532  for( int i = 0; i < collector.GetCount(); ++i )
533  {
534  if( aSubtract || ( aExclusiveOr && collector[i]->IsSelected() ) )
535  {
536  unselect( collector[i] );
537  anySubtracted = true;
538  }
539  else
540  {
541  select( collector[i] );
542  anyAdded = true;
543  }
544  }
545  }
546 
547  if( anyAdded )
548  {
550 
551  if( aItem && collector.GetCount() == 1 )
552  *aItem = collector[0];
553 
554  return true;
555  }
556  else if( anySubtracted )
557  {
559  return true;
560  }
561 
562  return false;
563 }
564 
565 
567 {
568  m_multiple = true; // Multiple selection mode is active
569  KIGFX::VIEW* view = getView();
570 
571  // hold all visible items
572  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
573  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> sheetPins;
574 
575  // Filter the view items based on the selection box
576  BOX2I selectionBox;
577 
578  selectionBox.SetMaximum();
579  view->Query( selectionBox, selectedItems ); // Get the list of selected items
580 
581  // Sheet pins aren't in the view; add them by hand
582  for( KIGFX::VIEW::LAYER_ITEM_PAIR& pair : selectedItems )
583  {
584  SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( pair.first );
585 
586  if( sheet )
587  {
588  int layer = pair.second;
589 
590  for( SCH_SHEET_PIN* pin : sheet->GetPins() )
591  sheetPins.emplace_back( KIGFX::VIEW::LAYER_ITEM_PAIR( pin, layer ) );
592  }
593  }
594 
595  selectedItems.insert( selectedItems.end(), sheetPins.begin(), sheetPins.end() );
596 
597  for( auto& item_pair : selectedItems )
598  {
599  if( EDA_ITEM* item = dynamic_cast<EDA_ITEM*>( item_pair.first ) )
600  {
601  if( Selectable( item ) )
602  select( item );
603  }
604  }
605 
606  m_multiple = false;
607 
608  return 0;
609 }
610 
611 
613 {
614  // There are certain parent/child and enclosure combinations that can be handled
615  // automatically.
616 
617  // Prefer exact hits to sloppy ones
618  int exactHits = 0;
619 
620  for( int i = collector.GetCount() - 1; i >= 0; --i )
621  {
622  EDA_ITEM* item = collector[ i ];
623 
624  if( item->HitTest( (wxPoint) aPos, 0 ) )
625  exactHits++;
626  }
627 
628  if( exactHits > 0 && exactHits < collector.GetCount() )
629  {
630  for( int i = collector.GetCount() - 1; i >= 0; --i )
631  {
632  EDA_ITEM* item = collector[ i ];
633 
634  if( !item->HitTest( (wxPoint) aPos, 0 ) )
635  collector.Transfer( item );
636  }
637  }
638 
639  // Prefer a non-sheet to a sheet
640  for( int i = 0; collector.GetCount() == 2 && i < 2; ++i )
641  {
642  EDA_ITEM* item = collector[ i ];
643  EDA_ITEM* other = collector[ ( i + 1 ) % 2 ];
644 
645  if( item->Type() != SCH_SHEET_T && other->Type() == SCH_SHEET_T )
646  collector.Transfer( other );
647  }
648 
649  // Prefer a symbol to a pin or the opposite, when both a symbol and a pin are selected
650  // We need to be able to select only a pin:
651  // - to display its characteristics (especially if an ERC is attached to the pin)
652  // - for cross probing, to select the corresponding pad.
653  // Note also the case happens only in schematic editor. In symbol editor, the symbol
654  // itself is never selected
655  for( int i = 0; collector.GetCount() == 2 && i < 2; ++i )
656  {
657  EDA_ITEM* item = collector[ i ];
658  EDA_ITEM* other = collector[ ( i + 1 ) % 2 ];
659 
660  if( item->Type() == SCH_COMPONENT_T && other->Type() == SCH_PIN_T )
661  {
663  collector.Transfer( other );
664  else
665  collector.Transfer( item );
666  }
667  }
668 
669  // Prefer a field to a symbol
670  for( int i = 0; collector.GetCount() == 2 && i < 2; ++i )
671  {
672  EDA_ITEM* item = collector[ i ];
673  EDA_ITEM* other = collector[ ( i + 1 ) % 2 ];
674 
675  if( item->Type() == SCH_FIELD_T && other->Type() == SCH_COMPONENT_T )
676  collector.Transfer( other );
677  }
678 
679  // No need for multiple wires at a single point; if there's a junction select that;
680  // otherwise any of the wires will do
681  bool junction = false;
682  bool wiresOnly = true;
683 
684  for( EDA_ITEM* item : collector )
685  {
686  if( item->Type() == SCH_JUNCTION_T )
687  junction = true;
688  else if( item->Type() != SCH_LINE_T )
689  wiresOnly = false;
690  }
691 
692  if( wiresOnly )
693  {
694  for( int j = collector.GetCount() - 1; j >= 0; --j )
695  {
696  if( junction && collector[ j ]->Type() != SCH_JUNCTION_T )
697  collector.Transfer( j );
698  else if( !junction && j > 0 )
699  collector.Transfer( j );
700  }
701  }
702 
703  // Construct a tight box (1/2 height and width) around the center of the closest item.
704  // All items which exist at least partly outside this box have sufficient other areas
705  // for selection and can be dropped.
706  EDA_ITEM* closest = nullptr;
707  int closestDist = INT_MAX;
708 
709  for( EDA_ITEM* item : collector )
710  {
711  int dist = EuclideanNorm( item->GetBoundingBox().GetCenter() - (wxPoint) aPos );
712 
713  if( dist < closestDist )
714  {
715  closestDist = dist;
716  closest = item;
717  }
718  }
719 
720  EDA_RECT tightBox = closest->GetBoundingBox();
721  tightBox.Inflate( -tightBox.GetWidth() / 4, -tightBox.GetHeight() / 4 );
722 
723  for( int i = collector.GetCount() - 1; i >= 0; --i )
724  {
725  EDA_ITEM* item = collector[ i ];
726 
727  if( item == closest )
728  continue;
729 
730  if( !item->HitTest( tightBox, true ) )
731  collector.Transfer( item );
732  }
733 }
734 
735 
737 {
738  if( m_selection.Empty() )
739  {
740  VECTOR2D cursorPos = getViewControls()->GetCursorPosition( true );
741 
742  ClearSelection();
743  SelectPoint( cursorPos, aFilterList );
744  m_selection.SetIsHover( true );
746  }
747  else // Trim an existing selection by aFilterList
748  {
749  for( int i = (int) m_selection.GetSize() - 1; i >= 0; --i )
750  {
751  EDA_ITEM* item = (EDA_ITEM*) m_selection.GetItem( i );
752 
753  if( !item->IsType( aFilterList ) )
754  {
755  unselect( item );
757  }
758  }
759  }
760 
762 
763  return m_selection;
764 }
765 
766 
768 {
769  VECTOR2I refP( 0, 0 );
770 
771  if( m_selection.Size() > 0 )
772  {
773  if( m_isLibEdit )
774  refP = static_cast<LIB_ITEM*>( m_selection.GetTopLeftItem() )->GetPosition();
775  else
776  refP = static_cast<SCH_ITEM*>( m_selection.GetTopLeftItem() )->GetPosition();
777  }
778 
780 }
781 
782 
784 {
785  bool cancelled = false; // Was the tool cancelled while it was running?
786  m_multiple = true; // Multiple selection mode is active
787  KIGFX::VIEW* view = getView();
788 
790  view->Add( &area );
791 
792  while( TOOL_EVENT* evt = Wait() )
793  {
794  if( evt->IsCancelInteractive() || evt->IsActivate() )
795  {
796  cancelled = true;
797  break;
798  }
799 
800  if( evt->IsDrag( BUT_LEFT ) )
801  {
803  ClearSelection();
804 
805  // Start drawing a selection box
806  area.SetOrigin( evt->DragOrigin() );
807  area.SetEnd( evt->Position() );
808  area.SetAdditive( m_additive );
811 
812  view->SetVisible( &area, true );
813  view->Update( &area );
814  getViewControls()->SetAutoPan( true );
815  }
816 
817  if( evt->IsMouseUp( BUT_LEFT ) )
818  {
819  getViewControls()->SetAutoPan( false );
820 
821  // End drawing the selection box
822  view->SetVisible( &area, false );
823 
824  // Mark items within the selection box as selected
825  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
826  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> sheetPins;
827 
828  // Filter the view items based on the selection box
829  BOX2I selectionBox = area.ViewBBox();
830  view->Query( selectionBox, selectedItems ); // Get the list of selected items
831 
832  // Sheet pins aren't in the view; add them by hand
833  for( KIGFX::VIEW::LAYER_ITEM_PAIR& pair : selectedItems )
834  {
835  SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( pair.first );
836 
837  if( sheet )
838  {
839  int layer = pair.second;
840 
841  for( SCH_SHEET_PIN* pin : sheet->GetPins() )
842  sheetPins.emplace_back( KIGFX::VIEW::LAYER_ITEM_PAIR( pin, layer ) );
843  }
844  }
845 
846  selectedItems.insert( selectedItems.end(), sheetPins.begin(), sheetPins.end() );
847 
848  int width = area.GetEnd().x - area.GetOrigin().x;
849  int height = area.GetEnd().y - area.GetOrigin().y;
850 
851  /* Selection mode depends on direction of drag-selection:
852  * Left > Right : Select objects that are fully enclosed by selection
853  * Right > Left : Select objects that are crossed by selection
854  */
855  bool windowSelection = width >= 0;
856  bool anyAdded = false;
857  bool anySubtracted = false;
858 
859  if( view->IsMirroredX() )
860  windowSelection = !windowSelection;
861 
862  // Construct an EDA_RECT to determine EDA_ITEM selection
863  EDA_RECT selectionRect( (wxPoint) area.GetOrigin(), wxSize( width, height ) );
864 
865  selectionRect.Normalize();
866 
867  for( KIGFX::VIEW::LAYER_ITEM_PAIR& pair : selectedItems )
868  {
869  EDA_ITEM* item = dynamic_cast<EDA_ITEM*>( pair.first );
870 
871  if( item && Selectable( item ) && item->HitTest( selectionRect, windowSelection ) )
872  {
873  if( m_subtractive || ( m_exclusive_or && item->IsSelected() ) )
874  {
875  unselect( item );
876  anySubtracted = true;
877  }
878  else
879  {
880  select( item );
881  item->SetFlags( STARTPOINT | ENDPOINT );
882  anyAdded = true;
883  }
884  }
885  }
886 
887  m_selection.SetIsHover( false );
888 
889  // Inform other potentially interested tools
890  if( anyAdded )
892 
893  if( anySubtracted )
895 
896  break; // Stop waiting for events
897  }
898  }
899 
900  getViewControls()->SetAutoPan( false );
901 
902  // Stop drawing the selection box
903  view->Remove( &area );
904  m_multiple = false; // Multiple selection mode is inactive
905 
906  if( !cancelled )
908 
909  return cancelled;
910 }
911 
912 
913 static KICAD_T nodeTypes[] =
914 {
916  SCH_PIN_T,
921  SCH_LABEL_T,
926  EOT
927 };
928 
929 
931 {
932  EE_COLLECTOR collector;
933 
934  //TODO(snh): Reimplement after exposing KNN interface
935  int thresholdMax = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
936 
937  for( int threshold : { 0, thresholdMax/2, thresholdMax } )
938  {
939  collector.m_Threshold = threshold;
940  collector.Collect( m_frame->GetScreen(), nodeTypes, (wxPoint) aPosition );
941 
942  if( collector.GetCount() > 0 )
943  break;
944  }
945 
946  return collector.GetCount() ? collector[ 0 ] : nullptr;
947 }
948 
949 
951 {
952  VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !aEvent.Modifier( MD_ALT ) );
953 
954  SelectPoint( cursorPos, nodeTypes );
955 
956  return 0;
957 }
958 
959 
961 {
962  static KICAD_T wiresAndBuses[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT };
963 
964  RequestSelection( wiresAndBuses );
965 
966  if( m_selection.Empty() )
967  return 0;
968 
969  SCH_LINE* line = (SCH_LINE*) m_selection.Front();
970  EDA_ITEMS items;
971 
973  auto conns = m_frame->GetScreen()->MarkConnections( line );
974 
975  for( auto item : conns )
976  select( item );
977 
978  if( m_selection.GetSize() > 1 )
980 
981  return 0;
982 }
983 
984 
986 {
987  AddItemToSel( aEvent.Parameter<EDA_ITEM*>() );
988  m_selection.SetIsHover( false );
989  return 0;
990 }
991 
992 
993 void EE_SELECTION_TOOL::AddItemToSel( EDA_ITEM* aItem, bool aQuietMode )
994 {
995  if( aItem )
996  {
997  select( aItem );
998 
999  // Inform other potentially interested tools
1000  if( !aQuietMode )
1002  }
1003 }
1004 
1005 
1007 {
1008  AddItemsToSel( aEvent.Parameter<EDA_ITEMS*>(), false );
1009  m_selection.SetIsHover( false );
1010  return 0;
1011 }
1012 
1013 
1014 void EE_SELECTION_TOOL::AddItemsToSel( EDA_ITEMS* aList, bool aQuietMode )
1015 {
1016  if( aList )
1017  {
1018  for( EDA_ITEM* item : *aList )
1019  select( item );
1020 
1021  // Inform other potentially interested tools
1022  if( !aQuietMode )
1024  }
1025 }
1026 
1027 
1029 {
1030  RemoveItemFromSel( aEvent.Parameter<EDA_ITEM*>() );
1031  m_selection.SetIsHover( false );
1032  return 0;
1033 }
1034 
1035 
1036 void EE_SELECTION_TOOL::RemoveItemFromSel( EDA_ITEM* aItem, bool aQuietMode )
1037 {
1038  if( aItem )
1039  {
1040  unselect( aItem );
1041 
1042  // Inform other potentially interested tools
1043  if( !aQuietMode )
1045  }
1046 }
1047 
1048 
1050 {
1051  RemoveItemsFromSel( aEvent.Parameter<EDA_ITEMS*>(), false );
1052  m_selection.SetIsHover( false );
1053  return 0;
1054 }
1055 
1056 
1057 void EE_SELECTION_TOOL::RemoveItemsFromSel( EDA_ITEMS* aList, bool aQuietMode )
1058 {
1059  if( aList )
1060  {
1061  for( EDA_ITEM* item : *aList )
1062  unselect( item );
1063 
1064  // Inform other potentially interested tools
1065  if( !aQuietMode )
1067  }
1068 }
1069 
1070 
1072 {
1073  highlight( aItem, BRIGHTENED );
1074 }
1075 
1076 
1078 {
1079  unhighlight( aItem, BRIGHTENED );
1080 }
1081 
1082 
1084 {
1085  ClearSelection();
1086 
1087  return 0;
1088 }
1089 
1090 
1092 {
1093  m_selection.Clear();
1094 
1095  if( m_isLibEdit )
1096  {
1097  LIB_PART* start = static_cast<LIB_EDIT_FRAME*>( m_frame )->GetCurPart();
1098 
1099  for( LIB_ITEM& item : start->GetDrawItems() )
1100  {
1101  if( item.IsSelected() )
1102  select( static_cast<EDA_ITEM*>( &item ) );
1103  }
1104  }
1105  else
1106  {
1107  for( auto item : m_frame->GetScreen()->Items() )
1108  {
1109  // If the field and component are selected, only use the component
1110  if( item->IsSelected() )
1111  {
1112  select( item );
1113  }
1114  else
1115  {
1116  if( item->Type() == SCH_COMPONENT_T )
1117  {
1118  for( SCH_FIELD& field : static_cast<SCH_COMPONENT*>( item )->GetFields() )
1119  {
1120  if( field.IsSelected() )
1121  select( &field );
1122  }
1123  }
1124 
1125  if( item->Type() == SCH_SHEET_T )
1126  {
1127  for( SCH_FIELD& field : static_cast<SCH_SHEET*>( item )->GetFields() )
1128  {
1129  if( field.IsSelected() )
1130  select( &field );
1131  }
1132 
1133  for( SCH_SHEET_PIN* pin : static_cast<SCH_SHEET*>( item )->GetPins() )
1134  {
1135  if( pin->IsSelected() )
1136  select( pin );
1137  }
1138  }
1139 
1140  }
1141  }
1142  }
1143 
1145 
1146  // Inform other potentially interested tools
1148 }
1149 
1150 
1152 {
1153  EE_COLLECTOR* collector = aEvent.Parameter<EE_COLLECTOR*>();
1154 
1155  if( !doSelectionMenu( collector ) )
1156  collector->m_MenuCancelled = true;
1157 
1158  return 0;
1159 }
1160 
1161 
1163 {
1164  EDA_ITEM* current = nullptr;
1165  bool selectAll = false;
1166  bool expandSelection = false;
1167 
1168  do
1169  {
1171  if( expandSelection )
1172  aCollector->Combine();
1173 
1174  expandSelection = false;
1175 
1176  int limit = std::min( 9, aCollector->GetCount() );
1177  ACTION_MENU menu( true );
1178 
1179  for( int i = 0; i < limit; ++i )
1180  {
1181  wxString text;
1182  EDA_ITEM* item = ( *aCollector )[i];
1183  text = item->GetSelectMenuText( m_frame->GetUserUnits() );
1184 
1185  wxString menuText = wxString::Format( "&%d. %s\t%d", i + 1, text, i + 1 );
1186  menu.Add( menuText, i + 1, item->GetMenuImage() );
1187  }
1188 
1189  menu.AppendSeparator();
1190  menu.Add( _( "Select &All\tA" ), limit + 1, net_highlight_schematic_xpm );
1191 
1192  if( !expandSelection && aCollector->HasAdditionalItems() )
1193  menu.Add( _( "&Expand Selection\tE" ), limit + 2, nullptr );
1194 
1195  if( aCollector->m_MenuTitle.Length() )
1196  {
1197  menu.SetTitle( aCollector->m_MenuTitle );
1198  menu.SetIcon( info_xpm );
1199  menu.DisplayTitle( true );
1200  }
1201  else
1202  {
1203  menu.DisplayTitle( false );
1204  }
1205 
1206  SetContextMenu( &menu, CMENU_NOW );
1207 
1208  while( TOOL_EVENT* evt = Wait() )
1209  {
1210  if( evt->Action() == TA_CHOICE_MENU_UPDATE )
1211  {
1212  if( selectAll )
1213  {
1214  for( int i = 0; i < aCollector->GetCount(); ++i )
1215  unhighlight( ( *aCollector )[i], BRIGHTENED );
1216  }
1217  else if( current )
1218  {
1219  unhighlight( current, BRIGHTENED );
1220  }
1221 
1222  int id = *evt->GetCommandId();
1223 
1224  // User has pointed an item, so show it in a different way
1225  if( id > 0 && id <= limit )
1226  {
1227  current = ( *aCollector )[id - 1];
1228  highlight( current, BRIGHTENED );
1229  }
1230  else
1231  {
1232  current = nullptr;
1233  }
1234 
1235  // User has pointed on the "Select All" option
1236  if( id == limit + 1 )
1237  {
1238  for( int i = 0; i < aCollector->GetCount(); ++i )
1239  highlight( ( *aCollector )[i], BRIGHTENED );
1240  selectAll = true;
1241  }
1242  else
1243  {
1244  selectAll = false;
1245  }
1246  }
1247  else if( evt->Action() == TA_CHOICE_MENU_CHOICE )
1248  {
1249  if( selectAll )
1250  {
1251  for( int i = 0; i < aCollector->GetCount(); ++i )
1252  unhighlight( ( *aCollector )[i], BRIGHTENED );
1253  }
1254  else if( current )
1255  unhighlight( current, BRIGHTENED );
1256 
1257  OPT<int> id = evt->GetCommandId();
1258 
1259  // User has selected the "Select All" option
1260  if( id == limit + 1 )
1261  {
1262  selectAll = true;
1263  current = nullptr;
1264  }
1265  // User has selected an item, so this one will be returned
1266  else if( id && ( *id > 0 ) && ( *id <= limit ) )
1267  {
1268  selectAll = false;
1269  current = ( *aCollector )[*id - 1];
1270  }
1271  else
1272  {
1273  selectAll = false;
1274  current = nullptr;
1275  }
1276  }
1277  else if( evt->Action() == TA_CHOICE_MENU_CLOSED )
1278  {
1279  break;
1280  }
1281 
1282  getView()->UpdateItems();
1283  m_frame->GetCanvas()->Refresh();
1284  }
1285  } while( expandSelection );
1286 
1287  if( selectAll )
1288  return true;
1289  else if( current )
1290  {
1291  unhighlight( current, BRIGHTENED );
1292 
1293  getView()->UpdateItems();
1294  m_frame->GetCanvas()->Refresh();
1295 
1296  aCollector->Empty();
1297  aCollector->Append( current );
1298  return true;
1299  }
1300 
1301  return false;
1302 }
1303 
1304 
1305 bool EE_SELECTION_TOOL::Selectable( const EDA_ITEM* aItem, bool checkVisibilityOnly ) const
1306 {
1307  // NOTE: in the future this is where eeschema layer/itemtype visibility will be handled
1308  LIB_EDIT_FRAME* symbeditFrame = dynamic_cast< LIB_EDIT_FRAME* >( m_frame );
1309 
1310  switch( aItem->Type() )
1311  {
1312  case SCH_PIN_T:
1313  if( !static_cast<const SCH_PIN*>( aItem )->IsVisible() && !m_frame->GetShowAllPins() )
1314  return false;
1315  break;
1316 
1317  case LIB_PART_T: // In libedit we do not want to select the symbol itself.
1318  return false;
1319 
1320  case LIB_FIELD_T: // LIB_FIELD object can always be edited.
1321  break;
1322 
1323  case LIB_ARC_T:
1324  case LIB_CIRCLE_T:
1325  case LIB_TEXT_T:
1326  case LIB_RECTANGLE_T:
1327  case LIB_POLYLINE_T:
1328  case LIB_BEZIER_T:
1329  case LIB_PIN_T:
1330  {
1331  if( symbeditFrame )
1332  {
1333  LIB_ITEM* lib_item = (LIB_ITEM*) aItem;
1334 
1335  if( lib_item->GetUnit() && lib_item->GetUnit() != symbeditFrame->GetUnit() )
1336  return false;
1337 
1338  if( lib_item->GetConvert() && lib_item->GetConvert() != symbeditFrame->GetConvert() )
1339  return false;
1340  }
1341 
1342  break;
1343  }
1344 
1345  case SCH_MARKER_T: // Always selectable
1346  return true;
1347 
1348  default: // Suppress warnings
1349  break;
1350  }
1351 
1352  return true;
1353 }
1354 
1355 
1357 {
1358  if( m_selection.Empty() )
1359  return;
1360 
1361  while( m_selection.GetSize() )
1363 
1364  getView()->Update( &m_selection );
1365 
1366  m_selection.SetIsHover( false );
1368 
1369  // Inform other potentially interested tools
1371 }
1372 
1373 
1375 {
1376  highlight( aItem, SELECTED, &m_selection );
1377 }
1378 
1379 
1381 {
1382  unhighlight( aItem, SELECTED, &m_selection );
1383 }
1384 
1385 
1386 void EE_SELECTION_TOOL::highlight( EDA_ITEM* aItem, int aMode, EE_SELECTION* aGroup )
1387 {
1388  KICAD_T itemType = aItem->Type();
1389 
1390  if( aMode == SELECTED )
1391  aItem->SetSelected();
1392  else if( aMode == BRIGHTENED )
1393  aItem->SetBrightened();
1394 
1395  if( aGroup )
1396  aGroup->Add( aItem );
1397 
1398  // Highlight pins and fields. (All the other component children are currently only
1399  // represented in the LIB_PART and will inherit the settings of the parent component.)
1400  if( itemType == SCH_COMPONENT_T )
1401  {
1402  for( SCH_PIN* pin : static_cast<SCH_COMPONENT*>( aItem )->GetPins() )
1403  {
1404  if( aMode == SELECTED )
1405  pin->SetSelected();
1406  else if( aMode == BRIGHTENED )
1407  pin->SetBrightened();
1408  }
1409 
1410  for( SCH_FIELD& field : static_cast<SCH_COMPONENT*>( aItem )->GetFields() )
1411  {
1412  if( aMode == SELECTED )
1413  field.SetSelected();
1414  else if( aMode == BRIGHTENED )
1415  field.SetBrightened();
1416  }
1417  }
1418  else if( itemType == SCH_SHEET_T )
1419  {
1420  for( SCH_FIELD& field : static_cast<SCH_SHEET*>( aItem )->GetFields() )
1421  {
1422  if( aMode == SELECTED )
1423  field.SetSelected();
1424  else if( aMode == BRIGHTENED )
1425  field.SetBrightened();
1426  }
1427 
1428  for( SCH_SHEET_PIN* pin : static_cast<SCH_SHEET*>( aItem )->GetPins() )
1429  {
1430  if( aMode == SELECTED )
1431  pin->SetSelected();
1432  else if( aMode == BRIGHTENED )
1433  pin->SetBrightened();
1434  }
1435  }
1436 
1437  if( itemType == SCH_PIN_T || itemType == SCH_FIELD_T || itemType == SCH_SHEET_PIN_T )
1438  getView()->Update( aItem->GetParent() );
1439  else
1440  getView()->Update( aItem );
1441 }
1442 
1443 
1444 void EE_SELECTION_TOOL::unhighlight( EDA_ITEM* aItem, int aMode, EE_SELECTION* aGroup )
1445 {
1446  KICAD_T itemType = aItem->Type();
1447 
1448  if( aMode == SELECTED )
1449  aItem->ClearSelected();
1450  else if( aMode == BRIGHTENED )
1451  aItem->ClearBrightened();
1452 
1453  if( aGroup )
1454  aGroup->Remove( aItem );
1455 
1456  // Unhighlight pins and fields. (All the other component children are currently only
1457  // represented in the LIB_PART.)
1458  if( itemType == SCH_COMPONENT_T )
1459  {
1460  for( SCH_PIN* pin : static_cast<SCH_COMPONENT*>( aItem )->GetPins() )
1461  {
1462  if( aMode == SELECTED )
1463  pin->ClearSelected();
1464  else if( aMode == BRIGHTENED )
1465  pin->ClearBrightened();
1466  }
1467 
1468  for( SCH_FIELD& field : static_cast<SCH_COMPONENT*>( aItem )->GetFields() )
1469  {
1470  if( aMode == SELECTED )
1471  field.ClearSelected();
1472  else if( aMode == BRIGHTENED )
1473  field.ClearBrightened();
1474  }
1475  }
1476  else if( itemType == SCH_SHEET_T )
1477  {
1478  for( SCH_FIELD& field : static_cast<SCH_SHEET*>( aItem )->GetFields() )
1479  {
1480  if( aMode == SELECTED )
1481  field.ClearSelected();
1482  else if( aMode == BRIGHTENED )
1483  field.ClearBrightened();
1484  }
1485 
1486  for( SCH_SHEET_PIN* pin : static_cast<SCH_SHEET*>( aItem )->GetPins() )
1487  {
1488  if( aMode == SELECTED )
1489  pin->ClearSelected();
1490  else if( aMode == BRIGHTENED )
1491  pin->ClearBrightened();
1492  }
1493  }
1494 
1495  if( itemType == SCH_PIN_T || itemType == SCH_FIELD_T || itemType == SCH_SHEET_PIN_T )
1496  getView()->Update( aItem->GetParent() );
1497  else
1498  getView()->Update( aItem );
1499 }
1500 
1501 
1503 {
1504  const unsigned GRIP_MARGIN = 20;
1505  VECTOR2I margin = getView()->ToWorld( VECTOR2I( GRIP_MARGIN, GRIP_MARGIN ), false );
1506 
1507  // Check if the point is located within any of the currently selected items bounding boxes
1508  for( auto item : m_selection )
1509  {
1510  BOX2I itemBox = item->ViewBBox();
1511  itemBox.Inflate( margin.x, margin.y ); // Give some margin for gripping an item
1512 
1513  if( itemBox.Contains( aPoint ) )
1514  return true;
1515  }
1516 
1517  return false;
1518 }
1519 
1520 
1522 {
1524 
1529 
1535 
1537 }
1538 
1539 
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:133
void Empty()
Function Empty sets the list to empty.
Definition: collector.h:110
void ClearReferencePoint()
Definition: selection.h:250
static TOOL_ACTION pinTable
Definition: ee_actions.h:146
static TOOL_ACTION properties
Definition: ee_actions.h:121
SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:52
void AddStandardSubMenus(TOOL_MENU &aMenu)
Function CreateBasicMenu.
static const TOOL_EVENT SelectedEvent
Definition: actions.h:206
void SetEnd(VECTOR2I aEnd)
Set the current end of the rectangle (the corner that moves with the cursor.
TOOL_MENU m_menu
functions below are not yet implemented - their interface may change
bool selectionContains(const VECTOR2I &aPoint) const
Function selectionContains()
int m_Threshold
Definition: collector.h:67
int UpdateMenu(const TOOL_EVENT &aEvent)
virtual void Clear() override
Function Clear() Removes all the stored items from the group.
Definition: selection.h:95
static bool IsDrawingWire(const SELECTION &aSelection)
int SelectAll(const TOOL_EVENT &aEvent)
Select all visible items in sheet
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
static TOOL_ACTION breakBus
Definition: ee_actions.h:135
static SELECTION_CONDITION SingleSymbol
int GetConvert() const
wxPoint GetStartPoint() const
Definition: sch_line.h:94
bool IsSelected() const
Definition: base_struct.h:203
Model changes (required full reload)
Definition: tool_base.h:82
static const TOOL_EVENT UnselectedEvent
Definition: actions.h:207
SCH_SHEET * Last() const
Function Last returns a pointer to the last sheet of the list One can see the others sheet as the "pa...
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:43
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:474
void SetOrigin(VECTOR2I aOrigin)
Set the origin of the rectange (the fixed corner)
void ClearSelected()
Definition: base_struct.h:211
static SELECTION_CONDITION MoreThan(int aNumber)
Creates a functor that tests if the number of selected items is greater than the value given as param...
void Collect(SCH_SCREEN *aScreen, const KICAD_T aFilterList[], const wxPoint &aPos, int aUnit=0, int aConvert=0)
Function Collect scans a EDA_ITEM using this class's Inspector method, which does the collection.
void SetCurrentCursor(wxStockCursor aStockCursorID)
Function SetCurrentCursor Set the current cursor shape for this panel.
static TOOL_ACTION addItemsToSel
Selects a list of items (specified as the event parameter)
Definition: ee_actions.h:63
VIEW_CONTROLS class definition.
static bool Idle(const SELECTION &aSelection)
Tests if there no items selected or being edited.
static SELECTION_CONDITION OnlyTypes(const KICAD_T aTypes[])
Creates a functor that tests if the selected items are only of given types.
CONDITIONAL_MENU & GetMenu()
Function GetMenu.
Definition: tool_menu.cpp:46
static TOOL_ACTION placeHierLabel
Definition: ee_actions.h:87
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:219
static TOOL_ACTION placeJunction
Definition: ee_actions.h:83
static TOOL_ACTION selectConnection
If current selection is a wire or bus, expand to entire connection.
Definition: ee_actions.h:53
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
virtual void Remove(VIEW_ITEM *aItem)
Function Remove() Removes a VIEW_ITEM from the view.
Definition: view.cpp:375
int GetWidth() const
Definition: eda_rect.h:119
bool selectMultiple()
Function selectMultiple() Handles drawing a selection box that allows one to select many items at the...
static TOOL_ACTION unfoldBus
Definition: ee_actions.h:81
void SetBrightened()
Definition: base_struct.h:209
#define HITTEST_THRESHOLD_PIXELS
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:140
void SetExclusiveOr(bool aExclusiveOr)
EE_COLLECTOR.
Definition: ee_collectors.h:42
bool Selectable(const EDA_ITEM *aItem, bool checkVisibilityOnly=false) const
Function Selectable() Checks conditions for an item to be selected.
int AddItemsToSel(const TOOL_EVENT &aEvent)
void select(EDA_ITEM *aItem)
Function select() Takes necessary action mark an item as selected.
Schematic editor (Eeschema) main window.
void UpdateAll()
Runs update handlers for the menu and its submenus.
static TOOL_ACTION removeItemsFromSel
Definition: ee_actions.h:64
static SELECTION_CONDITION Count(int aNumber)
Creates a functor that tests if the number of selected items is equal to the value given as parameter...
void SetContextMenu(ACTION_MENU *aMenu, CONTEXT_MENU_TRIGGER aTrigger=CMENU_BUTTON)
Function SetContextMenu()
VECTOR2< int > VECTOR2I
Definition: vector2d.h:594
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Function Go()
bool Contains(const wxPoint &aPoint) const
Function Contains.
void Remove(int aIndex)
Function Remove removes the item at aIndex (first position is 0);.
Definition: collector.h:130
bool InvokeTool(TOOL_ID aToolId)
Function InvokeTool() Calls a tool by sending a tool activation event to tool of given ID.
Symbol library viewer main window.
search types array terminator (End Of Types)
Definition: typeinfo.h:82
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:78
PAINTER * GetPainter() const
Function GetPainter() Returns the painter object used by the view for drawing VIEW_ITEMS.
Definition: view.h:199
void GuessSelectionCandidates(EE_COLLECTOR &collector, const VECTOR2I &aPos)
Apply heuristics to try and determine a single object when multiple are found under the cursor.
The base class for drawable items used by schematic library components.
Definition: lib_item.h:61
static TOOL_ACTION breakWire
Definition: ee_actions.h:134
void SetIsHover(bool aIsHover)
Definition: selection.h:66
virtual void Add(EDA_ITEM *aItem)
Definition: selection.h:76
const KICAD_T movableSymbolItems[]
static TOOL_ACTION leaveSheet
Definition: ee_actions.h:185
void ClearBrightened()
Definition: base_struct.h:212
static TOOL_ACTION removeItemFromSel
Definition: ee_actions.h:60
void Append(EDA_ITEM *item)
Function Append adds an item to the end of the list.
Definition: collector.h:120
void SetAdditive(bool aAdditive)
bool m_MenuCancelled
Definition: collector.h:70
EE_SELECTION & GetSelection()
Function GetSelection()
EESCHEMA_SETTINGS * eeconfig() const
EE_SELECTION & RequestSelection(const KICAD_T *aFilterList=EE_COLLECTOR::AllItems)
Function RequestSelection()
virtual bool HitTest(const wxPoint &aPosition, int aAccuracy=0) const
Function HitTest tests if aPosition is contained within or on the bounding box of an item.
Definition: base_struct.h:307
void updateReferencePoint()
Sets the reference point to the anchor of the top-left item.
static SELECTION_CONDITION SingleDeMorganSymbol
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:101
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
#define SELECTED
Definition: base_struct.h:124
int SelectNode(const TOOL_EVENT &aEvent)
Select node under cursor
void SetReferencePoint(const VECTOR2I &aP)
Definition: selection.h:245
int GetUnit() const
Definition: lib_item.h:295
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
void Transfer(int aIndex)
Moves the item at aIndex (first position is 0) to the backup list.
Definition: collector.h:174
void BrightenItem(EDA_ITEM *aItem)
void highlight(EDA_ITEM *aItem, int aHighlightMode, EE_SELECTION *aGroup=nullptr)
Function highlight() Highlights the item visually.
int GetUnit() const
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:232
static TOOL_ACTION addItemToSel
Selects an item (specified as the event parameter).
Definition: ee_actions.h:59
void SetSelected()
Definition: base_struct.h:208
static TOOL_ACTION drawWire
Definition: ee_actions.h:79
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagates an event to tools that requested events of matching type(s).
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
std::vector< EDA_ITEM * > EDA_ITEMS
Define list of drawing items for screens.
Definition: base_struct.h:588
static TOOL_ACTION explicitCrossProbe
Definition: ee_actions.h:197
T Parameter() const
Function Parameter() Returns a non-standard parameter assigned to the event.
Definition: tool_event.h:435
static TOOL_ACTION symbolProperties
Definition: ee_actions.h:145
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
bool Contains(const Vec &aPoint) const
Function Contains.
Definition: box2.h:151
TOOL_EVENT.
Definition: tool_event.h:171
void SetMaximum()
Definition: box2.h:73
const BOX2I ViewBBox() const override
Function ViewBBox() returns the bounding box of the item covering all its layers.
SCHEMATIC & Schematic() const
Define a library symbol object.
bool ToolStackIsEmpty()
Definition: tools_holder.h:117
const BITMAP_OPAQUE net_highlight_schematic_xpm[1]
#define BRIGHTENED
item is drawn with a bright contour
Definition: base_struct.h:139
EDA_ITEM * GetParent() const
Definition: base_struct.h:195
bool GetDragSelects() const
Indicates that a drag should draw a selection rectangle, even when started over an item.
Definition: tools_holder.h:134
VIEW_GROUP extends VIEW_ITEM by possibility of grouping items into a single object.
int SelectConnection(const TOOL_EVENT &aEvent)
If node selected then expand to connection, otherwise select connection under cursor
static const TOOL_EVENT ClearedEvent
Definition: actions.h:208
virtual bool IsType(const KICAD_T aScanTypes[]) const
Function IsType Checks whether the item is one of the listed types.
Definition: base_struct.h:262
std::function< bool(const SELECTION &)> SELECTION_CONDITION
Functor type that checks a specific condition for selected items.
void UpdateItems()
Function UpdateItems() Iterates through the list of items that asked for updating and updates them.
Definition: view.cpp:1412
static TOOL_ACTION selectionActivate
Activation of the selection tool.
Definition: ee_actions.h:46
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet.h:84
static TOOL_ACTION importSheetPin
Definition: ee_actions.h:90
static TOOL_ACTION clearSelection
Clears the current selection.
Definition: ee_actions.h:56
std::unique_ptr< LIB_PART > & GetPartRef()
static TOOL_ACTION updateMenu
Definition: actions.h:165
static SELECTION_CONDITION SingleMultiUnitSymbol
virtual KIGFX::VIEW_ITEM * GetItem(unsigned int aIdx) const override
Definition: selection.h:105
virtual void Update(VIEW_ITEM *aItem, int aUpdateFlags)
For dynamic VIEWs, informs the associated VIEW that the graphical representation of this item has cha...
Definition: view.cpp:1531
int GetConvert() const
Definition: lib_item.h:298
const BITMAP_OPAQUE info_xpm[1]
Definition: info.cpp:75
void UnbrightenItem(EDA_ITEM *aItem)
EDA_ITEM * GetNode(VECTOR2I aPosition)
Find (but don't select) node under cursor
int GetHeight() const
Definition: eda_rect.h:120
KIGFX::VIEW * getView() const
Function getView()
Definition: tool_base.cpp:36
virtual void SetAutoPan(bool aEnabled)
Function SetAutoPan Turns on/off auto panning (this feature is used when there is a tool active (eg.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:121
static bool IsDrawingBus(const SELECTION &aSelection)
static TOOL_ACTION drawBus
Definition: ee_actions.h:80
wxString m_MenuTitle
Definition: collector.h:69
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:216
bool IsMirroredX() const
Function IsMirroredX() Returns true if view is flipped across the X axis.
Definition: view.h:230
void SetSubtractive(bool aSubtractive)
virtual unsigned int GetSize() const override
Function GetSize() Returns the number of stored items.
Definition: selection.h:100
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition: sch_sheet.h:362
int Modifier(int aMask=MD_MODIFIER_MASK) const
Returns information about key modifiers state (Ctrl, Alt, etc.)
Definition: tool_event.h:342
static TOOL_ACTION placeLabel
Definition: ee_actions.h:85
int RemoveItemFromSel(const TOOL_EVENT &aEvent)
void Normalize()
Function Normalize ensures that the height ant width are positive.
void unselect(EDA_ITEM *aItem)
Function unselect() Takes necessary action mark an item as unselected.
EDA_ITEM * GetTopLeftItem(bool onlyModules=false) const override
virtual RENDER_SETTINGS * GetSettings()=0
Function GetAdapter Returns pointer to current settings that are going to be used when drawing items.
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:302
SCH_SHEET & Root() const
Definition: schematic.h:94
static KICAD_T nodeTypes[]
The symbol library editor main window.
bool HasAdditionalItems()
Test if the collector has heuristic backup items.
Definition: collector.h:156
int AddItemToSel(const TOOL_EVENT &aEvent)
void SetHighlight(bool aEnabled, int aNetcode=-1, bool aMulti=false)
Function SetHighlight Turns on/off highlighting - it may be done for the active layer or the specifie...
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:37
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:201
virtual bool GetShowAllPins() const
Allow some frames to show/hide hidden pins.
bool SelectPoint(const VECTOR2I &aWhere, const KICAD_T *aFilterList=EE_COLLECTOR::AllItems, EDA_ITEM **aItem=nullptr, bool *aSelectionCancelledFlag=nullptr, bool aCheckLocked=false, bool aAdd=false, bool aSubtract=false, bool aExclusiveOr=false)
Function SelectPoint() Selects one or all items pointed by the parameter aWhere.
#define _(s)
Definition: 3d_actions.cpp:33
int SelectionMenu(const TOOL_EVENT &aEvent)
Function SelectionMenu() Shows a popup menu to trim the COLLECTOR passed as aEvent's parameter down t...
bool doSelectionMenu(EE_COLLECTOR *aItems)
Allows the selection of a single item from a list via pop-up menu.
SCH_BASE_FRAME * m_frame
static TOOL_ACTION assignNetclass
Definition: ee_actions.h:153
virtual wxString GetSelectMenuText(EDA_UNITS aUnits) const
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
std::pair< VIEW_ITEM *, int > LAYER_ITEM_PAIR
Definition: view.h:66
bool HitTestPoints(const wxPoint &pointA, const wxPoint &pointB, double threshold)
Test, if two points are near each other.
Definition: trigo.h:171
static TOOL_ACTION selectionMenu
Runs a selection menu to select from a list of items.
Definition: ee_actions.h:67
EE_RTREE & Items()
Definition: sch_screen.h:158
#define ENDPOINT
ends. (Used to support dragging.)
Definition: base_struct.h:123
static SELECTION_CONDITION OnlyType(KICAD_T aType)
Creates a functor that tests if the selected items are only of given type.
void RebuildSelection()
Rebuilds the selection from the EDA_ITEMs' selection flags.
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
static const KICAD_T AllItems[]
Definition: ee_collectors.h:45
int Size() const
Returns the number of selected parts.
Definition: selection.h:127
Schematic symbol object.
Definition: sch_component.h:80
static bool Empty(const SELECTION &aSelection)
Tests if there are no items selected.
static TOOL_ACTION selectNode
Select the junction, wire or bus segment under the cursor.
Definition: ee_actions.h:49
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: base_struct.h:159
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:79
static TOOL_ACTION enterSheet
Definition: ee_actions.h:184
boost::optional< T > OPT
Definition: optional.h:7
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: base_struct.h:233
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Sets the item visibility.
Definition: view.cpp:1477
void Combine()
Re-combines the backup list into the main list of the collector.
Definition: collector.h:164
SCH_SHEET_PATH & GetCurrentSheet() const
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Function Add() Adds a VIEW_ITEM to the view.
Definition: view.cpp:345
void setTransitions() override
Sets up handlers for various events.
void ClearDrawingState()
Clear the state flags of all the items in the screen.
Definition: sch_screen.cpp:834
virtual int Query(const BOX2I &aRect, std::vector< LAYER_ITEM_PAIR > &aResult) const
Function Query() Finds all visible items that touch or are within the rectangle aRect.
Definition: view.cpp:451
virtual const EDA_RECT GetBoundingBox() const
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
Definition: base_struct.cpp:97
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:42
VIEW.
Definition: view.h:61
static TOOL_ACTION placeGlobalLabel
Definition: ee_actions.h:86
static TOOL_ACTION finishBus
Definition: ee_actions.h:96
int RemoveItemsFromSel(const TOOL_EVENT &aEvent)
virtual BITMAP_DEF GetMenuImage() const
Function GetMenuImage returns a pointer to an image to be used in menus.
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Adds a menu entry to run a TOOL_ACTION on selected items.
EE_SELECTION m_selection
static TOOL_ACTION selectAll
Definition: actions.h:73
EDA_RECT GetBoundingBox() const
Definition: selection.h:156
void ShowContextMenu(SELECTION &aSelection)
Function ShowContextMenu.
Definition: tool_menu.cpp:59
static TOOL_ACTION finishWire
Definition: ee_actions.h:95
void unhighlight(EDA_ITEM *aItem, int aHighlightMode, EE_SELECTION *aGroup=nullptr)
Function unhighlight() Unhighlights the item visually.
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.
EDA_ITEM * Front() const
Definition: selection.h:184
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
const KICAD_T movableSchematicItems[]
KICAD_T Type() const
Function Type()
Definition: base_struct.h:193
int Main(const TOOL_EVENT &aEvent)
Function Main()
#define STARTPOINT
When a line is selected, these flags indicate which.
Definition: base_struct.h:122
std::set< SCH_ITEM * > MarkConnections(SCH_LINE *aSegment)
Return all wires and junctions connected to aSegment which are not connected any component pin.
Definition: sch_screen.cpp:328
virtual void Remove(EDA_ITEM *aItem)
Definition: selection.h:87
wxPoint GetEndPoint() const
Definition: sch_line.h:97