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 ()
 Bring the dispatcher to its initial state. More...
 
virtual void DispatchWxEvent (wxEvent &aEvent)
 Process wxEvents (mostly UI events), translate them to TOOL_EVENTs, and make tools handle those. More...
 
OPT< TOOL_EVENTGetToolEvent (wxKeyEvent *aKeyEvent, bool *aSpecialKeyFlag)
 Map a wxWidgets key event to a TOOL_EVENT. More...
 
virtual void DispatchWxCommand (wxCommandEvent &aEvent)
 Process wxCommands (mostly menu related events) and runs appropriate actions (eg. More...
 

Private Member Functions

bool handleMouseButton (wxEvent &aEvent, int aIndex, bool aMotion)
 Saves the state of key modifiers (Alt, Ctrl and so on). More...
 
KIGFX::VIEWgetView ()
 Instance of tool manager that cooperates with the dispatcher. More...
 

Static Private Member Functions

static int decodeModifiers (const wxKeyboardState *aState)
 Stores all the information regarding a mouse button state. More...
 

Private Attributes

VECTOR2D m_lastMousePos
 The last mouse cursor position (in world coordinates). More...
 
std::vector< BUTTON_STATE * > m_buttons
 Returns the instance of VIEW, used by the application. More...
 
TOOL_MANAGERm_toolMgr
 Instance of an actions list that handles legacy action translation. More...
 
ACTIONSm_actions
 

Static Private Attributes

static const int MouseButtonCount = 3
 < Number of mouse buttons that is handled in events. More...
 
static const int DragTimeThreshold = 300
 The distance threshold for mouse cursor that distinguishes between a single mouse click and a beginning of drag event (expressed in screen pixels). More...
 
static const int DragDistanceThreshold = 8
 Handles mouse related events (click, motion, dragging). 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 51 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 124 of file tool_dispatcher.cpp.

124  :
125  m_toolMgr( aToolMgr ),
126  m_actions( aActions )
127 {
128  m_buttons.push_back( new BUTTON_STATE( BUT_LEFT, wxEVT_LEFT_DOWN,
129  wxEVT_LEFT_UP, wxEVT_LEFT_DCLICK ) );
130  m_buttons.push_back( new BUTTON_STATE( BUT_RIGHT, wxEVT_RIGHT_DOWN,
131  wxEVT_RIGHT_UP, wxEVT_RIGHT_DCLICK ) );
132  m_buttons.push_back( new BUTTON_STATE( BUT_MIDDLE, wxEVT_MIDDLE_DOWN,
133  wxEVT_MIDDLE_UP, wxEVT_MIDDLE_DCLICK ) );
134 
135  ResetState();
136 }
virtual void ResetState()
Bring the dispatcher to its initial state.
std::vector< BUTTON_STATE * > m_buttons
Returns the instance of VIEW, used by the application.
TOOL_MANAGER * m_toolMgr
Instance of an actions list that handles legacy action translation.

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

◆ ~TOOL_DISPATCHER()

TOOL_DISPATCHER::~TOOL_DISPATCHER ( )
virtual

Definition at line 139 of file tool_dispatcher.cpp.

140 {
141  for( BUTTON_STATE* st : m_buttons )
142  delete st;
143 }
std::vector< BUTTON_STATE * > m_buttons
Returns the instance of VIEW, used by the application.

References m_buttons.

Member Function Documentation

◆ decodeModifiers()

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

Stores all the information regarding a mouse button state.

Definition at line 104 of file tool_dispatcher.h.

References MD_ALT, MD_CTRL, and MD_SHIFT.

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

◆ DispatchWxCommand()

void TOOL_DISPATCHER::DispatchWxCommand ( wxCommandEvent &  aEvent)
virtual

Process wxCommands (mostly menu related events) and runs appropriate actions (eg.

run the specified tool).

Parameters
aEventis the wxCommandEvent to be processed.

Definition at line 626 of file tool_dispatcher.cpp.

627 {
628  OPT<TOOL_EVENT> evt = m_actions->TranslateLegacyId( aEvent.GetId() );
629 
630  if( evt )
631  {
632  wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxCommand %s", evt->Format() );
633 
634  m_toolMgr->ProcessEvent( *evt );
635  }
636  else
637  aEvent.Skip();
638 }
virtual OPT< TOOL_EVENT > TranslateLegacyId(int aId)=0
Translate legacy tool ids to the corresponding TOOL_ACTION name.
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagate 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 an actions list that handles legacy action translation.

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

Process wxEvents (mostly UI events), translate them to TOOL_EVENTs, and make tools handle those.

Parameters
aEventis the wxWidgets event to be processed.

Definition at line 424 of file tool_dispatcher.cpp.

425 {
426  bool motion = false;
427  bool buttonEvents = false;
428  VECTOR2D pos;
429  OPT<TOOL_EVENT> evt;
430  bool keyIsEscape = false; // True if the keypress was the escape key
431  bool keyIsSpecial = false; // True if the key is a special key code
432  wxWindow* focus = wxWindow::FindFocus();
433 
434  // Required in win32 to ensure wxTimer events get scheduled in between other events
435  // Or else we may stall them out entirely and never get them during actions like rapid
436  // mouse moves.
438 
439  wxEventType type = aEvent.GetEventType();
440 
441  // Sometimes there is no window that has the focus (it happens when another PCB_BASE_FRAME
442  // is opened and is iconized on Windows).
443  // In this case, give the focus to the parent frame (GAL canvas itself does not accept the
444  // focus when iconized for some obscure reason)
445  if( focus == nullptr )
446  {
447  wxWindow* holderWindow = dynamic_cast<wxWindow*>( m_toolMgr->GetToolHolder() );
448 
449 #if defined( _WIN32 )
450  // Mouse events may trigger regardless of window status (windows feature)
451  // However we need to avoid focus fighting (especially modals)
452  if( holderWindow && holderWindow->GetHWND() == GetForegroundWindow() )
453 #else
454  if( holderWindow )
455 #endif
456  {
457  holderWindow->SetFocus();
458  }
459  }
460 
461  if( isMouseClick( type ) )
462  {
464  m_toolMgr->GetToolHolder()->GetToolCanvas()->SetFocus();
465  }
466 
467  // Mouse handling
468  // Note: wxEVT_LEFT_DOWN event must always be skipped.
469  if( type == wxEVT_MOTION || type == wxEVT_MOUSEWHEEL ||
470 #if wxCHECK_VERSION( 3, 1, 0 ) || defined( USE_OSX_MAGNIFY_EVENT )
471  type == wxEVT_MAGNIFY ||
472 #endif
473  isMouseClick( type ) ||
474  // Event issued when mouse retains position in screen coordinates,
475  // but changes in world coordinates (e.g. autopanning)
477  {
478  wxMouseEvent* me = static_cast<wxMouseEvent*>( &aEvent );
479  int mods = decodeModifiers( me );
480 
481  if( m_toolMgr->GetViewControls() )
482  {
484 
485  if( pos != m_lastMousePos )
486  {
487  motion = true;
488  m_lastMousePos = pos;
489  }
490  }
491 
492  for( unsigned int i = 0; i < m_buttons.size(); i++ )
493  buttonEvents |= handleMouseButton( aEvent, i, motion );
494 
495  if( m_toolMgr->GetViewControls() )
496  {
497  if( !buttonEvents && motion )
498  {
499  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_MOTION, mods );
500  evt->SetMousePosition( pos );
501  }
502  }
503  }
504  else if( type == wxEVT_CHAR_HOOK || type == wxEVT_CHAR )
505  {
506  wxKeyEvent* ke = static_cast<wxKeyEvent*>( &aEvent );
507 
508  keyIsEscape = ( ke->GetKeyCode() == WXK_ESCAPE );
509 
510  wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( focus );
511  wxStyledTextCtrl* styledText = dynamic_cast<wxStyledTextCtrl*>( focus );
512 
513  if( textEntry || styledText )
514  {
515  bool enabled = true;
516 
517  if( textEntry )
518  enabled = textEntry->IsEditable();
519  else if( styledText )
520  enabled = styledText->IsEditable();
521 
522  // Never process key events for tools when a text entry has focus
523  if( enabled )
524  {
525  aEvent.Skip();
526  return;
527  }
528  // Even if not enabled, allow a copy out
529  else if( ke->GetModifiers() == wxMOD_CONTROL && ke->GetKeyCode() == 'C' )
530  {
531  aEvent.Skip();
532  return;
533  }
534  }
535 
536  evt = GetToolEvent( ke, &keyIsSpecial );
537  }
538  else if( type == wxEVT_MENU_OPEN || type == wxEVT_MENU_CLOSE || type == wxEVT_MENU_HIGHLIGHT )
539  {
540  //
541  // wxWidgets has several issues that we have to work around:
542  //
543  // 1) wxWidgets 3.0.x Windows has a bug where wxEVT_MENU_OPEN and wxEVT_MENU_HIGHLIGHT
544  // events are not captured by the ACTON_MENU menus. So we forward them here.
545  // (FWIW, this one is fixed in wxWidgets 3.1.x.)
546  //
547  // 2) wxWidgets doesn't pass the menu pointer for wxEVT_MENU_HIGHLIGHT events. So we
548  // store the menu pointer from the wxEVT_MENU_OPEN call.
549  //
550  // 3) wxWidgets has no way to tell whether a command is from a menu selection or a
551  // hotkey. So we keep track of menu highlighting so we can differentiate.
552  //
553 
554  static ACTION_MENU* currentMenu;
555 
556  wxMenuEvent& menuEvent = *dynamic_cast<wxMenuEvent*>( &aEvent );
557 
558  if( type == wxEVT_MENU_OPEN )
559  {
560  currentMenu = dynamic_cast<ACTION_MENU*>( menuEvent.GetMenu() );
561 
562  if( currentMenu )
563  currentMenu->OnMenuEvent( menuEvent );
564  }
565  else if( type == wxEVT_MENU_HIGHLIGHT )
566  {
567  if( currentMenu )
568  currentMenu->OnMenuEvent( menuEvent );
569  }
570  else if( type == wxEVT_MENU_CLOSE )
571  {
572  if( currentMenu )
573  currentMenu->OnMenuEvent( menuEvent );
574 
575  currentMenu = nullptr;
576  }
577 
578  aEvent.Skip();
579  }
580 
581  bool handled = false;
582 
583  if( evt )
584  {
585  wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxEvent %s", evt->Format() );
586 
587  handled = m_toolMgr->ProcessEvent( *evt );
588 
589  wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxEvent - Handled: %s %s",
590  ( handled ? "true" : "false" ), evt->Format() );
591  }
592 
593  // pass the event to the GUI, it might still be interested in it
594  // Note wxEVT_CHAR_HOOK event is already skipped for special keys not used by KiCad
595  // and wxEVT_LEFT_DOWN must be always Skipped.
596  //
597  // On OS X, key events are always meant to be caught. An uncaught key event is assumed
598  // to be a user input error by OS X (as they are pressing keys in a context where nothing
599  // is there to catch the event). This annoyingly makes OS X beep and/or flash the screen
600  // in Pcbnew and the footprint editor any time a hotkey is used. The correct procedure is
601  // to NOT pass wxEVT_CHAR events to the GUI under OS X.
602  //
603  // On Windows, avoid to call wxEvent::Skip for special keys because some keys
604  // (PAGE_UP, PAGE_DOWN) have predefined actions (like move thumbtrack cursor), and we do
605  // not want these actions executed (most are handled by KiCad)
606 
607  if( !evt || type == wxEVT_LEFT_DOWN )
608  aEvent.Skip();
609 
610  // Not handled wxEVT_CHAR must be Skipped (sent to GUI).
611  // Otherwise accelerators and shortcuts in main menu or toolbars are not seen.
612  // Escape key presses are never skipped by the handler since they correspond to tool cancel
613  // events, and if they aren't skipped then they are propagated to other frames (which we
614  // don't want).
615  if( (type == wxEVT_CHAR || type == wxEVT_CHAR_HOOK)
616  && !keyIsSpecial
617  && !handled
618  && !keyIsEscape )
619  aEvent.Skip();
620 
621  wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxEvent - Wx event skipped: %s",
622  ( aEvent.GetSkipped() ? "true" : "false" ) );
623 }
static int decodeModifiers(const wxKeyboardState *aState)
Stores all the information regarding a mouse button state.
virtual VECTOR2D GetMousePosition(bool aWorldCoordinates=true) const =0
Return the current mouse pointer position.
static const wxEventType EVT_REFRESH_MOUSE
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:45
virtual wxWindow * GetToolCanvas() const =0
Canvas access.
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagate an event to tools that requested events of matching type(s).
void ForceTimerMessagesToBeCreatedIfNecessary()
Forces wxTimers to fire more promptly on Win32.
Definition: gtk/app.cpp:56
Generic, UI-independent tool event.
Definition: tool_event.h:173
VECTOR2D m_lastMousePos
The last mouse cursor position (in world coordinates).
std::vector< BUTTON_STATE * > m_buttons
Returns the instance of VIEW, used by the application.
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)
Map a wxWidgets key event to a TOOL_EVENT.
static bool isMouseClick(wxEventType type)
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)
Saves the state of key modifiers (Alt, Ctrl and so on).
TOOL_MANAGER * m_toolMgr
Instance of an actions list that handles legacy action translation.

