KiCad PCB EDA Suite
Loading...
Searching...
No Matches
wx_view_controls.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) 2012 Torsten Hueter, torstenhtr <at> gmx.de
5 * Copyright (C) 2013-2015 CERN
6 * Copyright (C) 2012-2024 KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * @author Tomasz Wlostowski <[email protected]>
9 * @author Maciej Suminski <[email protected]>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, you may find one here:
23 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
24 * or you may search the http://www.gnu.org website for the version 2 license,
25 * or you may write to the Free Software Foundation, Inc.,
26 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
27 */
28
29#include <pgm_base.h>
30#include <core/profile.h>
31#include <view/view.h>
36#include <trace_helpers.h>
38#include <math/util.h> // for KiROUND
40#include <widgets/ui_common.h>
42#include <eda_draw_frame.h>
43#include <kiway.h>
44#include <kiplatform/ui.h>
45#include <wx/log.h>
46
47#ifdef __WXMSW__
48 #define USE_MOUSE_CAPTURE
49#endif
50
51using namespace KIGFX;
52
53const wxEventType WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE = wxNewEventType();
54
55
56static std::unique_ptr<ZOOM_CONTROLLER> GetZoomControllerForPlatform( bool aAcceleration )
57{
58#ifdef __WXMAC__
59 // On Apple pointer devices, wheel events occur frequently and with
60 // smaller rotation values. For those devices, let's handle zoom
61 // based on the rotation amount rather than the time difference.
62 return std::make_unique<CONSTANT_ZOOM_CONTROLLER>( CONSTANT_ZOOM_CONTROLLER::MAC_SCALE );
63#elif __WXGTK3__
64 // GTK3 is similar, but the scale constant is smaller
65 return std::make_unique<CONSTANT_ZOOM_CONTROLLER>( CONSTANT_ZOOM_CONTROLLER::GTK3_SCALE );
66#else
67 if( aAcceleration )
68 return std::make_unique<ACCELERATING_ZOOM_CONTROLLER>();
69 else
70 return std::make_unique<CONSTANT_ZOOM_CONTROLLER>( CONSTANT_ZOOM_CONTROLLER::MSW_SCALE );
71#endif
72}
73
74
76 VIEW_CONTROLS( aView ),
77 m_state( IDLE ),
78 m_parentPanel( aParentPanel ),
79 m_scrollScale( 1.0, 1.0 ),
80#ifdef __WXGTK3__
81 m_lastTimestamp( 0 ),
82#endif
83 m_cursorPos( 0, 0 ),
84 m_updateCursor( true ),
85 m_infinitePanWorks( false ),
86 m_gestureLastZoomFactor( 1.0 )
87{
89
90 m_MotionEventCounter = std::make_unique<PROF_COUNTER>( "Mouse motion events" );
91
92 m_parentPanel->Connect( wxEVT_MOTION,
93 wxMouseEventHandler( WX_VIEW_CONTROLS::onMotion ), nullptr, this );
94 m_parentPanel->Connect( wxEVT_MAGNIFY,
95 wxMouseEventHandler( WX_VIEW_CONTROLS::onMagnify ), nullptr, this );
96 m_parentPanel->Connect( wxEVT_MOUSEWHEEL,
97 wxMouseEventHandler( WX_VIEW_CONTROLS::onWheel ), nullptr, this );
98 m_parentPanel->Connect( wxEVT_MIDDLE_UP,
99 wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), nullptr, this );
100 m_parentPanel->Connect( wxEVT_MIDDLE_DOWN,
101 wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), nullptr, this );
102 m_parentPanel->Connect( wxEVT_LEFT_UP,
103 wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), nullptr, this );
104 m_parentPanel->Connect( wxEVT_LEFT_DOWN,
105 wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), nullptr, this );
106 m_parentPanel->Connect( wxEVT_RIGHT_UP,
107 wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), nullptr, this );
108 m_parentPanel->Connect( wxEVT_RIGHT_DOWN,
109 wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), nullptr, this );
110#if defined __WXMSW__
111 m_parentPanel->Connect( wxEVT_ENTER_WINDOW,
112 wxMouseEventHandler( WX_VIEW_CONTROLS::onEnter ), nullptr, this );
113#endif
114 m_parentPanel->Connect( wxEVT_LEAVE_WINDOW,
115 wxMouseEventHandler( WX_VIEW_CONTROLS::onLeave ), nullptr, this );
116 m_parentPanel->Connect( wxEVT_SCROLLWIN_THUMBTRACK,
117 wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), nullptr, this );
118 m_parentPanel->Connect( wxEVT_SCROLLWIN_PAGEUP,
119 wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), nullptr, this );
120 m_parentPanel->Connect( wxEVT_SCROLLWIN_PAGEDOWN,
121 wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), nullptr, this );
122
123 m_parentPanel->Connect( wxEVT_SCROLLWIN_BOTTOM,
124 wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), nullptr, this );
125 m_parentPanel->Connect( wxEVT_SCROLLWIN_TOP,
126 wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), nullptr, this );
127 m_parentPanel->Connect( wxEVT_SCROLLWIN_LINEUP,
128 wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), nullptr, this );
129 m_parentPanel->Connect( wxEVT_SCROLLWIN_LINEDOWN,
130 wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), nullptr, this );
131#if defined USE_MOUSE_CAPTURE
132 m_parentPanel->Connect( wxEVT_MOUSE_CAPTURE_LOST,
133 wxMouseEventHandler( WX_VIEW_CONTROLS::onCaptureLost ), nullptr, this );
134#endif
135
136#ifdef __WXMSW__
137 if( m_parentPanel->EnableTouchEvents( wxTOUCH_ZOOM_GESTURE | wxTOUCH_PAN_GESTURES ) )
138 {
139 m_parentPanel->Connect( wxEVT_GESTURE_ZOOM,
140 wxZoomGestureEventHandler( WX_VIEW_CONTROLS::onZoomGesture ),
141 nullptr, this );
142
143 m_parentPanel->Connect( wxEVT_GESTURE_PAN,
144 wxPanGestureEventHandler( WX_VIEW_CONTROLS::onPanGesture ), nullptr,
145 this );
146 }
147#endif
148
149 m_cursorWarped = false;
150
151 m_panTimer.SetOwner( this );
152 this->Connect( wxEVT_TIMER, wxTimerEventHandler( WX_VIEW_CONTROLS::onTimer ), nullptr, this );
153
157}
158
159
161{
162#if defined USE_MOUSE_CAPTURE
163 if( m_parentPanel->HasCapture() )
164 m_parentPanel->ReleaseMouse();
165#endif
166}
167
168
170{
172
189
190 m_zoomController.reset();
191
192 if( cfg->m_Input.zoom_speed_auto )
193 {
195 }
196 else
197 {
198 if( cfg->m_Input.zoom_acceleration )
199 {
201 std::make_unique<ACCELERATING_ZOOM_CONTROLLER>( cfg->m_Input.zoom_speed );
202 }
203 else
204 {
206
207 m_zoomController = std::make_unique<CONSTANT_ZOOM_CONTROLLER>( scale );
208 }
209 }
210}
211
212
213void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
214{
215 ( *m_MotionEventCounter )++;
216
217 // Because Weston sends a motion event to previous location after warping the pointer
218 wxPoint mouseRel = m_parentPanel->ScreenToClient( KIPLATFORM::UI::GetMousePosition() );
219
220 bool isAutoPanning = false;
221 int x = mouseRel.x;
222 int y = mouseRel.y;
223 VECTOR2D mousePos( x, y );
224
225 // Automatic focus switching between SCH and PCB windows on canvas mouse motion
227 {
229 {
230 KIWAY_PLAYER* otherFrame = nullptr;
231
232 if( frame->IsType( FRAME_PCB_EDITOR ) )
233 {
234 otherFrame = frame->Kiway().Player( FRAME_SCH, false );
235 }
236 else if( frame->IsType( FRAME_SCH ) )
237 {
238 otherFrame = frame->Kiway().Player( FRAME_PCB_EDITOR, false );
239 }
240
241 if( otherFrame && KIPLATFORM::UI::IsWindowActive( otherFrame )
242 && !KIPLATFORM::UI::IsWindowActive( frame ) )
243 {
244 frame->Raise();
245 }
246 }
247 }
248
250 handleCursorCapture( x, y );
251
253 isAutoPanning = handleAutoPanning( aEvent );
254
255 if( !isAutoPanning && aEvent.Dragging() )
256 {
257 if( m_state == DRAG_PANNING )
258 {
259 static bool justWarped = false;
260 int warpX = 0;
261 int warpY = 0;
262 wxSize parentSize = m_parentPanel->GetClientSize();
263
264 if( x < 0 )
265 {
266 warpX = parentSize.x;
267 }
268 else if(x >= parentSize.x )
269 {
270 warpX = -parentSize.x;
271 }
272
273 if( y < 0 )
274 {
275 warpY = parentSize.y;
276 }
277 else if( y >= parentSize.y )
278 {
279 warpY = -parentSize.y;
280 }
281
282 if( !justWarped )
283 {
284 VECTOR2D d = m_dragStartPoint - mousePos;
285 m_dragStartPoint = mousePos;
286 VECTOR2D delta = m_view->ToWorld( d, false );
288 aEvent.StopPropagation();
289 }
290
291 if( warpX || warpY )
292 {
293 if( !justWarped )
294 {
296 && KIPLATFORM::UI::WarpPointer( m_parentPanel, x + warpX, y + warpY ) )
297 {
298 m_dragStartPoint += VECTOR2D( warpX, warpY );
299 justWarped = true;
300 }
301 }
302 else
303 justWarped = false;
304 }
305 else
306 justWarped = false;
307 }
308 else if( m_state == DRAG_ZOOMING )
309 {
310 static bool justWarped = false;
311 int warpY = 0;
312 wxSize parentSize = m_parentPanel->GetClientSize();
313
314 if( y < 0 )
315 {
316 warpY = parentSize.y;
317 }
318 else if( y >= parentSize.y )
319 {
320 warpY = -parentSize.y;
321 }
322
323 if( !justWarped )
324 {
325 VECTOR2D d = m_dragStartPoint - mousePos;
326 m_dragStartPoint = mousePos;
327
328 double scale = exp( d.y * m_settings.m_zoomSpeed * 0.001 );
329
330 wxLogTrace( traceZoomScroll, wxString::Format( "dy: %f scale: %f", d.y, scale ) );
331
333 aEvent.StopPropagation();
334 }
335
336 if( warpY )
337 {
338 if( !justWarped )
339 {
341 m_dragStartPoint += VECTOR2D( 0, warpY );
342 justWarped = true;
343 }
344 else
345 justWarped = false;
346 }
347 else
348 justWarped = false;
349 }
350 }
351
352 if( m_updateCursor ) // do not update the cursor position if it was explicitly set
353 m_cursorPos = GetClampedCoords( m_view->ToWorld( mousePos ) );
354 else
355 m_updateCursor = true;
356
357 aEvent.Skip();
358}
359
360
361void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& aEvent )
362{
363#ifdef __WXGTK3__
364 if( aEvent.GetTimestamp() == m_lastTimestamp )
365 {
366 aEvent.Skip( false );
367 return;
368 }
369
370 m_lastTimestamp = aEvent.GetTimestamp();
371#endif
372
373 const double wheelPanSpeed = 0.001;
374 const int axis = aEvent.GetWheelAxis();
375
376 if( axis == wxMOUSE_WHEEL_HORIZONTAL && !m_settings.m_horizontalPan )
377 return;
378
379 // Pick the modifier, if any. Shift beats control beats alt, we don't support more than one.
380 int nMods = 0;
381 int modifiers = 0;
382 if( aEvent.ShiftDown() )
383 {
384 nMods += 1;
385 modifiers = WXK_SHIFT;
386 }
387 if( aEvent.ControlDown() )
388 {
389 nMods += 1;
390 modifiers = modifiers == 0 ? WXK_CONTROL : modifiers;
391 }
392 if( aEvent.AltDown() )
393 {
394 nMods += 1;
395 modifiers = modifiers == 0 ? WXK_ALT : modifiers;
396 }
397
398 // Zero or one modifier is view control
399 if( nMods <= 1 )
400 {
401 // Restrict zoom handling to the vertical axis, otherwise horizontal
402 // scrolling events (e.g. touchpads and some mice) end up interpreted
403 // as vertical scroll events and confuse the user.
404 if( modifiers == m_settings.m_scrollModifierZoom && axis == wxMOUSE_WHEEL_VERTICAL )
405 {
406 const int rotation =
407 aEvent.GetWheelRotation() * ( m_settings.m_scrollReverseZoom ? -1 : 1 );
408 const double zoomScale = m_zoomController->GetScaleForRotation( rotation );
409
411 {
413 m_view->SetScale( m_view->GetScale() * zoomScale );
414 }
415 else
416 {
417 const VECTOR2D anchor = m_view->ToWorld( VECTOR2D( aEvent.GetX(), aEvent.GetY() ) );
418 m_view->SetScale( m_view->GetScale() * zoomScale, anchor );
419 }
420
421 // Refresh the zoom level and mouse position on message panel
422 // (mouse position has not changed, only the zoom level has changed):
423 refreshMouse( true );
424 }
425 else
426 {
427 // Scrolling
428 VECTOR2D scrollVec = m_view->ToWorld( m_view->GetScreenPixelSize(), false )
429 * ( (double) aEvent.GetWheelRotation() * wheelPanSpeed );
430 double scrollX = 0.0;
431 double scrollY = 0.0;
432 bool hReverse = false;
433
434 if( axis != wxMOUSE_WHEEL_HORIZONTAL )
436
437 if( axis == wxMOUSE_WHEEL_HORIZONTAL || modifiers == m_settings.m_scrollModifierPanH )
438 {
439 if( hReverse )
440 scrollX = scrollVec.x;
441 else
442 scrollX = ( axis == wxMOUSE_WHEEL_HORIZONTAL ) ? scrollVec.x : -scrollVec.x;
443 }
444 else
445 {
446 scrollY = -scrollVec.y;
447 }
448
449 VECTOR2D delta( scrollX, scrollY );
450
452 refreshMouse( true );
453 }
454
455 // Do not skip this event, otherwise wxWidgets will fire
456 // 3 wxEVT_SCROLLWIN_LINEUP or wxEVT_SCROLLWIN_LINEDOWN (normal wxWidgets behavior)
457 // and we do not want that.
458 }
459 else
460 {
461 // When we have muliple mods, forward it for tool handling
462 aEvent.Skip();
463 }
464}
465
466
467void WX_VIEW_CONTROLS::onMagnify( wxMouseEvent& aEvent )
468{
469 // Scale based on the magnification from our underlying magnification event.
470 VECTOR2D anchor = m_view->ToWorld( VECTOR2D( aEvent.GetX(), aEvent.GetY() ) );
471 m_view->SetScale( m_view->GetScale() * ( aEvent.GetMagnification() + 1.0f ), anchor );
472
473 aEvent.Skip();
474}
475
476
478{
479 m_state = aNewState;
480}
481
482void WX_VIEW_CONTROLS::onButton( wxMouseEvent& aEvent )
483{
484 switch( m_state )
485 {
486 case IDLE:
487 case AUTO_PANNING:
488 if( ( aEvent.MiddleDown() && m_settings.m_dragMiddle == MOUSE_DRAG_ACTION::PAN ) ||
489 ( aEvent.RightDown() && m_settings.m_dragRight == MOUSE_DRAG_ACTION::PAN ) )
490 {
491 m_dragStartPoint = VECTOR2D( aEvent.GetX(), aEvent.GetY() );
494
495#if defined USE_MOUSE_CAPTURE
496 if( !m_parentPanel->HasCapture() )
497 m_parentPanel->CaptureMouse();
498#endif
499 }
500 else if( ( aEvent.MiddleDown() && m_settings.m_dragMiddle == MOUSE_DRAG_ACTION::ZOOM ) ||
501 ( aEvent.RightDown() && m_settings.m_dragRight == MOUSE_DRAG_ACTION::ZOOM ) )
502 {
503 m_dragStartPoint = VECTOR2D( aEvent.GetX(), aEvent.GetY() );
506
507#if defined USE_MOUSE_CAPTURE
508 if( !m_parentPanel->HasCapture() )
509 m_parentPanel->CaptureMouse();
510#endif
511 }
512
513 if( aEvent.LeftUp() )
514 setState( IDLE ); // Stop autopanning when user release left mouse button
515
516 break;
517
518 case DRAG_ZOOMING:
519 case DRAG_PANNING:
520 if( aEvent.MiddleUp() || aEvent.LeftUp() || aEvent.RightUp() )
521 {
522 setState( IDLE );
524
525#if defined USE_MOUSE_CAPTURE
526 if( !m_settings.m_cursorCaptured && m_parentPanel->HasCapture() )
527 m_parentPanel->ReleaseMouse();
528#endif
529 }
530
531 break;
532 }
533
534 aEvent.Skip();
535}
536
537
538void WX_VIEW_CONTROLS::onEnter( wxMouseEvent& aEvent )
539{
540 // Avoid stealing focus from text controls
541 // This is particularly important for users using On-Screen-Keyboards
542 // They may move the mouse over the canvas to reach the keyboard
544 {
545 return;
546 }
547
548#if defined( _WIN32 ) || defined( __WXGTK__ )
549 // Win32 and some *nix WMs transmit mouse move and wheel events to all controls below the mouse regardless
550 // of focus. Forcing the focus here will cause the EDA FRAMES to immediately become the
551 // top level active window.
552 if( m_parentPanel->GetParent() != nullptr )
553 {
554 // this assumes the parent panel's parent is the eda window
556 {
558 }
559 }
560#else
562#endif
563}
564
565
566void WX_VIEW_CONTROLS::onLeave( wxMouseEvent& aEvent )
567{
568#if !defined USE_MOUSE_CAPTURE
569 onMotion( aEvent );
570#endif
571}
572
573void WX_VIEW_CONTROLS::onCaptureLost( wxMouseEvent& aEvent )
574{
575 // This method must be present to suppress the capture-lost assertion
576
577 // Set the flag to allow calling m_parentPanel->CaptureMouse()
578 // Note: One cannot call m_parentPanel->CaptureMouse() twice, this is not accepted
579 // by wxWidgets (MSW specific) so we need this guard
581}
582
583
584void WX_VIEW_CONTROLS::onTimer( wxTimerEvent& aEvent )
585{
586 switch( m_state )
587 {
588 case AUTO_PANNING:
589 {
591 {
592 setState( IDLE );
593 return;
594 }
595
596 #ifdef __WXMSW__
597 // Hackfix: It's possible for the mouse to leave the canvas
598 // without triggering any leave events on windows
599 // Use a MSW only wx function
600 if( !m_parentPanel->IsMouseInWindow() )
601 {
602 m_panTimer.Stop();
603 setState( IDLE );
604 return;
605 }
606 #endif
607
608 if( !m_parentPanel->HasFocus() && !m_parentPanel->StatusPopupHasFocus() )
609 {
610 setState( IDLE );
611 return;
612 }
613
614 double borderSize = std::min( m_settings.m_autoPanMargin * m_view->GetScreenPixelSize().x,
616
617 // When the mouse cursor is outside the area with no pan,
618 // m_panDirection is the dist to this area limit ( in pixels )
619 // It will be used also as pan value (the pan speed depends on this dist).
621
622 // When the mouse cursor is outside the area with no pan, the pan value
623 // is accelerated depending on the dist between the area and the cursor
624 float accel = 0.5f + ( m_settings.m_autoPanAcceleration / 5.0f );
625
626 // For a small mouse cursor dist to area, just use the distance.
627 // But for a dist > borderSize / 2, use an accelerated pan value
628
629 if( dir.EuclideanNorm() >= borderSize ) // far from area limits
630 dir = dir.Resize( borderSize * accel );
631 else if( dir.EuclideanNorm() > borderSize / 2 ) // Near from area limits
632 dir = dir.Resize( borderSize );
633
634 dir = m_view->ToWorld( dir, false );
635 m_view->SetCenter( m_view->GetCenter() + dir );
636
637 refreshMouse( true );
638
639 m_panTimer.Start();
640 }
641 break;
642
643 case IDLE: // Just remove unnecessary warnings
644 case DRAG_PANNING:
645 case DRAG_ZOOMING:
646 break;
647 }
648}
649
650
651void WX_VIEW_CONTROLS::onZoomGesture( wxZoomGestureEvent& aEvent )
652{
653 if( aEvent.IsGestureStart() )
654 {
656 m_gestureLastPos = VECTOR2D( aEvent.GetPosition().x, aEvent.GetPosition().y );
657 }
658
659 VECTOR2D evtPos( aEvent.GetPosition().x, aEvent.GetPosition().y );
660 VECTOR2D deltaWorld = m_view->ToWorld( evtPos - m_gestureLastPos, false );
661
662 m_view->SetCenter( m_view->GetCenter() - deltaWorld );
663
664 m_view->SetScale( m_view->GetScale() * aEvent.GetZoomFactor() / m_gestureLastZoomFactor,
665 m_view->ToWorld( evtPos ) );
666
667 m_gestureLastZoomFactor = aEvent.GetZoomFactor();
668 m_gestureLastPos = evtPos;
669
670 refreshMouse( true );
671}
672
673
674void WX_VIEW_CONTROLS::onPanGesture( wxPanGestureEvent& aEvent )
675{
676 VECTOR2I screenDelta( aEvent.GetDelta().x, aEvent.GetDelta().y );
677 VECTOR2D deltaWorld = m_view->ToWorld( screenDelta, false );
678
679 m_view->SetCenter( m_view->GetCenter() - deltaWorld );
680
681 refreshMouse( true );
682}
683
684
685void WX_VIEW_CONTROLS::onScroll( wxScrollWinEvent& aEvent )
686{
687 const double linePanDelta = 0.05;
688 const double pagePanDelta = 0.5;
689
690 int type = aEvent.GetEventType();
691 int dir = aEvent.GetOrientation();
692
693 if( type == wxEVT_SCROLLWIN_THUMBTRACK )
694 {
695 auto center = m_view->GetCenter();
696 const auto& boundary = m_view->GetBoundary();
697
698 // Flip scroll direction in flipped view
699 const double xstart = ( m_view->IsMirroredX() ?
700 boundary.GetRight() : boundary.GetLeft() );
701 const double xdelta = ( m_view->IsMirroredX() ? -1 : 1 );
702
703 if( dir == wxHORIZONTAL )
704 center.x = xstart + xdelta * ( aEvent.GetPosition() / m_scrollScale.x );
705 else
706 center.y = boundary.GetTop() + aEvent.GetPosition() / m_scrollScale.y;
707
708 m_view->SetCenter( center );
709 }
710 else if( type == wxEVT_SCROLLWIN_THUMBRELEASE ||
711 type == wxEVT_SCROLLWIN_TOP ||
712 type == wxEVT_SCROLLWIN_BOTTOM )
713 {
714 // Do nothing on thumb release, we don't care about it.
715 // We don't have a concept of top or bottom in our viewport, so ignore those events.
716 }
717 else
718 {
719 double dist = 0;
720
721 if( type == wxEVT_SCROLLWIN_PAGEUP )
722 {
723 dist = pagePanDelta;
724 }
725 else if( type == wxEVT_SCROLLWIN_PAGEDOWN )
726 {
727 dist = -pagePanDelta;
728 }
729 else if( type == wxEVT_SCROLLWIN_LINEUP )
730 {
731 dist = linePanDelta;
732 }
733 else if( type == wxEVT_SCROLLWIN_LINEDOWN )
734 {
735 dist = -linePanDelta;
736 }
737 else
738 {
739 wxCHECK_MSG( false, /* void */, wxT( "Unhandled event type" ) );
740 }
741
742 VECTOR2D scroll = m_view->ToWorld( m_view->GetScreenPixelSize(), false ) * dist;
743
744 double scrollX = 0.0;
745 double scrollY = 0.0;
746
747 if ( dir == wxHORIZONTAL )
748 scrollX = -scroll.x;
749 else
750 scrollY = -scroll.y;
751
752 VECTOR2D delta( scrollX, scrollY );
753
755 }
756
758}
759
760
762{
763#if defined USE_MOUSE_CAPTURE
764 // Note: for some reason, m_parentPanel->HasCapture() can be false even if CaptureMouse()
765 // was called (i.e. mouse was captured, so when need to test m_MouseCapturedLost to be
766 // sure a wxEVT_MOUSE_CAPTURE_LOST event was fired before. Otherwise wxMSW complains
767 // The IsModalDialogFocused is checked because it's possible to start a capture
768 // due to event ordering while a modal dialog was just opened, the mouse capture steels focus
769 // from the modal and causes odd behavior
770 if( aEnabled && !m_parentPanel->HasCapture() && m_parentPanel->m_MouseCapturedLost
772 {
773 m_parentPanel->CaptureMouse();
774
775 // Clear the flag to allow calling m_parentPanel->CaptureMouse()
776 // Calling it without calling ReleaseMouse() is not accepted by wxWidgets (MSW specific)
778 }
779 else if( !aEnabled && m_parentPanel->HasCapture()
781 {
782 m_parentPanel->ReleaseMouse();
783
784 // Mouse is released, calling CaptureMouse() is allowed now:
786 }
787#endif
789}
790
791
793{
795 {
796 setState( IDLE );
797#if defined USE_MOUSE_CAPTURE
798 if( !m_settings.m_cursorCaptured && m_parentPanel->HasCapture() )
799 m_parentPanel->ReleaseMouse();
800#endif
801 }
802}
803
804
805VECTOR2D WX_VIEW_CONTROLS::GetMousePosition( bool aWorldCoordinates ) const
806{
807 wxPoint msp = getMouseScreenPosition();
808 VECTOR2D screenPos( msp.x, msp.y );
809
810 return aWorldCoordinates ? GetClampedCoords( m_view->ToWorld( screenPos ) ) : screenPos;
811}
812
813
815{
816 GAL* gal = m_view->GetGAL();
817
818 if( aEnableSnapping && gal->GetGridSnapping() )
819 {
820 return gal->GetGridPoint( m_cursorPos );
821 }
822 else
823 {
824 return m_cursorPos;
825 }
826}
827
828
830{
832 {
834 }
835 else
836 {
837 return GetClampedCoords( GetRawCursorPosition( aEnableSnapping ) );
838 }
839}
840
841
842void WX_VIEW_CONTROLS::SetCursorPosition( const VECTOR2D& aPosition, bool aWarpView,
843 bool aTriggeredByArrows, long aArrowCommand )
844{
845 m_updateCursor = false;
846
847 VECTOR2D clampedPosition = GetClampedCoords( aPosition );
848
849 if( aTriggeredByArrows )
850 {
854 m_cursorWarped = false;
855 }
856 else
857 {
861 m_cursorWarped = true;
862 }
863
864 WarpMouseCursor( clampedPosition, true, aWarpView );
865 m_cursorPos = clampedPosition;
866}
867
868
870 bool aWarpView = true )
871{
872 m_updateCursor = false;
873
874 VECTOR2D clampedPosition = GetClampedCoords( aPosition );
875
876 const VECTOR2I& screenSize = m_view->GetGAL()->GetScreenPixelSize();
877 BOX2I screen( VECTOR2I( 0, 0 ), screenSize );
878 VECTOR2D screenPos = m_view->ToScreen( clampedPosition );
879
880 if( aWarpView && !screen.Contains( screenPos ) )
881 m_view->SetCenter( clampedPosition );
882
883 m_cursorPos = clampedPosition;
884}
885
886
887void WX_VIEW_CONTROLS::WarpMouseCursor( const VECTOR2D& aPosition, bool aWorldCoordinates,
888 bool aWarpView )
889{
890 if( aWorldCoordinates )
891 {
892 const VECTOR2I& screenSize = m_view->GetGAL()->GetScreenPixelSize();
893 BOX2I screen( VECTOR2I( 0, 0 ), screenSize );
894 VECTOR2D clampedPosition = GetClampedCoords( aPosition );
895 VECTOR2D screenPos = m_view->ToScreen( clampedPosition );
896
897 if( !screen.Contains( screenPos ) )
898 {
899 if( aWarpView )
900 {
901 m_view->SetCenter( clampedPosition );
902 KIPLATFORM::UI::WarpPointer( m_parentPanel, screenSize.x / 2, screenSize.y / 2 );
903 }
904 }
905 else
906 {
907 KIPLATFORM::UI::WarpPointer( m_parentPanel, screenPos.x, screenPos.y );
908 }
909 }
910 else
911 {
912 KIPLATFORM::UI::WarpPointer( m_parentPanel, aPosition.x, aPosition.y );
913 }
914
915 // If we are not refreshing because of mouse movement, don't set the modifiers
916 // because we are refreshing for keyboard movement, which uses the same modifiers for other actions
918}
919
920
922{
923 const VECTOR2I& screenSize = m_view->GetGAL()->GetScreenPixelSize();
924 VECTOR2D screenCenter( screenSize / 2 );
925
926 if( GetMousePosition( false ) != screenCenter )
927 {
928 VECTOR2D newCenter = GetCursorPosition();
929
930 if( KIPLATFORM::UI::WarpPointer( m_parentPanel, screenCenter.x, screenCenter.y ) )
931 {
932 m_view->SetCenter( newCenter );
933 m_dragStartPoint = screenCenter;
934 }
935 }
936}
937
938
940{
941 int border = std::min( m_settings.m_autoPanMargin * m_view->GetScreenPixelSize().x,
943 border += 2;
944
945 VECTOR2D topLeft( border, border );
946 VECTOR2D botRight( m_view->GetScreenPixelSize().x - border,
947 m_view->GetScreenPixelSize().y - border );
948
949 topLeft = m_view->ToWorld( topLeft );
950 botRight = m_view->ToWorld( botRight );
951
952 VECTOR2D pos = GetMousePosition( true );
953
954 if( pos.x < topLeft.x )
955 pos.x = topLeft.x;
956 else if( pos.x > botRight.x )
957 pos.x = botRight.x;
958
959 if( pos.y < topLeft.y )
960 pos.y = topLeft.y;
961 else if( pos.y > botRight.y )
962 pos.y = botRight.y;
963
964 SetCursorPosition( pos, false, false, 0 );
965
966 if( aWarpMouseCursor )
967 WarpMouseCursor( pos, true );
968}
969
970
971bool WX_VIEW_CONTROLS::handleAutoPanning( const wxMouseEvent& aEvent )
972{
973 VECTOR2I p( aEvent.GetX(), aEvent.GetY() );
975
977 {
978 // last cursor move event came from keyboard cursor control. If auto-panning is enabled
979 // and the next position is inside the autopan zone, check if it really came from a mouse
980 // event, otherwise disable autopan temporarily. Also temporarily disable autopan if the
981 // cursor is in the autopan zone because the application warped the cursor.
982
983 m_cursorWarped = false;
984 return true;
985 }
986
987 m_cursorWarped = false;
988
989 // Compute areas where autopanning is active
990 int borderStart = std::min( m_settings.m_autoPanMargin * m_view->GetScreenPixelSize().x,
992 borderStart = std::max( borderStart, 2 );
993 int borderEndX = m_view->GetScreenPixelSize().x - borderStart;
994 int borderEndY = m_view->GetScreenPixelSize().y - borderStart;
995
996 if( p.x < borderStart )
997 m_panDirection.x = -( borderStart - p.x );
998 else if( p.x > borderEndX )
999 m_panDirection.x = ( p.x - borderEndX );
1000 else
1001 m_panDirection.x = 0;
1002
1003 if( p.y < borderStart )
1004 m_panDirection.y = -( borderStart - p.y );
1005 else if( p.y > borderEndY )
1006 m_panDirection.y = ( p.y - borderEndY );
1007 else
1008 m_panDirection.y = 0;
1009
1010 bool borderHit = ( m_panDirection.x != 0 || m_panDirection.y != 0 );
1011
1012 switch( m_state )
1013 {
1014 case AUTO_PANNING:
1015 if( !borderHit )
1016 {
1017 m_panTimer.Stop();
1018 setState( IDLE );
1019
1020 return false;
1021 }
1022
1023 return true;
1024
1025 case IDLE:
1026 if( borderHit )
1027 {
1029 m_panTimer.Start( (int) ( 250.0 / 60.0 ), true );
1030
1031 return true;
1032 }
1033
1034 return false;
1035
1036 case DRAG_PANNING:
1037 case DRAG_ZOOMING:
1038 return false;
1039 }
1040
1041 wxCHECK_MSG( false, false, wxT( "This line should never be reached" ) );
1042
1043 return false;
1044}
1045
1046
1048{
1050 {
1051 bool warp = false;
1052 wxSize parentSize = m_parentPanel->GetClientSize();
1053
1054 if( x < 0 )
1055 {
1056 x = 0;
1057 warp = true;
1058 }
1059 else if( x >= parentSize.x )
1060 {
1061 x = parentSize.x - 1;
1062 warp = true;
1063 }
1064
1065 if( y < 0 )
1066 {
1067 y = 0;
1068 warp = true;
1069 }
1070 else if( y >= parentSize.y )
1071 {
1072 y = parentSize.y - 1;
1073 warp = true;
1074 }
1075
1076 if( warp )
1078 }
1079}
1080
1081
1082void WX_VIEW_CONTROLS::refreshMouse( bool aSetModifiers )
1083{
1084 // Notify tools that the cursor position has changed in the world coordinates
1085 wxMouseEvent moveEvent( EVT_REFRESH_MOUSE );
1086 wxPoint msp = getMouseScreenPosition();
1087 moveEvent.SetX( msp.x );
1088 moveEvent.SetY( msp.y );
1089
1090 if( aSetModifiers )
1091 {
1092 // Set the modifiers state
1093 moveEvent.SetControlDown( wxGetKeyState( WXK_CONTROL ) );
1094 moveEvent.SetShiftDown( wxGetKeyState( WXK_SHIFT ) );
1095 moveEvent.SetAltDown( wxGetKeyState( WXK_ALT ) );
1096 }
1097
1098 m_cursorPos = GetClampedCoords( m_view->ToWorld( VECTOR2D( msp.x, msp.y ) ) );
1099 wxPostEvent( m_parentPanel, moveEvent );
1100}
1101
1102
1104{
1105 wxPoint msp = KIPLATFORM::UI::GetMousePosition();
1106 m_parentPanel->ScreenToClient( &msp.x, &msp.y );
1107 return msp;
1108}
1109
1110
1112{
1113 const BOX2D viewport = m_view->GetViewport();
1114 const BOX2D& boundary = m_view->GetBoundary();
1115
1116 m_scrollScale.x = 2e3 / viewport.GetWidth(); // TODO it does not have to be updated so often
1117 m_scrollScale.y = 2e3 / viewport.GetHeight();
1118 VECTOR2I newScroll( ( viewport.Centre().x - boundary.GetLeft() ) * m_scrollScale.x,
1119 ( viewport.Centre().y - boundary.GetTop() ) * m_scrollScale.y );
1120
1121 // We add the width of the scroll bar thumb to the range because the scroll range is given by
1122 // the full bar while the position is given by the left/top position of the thumb
1123 VECTOR2I newRange( m_scrollScale.x * boundary.GetWidth() +
1124 m_parentPanel->GetScrollThumb( wxSB_HORIZONTAL ),
1125 m_scrollScale.y * boundary.GetHeight() +
1126 m_parentPanel->GetScrollThumb( wxSB_VERTICAL ) );
1127
1128 // Flip scroll direction in flipped view
1129 if( m_view->IsMirroredX() )
1130 newScroll.x = ( boundary.GetRight() - viewport.Centre().x ) * m_scrollScale.x;
1131
1132 // Adjust scrollbars only if it is needed. Otherwise there are cases when canvas is continuously
1133 // refreshed (Windows)
1134 if( m_scrollPos != newScroll || newRange.x != m_parentPanel->GetScrollRange( wxSB_HORIZONTAL )
1135 || newRange.y != m_parentPanel->GetScrollRange( wxSB_VERTICAL ) )
1136 {
1137 m_parentPanel->SetScrollbars( 1, 1, newRange.x, newRange.y, newScroll.x, newScroll.y,
1138 true );
1139 m_scrollPos = newScroll;
1140
1141#if !defined( __APPLE__ ) && !defined( WIN32 )
1142 // Trigger a mouse refresh to get the canvas update in GTK (re-draws the scrollbars).
1143 // Note that this causes an infinite loop on OSX and Windows (in certain cases) as it
1144 // generates a paint event.
1145 refreshMouse( false );
1146#endif
1147 }
1148}
1149
1150void WX_VIEW_CONTROLS::ForceCursorPosition( bool aEnabled, const VECTOR2D& aPosition )
1151{
1152 VECTOR2D clampedPosition = GetClampedCoords( aPosition );
1153
1155 m_settings.m_forcedPosition = clampedPosition;
1156}
constexpr size_type GetWidth() const
Definition: box2.h:214
constexpr Vec Centre() const
Definition: box2.h:97
constexpr size_type GetHeight() const
Definition: box2.h:215
constexpr coord_type GetLeft() const
Definition: box2.h:228
constexpr bool Contains(const Vec &aPoint) const
Definition: box2.h:168
constexpr coord_type GetRight() const
Definition: box2.h:217
constexpr coord_type GetTop() const
Definition: box2.h:229
The base class for create windows for drawing purpose.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
bool m_MouseCapturedLost
used on wxMSW: true after a wxEVT_MOUSE_CAPTURE_LOST was received false after the mouse is recaptured...
void SetFocus() override
EDA_DRAW_FRAME * GetParentEDAFrame() const
Returns parent EDA_DRAW_FRAME, if available or NULL otherwise.
static constexpr double MAC_SCALE
static constexpr double MSW_SCALE
A suitable (magic) scale factor for Windows systems.
static constexpr double GTK3_SCALE
A suitable (magic) scale factor for Mac systems.
static constexpr double MANUAL_SCALE_FACTOR
Abstract interface for drawing on a 2D-surface.
VECTOR2D GetGridPoint(const VECTOR2D &aPoint) const
For a given point it returns the nearest point belonging to the grid in world coordinates.
bool GetGridSnapping() const
const VECTOR2I & GetScreenPixelSize() const
Return GAL canvas size in pixels.
An interface for classes handling user events controlling the view behavior such as zooming,...
virtual void CaptureCursor(bool aEnabled)
Force the cursor to stay within the drawing panel area.
bool m_cursorWarped
Current VIEW_CONTROLS settings.
bool IsCursorWarpingEnabled() const
VC_SETTINGS m_settings
VIEW * m_view
< Pointer to controlled VIEW.
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:68
double GetScale() const
Definition: view.h:273
BOX2D GetViewport() const
Return the current viewport visible area rectangle.
Definition: view.cpp:522
const VECTOR2D & GetCenter() const
Return the center point of this VIEW (in world space coordinates).
Definition: view.h:343
virtual void SetScale(double aScale, VECTOR2D aAnchor={ 0, 0 })
Set the scaling factor, zooming around a given anchor point.
Definition: view.cpp:562
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:478
const VECTOR2I & GetScreenPixelSize() const
Return the size of the our rendering area in pixels.
Definition: view.cpp:1186
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:199
VECTOR2D ToWorld(const VECTOR2D &aCoord, bool aAbsolute=true) const
Converts a screen space point/vector to a point/vector in world space coordinates.
Definition: view.cpp:459
bool IsMirroredX() const
Return true if view is flipped across the X axis.
Definition: view.h:247
const BOX2D & GetBoundary() const
Definition: view.h:302
void SetCenter(const VECTOR2D &aCenter)
Set the center point of the VIEW (i.e.
Definition: view.cpp:588
bool m_updateCursor
Flag to indicate if infinite panning works on this platform.
bool m_infinitePanWorks
A #ZOOM_CONTROLLER that determines zoom steps. This is platform-specific.
void SetCrossHairCursorPosition(const VECTOR2D &aPosition, bool aWarpView) override
void LoadSettings() override
Event that forces mouse move event in the dispatcher (eg.
void setState(STATE aNewState)
Sets the interaction state, simply a internal setter to make it easier to debug changes.
STATE m_state
Panel that is affected by VIEW_CONTROLS.
void CaptureCursor(bool aEnabled) override
Force the cursor to stay within the drawing panel area.
void onScroll(wxScrollWinEvent &aEvent)
wxTimer m_panTimer
Ratio used for scaling world coordinates to scrollbar position.
void onButton(wxMouseEvent &aEvent)
void onEnter(wxMouseEvent &WXUNUSED(aEvent))
void onWheel(wxMouseEvent &aEvent)
Handler functions.
VECTOR2I m_scrollPos
The mouse position when a drag zoom started.
void refreshMouse(bool aSetModifiers)
Send an event to refresh mouse position.
WX_VIEW_CONTROLS(VIEW *aView, EDA_DRAW_PANEL_GAL *aParentPanel)
void onZoomGesture(wxZoomGestureEvent &aEvent)
void PinCursorInsideNonAutoscrollArea(bool aWarpMouseCursor) override
Return the current mouse pointer position.
void SetCursorPosition(const VECTOR2D &aPosition, bool warpView, bool aTriggeredByArrows, long aArrowCommand) override
Move the graphic crosshair cursor to the requested position expressed in world coordinates.
VECTOR2D GetMousePosition(bool aWorldCoordinates=true) const override
Return the current mouse pointer position.
void WarpMouseCursor(const VECTOR2D &aPosition, bool aWorldCoordinates=false, bool aWarpView=false) override
Set the viewport center to the current cursor position and warps the cursor to the screen center.
void onMagnify(wxMouseEvent &aEvent)
VECTOR2D GetRawCursorPosition(bool aSnappingEnabled=true) const override
Return the current cursor position in world coordinates ignoring the cursorUp position force mode.
VECTOR2D m_scrollScale
Current scrollbar position.
bool handleAutoPanning(const wxMouseEvent &aEvent)
Compute new viewport settings while in autopanning mode.
wxPoint getMouseScreenPosition() const
Get the cursor position in the screen coordinates.
void onPanGesture(wxPanGestureEvent &aEvent)
void onTimer(wxTimerEvent &WXUNUSED(aEvent))
std::unique_ptr< ZOOM_CONTROLLER > m_zoomController
Used to track gesture events.
STATE
< Possible states for WX_VIEW_CONTROLS.
@ DRAG_PANNING
Panning with mouse button pressed.
@ AUTO_PANNING
Panning on approaching borders of the frame.
@ DRAG_ZOOMING
Zooming with mouse button pressed.
@ IDLE
Nothing is happening.
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
void CenterOnCursor() override
Adjusts the scrollbars position to match the current viewport.
VECTOR2D m_cursorPos
Flag deciding whether the cursor position should be calculated using the mouse position.
void onCaptureLost(wxMouseEvent &WXUNUSED(aEvent))
void onMotion(wxMouseEvent &aEvent)
std::unique_ptr< PROF_COUNTER > m_MotionEventCounter
EDA_DRAW_PANEL_GAL * m_parentPanel
Store information about point where dragging has started.
void UpdateScrollbars()
End any mouse drag action still in progress.
void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0)) override
Applies VIEW_CONTROLS settings from the program COMMON_SETTINGS.
void handleCursorCapture(int x, int y)
Limit the cursor position to within the canvas by warping it.
void onLeave(wxMouseEvent &WXUNUSED(aEvent))
VECTOR2D m_zoomStartPoint
Current cursor position (world coordinates).
static const wxEventType EVT_REFRESH_MOUSE
VECTOR2D m_panDirection
Timer responsible for handling autopanning.
VECTOR2D m_dragStartPoint
Current direction of panning (only autopanning mode).
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:55
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
Definition: kiway_player.h:65
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:406
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition: pgm_base.cpp:679
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:283
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Definition: vector2d.h:385
@ FRAME_PCB_EDITOR
Definition: frame_type.h:42
@ FRAME_SCH
Definition: frame_type.h:34
a few functions useful in geometry calculations.
VECTOR2< ret_type > GetClampedCoords(const VECTOR2< in_type > &aCoords, pad_type aPadding=1u)
Clamps a vector to values that can be negated, respecting numeric limits of coordinates data type wit...
const wxChar *const traceZoomScroll
Flag to enable debug output of zoom-scrolling calculations in KIGFX::ZOOM_CONTROLLER and derivatives.
The Cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:247
wxPoint GetMousePosition()
Returns the mouse position in screen coordinates.
Definition: wxgtk/ui.cpp:620
void InfiniteDragReleaseWindow()
On Wayland, allows the cursor to freely move again after a drag (see InfiniteDragPrepareWindow).
Definition: wxgtk/ui.cpp:614
bool WarpPointer(wxWindow *aWindow, int aX, int aY)
Move the mouse cursor to a specific position relative to the window.
Definition: wxgtk/ui.cpp:253
bool IsWindowActive(wxWindow *aWindow)
Check to see if the given window is the currently active window (e.g.
Definition: wxgtk/ui.cpp:73
bool InfiniteDragPrepareWindow(wxWindow *aWindow)
On Wayland, restricts the pointer movement to a rectangle slightly bigger than the given wxWindow.
Definition: wxgtk/ui.cpp:607
KICOMMON_API bool IsInputControlFocused(wxWindow *aFocus=nullptr)
Check if a input control has focus.
Definition: ui_common.cpp:263
KICOMMON_API bool IsModalDialogFocused()
Definition: ui_common.cpp:317
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: pgm_base.cpp:1060
see class PGM_BASE
const int scale
MOUSE_DRAG_ACTION drag_right
MOUSE_DRAG_ACTION drag_middle
MOUSE_DRAG_ACTION drag_left
float m_autoPanMargin
How fast is panning when in auto mode.
Definition: view_controls.h:80
VECTOR2D m_forcedPosition
Is the forced cursor position enabled.
Definition: view_controls.h:56
MOUSE_DRAG_ACTION m_dragLeft
bool m_horizontalPan
Enable the accelerating zoom controller.
Definition: view_controls.h:92
bool m_autoPanSettingEnabled
Distance from cursor to VIEW edge when panning is active.
Definition: view_controls.h:77
bool m_focusFollowSchPcb
Flag for turning on autopanning.
Definition: view_controls.h:71
float m_autoPanAcceleration
If the cursor is allowed to be warped.
Definition: view_controls.h:86
MOUSE_DRAG_ACTION m_dragMiddle
bool m_cursorCaptured
Should the cursor snap to grid or move freely.
Definition: view_controls.h:62
int m_zoomSpeed
When true, ignore zoom_speed and pick a platform-specific default.
Definition: view_controls.h:98
int m_scrollModifierZoom
What modifier key to enable horizontal pan with the (vertical) scroll wheel.
int m_scrollModifierPanH
What modifier key to enable vertical with the (vertical) scroll wheel.
VECTOR2D m_lastKeyboardCursorPosition
Whether to invert the scroll wheel movement for zoom.
bool m_warpCursor
Enable horizontal panning with the horizontal scroll/trackpad input.
Definition: view_controls.h:89
MOUSE_DRAG_ACTION m_dragRight
Is last cursor motion event coming from keyboard arrow cursor motion action.
bool m_scrollReverseZoom
Whether to invert the scroll wheel movement for horizontal pan.
bool m_zoomAcceleration
Zoom speed for the non-accelerating zoom controller.
Definition: view_controls.h:95
bool m_lastKeyboardCursorPositionValid
ACTIONS::CURSOR_UP, ACTIONS::CURSOR_DOWN, etc.
bool m_zoomSpeedAuto
What modifier key to enable zoom with the (vertical) scroll wheel.
bool m_autoPanEnabled
Flag for turning on autopanning.
Definition: view_controls.h:74
long m_lastKeyboardCursorCommand
Position of the above event.
bool m_forceCursorPosition
Should the cursor be locked within the parent window area.
Definition: view_controls.h:59
constexpr int delta
wxLogTrace helper definitions.
Functions to provide common constants and other functions to assist in making a consistent UI.
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:691
VECTOR2< double > VECTOR2D
Definition: vector2d.h:690
static std::unique_ptr< ZOOM_CONTROLLER > GetZoomControllerForPlatform(bool aAcceleration)
WX_VIEW_CONTROLS class definition.
ZOOM_CONTROLLER class definition.