KiCad PCB EDA Suite
TOOL_DISPATCHER Class Reference

#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)
 
virtual ~TOOL_DISPATCHER ()
 
virtual void ResetState ()
 Brings the dispatcher to its initial state. More...
 
virtual void DispatchWxEvent (wxEvent &aEvent)
 Processes wxEvents (mostly UI events), translates them to TOOL_EVENTs, and makes tools handle those. More...
 
OPT< TOOL_EVENTGetToolEvent (wxKeyEvent *aKeyEvent, bool *aSpecialKeyFlag)
 Maps a wxWidgets key event to a TOOL_EVENT. More...
 
virtual void DispatchWxCommand (wxCommandEvent &aEvent)
 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...
 
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

  • 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 49 of file tool_dispatcher.h.

Constructor & Destructor Documentation

◆ TOOL_DISPATCHER()

TOOL_DISPATCHER::TOOL_DISPATCHER ( TOOL_MANAGER aToolMgr,
ACTIONS aActions 
)
Parameters
aToolMgrtool manager instance the events will be sent to
aActionsACTIONS subclass instance for ACTIONS::TranslateLegacyId()

Definition at line 122 of file tool_dispatcher.cpp.

122  :
123  m_toolMgr( aToolMgr ),
124  m_actions( aActions )
125 {
126  m_buttons.push_back( new BUTTON_STATE( BUT_LEFT, wxEVT_LEFT_DOWN,
127  wxEVT_LEFT_UP, wxEVT_LEFT_DCLICK ) );
128  m_buttons.push_back( new BUTTON_STATE( BUT_RIGHT, wxEVT_RIGHT_DOWN,
129  wxEVT_RIGHT_UP, wxEVT_RIGHT_DCLICK ) );
130  m_buttons.push_back( new BUTTON_STATE( BUT_MIDDLE, wxEVT_MIDDLE_DOWN,
131  wxEVT_MIDDLE_UP, wxEVT_MIDDLE_DCLICK ) );
132 
133  ResetState();
134 }
ACTIONS * m_actions
Instance of an actions list that handles legacy action translation
virtual void 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.

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

◆ ~TOOL_DISPATCHER()

TOOL_DISPATCHER::~TOOL_DISPATCHER ( )
virtual

Definition at line 137 of file tool_dispatcher.cpp.

138 {
139  for( BUTTON_STATE* st : m_buttons )
140  delete st;
141 }
std::vector< BUTTON_STATE * > m_buttons
State of mouse buttons.

References m_buttons.

Member Function Documentation

◆ decodeModifiers()

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.

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  }

References MD_ALT, MD_CTRL, and MD_SHIFT.

Referenced by DispatchWxEvent(), GetToolEvent(), and handleMouseButton().

◆ DispatchWxCommand()

void TOOL_DISPATCHER::DispatchWxCommand ( wxCommandEvent &  aEvent)
virtual

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 605 of file tool_dispatcher.cpp.

606 {
607  OPT<TOOL_EVENT> evt = m_actions->TranslateLegacyId( aEvent.GetId() );
608 
609  if( evt )
610  {
611  wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxCommand %s", evt->Format() );
612 
613  m_toolMgr->ProcessEvent( *evt );
614  }
615  else
616  aEvent.Skip();
617 }
ACTIONS * m_actions
Instance of an actions list that handles legacy action translation
virtual OPT< 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).
const wxChar *const kicadTraceToolStack
Flag to enable tracing of the tool handling stack.
boost::optional< T > OPT
Definition: optional.h:7
TOOL_MANAGER * m_toolMgr
Instance of tool manager that cooperates with the dispatcher.

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

Referenced by EDA_3D_CANVAS::SetEventDispatcher(), EDA_DRAW_PANEL_GAL::SetEventDispatcher(), CVPCB_MAINFRAME::setupEventHandlers(), and KICAD_MANAGER_FRAME::setupTools().

◆ DispatchWxEvent()

void TOOL_DISPATCHER::DispatchWxEvent ( wxEvent &  aEvent)
virtual

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 410 of file tool_dispatcher.cpp.