References decodeModifiers(), KIGFX::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE, KIPLATFORM::APP::ForceTimerMessagesToBeCreatedIfNecessary(), KIGFX::VIEW_CONTROLS::GetMousePosition(), TOOLS_HOLDER::GetToolCanvas(), GetToolEvent(), TOOL_MANAGER::GetToolHolder(), TOOL_MANAGER::GetViewControls(), handleMouseButton(), isMouseClick(), 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 
)

Map a wxWidgets key event to a TOOL_EVENT.

Definition at line 344 of file tool_dispatcher.cpp.

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

Instance of tool manager that cooperates with the dispatcher.

Definition at line 153 of file tool_dispatcher.cpp.

154 {
155  return m_toolMgr->GetView();
156 }
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:289
TOOL_MANAGER * m_toolMgr
Instance of an actions list that handles legacy action translation.

References TOOL_MANAGER::GetView(), and m_toolMgr.

Referenced by handleMouseButton().

◆ handleMouseButton()

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

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

Definition at line 159 of file tool_dispatcher.cpp.

160 {
161  BUTTON_STATE* st = m_buttons[aIndex];
162  wxEventType type = aEvent.GetEventType();
163  OPT<TOOL_EVENT> evt;
164  bool isClick = false;
165 
166 // bool up = type == st->upEvent;
167 // bool down = type == st->downEvent;
168  bool up = false, down = false;
169  bool dblClick = type == st->dblClickEvent;
170  bool state = st->GetState();
171 
172  if( !dblClick )
173  {
174  // Sometimes the dispatcher does not receive mouse button up event, so it stays
175  // in the dragging mode even if the mouse button is not held anymore
176  if( st->pressed && !state )
177  up = true;
178  // Don't apply same logic to down events as it kills touchpad tapping
179  else if( !st->pressed && type == st->downEvent )
180  down = true;
181  }
182 
183  int mods = decodeModifiers( static_cast<wxMouseEvent*>( &aEvent ) );
184  int args = st->button | mods;
185 
186  if( down ) // Handle mouse button press
187  {
188  st->downTimestamp = wxGetLocalTimeMillis();
189 
190  if( !st->pressed ) // save the drag origin on the first click only
191  st->dragOrigin = m_lastMousePos;
192 
193  st->downPosition = m_lastMousePos;
194  st->dragMaxDelta = 0;
195  st->pressed = true;
196  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DOWN, args );
197  }
198  else if( up ) // Handle mouse button release
199  {
200  st->pressed = false;
201 
202  if( st->dragging )
203  {
204  wxLongLong t = wxGetLocalTimeMillis();
205 
206  // Determine if it was just a single click or beginning of dragging
207  if( t - st->downTimestamp < DragTimeThreshold &&
208  st->dragMaxDelta < DragDistanceThreshold )
209  isClick = true;
210  else
211  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_UP, args );
212  }
213  else
214  isClick = true;
215 
216  if( isClick )
217  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_CLICK, args );
218 
219  st->dragging = false;
220  }
221  else if( dblClick )
222  {
223  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DBLCLICK, args );
224  }
225 
226  if( st->pressed && aMotion )
227  {
228  st->dragging = true;
229  double dragPixelDistance =
230  getView()->ToScreen( m_lastMousePos - st->dragOrigin, false ).EuclideanNorm();
231  st->dragMaxDelta = std::max( st->dragMaxDelta, dragPixelDistance );
232 
233  wxLongLong t = wxGetLocalTimeMillis();
234 
235  if( t - st->downTimestamp > DragTimeThreshold || st->dragMaxDelta > DragDistanceThreshold )
236  {
237  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DRAG, args );
238  evt->setMouseDragOrigin( st->dragOrigin );
239  evt->setMouseDelta( m_lastMousePos - st->dragOrigin );
240  }
241  }
242 
243  if( evt )
244  {
245  evt->SetMousePosition( isClick ? st->downPosition : m_lastMousePos );
246  m_toolMgr->ProcessEvent( *evt );
247 
248  return true;
249  }
250 
251  return false;
252 }
static int decodeModifiers(const wxKeyboardState *aState)
Stores all the information regarding a mouse button state.
static const int DragDistanceThreshold
Handles mouse related events (click, motion, dragging).
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagate an event to tools that requested events of matching type(s).
Generic, UI-independent tool event.
Definition: tool_event.h:173
VECTOR2D m_lastMousePos
The last mouse cursor position (in world coordinates).
VECTOR2D ToScreen(const VECTOR2D &aCoord, bool aAbsolute=true) const
Convert a world space point/vector to a point/vector in screen space coordinates.
Definition: view.cpp:469
std::vector< BUTTON_STATE * > m_buttons
Returns the instance of VIEW, used by the application.
boost::optional< T > OPT
Definition: optional.h:7
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:293
static const int DragTimeThreshold
The distance threshold for mouse cursor that distinguishes between a single mouse click and a beginni...
KIGFX::VIEW * getView()
Instance of tool manager that cooperates with the dispatcher.
TOOL_MANAGER * m_toolMgr
Instance of an actions list that handles legacy action translation.

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

