KiCad PCB EDA Suite
tool_dispatcher.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2013 CERN
5  * Copyright (C) 2013-2021 KiCad Developers, see CHANGELOG.txt for contributors.
6  * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 #include <macros.h>
27 #include <trace_helpers.h>
28 
29 #include <tool/tool_manager.h>
30 #include <tool/tools_holder.h>
31 #include <tool/tool_dispatcher.h>
32 #include <tool/actions.h>
33 #include <tool/action_manager.h>
34 #include <tool/action_menu.h>
35 #include <view/view.h>
36 #include <view/wx_view_controls.h>
37 
38 #include <class_draw_panel_gal.h>
39 #include <eda_draw_frame.h>
40 
41 #include <core/arraydim.h>
42 #include <core/optional.h>
43 #include <wx/stc/stc.h>
44 #include <kiplatform/app.h>
45 
48 {
49  BUTTON_STATE( TOOL_MOUSE_BUTTONS aButton, const wxEventType& aDownEvent,
50  const wxEventType& aUpEvent, const wxEventType& aDblClickEvent ) :
51  dragging( false ),
52  pressed( false ),
53  dragMaxDelta( 0.0f ),
54  button( aButton ),
55  downEvent( aDownEvent ),
56  upEvent( aUpEvent ),
57  dblClickEvent( aDblClickEvent )
58  {};
59 
61  bool dragging;
62 
64  bool pressed;
65 
68 
71 
74  double dragMaxDelta;
75 
78 
80  wxEventType downEvent;
81 
83  wxEventType upEvent;
84 
86  wxEventType dblClickEvent;
87 
89  wxLongLong downTimestamp;
90 
92  void Reset()
93  {
94  dragging = false;
95  pressed = false;
96  }
97 
99  bool GetState() const
100  {
101  wxMouseState mouseState = wxGetMouseState();
102 
103  switch( button )
104  {
105  case BUT_LEFT:
106  return mouseState.LeftIsDown();
107 
108  case BUT_MIDDLE:
109  return mouseState.MiddleIsDown();
110 
111  case BUT_RIGHT:
112  return mouseState.RightIsDown();
113 
114  default:
115  assert( false );
116  break;
117  }
118 
119  return false;
120  }
121 };
122 
123 
125  m_toolMgr( aToolMgr )
126 {
127  m_buttons.push_back( new BUTTON_STATE( BUT_LEFT, wxEVT_LEFT_DOWN,
128  wxEVT_LEFT_UP, wxEVT_LEFT_DCLICK ) );
129  m_buttons.push_back( new BUTTON_STATE( BUT_RIGHT, wxEVT_RIGHT_DOWN,
130  wxEVT_RIGHT_UP, wxEVT_RIGHT_DCLICK ) );
131  m_buttons.push_back( new BUTTON_STATE( BUT_MIDDLE, wxEVT_MIDDLE_DOWN,
132  wxEVT_MIDDLE_UP, wxEVT_MIDDLE_DCLICK ) );
133 
134  ResetState();
135 }
136 
137 
139 {
140  for( BUTTON_STATE* st : m_buttons )
141  delete st;
142 }
143 
144 
146 {
147  for( BUTTON_STATE* st : m_buttons )
148  st->Reset();
149 }
150 
151 
153 {
154  return m_toolMgr->GetView();
155 }
156 
157 
158 bool TOOL_DISPATCHER::handleMouseButton( wxEvent& aEvent, int aIndex, bool aMotion )
159 {
160  BUTTON_STATE* st = m_buttons[aIndex];
161  wxEventType type = aEvent.GetEventType();
162  OPT<TOOL_EVENT> evt;
163  bool isClick = false;
164 
165 // bool up = type == st->upEvent;
166 // bool down = type == st->downEvent;
167  bool up = false, down = false;
168  bool dblClick = type == st->dblClickEvent;
169  bool state = st->GetState();
170 
171  if( !dblClick )
172  {
173  // Sometimes the dispatcher does not receive mouse button up event, so it stays
174  // in the dragging mode even if the mouse button is not held anymore
175  if( st->pressed && !state )
176  up = true;
177  // Don't apply same logic to down events as it kills touchpad tapping
178  else if( !st->pressed && type == st->downEvent )
179  down = true;
180  }
181 
182  int mods = decodeModifiers( static_cast<wxMouseEvent*>( &aEvent ) );
183  int args = st->button | mods;
184 
185  if( down ) // Handle mouse button press
186  {
187  st->downTimestamp = wxGetLocalTimeMillis();
188 
189  if( !st->pressed ) // save the drag origin on the first click only
191 
193  st->dragMaxDelta = 0;
194  st->pressed = true;
195  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DOWN, args );
196  }
197  else if( up ) // Handle mouse button release
198  {
199  st->pressed = false;
200 
201  if( st->dragging )
202  {
203  wxLongLong t = wxGetLocalTimeMillis();
204 
205  // Determine if it was just a single click or beginning of dragging
206  if( t - st->downTimestamp < DragTimeThreshold &&
208  isClick = true;
209  else
210  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_UP, args );
211  }
212  else
213  isClick = true;
214 
215  if( isClick )
216  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_CLICK, args );
217 
218  st->dragging = false;
219  }
220  else if( dblClick )
221  {
222  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DBLCLICK, args );
223  }
224 
225  if( st->pressed && aMotion )
226  {
227  st->dragging = true;
228  double dragPixelDistance =
230  st->dragMaxDelta = std::max( st->dragMaxDelta, dragPixelDistance );
231 
232  wxLongLong t = wxGetLocalTimeMillis();
233 
235  {
236  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DRAG, args );
237  evt->setMouseDragOrigin( st->dragOrigin );
238  evt->setMouseDelta( m_lastMousePos - st->dragOrigin );
239  }
240  }
241 
242  if( evt )
243  {
244  evt->SetMousePosition( isClick ? st->downPosition : m_lastMousePos );
245  m_toolMgr->ProcessEvent( *evt );
246 
247  return true;
248  }
249 
250  return false;
251 }
252 
253 
254 // Helper function to know if a special key ( see key list ) should be captured
255 // or if the event can be skipped
256 // on Linux, the event must be passed to the GUI if they are not used by KiCad,
257 // especially the wxEVENT_CHAR_HOOK, if it is not handled
258 // Some keys have a predefined action in wxWidgets so, even if not used,
259 // the even will be not skipped
260 // the unused keys listed in isKeySpecialCode() will be not skipped
261 bool isKeySpecialCode( int aKeyCode )
262 {
263  // These keys have predefined actions (like move thumbtrack cursor),
264  // and we do not want these actions executed
265  const enum wxKeyCode special_keys[] =
266  {
267  WXK_PAGEUP, WXK_PAGEDOWN,
268  WXK_NUMPAD_PAGEUP, WXK_NUMPAD_PAGEDOWN
269  };
270 
271  bool isInList = false;
272 
273  for( unsigned ii = 0; ii < arrayDim( special_keys ) && !isInList; ii++ )
274  {
275  if( special_keys[ii] == aKeyCode )
276  isInList = true;
277  }
278 
279  return isInList;
280 }
281 
282 
283 // Helper function to know if a key should be managed by DispatchWxEvent()
284 // or if the event can be ignored and skipped because the key is only a modifier
285 // that is not used alone in kicad
286 static bool isKeyModifierOnly( int aKeyCode )
287 {
288  const enum wxKeyCode special_keys[] =
289  {
290  WXK_CONTROL, WXK_RAW_CONTROL, WXK_SHIFT,WXK_ALT
291  };
292 
293  bool isInList = false;
294 
295  for( unsigned ii = 0; ii < arrayDim( special_keys ) && !isInList; ii++ )
296  {
297  if( special_keys[ii] == aKeyCode )
298  isInList = true;
299  }
300 
301  return isInList;
302 }
303 
304 
305 static bool isMouseClick( wxEventType type )
306 {
307  return type == wxEVT_LEFT_DOWN || type == wxEVT_LEFT_UP || type == wxEVT_MIDDLE_DOWN
308  || type == wxEVT_MIDDLE_UP || type == wxEVT_RIGHT_DOWN || type == wxEVT_RIGHT_UP
309  || type == wxEVT_LEFT_DCLICK || type == wxEVT_MIDDLE_DCLICK
310  || type == wxEVT_RIGHT_DCLICK;
311 }
312 
313 
314 /* A helper class that convert some special key codes to an equivalent.
315  * WXK_NUMPAD_UP to WXK_UP,
316  * WXK_NUMPAD_DOWN to WXK_DOWN,
317  * WXK_NUMPAD_LEFT to WXK_LEFT,
318  * WXK_NUMPAD_RIGHT,
319  * WXK_NUMPAD_PAGEUP,
320  * WXK_NUMPAD_PAGEDOWN
321  * note:
322  * wxEVT_CHAR_HOOK does this conversion when it is skipped by firing a wxEVT_CHAR
323  * with this converted code, but we do not skip these key events because they also
324  * have default action (scroll the panel)
325  */
326 int translateSpecialCode( int aKeyCode )
327 {
328  switch( aKeyCode )
329  {
330  case WXK_NUMPAD_UP: return WXK_UP;
331  case WXK_NUMPAD_DOWN: return WXK_DOWN;
332  case WXK_NUMPAD_LEFT: return WXK_LEFT;
333  case WXK_NUMPAD_RIGHT: return WXK_RIGHT;
334  case WXK_NUMPAD_PAGEUP: return WXK_PAGEUP;
335  case WXK_NUMPAD_PAGEDOWN: return WXK_PAGEDOWN;
336  default: break;
337  };
338 
339  return aKeyCode;
340 }
341 
342 
343 OPT<TOOL_EVENT> TOOL_DISPATCHER::GetToolEvent( wxKeyEvent* aKeyEvent, bool* keyIsSpecial )
344 {
345  OPT<TOOL_EVENT> evt;
346  int key = aKeyEvent->GetKeyCode();
347  int unicode_key = aKeyEvent->GetUnicodeKey();
348 
349  // This wxEVT_CHAR_HOOK event can be ignored: not useful in Kicad
350  if( isKeyModifierOnly( key ) )
351  {
352  aKeyEvent->Skip();
353  return evt;
354  }
355 
356  wxLogTrace( kicadTraceKeyEvent, "TOOL_DISPATCHER::GetToolEvent %s", dump( *aKeyEvent ) );
357 
358  // if the key event must be skipped, skip it here if the event is a wxEVT_CHAR_HOOK
359  // and do nothing.
360  *keyIsSpecial = isKeySpecialCode( key );
361 
362  if( aKeyEvent->GetEventType() == wxEVT_CHAR_HOOK )
363  key = translateSpecialCode( key );
364 
365  int mods = decodeModifiers( aKeyEvent );
366 
367  if( mods & MD_CTRL )
368  {
369  // wxWidgets maps key codes related to Ctrl+letter handled by CHAR_EVT
370  // (http://docs.wxwidgets.org/trunk/classwx_key_event.html):
371  // char events for ASCII letters in this case carry codes corresponding to the ASCII
372  // value of Ctrl-Latter, i.e. 1 for Ctrl-A, 2 for Ctrl-B and so on until 26 for Ctrl-Z.
373  // They are remapped here to be more easy to handle in code
374  // Note also on OSX wxWidgets has a differnt behavior and the mapping is made
375  // only for ctrl+'A' to ctlr+'Z' (unicode code return 'A' to 'Z').
376  // Others OS return WXK_CONTROL_A to WXK_CONTROL_Z, and Ctrl+'M' returns the same code as
377  // the return key, so the remapping does not use the unicode key value.
378 #ifdef __APPLE__
379  if( unicode_key >= 'A' && unicode_key <= 'Z' && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
380 #else
381  (void) unicode_key; //not used: avoid compil warning
382 
383  if( key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
384 #endif
385  key += 'A' - 1;
386  }
387 
388 #ifdef __APPLE__
389  if( mods & MD_ALT )
390  {
391  // OSX maps a bunch of commonly used extended-ASCII characters onto the keyboard
392  // using the ALT key. Since we use ALT for some of our hotkeys, we need to map back
393  // to the underlying keys. The kVK_ANSI_* values come from Apple and are said to be
394  // hardware independant.
395  switch( aKeyEvent->GetRawKeyCode() )
396  {
397  case /* kVK_ANSI_1 */ 0x12: key = '1'; break;
398  case /* kVK_ANSI_2 */ 0x13: key = '2'; break;
399  case /* kVK_ANSI_3 */ 0x14: key = '3'; break;
400  case /* kVK_ANSI_4 */ 0x15: key = '4'; break;
401  case /* kVK_ANSI_6 */ 0x16: key = '6'; break;
402  case /* kVK_ANSI_5 */ 0x17: key = '5'; break;
403  case /* kVK_ANSI_Equal */ 0x18: key = '='; break;
404  case /* kVK_ANSI_9 */ 0x19: key = '9'; break;
405  case /* kVK_ANSI_7 */ 0x1A: key = '7'; break;
406  case /* kVK_ANSI_Minus */ 0x1B: key = '-'; break;
407  case /* kVK_ANSI_8 */ 0x1C: key = '8'; break;
408  case /* kVK_ANSI_0 */ 0x1D: key = '0'; break;
409  default: ;
410  }
411  }
412 #endif
413 
414  if( key == WXK_ESCAPE ) // ESC is the special key for canceling tools
416  else
417  evt = TOOL_EVENT( TC_KEYBOARD, TA_KEY_PRESSED, key | mods );
418 
419  return evt;
420 }
421 
422 
423 void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
424 {
425  bool motion = false;
426  bool buttonEvents = false;
427  VECTOR2D pos;
428  OPT<TOOL_EVENT> evt;
429  bool keyIsEscape = false; // True if the keypress was the escape key
430  bool keyIsSpecial = false; // True if the key is a special key code
431  wxWindow* focus = wxWindow::FindFocus();
432 
433  // Required in win32 to ensure wxTimer events get scheduled in between other events
434  // Or else we may stall them out entirely and never get them during actions like rapid
435  // mouse moves.
437 
438  wxEventType type = aEvent.GetEventType();
439 
440  // Sometimes there is no window that has the focus (it happens when another PCB_BASE_FRAME
441  // is opened and is iconized on Windows).
442  // In this case, give the focus to the parent frame (GAL canvas itself does not accept the
443  // focus when iconized for some obscure reason)
444  if( focus == nullptr )
445  {
446  wxWindow* holderWindow = dynamic_cast<wxWindow*>( m_toolMgr->GetToolHolder() );
447 
448 #if defined( _WIN32 )
449  // Mouse events may trigger regardless of window status (windows feature)
450  // However we need to avoid focus fighting (especially modals)
451  if( holderWindow && holderWindow->GetHWND() == GetForegroundWindow() )
452 #else
453  if( holderWindow )
454 #endif
455  {
456  holderWindow->SetFocus();
457  }
458  }
459 
460  if( isMouseClick( type ) )
461  {
463  m_toolMgr->GetToolHolder()->GetToolCanvas()->SetFocus();
464  }
465 
466  // Mouse handling
467  // Note: wxEVT_LEFT_DOWN event must always be skipped.
468  if( type == wxEVT_MOTION || type == wxEVT_MOUSEWHEEL ||
469 #if wxCHECK_VERSION( 3, 1, 0 ) || defined( USE_OSX_MAGNIFY_EVENT )
470  type == wxEVT_MAGNIFY ||
471 #endif
472  isMouseClick( type ) ||
473  // Event issued when mouse retains position in screen coordinates,
474  // but changes in world coordinates (e.g. autopanning)
476  {
477  wxMouseEvent* me = static_cast<wxMouseEvent*>( &aEvent );
478  int mods = decodeModifiers( me );
479 
480  if( m_toolMgr->GetViewControls() )
481  {
483 
484  if( pos != m_lastMousePos )
485  {
486  motion = true;
487  m_lastMousePos = pos;
488  }
489  }
490 
491  for( unsigned int i = 0; i < m_buttons.size(); i++ )
492  buttonEvents |= handleMouseButton( aEvent, i, motion );
493 
494  if( m_toolMgr->GetViewControls() )
495  {
496  if( !buttonEvents && motion )
497  {
498  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_MOTION, mods );
499  evt->SetMousePosition( pos );
500  }
501  }
502  }
503  else if( type == wxEVT_CHAR_HOOK || type == wxEVT_CHAR )
504  {
505  wxKeyEvent* ke = static_cast<wxKeyEvent*>( &aEvent );
506 
507  keyIsEscape = ( ke->GetKeyCode() == WXK_ESCAPE );
508 
509  wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( focus );
510  wxStyledTextCtrl* styledText = dynamic_cast<wxStyledTextCtrl*>( focus );
511 
512  if( textEntry || styledText )
513  {
514  bool enabled = true;
515 
516  if( textEntry )
517  enabled = textEntry->IsEditable();
518  else if( styledText )
519  enabled = styledText->IsEditable();
520 
521  // Never process key events for tools when a text entry has focus
522  if( enabled )
523  {
524  aEvent.Skip();
525  return;
526  }
527  // Even if not enabled, allow a copy out
528  else if( ke->GetModifiers() == wxMOD_CONTROL && ke->GetKeyCode() == 'C' )
529  {
530  aEvent.Skip();
531  return;
532  }
533  }
534 
535  evt = GetToolEvent( ke, &keyIsSpecial );
536  }
537  else if( type == wxEVT_MENU_OPEN || type == wxEVT_MENU_CLOSE || type == wxEVT_MENU_HIGHLIGHT )
538  {
539  //
540  // wxWidgets has several issues that we have to work around:
541  //
542  // 1) wxWidgets 3.0.x Windows has a bug where wxEVT_MENU_OPEN and wxEVT_MENU_HIGHLIGHT
543  // events are not captured by the ACTON_MENU menus. So we forward them here.
544  // (FWIW, this one is fixed in wxWidgets 3.1.x.)
545  //
546  // 2) wxWidgets doesn't pass the menu pointer for wxEVT_MENU_HIGHLIGHT events. So we
547  // store the menu pointer from the wxEVT_MENU_OPEN call.
548  //
549  // 3) wxWidgets has no way to tell whether a command is from a menu selection or a
550  // hotkey. So we keep track of menu highlighting so we can differentiate.
551  //
552 
553  static ACTION_MENU* currentMenu;
554 
555  wxMenuEvent& menuEvent = *dynamic_cast<wxMenuEvent*>( &aEvent );
556 
557  if( type == wxEVT_MENU_OPEN )
558  {
559  currentMenu = dynamic_cast<ACTION_MENU*>( menuEvent.GetMenu() );
560 
561  if( currentMenu )
562  currentMenu->OnMenuEvent( menuEvent );
563  }
564  else if( type == wxEVT_MENU_HIGHLIGHT )
565  {
566  if( currentMenu )
567  currentMenu->OnMenuEvent( menuEvent );
568  }
569  else if( type == wxEVT_MENU_CLOSE )
570  {
571  if( currentMenu )
572  currentMenu->OnMenuEvent( menuEvent );
573 
574  currentMenu = nullptr;
575  }
576 
577  aEvent.Skip();
578  }
579 
580  bool handled = false;
581 
582  if( evt )
583  {
584  wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxEvent %s", evt->Format() );
585 
586  handled = m_toolMgr->ProcessEvent( *evt );
587 
588  wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxEvent - Handled: %s %s",
589  ( handled ? "true" : "false" ), evt->Format() );
590  }
591 
592  // pass the event to the GUI, it might still be interested in it
593  // Note wxEVT_CHAR_HOOK event is already skipped for special keys not used by KiCad
594  // and wxEVT_LEFT_DOWN must be always Skipped.
595  //
596  // On OS X, key events are always meant to be caught. An uncaught key event is assumed
597  // to be a user input error by OS X (as they are pressing keys in a context where nothing
598  // is there to catch the event). This annoyingly makes OS X beep and/or flash the screen
599  // in Pcbnew and the footprint editor any time a hotkey is used. The correct procedure is
600  // to NOT pass wxEVT_CHAR events to the GUI under OS X.
601  //
602  // On Windows, avoid to call wxEvent::Skip for special keys because some keys
603  // (PAGE_UP, PAGE_DOWN) have predefined actions (like move thumbtrack cursor), and we do
604  // not want these actions executed (most are handled by KiCad)
605 
606  if( !evt || type == wxEVT_LEFT_DOWN )
607  aEvent.Skip();
608 
609  // Not handled wxEVT_CHAR must be Skipped (sent to GUI).
610  // Otherwise accelerators and shortcuts in main menu or toolbars are not seen.
611  // Escape key presses are never skipped by the handler since they correspond to tool cancel
612  // events, and if they aren't skipped then they are propagated to other frames (which we
613  // don't want).
614  if( (type == wxEVT_CHAR || type == wxEVT_CHAR_HOOK)
615  && !keyIsSpecial
616  && !handled
617  && !keyIsEscape )
618  aEvent.Skip();
619 
620  wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxEvent - Wx event skipped: %s",
621  ( aEvent.GetSkipped() ? "true" : "false" ) );
622 }
VECTOR2D downPosition
Difference between drag origin point and current mouse position (expressed as distance in pixels).
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:289
static int decodeModifiers(const wxKeyboardState *aState)
Stores all the information regarding a mouse button state.
double dragMaxDelta
Determines the mouse button for which information are stored.
BUTTON_STATE(TOOL_MOUSE_BUTTONS aButton, const wxEventType &aDownEvent, const wxEventType &aUpEvent, const wxEventType &aDblClickEvent)
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:47
int translateSpecialCode(int aKeyCode)
static bool isKeyModifierOnly(int aKeyCode)
static const int DragDistanceThreshold
Handles mouse related events (click, motion, dragging).
virtual ~TOOL_DISPATCHER()
virtual void ResetState()
Bring the dispatcher to its initial state.
bool dragging
Flag indicating that dragging is active for the given button.
VECTOR2D dragOrigin
Point where click event has occurred.
WX_VIEW_CONTROLS class definition.
void Reset()
Checks the current state of the button.
This file contains miscellaneous commonly used macros and functions.
Master controller class:
Definition: tool_manager.h:52
< Stores information about a mouse button state
wxString dump(const wxArrayString &aArray)
Debug helper for printing wxArrayString contents.
virtual wxWindow * GetToolCanvas() const =0
Canvas access.
wxEventType dblClickEvent
Time stamp for the last mouse button press event.
wxEventType downEvent
The type of wxEvent that determines mouse button release.
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:81
virtual void DispatchWxEvent(wxEvent &aEvent)
Process wxEvents (mostly UI events), translate them to TOOL_EVENTs, and make tools handle those.
bool isKeySpecialCode(int aKeyCode)
Generic, UI-independent tool event.
Definition: tool_event.h:173
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
wxLogTrace helper definitions.
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:470
std::vector< BUTTON_STATE * > m_buttons
Returns the instance of VIEW, used by the application.
void OnMenuEvent(wxMenuEvent &aEvent)
TOOL_MOUSE_BUTTONS
Definition: tool_event.h:128
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.
TOOL_DISPATCHER(TOOL_MANAGER *aToolMgr)
static bool isMouseClick(wxEventType type)
bool pressed
Point where dragging has started (in world coordinates).
const wxChar *const kicadTraceKeyEvent
Flag to enable wxKeyEvent debug tracing.
const wxChar *const kicadTraceToolStack
Flag to enable tracing of the tool handling stack.
boost::optional< T > OPT
Definition: optional.h:7
wxEventType upEvent
The type of wxEvent that determines mouse button double click.
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:293
wxLongLong downTimestamp
Restores initial state.
static const int DragTimeThreshold
The distance threshold for mouse cursor that distinguishes between a single mouse click and a beginni...
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:67
TOOL_MOUSE_BUTTONS button
The type of wxEvent that determines mouse button press.
bool handleMouseButton(wxEvent &aEvent, int aIndex, bool aMotion)
Saves the state of key modifiers (Alt, Ctrl and so on).
KIGFX::VIEW * getView()
Instance of tool manager that cooperates with the dispatcher.
TOOL_MANAGER * m_toolMgr