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-2021 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 #include <bitmaps.h>
26 #include <core/typeinfo.h>
27 #include <core/kicad_algo.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_symbol.h>
41 #include <sch_field.h>
42 #include <sch_edit_frame.h>
43 #include <sch_item.h>
44 #include <sch_line.h>
45 #include <sch_sheet.h>
46 #include <sch_sheet_pin.h>
47 #include <schematic.h>
48 #include <tool/tool_event.h>
49 #include <tool/tool_manager.h>
50 #include <tools/ee_grid_helper.h>
52 #include <trigo.h>
53 #include <view/view.h>
54 #include <view/view_controls.h>
55 
57 {
58  if( aSel.GetSize() == 1 )
59  {
60  SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aSel.Front() );
61 
62  if( symbol )
63  return !symbol->GetLibSymbolRef() || !symbol->GetLibSymbolRef()->IsPower();
64  }
65 
66  return false;
67 };
68 
69 
71 {
72  return aSel.GetSize() == 1 && aSel.Front()->Type() == SCH_SYMBOL_T;
73 };
74 
75 
77 {
78  if( aSel.GetSize() == 1 )
79  {
80  SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aSel.Front() );
81 
82  if( symbol )
83  return symbol->GetLibSymbolRef() && symbol->GetLibSymbolRef()->HasConversion();
84  }
85 
86  return false;
87 };
88 
89 
91 {
92  if( aSel.GetSize() == 1 )
93  {
94  SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( aSel.Front() );
95 
96  if( symbol )
97  return symbol->GetLibSymbolRef() && symbol->GetLibSymbolRef()->GetUnitCount() >= 2;
98  }
99 
100  return false;
101 };
102 
103 
104 #define HITTEST_THRESHOLD_PIXELS 5
105 
106 
108  TOOL_INTERACTIVE( "eeschema.InteractiveSelection" ),
109  m_frame( nullptr ),
110  m_additive( false ),
111  m_subtractive( false ),
112  m_exclusive_or( false ),
113  m_multiple( false ),
114  m_skip_heuristics( false ),
115  m_nonModifiedCursor( KICURSOR::ARROW ),
116  m_isSymbolEditor( false ),
117  m_isSymbolViewer( false ),
118  m_unit( 0 ),
119  m_convert( 0 )
120 {
121  m_selection.Clear();
122 }
123 
124 
126 {
127  getView()->Remove( &m_selection );
128 }
129 
130 
132 
133 
135 {
136  m_frame = getEditFrame<SCH_BASE_FRAME>();
137 
138  SYMBOL_VIEWER_FRAME* symbolViewerFrame = dynamic_cast<SYMBOL_VIEWER_FRAME*>( m_frame );
139  SYMBOL_EDIT_FRAME* symbolEditorFrame = dynamic_cast<SYMBOL_EDIT_FRAME*>( m_frame );
140 
141  if( symbolEditorFrame )
142  {
143  m_isSymbolEditor = true;
144  m_unit = symbolEditorFrame->GetUnit();
145  m_convert = symbolEditorFrame->GetConvert();
146  }
147  else
148  {
149  m_isSymbolViewer = symbolViewerFrame != nullptr;
150  }
151 
152  static KICAD_T wireOrBusTypes[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT };
153  static KICAD_T connectedTypes[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T,
156 
157  auto wireSelection = E_C::MoreThan( 0 ) && E_C::OnlyType( SCH_LINE_LOCATE_WIRE_T );
158  auto busSelection = E_C::MoreThan( 0 ) && E_C::OnlyType( SCH_LINE_LOCATE_BUS_T );
159  auto wireOrBusSelection = E_C::MoreThan( 0 ) && E_C::OnlyTypes( wireOrBusTypes );
160  auto connectedSelection = E_C::MoreThan( 0 ) && E_C::OnlyTypes( connectedTypes );
161  auto sheetSelection = E_C::Count( 1 ) && E_C::OnlyType( SCH_SHEET_T );
162 
163  auto schEditSheetPageNumberCondition =
164  [&] ( const SELECTION& aSel )
165  {
167  return false;
168 
169  return E_C::LessThan( 2 )( aSel ) && E_C::OnlyType( SCH_SHEET_T )( aSel );
170  };
171 
172  auto schEditCondition =
173  [this] ( const SELECTION& aSel )
174  {
176  };
177 
178  auto belowRootSheetCondition =
179  [&]( const SELECTION& aSel )
180  {
181  SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
182 
183  return editFrame
184  && editFrame->GetCurrentSheet().Last() != &editFrame->Schematic().Root();
185  };
186 
187  auto haveSymbolCondition =
188  [&]( const SELECTION& sel )
189  {
190  return m_isSymbolEditor &&
191  static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->GetCurSymbol();
192  };
193 
194  auto& menu = m_menu.GetMenu();
195 
196  menu.AddItem( EE_ACTIONS::enterSheet, sheetSelection && EE_CONDITIONS::Idle, 1 );
197  menu.AddItem( EE_ACTIONS::explicitCrossProbe, sheetSelection && EE_CONDITIONS::Idle, 1 );
198  menu.AddItem( EE_ACTIONS::leaveSheet, belowRootSheetCondition, 1 );
199 
200  menu.AddSeparator( 100 );
201  menu.AddItem( EE_ACTIONS::drawWire, schEditCondition && EE_CONDITIONS::Empty, 100 );
202  menu.AddItem( EE_ACTIONS::drawBus, schEditCondition && EE_CONDITIONS::Empty, 100 );
203 
204  menu.AddSeparator( 100 );
206 
207  menu.AddSeparator( 100 );
209 
210  menu.AddSeparator( 200 );
211  menu.AddItem( EE_ACTIONS::selectConnection, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
212  menu.AddItem( EE_ACTIONS::placeJunction, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
213  menu.AddItem( EE_ACTIONS::placeLabel, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
214  menu.AddItem( EE_ACTIONS::placeGlobalLabel, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
215  menu.AddItem( EE_ACTIONS::placeHierLabel, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
216  menu.AddItem( EE_ACTIONS::breakWire, wireSelection && EE_CONDITIONS::Idle, 250 );
217  menu.AddItem( EE_ACTIONS::breakBus, busSelection && EE_CONDITIONS::Idle, 250 );
218  menu.AddItem( EE_ACTIONS::importSingleSheetPin, sheetSelection && EE_CONDITIONS::Idle, 250 );
219  menu.AddItem( EE_ACTIONS::assignNetclass, connectedSelection && EE_CONDITIONS::Idle, 250 );
220  menu.AddItem( EE_ACTIONS::editPageNumber, schEditSheetPageNumberCondition, 250 );
221 
222  menu.AddSeparator( 400 );
223  menu.AddItem( EE_ACTIONS::symbolProperties,
224  haveSymbolCondition && EE_CONDITIONS::Empty, 400 );
225  menu.AddItem( EE_ACTIONS::pinTable,
226  haveSymbolCondition && EE_CONDITIONS::Empty, 400 );
227 
228  menu.AddSeparator( 1000 );
230 
231  return true;
232 }
233 
234 
236 {
237  m_frame = getEditFrame<SCH_BASE_FRAME>();
238 
239  if( aReason == TOOL_BASE::MODEL_RELOAD )
240  {
241  // Remove pointers to the selected items from containers without changing their
242  // properties (as they are already deleted while a new sheet is loaded)
243  m_selection.Clear();
244  getView()->GetPainter()->GetSettings()->SetHighlight( false );
245 
246  SYMBOL_EDIT_FRAME* symbolEditFrame = dynamic_cast<SYMBOL_EDIT_FRAME*>( m_frame );
247  SYMBOL_VIEWER_FRAME* symbolViewerFrame = dynamic_cast<SYMBOL_VIEWER_FRAME*>( m_frame );
248 
249  if( symbolEditFrame )
250  {
251  m_isSymbolEditor = true;
252  m_unit = symbolEditFrame->GetUnit();
253  m_convert = symbolEditFrame->GetConvert();
254  }
255  else
256  m_isSymbolViewer = symbolViewerFrame != nullptr;
257  }
258  else
259  // Restore previous properties of selected items and remove them from containers
260  ClearSelection();
261 
262  // Reinsert the VIEW_GROUP, in case it was removed from the VIEW
263  getView()->Remove( &m_selection );
264  getView()->Add( &m_selection );
265 }
266 
267 
269 {
270  ACTION_MENU* actionMenu = aEvent.Parameter<ACTION_MENU*>();
271  CONDITIONAL_MENU* conditionalMenu = dynamic_cast<CONDITIONAL_MENU*>( actionMenu );
272 
273  if( conditionalMenu )
274  conditionalMenu->Evaluate( m_selection );
275 
276  if( actionMenu )
277  actionMenu->UpdateAll();
278 
279  return 0;
280 }
281 
282 
284 {
285  SCH_MARKER_T,
290  SCH_LINE_T,
291  SCH_BITMAP_T,
292  SCH_TEXT_T,
293  SCH_LABEL_T,
296  SCH_FIELD_T,
297  SCH_SYMBOL_T,
299  SCH_SHEET_T,
300  EOT
301 };
302 
303 
305 {
306  LIB_ARC_T,
307  LIB_CIRCLE_T,
308  LIB_TEXT_T,
311  LIB_BEZIER_T,
312  LIB_PIN_T,
313  LIB_FIELD_T,
314  EOT
315 };
316 
317 
319 {
320  LIB_FIELD_T,
321  EOT
322 };
323 
324 
325 void EE_SELECTION_TOOL::setModifiersState( bool aShiftState, bool aCtrlState, bool aAltState )
326 {
327  // Set the configuration of m_additive, m_subtractive, m_exclusive_or
328  // from the state of modifier keys SHIFT, CTRL, ALT and the OS
329 
330  // on left click, a selection is made, depending on modifiers ALT, SHIFT, CTRL:
331  // Due to the fact ALT key modifier cannot be used freely on Windows and Linux,
332  // actions are different on OSX and others OS
333  // Especially, ALT key cannot be used to force showing the full selection choice
334  // context menu (the menu is immediately closed on Windows )
335  //
336  // No modifier = select items and deselect previous selection
337  // ALT (on OSX) = skip heuristic and show full selection choice
338  // ALT (on others) = exclusive OR of selected items (inverse selection)
339  //
340  // CTRL/CMD (on OSX) = exclusive OR of selected items (inverse selection)
341  // CTRL (on others) = skip heuristic and show full selection choice
342  //
343  // SHIFT = add selected items to the current selection
344  //
345  // CTRL/CMD+SHIFT (on OSX) = remove selected items to the current selection
346  // CTRL+SHIFT (on others) = unused (can be used for a new action)
347  //
348  // CTRL/CMT+ALT (on OSX) = unused (can be used for a new action)
349  // CTRL+ALT (on others) = do nothing (same as no modifier)
350  //
351  // SHIFT+ALT (on OSX) = do nothing (same as no modifier)
352  // SHIFT+ALT (on others) = remove selected items to the current selection
353 
354 #ifdef __WXOSX_MAC__
355  m_subtractive = aCtrlState && aShiftState && !aAltState;
356  m_additive = aShiftState && !aCtrlState && !aAltState;
357  m_exclusive_or = aCtrlState && !aShiftState && !aAltState;
358  m_skip_heuristics = aAltState && !aShiftState && !aCtrlState;
359 
360 #else
361  m_subtractive = aShiftState && !aCtrlState && aAltState;
362  m_additive = aShiftState && !aCtrlState && !aAltState;
363  m_exclusive_or = !aShiftState && !aCtrlState && aAltState;
364 
365  // Is the user requesting that the selection list include all possible
366  // items without removing less likely selection candidates
367  // Cannot use the Alt key on windows or the disambiguation context menu is immediately
368  // dismissed rendering it useless.
369  m_skip_heuristics = aCtrlState && !aShiftState && !aAltState;
370 #endif
371 }
372 
373 
375 {
377 
378  KIID lastRolloverItem = niluuid;
379 
380  // Main loop: keep receiving events
381  while( TOOL_EVENT* evt = Wait() )
382  {
383  bool displayWireCursor = false;
384  bool displayBusCursor = false;
385  bool displayLineCursor = false;
386  KIID rolloverItem = lastRolloverItem;
387 
388  // on left click, a selection is made, depending on modifiers ALT, SHIFT, CTRL:
389  setModifiersState( evt->Modifier( MD_SHIFT ), evt->Modifier( MD_CTRL ),
390  evt->Modifier( MD_ALT ) );
391 
392  bool modifier_enabled = m_subtractive || m_additive || m_exclusive_or;
393 
394  MOUSE_DRAG_ACTION drag_action = m_frame->GetDragAction();
396 
397  // Single click? Select single object
398  if( evt->IsClick( BUT_LEFT ) )
399  {
400  if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
401  schframe->FocusOnItem( nullptr );
402 
403  EE_COLLECTOR collector;
404  bool continueSelect = true;
405 
406  // Collect items at the clicked location (doesn't select them yet)
407  if( CollectHits( collector, evt->Position()) )
408  {
409  narrowSelection( collector, evt->Position(), false );
410 
411  if( collector.GetCount() == 1 && !m_isSymbolEditor && !modifier_enabled )
412  {
413  // Check if we want to auto start wires
414  VECTOR2I snappedCursorPos = grid.BestSnapAnchor( evt->Position(),
415  LAYER_CONNECTABLE, nullptr );
416 
418  && collector[0]->IsPointClickableAnchor( (wxPoint) snappedCursorPos ) )
419  {
420  OPT_TOOL_EVENT newEvt;
421  SCH_CONNECTION* connection = collector[0]->Connection();
422 
423  if( ( connection && ( connection->IsNet() || connection->IsUnconnected() ) )
424  || collector[0]->Type() == SCH_SYMBOL_T )
425  {
426  newEvt = EE_ACTIONS::drawWire.MakeEvent();
427  }
428  else if( connection && connection->IsBus() )
429  {
430  newEvt = EE_ACTIONS::drawBus.MakeEvent();
431  }
432  else if( collector[0]->Type() == SCH_LINE_T
433  && static_cast<SCH_LINE*>( collector[0] )->IsGraphicLine() )
434  {
435  newEvt = EE_ACTIONS::drawLines.MakeEvent();
436  }
437 
438  auto* params = newEvt->Parameter<DRAW_SEGMENT_EVENT_PARAMS*>();
439  auto* newParams = new DRAW_SEGMENT_EVENT_PARAMS();
440 
441  *newParams= *params;
442  newParams->quitOnDraw = true;
443  newEvt->SetParameter( newParams );
444 
445  getViewControls()->ForceCursorPosition( true, snappedCursorPos );
446  newEvt->SetMousePosition( snappedCursorPos );
447  newEvt->SetHasPosition( true );
448  newEvt->SetForceImmediate( true );
449  m_toolMgr->ProcessEvent( *newEvt );
450 
451  continueSelect = false;
452  }
453  else if( collector[0]->IsHypertext() )
454  {
455  collector[0]->DoHypertextMenu( m_frame );
456  continueSelect = false;
457  }
458  }
459  }
460 
461  if( continueSelect )
462  {
463  // If we didn't click on an anchor, we perform a normal select, pass in the
464  // items we previously collected
465  selectPoint( collector, nullptr, nullptr, m_additive, m_subtractive,
466  m_exclusive_or );
467  }
468  }
469  else if( evt->IsClick( BUT_RIGHT ) )
470  {
471  // right click? if there is any object - show the context menu
472  bool selectionCancelled = false;
473 
474  if( m_selection.Empty() )
475  {
476  ClearSelection();
477  SelectPoint( evt->Position(), EE_COLLECTOR::AllItems, nullptr,
478  &selectionCancelled );
479  m_selection.SetIsHover( true );
480  }
481  // If the cursor has moved off the bounding box of the selection by more than
482  // a grid square, check to see if there is another item available for selection
483  // under the cursor. If there is, the user likely meant to get the context menu
484  // for that item. If there is no new item, then keep the original selection and
485  // show the context menu for it.
486  else if( !m_selection.GetBoundingBox().Inflate(
487  grid.GetGrid().x, grid.GetGrid().y ).Contains(
488  (wxPoint) evt->Position() ) )
489  {
490  EE_SELECTION saved_selection = m_selection;
491 
492  for( const auto& item : saved_selection )
493  RemoveItemFromSel( item, true );
494 
495  SelectPoint( evt->Position(), EE_COLLECTOR::AllItems, nullptr,
496  &selectionCancelled );
497 
498  if( m_selection.Empty() )
499  {
500  m_selection.SetIsHover( false );
501 
502  for( const auto& item : saved_selection )
503  AddItemToSel( item, true);
504  }
505  else
506  {
507  m_selection.SetIsHover( true );
508  }
509  }
510 
511  if( !selectionCancelled )
513  }
514  else if( evt->IsDblClick( BUT_LEFT ) )
515  {
516  // double click? Display the properties window
517  if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
518  schframe->FocusOnItem( nullptr );
519 
520  if( m_selection.Empty() )
521  SelectPoint( evt->Position() );
522 
523  EDA_ITEM* item = m_selection.Front();
524 
525  if( item && item->Type() == SCH_SHEET_T )
527  else
529  }
530  else if( evt->IsDblClick( BUT_MIDDLE ) )
531  {
532  // Middle double click? Do zoom to fit or zoom to objects
533  if( evt->Modifier( MD_CTRL ) ) // Is CTRL key down?
535  else
537  }
538  else if( evt->IsDrag( BUT_LEFT ) )
539  {
540  // Is another tool already moving a new object? Don't allow a drag start
541  if( !m_selection.Empty() && m_selection[0]->HasFlag( IS_NEW | IS_MOVING ) )
542  {
543  evt->SetPassEvent();
544  continue;
545  }
546 
547  // drag with LMB? Select multiple objects (or at least draw a selection box) or
548  // drag them
549  if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
550  schframe->FocusOnItem( nullptr );
551 
552  if( modifier_enabled || drag_action == MOUSE_DRAG_ACTION::SELECT )
553  {
554  selectMultiple();
555  }
556  else if( m_selection.Empty() && drag_action != MOUSE_DRAG_ACTION::DRAG_ANY )
557  {
558  selectMultiple();
559  }
560  else
561  {
562  if( m_isSymbolEditor )
563  {
564  if( static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->IsSymbolAlias() )
566  else
568  }
569  else
570  {
572  }
573 
574  // Check if dragging has started within any of selected items bounding box
575  if( selectionContains( evt->Position() ) )
576  {
577  // Yes -> run the move tool and wait till it finishes
578  if( m_isSymbolEditor )
579  m_toolMgr->InvokeTool( "eeschema.SymbolMoveTool" );
580  else
581  m_toolMgr->InvokeTool( "eeschema.InteractiveMove" );
582  }
583  else
584  {
585  // No -> drag a selection box
586  selectMultiple();
587  }
588  }
589  }
590  else if( evt->Category() == TC_COMMAND && evt->Action() == TA_CHOICE_MENU_CHOICE )
591  {
592  // context sub-menu selection? Handle unit selection or bus unfolding
593  if( evt->GetCommandId().get() >= ID_POPUP_SCH_SELECT_UNIT_CMP
594  && evt->GetCommandId().get() <= ID_POPUP_SCH_SELECT_UNIT_SYM_MAX )
595  {
596  SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( m_selection.Front() );
597  int unit = evt->GetCommandId().get() - ID_POPUP_SCH_SELECT_UNIT_CMP;
598 
599  if( symbol )
600  static_cast<SCH_EDIT_FRAME*>( m_frame )->SelectUnit( symbol, unit );
601  }
602  else if( evt->GetCommandId().get() >= ID_POPUP_SCH_UNFOLD_BUS
603  && evt->GetCommandId().get() <= ID_POPUP_SCH_UNFOLD_BUS_END )
604  {
605  wxString* net = new wxString( *evt->Parameter<wxString*>() );
607  }
608 
609  }
610  else if( evt->IsCancelInteractive() )
611  {
612  if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
613  schframe->FocusOnItem( nullptr );
614 
615  ClearSelection();
616  }
617  else if( evt->Action() == TA_UNDO_REDO_PRE )
618  {
619  if( SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( m_frame ) )
620  schframe->FocusOnItem( nullptr );
621 
622  ClearSelection();
623  }
624  else if( evt->IsMotion() && !m_isSymbolEditor && m_frame->ToolStackIsEmpty() )
625  {
626  rolloverItem = niluuid;
627  EE_COLLECTOR collector;
628 
629  // We are checking if we should display a pencil when hovering over anchors
630  // for "auto starting" wires when clicked
631  if( CollectHits( collector, evt->Position()) )
632  {
633  narrowSelection( collector, evt->Position(), false );
634 
635  if( collector.GetCount() == 1 && !modifier_enabled )
636  {
637  VECTOR2I snappedCursorPos = grid.BestSnapAnchor( evt->Position(),
638  LAYER_CONNECTABLE, nullptr );
639 
641  && collector[0]->IsPointClickableAnchor( (wxPoint) snappedCursorPos ) )
642  {
643  SCH_CONNECTION* connection = collector[0]->Connection();
644 
645  if( ( connection && ( connection->IsNet() || connection->IsUnconnected() ) )
646  || collector[0]->Type() == SCH_SYMBOL_T )
647  {
648  displayWireCursor = true;
649  }
650  else if( connection && connection->IsBus() )
651  {
652  displayBusCursor = true;
653  }
654  else if( collector[0]->Type() == SCH_LINE_T
655  && static_cast<SCH_LINE*>( collector[0] )->IsGraphicLine() )
656  {
657  displayLineCursor = true;
658  }
659 
660  getViewControls()->ForceCursorPosition( true, snappedCursorPos );
661  }
662  else if( collector[0]->IsHypertext()
663  && !collector[0]->IsSelected()
665  {
666  rolloverItem = collector[0]->m_Uuid;
667  }
668  }
669  }
670  else
671  {
673  }
674  }
675  else
676  {
677  evt->SetPassEvent();
678  }
679 
680  if( rolloverItem != lastRolloverItem )
681  {
682  EDA_ITEM* item = m_frame->GetItem( lastRolloverItem );
683 
684  if( item )
685  {
686  item->ClearFlags( IS_ROLLOVER );
687  lastRolloverItem = niluuid;
688 
689  if( item->Type() == SCH_FIELD_T )
690  m_frame->GetCanvas()->GetView()->Update( item->GetParent() );
691  else
692  m_frame->GetCanvas()->GetView()->Update( item );
693  }
694 
695  item = m_frame->GetItem( rolloverItem );
696 
697  if( item )
698  {
699  item->SetFlags( IS_ROLLOVER );
700  lastRolloverItem = rolloverItem;
701 
702  if( item->Type() == SCH_FIELD_T )
703  m_frame->GetCanvas()->GetView()->Update( item->GetParent() );
704  else
705  m_frame->GetCanvas()->GetView()->Update( item );
706  }
707  }
708 
709  if( m_frame->ToolStackIsEmpty() )
710  {
711  if( displayWireCursor )
712  {
714  }
715  else if( displayBusCursor )
716  {
718  }
719  else if( displayLineCursor )
720  {
722  }
723  else if( rolloverItem != niluuid )
724  {
726  }
727  else if( !m_selection.Empty()
728  && drag_action == MOUSE_DRAG_ACTION::DRAG_SELECTED
729  && evt->HasPosition()
730  && selectionContains( evt->Position() ) ) //move/drag option prediction
731  {
733  }
734  else
735  {
737  }
738  }
739  }
740 
741  // Shutting down; clear the selection
742  m_selection.Clear();
743 
744  return 0;
745 }
746 
747 
748 void EE_SELECTION_TOOL::OnIdle( wxIdleEvent& aEvent )
749 {
750  if( m_frame->ToolStackIsEmpty() && !m_multiple )
751  {
752  wxMouseState keyboardState = wxGetMouseState();
753 
754  setModifiersState( keyboardState.ShiftDown(), keyboardState.ControlDown(),
755  keyboardState.AltDown() );
756 
757  if( m_additive )
759  else if( m_subtractive )
761  else if( m_exclusive_or )
763  else
765  }
766 }
767 
768 
770 {
771  return m_selection;
772 }
773 
774 
775 bool EE_SELECTION_TOOL::CollectHits( EE_COLLECTOR& aCollector, const VECTOR2I& aWhere,
776  const KICAD_T* aFilterList )
777 {
778  aCollector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
779 
780  if( m_isSymbolEditor )
781  {
782  LIB_SYMBOL* symbol = static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->GetCurSymbol();
783 
784  if( !symbol )
785  return false;
786 
787  aCollector.Collect( symbol->GetDrawItems(), aFilterList, (wxPoint) aWhere, m_unit,
788  m_convert );
789  }
790  else
791  {
792  aCollector.Collect( m_frame->GetScreen(), aFilterList, (wxPoint) aWhere, m_unit,
793  m_convert );
794  }
795 
796  return aCollector.GetCount() > 0;
797 }
798 
799 
801  bool aCheckLocked )
802 {
803  for( int i = collector.GetCount() - 1; i >= 0; --i )
804  {
805  if( !Selectable( collector[i] ) )
806  {
807  collector.Remove( i );
808  continue;
809  }
810 
811  if( aCheckLocked && collector[i]->IsLocked() )
812  {
813  collector.Remove( i );
814  continue;
815  }
816 
817  // SelectPoint, unlike other selection routines, can select line ends
818  if( collector[i]->Type() == SCH_LINE_T )
819  {
820  SCH_LINE* line = (SCH_LINE*) collector[i];
821  line->ClearFlags( STARTPOINT | ENDPOINT );
822 
823  if( HitTestPoints( line->GetStartPoint(), (wxPoint) aWhere, collector.m_Threshold ) )
824  line->SetFlags( STARTPOINT );
825  else if( HitTestPoints( line->GetEndPoint(), (wxPoint) aWhere, collector.m_Threshold ) )
826  line->SetFlags( ENDPOINT );
827  else
828  line->SetFlags( STARTPOINT | ENDPOINT );
829  }
830  }
831 
832  // Apply some ugly heuristics to avoid disambiguation menus whenever possible
833  if( collector.GetCount() > 1 && !m_skip_heuristics )
834  {
835  GuessSelectionCandidates( collector, aWhere );
836  }
837 }
838 
839 
841  bool* aSelectionCancelledFlag, bool aAdd, bool aSubtract,
842  bool aExclusiveOr )
843 {
845 
846  // If still more than one item we're going to have to ask the user.
847  if( aCollector.GetCount() > 1 )
848  {
849  // Must call selectionMenu via RunAction() to avoid event-loop contention
850  m_toolMgr->RunAction( EE_ACTIONS::selectionMenu, true, &aCollector );
851 
852  if( aCollector.m_MenuCancelled )
853  {
854  if( aSelectionCancelledFlag )
855  *aSelectionCancelledFlag = true;
856 
857  return false;
858  }
859  }
860 
861  if( !aAdd && !aSubtract && !aExclusiveOr )
862  ClearSelection();
863 
864  bool anyAdded = false;
865  bool anySubtracted = false;
866 
867  if( aCollector.GetCount() > 0 )
868  {
869  for( int i = 0; i < aCollector.GetCount(); ++i )
870  {
871  if( aSubtract || ( aExclusiveOr && aCollector[i]->IsSelected() ) )
872  {
873  unselect( aCollector[i] );
874  anySubtracted = true;
875  }
876  else
877  {
878  select( aCollector[i] );
879  anyAdded = true;
880  }
881  }
882  }
883 
884  if( anyAdded )
885  {
887 
888  if( aItem && aCollector.GetCount() == 1 )
889  *aItem = aCollector[0];
890 
891  return true;
892  }
893  else if( anySubtracted )
894  {
896  return true;
897  }
898 
899  return false;
900 }
901 
902 
903 bool EE_SELECTION_TOOL::SelectPoint( const VECTOR2I& aWhere, const KICAD_T* aFilterList,
904  EDA_ITEM** aItem, bool* aSelectionCancelledFlag,
905  bool aCheckLocked, bool aAdd, bool aSubtract,
906  bool aExclusiveOr )
907 {
908  EE_COLLECTOR collector;
909 
910  if( !CollectHits( collector, aWhere, aFilterList ) )
911  return false;
912 
913  narrowSelection( collector, aWhere, aCheckLocked );
914 
915  return selectPoint( collector, aItem, aSelectionCancelledFlag, aAdd, aSubtract, aExclusiveOr );
916 }
917 
918 
920 {
921  m_multiple = true; // Multiple selection mode is active
922  KIGFX::VIEW* view = getView();
923 
924  // hold all visible items
925  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
926  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> sheetPins;
927 
928  // Filter the view items based on the selection box
929  BOX2I selectionBox;
930 
931  selectionBox.SetMaximum();
932  view->Query( selectionBox, selectedItems ); // Get the list of selected items
933 
934  // Sheet pins aren't in the view; add them by hand
935  for( KIGFX::VIEW::LAYER_ITEM_PAIR& pair : selectedItems )
936  {
937  SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( pair.first );
938 
939  if( sheet )
940  {
941  int layer = pair.second;
942 
943  for( SCH_SHEET_PIN* pin : sheet->GetPins() )
944  sheetPins.emplace_back( KIGFX::VIEW::LAYER_ITEM_PAIR( pin, layer ) );
945  }
946  }
947 
948  selectedItems.insert( selectedItems.end(), sheetPins.begin(), sheetPins.end() );
949 
950  for( const std::pair<KIGFX::VIEW_ITEM*, int>& item_pair : selectedItems )
951  {
952  if( EDA_ITEM* item = dynamic_cast<EDA_ITEM*>( item_pair.first ) )
953  {
954  if( Selectable( item ) )
955  select( item );
956  }
957  }
958 
959  m_multiple = false;
960 
961  return 0;
962 }
963 
964 
966 {
967  // There are certain parent/child and enclosure combinations that can be handled
968  // automatically.
969 
970  // Prefer exact hits to sloppy ones
971  int exactHits = 0;
972 
973  for( int i = collector.GetCount() - 1; i >= 0; --i )
974  {
975  EDA_ITEM* item = collector[ i ];
976 
977  if( item->HitTest( (wxPoint) aPos, 0 ) )
978  exactHits++;
979  }
980 
981  if( exactHits > 0 && exactHits < collector.GetCount() )
982  {
983  for( int i = collector.GetCount() - 1; i >= 0; --i )
984  {
985  EDA_ITEM* item = collector[ i ];
986 
987  if( !item->HitTest( (wxPoint) aPos, 0 ) )
988  collector.Transfer( item );
989  }
990  }
991 
992  // Prefer a non-sheet to a sheet
993  for( int i = 0; collector.GetCount() == 2 && i < 2; ++i )
994  {
995  EDA_ITEM* item = collector[ i ];
996  EDA_ITEM* other = collector[ ( i + 1 ) % 2 ];
997 
998  if( item->Type() != SCH_SHEET_T && other->Type() == SCH_SHEET_T )
999  collector.Transfer( other );
1000  }
1001 
1002  // Prefer a symbol to a pin or the opposite, when both a symbol and a pin are selected
1003  // We need to be able to select only a pin:
1004  // - to display its characteristics (especially if an ERC is attached to the pin)
1005  // - for cross probing, to select the corresponding pad.
1006  // Note also the case happens only in schematic editor. In symbol editor, the symbol
1007  // itself is never selected
1008  for( int i = 0; collector.GetCount() == 2 && i < 2; ++i )
1009  {
1010  SCH_ITEM* item = collector[i];
1011  SCH_ITEM* other = collector[( i + 1 ) % 2];
1012 
1013  if( item->Type() == SCH_SYMBOL_T && other->Type() == SCH_PIN_T )
1014  {
1015  // Make sure we aren't clicking on the pin anchor itself, only the rest of the
1016  // pin should select the symbol with this setting
1017  // To avoid conflict with the auto-start wires option
1019  wxPoint cursorPos = wxPoint( grid.BestSnapAnchor( aPos, LAYER_CONNECTABLE,
1020  nullptr ) );
1021 
1022  if( !m_isSymbolEditor
1024  && !other->IsPointClickableAnchor( cursorPos ) )
1025  {
1026  collector.Transfer( other );
1027  }
1028  else
1029  {
1030  collector.Transfer( item );
1031  }
1032  }
1033  }
1034 
1035  // Prefer things that are generally smaller than a symbol to a symbol
1036  const std::set<KICAD_T> preferred =
1037  {
1038  SCH_FIELD_T,
1039  SCH_LINE_T,
1043  SCH_MARKER_T
1044  };
1045 
1046  for( int i = 0; collector.GetCount() == 2 && i < 2; ++i )
1047  {
1048  EDA_ITEM* item = collector[ i ];
1049  EDA_ITEM* other = collector[ ( i + 1 ) % 2 ];
1050 
1051  if( preferred.count( item->Type() ) && other->Type() == SCH_SYMBOL_T )
1052  collector.Transfer( other );
1053  }
1054 
1055  // No need for multiple wires at a single point; if there's a junction select that;
1056  // otherwise any of the wires will do
1057  bool junction = false;
1058  bool wiresOnly = true;
1059 
1060  for( EDA_ITEM* item : collector )
1061  {
1062  if( item->Type() == SCH_JUNCTION_T )
1063  junction = true;
1064  else if( item->Type() != SCH_LINE_T )
1065  wiresOnly = false;
1066  }
1067 
1068  if( wiresOnly )
1069  {
1070  for( int j = collector.GetCount() - 1; j >= 0; --j )
1071  {
1072  if( junction && collector[ j ]->Type() != SCH_JUNCTION_T )
1073  collector.Transfer( j );
1074  else if( !junction && j > 0 )
1075  collector.Transfer( j );
1076  }
1077  }
1078 
1079  // Construct a tight box (1/2 height and width) around the center of the closest item.
1080  // All items which exist at least partly outside this box have sufficient other areas
1081  // for selection and can be dropped.
1082  EDA_ITEM* closest = nullptr;
1083  int closestDist = INT_MAX;
1084 
1085  for( EDA_ITEM* item : collector )
1086  {
1087  int dist = EuclideanNorm( item->GetBoundingBox().GetCenter() - (wxPoint) aPos );
1088 
1089  if( dist < closestDist )
1090  {
1091  closestDist = dist;
1092  closest = item;
1093  }
1094  }
1095 
1096  if( closest ) // Don't try and get a tight bbox if nothing is near the mouse pointer
1097  {
1098  EDA_RECT tightBox = closest->GetBoundingBox();
1099  tightBox.Inflate( -tightBox.GetWidth() / 4, -tightBox.GetHeight() / 4 );
1100 
1101  for( int i = collector.GetCount() - 1; i >= 0; --i )
1102  {
1103  EDA_ITEM* item = collector[i];
1104 
1105  if( item == closest )
1106  continue;
1107 
1108  if( !item->HitTest( tightBox, true ) )
1109  collector.Transfer( item );
1110  }
1111  }
1112 }
1113 
1114 
1116 {
1117  if( m_selection.Empty() )
1118  {
1119  VECTOR2D cursorPos = getViewControls()->GetCursorPosition( true );
1120 
1121  ClearSelection();
1122  SelectPoint( cursorPos, aFilterList );
1123  m_selection.SetIsHover( true );
1125  }
1126  else // Trim an existing selection by aFilterList
1127  {
1128  for( int i = (int) m_selection.GetSize() - 1; i >= 0; --i )
1129  {
1130  EDA_ITEM* item = (EDA_ITEM*) m_selection.GetItem( i );
1131 
1132  if( !item->IsType( aFilterList ) )
1133  {
1134  unselect( item );
1136  }
1137  }
1138  }
1139 
1141 
1142  return m_selection;
1143 }
1144 
1145 
1147 {
1148  VECTOR2I refP( 0, 0 );
1149 
1150  if( m_selection.Size() > 0 )
1151  {
1152  if( m_isSymbolEditor )
1153  refP = static_cast<LIB_ITEM*>( m_selection.GetTopLeftItem() )->GetPosition();
1154  else
1155  refP = static_cast<SCH_ITEM*>( m_selection.GetTopLeftItem() )->GetPosition();
1156  }
1157 
1159 }
1160 
1161 
1163 {
1164  bool cancelled = false; // Was the tool canceled while it was running?
1165  m_multiple = true; // Multiple selection mode is active
1166  KIGFX::VIEW* view = getView();
1167 
1169  view->Add( &area );
1170 
1171  while( TOOL_EVENT* evt = Wait() )
1172  {
1173  int width = area.GetEnd().x - area.GetOrigin().x;
1174 
1175  /* Selection mode depends on direction of drag-selection:
1176  * Left > Right : Select objects that are fully enclosed by selection
1177  * Right > Left : Select objects that are crossed by selection
1178  */
1179  bool windowSelection = width >= 0;
1180 
1181  if( view->IsMirroredX() )
1182  windowSelection = !windowSelection;
1183 
1186 
1187  if( evt->IsCancelInteractive() || evt->IsActivate() )
1188  {
1189  cancelled = true;
1190  break;
1191  }
1192 
1193  if( evt->IsDrag( BUT_LEFT ) )
1194  {
1195  if( !m_additive && !m_subtractive && !m_exclusive_or )
1196  ClearSelection();
1197 
1198  // Start drawing a selection box
1199  area.SetOrigin( evt->DragOrigin() );
1200  area.SetEnd( evt->Position() );
1201  area.SetAdditive( m_additive );
1202  area.SetSubtractive( m_subtractive );
1204 
1205  view->SetVisible( &area, true );
1206  view->Update( &area );
1207  getViewControls()->SetAutoPan( true );
1208  }
1209 
1210  if( evt->IsMouseUp( BUT_LEFT ) )
1211  {
1212  getViewControls()->SetAutoPan( false );
1213 
1214  // End drawing the selection box
1215  view->SetVisible( &area, false );
1216 
1217  // Mark items within the selection box as selected
1218  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
1219  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> children;
1220 
1221  // Filter the view items based on the selection box
1222  BOX2I selectionBox = area.ViewBBox();
1223  view->Query( selectionBox, selectedItems ); // Get the list of selected items
1224 
1225  // Some children aren't in the view; add them by hand.
1226  // DO NOT add them directly to selectedItems. If we add enough to cause the vector
1227  // to grow it will re-allocate and invalidate the top-level for-loop iterator.
1228  for( KIGFX::VIEW::LAYER_ITEM_PAIR& pair : selectedItems )
1229  {
1230  SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( pair.first );
1231 
1232  if( sheet )
1233  {
1234  int layer = pair.second;
1235 
1236  for( SCH_SHEET_PIN* pin : sheet->GetPins() )
1237  children.emplace_back( KIGFX::VIEW::LAYER_ITEM_PAIR( pin, layer ) );
1238  }
1239 
1240  SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( pair.first );
1241 
1242  if( symbol )
1243  {
1244  int layer = pair.second;
1245 
1246  for( SCH_FIELD& field : symbol->GetFields() )
1247  children.emplace_back( KIGFX::VIEW::LAYER_ITEM_PAIR( &field, layer ) );
1248  }
1249 
1250  SCH_GLOBALLABEL* gLabel = dynamic_cast<SCH_GLOBALLABEL*>( pair.first );
1251 
1252  if( gLabel )
1253  {
1254  int layer = pair.second;
1255  SCH_FIELD* intersheetRef = gLabel->GetIntersheetRefs();
1256 
1257  children.emplace_back( KIGFX::VIEW::LAYER_ITEM_PAIR( intersheetRef, layer ) );
1258  }
1259  }
1260 
1261  selectedItems.insert( selectedItems.end(), children.begin(), children.end() );
1262 
1263  int height = area.GetEnd().y - area.GetOrigin().y;
1264 
1265  bool anyAdded = false;
1266  bool anySubtracted = false;
1267 
1268  // Construct an EDA_RECT to determine EDA_ITEM selection
1269  EDA_RECT selectionRect( (wxPoint) area.GetOrigin(), wxSize( width, height ) );
1270 
1271  selectionRect.Normalize();
1272 
1273  for( KIGFX::VIEW::LAYER_ITEM_PAIR& pair : selectedItems )
1274  {
1275  EDA_ITEM* item = dynamic_cast<EDA_ITEM*>( pair.first );
1276 
1277  if( item && Selectable( item ) && item->HitTest( selectionRect, windowSelection ) )
1278  {
1279  if( m_subtractive || ( m_exclusive_or && item->IsSelected() ) )
1280  {
1281  unselect( item );
1282  anySubtracted = true;
1283  }
1284  else
1285  {
1286  select( item );
1287  item->SetFlags( STARTPOINT | ENDPOINT );
1288  anyAdded = true;
1289  }
1290  }
1291  }
1292 
1293  m_selection.SetIsHover( false );
1294 
1295  // Inform other potentially interested tools
1296  if( anyAdded )
1298 
1299  if( anySubtracted )
1301 
1302  break; // Stop waiting for events
1303  }
1304  }
1305 
1306  getViewControls()->SetAutoPan( false );
1307 
1308  // Stop drawing the selection box
1309  view->Remove( &area );
1310  m_multiple = false; // Multiple selection mode is inactive
1311 
1312  if( !cancelled )
1314 
1315  return cancelled;
1316 }
1317 
1318 
1319 static KICAD_T nodeTypes[] =
1320 {
1322  SCH_PIN_T,
1327  SCH_LABEL_T,
1332  EOT
1333 };
1334 
1335 
1337 {
1338  EE_COLLECTOR collector;
1339 
1340  //TODO(snh): Reimplement after exposing KNN interface
1341  int thresholdMax = KiROUND(
1343 
1344  for( int threshold : { 0, thresholdMax/2, thresholdMax } )
1345  {
1346  collector.m_Threshold = threshold;
1347  collector.Collect( m_frame->GetScreen(), nodeTypes, (wxPoint) aPosition );
1348 
1349  if( collector.GetCount() > 0 )
1350  break;
1351  }
1352 
1353  return collector.GetCount() ? collector[ 0 ] : nullptr;
1354 }
1355 
1356 
1358 {
1359  VECTOR2I cursorPos = getViewControls()->GetCursorPosition( false );
1360 
1361  SelectPoint( cursorPos, nodeTypes );
1362 
1363  return 0;
1364 }
1365 
1366 
1368 {
1369  static KICAD_T wiresAndBuses[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT };
1370 
1371  RequestSelection( wiresAndBuses );
1372 
1373  if( m_selection.Empty() )
1374  return 0;
1375 
1376  SCH_LINE* line = (SCH_LINE*) m_selection.Front();
1377  EDA_ITEMS items;
1378 
1380  std::set<SCH_ITEM*> conns = m_frame->GetScreen()->MarkConnections( line );
1381 
1382  for( SCH_ITEM* item : conns )
1383  select( item );
1384 
1385  if( m_selection.GetSize() > 1 )
1387 
1388  return 0;
1389 }
1390 
1391 
1393 {
1394  AddItemToSel( aEvent.Parameter<EDA_ITEM*>() );
1395  m_selection.SetIsHover( false );
1396  return 0;
1397 }
1398 
1399 
1400 void EE_SELECTION_TOOL::AddItemToSel( EDA_ITEM* aItem, bool aQuietMode )
1401 {
1402  if( aItem )
1403  {
1404  select( aItem );
1405 
1406  // Inform other potentially interested tools
1407  if( !aQuietMode )
1409  }
1410 }
1411 
1412 
1414 {
1415  AddItemsToSel( aEvent.Parameter<EDA_ITEMS*>(), false );
1416  m_selection.SetIsHover( false );
1417  return 0;
1418 }
1419 
1420 
1421 void EE_SELECTION_TOOL::AddItemsToSel( EDA_ITEMS* aList, bool aQuietMode )
1422 {
1423  if( aList )
1424  {
1425  for( EDA_ITEM* item : *aList )
1426  select( item );
1427 
1428  // Inform other potentially interested tools
1429  if( !aQuietMode )
1431  }
1432 }
1433 
1434 
1436 {
1437  RemoveItemFromSel( aEvent.Parameter<EDA_ITEM*>() );
1438  m_selection.SetIsHover( false );
1439  return 0;
1440 }
1441 
1442 
1443 void EE_SELECTION_TOOL::RemoveItemFromSel( EDA_ITEM* aItem, bool aQuietMode )
1444 {
1445  if( aItem )
1446  {
1447  unselect( aItem );
1448 
1449  // Inform other potentially interested tools
1450  if( !aQuietMode )
1452  }
1453 }
1454 
1455 
1457 {
1458  RemoveItemsFromSel( aEvent.Parameter<EDA_ITEMS*>(), false );
1459  m_selection.SetIsHover( false );
1460  return 0;
1461 }
1462 
1463 
1464 void EE_SELECTION_TOOL::RemoveItemsFromSel( EDA_ITEMS* aList, bool aQuietMode )
1465 {
1466  if( aList )
1467  {
1468  for( EDA_ITEM* item : *aList )
1469  unselect( item );
1470 
1471  // Inform other potentially interested tools
1472  if( !aQuietMode )
1474  }
1475 }
1476 
1477 
1478 void EE_SELECTION_TOOL::RemoveItemsFromSel( std::vector<KIID>* aList, bool aQuietMode )
1479 {
1480  EDA_ITEMS removeItems;
1481 
1482  for( EDA_ITEM* item : m_selection )
1483  {
1484  if( alg::contains( *aList, item->m_Uuid ) )
1485  removeItems.push_back( item );
1486  }
1487 
1488  RemoveItemsFromSel( &removeItems, aQuietMode );
1489 }
1490 
1491 
1493 {
1494  highlight( aItem, BRIGHTENED );
1495 }
1496 
1497 
1499 {
1500  unhighlight( aItem, BRIGHTENED );
1501 }
1502 
1503 
1505 {
1506  ClearSelection();
1507 
1508  return 0;
1509 }
1510 
1511 
1513 {
1514  m_selection.Clear();
1515 
1516  if( m_isSymbolEditor )
1517  {
1518  LIB_SYMBOL* start = static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->GetCurSymbol();
1519 
1520  for( LIB_ITEM& item : start->GetDrawItems() )
1521  {
1522  if( item.IsSelected() )
1523  select( static_cast<EDA_ITEM*>( &item ) );
1524  }
1525  }
1526  else
1527  {
1528  for( SCH_ITEM* item : m_frame->GetScreen()->Items() )
1529  {
1530  // If the field and symbol are selected, only use the symbol
1531  if( item->IsSelected() )
1532  {
1533  select( item );
1534  }
1535  else
1536  {
1537  item->RunOnChildren(
1538  [&]( SCH_ITEM* aChild )
1539  {
1540  if( aChild->IsSelected() )
1541  select( aChild );
1542  } );
1543  }
1544  }
1545  }
1546 
1548 
1549  // Inform other potentially interested tools
1551 }
1552 
1553 
1555 {
1556  EE_COLLECTOR* collector = aEvent.Parameter<EE_COLLECTOR*>();
1557 
1558  if( !doSelectionMenu( collector ) )
1559  collector->m_MenuCancelled = true;
1560 
1561  return 0;
1562 }
1563 
1564 
1566 {
1567  EDA_ITEM* current = nullptr;
1568  bool selectAll = false;
1569  bool expandSelection = false;
1570 
1571  do
1572  {
1574  if( expandSelection )
1575  aCollector->Combine();
1576 
1577  expandSelection = false;
1578 
1579  int limit = std::min( 9, aCollector->GetCount() );
1580  ACTION_MENU menu( true );
1581 
1582  for( int i = 0; i < limit; ++i )
1583  {
1584  wxString text;
1585  EDA_ITEM* item = ( *aCollector )[i];
1587 
1588  wxString menuText = wxString::Format( "&%d. %s\t%d", i + 1, text, i + 1 );
1589  menu.Add( menuText, i + 1, item->GetMenuImage() );
1590  }
1591 
1592  menu.AppendSeparator();
1593  menu.Add( _( "Select &All\tA" ), limit + 1, BITMAPS::INVALID_BITMAP );
1594 
1595  if( !expandSelection && aCollector->HasAdditionalItems() )
1596  menu.Add( _( "&Expand Selection\tE" ), limit + 2, BITMAPS::INVALID_BITMAP );
1597 
1598  if( aCollector->m_MenuTitle.Length() )
1599  {
1600  menu.SetTitle( aCollector->m_MenuTitle );
1601  menu.SetIcon( BITMAPS::info );
1602  menu.DisplayTitle( true );
1603  }
1604  else
1605  {
1606  menu.DisplayTitle( false );
1607  }
1608 
1609  SetContextMenu( &menu, CMENU_NOW );
1610 
1611  while( TOOL_EVENT* evt = Wait() )
1612  {
1613  if( evt->Action() == TA_CHOICE_MENU_UPDATE )
1614  {
1615  if( selectAll )
1616  {
1617  for( int i = 0; i < aCollector->GetCount(); ++i )
1618  unhighlight( ( *aCollector )[i], BRIGHTENED );
1619  }
1620  else if( current )
1621  {
1622  unhighlight( current, BRIGHTENED );
1623  }
1624 
1625  int id = *evt->GetCommandId();
1626 
1627  // User has pointed an item, so show it in a different way
1628  if( id > 0 && id <= limit )
1629  {
1630  current = ( *aCollector )[id - 1];
1631  highlight( current, BRIGHTENED );
1632  }
1633  else
1634  {
1635  current = nullptr;
1636  }
1637 
1638  // User has pointed on the "Select All" option
1639  if( id == limit + 1 )
1640  {
1641  for( int i = 0; i < aCollector->GetCount(); ++i )
1642  highlight( ( *aCollector )[i], BRIGHTENED );
1643  selectAll = true;
1644  }
1645  else
1646  {
1647  selectAll = false;
1648  }
1649  }
1650  else if( evt->Action() == TA_CHOICE_MENU_CHOICE )
1651  {
1652  if( selectAll )
1653  {
1654  for( int i = 0; i < aCollector->GetCount(); ++i )
1655  unhighlight( ( *aCollector )[i], BRIGHTENED );
1656  }
1657  else if( current )
1658  unhighlight( current, BRIGHTENED );
1659 
1660  OPT<int> id = evt->GetCommandId();
1661 
1662  // User has selected the "Select All" option
1663  if( id == limit + 1 )
1664  {
1665  selectAll = true;
1666  current = nullptr;
1667  }
1668  else if( id == limit + 2 )
1669  {
1670  selectAll = false;
1671  current = nullptr;
1672  expandSelection = true;
1673  }
1674  // User has selected an item, so this one will be returned
1675  else if( id && ( *id > 0 ) && ( *id <= limit ) )
1676  {
1677  selectAll = false;
1678  current = ( *aCollector )[*id - 1];
1679  }
1680  // User has cancelled the menu (either by <esc> or clicking out of it)
1681  else
1682  {
1683  selectAll = false;
1684  current = nullptr;
1685  }
1686  }
1687  else if( evt->Action() == TA_CHOICE_MENU_CLOSED )
1688  {
1689  break;
1690  }
1691 
1692  getView()->UpdateItems();
1693  m_frame->GetCanvas()->Refresh();
1694  }
1695  } while( expandSelection );
1696 
1697  if( selectAll )
1698  return true;
1699  else if( current )
1700  {
1701  unhighlight( current, BRIGHTENED );
1702 
1703  getView()->UpdateItems();
1704  m_frame->GetCanvas()->Refresh();
1705 
1706  aCollector->Empty();
1707  aCollector->Append( current );
1708  return true;
1709  }
1710 
1711  return false;
1712 }
1713 
1714 
1715 bool EE_SELECTION_TOOL::Selectable( const EDA_ITEM* aItem, bool checkVisibilityOnly ) const
1716 {
1717  // NOTE: in the future this is where Eeschema layer/itemtype visibility will be handled
1718 
1719  SYMBOL_EDIT_FRAME* symEditFrame = dynamic_cast<SYMBOL_EDIT_FRAME*>( m_frame );
1720 
1721  // Do not allow selection of anything except fields when the current symbol in the symbol
1722  // editor is a derived symbol.
1723  if( symEditFrame && symEditFrame->IsSymbolAlias() && aItem->Type() != LIB_FIELD_T )
1724  return false;
1725 
1726  switch( aItem->Type() )
1727  {
1728  case SCH_PIN_T:
1729  if( !static_cast<const SCH_PIN*>( aItem )->IsVisible() && !m_frame->GetShowAllPins() )
1730  return false;
1731  break;
1732 
1733  case LIB_SYMBOL_T: // In symbol_editor we do not want to select the symbol itself.
1734  return false;
1735 
1736  case LIB_FIELD_T: // LIB_FIELD object can always be edited.
1737  break;
1738 
1739  case LIB_ARC_T:
1740  case LIB_CIRCLE_T:
1741  case LIB_TEXT_T:
1742  case LIB_RECTANGLE_T:
1743  case LIB_POLYLINE_T:
1744  case LIB_BEZIER_T:
1745  case LIB_PIN_T:
1746  {
1747  if( symEditFrame )
1748  {
1749  LIB_ITEM* lib_item = (LIB_ITEM*) aItem;
1750 
1751  if( lib_item->GetUnit() && lib_item->GetUnit() != symEditFrame->GetUnit() )
1752  return false;
1753 
1754  if( lib_item->GetConvert() && lib_item->GetConvert() != symEditFrame->GetConvert() )
1755  return false;
1756  }
1757 
1758  break;
1759  }
1760 
1761  case SCH_MARKER_T: // Always selectable
1762  return true;
1763 
1764  default: // Suppress warnings
1765  break;
1766  }
1767 
1768  return true;
1769 }
1770 
1771 
1773 {
1774  if( m_selection.Empty() )
1775  return;
1776 
1777  while( m_selection.GetSize() )
1779 
1780  getView()->Update( &m_selection );
1781 
1782  m_selection.SetIsHover( false );
1784 
1785  // Inform other potentially interested tools
1787 }
1788 
1789 
1791 {
1792  highlight( aItem, SELECTED, &m_selection );
1793 }
1794 
1795 
1797 {
1798  unhighlight( aItem, SELECTED, &m_selection );
1799 }
1800 
1801 
1802 void EE_SELECTION_TOOL::highlight( EDA_ITEM* aItem, int aMode, EE_SELECTION* aGroup )
1803 {
1804  KICAD_T itemType = aItem->Type();
1805 
1806  if( aMode == SELECTED )
1807  aItem->SetSelected();
1808  else if( aMode == BRIGHTENED )
1809  aItem->SetBrightened();
1810 
1811  if( aGroup )
1812  aGroup->Add( aItem );
1813 
1814  // Highlight pins and fields. (All the other symbol children are currently only
1815  // represented in the LIB_SYMBOL and will inherit the settings of the parent symbol.)
1816  if( SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( aItem ) )
1817  {
1818  sch_item->RunOnChildren(
1819  [&]( SCH_ITEM* aChild )
1820  {
1821  if( aMode == SELECTED )
1822  aChild->SetSelected();
1823  else if( aMode == BRIGHTENED )
1824  aChild->SetBrightened();
1825  } );
1826  }
1827 
1828  if( itemType == SCH_PIN_T || itemType == SCH_FIELD_T || itemType == SCH_SHEET_PIN_T )
1829  getView()->Update( aItem->GetParent() );
1830  else
1831  getView()->Update( aItem );
1832 }
1833 
1834 
1835 void EE_SELECTION_TOOL::unhighlight( EDA_ITEM* aItem, int aMode, EE_SELECTION* aGroup )
1836 {
1837  KICAD_T itemType = aItem->Type();
1838 
1839  if( aMode == SELECTED )
1840  aItem->ClearSelected();
1841  else if( aMode == BRIGHTENED )
1842  aItem->ClearBrightened();
1843 
1844  if( aGroup )
1845  aGroup->Remove( aItem );
1846 
1847  // Unhighlight pins and fields. (All the other symbol children are currently only
1848  // represented in the LIB_SYMBOL.)
1849  if( SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( aItem ) )
1850  {
1851  sch_item->RunOnChildren(
1852  [&]( SCH_ITEM* aChild )
1853  {
1854  if( aMode == SELECTED )
1855  aChild->ClearSelected();
1856  else if( aMode == BRIGHTENED )
1857  aChild->ClearBrightened();
1858  } );
1859  }
1860 
1861  if( itemType == SCH_PIN_T || itemType == SCH_FIELD_T || itemType == SCH_SHEET_PIN_T )
1862  getView()->Update( aItem->GetParent() );
1863  else
1864  getView()->Update( aItem );
1865 }
1866 
1867 
1869 {
1870  const unsigned GRIP_MARGIN = 20;
1871  VECTOR2I margin = getView()->ToWorld( VECTOR2I( GRIP_MARGIN, GRIP_MARGIN ), false );
1872 
1873  // Check if the point is located within any of the currently selected items bounding boxes
1874  for( EDA_ITEM* item : m_selection )
1875  {
1876  BOX2I itemBox = item->ViewBBox();
1877  itemBox.Inflate( margin.x, margin.y ); // Give some margin for gripping an item
1878 
1879  if( itemBox.Contains( aPoint ) )
1880  return true;
1881  }
1882 
1883  return false;
1884 }
1885 
1886 
1888 {
1890 
1895 
1901 
1903 }
1904 
1905 
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:146
void Empty()
Clear the list.
Definition: collector.h:95
static TOOL_ACTION editPageNumber
Definition: ee_actions.h:151
void SetEnd(const VECTOR2I &aEnd)
Set the current end of the rectangle (the corner that moves with the cursor.
void ClearReferencePoint()
Definition: selection.h:191
static TOOL_ACTION pinTable
Definition: ee_actions.h:142
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:117
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:49
void AddStandardSubMenus(TOOL_MENU &aMenu)
Construct a "basic" menu for a tool, containing only items that apply to all tools (e....
void OnIdle(wxIdleEvent &aEvent)
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:283
static const TOOL_EVENT SelectedEvent
Definition: actions.h:199
TOOL_MENU m_menu
The functions below are not yet implemented - their interface may change.
bool selectionContains(const VECTOR2I &aPoint) const
Set up handlers for various events.
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:82
KIID niluuid(0)
bool IsUnconnected() const
static bool IsDrawingWire(const SELECTION &aSelection)
#define STARTPOINT
When a line is selected, these flags indicate which.
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
int SelectAll(const TOOL_EVENT &aEvent)
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:131
static SELECTION_CONDITION SingleSymbol
wxPoint GetStartPoint() const
Definition: sch_line.h:90
bool IsSelected() const
Definition: eda_item.h:123
Model changes (required full reload)
Definition: tool_base.h:80
static const TOOL_EVENT UnselectedEvent
Definition: actions.h:200
#define IS_NEW
New item, just created.
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:48
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:450
virtual void Add(EDA_ITEM *aItem)
Definition: selection.cpp:31
void ClearSelected()
Definition: eda_item.h:132
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)
Scan 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:60
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.
const KICAD_T movableSymbolAliasItems[]
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:46
static TOOL_ACTION placeHierLabel
Definition: ee_actions.h:84
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:214
static TOOL_ACTION placeJunction
Definition: ee_actions.h:80
static TOOL_ACTION selectConnection
If current selection is a wire or bus, expand to entire connection.
Definition: ee_actions.h:50
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:351
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with SCH_FIELDs.
Definition: sch_symbol.cpp:702
int GetWidth() const
Definition: eda_rect.h:109
bool selectMultiple()
Handle drawing a selection box that allows one to select many items at the same time.
static TOOL_ACTION unfoldBus
Definition: ee_actions.h:78
void SetBrightened()
Definition: eda_item.h:130
static TOOL_ACTION zoomFitScreen
Definition: actions.h:96
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:153
#define HITTEST_THRESHOLD_PIXELS
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:143
void SetExclusiveOr(bool aExclusiveOr)
bool Selectable(const EDA_ITEM *aItem, bool checkVisibilityOnly=false) const
Check conditions for an item to be selected.
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:189
Symbol library viewer main window.
int AddItemsToSel(const TOOL_EVENT &aEvent)
void select(EDA_ITEM *aItem)
Take necessary action mark an item as selected.
Schematic editor (Eeschema) main window.
void UpdateAll()
Run update handlers for the menu and its submenus.
KICURSOR
Definition: cursors.h:33
static TOOL_ACTION zoomFitObjects
Definition: actions.h:97
#define ENDPOINT
ends. (Used to support dragging.)
static TOOL_ACTION removeItemsFromSel
Definition: ee_actions.h:61
static TOOL_ACTION importSingleSheetPin
Definition: ee_actions.h:184
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:623
Define a library symbol object.
Definition: lib_symbol.h:96
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).
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.
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 symbols.
Definition: lib_item.h:61
static TOOL_ACTION breakWire
Definition: ee_actions.h:130
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:164
void SetIsHover(bool aIsHover)
Definition: selection.h:68
const KICAD_T movableSymbolItems[]
void setModifiersState(bool aShiftState, bool aCtrlState, bool aAltState)
Set the configuration of m_additive, m_subtractive, m_exclusive_or, m_skip_heuristics from the state ...
static TOOL_ACTION leaveSheet
Definition: ee_actions.h:181
void ClearBrightened()
Definition: eda_item.h:133
static TOOL_ACTION removeItemFromSel
Definition: ee_actions.h:57
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()
Return the set of currently selected items.
EESCHEMA_SETTINGS * eeconfig() const
EE_SELECTION & RequestSelection(const KICAD_T *aFilterList=EE_COLLECTOR::AllItems)
Return either an existing selection (filtered), or the selection at the current cursor if the existin...
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:225
void updateReferencePoint()
Set 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)
If node selected then expand to connection, otherwise select connection under cursor.
Definition: kiid.h:44
void SetReferencePoint(const VECTOR2I &aP)
Definition: selection.h:186
int GetUnit() const
Definition: lib_item.h:259
void SetOrigin(const VECTOR2I &aOrigin)
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)
This is the primary SelectPoint method that will prompt the user with a menu to disambiguate multiple...
void highlight(EDA_ITEM *aItem, int aHighlightMode, EE_SELECTION *aGroup=nullptr)
Highlight the item visually.
void narrowSelection(EE_COLLECTOR &collector, const VECTOR2I &aWhere, bool aCheckLocked)
Apply rules to narrow the collection down to selectable objects, and then heuristics to try and narro...
MOUSE_DRAG_ACTION GetDragAction() const
Indicates whether a drag should draw a selection rectangle or drag selected (or unselected) objects.
Definition: tools_holder.h:135
#define IS_MOVING
Item being moved.
static TOOL_ACTION addItemToSel
Selects an item (specified as the event parameter).
Definition: ee_actions.h:56
void SetSelected()
Definition: eda_item.h:129
bool IsSymbolAlias() const
Restore the empty editor screen, without any symbol or library selected.
static TOOL_ACTION drawWire
Definition: ee_actions.h:76
static SELECTION_CONDITION LessThan(int aNumber)
Create a functor that tests if the number of selected items is smaller than the value given as parame...
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagate an event to tools that requested events of matching type(s).
static TOOL_ACTION explicitCrossProbe
Definition: ee_actions.h:195
T Parameter() const
Return a non-standard parameter assigned to the event.
Definition: tool_event.h:427
static TOOL_ACTION symbolProperties
Definition: ee_actions.h:141
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
bool Contains(const Vec &aPoint) const
Definition: box2.h:134
Generic, UI-independent tool event.
Definition: tool_event.h:152
void SetMaximum()
Definition: box2.h:57
const BOX2I ViewBBox() const override
Set the origin of the rectangle (the fixed corner)
SCHEMATIC & Schematic() const
bool ToolStackIsEmpty()
Definition: tools_holder.h:116
EDA_ITEM * GetParent() const
Definition: eda_item.h:115
#define _(s)
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:154
int SelectConnection(const TOOL_EVENT &aEvent)
Clear current selection event handler.
static const TOOL_EVENT ClearedEvent
Selected item had a property changed (except movement)
Definition: actions.h:201
#define SELECTED
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Place the cursor immediately at a given point.
virtual bool IsType(const KICAD_T aScanTypes[]) const
Check whether the item is one of the listed types.
Definition: eda_item.h:183
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:1397
static TOOL_ACTION selectionActivate
Activation of the selection tool.
Definition: ee_actions.h:43
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:65
std::vector< EDA_ITEM * > EDA_ITEMS
Define list of drawing items for screens.
Definition: eda_item.h:507
static TOOL_ACTION clearSelection
Clears the current selection.
Definition: ee_actions.h:53
bool CollectHits(EE_COLLECTOR &aCollector, const VECTOR2I &aWhere, const KICAD_T *aFilterList=EE_COLLECTOR::AllItems)
Select one or more items at the location given by parameter aWhere.
static TOOL_ACTION updateMenu
Definition: actions.h:167
static SELECTION_CONDITION SingleMultiUnitSymbol
int GetConvert() const
Definition: lib_item.h:262
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition: lib_symbol.h:473
void UnbrightenItem(EDA_ITEM *aItem)
EDA_ITEM * GetNode(VECTOR2I aPosition)
Select node under cursor.
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:98
int GetHeight() const
Definition: eda_rect.h:110
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
virtual EDA_ITEM * GetItem(const KIID &aId) const
Fetch an item by KIID.
virtual void SetAutoPan(bool aEnabled)
Turn on/off auto panning (this feature is used when there is a tool active (eg.
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:97
static bool IsDrawingBus(const SELECTION &aSelection)
static TOOL_ACTION drawBus
Definition: ee_actions.h:77
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:54
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:87
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition: sch_sheet.h:184
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
static TOOL_ACTION placeLabel
Definition: ee_actions.h:82
int RemoveItemFromSel(const TOOL_EVENT &aEvent)
const VECTOR2D & GetGridSize() const
Return the grid size.
void Normalize()
Ensures that the height ant width are positive.
Definition: eda_rect.cpp:35
SCH_FIELD * GetIntersheetRefs()
Definition: sch_text.h:403
void unselect(EDA_ITEM *aItem)
Take necessary action mark an item as unselected.
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)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:281
virtual bool IsPointClickableAnchor(const wxPoint &aPos) const
Definition: sch_item.h:368
bool IsNet() const
SCH_SHEET & Root() const
Definition: schematic.h:92
static KICAD_T nodeTypes[]
bool HasAdditionalItems()
Test if the collector has heuristic backup items.
Definition: collector.h:140
Schematic symbol object.
Definition: sch_symbol.h:78
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)
This overload of SelectPoint will create an EE_COLLECTOR and collect hits at location aWhere before c...
virtual KIGFX::VIEW_ITEM * GetItem(unsigned int aIdx) const override
Definition: selection.cpp:52
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
int SelectionMenu(const TOOL_EVENT &aEvent)
Show a popup menu to trim the COLLECTOR passed as aEvent's parameter down to a single item.
#define IS_ROLLOVER
Rollover active. Used for hyperlink highlighting.
bool doSelectionMenu(EE_COLLECTOR *aItems)
Allow 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:148
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:109
virtual BITMAPS GetMenuImage() const
Return a pointer to an image to be used in menus.
Definition: eda_item.cpp:211
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:184
static TOOL_ACTION selectionMenu
Runs a selection menu to select from a list of items.
Definition: ee_actions.h:64
virtual void Remove(EDA_ITEM *aItem)
Definition: selection.cpp:43
EE_RTREE & Items()
Definition: sch_screen.h:102
static SELECTION_CONDITION OnlyType(KICAD_T aType)
Create a functor that tests if the selected items are only of given type.
void RebuildSelection()
Rebuild the selection from the EDA_ITEMs' selection flags.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
Handle the component boundary box.
Definition: eda_rect.h:42
static const KICAD_T AllItems[]
Definition: ee_collectors.h:42
TOOL_EVENT MakeEvent() const
Return the event associated with the action (i.e.
Definition: tool_action.cpp:72
int Size() const
Returns the number of selected parts.
Definition: selection.h:103
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:46
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:73
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:100
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:77
static TOOL_ACTION enterSheet
Definition: ee_actions.h:180
boost::optional< T > OPT
Definition: optional.h:7
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1449
static SELECTION_CONDITION SingleSymbolOrPower
void Combine()
Re-combine the backup list into the main list of the collector.
Definition: collector.h:148
SCH_SHEET_PATH & GetCurrentSheet() const
Represent a selection area (currently a rectangle) in a VIEW, drawn corner-to-corner between two poin...
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:293
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:321
static TOOL_ACTION drawLines
Definition: ee_actions.h:88
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
void ClearDrawingState()
Clear the state flags of all the items in the screen.
Definition: sch_screen.cpp:824
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:427
virtual const EDA_RECT GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:75
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
bool IsBus() const
static TOOL_ACTION placeGlobalLabel
Definition: ee_actions.h:83
static TOOL_ACTION finishBus
Definition: ee_actions.h:92
int RemoveItemsFromSel(const TOOL_EVENT &aEvent)
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:197
static TOOL_ACTION selectAll
Definition: actions.h:70
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:91
void unhighlight(EDA_ITEM *aItem, int aHighlightMode, EE_SELECTION *aGroup=nullptr)
Unhighlight 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:144
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Inflate the rectangle horizontally by dx and vertically by dy.
Definition: eda_rect.cpp:364
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:1503
const KICAD_T movableSchematicItems[]
OPT< TOOL_EVENT > OPT_TOOL_EVENT
Definition: tool_event.h:543
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113
int Main(const TOOL_EVENT &aEvent)
The main loop.
#define BRIGHTENED
item is drawn with a bright contour
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 symbol pin.
Definition: sch_screen.cpp:345
wxPoint GetEndPoint() const
Definition: sch_line.h:93