Bring the dispatcher to its initial state.

Definition at line 146 of file tool_dispatcher.cpp.

147 {
148  for( BUTTON_STATE* st : m_buttons )
149  st->Reset();
150 }
std::vector< BUTTON_STATE * > m_buttons
Returns the instance of VIEW, used by the application.

References m_buttons.

Referenced by TOOL_DISPATCHER().

Member Data Documentation

◆ DragDistanceThreshold

const int TOOL_DISPATCHER::DragDistanceThreshold = 8
staticprivate

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

Definition at line 98 of file tool_dispatcher.h.

Referenced by handleMouseButton().

◆ DragTimeThreshold

const int TOOL_DISPATCHER::DragTimeThreshold = 300
staticprivate

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

Definition at line 94 of file tool_dispatcher.h.

Referenced by handleMouseButton().

◆ m_actions

ACTIONS* TOOL_DISPATCHER::m_actions
private

Definition at line 136 of file tool_dispatcher.h.

Referenced by DispatchWxCommand().

◆ m_buttons

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

Returns the instance of VIEW, used by the application.

Definition at line 127 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).

State of mouse buttons.

Definition at line 121 of file tool_dispatcher.h.

Referenced by DispatchWxEvent(), and handleMouseButton().

◆ m_toolMgr

TOOL_MANAGER* TOOL_DISPATCHER::m_toolMgr
private

Instance of an actions list that handles legacy action translation.

Definition at line 133 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.

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


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