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 ACTIONS::TranslateLegacyId()

Definition at line 118 of file tool_dispatcher.cpp.

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

118  :
119  m_toolMgr( aToolMgr ),
120  m_actions( aActions )
121 {
122  m_buttons.push_back( new BUTTON_STATE( BUT_LEFT, wxEVT_LEFT_DOWN,
123  wxEVT_LEFT_UP, wxEVT_LEFT_DCLICK ) );
124  m_buttons.push_back( new BUTTON_STATE( BUT_RIGHT, wxEVT_RIGHT_DOWN,
125  wxEVT_RIGHT_UP, wxEVT_RIGHT_DCLICK ) );
126  m_buttons.push_back( new BUTTON_STATE( BUT_MIDDLE, wxEVT_MIDDLE_DOWN,
127  wxEVT_MIDDLE_UP, wxEVT_MIDDLE_DCLICK ) );
128 
129  ResetState();
130 }
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 133 of file tool_dispatcher.cpp.

References m_buttons.

134 {
135  for( BUTTON_STATE* st : m_buttons )
136  delete st;
137 }
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 430 of file tool_dispatcher.cpp.

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

Referenced by EDA_DRAW_PANEL_GAL::SetEventDispatcher().

431 {
433 
434  if( evt )
435  m_toolMgr->ProcessEvent( *evt );
436  else
437  aEvent.Skip();
438 
439  updateUI();
440 }
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...
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagates an event to tools that requested events of matching type(s).
void updateUI()
Redraws the status bar and message panel.
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 307 of file tool_dispatcher.cpp.

References decodeModifiers(), KIGFX::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE, TOOL_MANAGER::GetEditFrame(), KIGFX::VIEW_CONTROLS::GetMousePosition(), TOOL_MANAGER::GetViewControls(), handleMouseButton(), isKeySpecialCode(), 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, translateSpecialCode(), and updateUI().

Referenced by EDA_DRAW_PANEL_GAL::onEvent().

