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-2020 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/optional.h>
42 #include <wx/stc/stc.h>
43 
46 {
47  BUTTON_STATE( TOOL_MOUSE_BUTTONS aButton, const wxEventType& aDownEvent,
48  const wxEventType& aUpEvent, const wxEventType& aDblClickEvent ) :
49  dragging( false ),
50  pressed( false ),
51  dragMaxDelta( 0.0f ),
52  button( aButton ),
53  downEvent( aDownEvent ),
54  upEvent( aUpEvent ),
55  dblClickEvent( aDblClickEvent )
56  {};
57 
59  bool dragging;
60 
62  bool pressed;
63 
66 
69 
72  double dragMaxDelta;
73 
76 
78  wxEventType downEvent;
79 
81  wxEventType upEvent;
82 
84  wxEventType dblClickEvent;
85 
87  wxLongLong downTimestamp;
88 
90  void Reset()
91  {
92  dragging = false;
93  pressed = false;
94  }
95 
97  bool GetState() const
98  {
99  wxMouseState mouseState = wxGetMouseState();
100 
101  switch( button )
102  {
103  case BUT_LEFT:
104  return mouseState.LeftIsDown();
105 
106  case BUT_MIDDLE:
107  return mouseState.MiddleIsDown();
108 
109  case BUT_RIGHT:
110  return mouseState.RightIsDown();
111 
112  default:
113  assert( false );
114  break;
115  }
116 
117  return false;
118  }
119 };
120 
121 
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 }
135 
136 
138 {
139  for( BUTTON_STATE* st : m_buttons )
140  delete st;
141 }
142 
143 
145 {
146  for( BUTTON_STATE* st : m_buttons )
147  st->Reset();
148 }
149 
150 
152 {
153  return m_toolMgr->GetView();
154 }
155 
156 
157 bool TOOL_DISPATCHER::handleMouseButton( wxEvent& aEvent, int aIndex, bool aMotion )
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
190 
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 &&
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 =
229  st->dragMaxDelta = std::max( st->dragMaxDelta, dragPixelDistance );
230 
231  wxLongLong t = wxGetLocalTimeMillis();
232 
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 }
251 
252 // Helper function to know if a special key ( see key list ) should be captured
253 // or if the event can be skipped
254 // on Linux, the event must be passed to the GUI if they are not used by KiCad,
255 // especially the wxEVENT_CHAR_HOOK, if it is not handled
256 // Some keys have a predefined action in wxWidgets so, even if not used,
257 // the even will be not skipped
258 // the unused keys listed in isKeySpecialCode() will be not skipped
259 bool isKeySpecialCode( int aKeyCode )
260 {
261  // These keys have predefined actions (like move thumbtrack cursor),
262  // and we do not want these actions executed
263  const enum wxKeyCode special_keys[] =
264  {
265  WXK_PAGEUP, WXK_PAGEDOWN,
266  WXK_NUMPAD_PAGEUP, WXK_NUMPAD_PAGEDOWN
267  };
268 
269  bool isInList = false;
270 
271  for( unsigned ii = 0; ii < arrayDim( special_keys ) && !isInList; ii++ )
272  {
273  if( special_keys[ii] == aKeyCode )
274  isInList = true;
275  }
276 
277  return isInList;
278 }
279 
280 // Helper function to know if a key should be managed by DispatchWxEvent()
281 // or if the event can be ignored and skipped because the key is only a modifier
282 // that is not used alone in kicad
283 static bool isKeyModifierOnly( int aKeyCode )
284 {
285  const enum wxKeyCode special_keys[] =
286  {
287  WXK_CONTROL, WXK_RAW_CONTROL, WXK_SHIFT,WXK_ALT
288  };
289 
290  bool isInList = false;
291 
292  for( unsigned ii = 0; ii < arrayDim( special_keys ) && !isInList; ii++ )
293  {
294  if( special_keys[ii] == aKeyCode )
295  isInList = true;
296  }
297 
298  return isInList;
299 }
300 
301 /* A helper class that convert some special key codes to an equivalent.
302  * WXK_NUMPAD_UP to WXK_UP,
303  * WXK_NUMPAD_DOWN to WXK_DOWN,
304  * WXK_NUMPAD_LEFT to WXK_LEFT,
305  * WXK_NUMPAD_RIGHT,
306  * WXK_NUMPAD_PAGEUP,
307  * WXK_NUMPAD_PAGEDOWN
308  * note:
309  * wxEVT_CHAR_HOOK does this conversion when it is skipped by firing a wxEVT_CHAR
310  * with this converted code, but we do not skip these key events because they also
311  * have default action (scroll the panel)
312  */
313 int translateSpecialCode( int aKeyCode )
314 {
315  switch( aKeyCode )
316  {
317  case WXK_NUMPAD_UP: return WXK_UP;
318  case WXK_NUMPAD_DOWN: return WXK_DOWN;
319  case WXK_NUMPAD_LEFT: return WXK_LEFT;
320  case WXK_NUMPAD_RIGHT: return WXK_RIGHT;
321  case WXK_NUMPAD_PAGEUP: return WXK_PAGEUP;
322  case WXK_NUMPAD_PAGEDOWN: return WXK_PAGEDOWN;
323  default: break;
324  };
325 
326  return aKeyCode;
327 }
328 
329 
330 OPT<TOOL_EVENT> TOOL_DISPATCHER::GetToolEvent( wxKeyEvent* aKeyEvent, bool* keyIsSpecial )
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 }
408 
409 
410 void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
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 }
603 
604 
605 void TOOL_DISPATCHER::DispatchWxCommand( wxCommandEvent& aEvent )
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 }
VECTOR2D downPosition
Point where click event has occurred.
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:289
static int decodeModifiers(const wxKeyboardState *aState)
Saves the state of key modifiers (Alt, Ctrl and so on).
ACTIONS * m_actions
Instance of an actions list that handles legacy action translation
double dragMaxDelta
Difference between drag origin point and current mouse position (expressed as distance in pixels).
BUTTON_STATE(TOOL_MOUSE_BUTTONS aButton, const wxEventType &aDownEvent, const wxEventType &aUpEvent, const wxEventType &aDblClickEvent)
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 OPT< TOOL_EVENT > TranslateLegacyId(int aId)=0
Function TranslateLegacyId() Translates legacy tool ids to the corresponding TOOL_ACTION name.
int translateSpecialCode(int aKeyCode)
static bool isKeyModifierOnly(int aKeyCode)
static const int DragDistanceThreshold
The distance threshold for mouse cursor that disinguishes between a single mouse click and a beginnin...
virtual ~TOOL_DISPATCHER()
virtual void ResetState()
Brings the dispatcher to its initial state.
bool dragging
Flag indicating that dragging is active for the given button.
VECTOR2D dragOrigin
Point where dragging has started (in world coordinates).
TOOL_DISPATCHER(TOOL_MANAGER *aToolMgr, ACTIONS *aActions)
WX_VIEW_CONTROLS class definition.
void Reset()
Restores initial state.
This file contains miscellaneous commonly used macros and functions.
TOOL_MANAGER.
Definition: tool_manager.h:51
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
The type of wxEvent that determines mouse button double click.
wxEventType downEvent
The type of wxEvent that determines mouse button press.
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagates an event to tools that requested events of matching type(s).
virtual void DispatchWxEvent(wxEvent &aEvent)
Processes wxEvents (mostly UI events), translates them to TOOL_EVENTs, and makes tools handle those.
bool isKeySpecialCode(int aKeyCode)
TOOL_EVENT.
Definition: tool_event.h:171
bool GetState() const
Checks the current state of the button.
wxLogTrace helper definitions.
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.
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Definition: macros.h:160
void OnMenuEvent(wxMenuEvent &aEvent)
TOOL_MOUSE_BUTTONS
Definition: tool_event.h:124
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.
virtual void DispatchWxCommand(wxCommandEvent &aEvent)
Processes wxCommands (mostly menu related events) and runs appropriate actions (eg.
bool pressed
Flag indicating that the given button is pressed.
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
ACTIONS.
Definition: actions.h:43
wxEventType upEvent
The type of wxEvent that determines mouse button release.
T EuclideanNorm() const
Destructor.
Definition: vector2d.h:299
wxLongLong downTimestamp
Time stamp for the last mouse button press event.
static const int DragTimeThreshold
The time threshold for a mouse button press that distinguishes between a single mouse click and a beg...
VIEW.
Definition: view.h:61
TOOL_MOUSE_BUTTONS button
Determines the mouse button for which information are stored.
bool handleMouseButton(wxEvent &aEvent, int aIndex, bool aMotion)
Handles mouse related events (click, motion, dragging).
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.