KiCad PCB EDA Suite
TOOL_DISPATCHER Class Reference

Class TOOL_DISPATCHER. More...

#include <tool_dispatcher.h>

Inheritance diagram for TOOL_DISPATCHER:

Classes

struct  BUTTON_STATE
 

Stores information about a mouse button state

More...
 

Public Member Functions

 TOOL_DISPATCHER (TOOL_MANAGER *aToolMgr, ACTIONS *aActions)
 Constructor. More...
 
virtual ~TOOL_DISPATCHER ()
 
virtual void ResetState ()
 Function ResetState() Brings the dispatcher to its initial state. More...
 
virtual void DispatchWxEvent (wxEvent &aEvent)
 Function DispatchWxEvent() Processes wxEvents (mostly UI events), translates them to TOOL_EVENTs, and makes tools handle those. More...
 
virtual void DispatchWxCommand (wxCommandEvent &aEvent)
 Function DispatchWxCommand() Processes wxCommands (mostly menu related events) and runs appropriate actions (eg. More...
 

Private Member Functions

bool handleMouseButton (wxEvent &aEvent, int aIndex, bool aMotion)
 

Handles mouse related events (click, motion, dragging).

More...
 
void updateUI ()
 

Redraws the status bar and message panel.

More...
 
KIGFX::VIEWgetView ()
 

Returns the instance of VIEW, used by the application.

More...
 

Static Private Member Functions

static int decodeModifiers (const wxKeyboardState *aState)
 

Saves the state of key modifiers (Alt, Ctrl and so on).

More...
 

Private Attributes

VECTOR2D m_lastMousePos
 

The last mouse cursor position (in world coordinates).

More...
 
std::vector< BUTTON_STATE * > m_buttons
 

State of mouse buttons.

More...
 
TOOL_MANAGERm_toolMgr
 

Instance of tool manager that cooperates with the dispatcher.

More...
 
ACTIONSm_actions
 

Instance of an actions list that handles legacy action translation

More...
 

Static Private Attributes

static const int MouseButtonCount = 3
 

Number of mouse buttons that is handled in events.

More...
 
static const int DragTimeThreshold = 300
 

The time threshold for a mouse button press that distinguishes between a single mouse click and a beginning of drag event (expressed in milliseconds).

More...
 
static const int DragDistanceThreshold = 8
 

The distance threshold for mouse cursor that disinguishes between a single mouse click and a beginning of drag event (expressed in screen pixels).

More...
 

Detailed Description

Class TOOL_DISPATCHER.

  • takes wx events,
  • fixes all wx quirks (mouse warping, panning, ordering problems, etc)
  • translates coordinates to world space
  • low-level input conditioning (drag/click threshold), updating mouse position during view auto-scroll/pan.
  • issues TOOL_EVENTS to the tool manager

Definition at line 51 of file tool_dispatcher.h.

Constructor & Destructor Documentation

TOOL_DISPATCHER::TOOL_DISPATCHER ( TOOL_MANAGER aToolMgr,
ACTIONS aActions 
)

Constructor.

Parameters
aToolMgrtool manager instance the events will be sent to
aActionsACTIONS subclass instance for ::TranslateLegacyId()

Definition at line 117 of file tool_dispatcher.cpp.

References BUT_LEFT, BUT_MIDDLE, BUT_RIGHT, m_buttons, and ResetState().

117  :
118  m_toolMgr( aToolMgr ),
119  m_actions( aActions )
120 {
121  m_buttons.push_back( new BUTTON_STATE( BUT_LEFT, wxEVT_LEFT_DOWN,
122  wxEVT_LEFT_UP, wxEVT_LEFT_DCLICK ) );
123  m_buttons.push_back( new BUTTON_STATE( BUT_RIGHT, wxEVT_RIGHT_DOWN,
124  wxEVT_RIGHT_UP, wxEVT_RIGHT_DCLICK ) );
125  m_buttons.push_back( new BUTTON_STATE( BUT_MIDDLE, wxEVT_MIDDLE_DOWN,
126  wxEVT_MIDDLE_UP, wxEVT_MIDDLE_DCLICK ) );
127 
128  ResetState();
129 }
ACTIONS * m_actions
Instance of an actions list that handles legacy action translation
virtual void ResetState()
Function ResetState() Brings the dispatcher to its initial state.
std::vector< BUTTON_STATE * > m_buttons
State of mouse buttons.
TOOL_MANAGER * m_toolMgr
Instance of tool manager that cooperates with the dispatcher.
TOOL_DISPATCHER::~TOOL_DISPATCHER ( )
virtual

Definition at line 132 of file tool_dispatcher.cpp.

References m_buttons.

133 {
134  for( BUTTON_STATE* st : m_buttons )
135  delete st;
136 }
std::vector< BUTTON_STATE * > m_buttons
State of mouse buttons.

Member Function Documentation

static int TOOL_DISPATCHER::decodeModifiers ( const wxKeyboardState *  aState)
inlinestaticprivate

Saves the state of key modifiers (Alt, Ctrl and so on).

Definition at line 102 of file tool_dispatcher.h.

References MD_ALT, MD_CTRL, and MD_SHIFT.

Referenced by DispatchWxEvent(), and handleMouseButton().

103  {
104  int mods = 0;
105 
106  if( aState->ControlDown() )
107  mods |= MD_CTRL;
108 
109  if( aState->AltDown() )
110  mods |= MD_ALT;
111 
112  if( aState->ShiftDown() )
113  mods |= MD_SHIFT;
114 
115  return mods;
116  }
void TOOL_DISPATCHER::DispatchWxCommand ( wxCommandEvent &  aEvent)
virtual

Function DispatchWxCommand() Processes wxCommands (mostly menu related events) and runs appropriate actions (eg.

run the specified tool).

Parameters
aEventis the wxCommandEvent to be processed.

Definition at line 343 of file tool_dispatcher.cpp.

References m_actions, m_toolMgr, TOOL_MANAGER::ProcessEvent(), ACTIONS::TranslateLegacyId(), and updateUI().

Referenced by EDA_DRAW_PANEL_GAL::SetEventDispatcher().

344 {
346 
347  if( evt )
348  m_toolMgr->ProcessEvent( *evt );
349  else
350  aEvent.Skip();
351 
352  updateUI();
353 }
ACTIONS * m_actions
Instance of an actions list that handles legacy action translation
virtual boost::optional< TOOL_EVENT > TranslateLegacyId(int aId)=0
Function TranslateLegacyId() Translates legacy tool ids to the corresponding TOOL_ACTION name...
void updateUI()
Redraws the status bar and message panel.
void ProcessEvent(const TOOL_EVENT &aEvent)
Propagates an event to tools that requested events of matching type(s).
TOOL_MANAGER * m_toolMgr
Instance of tool manager that cooperates with the dispatcher.
void TOOL_DISPATCHER::DispatchWxEvent ( wxEvent &  aEvent)
virtual

Function DispatchWxEvent() Processes wxEvents (mostly UI events), translates them to TOOL_EVENTs, and makes tools handle those.

Parameters
aEventis the wxWidgets event to be processed.

Definition at line 244 of file tool_dispatcher.cpp.

References decodeModifiers(), KIGFX::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE, TOOL_MANAGER::GetEditFrame(), KIGFX::VIEW_CONTROLS::GetMousePosition(), getView(), TOOL_MANAGER::GetViewControls(), handleMouseButton(), m_buttons, m_lastMousePos, m_toolMgr, MD_CTRL, TOOL_MANAGER::ProcessEvent(), TA_CANCEL_TOOL, TA_KEY_PRESSED, TA_MOUSE_MOTION, TC_COMMAND, TC_KEYBOARD, TC_MOUSE, KIGFX::VIEW::ToWorld(), and updateUI().

Referenced by EDA_DRAW_PANEL_GAL::onEvent().

245 {
246  bool motion = false, buttonEvents = false;
248 
249  int type = aEvent.GetEventType();
250 
251  // Mouse handling
252  if( type == wxEVT_MOTION || type == wxEVT_MOUSEWHEEL ||
253 #if wxCHECK_VERSION( 3, 1, 0 ) || defined( USE_OSX_MAGNIFY_EVENT )
254  type == wxEVT_MAGNIFY ||
255 #endif
256  type == wxEVT_LEFT_DOWN || type == wxEVT_LEFT_UP ||
257  type == wxEVT_MIDDLE_DOWN || type == wxEVT_MIDDLE_UP ||
258  type == wxEVT_RIGHT_DOWN || type == wxEVT_RIGHT_UP ||
259  type == wxEVT_LEFT_DCLICK || type == wxEVT_MIDDLE_DCLICK || type == wxEVT_RIGHT_DCLICK ||
260  // Event issued whem mouse retains position in screen coordinates,
261  // but changes in world coordinates (e.g. autopanning)
263  {
264  wxMouseEvent* me = static_cast<wxMouseEvent*>( &aEvent );
265  int mods = decodeModifiers( me );
266 
268  VECTOR2D pos = getView()->ToWorld( screenPos );
269 
270  if( pos != m_lastMousePos )
271  {
272  motion = true;
273  m_lastMousePos = pos;
274  }
275 
276  for( unsigned int i = 0; i < m_buttons.size(); i++ )
277  buttonEvents |= handleMouseButton( aEvent, i, motion );
278 
279  if( !buttonEvents && motion )
280  {
281  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_MOTION, mods );
282  evt->SetMousePosition( pos );
283  }
284 
285 #ifdef __APPLE__
286  // TODO That's a big ugly workaround, somehow DRAWPANEL_GAL loses focus
287  // after second LMB click and currently I have no means to do better debugging
288  if( type == wxEVT_LEFT_UP )
289  static_cast<PCB_BASE_FRAME*>( m_toolMgr->GetEditFrame() )->GetGalCanvas()->SetFocus();
290 #endif /* __APPLE__ */
291  }
292 
293  // Keyboard handling
294  else if( type == wxEVT_CHAR )
295  {
296  wxKeyEvent* ke = static_cast<wxKeyEvent*>( &aEvent );
297  int key = ke->GetKeyCode();
298  int mods = decodeModifiers( ke );
299 
300  if( mods & MD_CTRL )
301  {
302 #if !wxCHECK_VERSION( 2, 9, 0 )
303  // I really look forward to the day when we will use only one version of wxWidgets..
304  const int WXK_CONTROL_A = 1;
305  const int WXK_CONTROL_Z = 26;
306 #endif
307 
308  // wxWidgets have a quirk related to Ctrl+letter hot keys handled by CHAR_EVT
309  // http://docs.wxwidgets.org/trunk/classwx_key_event.html:
310  // "char events for ASCII letters in this case carry codes corresponding to the ASCII
311  // value of Ctrl-Latter, i.e. 1 for Ctrl-A, 2 for Ctrl-B and so on until 26 for Ctrl-Z."
312  if( key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
313  key += 'A' - 1;
314  }
315 
316  if( key == WXK_ESCAPE ) // ESC is the special key for cancelling tools
318  else
319  evt = TOOL_EVENT( TC_KEYBOARD, TA_KEY_PRESSED, key | mods );
320  }
321 
322  if( evt )
323  m_toolMgr->ProcessEvent( *evt );
324 
325  // pass the event to the GUI, it might still be interested in it
326 #ifdef __APPLE__
327  // On OS X, key events are always meant to be caught. An uncaught key event is assumed
328  // to be a user input error by OS X (as they are pressing keys in a context where nothing
329  // is there to catch the event). This annoyingly makes OS X beep and/or flash the screen
330  // in pcbnew and the footprint editor any time a hotkey is used. The correct procedure is
331  // to NOT pass key events to the GUI under OS X.
332 
333  if( type != wxEVT_CHAR )
334  aEvent.Skip();
335 #else
336  aEvent.Skip();
337 #endif
338 
339  updateUI();
340 }
static int decodeModifiers(const wxKeyboardState *aState)
Saves the state of key modifiers (Alt, Ctrl and so on).
static const wxEventType EVT_REFRESH_MOUSE
Event that forces mouse move event in the dispatcher (eg.
wxWindow * GetEditFrame() const
Definition: tool_manager.h:258
VECTOR2D ToWorld(const VECTOR2D &aCoord, bool aAbsolute=true) const
Function ToWorld() Converts a screen space point/vector to a point/vector in world space coordinates...
Definition: view.cpp:439
KIGFX::VIEW_CONTROLS * GetViewControls() const
Definition: tool_manager.h:248
Class TOOL_EVENT.
Definition: tool_event.h:162
VECTOR2D m_lastMousePos
The last mouse cursor position (in world coordinates).
void updateUI()
Redraws the status bar and message panel.
std::vector< BUTTON_STATE * > m_buttons
State of mouse buttons.
void ProcessEvent(const TOOL_EVENT &aEvent)
Propagates an event to tools that requested events of matching type(s).
bool handleMouseButton(wxEvent &aEvent, int aIndex, bool aMotion)
Handles mouse related events (click, motion, dragging).
class PCB_BASE_FRAME basic PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer...
KIGFX::VIEW * getView()
Returns the instance of VIEW, used by the application.
TOOL_MANAGER * m_toolMgr
Instance of tool manager that cooperates with the dispatcher.
virtual VECTOR2I GetMousePosition() const =0
Function GetMousePosition() Returns the current mouse pointer position in screen coordinates.
KIGFX::VIEW * TOOL_DISPATCHER::getView ( )
private

Returns the instance of VIEW, used by the application.

Definition at line 146 of file tool_dispatcher.cpp.

References TOOL_MANAGER::GetEditFrame(), and m_toolMgr.

Referenced by DispatchWxEvent(), and handleMouseButton().

147 {
148  return static_cast<EDA_DRAW_FRAME*>( m_toolMgr->GetEditFrame() )->GetGalCanvas()->GetView();
149 }
wxWindow * GetEditFrame() const
Definition: tool_manager.h:258
Class EDA_DRAW_FRAME is the base class for create windows for drawing purpose.
Definition: draw_frame.h:53
TOOL_MANAGER * m_toolMgr
Instance of tool manager that cooperates with the dispatcher.
bool TOOL_DISPATCHER::handleMouseButton ( wxEvent &  aEvent,
int  aIndex,
bool  aMotion 
)
private

Handles mouse related events (click, motion, dragging).

Definition at line 152 of file tool_dispatcher.cpp.

References TOOL_DISPATCHER::BUTTON_STATE::button, TOOL_DISPATCHER::BUTTON_STATE::dblClickEvent, decodeModifiers(), TOOL_DISPATCHER::BUTTON_STATE::downPosition, TOOL_DISPATCHER::BUTTON_STATE::downTimestamp, DragDistanceThreshold, TOOL_DISPATCHER::BUTTON_STATE::dragging, TOOL_DISPATCHER::BUTTON_STATE::dragMaxDelta, TOOL_DISPATCHER::BUTTON_STATE::dragOrigin, DragTimeThreshold, VECTOR2< T >::EuclideanNorm(), TOOL_DISPATCHER::BUTTON_STATE::GetState(), getView(), m_buttons, m_lastMousePos, m_toolMgr, max, TOOL_DISPATCHER::BUTTON_STATE::pressed, TOOL_MANAGER::ProcessEvent(), TA_MOUSE_CLICK, TA_MOUSE_DBLCLICK, TA_MOUSE_DOWN, TA_MOUSE_DRAG, TA_MOUSE_UP, TC_MOUSE, and KIGFX::VIEW::ToScreen().

Referenced by DispatchWxEvent().

153 {
154  BUTTON_STATE* st = m_buttons[aIndex];
155  wxEventType type = aEvent.GetEventType();
157  bool isClick = false;
158 
159 // bool up = type == st->upEvent;
160 // bool down = type == st->downEvent;
161  bool up = false, down = false;
162  bool dblClick = type == st->dblClickEvent;
163  bool state = st->GetState();
164 
165  if( !dblClick )
166  {
167  // Sometimes the dispatcher does not receive mouse button up event, so it stays
168  // in the dragging mode even if the mouse button is not held anymore
169  if( st->pressed && !state )
170  up = true;
171  else if( !st->pressed && state )
172  down = true;
173  }
174 
175  int mods = decodeModifiers( static_cast<wxMouseEvent*>( &aEvent ) );
176  int args = st->button | mods;
177 
178  if( down ) // Handle mouse button press
179  {
180  st->downTimestamp = wxGetLocalTimeMillis();
181  st->dragOrigin = m_lastMousePos;
182  st->downPosition = m_lastMousePos;
183  st->dragMaxDelta = 0;
184  st->pressed = true;
185  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DOWN, args );
186  }
187  else if( up ) // Handle mouse button release
188  {
189  st->pressed = false;
190 
191  if( st->dragging )
192  {
193  wxLongLong t = wxGetLocalTimeMillis();
194 
195  // Determine if it was just a single click or beginning of dragging
196  if( t - st->downTimestamp < DragTimeThreshold &&
197  st->dragMaxDelta < DragDistanceThreshold )
198  isClick = true;
199  else
200  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_UP, args );
201  }
202  else
203  isClick = true;
204 
205  if( isClick )
206  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_CLICK, args );
207 
208  st->dragging = false;
209  }
210  else if( dblClick )
211  {
212  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DBLCLICK, args );
213  }
214 
215  if( st->pressed && aMotion )
216  {
217  st->dragging = true;
218  double dragPixelDistance =
219  getView()->ToScreen( m_lastMousePos - st->dragOrigin, false ).EuclideanNorm();
220  st->dragMaxDelta = std::max( st->dragMaxDelta, dragPixelDistance );
221 
222  wxLongLong t = wxGetLocalTimeMillis();
223 
224  if( t - st->downTimestamp > DragTimeThreshold || st->dragMaxDelta > DragDistanceThreshold )
225  {
226  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DRAG, args );
227  evt->setMouseDragOrigin( st->dragOrigin );
228  evt->setMouseDelta( m_lastMousePos - st->dragOrigin );
229  }
230  }
231 
232  if( evt )
233  {
234  evt->SetMousePosition( isClick ? st->downPosition : m_lastMousePos );
235  m_toolMgr->ProcessEvent( *evt );
236 
237  return true;
238  }
239 
240  return false;
241 }
static int decodeModifiers(const wxKeyboardState *aState)
Saves the state of key modifiers (Alt, Ctrl and so on).
static const int DragDistanceThreshold
The distance threshold for mouse cursor that disinguishes between a single mouse click and a beginnin...
T EuclideanNorm() const
Destructor.
Definition: vector2d.h:285
Class TOOL_EVENT.
Definition: tool_event.h:162
VECTOR2D m_lastMousePos
The last mouse cursor position (in world coordinates).
std::vector< BUTTON_STATE * > m_buttons
State of mouse buttons.
#define max(a, b)
Definition: auxiliary.h:86
VECTOR2D ToScreen(const VECTOR2D &aCoord, bool aAbsolute=true) const
Function ToScreen() Converts a world space point/vector to a point/vector in screen space coordinates...
Definition: view.cpp:458
void ProcessEvent(const TOOL_EVENT &aEvent)
Propagates an event to tools that requested events of matching type(s).
static const int DragTimeThreshold
The time threshold for a mouse button press that distinguishes between a single mouse click and a beg...
KIGFX::VIEW * getView()
Returns the instance of VIEW, used by the application.
TOOL_MANAGER * m_toolMgr
Instance of tool manager that cooperates with the dispatcher.
void TOOL_DISPATCHER::ResetState ( )
virtual

Function ResetState() Brings the dispatcher to its initial state.

Definition at line 139 of file tool_dispatcher.cpp.

References m_buttons.

Referenced by TOOL_DISPATCHER().

140 {
141  for( BUTTON_STATE* st : m_buttons )
142  st->Reset();
143 }
std::vector< BUTTON_STATE * > m_buttons
State of mouse buttons.
void TOOL_DISPATCHER::updateUI ( )
private

Redraws the status bar and message panel.

Definition at line 356 of file tool_dispatcher.cpp.

References TOOL_MANAGER::GetEditFrame(), m_toolMgr, and EDA_DRAW_FRAME::UpdateStatusBar().

Referenced by DispatchWxCommand(), and DispatchWxEvent().

357 {
358  // TODO I don't feel it is the right place for updating UI,
359  // but at the moment I cannot think of a better one..
360  EDA_DRAW_FRAME* frame = static_cast<EDA_DRAW_FRAME*>( m_toolMgr->GetEditFrame() );
361  frame->UpdateStatusBar();
362  //frame->UpdateMsgPanel();
363 }
wxWindow * GetEditFrame() const
Definition: tool_manager.h:258
Class EDA_DRAW_FRAME is the base class for create windows for drawing purpose.
Definition: draw_frame.h:53
virtual void UpdateStatusBar()
Function UpdateStatusBar updates the status bar information.
Definition: draw_frame.cpp:650
TOOL_MANAGER * m_toolMgr
Instance of tool manager that cooperates with the dispatcher.

