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 <[email protected]>
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 <ignore.h>
27 #include <macros.h>
28 #include <trace_helpers.h>
29 
30 #include <tool/tool_manager.h>
31 #include <tool/tools_holder.h>
32 #include <tool/tool_dispatcher.h>
33 #include <tool/actions.h>
34 #include <tool/action_manager.h>
35 #include <tool/action_menu.h>
36 #include <view/view.h>
37 #include <view/wx_view_controls.h>
38 
39 #include <class_draw_panel_gal.h>
40 #include <eda_draw_frame.h>
41 
42 #include <core/arraydim.h>
43 #include <core/optional.h>
44 #include <wx/log.h>
45 #include <wx/stc/stc.h>
46 #include <wx/settings.h>
47 #include <kiplatform/app.h>
48 #include <kiplatform/ui.h>
49 
52 {
53  BUTTON_STATE( TOOL_MOUSE_BUTTONS aButton, const wxEventType& aDownEvent,
54  const wxEventType& aUpEvent, const wxEventType& aDblClickEvent ) :
55  dragging( false ),
56  pressed( false ),
57  button( aButton ),
58  downEvent( aDownEvent ),
59  upEvent( aUpEvent ),
60  dblClickEvent( aDblClickEvent )
61  {};
62 
64  bool dragging;
65 
67  bool pressed;
68 
71 
74 
77 
80 
82  wxEventType downEvent;
83 
85  wxEventType upEvent;
86 
88  wxEventType dblClickEvent;
89 
91  wxLongLong downTimestamp;
92 
94  void Reset()
95  {
96  dragging = false;
97  pressed = false;
98  }
99 
101  bool GetState() const
102  {
103  wxMouseState mouseState = wxGetMouseState();
104 
105  switch( button )
106  {
107  case BUT_LEFT:
108  return mouseState.LeftIsDown();
109 
110  case BUT_MIDDLE:
111  return mouseState.MiddleIsDown();
112 
113  case BUT_RIGHT:
114  return mouseState.RightIsDown();
115 
116  default:
117  assert( false );
118  break;
119  }
120 
121  return false;
122  }
123 };
124 
125 
127  m_toolMgr( aToolMgr )
128 {
129  m_sysDragMinX = wxSystemSettings::GetMetric( wxSYS_DRAG_X );
130  m_sysDragMinY = wxSystemSettings::GetMetric( wxSYS_DRAG_Y );
131 
134 
135  m_buttons.push_back( new BUTTON_STATE( BUT_LEFT, wxEVT_LEFT_DOWN,
136  wxEVT_LEFT_UP, wxEVT_LEFT_DCLICK ) );
137  m_buttons.push_back( new BUTTON_STATE( BUT_RIGHT, wxEVT_RIGHT_DOWN,
138  wxEVT_RIGHT_UP, wxEVT_RIGHT_DCLICK ) );
139  m_buttons.push_back( new BUTTON_STATE( BUT_MIDDLE, wxEVT_MIDDLE_DOWN,
140  wxEVT_MIDDLE_UP, wxEVT_MIDDLE_DCLICK ) );
141 
142  ResetState();
143 }
144 
145 
147 {
148  for( BUTTON_STATE* st : m_buttons )
149  delete st;
150 }
151 
152 
154 {
155  for( BUTTON_STATE* st : m_buttons )
156  st->Reset();
157 }
158 
159 
161 {
162  return m_toolMgr->GetView();
163 }
164 
165 
166 bool TOOL_DISPATCHER::handleMouseButton( wxEvent& aEvent, int aIndex, bool aMotion )
167 {
168  BUTTON_STATE* st = m_buttons[aIndex];
169  wxEventType type = aEvent.GetEventType();
170  OPT<TOOL_EVENT> evt;
171  bool isClick = false;
172 
173 // bool up = type == st->upEvent;
174 // bool down = type == st->downEvent;
175  bool up = false, down = false;
176  bool dblClick = type == st->dblClickEvent;
177  bool state = st->GetState();
178 
179  if( !dblClick )
180  {
181  // Sometimes the dispatcher does not receive mouse button up event, so it stays
182  // in the dragging mode even if the mouse button is not held anymore
183  if( st->pressed && !state )
184  up = true;
185  // Don't apply same logic to down events as it kills touchpad tapping
186  else if( !st->pressed && type == st->downEvent )
187  down = true;
188  }
189 
190  int mods = decodeModifiers( static_cast<wxMouseEvent*>( &aEvent ) );
191  int args = st->button | mods;
192 
193  if( down ) // Handle mouse button press
194  {
195  st->downTimestamp = wxGetLocalTimeMillis();
196 
197  if( !st->pressed ) // save the drag origin on the first click only
198  {
201  }
202 
204  st->pressed = true;
205  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DOWN, args );
206  }
207  else if( up ) // Handle mouse button release
208  {
209  st->pressed = false;
210 
211  if( st->dragging )
212  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_UP, args );
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  if( !st->dragging )
229  {
230 #ifdef __WXMAC__
231  if( wxGetLocalTimeMillis() - st->downTimestamp > DragTimeThreshold )
232  st->dragging = true;
233 #endif
235 
236  if( abs( offset.x ) > m_sysDragMinX || abs( offset.y ) > m_sysDragMinY )
237  st->dragging = true;
238 
239  }
240 
241  if( st->dragging )
242  {
243  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_DRAG, args );
244  evt->setMouseDragOrigin( st->dragOrigin );
245  evt->setMouseDelta( m_lastMousePos - st->dragOrigin );
246  }
247  }
248 
249  if( evt )
250  {
251  evt->SetMousePosition( isClick ? st->downPosition : m_lastMousePos );
252  m_toolMgr->ProcessEvent( *evt );
253 
254  return true;
255  }
256 
257  return false;
258 }
259 
260 
261 // Helper function to know if a special key ( see key list ) should be captured
262 // or if the event can be skipped
263 // on Linux, the event must be passed to the GUI if they are not used by KiCad,
264 // especially the wxEVENT_CHAR_HOOK, if it is not handled
265 // Some keys have a predefined action in wxWidgets so, even if not used,
266 // the even will be not skipped
267 // the unused keys listed in isKeySpecialCode() will be not skipped
268 bool isKeySpecialCode( int aKeyCode )
269 {
270  // These keys have predefined actions (like move thumbtrack cursor),
271  // and we do not want these actions executed
272  const enum wxKeyCode special_keys[] =
273  {
274  WXK_PAGEUP, WXK_PAGEDOWN,
275  WXK_NUMPAD_PAGEUP, WXK_NUMPAD_PAGEDOWN
276  };
277 
278  bool isInList = false;
279 
280  for( unsigned ii = 0; ii < arrayDim( special_keys ) && !isInList; ii++ )
281  {
282  if( special_keys[ii] == aKeyCode )
283  isInList = true;
284  }
285 
286  return isInList;
287 }
288 
289 
290 // Helper function to know if a key should be managed by DispatchWxEvent()
291 // or if the event can be ignored and skipped because the key is only a modifier
292 // that is not used alone in kicad
293 static bool isKeyModifierOnly( int aKeyCode )
294 {
295  const enum wxKeyCode special_keys[] =
296  {
297  WXK_CONTROL, WXK_RAW_CONTROL, WXK_SHIFT,WXK_ALT
298  };
299 
300  bool isInList = false;
301 
302  for( unsigned ii = 0; ii < arrayDim( special_keys ) && !isInList; ii++ )
303  {
304  if( special_keys[ii] == aKeyCode )
305  isInList = true;
306  }
307 
308  return isInList;
309 }
310 
311 
312 static bool isMouseClick( wxEventType type )
313 {
314  return type == wxEVT_LEFT_DOWN || type == wxEVT_LEFT_UP || type == wxEVT_MIDDLE_DOWN
315  || type == wxEVT_MIDDLE_UP || type == wxEVT_RIGHT_DOWN || type == wxEVT_RIGHT_UP
316  || type == wxEVT_LEFT_DCLICK || type == wxEVT_MIDDLE_DCLICK
317  || type == wxEVT_RIGHT_DCLICK;
318 }
319 
320 
321 /* A helper class that convert some special key codes to an equivalent.
322  * WXK_NUMPAD_UP to WXK_UP,
323  * WXK_NUMPAD_DOWN to WXK_DOWN,
324  * WXK_NUMPAD_LEFT to WXK_LEFT,
325  * WXK_NUMPAD_RIGHT,
326  * WXK_NUMPAD_PAGEUP,
327  * WXK_NUMPAD_PAGEDOWN
328  * note:
329  * wxEVT_CHAR_HOOK does this conversion when it is skipped by firing a wxEVT_CHAR
330  * with this converted code, but we do not skip these key events because they also
331  * have default action (scroll the panel)
332  */
333 int translateSpecialCode( int aKeyCode )
334 {
335  switch( aKeyCode )
336  {
337  case WXK_NUMPAD_UP: return WXK_UP;
338  case WXK_NUMPAD_DOWN: return WXK_DOWN;
339  case WXK_NUMPAD_LEFT: return WXK_LEFT;
340  case WXK_NUMPAD_RIGHT: return WXK_RIGHT;
341  case WXK_NUMPAD_PAGEUP: return WXK_PAGEUP;
342  case WXK_NUMPAD_PAGEDOWN: return WXK_PAGEDOWN;
343  default: break;
344  };
345 
346  return aKeyCode;
347 }
348 
349 
350 OPT<TOOL_EVENT> TOOL_DISPATCHER::GetToolEvent( wxKeyEvent* aKeyEvent, bool* keyIsSpecial )
351 {
352  OPT<TOOL_EVENT> evt;
353  int key = aKeyEvent->GetKeyCode();
354  int unicode_key = aKeyEvent->GetUnicodeKey();
355 
356  // This wxEVT_CHAR_HOOK event can be ignored: not useful in Kicad
357  if( isKeyModifierOnly( key ) )
358  {
359  aKeyEvent->Skip();
360  return evt;
361  }
362 
363  wxLogTrace( kicadTraceKeyEvent, "TOOL_DISPATCHER::GetToolEvent %s", dump( *aKeyEvent ) );
364 
365  // if the key event must be skipped, skip it here if the event is a wxEVT_CHAR_HOOK
366  // and do nothing.
367  *keyIsSpecial = isKeySpecialCode( key );
368 
369  if( aKeyEvent->GetEventType() == wxEVT_CHAR_HOOK )
370  key = translateSpecialCode( key );
371 
372  int mods = decodeModifiers( aKeyEvent );
373 
374  if( mods & MD_CTRL )
375  {
376  // wxWidgets maps key codes related to Ctrl+letter handled by CHAR_EVT
377  // (http://docs.wxwidgets.org/trunk/classwx_key_event.html):
378  // char events for ASCII letters in this case carry codes corresponding to the ASCII
379  // value of Ctrl-Latter, i.e. 1 for Ctrl-A, 2 for Ctrl-B and so on until 26 for Ctrl-Z.
380  // They are remapped here to be more easy to handle in code
381  // Note also on OSX wxWidgets has a different behavior and the mapping is made
382  // only for ctrl+'A' to ctlr+'Z' (unicode code return 'A' to 'Z').
383  // Others OS return WXK_CONTROL_A to WXK_CONTROL_Z, and Ctrl+'M' returns the same code as
384  // the return key, so the remapping does not use the unicode key value.
385 #ifdef __APPLE__
386  if( unicode_key >= 'A' && unicode_key <= 'Z' && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
387 #else
388  ignore_unused( unicode_key );
389 
390  if( key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
391 #endif
392  key += 'A' - 1;
393  }
394 
395 #ifdef __APPLE__
396  if( mods & MD_ALT )
397  {
398  // OSX maps a bunch of commonly used extended-ASCII characters onto the keyboard
399  // using the ALT key. Since we use ALT for some of our hotkeys, we need to map back
400  // to the underlying keys. The kVK_ANSI_* values come from Apple and are said to be
401  // hardware independent.
402  switch( aKeyEvent->GetRawKeyCode() )
403  {
404  case /* kVK_ANSI_1 */ 0x12: key = '1'; break;
405  case /* kVK_ANSI_2 */ 0x13: key = '2'; break;
406  case /* kVK_ANSI_3 */ 0x14: key = '3'; break;
407  case /* kVK_ANSI_4 */ 0x15: key = '4'; break;
408  case /* kVK_ANSI_6 */ 0x16: key = '6'; break;
409  case /* kVK_ANSI_5 */ 0x17: key = '5'; break;
410  case /* kVK_ANSI_Equal */ 0x18: key = '='; break;
411  case /* kVK_ANSI_9 */ 0x19: key = '9'; break;
412  case /* kVK_ANSI_7 */ 0x1A: key = '7'; break;
413  case /* kVK_ANSI_Minus */ 0x1B: key = '-'; break;
414  case /* kVK_ANSI_8 */ 0x1C: key = '8'; break;
415  case /* kVK_ANSI_0 */ 0x1D: key = '0'; break;
416  default: ;
417  }
418  }
419 #endif
420 
421  if( key == WXK_ESCAPE ) // ESC is the special key for canceling tools
423  else
424  evt = TOOL_EVENT( TC_KEYBOARD, TA_KEY_PRESSED, key | mods );
425 
426  return evt;
427 }
428 
429 
430 void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
431 {
432  bool motion = false;
433  bool buttonEvents = false;
434  VECTOR2D pos;
435  OPT<TOOL_EVENT> evt;
436  bool keyIsEscape = false; // True if the keypress was the escape key
437  bool keyIsSpecial = false; // True if the key is a special key code
438  wxWindow* focus = wxWindow::FindFocus();
439 
440  // Required in win32 to ensure wxTimer events get scheduled in between other events
441  // Or else we may stall them out entirely and never get them during actions like rapid
442  // mouse moves.
444 
445  wxEventType type = aEvent.GetEventType();
446 
447  // Sometimes there is no window that has the focus (it happens when another PCB_BASE_FRAME
448  // is opened and is iconized on Windows).
449  // In this case, give the focus to the parent frame (GAL canvas itself does not accept the
450  // focus when iconized for some obscure reason)
451  if( focus == nullptr )
452  {
453  wxWindow* holderWindow = dynamic_cast<wxWindow*>( m_toolMgr->GetToolHolder() );
454 
455 #if defined( _WIN32 )
456  // Mouse events may trigger regardless of window status (windows feature)
457  // However we need to avoid focus fighting (especially modals)
458  if( holderWindow && KIPLATFORM::UI::IsWindowActive( holderWindow ) )
459 #else
460  if( holderWindow )
461 #endif
462  {
463  holderWindow->SetFocus();
464  }
465  }
466 
467  if( isMouseClick( type ) )
468  {
470  m_toolMgr->GetToolHolder()->GetToolCanvas()->SetFocus();
471  }
472 
473  // Mouse handling
474  // Note: wxEVT_LEFT_DOWN event must always be skipped.
475  if( type == wxEVT_MOTION || type == wxEVT_MOUSEWHEEL ||
476 #if wxCHECK_VERSION( 3, 1, 0 ) || defined( USE_OSX_MAGNIFY_EVENT )
477  type == wxEVT_MAGNIFY ||
478 #endif
479  isMouseClick( type ) ||
480  // Event issued when mouse retains position in screen coordinates,
481  // but changes in world coordinates (e.g. autopanning)
483  {
484  wxMouseEvent* me = static_cast<wxMouseEvent*>( &aEvent );
485  int mods = decodeModifiers( me );
486 
487  if( m_toolMgr->GetViewControls() )
488  {
491 
492  if( pos != m_lastMousePos )
493  {
494  motion = true;
495  m_lastMousePos = pos;
496  }
497  }
498 
499  for( unsigned int i = 0; i < m_buttons.size(); i++ )
500  buttonEvents |= handleMouseButton( aEvent, i, motion );
501 
502  if( m_toolMgr->GetViewControls() )
503  {
504  if( !buttonEvents && motion )
505  {
506  evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_MOTION, mods );
507  evt->SetMousePosition( pos );
508  }
509  }
510  }
511  else if( type == wxEVT_CHAR_HOOK || type == wxEVT_CHAR )
512  {
513  wxKeyEvent* ke = static_cast<wxKeyEvent*>( &aEvent );
514 
515  wxLogTrace( kicadTraceKeyEvent, "TOOL_DISPATCHER::DispatchWxEvent %s", dump( *ke ) );
516 
517  // Do not process wxEVT_CHAR_HOOK for a shift-modified key, as ACTION_MANAGER::RunHotKey
518  // will run the un-shifted key and that's not what we want. Wait to get the translated
519  // key from wxEVT_CHAR.
520  // See https://gitlab.com/kicad/code/kicad/-/issues/1809
521  if( type == wxEVT_CHAR_HOOK && ke->GetModifiers() == wxMOD_SHIFT )
522  {
523  aEvent.Skip();
524  return;
525  }
526 
527  keyIsEscape = ( ke->GetKeyCode() == WXK_ESCAPE );
528 
529  if( KIUI::IsInputControlFocused( focus ) )
530  {
531  bool enabled = KIUI::IsInputControlEditable( focus );
532 
533  // Never process key events for tools when a text entry has focus
534  if( enabled )
535  {
536  aEvent.Skip();
537  return;
538  }
539  // Even if not enabled, allow a copy out
540  else if( ke->GetModifiers() == wxMOD_CONTROL && ke->GetKeyCode() == 'C' )
541  {
542  aEvent.Skip();
543  return;
544  }
545  }
546 
547  evt = GetToolEvent( ke, &keyIsSpecial );
548  }
549  else if( type == wxEVT_MENU_OPEN || type == wxEVT_MENU_CLOSE || type == wxEVT_MENU_HIGHLIGHT )
550  {
551  //
552  // wxWidgets has several issues that we have to work around:
553  //
554  // 1) wxWidgets 3.0.x Windows has a bug where wxEVT_MENU_OPEN and wxEVT_MENU_HIGHLIGHT
555  // events are not captured by the ACTON_MENU menus. So we forward them here.
556  // (FWIW, this one is fixed in wxWidgets 3.1.x.)
557  //
558  // 2) wxWidgets doesn't pass the menu pointer for wxEVT_MENU_HIGHLIGHT events. So we
559  // store the menu pointer from the wxEVT_MENU_OPEN call.
560  //
561  // 3) wxWidgets has no way to tell whether a command is from a menu selection or a
562  // hotkey. So we keep track of menu highlighting so we can differentiate.
563  //
564 
565  static ACTION_MENU* currentMenu;
566 
567  wxMenuEvent& menuEvent = *dynamic_cast<wxMenuEvent*>( &aEvent );
568 
569  if( type == wxEVT_MENU_OPEN )
570  {
571  currentMenu = dynamic_cast<ACTION_MENU*>( menuEvent.GetMenu() );
572 
573  if( currentMenu )
574  currentMenu->OnMenuEvent( menuEvent );
575  }
576  else if( type == wxEVT_MENU_HIGHLIGHT )
577  {
578  if( currentMenu )
579  currentMenu->OnMenuEvent( menuEvent );
580  }
581  else if( type == wxEVT_MENU_CLOSE )
582  {
583  if( currentMenu )
584  currentMenu->OnMenuEvent( menuEvent );
585 
586  currentMenu = nullptr;
587  }
588 
589  aEvent.Skip();
590  }
591 
592  bool handled = false;
593 
594  if( evt )
595  {
596  wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxEvent %s", evt->Format() );
597 
598  handled = m_toolMgr->ProcessEvent( *evt );
599 
600  wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxEvent - Handled: %s %s",
601  ( handled ? "true" : "false" ), evt->Format() );
602  }
603 
604  // pass the event to the GUI, it might still be interested in it
605  // Note wxEVT_CHAR_HOOK event is already skipped for special keys not used by KiCad
606  // and wxEVT_LEFT_DOWN must be always Skipped.
607  //
608  // On OS X, key events are always meant to be caught. An uncaught key event is assumed
609  // to be a user input error by OS X (as they are pressing keys in a context where nothing
610  // is there to catch the event). This annoyingly makes OS X beep and/or flash the screen
611  // in Pcbnew and the footprint editor any time a hotkey is used. The correct procedure is
612  // to NOT pass wxEVT_CHAR events to the GUI under OS X.
613  //
614  // On Windows, avoid to call wxEvent::Skip for special keys because some keys
615  // (PAGE_UP, PAGE_DOWN) have predefined actions (like move thumbtrack cursor), and we do
616  // not want these actions executed (most are handled by KiCad)
617 
618  if( !evt || type == wxEVT_LEFT_DOWN )
619  aEvent.Skip();
620 
621  // Not handled wxEVT_CHAR must be Skipped (sent to GUI).
622  // Otherwise accelerators and shortcuts in main menu or toolbars are not seen.
623  // Escape key presses are never skipped by the handler since they correspond to tool cancel
624  // events, and if they aren't skipped then they are propagated to other frames (which we
625  // don't want).
626  if( (type == wxEVT_CHAR || type == wxEVT_CHAR_HOOK)
627  && !keyIsSpecial
628  && !handled
629  && !keyIsEscape )
630  aEvent.Skip();
631 
632  wxLogTrace( kicadTraceToolStack, "TOOL_DISPATCHER::DispatchWxEvent - Wx event skipped: %s",
633  ( aEvent.GetSkipped() ? "true" : "false" ) );
634 }
VECTOR2D downPosition
Determines the mouse button for which information are stored.
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:283
static int decodeModifiers(const wxKeyboardState *aState)
Stores all the information regarding a mouse button state.
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.
bool IsInputControlEditable(wxWindow *aControl)
Check if a input control has focus.
Definition: ui_common.cpp:253
static const wxEventType EVT_REFRESH_MOUSE
Defines the structure of a menu based on ACTIONs.
Definition: action_menu.h:48
int translateSpecialCode(int aKeyCode)
static bool isKeyModifierOnly(int aKeyCode)
static const int DragDistanceThreshold
Mininum distance before drag is activated in the X axis.
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 dragging has started (in screen coordinates).
VECTOR2D m_lastMousePosScreen
State of mouse buttons.
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:54
bool IsInputControlFocused(wxWindow *aFocus=nullptr)
Check if a input control has focus.
Definition: ui_common.cpp:220
< Stores information about a mouse button state
bool IsWindowActive(wxWindow *aWindow)
Check to see if the given window is the currently active window (e.g.
Definition: gtk/ui.cpp:50
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:88
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:152
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 dragOriginScreen
Point where click event has occurred.
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:123
TOOLS_HOLDER * GetToolHolder() const
Definition: tool_manager.h:294
int m_sysDragMinX
Maximum distance before drag is activated in the Y axis.
KIGFX::VIEW_CONTROLS * GetViewControls() const
Definition: tool_manager.h:285
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.
void ignore_unused(const T &)
Definition: ignore.h:24
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.
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:68
TOOL_MOUSE_BUTTONS button
The type of wxEvent that determines mouse button press.
int m_sysDragMinY
Handles mouse related events (click, motion, dragging).
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