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 The 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 ), m_state( IDLE ), m_parentPanel( aParentPanel ),
77 m_scrollScale( 1.0, 1.0 ), m_cursorPos( 0, 0 ), m_updateCursor( true ),
78 m_infinitePanWorks( false ), m_gestureLastZoomFactor( 1.0 )
79{
81
82 m_MotionEventCounter = std::make_unique<PROF_COUNTER>( "Mouse motion events" );
83
84 m_parentPanel->Connect( wxEVT_MOTION,
85 wxMouseEventHandler( WX_VIEW_CONTROLS::onMotion ), nullptr, this );
86 m_parentPanel->Connect( wxEVT_MAGNIFY,
87 wxMouseEventHandler( WX_VIEW_CONTROLS::onMagnify ), nullptr, this );
88 m_parentPanel->Connect( wxEVT_MOUSEWHEEL,
89 wxMouseEventHandler( WX_VIEW_CONTROLS::onWheel ), nullptr, this );
90 m_parentPanel->Connect( wxEVT_MIDDLE_UP,
91 wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), nullptr, this );
92 m_parentPanel->Connect( wxEVT_MIDDLE_DOWN,
93 wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), nullptr, this );
94 m_parentPanel->Connect( wxEVT_LEFT_UP,
95 wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), nullptr, this );
96 m_parentPanel->Connect( wxEVT_LEFT_DOWN,
97 wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), nullptr, this );
98 m_parentPanel->Connect( wxEVT_RIGHT_UP,
99 wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), nullptr, this );
100 m_parentPanel->Connect( wxEVT_RIGHT_DOWN,
101 wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), nullptr, this );
102#if defined __WXMSW__
103 m_parentPanel->Connect( wxEVT_ENTER_WINDOW,
104 wxMouseEventHandler( WX_VIEW_CONTROLS::onEnter ), nullptr, this );
105#endif
106 m_parentPanel->Connect( wxEVT_LEAVE_WINDOW,
107 wxMouseEventHandler( WX_VIEW_CONTROLS::onLeave ), nullptr, this );
108 m_parentPanel->Connect( wxEVT_SCROLLWIN_THUMBTRACK,
109 wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), nullptr, this );
110 m_parentPanel->Connect( wxEVT_SCROLLWIN_PAGEUP,
111 wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), nullptr, this );
112 m_parentPanel->Connect( wxEVT_SCROLLWIN_PAGEDOWN,
113 wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), nullptr, this );
114
115 m_parentPanel->Connect( wxEVT_SCROLLWIN_BOTTOM,
116 wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), nullptr, this );
117 m_parentPanel->Connect( wxEVT_SCROLLWIN_TOP,
118 wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), nullptr, this );
119 m_parentPanel->Connect( wxEVT_SCROLLWIN_LINEUP,
120 wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), nullptr, this );
121 m_parentPanel->Connect( wxEVT_SCROLLWIN_LINEDOWN,
122 wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), nullptr, this );
123#if defined USE_MOUSE_CAPTURE
124 m_parentPanel->Connect( wxEVT_MOUSE_CAPTURE_LOST,
125 wxMouseEventHandler( WX_VIEW_CONTROLS::onCaptureLost ), nullptr, this );
126#endif
127
128#ifndef __WXOSX__
129 if( m_parentPanel->EnableTouchEvents( wxTOUCH_ZOOM_GESTURE | wxTOUCH_PAN_GESTURES ) )
130 {
131 m_parentPanel->Connect( wxEVT_GESTURE_ZOOM,
132 wxZoomGestureEventHandler( WX_VIEW_CONTROLS::onZoomGesture ),
133 nullptr, this );
134
135 m_parentPanel->Connect( wxEVT_GESTURE_PAN,
136 wxPanGestureEventHandler( WX_VIEW_CONTROLS::onPanGesture ), nullptr,
137 this );
138 }
139#endif
140
141 m_cursorWarped = false;
142
143 m_panTimer.SetOwner( this );
144 Connect( wxEVT_TIMER, wxTimerEventHandler( WX_VIEW_CONTROLS::onTimer ), nullptr, this );
145
149}
150
151
153{
154#if defined USE_MOUSE_CAPTURE
155 if( m_parentPanel->HasCapture() )
156 m_parentPanel->ReleaseMouse();
157#endif
158}
159
160
162{
164
181
182 m_zoomController.reset();
183
184 if( cfg->m_Input.zoom_speed_auto )
185 {
187 }
188 else
189 {
190 if( cfg->m_Input.zoom_acceleration )
191 {
193 std::make_unique<ACCELERATING_ZOOM_CONTROLLER>( cfg->m_Input.zoom_speed );
194 }
195 else
196 {
198
199 m_zoomController = std::make_unique<CONSTANT_ZOOM_CONTROLLER>( scale );
200 }
201 }
202}
203
204
205void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
206{
207 ( *m_MotionEventCounter )++;
208
209 // Because Weston sends a motion event to previous location after warping the pointer
210 wxPoint mouseRel = m_parentPanel->ScreenToClient( KIPLATFORM::UI::GetMousePosition() );
211
212 bool isAutoPanning = false;
213 int x = mouseRel.x;
214 int y = mouseRel.y;
215 VECTOR2D mousePos( x, y );
216
217 // Automatic focus switching between SCH and PCB windows on canvas mouse motion
219 {
221 {
222 KIWAY_PLAYER* otherFrame = nullptr;
223
224 if( frame->IsType( FRAME_PCB_EDITOR ) )
225 {
226 otherFrame = frame->Kiway().Player( FRAME_SCH, false );
227 }
228 else if( frame->IsType( FRAME_SCH ) )
229 {
230 otherFrame = frame->Kiway().Player( FRAME_PCB_EDITOR, false );
231 }
232
233 if( otherFrame && KIPLATFORM::UI::IsWindowActive( otherFrame )
234 && !KIPLATFORM::UI::IsWindowActive( frame ) )
235 {
236 frame->Raise();
237 }
238 }
239 }
240
242 handleCursorCapture( x, y );
243
245 isAutoPanning = handleAutoPanning( aEvent );
246
247 if( !isAutoPanning && aEvent.Dragging() )
248 {
249 if( m_state == DRAG_PANNING )
250 {
251 static bool justWarped = false;
252 int warpX = 0;
253 int warpY = 0;
254 wxSize parentSize = m_parentPanel->GetClientSize();
255
256 if( x < 0 )
257 {
258 warpX = parentSize.x;
259 }
260 else if(x >= parentSize.x )
261 {
262 warpX = -parentSize.x;
263 }
264
265 if( y < 0 )
266 {
267 warpY = parentSize.y;
268 }
269 else if( y >= parentSize.y )
270 {
271 warpY = -parentSize.y;
272 }
273
274 if( !justWarped )
275 {
276 VECTOR2D d = m_dragStartPoint - mousePos;
277 m_dragStartPoint = mousePos;
278 VECTOR2D delta = m_view->ToWorld( d, false );
280 aEvent.StopPropagation();
281 }
282
283 if( warpX || warpY )
284 {
285 if( !justWarped )
286 {
288 && KIPLATFORM::UI::WarpPointer( m_parentPanel, x + warpX, y + warpY ) )
289 {
290 m_dragStartPoint += VECTOR2D( warpX, warpY );
291 justWarped = true;
292 }
293 }
294 else
295 {
296 justWarped = false;
297 }
298 }
299 else
300 {
301 justWarped = false;
302 }
303 }
304 else if( m_state == DRAG_ZOOMING )
305 {
306 static bool justWarped = false;
307 int warpY = 0;
308 wxSize parentSize = m_parentPanel->GetClientSize();
309
310 if( y < 0 )
311 {
312 warpY = parentSize.y;
313 }
314 else if( y >= parentSize.y )
315 {
316 warpY = -parentSize.y;
317 }
318
319 if( !justWarped )
320 {
321 VECTOR2D d = m_dragStartPoint - mousePos;
322 m_dragStartPoint = mousePos;
323
324 double scale = exp( d.y * m_settings.m_zoomSpeed * 0.001 );
325
326 wxLogTrace( traceZoomScroll, wxString::Format( "dy: %f scale: %f", d.y, scale ) );
327
329 aEvent.StopPropagation();
330 }
331
332 if( warpY )
333 {
334 if( !justWarped )
335 {
337 m_dragStartPoint += VECTOR2D( 0, warpY );
338 justWarped = true;
339 }
340 else
341 justWarped = false;
342 }
343 else
344 {
345 justWarped = false;
346 }
347 }
348 }
349
350 if( m_updateCursor ) // do not update the cursor position if it was explicitly set
351 m_cursorPos = GetClampedCoords( m_view->ToWorld( mousePos ) );
352 else
353 m_updateCursor = true;
354
355 aEvent.Skip();
356}
357
358
359void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& aEvent )
360{
361 const double wheelPanSpeed = 0.001;
362 const int axis = aEvent.GetWheelAxis();
363
364 if( axis == wxMOUSE_WHEEL_HORIZONTAL && !m_settings.m_horizontalPan )
365 return;
366
367 // Pick the modifier, if any. Shift beats control beats alt, we don't support more than one.
368 int nMods = 0;
369 int modifiers = 0;
370
371 if( aEvent.ShiftDown() )
372 {
373 nMods += 1;
374 modifiers = WXK_SHIFT;
375 }
376
377 if( aEvent.ControlDown() )
378 {
379 nMods += 1;
380 modifiers = modifiers == 0 ? WXK_CONTROL : modifiers;
381 }
382
383 if( aEvent.AltDown() )
384 {
385 nMods += 1;
386 modifiers = modifiers == 0 ? WXK_ALT : modifiers;
387 }
388
389 // Zero or one modifier is view control
390 if( nMods <= 1 )
391 {
392 // Restrict zoom handling to the vertical axis, otherwise horizontal
393 // scrolling events (e.g. touchpads and some mice) end up interpreted
394 // as vertical scroll events and confuse the user.
395 if( modifiers == m_settings.m_scrollModifierZoom && axis == wxMOUSE_WHEEL_VERTICAL )
396 {
397 const int rotation =
398 aEvent.GetWheelRotation() * ( m_settings.m_scrollReverseZoom ? -1 : 1 );
399 const double zoomScale = m_zoomController->GetScaleForRotation( rotation );
400
402 {
404 m_view->SetScale( m_view->GetScale() * zoomScale );
405 }
406 else
407 {
408 const VECTOR2D anchor = m_view->ToWorld( VECTOR2D( aEvent.GetX(), aEvent.GetY() ) );
409 m_view->SetScale( m_view->GetScale() * zoomScale, anchor );
410 }
411
412 // Refresh the zoom level and mouse position on message panel
413 // (mouse position has not changed, only the zoom level has changed):
414 refreshMouse( true );
415 }
416 else
417 {
418 // Scrolling
419 VECTOR2D scrollVec = m_view->ToWorld( m_view->GetScreenPixelSize(), false )
420 * ( (double) aEvent.GetWheelRotation() * wheelPanSpeed );
421 double scrollX = 0.0;
422 double scrollY = 0.0;
423 bool hReverse = false;
424
425 if( axis != wxMOUSE_WHEEL_HORIZONTAL )
427
428 if( axis == wxMOUSE_WHEEL_HORIZONTAL || modifiers == m_settings.m_scrollModifierPanH )
429 {
430 if( hReverse )
431 scrollX = scrollVec.x;
432 else
433 scrollX = ( axis == wxMOUSE_WHEEL_HORIZONTAL ) ? scrollVec.x : -scrollVec.x;
434 }
435 else
436 {
437 scrollY = -scrollVec.y;
438 }
439
440 VECTOR2D delta( scrollX, scrollY );
441
443 refreshMouse( true );
444 }
445
446 // Do not skip this event, otherwise wxWidgets will fire
447 // 3 wxEVT_SCROLLWIN_LINEUP or wxEVT_SCROLLWIN_LINEDOWN (normal wxWidgets behavior)
448 // and we do not want that.
449 }
450 else
451 {
452 // When we have multiple mods, forward it for tool handling
453 aEvent.Skip();
454 }
455}
456
457
458void WX_VIEW_CONTROLS::onMagnify( wxMouseEvent& aEvent )
459{
460 // Scale based on the magnification from our underlying magnification event.
461 VECTOR2D anchor = m_view->ToWorld( VECTOR2D( aEvent.GetX(), aEvent.GetY() ) );
462 m_view->SetScale( m_view->GetScale() * ( aEvent.GetMagnification() + 1.0f ), anchor );
463
464 aEvent.Skip();
465}
466
467
469{
470 m_state = aNewState;
471}
472
473
474void WX_VIEW_CONTROLS::onButton( wxMouseEvent& aEvent )
475{
476 switch( m_state )
477 {
478 case IDLE:
479 case AUTO_PANNING:
480 if( ( aEvent.MiddleDown() && m_settings.m_dragMiddle == MOUSE_DRAG_ACTION::PAN ) ||
481 ( aEvent.RightDown() && m_settings.m_dragRight == MOUSE_DRAG_ACTION::PAN ) )
482 {
483 m_dragStartPoint = VECTOR2D( aEvent.GetX(), aEvent.GetY() );
486
487#if defined USE_MOUSE_CAPTURE
488 if( !m_parentPanel->HasCapture() )
489 m_parentPanel->CaptureMouse();
490#endif
491 }
492 else if( ( aEvent.MiddleDown() && m_settings.m_dragMiddle == MOUSE_DRAG_ACTION::ZOOM ) ||
493 ( aEvent.RightDown() && m_settings.m_dragRight == MOUSE_DRAG_ACTION::ZOOM ) )
494 {
495 m_dragStartPoint = VECTOR2D( aEvent.GetX(), aEvent.GetY() );
498
499#if defined USE_MOUSE_CAPTURE
500 if( !m_parentPanel->HasCapture() )
501 m_parentPanel->CaptureMouse();
502#endif
503 }
504
505 if( aEvent.LeftUp() )
506 setState( IDLE ); // Stop autopanning when user release left mouse button
507
508 break;
509
510 case DRAG_ZOOMING:
511 case DRAG_PANNING:
512 if( aEvent.MiddleUp() || aEvent.LeftUp() || aEvent.RightUp() )
513 {
514 setState( IDLE );
516
517#if defined USE_MOUSE_CAPTURE
518 if( !m_settings.m_cursorCaptured && m_parentPanel->HasCapture() )
519 m_parentPanel->ReleaseMouse();
520#endif
521 }
522
523 break;
524 }
525
526 aEvent.Skip();
527}
528
529
530void WX_VIEW_CONTROLS::onEnter( wxMouseEvent& aEvent )
531{
532 // Avoid stealing focus from text controls
533 // This is particularly important for users using On-Screen-Keyboards
534 // They may move the mouse over the canvas to reach the keyboard
536 {
537 return;
538 }
539
540#if defined( _WIN32 ) || defined( __WXGTK__ )
541 // Win32 and some *nix WMs transmit mouse move and wheel events to all controls below the
542 // mouse regardless of focus. Forcing the focus here will cause the EDA FRAMES to immediately
543 // become the top level active window.
544 if( m_parentPanel->GetParent() != nullptr )
545 {
546 // this assumes the parent panel's parent is the eda window
548 {
550 }
551 }
552#else
554#endif
555}
556
557
558void WX_VIEW_CONTROLS::onLeave( wxMouseEvent& aEvent )
559{
560#if !defined USE_MOUSE_CAPTURE
561 onMotion( aEvent );
562#endif
563}
564
565
566void WX_VIEW_CONTROLS::onCaptureLost( wxMouseEvent& aEvent )
567{
568 // This method must be present to suppress the capture-lost assertion
569
570 // Set the flag to allow calling m_parentPanel->CaptureMouse()
571 // Note: One cannot call m_parentPanel->CaptureMouse() twice, this is not accepted
572 // by wxWidgets (MSW specific) so we need this guard
574}
575
576
577void WX_VIEW_CONTROLS::onTimer( wxTimerEvent& aEvent )
578{
579 switch( m_state )
580 {
581 case AUTO_PANNING:
582 {
584 {
585 setState( IDLE );
586 return;
587 }
588
589#ifdef __WXMSW__
590 // Hackfix: It's possible for the mouse to leave the canvas
591 // without triggering any leave events on windows
592 // Use a MSW only wx function
593 if( !m_parentPanel->IsMouseInWindow() )
594 {
595 m_panTimer.Stop();
596 setState( IDLE );
597 return;
598 }
599#endif
600
601 if( !m_parentPanel->HasFocus() && !m_parentPanel->StatusPopupHasFocus() )
602 {
603 setState( IDLE );
604 return;
605 }
606
607 double borderSize = std::min( m_settings.m_autoPanMargin * m_view->GetScreenPixelSize().x,
609
610 // When the mouse cursor is outside the area with no pan,
611 // m_panDirection is the dist to this area limit ( in pixels )
612 // It will be used also as pan value (the pan speed depends on this dist).
614
615 // When the mouse cursor is outside the area with no pan, the pan value
616 // is accelerated depending on the dist between the area and the cursor
617 float accel = 0.5f + ( m_settings.m_autoPanAcceleration / 5.0f );
618
619 // For a small mouse cursor dist to area, just use the distance.
620 // But for a dist > borderSize / 2, use an accelerated pan value
621
622 if( dir.EuclideanNorm() >= borderSize ) // far from area limits
623 dir = dir.Resize( borderSize * accel );
624 else if( dir.EuclideanNorm() > borderSize / 2 ) // Near from area limits
625 dir = dir.Resize( borderSize );
626
627 dir = m_view->ToWorld( dir, false );
628 m_view->SetCenter( m_view->GetCenter() + dir );
629
630 refreshMouse( true );
631
632 m_panTimer.Start();
633 }
634 break;
635
636 case IDLE: // Just remove unnecessary warnings
637 case DRAG_PANNING:
638 case DRAG_ZOOMING:
639 break;
640 }
641}
642
643
644void WX_VIEW_CONTROLS::onZoomGesture( wxZoomGestureEvent& aEvent )
645{
646 if( aEvent.IsGestureStart() )
647 {
649 m_gestureLastPos = VECTOR2D( aEvent.GetPosition().x, aEvent.GetPosition().y );
650 }
651
652 VECTOR2D evtPos( aEvent.GetPosition().x, aEvent.GetPosition().y );
653 VECTOR2D deltaWorld = m_view->ToWorld( evtPos - m_gestureLastPos, false );
654
655 m_view->SetCenter( m_view->GetCenter() - deltaWorld );
656
657 m_view->SetScale( m_view->GetScale() * aEvent.GetZoomFactor() / m_gestureLastZoomFactor,
658 m_view->ToWorld( evtPos ) );
659
660 m_gestureLastZoomFactor = aEvent.GetZoomFactor();
661 m_gestureLastPos = evtPos;
662
663 refreshMouse( true );
664}
665
666
667void WX_VIEW_CONTROLS::onPanGesture( wxPanGestureEvent& aEvent )
668{
669 VECTOR2I screenDelta( aEvent.GetDelta().x, aEvent.GetDelta().y );
670 VECTOR2D deltaWorld = m_view->ToWorld( screenDelta, false );
671
672 m_view->SetCenter( m_view->GetCenter() - deltaWorld );
673
674 refreshMouse( true );
675}
676
677
678void WX_VIEW_CONTROLS::onScroll( wxScrollWinEvent& aEvent )
679{
680 const double linePanDelta = 0.05;
681 const double pagePanDelta = 0.5;
682
683 int type = aEvent.GetEventType();
684 int dir = aEvent.GetOrientation();
685
686 if( type == wxEVT_SCROLLWIN_THUMBTRACK )
687 {
688 auto center = m_view->GetCenter();
689 const auto& boundary = m_view->GetBoundary();
690
691 // Flip scroll direction in flipped view
692 const double xstart = ( m_view->IsMirroredX() ?
693 boundary.GetRight() : boundary.GetLeft() );
694 const double xdelta = ( m_view->IsMirroredX() ? -1 : 1 );
695
696 if( dir == wxHORIZONTAL )
697 center.x = xstart + xdelta * ( aEvent.GetPosition() / m_scrollScale.x );
698 else
699 center.y = boundary.GetTop() + aEvent.GetPosition() / m_scrollScale.y;
700
701 m_view->SetCenter( center );
702 }
703 else if( type == wxEVT_SCROLLWIN_THUMBRELEASE ||
704 type == wxEVT_SCROLLWIN_TOP ||
705 type == wxEVT_SCROLLWIN_BOTTOM )
706 {
707 // Do nothing on thumb release, we don't care about it.
708 // We don't have a concept of top or bottom in our viewport, so ignore those events.
709 }
710 else
711 {
712 double dist = 0;
713
714 if( type == wxEVT_SCROLLWIN_PAGEUP )
715 {
716 dist = pagePanDelta;
717 }
718 else if( type == wxEVT_SCROLLWIN_PAGEDOWN )
719 {
720 dist = -pagePanDelta;
721 }
722 else if( type == wxEVT_SCROLLWIN_LINEUP )
723 {
724 dist = linePanDelta;
725 }
726 else if( type == wxEVT_SCROLLWIN_LINEDOWN )
727 {
728 dist = -linePanDelta;
729 }
730 else
731 {
732 wxCHECK_MSG( false, /* void */, wxT( "Unhandled event type" ) );
733 }
734
735 VECTOR2D scroll = m_view->ToWorld( m_view->GetScreenPixelSize(), false ) * dist;
736
737 double scrollX = 0.0;
738 double scrollY = 0.0;
739
740 if ( dir == wxHORIZONTAL )
741 scrollX = -scroll.x;
742 else
743 scrollY = -scroll.y;
744
745 VECTOR2D delta( scrollX, scrollY );
746
748 }
749
751}
752
753
755{
756#if defined USE_MOUSE_CAPTURE
757 // Note: for some reason, m_parentPanel->HasCapture() can be false even if CaptureMouse()
758 // was called (i.e. mouse was captured, so when need to test m_MouseCapturedLost to be
759 // sure a wxEVT_MOUSE_CAPTURE_LOST event was fired before. Otherwise wxMSW complains
760 // The IsModalDialogFocused is checked because it's possible to start a capture
761 // due to event ordering while a modal dialog was just opened, the mouse capture steels focus
762 // from the modal and causes odd behavior
763 if( aEnabled && !m_parentPanel->HasCapture() && m_parentPanel->m_MouseCapturedLost
765 {
766 m_parentPanel->CaptureMouse();
767
768 // Clear the flag to allow calling m_parentPanel->CaptureMouse()
769 // Calling it without calling ReleaseMouse() is not accepted by wxWidgets (MSW specific)
771 }
772 else if( !aEnabled && m_parentPanel->HasCapture()
774 {
775 m_parentPanel->ReleaseMouse();
776
777 // Mouse is released, calling CaptureMouse() is allowed now:
779 }
780#endif
782}
783
784
786{
788 {
789 setState( IDLE );
790
791#if defined USE_MOUSE_CAPTURE
792 if( !m_settings.m_cursorCaptured && m_parentPanel->HasCapture() )
793 m_parentPanel->ReleaseMouse();
794#endif
795 }
796}
797
798
799VECTOR2D WX_VIEW_CONTROLS::GetMousePosition( bool aWorldCoordinates ) const
800{
801 wxPoint msp = getMouseScreenPosition();
802 VECTOR2D screenPos( msp.x, msp.y );
803
804 return aWorldCoordinates ? GetClampedCoords( m_view->ToWorld( screenPos ) ) : screenPos;
805}
806
807
809{
810 GAL* gal = m_view->GetGAL();
811
812 if( aEnableSnapping && gal->GetGridSnapping() )
813 {
814 return gal->GetGridPoint( m_cursorPos );
815 }
816 else
817 {
818 return m_cursorPos;
819 }
820}
821
822
824{
826 {
828 }
829 else
830 {
831 return GetClampedCoords( GetRawCursorPosition( aEnableSnapping ) );
832 }
833}
834
835
836void WX_VIEW_CONTROLS::SetCursorPosition( const VECTOR2D& aPosition, bool aWarpView,
837 bool aTriggeredByArrows, long aArrowCommand )
838{
839 m_updateCursor = false;
840
841 VECTOR2D clampedPosition = GetClampedCoords( aPosition );
842
843 if( aTriggeredByArrows )
844 {
848 m_cursorWarped = false;
849 }
850 else
851 {
855 m_cursorWarped = true;
856 }
857
858 WarpMouseCursor( clampedPosition, true, aWarpView );
859 m_cursorPos = clampedPosition;
860}
861
862
864 bool aWarpView = true )
865{
866 m_updateCursor = false;
867
868 VECTOR2D clampedPosition = GetClampedCoords( aPosition );
869
870 const VECTOR2I& screenSize = m_view->GetGAL()->GetScreenPixelSize();
871 BOX2I screen( VECTOR2I( 0, 0 ), screenSize );
872 VECTOR2D screenPos = m_view->ToScreen( clampedPosition );
873
874 if( aWarpView && !screen.Contains( screenPos ) )
875 m_view->SetCenter( clampedPosition );
876
877 m_cursorPos = clampedPosition;
878}
879
880
881void WX_VIEW_CONTROLS::WarpMouseCursor( const VECTOR2D& aPosition, bool aWorldCoordinates,
882 bool aWarpView )
883{
884 if( aWorldCoordinates )
885 {
886 const VECTOR2I& screenSize = m_view->GetGAL()->GetScreenPixelSize();
887 BOX2I screen( VECTOR2I( 0, 0 ), screenSize );
888 VECTOR2D clampedPosition = GetClampedCoords( aPosition );
889 VECTOR2D screenPos = m_view->ToScreen( clampedPosition );
890
891 if( !screen.Contains( screenPos ) )
892 {
893 if( aWarpView )
894 {
895 m_view->SetCenter( clampedPosition );
896 KIPLATFORM::UI::WarpPointer( m_parentPanel, screenSize.x / 2, screenSize.y / 2 );
897 }
898 }
899 else
900 {
901 KIPLATFORM::UI::WarpPointer( m_parentPanel, screenPos.x, screenPos.y );
902 }
903 }
904 else
905 {
906 KIPLATFORM::UI::WarpPointer( m_parentPanel, aPosition.x, aPosition.y );
907 }
908
909 // If we are not refreshing because of mouse movement, don't set the modifiers because we
910 // are refreshing for keyboard movement, which uses the same modifiers for other actions
912}
913
914
916{
917 const VECTOR2I& screenSize = m_view->GetGAL()->GetScreenPixelSize();
918 VECTOR2D screenCenter( screenSize / 2 );
919
920 if( GetMousePosition( false ) != screenCenter )
921 {
922 VECTOR2D newCenter = GetCursorPosition();
923
924 if( KIPLATFORM::UI::WarpPointer( m_parentPanel, screenCenter.x, screenCenter.y ) )
925 {
926 m_view->SetCenter( newCenter );
927 m_dragStartPoint = screenCenter;
928 }
929 }
930}
931
932
934{
935 int border = std::min( m_settings.m_autoPanMargin * m_view->GetScreenPixelSize().x,
937 border += 2;
938
939 VECTOR2D topLeft( border, border );
940 VECTOR2D botRight( m_view->GetScreenPixelSize().x - border,
941 m_view->GetScreenPixelSize().y - border );
942
943 topLeft = m_view->ToWorld( topLeft );
944 botRight = m_view->ToWorld( botRight );
945
946 VECTOR2D pos = GetMousePosition( true );
947
948 if( pos.x < topLeft.x )
949 pos.x = topLeft.x;
950 else if( pos.x > botRight.x )
951 pos.x = botRight.x;
952
953 if( pos.y < topLeft.y )
954 pos.y = topLeft.y;
955 else if( pos.y > botRight.y )
956 pos.y = botRight.y;
957
958 SetCursorPosition( pos, false, false, 0 );
959
960 if( aWarpMouseCursor )
961 WarpMouseCursor( pos, true );
962}
963
964
965bool WX_VIEW_CONTROLS::handleAutoPanning( const wxMouseEvent& aEvent )
966{
967 VECTOR2I p( aEvent.GetX(), aEvent.GetY() );
969
971 {
972 // last cursor move event came from keyboard cursor control. If auto-panning is enabled
973 // and the next position is inside the autopan zone, check if it really came from a mouse
974 // event, otherwise disable autopan temporarily. Also temporarily disable autopan if the
975 // cursor is in the autopan zone because the application warped the cursor.
976
977 m_cursorWarped = false;
978 return true;
979 }
980
981 m_cursorWarped = false;
982
983 // Compute areas where autopanning is active
984 int borderStart = std::min( m_settings.m_autoPanMargin * m_view->GetScreenPixelSize().x,
986 borderStart = std::max( borderStart, 2 );
987 int borderEndX = m_view->GetScreenPixelSize().x - borderStart;
988 int borderEndY = m_view->GetScreenPixelSize().y - borderStart;
989
990 if( p.x < borderStart )
991 m_panDirection.x = -( borderStart - p.x );
992 else if( p.x > borderEndX )
993 m_panDirection.x = ( p.x - borderEndX );
994 else
995 m_panDirection.x = 0;
996
997 if( p.y < borderStart )
998 m_panDirection.y = -( borderStart - p.y );
999 else if( p.y > borderEndY )
1000 m_panDirection.y = ( p.y - borderEndY );
1001 else
1002 m_panDirection.y = 0;
1003
1004 bool borderHit = ( m_panDirection.x != 0 || m_panDirection.y != 0 );
1005
1006 switch( m_state )
1007 {
1008 case AUTO_PANNING:
1009 if( !borderHit )
1010 {
1011 m_panTimer.Stop();
1012 setState( IDLE );
1013
1014 return false;
1015 }
1016
1017 return true;
1018
1019 case IDLE:
1020 if( borderHit )
1021 {
1023 m_panTimer.Start( (int) ( 250.0 / 60.0 ), true );
1024
1025 return true;
1026 }
1027
1028 return false;
1029
1030 case DRAG_PANNING:
1031 case DRAG_ZOOMING:
1032 return false;
1033 }
1034
1035 wxCHECK_MSG( false, false, wxT( "This line should never be reached" ) );
1036
1037 return false;
1038}
1039
1040
1042{
1044 {
1045 bool warp = false;
1046 wxSize parentSize = m_parentPanel->GetClientSize();
1047
1048 if( x < 0 )
1049 {
1050 x = 0;
1051 warp = true;
1052 }
1053 else if( x >= parentSize.x )
1054 {
1055 x = parentSize.x - 1;
1056 warp = true;
1057 }
1058
1059 if( y < 0 )
1060 {
1061 y = 0;
1062 warp = true;
1063 }
1064 else if( y >= parentSize.y )
1065 {
1066 y = parentSize.y - 1;
1067 warp = true;
1068 }
1069
1070 if( warp )
1072 }
1073}
1074
1075
1076void WX_VIEW_CONTROLS::refreshMouse( bool aSetModifiers )
1077{
1078 // Notify tools that the cursor position has changed in the world coordinates
1079 wxMouseEvent moveEvent( EVT_REFRESH_MOUSE );
1080 wxPoint msp = getMouseScreenPosition();
1081 moveEvent.SetX( msp.x );
1082 moveEvent.SetY( msp.y );
1083
1084 if( aSetModifiers )
1085 {
1086 // Set the modifiers state
1087 moveEvent.SetControlDown( wxGetKeyState( WXK_CONTROL ) );
1088 moveEvent.SetShiftDown( wxGetKeyState( WXK_SHIFT ) );
1089 moveEvent.SetAltDown( wxGetKeyState( WXK_ALT ) );
1090 }
1091
1092 m_cursorPos = GetClampedCoords( m_view->ToWorld( VECTOR2D( msp.x, msp.y ) ) );
1093 wxPostEvent( m_parentPanel, moveEvent );
1094}
1095
1096
1098{
1099 wxPoint msp = KIPLATFORM::UI::GetMousePosition();
1100 m_parentPanel->ScreenToClient( &msp.x, &msp.y );
1101 return msp;
1102}
1103
1104
1106{
1107 const BOX2D viewport = m_view->GetViewport();
1108 const BOX2D& boundary = m_view->GetBoundary();
1109
1110 m_scrollScale.x = 2e3 / viewport.GetWidth(); // TODO it does not have to be updated so often
1111 m_scrollScale.y = 2e3 / viewport.GetHeight();
1112 VECTOR2I newScroll( ( viewport.Centre().x - boundary.GetLeft() ) * m_scrollScale.x,
1113 ( viewport.Centre().y - boundary.GetTop() ) * m_scrollScale.y );
1114
1115 // We add the width of the scroll bar thumb to the range because the scroll range is given by
1116 // the full bar while the position is given by the left/top position of the thumb
1117 VECTOR2I newRange( m_scrollScale.x * boundary.GetWidth() +
1118 m_parentPanel->GetScrollThumb( wxSB_HORIZONTAL ),
1119 m_scrollScale.y * boundary.GetHeight() +
1120 m_parentPanel->GetScrollThumb( wxSB_VERTICAL ) );
1121
1122 // Flip scroll direction in flipped view
1123 if( m_view->IsMirroredX() )
1124 newScroll.x = ( boundary.GetRight() - viewport.Centre().x ) * m_scrollScale.x;
1125
1126 // Adjust scrollbars only if it is needed. Otherwise there are cases when canvas is continuously
1127 // refreshed (Windows)
1128 if( m_scrollPos != newScroll || newRange.x != m_parentPanel->GetScrollRange( wxSB_HORIZONTAL )
1129 || newRange.y != m_parentPanel->GetScrollRange( wxSB_VERTICAL ) )
1130 {
1131 m_parentPanel->SetScrollbars( 1, 1, newRange.x, newRange.y, newScroll.x, newScroll.y,
1132 true );
1133 m_scrollPos = newScroll;
1134
1135#if !defined( __APPLE__ ) && !defined( WIN32 )
1136 // Trigger a mouse refresh to get the canvas update in GTK (re-draws the scrollbars).
1137 // Note that this causes an infinite loop on OSX and Windows (in certain cases) as it
1138 // generates a paint event.
1139 refreshMouse( false );
1140#endif
1141 }
1142}
1143
1144
1145void WX_VIEW_CONTROLS::ForceCursorPosition( bool aEnabled, const VECTOR2D& aPosition )
1146{
1147 VECTOR2D clampedPosition = GetClampedCoords( aPosition );
1148
1150 m_settings.m_forcedPosition = clampedPosition;
1151}
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
A suitable (magic) scale factor for Mac systems.
static constexpr double MSW_SCALE
A suitable (magic) scale factor for Windows systems.
static constexpr double GTK3_SCALE
A suitable (magic) scale factor for GTK3 systems.
static constexpr double MANUAL_SCALE_FACTOR
Multiplier for manual scale ssetting.
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
Application warped the cursor, not the user (keyboard).
bool IsCursorWarpingEnabled() const
VC_SETTINGS m_settings
Current VIEW_CONTROLS 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:67
double GetScale() const
Definition: view.h:272
BOX2D GetViewport() const
Return the current viewport visible area rectangle.
Definition: view.cpp:520
const VECTOR2D & GetCenter() const
Return the center point of this VIEW (in world space coordinates).
Definition: view.h:342
virtual void SetScale(double aScale, VECTOR2D aAnchor={ 0, 0 })
Set the scaling factor, zooming around a given anchor point.
Definition: view.cpp:560
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:476
const VECTOR2I & GetScreenPixelSize() const
Return the size of the our rendering area in pixels.
Definition: view.cpp:1190
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:198
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:457
bool IsMirroredX() const
Return true if view is flipped across the X axis.
Definition: view.h:246
const BOX2D & GetBoundary() const
Definition: view.h:301
void SetCenter(const VECTOR2D &aCenter)
Set the center point of the VIEW (i.e.
Definition: view.cpp:586
bool m_updateCursor
Flag deciding whether the cursor position should be calculated using the mouse position.
bool m_infinitePanWorks
Flag to indicate if infinite panning works on this platform.
void SetCrossHairCursorPosition(const VECTOR2D &aPosition, bool aWarpView) override
Move the graphic crosshair cursor to the requested position expressed in world coordinates.
void LoadSettings() override
Applies VIEW_CONTROLS settings from the program COMMON_SETTINGS.
void setState(STATE aNewState)
Set the interaction state, simply a internal setter to make it easier to debug changes.
STATE m_state
Current state of VIEW_CONTROLS.
void CaptureCursor(bool aEnabled) override
Force the cursor to stay within the drawing panel area.
void onScroll(wxScrollWinEvent &aEvent)
wxTimer m_panTimer
Timer responsible for handling autopanning.
void CancelDrag()
End any mouse drag action still in progress.
void onButton(wxMouseEvent &aEvent)
double m_gestureLastZoomFactor
Used to track gesture events.
void onEnter(wxMouseEvent &WXUNUSED(aEvent))
void onWheel(wxMouseEvent &aEvent)
Handler functions.
VECTOR2I m_scrollPos
Current scrollbar position.
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
void SetCursorPosition(const VECTOR2D &aPosition, bool warpView, bool aTriggeredByArrows, long aArrowCommand) override
Move 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
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
Ratio used for scaling world coordinates to 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
A #ZOOM_CONTROLLER that determines zoom steps. This is platform-specific.
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
Set the viewport center to the current cursor position and warps the cursor to the screen center.
VECTOR2D m_cursorPos
Current cursor position (world coordinates).
void onCaptureLost(wxMouseEvent &WXUNUSED(aEvent))
void onMotion(wxMouseEvent &aEvent)
std::unique_ptr< PROF_COUNTER > m_MotionEventCounter
EDA_DRAW_PANEL_GAL * m_parentPanel
Panel that is affected by VIEW_CONTROLS.
void UpdateScrollbars()
Adjusts the scrollbars position to match the current viewport.
void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0)) override
Place the cursor immediately at a given point.
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
The mouse position when a drag zoom started.
static const wxEventType EVT_REFRESH_MOUSE
Event that forces mouse move event in the dispatcher (eg.
VECTOR2D m_panDirection
Current direction of panning (only autopanning mode).
VECTOR2D m_dragStartPoint
Store information about point where dragging has started.
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:689
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:677
void InfiniteDragReleaseWindow()
On Wayland, allows the cursor to freely move again after a drag (see InfiniteDragPrepareWindow).
Definition: wxgtk/ui.cpp:671
bool WarpPointer(wxWindow *aWindow, int aX, int aY)
Move the mouse cursor to a specific position relative to the window.
Definition: wxgtk/ui.cpp:310
bool IsWindowActive(wxWindow *aWindow)
Check to see if the given window is the currently active window (e.g.
Definition: wxgtk/ui.cpp:130
bool InfiniteDragPrepareWindow(wxWindow *aWindow)
On Wayland, restricts the pointer movement to a rectangle slightly bigger than the given wxWindow.
Definition: wxgtk/ui.cpp:664
KICOMMON_API bool IsInputControlFocused(wxWindow *aFocus=nullptr)
Check if a input control has focus.
Definition: ui_common.cpp:264
KICOMMON_API bool IsModalDialogFocused()
Definition: ui_common.cpp:319
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:1073
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
Distance from cursor to VIEW edge when panning is active.
Definition: view_controls.h:80
VECTOR2D m_forcedPosition
Forced cursor position (world coordinates).
Definition: view_controls.h:56
MOUSE_DRAG_ACTION m_dragLeft
bool m_horizontalPan
Enable horizontal panning with the horizontal scroll/trackpad input.
Definition: view_controls.h:92
bool m_scrollReversePanH
Whether to invert the scroll wheel movement for horizontal pan.
bool m_autoPanSettingEnabled
Flag for turning on autopanning.
Definition: view_controls.h:77
bool m_focusFollowSchPcb
Flag for automatic focus switching between Schematic and PCB editors.
Definition: view_controls.h:71
float m_autoPanAcceleration
How fast does panning accelerate when approaching the window boundary.
Definition: view_controls.h:86
MOUSE_DRAG_ACTION m_dragMiddle
bool m_cursorCaptured
Should the cursor be locked within the parent window area.
Definition: view_controls.h:62
int m_zoomSpeed
Zoom speed for the non-accelerating zoom controller.
Definition: view_controls.h:98
int m_scrollModifierZoom
What modifier key to enable zoom with the (vertical) scroll wheel.
int m_scrollModifierPanH
What modifier key to enable horizontal pan with the (vertical) scroll wheel.
VECTOR2D m_lastKeyboardCursorPosition
Position of the above event.
bool m_warpCursor
If the cursor is allowed to be warped.
Definition: view_controls.h:89
MOUSE_DRAG_ACTION m_dragRight
bool m_scrollReverseZoom
Whether to invert the scroll wheel movement for zoom.
bool m_zoomAcceleration
Enable the accelerating zoom controller.
Definition: view_controls.h:95
bool m_lastKeyboardCursorPositionValid
Is last cursor motion event coming from keyboard arrow cursor motion action.
bool m_zoomSpeedAuto
When true, ignore zoom_speed and pick a platform-specific default.
bool m_autoPanEnabled
Flag for turning on autopanning.
Definition: view_controls.h:74
int m_scrollModifierPanV
What modifier key to enable vertical with the (vertical) scroll wheel.
long m_lastKeyboardCursorCommand
ACTIONS::CURSOR_UP, ACTIONS::CURSOR_DOWN, etc.
bool m_forceCursorPosition
Is the forced cursor position enabled.
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:695
VECTOR2< double > VECTOR2D
Definition: vector2d.h:694
static std::unique_ptr< ZOOM_CONTROLLER > GetZoomControllerForPlatform(bool aAcceleration)
WX_VIEW_CONTROLS class definition.
ZOOM_CONTROLLER class definition.