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