411 {
412  bool motion = false;
413  bool buttonEvents = false;
414  VECTOR2D pos;
415  OPT<TOOL_EVENT> evt;
416  bool keyIsEscape = false; // True if the keypress was the escape key
417  bool keyIsSpecial = false; // True if the key is a special key code
418  wxWindow* focus = wxWindow::FindFocus();
419 
420  int type = aEvent.GetEventType();
421 
422  // Sometimes there is no window that has the focus (it happens when another PCB_BASE_FRAME
423  // is opened and is iconized on Windows).
424  // In this case, give the focus to the parent frame (GAL canvas itself does not accept the
425  // focus when iconized for some obscure reason)
426  if( focus == nullptr )
427  {
428  wxWindow* window = dynamic_cast<wxWindow*>( m_toolMgr->GetToolHolder() );
429 
430  if( window )
431  window->SetFocus();
432  }
433 
434  // Mouse handling
435  // Note: wxEVT_LEFT_DOWN event must always be skipped.
436  if( type == wxEVT_MOTION || type == wxEVT_MOUSEWHEEL ||
437 #if wxCHECK_VERSION( 3, 1, 0 ) || defined( USE_OSX_MAGNIFY_EVENT )
438  type == wxEVT_MAGNIFY ||
439 #endif
440  type == wxEVT_LEFT_DOWN || type == wxEVT_LEFT_UP ||
441  type == wxEVT_MIDDLE_DOWN || type == wxEVT_MIDDLE_UP ||
442  type == wxEVT_RIGHT_DOWN || type == wxEVT_RIGHT_UP ||
443  type == wxEVT_LEFT_DCLICK || type == wxEVT_MIDDLE_DCLICK || type == wxEVT_RIGHT_DCLICK ||
444  // Event issued when mouse retains position in screen coordinates,
445  // but changes in world coordinates (e.g. autopanning)
447  {
448  wxMouseEvent* me = static_cast<wxMouseEvent*>( &aEvent );
449  int mods = decodeModifiers( me );
450 
451  if( m_toolMgr->GetViewControls() )
452  {
454 
455  if( pos != m_lastMousePos )
456  {
457  motion = true;
458  m_lastMousePos = pos;
459  }
460  }
461 
462  for( unsigned int i = 0; i < m_buttons.size(); i++ )
463  buttonEvents |= handleMouseButton( aEvent, i, motion );
464 
465  if( m_toolMgr->GetViewControls() )
466  {
467  if( !buttonEvents && motion )
468  {
469  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_MOTION, mods );
470  evt->SetMousePosition( pos );
471  }
472  }
473 
474 #ifdef __APPLE__
475  // TODO That's a big ugly workaround, somehow DRAWPANEL_GAL loses focus
476  // after second LMB click and currently I have no means to do better debugging
477  if( type == wxEVT_LEFT_UP )
478  {
480  m_toolMgr->GetToolHolder()->GetToolCanvas()->SetFocus();
481  }
482 #endif /* __APPLE__ */
483  }
484  else if( type == wxEVT_CHAR_HOOK || type == wxEVT_CHAR )
485  {
486  wxKeyEvent* ke = static_cast<wxKeyEvent*>( &aEvent );
487 
488  keyIsEscape = ( ke->GetKeyCode() == WXK_ESCAPE );
489 
490  wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( focus );
491  wxStyledTextCtrl* styledText = dynamic_cast<wxStyledTextCtrl*>( focus );
492 
493  if( textEntry || styledText )
494  {
495  bool enabled = true;
496 
497  if( textEntry )
498  enabled = textEntry->IsEditable();
499  else if( styledText )
500  enabled = styledText->IsEditable();
501 
502  // Never process key events for tools when a text entry has focus
503  if( enabled )
504  {
505  aEvent.Skip();
506  return;
507  }
508  // Even if not enabled, allow a copy out
509  else if( ke->GetModifiers() == wxMOD_CONTROL && ke->GetKeyCode() == 'C' )
510  {
511  aEvent.Skip();
512  return;
513  }
514  }
515 
516  evt = GetToolEvent( ke, &keyIsSpecial );
517  }
518  else if( type == wxEVT_MENU_OPEN || type == wxEVT_MENU_CLOSE || type == wxEVT_MENU_HIGHLIGHT )
519  {
520  //
521  // wxWidgets has several issues that we have to work around:
522  //
523  // 1) wxWidgets 3.0.x Windows has a bug where wxEVT_MENU_OPEN and wxEVT_MENU_HIGHLIGHT
524  // events are not captured by the ACTON_MENU menus. So we forward them here.
525  // (FWIW, this one is fixed in wxWidgets 3.1.x.)
526  //
527  // 2) wxWidgets doesn't pass the menu pointer for wxEVT_MENU_HIGHLIGHT events. So we
528  // store the menu pointer from the wxEVT_MENU_OPEN call.
529  //
530  // 3) wxWidgets has no way to tell whether a command is from a menu selection or a
531  // hotkey. So we keep track of menu highlighting so we can differentiate.
532  //
533 
534  static ACTION_MENU* currentMenu;
535 
536  wxMenuEvent& menuEvent = *dynamic_cast<wxMenuEvent*>( &aEvent );
537 
538  if( type == wxEVT_MENU_OPEN )
539  {
540  currentMenu = dynamic_cast<ACTION_MENU*>( menuEvent.GetMenu() );
541 
542  if( currentMenu )
543  currentMenu->OnMenuEvent( menuEvent );
544  }
545  else if( type == wxEVT_MENU_HIGHLIGHT )
546  {
547  if( currentMenu )
548  currentMenu->OnMenuEvent( menuEvent );
549  }
550  else if( type == wxEVT_MENU_CLOSE )
551  {
552  if( currentMenu )
553  currentMenu->OnMenuEvent( menuEvent );
554 
555  currentMenu = nullptr;
556  }
557 
558  aEvent.Skip();
559  }
560 
561  bool handled = false;
562 
563  if( evt )
564  {
565  wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxEvent %s", evt->Format() );
566 
567  handled = m_toolMgr->ProcessEvent( *evt );
568 
569  wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxEvent - Handled: %s %s",
570  ( handled ? "true" : "false" ), evt->Format() );
571  }
572 
573  // pass the event to the GUI, it might still be interested in it
574  // Note wxEVT_CHAR_HOOK event is already skipped for special keys not used by KiCad
575  // and wxEVT_LEFT_DOWN must be always Skipped.
576  //
577  // On OS X, key events are always meant to be caught. An uncaught key event is assumed
578  // to be a user input error by OS X (as they are pressing keys in a context where nothing
579  // is there to catch the event). This annoyingly makes OS X beep and/or flash the screen
580  // in Pcbnew and the footprint editor any time a hotkey is used. The correct procedure is
581  // to NOT pass wxEVT_CHAR events to the GUI under OS X.
582  //
583  // On Windows, avoid to call wxEvent::Skip for special keys because some keys
584  // (PAGE_UP, PAGE_DOWN) have predefined actions (like move thumbtrack cursor), and we do
585  // not want these actions executed (most are handled by KiCad)
586 
587  if( !evt || type == wxEVT_LEFT_DOWN )
588  aEvent.Skip();
589 
590  // Not handled wxEVT_CHAR must be Skipped (sent to GUI).
591  // Otherwise accelerators and shortcuts in main menu or toolbars are not seen.
592  // Escape key presses are never skipped by the handler since they correspond to tool cancel
593  // events, and if they aren't skipped then they are propagated to other frames (which we don't want).
594  if( (type == wxEVT_CHAR || type == wxEVT_CHAR_HOOK)
595  && !keyIsSpecial
596  && !handled
597  && !keyIsEscape )
598  aEvent.Skip();
599 
600  wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxEvent - Wx event skipped: %s",
601  ( aEvent.GetSkipped() ? "true" : "false" ) );
602 }
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.
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:43
virtual wxWindow * GetToolCanvas() const =0
Canvas access.
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagates an event to tools that requested events of matching type(s).
TOOL_EVENT.
Definition: tool_event.h:171
VECTOR2D m_lastMousePos
The last mouse cursor position (in world coordinates).
std::vector< BUTTON_STATE * > m_buttons
State of mouse buttons.
void OnMenuEvent(wxMenuEvent &aEvent)
TOOLS_HOLDER * GetToolHolder() const
Definition: tool_manager.h:300
KIGFX::VIEW_CONTROLS * GetViewControls() const
Definition: tool_manager.h:291
OPT< TOOL_EVENT > GetToolEvent(wxKeyEvent *aKeyEvent, bool *aSpecialKeyFlag)
Maps a wxWidgets key event to a TOOL_EVENT.
const wxChar *const kicadTraceToolStack
Flag to enable tracing of the tool handling stack.
boost::optional< T > OPT
Definition: optional.h:7
bool handleMouseButton(wxEvent &aEvent, int aIndex, bool aMotion)
Handles mouse related events (click, motion, dragging).
TOOL_MANAGER * m_toolMgr
Instance of tool manager that cooperates with the dispatcher.