308 {
309  bool motion = false, buttonEvents = false;
311  int key = 0; // key = 0 if the event is not a key event
312  bool keyIsSpecial = false; // True if the key is a special key code
313 
314  int type = aEvent.GetEventType();
315 
316  // Mouse handling
317  // Note: wxEVT_LEFT_DOWN event must always be skipped.
318  if( type == wxEVT_MOTION || type == wxEVT_MOUSEWHEEL ||
319 #if wxCHECK_VERSION( 3, 1, 0 ) || defined( USE_OSX_MAGNIFY_EVENT )
320  type == wxEVT_MAGNIFY ||
321 #endif
322  type == wxEVT_LEFT_DOWN || type == wxEVT_LEFT_UP ||
323  type == wxEVT_MIDDLE_DOWN || type == wxEVT_MIDDLE_UP ||
324  type == wxEVT_RIGHT_DOWN || type == wxEVT_RIGHT_UP ||
325  type == wxEVT_LEFT_DCLICK || type == wxEVT_MIDDLE_DCLICK || type == wxEVT_RIGHT_DCLICK ||
326  // Event issued whem mouse retains position in screen coordinates,
327  // but changes in world coordinates (e.g. autopanning)
329  {
330  wxMouseEvent* me = static_cast<wxMouseEvent*>( &aEvent );
331  int mods = decodeModifiers( me );
332 
334 
335  if( pos != m_lastMousePos )
336  {
337  motion = true;
338  m_lastMousePos = pos;
339  }
340 
341  for( unsigned int i = 0; i < m_buttons.size(); i++ )
342  buttonEvents |= handleMouseButton( aEvent, i, motion );
343 
344  if( !buttonEvents && motion )
345  {
346  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_MOTION, mods );
347  evt->SetMousePosition( pos );
348  }
349 
350 #ifdef __APPLE__
351  // TODO That's a big ugly workaround, somehow DRAWPANEL_GAL loses focus
352  // after second LMB click and currently I have no means to do better debugging
353  if( type == wxEVT_LEFT_UP )
354  static_cast<PCB_BASE_FRAME*>( m_toolMgr->GetEditFrame() )->GetGalCanvas()->SetFocus();
355 #endif /* __APPLE__ */
356  }
357  else if( type == wxEVT_CHAR_HOOK || type == wxEVT_CHAR )
358  {
359  wxKeyEvent* ke = static_cast<wxKeyEvent*>( &aEvent );
360  key = ke->GetKeyCode();
361  keyIsSpecial = isKeySpecialCode( key );
362 
363  // if the key event must be skipped, skip it here if the event is a wxEVT_CHAR_HOOK
364  // and do nothing.
365  // a wxEVT_CHAR will be fired by wxWidgets later for this key.
366  if( type == wxEVT_CHAR_HOOK )
367  {
368  if( !keyIsSpecial )
369  {
370  aEvent.Skip();
371  return;
372  }
373  else
374  key = translateSpecialCode( key );
375  }
376 
377  int mods = decodeModifiers( ke );
378 
379  // wxLogMessage( "key %d evt type %d", key, type );
380 
381  if( mods & MD_CTRL )
382  {
383  // wxWidgets maps key codes related to Ctrl+letter handled by CHAR_EVT
384  // (http://docs.wxwidgets.org/trunk/classwx_key_event.html):
385  // char events for ASCII letters in this case carry codes corresponding to the ASCII
386  // value of Ctrl-Latter, i.e. 1 for Ctrl-A, 2 for Ctrl-B and so on until 26 for Ctrl-Z.
387  // They are remapped here to be more easy to handle in code
388  if( key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
389  key += 'A' - 1;
390  }
391 
392  if( key == WXK_ESCAPE ) // ESC is the special key for cancelling tools
394  else
395  evt = TOOL_EVENT( TC_KEYBOARD, TA_KEY_PRESSED, key | mods );
396  }
397 
398  if( evt )
399  m_toolMgr->ProcessEvent( *evt );
400 
401  // pass the event to the GUI, it might still be interested in it
402  // Note wxEVT_CHAR_HOOK event is already skipped for special keys not used by kicad
403  // and wxEVT_LEFT_DOWN must be always Skipped.
404  //
405  // On OS X, key events are always meant to be caught. An uncaught key event is assumed
406  // to be a user input error by OS X (as they are pressing keys in a context where nothing
407  // is there to catch the event). This annoyingly makes OS X beep and/or flash the screen
408  // in pcbnew and the footprint editor any time a hotkey is used. The correct procedure is
409  // to NOT pass wxEVT_CHAR events to the GUI under OS X.
410  //
411  // On Windows, avoid to call wxEvent::Skip for special keys because some keys (ARROWS, PAGE_UP, PAGE_DOWN
412  // have predefined actions (like move thumbtrack cursor), and we do not want these
413  // actions executed (most are handled by Kicad)
414 
415  if( !evt || type == wxEVT_LEFT_DOWN )
416  aEvent.Skip();
417 
418  // The suitable Skip is already called, but the wxEVT_CHAR
419  // must be Skipped (sent to GUI).
420  // Otherwise accelerators and shortcuts in main menu or toolbars are not seen.
421 #ifndef __APPLE__
422  if( type == wxEVT_CHAR && !keyIsSpecial )
423  aEvent.Skip();
424 #endif
425 
426  updateUI();
427 }
static int decodeModifiers(const wxKeyboardState *aState)
Saves the state of key modifiers (Alt, Ctrl and so on).
virtual VECTOR2D GetMousePosition(bool aWorldCoordinates=true) const =0
Function GetMousePosition() Returns the current mouse pointer position.
static const wxEventType EVT_REFRESH_MOUSE
Event that forces mouse move event in the dispatcher (eg.
int translateSpecialCode(int aKeyCode)
wxWindow * GetEditFrame() const
Definition: tool_manager.h:267
KIGFX::VIEW_CONTROLS * GetViewControls() const
Definition: tool_manager.h:257
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagates an event to tools that requested events of matching type(s).
bool isKeySpecialCode(int aKeyCode)
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.
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...
TOOL_MANAGER * m_toolMgr
Instance of tool manager that cooperates with the dispatcher.
KIGFX::VIEW * TOOL_DISPATCHER::getView ( )
private

Returns the instance of VIEW, used by the application.

Definition at line 147 of file tool_dispatcher.cpp.

References TOOL_MANAGER::GetEditFrame(), and m_toolMgr.

Referenced by handleMouseButton().

148 {
149  return static_cast<EDA_DRAW_FRAME*>( m_toolMgr->GetEditFrame() )->GetGalCanvas()->GetView();
150 }
wxWindow * GetEditFrame() const
Definition: tool_manager.h:267
Class EDA_DRAW_FRAME is the base class for create windows for drawing purpose.
Definition: draw_frame.h:54
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 153 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().

154 {
155  BUTTON_STATE* st = m_buttons[aIndex];
156  wxEventType type = aEvent.GetEventType();
158  bool isClick = false;
159 
160 // bool up = type == st->upEvent;
161 // bool down = type == st->downEvent;
162  bool up = false, down = false;
163  bool dblClick = type == st->dblClickEvent;
164  bool state = st->GetState();
165 
166  if( !dblClick )
167  {
168  // Sometimes the dispatcher does not receive mouse button up event, so it stays
169  // in the dragging mode even if the mouse button is not held anymore
170  if( st->pressed && !state )
171  up = true;
172  else if( !st->pressed && state )
173  down = true;
174  }
175 
176  int mods = decodeModifiers( static_cast<wxMouseEvent*>( &aEvent ) );
177  int args = st->button | mods;
178 
179  if( down ) // Handle mouse button press
180  {
181  st->downTimestamp = wxGetLocalTimeMillis();
182 
183  if( !st->pressed ) // save the drag origin on the first click only
184  st->dragOrigin = m_lastMousePos;
185 
186  st->downPosition = m_lastMousePos;
187  st->dragMaxDelta = 0;
188  st->pressed = true;
189  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DOWN, args );
190  }
191  else if( up ) // Handle mouse button release
192  {
193  st->pressed = false;
194 
195  if( st->dragging )
196  {
197  wxLongLong t = wxGetLocalTimeMillis();
198 
199  // Determine if it was just a single click or beginning of dragging
200  if( t - st->downTimestamp < DragTimeThreshold &&
201  st->dragMaxDelta < DragDistanceThreshold )
202  isClick = true;
203  else
204  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_UP, args );
205  }
206  else
207  isClick = true;
208 
209  if( isClick )
210  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_CLICK, args );
211 
212  st->dragging = false;
213  }
214  else if( dblClick )
215  {
216  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DBLCLICK, args );
217  }
218 
219  if( st->pressed && aMotion )
220  {
221  st->dragging = true;
222  double dragPixelDistance =
223  getView()->ToScreen( m_lastMousePos - st->dragOrigin, false ).EuclideanNorm();
224  st->dragMaxDelta = std::max( st->dragMaxDelta, dragPixelDistance );
225 
226  wxLongLong t = wxGetLocalTimeMillis();
227 
228  if( t - st->downTimestamp > DragTimeThreshold || st->dragMaxDelta > DragDistanceThreshold )
229  {
230  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DRAG, args );
231  evt->setMouseDragOrigin( st->dragOrigin );
232  evt->setMouseDelta( m_lastMousePos - st->dragOrigin );
233  }
234  }
235 
236  if( evt )
237  {
238  evt->SetMousePosition( isClick ? st->downPosition : m_lastMousePos );
239  m_toolMgr->ProcessEvent( *evt );
240 
241  return true;
242  }
243 
244  return false;
245 }
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:295
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagates an event to tools that requested events of matching type(s).
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:460
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 140 of file tool_dispatcher.cpp.

References m_buttons.

Referenced by TOOL_DISPATCHER().

141 {
142  for( BUTTON_STATE* st : m_buttons )
143  st->Reset();
144 }
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 443 of file tool_dispatcher.cpp.

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

Referenced by DispatchWxCommand(), and DispatchWxEvent().

444 {
445  // TODO I don't feel it is the right place for updating UI,
446  // but at the moment I cannot think of a better one..
447  EDA_DRAW_FRAME* frame = static_cast<EDA_DRAW_FRAME*>( m_toolMgr->GetEditFrame() );
448  frame->UpdateStatusBar();
449  //frame->UpdateMsgPanel();
450 }
wxWindow * GetEditFrame() const
Definition: tool_manager.h:267
Class EDA_DRAW_FRAME is the base class for create windows for drawing purpose.
Definition: draw_frame.h:54
virtual void UpdateStatusBar()
Function UpdateStatusBar updates the status bar information.
Definition: draw_frame.cpp:680
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: