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  return 0;
96 }
97 
98 
100 {
101  auto& view = *getView();
102  auto& controls = *getViewControls();
103  auto previous_settings = controls.GetSettings();
104 
105  std::string tool = aEvent.GetCommandStr().get();
106  m_frame->PushTool( tool );
107  Activate();
108 
110  KIGFX::PREVIEW::RULER_ITEM ruler( twoPtMgr, m_frame->GetUserUnits() );
111 
112  view.Add( &ruler );
113  view.SetVisible( &ruler, false );
114 
115  bool originSet = false;
116 
117  controls.ShowCursor( true );
118  controls.SetSnapping( true );
119  controls.SetAdditionalPanButtons( false, true );
120 
121  while( TOOL_EVENT* evt = Wait() )
122  {
123  m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
124  const VECTOR2I cursorPos = controls.GetCursorPosition();
125 
126  auto clearRuler = [&]() {
127  view.SetVisible( &ruler, false );
128  controls.SetAutoPan( false );
129  controls.CaptureCursor( false );
130  originSet = false;
131  };
132 
133  if( evt->IsCancelInteractive() )
134  {
135  if( originSet )
136  clearRuler();
137  else
138  {
139  m_frame->PopTool( tool );
140  break;
141  }
142  }
143 
144  else if( evt->IsActivate() )
145  {
146  if( originSet )
147  clearRuler();
148 
149  if( evt->IsMoveTool() )
150  {
151  // leave ourselves on the stack so we come back after the move
152  break;
153  }
154  else
155  {
156  m_frame->PopTool( tool );
157  break;
158  }
159  }
160 
161  // click or drag starts
162  else if( !originSet && ( evt->IsDrag( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) )
163  {
164  if( !evt->IsDrag( BUT_LEFT ) )
165  {
166  twoPtMgr.SetOrigin( cursorPos );
167  twoPtMgr.SetEnd( cursorPos );
168  }
169 
170  controls.CaptureCursor( true );
171  controls.SetAutoPan( true );
172 
173  originSet = true;
174  }
175 
176  else if( !originSet && evt->IsMotion() )
177  {
178  // make sure the origin is set before a drag starts
179  // otherwise you can miss a step
180  twoPtMgr.SetOrigin( cursorPos );
181  twoPtMgr.SetEnd( cursorPos );
182  }
183 
184  // second click or mouse up after drag ends
185  else if( originSet && ( evt->IsClick( BUT_LEFT ) || evt->IsMouseUp( BUT_LEFT ) ) )
186  {
187  originSet = false;
188 
189  controls.SetAutoPan( false );
190  controls.CaptureCursor( false );
191 
192  view.SetVisible( &ruler, false );
193  }
194 
195  // move or drag when origin set updates rules
196  else if( originSet && ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) )
197  {
198  twoPtMgr.SetAngleSnap( evt->Modifier( MD_CTRL ) );
199  twoPtMgr.SetEnd( cursorPos );
200 
201  view.SetVisible( &ruler, true );
202  view.Update( &ruler, KIGFX::GEOMETRY );
203  }
204 
205  else if( evt->IsClick( BUT_RIGHT ) )
206  {
208  }
209 
210  else
211  evt->SetPassEvent();
212  }
213 
214  view.SetVisible( &ruler, false );
215  view.Remove( &ruler );
216  controls.ApplySettings( previous_settings );
217  return 0;
218 }
219 
221 {
223  CVPCB_ACTIONS::selectionActivate.MakeEvent() );
225 }
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:147
void setTransitions() override
Sets up handlers for various events.
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
TOOL_EVENT.
Definition: tool_event.h:171
void SetOrigin(const VECTOR2I &aOrigin)
Set the origin of the ruler (the fixed end)
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()
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:78
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
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
static TOOL_ACTION selectionTool
Definition: actions.h:146
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