KiCad PCB EDA Suite
cvpcb_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) 2018 KiCad Developers, see AUTHORS.txt for contributors.
5  *
6  * This program is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation, either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <limits>
21 
22 #include <functional>
23 using namespace std::placeholders;
24 
25 #include <class_draw_panel_gal.h>
26 #include <view/view.h>
27 #include <hotkeys.h>
28 
29 #include <tool/tool_event.h>
30 #include <tool/tool_manager.h>
32 
33 #include <cvpcb_id.h>
34 
35 #include "cvpcb_selection_tool.h"
36 #include "cvpcb_actions.h"
37 
38 // Selection tool actions
39 TOOL_ACTION CVPCB_ACTIONS::selectionActivate( "cvpcb.InteractiveSelection",
40  AS_GLOBAL, 0,
41  "", "", NULL, AF_ACTIVATE ); // No description, it is not supposed to be shown anywhere
42 
43 
44 TOOL_ACTION CVPCB_ACTIONS::measureTool( "cvpcb.InteractiveSelection.measureTool",
46  _( "Measure Tool" ), _( "Interactively measure distance between points" ),
47  nullptr, AF_ACTIVATE );
48 
49 
51  TOOL_INTERACTIVE( "cvpcb.InteractiveSelection" ),
52  m_frame( NULL ), m_menu( *this )
53 {
54 }
55 
56 
58 {
59  getView()->Remove( &m_selection );
60 }
61 
62 
64 {
65  m_menu.AddStandardSubMenus( *getEditFrame<DISPLAY_FOOTPRINTS_FRAME>() );
66 
67  return true;
68 }
69 
70 
72 {
73  m_frame = getEditFrame<DISPLAY_FOOTPRINTS_FRAME>();
74 }
75 
76 
78 {
79  // Main loop: keep receiving events
80  while( OPT_TOOL_EVENT evt = Wait() )
81  {
82  // This is kind of hacky: activate RMB drag on any event.
83  // There doesn't seem to be any other good way to tell when another tool
84  // is canceled and control returns to the selection tool, except by the
85  // fact that the selection tool starts to get events again.
87  {
88  getViewControls()->SetAdditionalPanButtons( false, true );
89  }
90 
91  // Disable RMB pan for other tools; they can re-enable if desired
92  if( evt->IsActivate() )
93  {
94  getViewControls()->SetAdditionalPanButtons( false, false );
95  }
96 
97  // single click? Select single object
98  if( evt->IsClick( BUT_LEFT ) )
99  {
100  clearSelection();
101  }
102 
103  // right click? if there is any object - show the context menu
104  else if( evt->IsClick( BUT_RIGHT ) )
105  {
107  }
108 
109  else if( evt->IsCancel() || evt->Action() == TA_UNDO_REDO_PRE )
110  {
111  clearSelection();
112  }
113 
114  else if( evt->Action() == TA_CONTEXT_MENU_CLOSED )
115  {
116  m_menu.CloseContextMenu( evt );
117  }
118  }
119 
120  // This tool is supposed to be active forever
121  wxASSERT( false );
122 
123  return 0;
124 }
125 
126 
128 {
129  return m_selection;
130 }
131 
132 
134 {
137 }
138 
139 /*
140 void CVPCB_SELECTION_TOOL::zoomFitSelection( void )
141 {
142  //Should recalculate the view to zoom in on the selection
143  auto selectionBox = m_selection.ViewBBox();
144  auto canvas = m_frame->GetGalCanvas();
145  auto view = getView();
146 
147  VECTOR2D screenSize = view->ToWorld( canvas->GetClientSize(), false );
148 
149  if( !( selectionBox.GetWidth() == 0 ) || !( selectionBox.GetHeight() == 0 ) )
150  {
151  VECTOR2D vsize = selectionBox.GetSize();
152  double scale = view->GetScale() / std::max( fabs( vsize.x / screenSize.x ),
153  fabs( vsize.y / screenSize.y ) );
154  view->SetScale( scale );
155  view->SetCenter( selectionBox.Centre() );
156  view->Add( &m_selection );
157  }
158 
159  m_frame->GetGalCanvas()->ForceRefresh();
160 }
161 */
162 
164 {
165  auto& view = *getView();
166  auto& controls = *getViewControls();
167  auto previous_settings = controls.GetSettings();
168 
169  Activate();
170  m_frame->SetToolID( ID_TB_MEASUREMENT_TOOL, wxCURSOR_PENCIL,
171  _( "Measure distance" ) );
172 
174  KIGFX::PREVIEW::RULER_ITEM ruler( twoPtMgr, m_frame->GetUserUnits() );
175 
176  view.Add( &ruler );
177  view.SetVisible( &ruler, false );
178 
179  bool originSet = false;
180 
181  controls.ShowCursor( true );
182  controls.SetSnapping( true );
183  controls.SetAdditionalPanButtons( false, true );
184 
185  while( auto evt = Wait() )
186  {
187  const VECTOR2I cursorPos = controls.GetCursorPosition();
188 
189  if( evt->IsCancel() || evt->IsActivate() )
190  {
191  break;
192  }
193 
194  // click or drag starts
195  else if( !originSet &&
196  ( evt->IsDrag( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) )
197  {
198  if( !evt->IsDrag( BUT_LEFT ) )
199  {
200  twoPtMgr.SetOrigin( cursorPos );
201  twoPtMgr.SetEnd( cursorPos );
202  }
203 
204  controls.CaptureCursor( true );
205  controls.SetAutoPan( true );
206 
207  originSet = true;
208  }
209 
210  else if( !originSet && evt->IsMotion() )
211  {
212  // make sure the origin is set before a drag starts
213  // otherwise you can miss a step
214  twoPtMgr.SetOrigin( cursorPos );
215  twoPtMgr.SetEnd( cursorPos );
216  }
217 
218  // second click or mouse up after drag ends
219  else if( originSet &&
220  ( evt->IsClick( BUT_LEFT ) || evt->IsMouseUp( BUT_LEFT ) ) )
221  {
222  originSet = false;
223 
224  controls.SetAutoPan( false );
225  controls.CaptureCursor( false );
226 
227  view.SetVisible( &ruler, false );
228  }
229 
230  // move or drag when origin set updates rules
231  else if( originSet &&
232  ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) )
233  {
234  twoPtMgr.SetAngleSnap( evt->Modifier( MD_CTRL ) );
235  twoPtMgr.SetEnd( cursorPos );
236 
237  view.SetVisible( &ruler, true );
238  view.Update( &ruler, KIGFX::GEOMETRY );
239  }
240 
241  else if( evt->IsClick( BUT_RIGHT ) )
242  {
244  }
245  }
246 
247  view.SetVisible( &ruler, false );
248  view.Remove( &ruler );
249 
250  controls.ApplySettings( previous_settings );
251 
253 
254  return 0;
255 }
256 
257 const BOX2I SELECTION::ViewBBox() const
258 {
259  EDA_RECT eda_bbox;
260 
261  if( Size() == 1 )
262  {
263  eda_bbox = Front()->GetBoundingBox();
264  }
265  else if( Size() > 1 )
266  {
267  eda_bbox = Front()->GetBoundingBox();
268  auto i = m_items.begin();
269  ++i;
270 
271  for( ; i != m_items.end(); ++i )
272  {
273  eda_bbox.Merge( (*i)->GetBoundingBox() );
274  }
275  }
276 
277  return BOX2I( eda_bbox.GetOrigin(), eda_bbox.GetSize() );
278 }
279 
280 
282 {
283  std::vector<VIEW_ITEM*> items;
284 
285  for( auto item : m_items )
286  items.push_back( item );
287 
288  return items;
289 }
BOX2< VECTOR2I > BOX2I
Definition: box2.h:520
virtual void SetToolID(int aId, int aCursor, const wxString &aToolMsg) override
Set the tool command ID to aId and sets the cursor to aCursor.
const wxPoint GetOrigin() const
Definition: eda_rect.h:112
void Merge(const EDA_RECT &aRect)
Function Merge modifies the position and size of the rectangle in order to contain aRect...
const wxSize GetSize() const
Definition: eda_rect.h:101
static TOOL_ACTION selectionActivate
Activation of the selection tool.
Definition: cvpcb_actions.h:47
virtual const VIEW_GROUP::ITEMS updateDrawList() const override
Definition: selection.cpp:140
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
Class TWO_POINT_GEOMETRY_MANAGER.
SELECTION m_selection
Current state of selection (not really used: no selection in display footprints frame).
virtual void Remove(VIEW_ITEM *aItem)
Function Remove() Removes a VIEW_ITEM from the view.
Definition: view.cpp:365
OPT_TOOL_EVENT Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
TOOL_MENU m_menu
Menu model displayed by the tool.
static int LegacyHotKey(int aHotKey)
Creates a hot key code that refers to a legacy hot key setting, instead of a particular key...
Definition: tool_action.h:174
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Function Go()
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
int MeasureTool(const TOOL_EVENT &aEvent)
Launches a tool to measure between points
Pcbnew hotkeys.
const BOX2I ViewBBox() const override
Function ViewBBox() Returns the bounding box for all stored items covering all its layers...
Definition: selection.cpp:132
void AddStandardSubMenus(EDA_DRAW_FRAME &aFrame)
Function CreateBasicMenu.
Definition: tool_menu.cpp:95
DISPLAY_FOOTPRINTS_FRAME * m_frame
Pointer to the parent frame.
EDA_UNITS_T GetUserUnits() const override
Return the user units currently in use.
Definition: draw_frame.h:284
Class TOOL_EVENT.
Definition: tool_event.h:168
void SetOrigin(const VECTOR2I &aOrigin)
Set the origin of the ruler (the fixed end)
Class RULER_ITEM.
Definition: ruler_item.h:43
void clearSelection()
Clears the current selection.
All active tools
Definition: tool_event.h:144
int Main(const TOOL_EVENT &aEvent)
Function Main()
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:41
KIGFX::VIEW * getView() const
Function getView()
Definition: tool_base.cpp:35
std::vector< VIEW_ITEM * > ITEMS
Definition: view_group.h:45
void setTransitions() override
Sets up handlers for various events.
void SetAdditionalPanButtons(bool aLeft=false, bool aRight=false)
virtual void SetNoToolSelected()
Select the ID_NO_TOOL_SELECTED id tool (Idle tool)
SELECTION & GetSelection()
Returns the set of currently selected items.
void CloseContextMenu(OPT_TOOL_EVENT &evt)
Function CloseContextMenu.
Definition: tool_menu.cpp:82
int GetToolId() const
Definition: draw_frame.h:519
Class TOOL_ACTION.
Definition: tool_action.h:46
size_t i
Definition: json11.cpp:597
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:80
void Activate()
Function Activate() Runs the tool.
void ShowContextMenu(SELECTION &aSelection)
Function ShowContextMenu.
Definition: tool_menu.cpp:62
static TOOL_ACTION measureTool
Definition: cvpcb_actions.h:51
void SetEnd(const VECTOR2I &aEnd)
Set the current end of the rectangle (the end that moves with the cursor.
OPT< TOOL_EVENT > OPT_TOOL_EVENT
Definition: tool_event.h:495
Color has changed.
Definition: view_item.h:57