KiCad PCB EDA Suite
TOOL_DISPATCHER Class Reference

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...
 
OPT< TOOL_EVENTGetToolEvent (wxKeyEvent *aKeyEvent, bool *aSpecialKeyFlag)
 Function GetToolEvent() Maps a wxWidgets key event to a TOOL_EVENT. 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...
 
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

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

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

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

◆ ~TOOL_DISPATCHER()

TOOL_DISPATCHER::~TOOL_DISPATCHER ( )
virtual

Definition at line 135 of file tool_dispatcher.cpp.

136 {
137  for( BUTTON_STATE* st : m_buttons )
138  delete st;
139 }
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 108 of file tool_dispatcher.h.

109  {
110  int mods = 0;
111 
112  if( aState->ControlDown() )
113  mods |= MD_CTRL;
114 
115  if( aState->AltDown() )
116  mods |= MD_ALT;
117 
118  if( aState->ShiftDown() )
119  mods |= MD_SHIFT;
120 
121  return mods;
122  }

References MD_ALT, MD_CTRL, and MD_SHIFT.

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

◆ DispatchWxCommand()

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

585 {
586  OPT<TOOL_EVENT> evt = m_actions->TranslateLegacyId( aEvent.GetId() );
587 
588  if( evt )
589  {
590  wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxCommand %s", evt->Format() );
591 
592  m_toolMgr->ProcessEvent( *evt );
593  }
594  else
595  aEvent.Skip();
596 }
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(), and CVPCB_MAINFRAME::setupEventHandlers().

◆ DispatchWxEvent()

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

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

◆ GetToolEvent()

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

Function GetToolEvent() Maps a wxWidgets key event to a TOOL_EVENT.

Definition at line 328 of file tool_dispatcher.cpp.

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

150 {
151  return m_toolMgr->GetView();
152 }
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:284
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 155 of file tool_dispatcher.cpp.

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

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

Definition at line 142 of file tool_dispatcher.cpp.

143 {
144  for( BUTTON_STATE* st : m_buttons )
145  st->Reset();
146 }
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 102 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 98 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 140 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 131 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 125 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 137 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 94 of file tool_dispatcher.h.


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