Member Data Documentation

const int TOOL_DISPATCHER::DragDistanceThreshold = 8
staticprivate

The distance threshold for mouse cursor that disinguishes between a single mouse click and a beginning of drag event (expressed in screen pixels).

Definition at line 96 of file tool_dispatcher.h.

Referenced by handleMouseButton().

const int TOOL_DISPATCHER::DragTimeThreshold = 300
staticprivate

The time threshold for a mouse button press that distinguishes between a single mouse click and a beginning of drag event (expressed in milliseconds).

Definition at line 92 of file tool_dispatcher.h.

Referenced by handleMouseButton().

ACTIONS* TOOL_DISPATCHER::m_actions
private

Instance of an actions list that handles legacy action translation

Definition at line 137 of file tool_dispatcher.h.

Referenced by DispatchWxCommand().

std::vector<BUTTON_STATE*> TOOL_DISPATCHER::m_buttons
private

State of mouse buttons.

Definition at line 128 of file tool_dispatcher.h.

Referenced by DispatchWxEvent(), handleMouseButton(), ResetState(), TOOL_DISPATCHER(), and ~TOOL_DISPATCHER().

VECTOR2D TOOL_DISPATCHER::m_lastMousePos
private

The last mouse cursor position (in world coordinates).

Definition at line 122 of file tool_dispatcher.h.

Referenced by DispatchWxEvent(), and handleMouseButton().

TOOL_MANAGER* TOOL_DISPATCHER::m_toolMgr
private

Instance of tool manager that cooperates with the dispatcher.

Definition at line 134 of file tool_dispatcher.h.

Referenced by DispatchWxCommand(), DispatchWxEvent(), getView(), handleMouseButton(), and updateUI().

const int TOOL_DISPATCHER::MouseButtonCount = 3
staticprivate

Number of mouse buttons that is handled in events.

Definition at line 88 of file tool_dispatcher.h.


The documentation for this class was generated from the following files: