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 <symbol_edit_frame.h>
33 #include <lib_item.h>
34 #include <symbol_viewer_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_item.h>
43 #include <sch_line.h>
44 #include <sch_sheet.h>
45 #include <schematic.h>
46 #include <tool/tool_event.h>
47 #include <tool/tool_manager.h>
48 #include <tools/ee_grid_helper.h>
50 #include <trigo.h>
51 #include <view/view.h>
52 #include <view/view_controls.h>
53 
54 
56 {
57  if( aSel.GetSize() == 1 )
58  {
59  SCH_COMPONENT* symbol = dynamic_cast<SCH_COMPONENT*>( aSel.Front() );
60 
61  if( symbol )
62  return !symbol->GetPartRef() || !symbol->GetPartRef()->IsPower();
63  }
64 
65  return false;
66 };
67 
68 
70 {
71  if( aSel.GetSize() == 1 )
72  {
73  SCH_COMPONENT* symbol = dynamic_cast<SCH_COMPONENT*>( aSel.Front() );
74 
75  if( symbol )
76  return symbol->GetPartRef() && symbol->GetPartRef()->HasConversion();
77  }
78 
79  return false;
80 };
81 
82 
84 {
85  if( aSel.GetSize() == 1 )
86  {
87  SCH_COMPONENT* symbol = dynamic_cast<SCH_COMPONENT*>( aSel.Front() );
88 
89  if( symbol )
90  return symbol->GetPartRef() && symbol->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_nonModifiedCursor( KICURSOR::ARROW ),
109  m_isSymbolEditor( false ),
110  m_isSymbolViewer( false ),
111  m_unit( 0 ),
112  m_convert( 0 )
113 {
114  m_selection.Clear();
115 }
116 
117 
119 {
120  getView()->Remove( &m_selection );
121 }
122 
123 
125 
126 
128 {
129  m_frame = getEditFrame<SCH_BASE_FRAME>();
130 
131  SYMBOL_VIEWER_FRAME* symbolViewerFrame = dynamic_cast<SYMBOL_VIEWER_FRAME*>( m_frame );
132  SYMBOL_EDIT_FRAME* symbolEditorFrame = dynamic_cast<SYMBOL_EDIT_FRAME*>( m_frame );
133 
134  if( symbolEditorFrame )
135  {
136  m_isSymbolEditor = true;
137  m_unit = symbolEditorFrame->GetUnit();
138  m_convert = symbolEditorFrame->GetConvert();
139  }
140  else
141  {
142  m_isSymbolViewer = symbolViewerFrame != nullptr;
143  }
144 
145  static KICAD_T wireOrBusTypes[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT };
146  static KICAD_T connectedTypes[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T,
149 
150  auto wireSelection = E_C::MoreThan( 0 ) && E_C::OnlyType( SCH_LINE_LOCATE_WIRE_T );
151  auto busSelection = E_C::MoreThan( 0 ) && E_C::OnlyType( SCH_LINE_LOCATE_BUS_T );
152  auto wireOrBusSelection = E_C::MoreThan( 0 ) && E_C::OnlyTypes( wireOrBusTypes );
153  auto connectedSelection = E_C::MoreThan( 0 ) && E_C::OnlyTypes( connectedTypes );
154  auto sheetSelection = E_C::Count( 1 ) && E_C::OnlyType( SCH_SHEET_T );
155 
156  auto schEditSheetPageNumberCondition =
157  [this] ( const SELECTION& aSel )
158  {
159  return !m_isSymbolEditor
160  && !m_isSymbolViewer
161  && ( E_C::Empty || ( E_C::Count( 1 ) && E_C::OnlyType( SCH_SHEET_T ) ) );
162  };
163 
164  auto schEditCondition =
165  [this] ( const SELECTION& aSel )
166  {
168  };
169 
170  auto belowRootSheetCondition =
171  [&]( const SELECTION& aSel )
172  {
173  SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
174 
175  return editFrame
176  && editFrame->GetCurrentSheet().Last() != &editFrame->Schematic().Root();
177  };
178 
179  auto havePartCondition =
180  [&]( const SELECTION& sel )
181  {
182  return m_isSymbolEditor && static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->GetCurPart();
183  };
184 
185  auto& menu = m_menu.GetMenu();
186 
187  menu.AddItem( EE_ACTIONS::enterSheet, sheetSelection && EE_CONDITIONS::Idle, 1 );
188  menu.AddItem( EE_ACTIONS::explicitCrossProbe, sheetSelection && EE_CONDITIONS::Idle, 1 );
189  menu.AddItem( EE_ACTIONS::leaveSheet, belowRootSheetCondition, 1 );
190 
191  menu.AddSeparator( 100 );
192  menu.AddItem( EE_ACTIONS::drawWire, schEditCondition && EE_CONDITIONS::Empty, 100 );
193  menu.AddItem( EE_ACTIONS::drawBus, schEditCondition && EE_CONDITIONS::Empty, 100 );
194 
195  menu.AddSeparator( 100 );
197 
198  menu.AddSeparator( 100 );
200 
201  menu.AddSeparator( 200 );
202  menu.AddItem( EE_ACTIONS::selectConnection, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
203  menu.AddItem( EE_ACTIONS::placeJunction, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
204  menu.AddItem( EE_ACTIONS::placeLabel, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
205  menu.AddItem( EE_ACTIONS::placeGlobalLabel, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
206  menu.AddItem( EE_ACTIONS::placeHierLabel, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
207  menu.AddItem( EE_ACTIONS::breakWire, wireSelection && EE_CONDITIONS::Idle, 250 );
208  menu.AddItem( EE_ACTIONS::breakBus, busSelection && EE_CONDITIONS::Idle, 250 );
209  menu.AddItem( EE_ACTIONS::importSheetPin, sheetSelection && EE_CONDITIONS::Idle, 250 );
210  menu.AddItem( EE_ACTIONS::assignNetclass, connectedSelection && EE_CONDITIONS::Idle, 250 );
211  menu.AddItem( EE_ACTIONS::editPageNumber, schEditSheetPageNumberCondition, 250 );
212 
213  menu.AddSeparator( 400 );
214  menu.AddItem( EE_ACTIONS::symbolProperties, havePartCondition && EE_CONDITIONS::Empty, 400 );
215  menu.AddItem( EE_ACTIONS::pinTable, havePartCondition && EE_CONDITIONS::Empty, 400 );
216 
217  menu.AddSeparator( 1000 );
219 
220  return true;
221 }
222 
223 
225 {
226  m_frame = getEditFrame<SCH_BASE_FRAME>();
227 
228  if( aReason == TOOL_BASE::MODEL_RELOAD )
229  {
230  // Remove pointers to the selected items from containers without changing their
231  // properties (as they are already deleted while a new sheet is loaded)
232  m_selection.Clear();
233  getView()->GetPainter()->GetSettings()->SetHighlight( false );
234 
235  SYMBOL_EDIT_FRAME* symbolEditFrame = dynamic_cast<SYMBOL_EDIT_FRAME*>( m_frame );
236  SYMBOL_VIEWER_FRAME* symbolViewerFrame = dynamic_cast<SYMBOL_VIEWER_FRAME*>( m_frame );
237 
238  if( symbolEditFrame )
239  {
240  m_isSymbolEditor = true;
241  m_unit = symbolEditFrame->GetUnit();
242  m_convert = symbolEditFrame->GetConvert();
243  }
244  else
245  m_isSymbolViewer = symbolViewerFrame != nullptr;
246  }
247  else
248  // Restore previous properties of selected items and remove them from containers
249  ClearSelection();
250 
251  // Reinsert the VIEW_GROUP, in case it was removed from the VIEW
252  getView()->Remove( &m_selection );
253  getView()->Add( &m_selection );
254 }
255 
256 
258 {
259  ACTION_MENU* actionMenu = aEvent.Parameter<ACTION_MENU*>();
260  CONDITIONAL_MENU* conditionalMenu = dynamic_cast<CONDITIONAL_MENU*>( actionMenu );
261 
262  if( conditionalMenu )
263  conditionalMenu->Evaluate( m_selection );
264 
265  if( actionMenu )
266  actionMenu->UpdateAll();
267 
268  return 0;
269 }
270 
271 
273 {
274  SCH_MARKER_T,
279  SCH_LINE_T,
280  SCH_BITMAP_T,
281  SCH_TEXT_T,
282  SCH_LABEL_T,
285  SCH_FIELD_T,
288  SCH_SHEET_T,
289  EOT
290 };
291 
292 
294 {
295  LIB_ARC_T,
296  LIB_CIRCLE_T,
297  LIB_TEXT_T,
300  LIB_BEZIER_T,
301  LIB_PIN_T,
302  LIB_FIELD_T,
303  EOT
304 };
305 
306 
308 {
310 
311  KIID lastRolloverItem = niluuid;
312 
313  // Main loop: keep receiving events
314  while( TOOL_EVENT* evt = Wait() )
315  {
316  bool displayWireCursor = false;
317  KIID rolloverItem = lastRolloverItem;
319 
320  if( evt->Modifier( MD_SHIFT ) && evt->Modifier( MD_CTRL ) )
321  m_subtractive = true;
322  else if( evt->Modifier( MD_SHIFT ) )
323  m_additive = true;
324  else if( evt->Modifier( MD_CTRL ) )
325  m_exclusive_or = true;
326 
327  bool modifier_enabled = m_subtractive || m_additive || m_exclusive_or;
328  MOUSE_DRAG_ACTION drag_action = m_frame->GetDragAction();
329 
330  // Is the user requesting that the selection list include all possible
331  // items without removing less likely selection candidates
332  m_skip_heuristics = !!evt->Modifier( MD_ALT );
333 
334  EE_GRID_HELPER grid( m_toolMgr );
335 
336  // Single click? Select single object
337  if( evt->IsClick( BUT_LEFT ) )
338  {
339  if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
340  schframe->FocusOnItem( nullptr );
341 
342  EE_COLLECTOR collector;
343  bool continueSelect = true;
344 
345  // Collect items at the clicked location (doesn't select them yet)
346  if( CollectHits( collector, evt->Position()) )
347  {
348  narrowSelection( collector, evt->Position(), false );
349 
350  if( collector.GetCount() == 1 && !m_isSymbolEditor && !modifier_enabled )
351  {
352  // Check if we want to auto start wires
353  VECTOR2I snappedCursorPos = grid.BestSnapAnchor( evt->Position(),
354  LAYER_CONNECTABLE, nullptr );
355 
357  && collector[0]->IsPointClickableAnchor( (wxPoint) snappedCursorPos ) )
358  {
360  auto* params = newEvt->Parameter<DRAW_SEGMENT_EVENT_PARAMS*>();
361  auto* newParams = new DRAW_SEGMENT_EVENT_PARAMS();
362 
363  *newParams= *params;
364  newParams->quitOnDraw = true;
365  newEvt->SetParameter( newParams );
366 
367  newEvt->SetMousePosition( snappedCursorPos );
368  m_toolMgr->ProcessEvent( *newEvt );
369  continueSelect = false;
370  }
371  else if( collector[0]->IsHypertext() )
372  {
373  collector[0]->DoHypertextMenu( m_frame );
374  continueSelect = false;
375  }
376  }
377  }
378 
379  if( continueSelect )
380  {
381  // If we didn't click on an anchor, we perform a normal select, pass in the
382  // items we previously collected
383  selectPoint( collector, nullptr, nullptr, m_additive, m_subtractive,
384  m_exclusive_or );
385  }
386  }
387  else if( evt->IsClick( BUT_RIGHT ) )
388  {
389  // right click? if there is any object - show the context menu
390  bool selectionCancelled = false;
391 
392  if( m_selection.Empty() ||
393  !m_selection.GetBoundingBox().Contains( (wxPoint) evt->Position() ) )
394  {
395  ClearSelection();
396  SelectPoint( evt->Position(), EE_COLLECTOR::AllItems, nullptr,
397  &selectionCancelled );
398  m_selection.SetIsHover( true );
399  }
400 
401  if( !selectionCancelled )
403  }
404  else if( evt->IsDblClick( BUT_LEFT ) )
405  {
406  // double click? Display the properties window
407  if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
408  schframe->FocusOnItem( nullptr );
409 
410  if( m_selection.Empty() )
411  SelectPoint( evt->Position() );
412 
413  EDA_ITEM* item = m_selection.Front();
414 
415  if( item && item->Type() == SCH_SHEET_T )
417  else
419  }
420  else if( evt->IsDblClick( BUT_MIDDLE ) )
421  {
422  // Middle double click? Do zoom to fit or zoom to objects
423  if( m_exclusive_or ) // Is CTRL key down?
425  else
427  }
428  else if( evt->IsDrag( BUT_LEFT ) )
429  {
430  // drag with LMB? Select multiple objects (or at least draw a selection box) or
431  // drag them
432  if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
433  schframe->FocusOnItem( nullptr );
434 
435  if( modifier_enabled || drag_action == MOUSE_DRAG_ACTION::SELECT )
436  {
437  selectMultiple();
438  }
439  else if( m_selection.Empty() && drag_action != MOUSE_DRAG_ACTION::DRAG_ANY )
440  {
441  selectMultiple();
442  }
443  else
444  {
445  // selection is empty? try to start dragging the item under the point where drag
446  // started
449  else if( m_selection.Empty() )
451 
452  // Check if dragging has started within any of selected items bounding box
453  if( selectionContains( evt->Position() ) )
454  {
455  // Yes -> run the move tool and wait till it finishes
456  if( m_isSymbolEditor )
457  {
458  SYMBOL_EDIT_FRAME* libFrame = dynamic_cast<SYMBOL_EDIT_FRAME*>( m_frame );
459 
460  // Cannot move any derived symbol elements for now.
461  if( libFrame && libFrame->GetCurPart() && libFrame->GetCurPart()->IsRoot() )
462  m_toolMgr->InvokeTool( "eeschema.SymbolMoveTool" );
463  }
464  else
465  {
466  m_toolMgr->InvokeTool( "eeschema.InteractiveMove" );
467  }
468  }
469  else
470  {
471  // No -> drag a selection box
472  selectMultiple();
473  }
474  }
475  }
476  else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CHOICE_MENU_CHOICE )
477  {
478  // context sub-menu selection? Handle unit selection or bus unfolding
479  if( evt->GetCommandId().get() >= ID_POPUP_SCH_SELECT_UNIT_CMP
480  && evt->GetCommandId().get() <= ID_POPUP_SCH_SELECT_UNIT_CMP_MAX )
481  {
482  SCH_COMPONENT* component = dynamic_cast<SCH_COMPONENT*>( m_selection.Front() );
483  int unit = evt->GetCommandId().get() - ID_POPUP_SCH_SELECT_UNIT_CMP;
484 
485  if( component )
486  static_cast<SCH_EDIT_FRAME*>( m_frame )->SelectUnit( component, unit );
487  }
488  else if( evt->GetCommandId().get() >= ID_POPUP_SCH_UNFOLD_BUS
489  && evt->GetCommandId().get() <= ID_POPUP_SCH_UNFOLD_BUS_END )
490  {
491  wxString* net = new wxString( *evt->Parameter<wxString*>() );
493  }
494 
495  }
496  else if( evt->IsCancelInteractive() )
497  {
498  if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
499  schframe->FocusOnItem( nullptr );
500 
501  ClearSelection();
502  }
503  else if( evt->Action() == TA_UNDO_REDO_PRE )
504  {
505  if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
506  schframe->FocusOnItem( nullptr );
507 
508  ClearSelection();
509  }
510  else if( evt->IsMotion() && !m_isSymbolEditor && m_frame->ToolStackIsEmpty() )
511  {
512  rolloverItem = niluuid;
513  EE_COLLECTOR collector;
514 
515  // We are checking if we should display a pencil when hovering over anchors
516  // for "auto starting" wires when clicked
517  if( CollectHits( collector, evt->Position()) )
518  {
519  narrowSelection( collector, evt->Position(), false );
520 
521  if( collector.GetCount() == 1 && !modifier_enabled )
522  {
523  VECTOR2I snappedCursorPos = grid.BestSnapAnchor( evt->Position(),
524  LAYER_CONNECTABLE, nullptr );
525 
527  && collector[0]->IsPointClickableAnchor( (wxPoint) snappedCursorPos ) )
528  {
529  displayWireCursor = true;
530  }
531  else if( collector[0]->IsHypertext()
532  && !collector[0]->IsSelected()
534  {
535  rolloverItem = collector[0]->m_Uuid;
536  }
537  }
538  }
539  }
540  else
541  {
542  evt->SetPassEvent();
543  }
544 
545  if( rolloverItem != lastRolloverItem )
546  {
547  EDA_ITEM* item = m_frame->GetItem( lastRolloverItem );
548 
549  if( item )
550  {
551  item->ClearFlags( IS_ROLLOVER );
552  lastRolloverItem = niluuid;
553 
554  if( item->Type() == SCH_FIELD_T )
555  m_frame->GetCanvas()->GetView()->Update( item->GetParent() );
556  else
557  m_frame->GetCanvas()->GetView()->Update( item );
558  }
559 
560  item = m_frame->GetItem( rolloverItem );
561 
562  if( item )
563  {
564  item->SetFlags( IS_ROLLOVER );
565  lastRolloverItem = rolloverItem;
566 
567  if( item->Type() == SCH_FIELD_T )
568  m_frame->GetCanvas()->GetView()->Update( item->GetParent() );
569  else
570  m_frame->GetCanvas()->GetView()->Update( item );
571  }
572  }
573 
574  if( m_frame->ToolStackIsEmpty() )
575  {
576  if( displayWireCursor )
577  {
579  }
580  else if( rolloverItem != niluuid )
581  {
583  }
584  else if( !m_selection.Empty()
585  && drag_action == MOUSE_DRAG_ACTION::DRAG_SELECTED
586  && evt->HasPosition()
587  && selectionContains( evt->Position() ) ) //move/drag option prediction
588  {
590  }
591  else
592  {
594  }
595  }
596  }
597 
598  // Shutting down; clear the selection
599  m_selection.Clear();
600 
601  return 0;
602 }
603 
604 
605 void EE_SELECTION_TOOL::OnIdle( wxIdleEvent& aEvent )
606 {
607  if( m_frame->ToolStackIsEmpty() && !m_multiple )
608  {
609  wxMouseState keyboardState = wxGetMouseState();
610 
612 
613  if( keyboardState.ShiftDown() && keyboardState.ControlDown() )
614  m_subtractive = true;
615  else if( keyboardState.ShiftDown() )
616  m_additive = true;
617  else if( keyboardState.ControlDown() )
618  m_exclusive_or = true;
619 
620  if( m_additive )
622  else if( m_subtractive )
624  else if( m_exclusive_or )
626  else
628  }
629 }
630 
631 
633 {
634  return m_selection;
635 }
636 
637 
638 bool EE_SELECTION_TOOL::CollectHits( EE_COLLECTOR& aCollector, const VECTOR2I& aWhere,
639  const KICAD_T* aFilterList )
640 {
641  aCollector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
642 
643  if( m_isSymbolEditor )
644  {
645  LIB_PART* part = static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->GetCurPart();
646 
647  if( !part )
648  return false;
649 
650  aCollector.Collect( part->GetDrawItems(), aFilterList, (wxPoint) aWhere, m_unit,
651  m_convert );
652  }
653  else
654  {
655  aCollector.Collect( m_frame->GetScreen(), aFilterList, (wxPoint) aWhere, m_unit,
656  m_convert );
657  }
658 
659  return aCollector.GetCount() > 0;
660 }
661 
662 
664  bool aCheckLocked )
665 {
666  for( int i = collector.GetCount() - 1; i >= 0; --i )
667  {
668  if( !Selectable( collector[i] ) )
669  {
670  collector.Remove( i );
671  continue;
672  }
673 
674  if( aCheckLocked && collector[i]->IsLocked() )
675  {
676  collector.Remove( i );
677  continue;
678  }
679 
680  // SelectPoint, unlike other selection routines, can select line ends
681  if( collector[i]->Type() == SCH_LINE_T )
682  {
683  SCH_LINE* line = (SCH_LINE*) collector[i];
684  line->ClearFlags( STARTPOINT | ENDPOINT );
685 
686  if( HitTestPoints( line->GetStartPoint(), (wxPoint) aWhere, collector.m_Threshold ) )
687  line->SetFlags( STARTPOINT );
688  else if( HitTestPoints( line->GetEndPoint(), (wxPoint) aWhere, collector.m_Threshold ) )
689  line->SetFlags( ENDPOINT );
690  else
691  line->SetFlags( STARTPOINT | ENDPOINT );
692  }
693  }
694 
695  // Apply some ugly heuristics to avoid disambiguation menus whenever possible
696  if( collector.GetCount() > 1 && !m_skip_heuristics )
697  {
698  GuessSelectionCandidates( collector, aWhere );
699  }
700 }
701 
702 
704  bool* aSelectionCancelledFlag, bool aAdd, bool aSubtract,
705  bool aExclusiveOr )
706 {
708 
709  // If still more than one item we're going to have to ask the user.
710  if( aCollector.GetCount() > 1 )
711  {
712  // Must call selectionMenu via RunAction() to avoid event-loop contention
713  m_toolMgr->RunAction( EE_ACTIONS::selectionMenu, true, &aCollector );
714 
715  if( aCollector.m_MenuCancelled )
716  {
717  if( aSelectionCancelledFlag )
718  *aSelectionCancelledFlag = true;
719 
720  return false;
721  }
722  }
723 
724  if( !aAdd && !aSubtract && !aExclusiveOr )
725  ClearSelection();
726 
727  bool anyAdded = false;
728  bool anySubtracted = false;
729 
730  if( aCollector.GetCount() > 0 )
731  {
732  for( int i = 0; i < aCollector.GetCount(); ++i )
733  {
734  if( aSubtract || ( aExclusiveOr && aCollector[i]->IsSelected() ) )
735  {
736  unselect( aCollector[i] );
737  anySubtracted = true;
738  }
739  else
740  {
741  select( aCollector[i] );
742  anyAdded = true;
743  }
744  }
745  }
746 
747  if( anyAdded )
748  {
750 
751  if( aItem && aCollector.GetCount() == 1 )
752  *aItem = aCollector[0];
753 
754  return true;
755  }
756  else if( anySubtracted )
757  {
759  return true;
760  }
761 
762  return false;
763 }
764 
765 
766 bool EE_SELECTION_TOOL::SelectPoint( const VECTOR2I& aWhere, const KICAD_T* aFilterList,
767  EDA_ITEM** aItem, bool* aSelectionCancelledFlag,
768  bool aCheckLocked, bool aAdd, bool aSubtract,
769  bool aExclusiveOr )
770 {
771  EE_COLLECTOR collector;
772 
773  if( !CollectHits( collector, aWhere, aFilterList ) )
774  return false;
775 
776  narrowSelection( collector, aWhere, aCheckLocked );
777 
778  return selectPoint( collector, aItem, aSelectionCancelledFlag, aAdd, aSubtract, aExclusiveOr );
779 }
780 
781 
783 {
784  m_multiple = true; // Multiple selection mode is active
785  KIGFX::VIEW* view = getView();
786 
787  // hold all visible items
788  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
789  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> sheetPins;
790 
791  // Filter the view items based on the selection box
792  BOX2I selectionBox;
793 
794  selectionBox.SetMaximum();
795  view->Query( selectionBox, selectedItems ); // Get the list of selected items
796 
797  // Sheet pins aren't in the view; add them by hand
798  for( KIGFX::VIEW::LAYER_ITEM_PAIR& pair : selectedItems )
799  {
800  SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( pair.first );
801 
802  if( sheet )
803  {
804  int layer = pair.second;
805 
806  for( SCH_SHEET_PIN* pin : sheet->GetPins() )
807  sheetPins.emplace_back( KIGFX::VIEW::LAYER_ITEM_PAIR( pin, layer ) );
808  }
809  }
810 
811  selectedItems.insert( selectedItems.end(), sheetPins.begin(), sheetPins.end() );
812 
813  for( const std::pair<KIGFX::VIEW_ITEM*, int>& item_pair : selectedItems )
814  {
815  if( EDA_ITEM* item = dynamic_cast<EDA_ITEM*>( item_pair.first ) )
816  {
817  if( Selectable( item ) )
818  select( item );
819  }
820  }
821 
822  m_multiple = false;
823 
824  return 0;
825 }
826 
827 
829 {
830  // There are certain parent/child and enclosure combinations that can be handled
831  // automatically.
832 
833  // Prefer exact hits to sloppy ones
834  int exactHits = 0;
835 
836  for( int i = collector.GetCount() - 1; i >= 0; --i )
837  {
838  EDA_ITEM* item = collector[ i ];
839 
840  if( item->HitTest( (wxPoint) aPos, 0 ) )
841  exactHits++;
842  }
843 
844  if( exactHits > 0 && exactHits < collector.GetCount() )
845  {
846  for( int i = collector.GetCount() - 1; i >= 0; --i )
847  {
848  EDA_ITEM* item = collector[ i ];
849 
850  if( !item->HitTest( (wxPoint) aPos, 0 ) )
851  collector.Transfer( item );
852  }
853  }
854 
855  // Prefer a non-sheet to a sheet
856  for( int i = 0; collector.GetCount() == 2 && i < 2; ++i )
857  {
858  EDA_ITEM* item = collector[ i ];
859  EDA_ITEM* other = collector[ ( i + 1 ) % 2 ];
860 
861  if( item->Type() != SCH_SHEET_T && other->Type() == SCH_SHEET_T )
862  collector.Transfer( other );
863  }
864 
865  // Prefer a symbol to a pin or the opposite, when both a symbol and a pin are selected
866  // We need to be able to select only a pin:
867  // - to display its characteristics (especially if an ERC is attached to the pin)
868  // - for cross probing, to select the corresponding pad.
869  // Note also the case happens only in schematic editor. In symbol editor, the symbol
870  // itself is never selected
871  for( int i = 0; collector.GetCount() == 2 && i < 2; ++i )
872  {
873  SCH_ITEM* item = collector[i];
874  SCH_ITEM* other = collector[( i + 1 ) % 2];
875 
876  if( item->Type() == SCH_COMPONENT_T && other->Type() == SCH_PIN_T )
877  {
878  // Make sure we aren't clicking on the pin anchor itself, only the rest of the
879  // pin should select the symbol with this setting
880  // To avoid conflict with the auto-start wires option
881  EE_GRID_HELPER grid( m_toolMgr );
882  wxPoint cursorPos = wxPoint( grid.BestSnapAnchor( aPos, LAYER_CONNECTABLE,
883  nullptr ) );
884 
885  if( !m_isSymbolEditor
887  && !other->IsPointClickableAnchor( cursorPos ) )
888  {
889  collector.Transfer( other );
890  }
891  else
892  {
893  collector.Transfer( item );
894  }
895  }
896  }
897 
898  // Prefer a field to a symbol
899  for( int i = 0; collector.GetCount() == 2 && i < 2; ++i )
900  {
901  EDA_ITEM* item = collector[ i ];
902  EDA_ITEM* other = collector[ ( i + 1 ) % 2 ];
903 
904  if( item->Type() == SCH_FIELD_T && other->Type() == SCH_COMPONENT_T )
905  collector.Transfer( other );
906  }
907 
908  // No need for multiple wires at a single point; if there's a junction select that;
909  // otherwise any of the wires will do
910  bool junction = false;
911  bool wiresOnly = true;
912 
913  for( EDA_ITEM* item : collector )
914  {
915  if( item->Type() == SCH_JUNCTION_T )
916  junction = true;
917  else if( item->Type() != SCH_LINE_T )
918  wiresOnly = false;
919  }
920 
921  if( wiresOnly )
922  {
923  for( int j = collector.GetCount() - 1; j >= 0; --j )
924  {
925  if( junction && collector[ j ]->Type() != SCH_JUNCTION_T )
926  collector.Transfer( j );
927  else if( !junction && j > 0 )
928  collector.Transfer( j );
929  }
930  }
931 
932  // Construct a tight box (1/2 height and width) around the center of the closest item.
933  // All items which exist at least partly outside this box have sufficient other areas
934  // for selection and can be dropped.
935  EDA_ITEM* closest = nullptr;
936  int closestDist = INT_MAX;
937 
938  for( EDA_ITEM* item : collector )
939  {
940  int dist = EuclideanNorm( item->GetBoundingBox().GetCenter() - (wxPoint) aPos );
941 
942  if( dist < closestDist )
943  {
944  closestDist = dist;
945  closest = item;
946  }
947  }
948 
949  if( closest ) // Don't try and get a tight bbox if nothing is near the mouse pointer
950  {
951  EDA_RECT tightBox = closest->GetBoundingBox();
952  tightBox.Inflate( -tightBox.GetWidth() / 4, -tightBox.GetHeight() / 4 );
953 
954  for( int i = collector.GetCount() - 1; i >= 0; --i )
955  {
956  EDA_ITEM* item = collector[i];
957 
958  if( item == closest )
959  continue;
960 
961  if( !item->HitTest( tightBox, true ) )
962  collector.Transfer( item );
963  }
964  }
965 }
966 
967 
969 {
970  if( m_selection.Empty() )
971  {
972  VECTOR2D cursorPos = getViewControls()->GetCursorPosition( true );
973 
974  ClearSelection();
975  SelectPoint( cursorPos, aFilterList );
976  m_selection.SetIsHover( true );
978  }
979  else // Trim an existing selection by aFilterList
980  {
981  for( int i = (int) m_selection.GetSize() - 1; i >= 0; --i )
982  {
983  EDA_ITEM* item = (EDA_ITEM*) m_selection.GetItem( i );
984 
985  if( !item->IsType( aFilterList ) )
986  {
987  unselect( item );
989  }
990  }
991  }
992 
994 
995  return m_selection;
996 }
997 
998 
1000 {
1001  VECTOR2I refP( 0, 0 );
1002 
1003  if( m_selection.Size() > 0 )
1004  {
1005  if( m_isSymbolEditor )
1006  refP = static_cast<LIB_ITEM*>( m_selection.GetTopLeftItem() )->GetPosition();
1007  else
1008  refP = static_cast<SCH_ITEM*>( m_selection.GetTopLeftItem() )->GetPosition();
1009  }
1010 
1012 }
1013 
1014 
1016 {
1017  bool cancelled = false; // Was the tool canceled while it was running?
1018  m_multiple = true; // Multiple selection mode is active
1019  KIGFX::VIEW* view = getView();
1020 
1022  view->Add( &area );
1023 
1024  while( TOOL_EVENT* evt = Wait() )
1025  {
1026  int width = area.GetEnd().x - area.GetOrigin().x;
1027 
1028  /* Selection mode depends on direction of drag-selection:
1029  * Left > Right : Select objects that are fully enclosed by selection
1030  * Right > Left : Select objects that are crossed by selection
1031  */
1032  bool windowSelection = width >= 0;
1033 
1034  if( view->IsMirroredX() )
1035  windowSelection = !windowSelection;
1036 
1038  windowSelection ? KICURSOR::SELECT_WINDOW : KICURSOR::SELECT_LASSO );
1039 
1040  if( evt->IsCancelInteractive() || evt->IsActivate() )
1041  {
1042  cancelled = true;
1043  break;
1044  }
1045 
1046  if( evt->IsDrag( BUT_LEFT ) )
1047  {
1048  if( !m_additive && !m_subtractive && !m_exclusive_or )
1049  ClearSelection();
1050 
1051  // Start drawing a selection box
1052  area.SetOrigin( evt->DragOrigin() );
1053  area.SetEnd( evt->Position() );
1054  area.SetAdditive( m_additive );
1055  area.SetSubtractive( m_subtractive );
1057 
1058  view->SetVisible( &area, true );
1059  view->Update( &area );
1060  getViewControls()->SetAutoPan( true );
1061  }
1062 
1063  if( evt->IsMouseUp( BUT_LEFT ) )
1064  {
1065  getViewControls()->SetAutoPan( false );
1066 
1067  // End drawing the selection box
1068  view->SetVisible( &area, false );
1069 
1070  // Mark items within the selection box as selected
1071  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
1072  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> sheetPins;
1073 
1074  // Filter the view items based on the selection box
1075  BOX2I selectionBox = area.ViewBBox();
1076  view->Query( selectionBox, selectedItems ); // Get the list of selected items
1077 
1078  // Sheet pins aren't in the view; add them by hand
1079  for( KIGFX::VIEW::LAYER_ITEM_PAIR& pair : selectedItems )
1080  {
1081  SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( pair.first );
1082 
1083  if( sheet )
1084  {
1085  int layer = pair.second;
1086 
1087  for( SCH_SHEET_PIN* pin : sheet->GetPins() )
1088  sheetPins.emplace_back( KIGFX::VIEW::LAYER_ITEM_PAIR( pin, layer ) );
1089  }
1090  }
1091 
1092  selectedItems.insert( selectedItems.end(), sheetPins.begin(), sheetPins.end() );
1093 
1094  int height = area.GetEnd().y - area.GetOrigin().y;
1095 
1096  bool anyAdded = false;
1097  bool anySubtracted = false;
1098 
1099  // Construct an EDA_RECT to determine EDA_ITEM selection
1100  EDA_RECT selectionRect( (wxPoint) area.GetOrigin(), wxSize( width, height ) );
1101 
1102  selectionRect.Normalize();
1103 
1104  for( KIGFX::VIEW::LAYER_ITEM_PAIR& pair : selectedItems )
1105  {
1106  EDA_ITEM* item = dynamic_cast<EDA_ITEM*>( pair.first );
1107 
1108  if( item && Selectable( item ) && item->HitTest( selectionRect, windowSelection ) )
1109  {
1110  if( m_subtractive || ( m_exclusive_or && item->IsSelected() ) )
1111  {
1112  unselect( item );
1113  anySubtracted = true;
1114  }
1115  else
1116  {
1117  select( item );
1118  item->SetFlags( STARTPOINT | ENDPOINT );
1119  anyAdded = true;
1120  }
1121  }
1122  }
1123 
1124  m_selection.SetIsHover( false );
1125 
1126  // Inform other potentially interested tools
1127  if( anyAdded )
1129 
1130  if( anySubtracted )
1132 
1133  break; // Stop waiting for events
1134  }
1135  }
1136 
1137  getViewControls()->SetAutoPan( false );
1138 
1139  // Stop drawing the selection box
1140  view->Remove( &area );
1141  m_multiple = false; // Multiple selection mode is inactive
1142 
1143  if( !cancelled )
1145 
1146  return cancelled;
1147 }
1148 
1149 
1150 static KICAD_T nodeTypes[] =
1151 {
1153  SCH_PIN_T,
1158  SCH_LABEL_T,
1163  EOT
1164 };
1165 
1166 
1168 {
1169  EE_COLLECTOR collector;
1170 
1171  //TODO(snh): Reimplement after exposing KNN interface
1172  int thresholdMax = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
1173 
1174  for( int threshold : { 0, thresholdMax/2, thresholdMax } )
1175  {
1176  collector.m_Threshold = threshold;
1177  collector.Collect( m_frame->GetScreen(), nodeTypes, (wxPoint) aPosition );
1178 
1179  if( collector.GetCount() > 0 )
1180  break;
1181  }
1182 
1183  return collector.GetCount() ? collector[ 0 ] : nullptr;
1184 }
1185 
1186 
1188 {
1189  VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !aEvent.Modifier( MD_ALT ) );
1190 
1191  SelectPoint( cursorPos, nodeTypes );
1192 
1193  return 0;
1194 }
1195 
1196 
1198 {
1199  static KICAD_T wiresAndBuses[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT };
1200 
1201  RequestSelection( wiresAndBuses );
1202 
1203  if( m_selection.Empty() )
1204  return 0;
1205 
1206  SCH_LINE* line = (SCH_LINE*) m_selection.Front();
1207  EDA_ITEMS items;
1208 
1210  std::set<SCH_ITEM*> conns = m_frame->GetScreen()->MarkConnections( line );
1211 
1212  for( SCH_ITEM* item : conns )
1213  select( item );
1214 
1215  if( m_selection.GetSize() > 1 )
1217 
1218  return 0;
1219 }
1220 
1221 
1223 {
1224  AddItemToSel( aEvent.Parameter<EDA_ITEM*>() );
1225  m_selection.SetIsHover( false );
1226  return 0;
1227 }
1228 
1229 
1230 void EE_SELECTION_TOOL::AddItemToSel( EDA_ITEM* aItem, bool aQuietMode )
1231 {
1232  if( aItem )
1233  {
1234  select( aItem );
1235 
1236  // Inform other potentially interested tools
1237  if( !aQuietMode )
1239  }
1240 }
1241 
1242 
1244 {
1245  AddItemsToSel( aEvent.Parameter<EDA_ITEMS*>(), false );
1246  m_selection.SetIsHover( false );
1247  return 0;
1248 }
1249 
1250 
1251 void EE_SELECTION_TOOL::AddItemsToSel( EDA_ITEMS* aList, bool aQuietMode )
1252 {
1253  if( aList )
1254  {
1255  for( EDA_ITEM* item : *aList )
1256  select( item );
1257 
1258  // Inform other potentially interested tools
1259  if( !aQuietMode )
1261  }
1262 }
1263 
1264 
1266 {
1267  RemoveItemFromSel( aEvent.Parameter<EDA_ITEM*>() );
1268  m_selection.SetIsHover( false );
1269  return 0;
1270 }
1271 
1272 
1273 void EE_SELECTION_TOOL::RemoveItemFromSel( EDA_ITEM* aItem, bool aQuietMode )
1274 {
1275  if( aItem )
1276  {
1277  unselect( aItem );
1278 
1279  // Inform other potentially interested tools
1280  if( !aQuietMode )
1282  }
1283 }
1284 
1285 
1287 {
1288  RemoveItemsFromSel( aEvent.Parameter<EDA_ITEMS*>(), false );
1289  m_selection.SetIsHover( false );
1290  return 0;
1291 }
1292 
1293 
1294 void EE_SELECTION_TOOL::RemoveItemsFromSel( EDA_ITEMS* aList, bool aQuietMode )
1295 {
1296  if( aList )
1297  {
1298  for( EDA_ITEM* item : *aList )
1299  unselect( item );
1300 
1301  // Inform other potentially interested tools
1302  if( !aQuietMode )
1304  }
1305 }
1306 
1307 
1309 {
1310  highlight( aItem, BRIGHTENED );
1311 }
1312 
1313 
1315 {
1316  unhighlight( aItem, BRIGHTENED );
1317 }
1318 
1319 
1321 {
1322  ClearSelection();
1323 
1324  return 0;
1325 }
1326 
1327 
1329 {
1330  m_selection.Clear();
1331 
1332  if( m_isSymbolEditor )
1333  {
1334  LIB_PART* start = static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->GetCurPart();
1335 
1336  for( LIB_ITEM& item : start->GetDrawItems() )
1337  {
1338  if( item.IsSelected() )
1339  select( static_cast<EDA_ITEM*>( &item ) );
1340  }
1341  }
1342  else
1343  {
1344  for( SCH_ITEM* item : m_frame->GetScreen()->Items() )
1345  {
1346  // If the field and component are selected, only use the component
1347  if( item->IsSelected() )
1348  {
1349  select( item );
1350  }
1351  else
1352  {
1353  item->RunOnChildren(
1354  [&]( SCH_ITEM* aChild )
1355  {
1356  if( aChild->IsSelected() )
1357  select( aChild );
1358  } );
1359  }
1360  }
1361  }
1362 
1364 
1365  // Inform other potentially interested tools
1367 }
1368 
1369 
1371 {
1372  EE_COLLECTOR* collector = aEvent.Parameter<EE_COLLECTOR*>();
1373 
1374  if( !doSelectionMenu( collector ) )
1375  collector->m_MenuCancelled = true;
1376 
1377  return 0;
1378 }
1379 
1380 
1382 {
1383  EDA_ITEM* current = nullptr;
1384  bool selectAll = false;
1385  bool expandSelection = false;
1386 
1387  do
1388  {
1390  if( expandSelection )
1391  aCollector->Combine();
1392 
1393  expandSelection = false;
1394 
1395  int limit = std::min( 9, aCollector->GetCount() );
1396  ACTION_MENU menu( true );
1397 
1398  for( int i = 0; i < limit; ++i )
1399  {
1400  wxString text;
1401  EDA_ITEM* item = ( *aCollector )[i];
1402  text = item->GetSelectMenuText( m_frame->GetUserUnits() );
1403 
1404  wxString menuText = wxString::Format( "&%d. %s\t%d", i + 1, text, i + 1 );
1405  menu.Add( menuText, i + 1, item->GetMenuImage() );
1406  }
1407 
1408  menu.AppendSeparator();
1409  menu.Add( _( "Select &All\tA" ), limit + 1, nullptr );
1410 
1411  if( !expandSelection && aCollector->HasAdditionalItems() )
1412  menu.Add( _( "&Expand Selection\tE" ), limit + 2, nullptr );
1413 
1414  if( aCollector->m_MenuTitle.Length() )
1415  {
1416  menu.SetTitle( aCollector->m_MenuTitle );
1417  menu.SetIcon( info_xpm );
1418  menu.DisplayTitle( true );
1419  }
1420  else
1421  {
1422  menu.DisplayTitle( false );
1423  }
1424 
1425  SetContextMenu( &menu, CMENU_NOW );
1426 
1427  while( TOOL_EVENT* evt = Wait() )
1428  {
1429  if( evt->Action() == TA_CHOICE_MENU_UPDATE )
1430  {
1431  if( selectAll )
1432  {
1433  for( int i = 0; i < aCollector->GetCount(); ++i )
1434  unhighlight( ( *aCollector )[i], BRIGHTENED );
1435  }
1436  else if( current )
1437  {
1438  unhighlight( current, BRIGHTENED );
1439  }
1440 
1441  int id = *evt->GetCommandId();
1442 
1443  // User has pointed an item, so show it in a different way
1444  if( id > 0 && id <= limit )
1445  {
1446  current = ( *aCollector )[id - 1];
1447  highlight( current, BRIGHTENED );
1448  }
1449  else
1450  {
1451  current = nullptr;
1452  }
1453 
1454  // User has pointed on the "Select All" option
1455  if( id == limit + 1 )
1456  {
1457  for( int i = 0; i < aCollector->GetCount(); ++i )
1458  highlight( ( *aCollector )[i], BRIGHTENED );
1459  selectAll = true;
1460  }
1461  else
1462  {
1463  selectAll = false;
1464  }
1465  }
1466  else if( evt->Action() == TA_CHOICE_MENU_CHOICE )
1467  {
1468  if( selectAll )
1469  {
1470  for( int i = 0; i < aCollector->GetCount(); ++i )
1471  unhighlight( ( *aCollector )[i], BRIGHTENED );
1472  }
1473  else if( current )
1474  unhighlight( current, BRIGHTENED );
1475 
1476  OPT<int> id = evt->GetCommandId();
1477 
1478  // User has selected the "Select All" option
1479  if( id == limit + 1 )
1480  {
1481  selectAll = true;
1482  current = nullptr;
1483  }
1484  // User has selected an item, so this one will be returned
1485  else if( id && ( *id > 0 ) && ( *id <= limit ) )
1486  {
1487  selectAll = false;
1488  current = ( *aCollector )[*id - 1];
1489  }
1490  else
1491  {
1492  selectAll = false;
1493  current = nullptr;
1494  }
1495  }
1496  else if( evt->Action() == TA_CHOICE_MENU_CLOSED )
1497  {
1498  break;
1499  }
1500 
1501  getView()->UpdateItems();
1502  m_frame->GetCanvas()->Refresh();
1503  }
1504  } while( expandSelection );
1505 
1506  if( selectAll )
1507  return true;
1508  else if( current )
1509  {
1510  unhighlight( current, BRIGHTENED );
1511 
1512  getView()->UpdateItems();
1513  m_frame->GetCanvas()->Refresh();
1514 
1515  aCollector->Empty();
1516  aCollector->Append( current );
1517  return true;
1518  }
1519 
1520  return false;
1521 }
1522 
1523 
1524 bool EE_SELECTION_TOOL::Selectable( const EDA_ITEM* aItem, bool checkVisibilityOnly ) const
1525 {
1526  // NOTE: in the future this is where Eeschema layer/itemtype visibility will be handled
1527  SYMBOL_EDIT_FRAME* symEditFrame = dynamic_cast< SYMBOL_EDIT_FRAME* >( m_frame );
1528 
1529  // Do not allow selection of anything except fields when the current symbol in the symbol
1530  // editor is a derived symbol.
1531  if( symEditFrame && symEditFrame->GetCurPart() && symEditFrame->GetCurPart()->IsAlias()
1532  && aItem->Type() != LIB_FIELD_T )
1533  return false;
1534 
1535  switch( aItem->Type() )
1536  {
1537  case SCH_PIN_T:
1538  if( !static_cast<const SCH_PIN*>( aItem )->IsVisible() && !m_frame->GetShowAllPins() )
1539  return false;
1540  break;
1541 
1542  case LIB_PART_T: // In symbol_editor we do not want to select the symbol itself.
1543  return false;
1544 
1545  case LIB_FIELD_T: // LIB_FIELD object can always be edited.
1546  break;
1547 
1548  case LIB_ARC_T:
1549  case LIB_CIRCLE_T:
1550  case LIB_TEXT_T:
1551  case LIB_RECTANGLE_T:
1552  case LIB_POLYLINE_T:
1553  case LIB_BEZIER_T:
1554  case LIB_PIN_T:
1555  {
1556  if( symEditFrame )
1557  {
1558  LIB_ITEM* lib_item = (LIB_ITEM*) aItem;
1559 
1560  if( lib_item->GetUnit() && lib_item->GetUnit() != symEditFrame->GetUnit() )
1561  return false;
1562 
1563  if( lib_item->GetConvert() && lib_item->GetConvert() != symEditFrame->GetConvert() )
1564  return false;
1565  }
1566 
1567  break;
1568  }
1569 
1570  case SCH_MARKER_T: // Always selectable
1571  return true;
1572 
1573  default: // Suppress warnings
1574  break;
1575  }
1576 
1577  return true;
1578 }
1579 
1580 
1582 {
1583  if( m_selection.Empty() )
1584  return;
1585 
1586  while( m_selection.GetSize() )
1588 
1589  getView()->Update( &m_selection );
1590 
1591  m_selection.SetIsHover( false );
1593 
1594  // Inform other potentially interested tools
1596 }
1597 
1598 
1600 {
1601  highlight( aItem, SELECTED, &m_selection );
1602 }
1603 
1604 
1606 {
1607  unhighlight( aItem, SELECTED, &m_selection );
1608 }
1609 
1610 
1611 void EE_SELECTION_TOOL::highlight( EDA_ITEM* aItem, int aMode, EE_SELECTION* aGroup )
1612 {
1613  KICAD_T itemType = aItem->Type();
1614 
1615  if( aMode == SELECTED )
1616  aItem->SetSelected();
1617  else if( aMode == BRIGHTENED )
1618  aItem->SetBrightened();
1619 
1620  if( aGroup )
1621  aGroup->Add( aItem );
1622 
1623  // Highlight pins and fields. (All the other component children are currently only
1624  // represented in the LIB_PART and will inherit the settings of the parent component.)
1625  if( SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( aItem ) )
1626  {
1627  sch_item->RunOnChildren(
1628  [&]( SCH_ITEM* aChild )
1629  {
1630  if( aMode == SELECTED )
1631  aChild->SetSelected();
1632  else if( aMode == BRIGHTENED )
1633  aChild->SetBrightened();
1634  } );
1635  }
1636 
1637  if( itemType == SCH_PIN_T || itemType == SCH_FIELD_T || itemType == SCH_SHEET_PIN_T )
1638  getView()->Update( aItem->GetParent() );
1639  else
1640  getView()->Update( aItem );
1641 }
1642 
1643 
1644 void EE_SELECTION_TOOL::unhighlight( EDA_ITEM* aItem, int aMode, EE_SELECTION* aGroup )
1645 {
1646  KICAD_T itemType = aItem->Type();
1647 
1648  if( aMode == SELECTED )
1649  aItem->ClearSelected();
1650  else if( aMode == BRIGHTENED )
1651  aItem->ClearBrightened();
1652 
1653  if( aGroup )
1654  aGroup->Remove( aItem );
1655 
1656  // Unhighlight pins and fields. (All the other component children are currently only
1657  // represented in the LIB_PART.)
1658  if( SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( aItem ) )
1659  {
1660  sch_item->RunOnChildren(
1661  [&]( SCH_ITEM* aChild )
1662  {
1663  if( aMode == SELECTED )
1664  aChild->ClearSelected();
1665  else if( aMode == BRIGHTENED )
1666  aChild->ClearBrightened();
1667  } );
1668  }
1669 
1670  if( itemType == SCH_PIN_T || itemType == SCH_FIELD_T || itemType == SCH_SHEET_PIN_T )
1671  getView()->Update( aItem->GetParent() );
1672  else
1673  getView()->Update( aItem );
1674 }
1675 
1676 
1678 {
1679  const unsigned GRIP_MARGIN = 20;
1680  VECTOR2I margin = getView()->ToWorld( VECTOR2I( GRIP_MARGIN, GRIP_MARGIN ), false );
1681 
1682  // Check if the point is located within any of the currently selected items bounding boxes
1683  for( EDA_ITEM* item : m_selection )
1684  {
1685  BOX2I itemBox = item->ViewBBox();
1686  itemBox.Inflate( margin.x, margin.y ); // Give some margin for gripping an item
1687 
1688  if( itemBox.Contains( aPoint ) )
1689  return true;
1690  }
1691 
1692  return false;
1693 }
1694 
1695 
1697 {
1699 
1704 
1710 
1712 }
1713 
1714 
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:134
void Empty()
Clear the list.
Definition: collector.h:95
static TOOL_ACTION editPageNumber
Definition: ee_actions.h:155
void ClearReferencePoint()
Definition: selection.h:269
static TOOL_ACTION pinTable
Definition: ee_actions.h:146
KIGFX::SCH_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
static TOOL_ACTION properties
Definition: ee_actions.h:121
void AddStandardSubMenus(TOOL_MENU &aMenu)
Construct a "basic" menu for a tool, containing only items that apply to all tools (e....
virtual EDA_ITEM * GetItem(const KIID &aId)
Fetch an item by KIID.
void OnIdle(wxIdleEvent &aEvent)
static const TOOL_EVENT SelectedEvent
Definition: actions.h:211
void SetEnd(VECTOR2I aEnd)
Set the current end of the rectangle (the corner that moves with the cursor.
TOOL_MENU m_menu
The functions below are not yet implemented - their interface may change.
bool selectionContains(const VECTOR2I &aPoint) const
Function selectionContains()
int m_Threshold
Definition: collector.h:248
int UpdateMenu(const TOOL_EVENT &aEvent)
virtual void Clear() override
Remove all the stored items from the group.
Definition: selection.h:96
KIID niluuid(0)
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))
Suspend execution of the tool until an event specified in aEventList arrives.
static TOOL_ACTION breakBus
Definition: ee_actions.h:135
static SELECTION_CONDITION SingleSymbol
wxPoint GetStartPoint() const
Definition: sch_line.h:94
bool IsSelected() const
Definition: eda_item.h:171
Model changes (required full reload)
Definition: tool_base.h:81
static const TOOL_EVENT UnselectedEvent
Definition: actions.h:212
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:45
VECTOR2D ToWorld(const VECTOR2D &aCoord, bool aAbsolute=true) const
Converts a screen space point/vector to a point/vector in world space coordinates.
Definition: view.cpp:456
void SetOrigin(VECTOR2I aOrigin)
Set the origin of the rectange (the fixed corner)
void ClearSelected()
Definition: eda_item.h:180
static SELECTION_CONDITION MoreThan(int aNumber)
Create a functor that tests if the number of selected items is greater than the value given as parame...
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.
EDA_RECT GetBoundingBox() const override
static TOOL_ACTION addItemsToSel
Selects a list of items (specified as the event parameter)
Definition: ee_actions.h:63
static bool Idle(const SELECTION &aSelection)
Test if there no items selected or being edited.
static SELECTION_CONDITION OnlyTypes(const KICAD_T aTypes[])
Create a functor that tests if the selected items are only of given types.
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:46
static TOOL_ACTION placeHierLabel
Definition: ee_actions.h:87
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:215
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)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:357
int GetWidth() const
Definition: eda_rect.h:114
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: eda_item.h:178
static TOOL_ACTION zoomFitScreen
Definition: actions.h:99
#define HITTEST_THRESHOLD_PIXELS
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:141
VECTOR2I BestSnapAnchor(const VECTOR2I &aOrigin, int aLayer, SCH_ITEM *aDraggedItem)
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.
Symbol library viewer main window.
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.
#define IS_ROLLOVER
Rollover active. Used for hyperlink highlighting.
Definition: eda_item.h:128
void UpdateAll()
Run update handlers for the menu and its submenus.
KICURSOR
Definition: cursors.h:33
static TOOL_ACTION zoomFitObjects
Definition: actions.h:100
static TOOL_ACTION removeItemsFromSel
Definition: ee_actions.h:64
static SELECTION_CONDITION Count(int aNumber)
Create 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)
Assign a context menu and tells when it should be activated.
VECTOR2< int > VECTOR2I
Definition: vector2d.h:630
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
bool Contains(const wxPoint &aPoint) const
Definition: eda_rect.cpp:57
void Remove(int aIndex)
Remove the item at aIndex (first position is 0).
Definition: collector.h:115
bool InvokeTool(TOOL_ID aToolId)
Call a tool by sending a tool activation event to tool of given ID.
void SetCurrentCursor(KICURSOR cursor)
Set the current cursor shape for this panel.
search types array terminator (End Of Types)
Definition: typeinfo.h:81
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:77
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:207
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:62
static TOOL_ACTION breakWire
Definition: ee_actions.h:134
void SetIsHover(bool aIsHover)
Definition: selection.h:67
virtual void Add(EDA_ITEM *aItem)
Definition: selection.h:77
const KICAD_T movableSymbolItems[]
static TOOL_ACTION leaveSheet
Definition: ee_actions.h:187
void ClearBrightened()
Definition: eda_item.h:181
static TOOL_ACTION removeItemFromSel
Definition: ee_actions.h:60
void Append(EDA_ITEM *item)
Add an item to the end of the list.
Definition: collector.h:105
void SetAdditive(bool aAdditive)
bool m_MenuCancelled
Definition: collector.h:251
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
Test if aPosition is contained within or on the bounding box of an item.
Definition: eda_item.h:273
void updateReferencePoint()
Sets the reference point to the anchor of the top-left item.
static SELECTION_CONDITION SingleDeMorganSymbol
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:87
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
int SelectNode(const TOOL_EVENT &aEvent)
Select node under cursor
Definition: kiid.h:44
void SetReferencePoint(const VECTOR2I &aP)
Definition: selection.h:264
int GetUnit() const
Definition: lib_item.h:296
bool Init() override
Init() is called once upon a registration of the tool.
void Transfer(int aIndex)
Move the item at aIndex (first position is 0) to the backup list.
Definition: collector.h:159
void BrightenItem(EDA_ITEM *aItem)
MOUSE_DRAG_ACTION
bool selectPoint(EE_COLLECTOR &aCollector, EDA_ITEM **aItem=nullptr, bool *aSelectionCancelledFlag=nullptr, bool aAdd=false, bool aSubtract=false, bool aExclusiveOr=false)
Function SelectPoint() This is the primary SelectPoint method that will prompt the user with a menu t...
#define BRIGHTENED
item is drawn with a bright contour
Definition: eda_item.h:129
void highlight(EDA_ITEM *aItem, int aHighlightMode, EE_SELECTION *aGroup=nullptr)
Function highlight() Highlights the item visually.
void narrowSelection(EE_COLLECTOR &collector, const VECTOR2I &aWhere, bool aCheckLocked)
Applies rules to narrow the collection down to selectable objects, and then heuristics to try and nar...
MOUSE_DRAG_ACTION GetDragAction() const
Indicates whether a drag should draw a selection rectangle or drag selected (or unselected) objects.
Definition: tools_holder.h:134
void SetFlags(STATUS_FLAGS aMask)
Definition: eda_item.h:201
static TOOL_ACTION addItemToSel
Selects an item (specified as the event parameter).
Definition: ee_actions.h:59
void SetSelected()
Definition: eda_item.h:177
static TOOL_ACTION drawWire
Definition: ee_actions.h:79
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagate an event to tools that requested events of matching type(s).
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
static TOOL_ACTION explicitCrossProbe
Definition: ee_actions.h:200
T Parameter() const
Return a non-standard parameter assigned to the event.
Definition: tool_event.h:426
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
#define SELECTED
Definition: eda_item.h:113
Generic, UI-independent tool event.
Definition: tool_event.h:170
void SetMaximum()
Definition: box2.h:73
const BOX2I ViewBBox() const override
Return 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
EDA_ITEM * GetParent() const
Definition: eda_item.h:163
int SelectConnection(const TOOL_EVENT &aEvent)
If node selected then expand to connection, otherwise select connection under cursor
static const TOOL_EVENT ClearedEvent
Selected item had a property changed (except movement)
Definition: actions.h:213
virtual bool IsType(const KICAD_T aScanTypes[]) const
Check whether the item is one of the listed types.
Definition: eda_item.h:231
std::function< bool(const SELECTION &)> SELECTION_CONDITION
< Functor type that checks a specific condition for selected items.
void UpdateItems()
Iterate through the list of items that asked for updating and updates them.
Definition: view.cpp:1394
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:85
std::vector< EDA_ITEM * > EDA_ITEMS
Define list of drawing items for screens.
Definition: eda_item.h:555
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()
bool CollectHits(EE_COLLECTOR &aCollector, const VECTOR2I &aWhere, const KICAD_T *aFilterList=EE_COLLECTOR::AllItems)
Function CollectHits() Selects one or more items at the location given by parameter aWhere.
static TOOL_ACTION updateMenu
Definition: actions.h:172
static SELECTION_CONDITION SingleMultiUnitSymbol
virtual KIGFX::VIEW_ITEM * GetItem(unsigned int aIdx) const override
Definition: selection.h:106
int GetConvert() const
Definition: lib_item.h:299
const BITMAP_OPAQUE info_xpm[1]
Definition: info.cpp:36
LIB_PART * GetCurPart()
Return the current part being edited or NULL if none selected.
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:115
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
virtual void SetAutoPan(bool aEnabled)
Turn 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:122
static bool IsDrawingBus(const SELECTION &aSelection)
static TOOL_ACTION drawBus
Definition: ee_actions.h:80
wxString m_MenuTitle
Definition: collector.h:250
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:219
bool IsMirroredX() const
Return true if view is flipped across the X axis.
Definition: view.h:237
void SetSubtractive(bool aSubtractive)
virtual unsigned int GetSize() const override
Return the number of stored items.
Definition: selection.h:101
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition: sch_sheet.h:365
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
int Modifier(int aMask=MD_MODIFIER_MASK) const
Definition: tool_event.h:340
static TOOL_ACTION placeLabel
Definition: ee_actions.h:85
int RemoveItemFromSel(const TOOL_EVENT &aEvent)
void Normalize()
Ensures that the height ant width are positive.
Definition: eda_rect.cpp:35
void unselect(EDA_ITEM *aItem)
Function unselect() Takes necessary action mark an item as unselected.
#define STARTPOINT
When a line is selected, these flags indicate which.
Definition: eda_item.h:111
EDA_ITEM * GetTopLeftItem(bool onlyModules=false) const override
virtual RENDER_SETTINGS * GetSettings()=0
Return a 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
virtual bool IsPointClickableAnchor(const wxPoint &aPos) const
Definition: sch_item.h:388
SCH_SHEET & Root() const
Definition: schematic.h:102
static KICAD_T nodeTypes[]
bool HasAdditionalItems()
Test if the collector has heuristic backup items.
Definition: collector.h:140
int AddItemToSel(const TOOL_EVENT &aEvent)
void SetHighlight(bool aEnabled, int aNetcode=-1, bool aMulti=false)
Turns on/off highlighting.
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:37
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() This overload of SelectPoint will create an EE_COLLECTOR and collect hits at l...
#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:152
virtual wxString GetSelectMenuText(EDA_UNITS aUnits) const
Return the text to display to be used in the selection clarification context menu when multiple items...
Definition: eda_item.cpp:123
std::pair< VIEW_ITEM *, int > LAYER_ITEM_PAIR
Definition: view.h:72
bool HitTestPoints(const wxPoint &pointA, const wxPoint &pointB, double threshold)
Test, if two points are near each other.
Definition: trigo.h:172
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:159
static SELECTION_CONDITION OnlyType(KICAD_T aType)
Create a functor that tests if the selected items are only of given type.
bool IsAlias() const
void RebuildSelection()
Rebuilds the selection from the EDA_ITEMs' selection flags.
Handle the component boundary box.
Definition: eda_rect.h:42
static const KICAD_T AllItems[]
Definition: ee_collectors.h:45
TOOL_EVENT MakeEvent() const
Return the event associated with the action (i.e.
Definition: tool_action.h:123
int Size() const
Returns the number of selected parts.
Definition: selection.h:128
Schematic symbol object.
Definition: sch_component.h:79
static bool Empty(const SELECTION &aSelection)
Test 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
bool IsRoot() const override
For symbols derived from other symbols, IsRoot() indicates no derivation.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:148
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
static TOOL_ACTION enterSheet
Definition: ee_actions.h:186
boost::optional< T > OPT
Definition: optional.h:7
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:202
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1459
void Combine()
Re-combine the backup list into the main list of the collector.
Definition: collector.h:148
SCH_SHEET_PATH & GetCurrentSheet() const
#define ENDPOINT
ends. (Used to support dragging.)
Definition: eda_item.h:112
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:327
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:838
virtual int Query(const BOX2I &aRect, std::vector< LAYER_ITEM_PAIR > &aResult) const
Find all visible items that touch or are within the rectangle aRect.
Definition: view.cpp:433
virtual const EDA_RECT GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:89
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:42
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:67
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
Return a pointer to an image to be used in menus.
Definition: eda_item.cpp:221
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Add a menu entry to run a TOOL_ACTION on selected items.
EE_SELECTION m_selection
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:194
static TOOL_ACTION selectAll
Definition: actions.h:73
void ShowContextMenu(SELECTION &aSelection)
Helper function to set and immediately show a CONDITIONAL_MENU in concert with the given SELECTION.
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
Return the current cursor position in world coordinates.
EDA_ITEM * Front() const
Definition: selection.h:203
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Inflate the rectangle horizontally by dx and vertically by dy.
Definition: eda_rect.cpp:363
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1513
const KICAD_T movableSchematicItems[]
OPT< TOOL_EVENT > OPT_TOOL_EVENT
Definition: tool_event.h:548
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:161
int Main(const TOOL_EVENT &aEvent)
Function Main()
The symbol library editor main window.
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:326
virtual void Remove(EDA_ITEM *aItem)
Definition: selection.h:88
wxPoint GetEndPoint() const
Definition: sch_line.h:97