KiCad PCB EDA Suite
cvpcb_fpviewer_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-2019 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 <functional>
21 using namespace std::placeholders;
22 
23 #include <bitmaps.h>
25 #include <tool/tool_event.h>
26 #include <tools/cvpcb_actions.h>
28 #include <view/view.h>
29 #include <view/view_controls.h>
30 
32  TOOL_INTERACTIVE( "cvpcb.FootprintViewerInteractiveSelection" ),
33  m_frame( nullptr )
34 {
35 }
36 
37 
39 {
40  getEditFrame<DISPLAY_FOOTPRINTS_FRAME>()->AddStandardSubMenus( m_menu );
41  return true;
42 }
43 
44 
46 {
47  m_frame = getEditFrame<DISPLAY_FOOTPRINTS_FRAME>();
48 }
49 
50 
52 {
53  // Main loop: keep receiving events
54  while( TOOL_EVENT* evt = Wait() )
55  {
56  if( m_frame->ToolStackIsEmpty() )
57  m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
58 
59  // This is kind of hacky: activate RMB drag on any event.
60  // There doesn't seem to be any other good way to tell when another tool
61  // is canceled and control returns to the selection tool, except by the
62  // fact that the selection tool starts to get events again.
64  {
65  getViewControls()->SetAdditionalPanButtons( false, true );
66  }
67 
68  // Disable RMB pan for other tools; they can re-enable if desired
69  if( evt->IsActivate() )
70  {
71  getViewControls()->SetAdditionalPanButtons( false, false );
72  }
73 
74  // single click? Select single object
75  if( evt->IsClick( BUT_LEFT ) )
76  {
78  }
79 
80  // right click? if there is any object - show the context menu
81  else if( evt->IsClick( BUT_RIGHT ) )
82  {
84  }
85 
86  else if( evt->IsCancel() || evt->Action() == TA_UNDO_REDO_PRE )
87  {
89  }
90 
91  else
92  evt->SetPassEvent();
93  }
94 
95  // This tool is supposed to be active forever
96  wxASSERT( false );
97 
98  return 0;
99 }
100 
101 
103 {
104  auto& view = *getView();
105  auto& controls = *getViewControls();
106  auto previous_settings = controls.GetSettings();
107 
108  std::string tool = aEvent.GetCommandStr().get();
109  m_frame->PushTool( tool );
110  Activate();
111 
113  KIGFX::PREVIEW::RULER_ITEM ruler( twoPtMgr, m_frame->GetUserUnits() );
114 
115  view.Add( &ruler );
116  view.SetVisible( &ruler, false );
117 
118  bool originSet = false;
119 
120  controls.ShowCursor( true );
121  controls.SetSnapping( true );
122  controls.SetAdditionalPanButtons( false, true );
123 
124  while( TOOL_EVENT* evt = Wait() )
125  {
126  m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
127  const VECTOR2I cursorPos = controls.GetCursorPosition();
128 
129  auto clearRuler = [&]() {
130  view.SetVisible( &ruler, false );
131  controls.SetAutoPan( false );
132  controls.CaptureCursor( false );
133  originSet = false;
134  };
135 
136  if( evt->IsCancelInteractive() )
137  {
138  if( originSet )
139  clearRuler();
140  else
141  {
142  m_frame->PopTool( tool );
143  break;
144  }
145  }
146 
147  else if( evt->IsActivate() )
148  {
149  if( originSet )
150  clearRuler();
151 
152  if( evt->IsMoveTool() )
153  {
154  // leave ourselves on the stack so we come back after the move
155  break;
156  }
157  else
158  {
159  m_frame->PopTool( tool );
160  break;
161  }
162  }
163 
164  // click or drag starts
165  else if( !originSet && ( evt->IsDrag( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) )
166  {
167  if( !evt->IsDrag( BUT_LEFT ) )
168  {
169  twoPtMgr.SetOrigin( cursorPos );
170  twoPtMgr.SetEnd( cursorPos );
171  }
172 
173  controls.CaptureCursor( true );
174  controls.SetAutoPan( true );
175 
176  originSet = true;
177  }
178 
179  else if( !originSet && evt->IsMotion() )
180  {
181  // make sure the origin is set before a drag starts
182  // otherwise you can miss a step
183  twoPtMgr.SetOrigin( cursorPos );
184  twoPtMgr.SetEnd( cursorPos );
185  }
186 
187  // second click or mouse up after drag ends
188  else if( originSet && ( evt->IsClick( BUT_LEFT ) || evt->IsMouseUp( BUT_LEFT ) ) )
189  {
190  originSet = false;
191 
192  controls.SetAutoPan( false );
193  controls.CaptureCursor( false );
194 
195  view.SetVisible( &ruler, false );
196  }
197 
198  // move or drag when origin set updates rules
199  else if( originSet && ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) )
200  {
201  twoPtMgr.SetAngleSnap( evt->Modifier( MD_CTRL ) );
202  twoPtMgr.SetEnd( cursorPos );
203 
204  view.SetVisible( &ruler, true );
205  view.Update( &ruler, KIGFX::GEOMETRY );
206  }
207 
208  else if( evt->IsClick( BUT_RIGHT ) )
209  {
211  }
212 
213  else
214  evt->SetPassEvent();
215  }
216 
217  view.SetVisible( &ruler, false );
218  view.Remove( &ruler );
219  controls.ApplySettings( previous_settings );
220  return 0;
221 }
222 
224 {
226  CVPCB_ACTIONS::selectionActivate.MakeEvent() );
228 }
virtual void PushTool(const std::string &actionName)
NB: the definition of "tool" is different at the user level.
TOOL_MENU m_menu
functions below are not yet implemented - their interface may change
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
int MeasureTool(const TOOL_EVENT &aEvent)
Launches a tool to measure between points
void SetCurrentCursor(wxStockCursor aStockCursorID)
Function SetCurrentCursor Set the current cursor shape for this panel.
VIEW_CONTROLS class definition.
static TOOL_ACTION selectionActivate
Activation actions.
Definition: cvpcb_actions.h:44
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Function Go()
DISPLAY_FOOTPRINTS_FRAME * m_frame
Pointer to the parent frame.
static TOOL_ACTION measureTool
Definition: actions.h:144
void setTransitions() override
Sets up handlers for various events.
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
Class TOOL_EVENT.
Definition: tool_event.h:171
void SetOrigin(const VECTOR2I &aOrigin)
Set the origin of the ruler (the fixed end)
Class RULER_ITEM.
Definition: ruler_item.h:43
KIGFX::VIEW * getView() const
Function getView()
Definition: tool_base.cpp:36
int Main(const TOOL_EVENT &aEvent)
Function Main()
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:463
void SetAdditionalPanButtons(bool aLeft=false, bool aRight=false)
bool ToolStackIsEmpty()
EDA_UNITS_T GetUserUnits() const
Return the user units currently in use.
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:79
SELECTION m_selection
Current state of selection (not really used: no selection in display footprints frame).
virtual void PopTool(const std::string &actionName)
void Activate()
Function Activate() Runs the tool.
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:42
bool IsCurrentTool(const TOOL_ACTION &aAction) const
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
void ShowContextMenu(SELECTION &aSelection)
Function ShowContextMenu.
Definition: tool_menu.cpp:59
static TOOL_ACTION selectionTool
Definition: actions.h:143
void SetEnd(const VECTOR2I &aEnd)
Set the current end of the rectangle (the end that moves with the cursor.
Color has changed.
Definition: view_item.h:57