References decodeModifiers(), KIGFX::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE, KIGFX::VIEW_CONTROLS::GetMousePosition(), TOOLS_HOLDER::GetToolCanvas(), GetToolEvent(), TOOL_MANAGER::GetToolHolder(), TOOL_MANAGER::GetViewControls(), handleMouseButton(), kicadTraceToolStack, m_buttons, m_lastMousePos, m_toolMgr, ACTION_MENU::OnMenuEvent(), TOOL_MANAGER::ProcessEvent(), TA_MOUSE_MOTION, and TC_MOUSE.

Referenced by EDA_3D_CANVAS::OnEvent(), EDA_DRAW_PANEL_GAL::OnEvent(), PANEL_PREV_3D::OnMenuEvent(), EDA_BASE_FRAME::OnMenuEvent(), CVPCB_MAINFRAME::setupEventHandlers(), and KICAD_MANAGER_FRAME::setupTools().

◆ GetToolEvent()

OPT< TOOL_EVENT > TOOL_DISPATCHER::GetToolEvent ( wxKeyEvent *  aKeyEvent,
bool *  aSpecialKeyFlag 
)

Maps a wxWidgets key event to a TOOL_EVENT.

Definition at line 330 of file tool_dispatcher.cpp.

331 {
332  OPT<TOOL_EVENT> evt;
333  int key = aKeyEvent->GetKeyCode();
334  int unicode_key = aKeyEvent->GetUnicodeKey();
335 
336  // This wxEVT_CHAR_HOOK event can be ignored: not useful in Kicad
337  if( isKeyModifierOnly( key ) )
338  {
339  aKeyEvent->Skip();
340  return evt;
341  }
342 
343  wxLogTrace( kicadTraceKeyEvent, "TOOL_DISPATCHER::GetToolEvent %s", dump( *aKeyEvent ) );
344 
345  // if the key event must be skipped, skip it here if the event is a wxEVT_CHAR_HOOK
346  // and do nothing.
347  *keyIsSpecial = isKeySpecialCode( key );
348 
349  if( aKeyEvent->GetEventType() == wxEVT_CHAR_HOOK )
350  key = translateSpecialCode( key );
351 
352  int mods = decodeModifiers( aKeyEvent );
353 
354  if( mods & MD_CTRL )
355  {
356  // wxWidgets maps key codes related to Ctrl+letter handled by CHAR_EVT
357  // (http://docs.wxwidgets.org/trunk/classwx_key_event.html):
358  // char events for ASCII letters in this case carry codes corresponding to the ASCII
359  // value of Ctrl-Latter, i.e. 1 for Ctrl-A, 2 for Ctrl-B and so on until 26 for Ctrl-Z.
360  // They are remapped here to be more easy to handle in code
361  // Note also on OSX wxWidgets has a differnt behavior and the mapping is made
362  // only for ctrl+'A' to ctlr+'Z' (unicode code return 'A' to 'Z').
363  // Others OS return WXK_CONTROL_A to WXK_CONTROL_Z, and Ctrl+'M' returns the same code as
364  // the return key, so the remapping does not use the unicode key value.
365 #ifdef __APPLE__
366  if( unicode_key >= 'A' && unicode_key <= 'Z' && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
367 #else
368  (void) unicode_key; //not used: avoid compil warning
369 
370  if( key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
371 #endif
372  key += 'A' - 1;
373  }
374 
375 #ifdef __APPLE__
376  if( mods & MD_ALT )
377  {
378  // OSX maps a bunch of commonly used extended-ASCII characters onto the keyboard
379  // using the ALT key. Since we use ALT for some of our hotkeys, we need to map back
380  // to the underlying keys. The kVK_ANSI_* values come from Apple and are said to be
381  // hardware independant.
382  switch( aKeyEvent->GetRawKeyCode() )
383  {
384  case /* kVK_ANSI_1 */ 0x12: key = '1'; break;
385  case /* kVK_ANSI_2 */ 0x13: key = '2'; break;
386  case /* kVK_ANSI_3 */ 0x14: key = '3'; break;
387  case /* kVK_ANSI_4 */ 0x15: key = '4'; break;
388  case /* kVK_ANSI_6 */ 0x16: key = '6'; break;
389  case /* kVK_ANSI_5 */ 0x17: key = '5'; break;
390  case /* kVK_ANSI_Equal */ 0x18: key = '='; break;
391  case /* kVK_ANSI_9 */ 0x19: key = '9'; break;
392  case /* kVK_ANSI_7 */ 0x1A: key = '7'; break;
393  case /* kVK_ANSI_Minus */ 0x1B: key = '-'; break;
394  case /* kVK_ANSI_8 */ 0x1C: key = '8'; break;
395  case /* kVK_ANSI_0 */ 0x1D: key = '0'; break;
396  default: ;
397  }
398  }
399 #endif
400 
401  if( key == WXK_ESCAPE ) // ESC is the special key for canceling tools
403  else
404  evt = TOOL_EVENT( TC_KEYBOARD, TA_KEY_PRESSED, key | mods );
405 
406  return evt;
407 }
static int decodeModifiers(const wxKeyboardState *aState)
Saves the state of key modifiers (Alt, Ctrl and so on).
int translateSpecialCode(int aKeyCode)
static bool isKeyModifierOnly(int aKeyCode)
wxString dump(const wxArrayString &aArray)
Debug helper for printing wxArrayString contents.
bool isKeySpecialCode(int aKeyCode)
TOOL_EVENT.
Definition: tool_event.h:171
const wxChar *const kicadTraceKeyEvent
Flag to enable wxKeyEvent debug tracing.
boost::optional< T > OPT
Definition: optional.h:7

References decodeModifiers(), dump(), isKeyModifierOnly(), isKeySpecialCode(), kicadTraceKeyEvent, MD_ALT, MD_CTRL, TA_CANCEL_TOOL, TA_KEY_PRESSED, TC_COMMAND, TC_KEYBOARD, and translateSpecialCode().

Referenced by DispatchWxEvent().

◆ getView()

KIGFX::VIEW * TOOL_DISPATCHER::getView ( )
private

Returns the instance of VIEW, used by the application.

Definition at line 151 of file tool_dispatcher.cpp.

152 {
153  return m_toolMgr->GetView();
154 }
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:289
TOOL_MANAGER * m_toolMgr
Instance of tool manager that cooperates with the dispatcher.

References TOOL_MANAGER::GetView(), and m_toolMgr.

Referenced by handleMouseButton().

◆ handleMouseButton()

bool TOOL_DISPATCHER::handleMouseButton ( wxEvent &  aEvent,
int  aIndex,
bool  aMotion 
)
private

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

Definition at line 157 of file tool_dispatcher.cpp.

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

References TOOL_DISPATCHER::BUTTON_STATE::button, TOOL_DISPATCHER::BUTTON_STATE::dblClickEvent, decodeModifiers(), TOOL_DISPATCHER::BUTTON_STATE::downEvent, 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, 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().

◆ ResetState()

void TOOL_DISPATCHER::ResetState ( )
virtual

Brings the dispatcher to its initial state.

Definition at line 144 of file tool_dispatcher.cpp.

145 {
146  for( BUTTON_STATE* st : m_buttons )
147  st->Reset();
148 }
std::vector< BUTTON_STATE * > m_buttons
State of mouse buttons.

References m_buttons.

Referenced by TOOL_DISPATCHER().

Member Data Documentation

◆ DragDistanceThreshold

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().

◆ DragTimeThreshold

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().

◆ m_actions

ACTIONS* TOOL_DISPATCHER::m_actions
private

Instance of an actions list that handles legacy action translation

Definition at line 134 of file tool_dispatcher.h.

Referenced by DispatchWxCommand().

◆ m_buttons

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

State of mouse buttons.

Definition at line 125 of file tool_dispatcher.h.

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

◆ m_lastMousePos

VECTOR2D TOOL_DISPATCHER::m_lastMousePos
private

The last mouse cursor position (in world coordinates).

Definition at line 119 of file tool_dispatcher.h.

Referenced by DispatchWxEvent(), and handleMouseButton().

◆ m_toolMgr

TOOL_MANAGER* TOOL_DISPATCHER::m_toolMgr
private

Instance of tool manager that cooperates with the dispatcher.

Definition at line 131 of file tool_dispatcher.h.

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

◆ MouseButtonCount

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: