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 ),
77 m_state( IDLE ),
78 m_parentPanel( aParentPanel ),
79 m_scrollScale( 1.0, 1.0 ),
80 m_cursorPos( 0, 0 ),
81 m_updateCursor( true ),
82 m_metaPanning( false ),
83 m_metaPanStart( 0, 0 ),
84 m_infinitePanWorks( false ),
85 m_gestureLastZoomFactor( 1.0 )
86{
88
89 m_MotionEventCounter = std::make_unique<PROF_COUNTER>( "Mouse motion events" );
90
91 m_parentPanel->Connect( wxEVT_MOTION,
92 wxMouseEventHandler( WX_VIEW_CONTROLS::onMotion ), nullptr, this );
93 m_parentPanel->Connect( wxEVT_MAGNIFY,
94 wxMouseEventHandler( WX_VIEW_CONTROLS::onMagnify ), nullptr, this );
95 m_parentPanel->Connect( wxEVT_MOUSEWHEEL,
96 wxMouseEventHandler( WX_VIEW_CONTROLS::onWheel ), nullptr, this );
97 m_parentPanel->Connect( wxEVT_MIDDLE_UP,
98 wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), nullptr, this );
99 m_parentPanel->Connect( wxEVT_MIDDLE_DOWN,
100 wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), nullptr, this );
101 m_parentPanel->Connect( wxEVT_LEFT_UP,
102 wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), nullptr, this );
103 m_parentPanel->Connect( wxEVT_LEFT_DOWN,
104 wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), nullptr, this );
105 m_parentPanel->Connect( wxEVT_RIGHT_UP,
106 wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), nullptr, this );
107 m_parentPanel->Connect( wxEVT_RIGHT_DOWN,
108 wxMouseEventHandler( WX_VIEW_CONTROLS::onButton ), nullptr, this );
109#if defined __WXMSW__
110 m_parentPanel->Connect( wxEVT_ENTER_WINDOW,
111 wxMouseEventHandler( WX_VIEW_CONTROLS::onEnter ), nullptr, this );
112#endif
113 m_parentPanel->Connect( wxEVT_LEAVE_WINDOW,
114 wxMouseEventHandler( WX_VIEW_CONTROLS::onLeave ), nullptr, this );
115 m_parentPanel->Connect( wxEVT_SCROLLWIN_THUMBTRACK,
116 wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), nullptr, this );
117 m_parentPanel->Connect( wxEVT_SCROLLWIN_PAGEUP,
118 wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), nullptr, this );
119 m_parentPanel->Connect( wxEVT_SCROLLWIN_PAGEDOWN,
120 wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), nullptr, this );
121
122 m_parentPanel->Connect( wxEVT_SCROLLWIN_BOTTOM,
123 wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), nullptr, this );
124 m_parentPanel->Connect( wxEVT_SCROLLWIN_TOP,
125 wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), nullptr, this );
126 m_parentPanel->Connect( wxEVT_SCROLLWIN_LINEUP,
127 wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), nullptr, this );
128 m_parentPanel->Connect( wxEVT_SCROLLWIN_LINEDOWN,
129 wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), nullptr, this );
130#if defined USE_MOUSE_CAPTURE
131 m_parentPanel->Connect( wxEVT_MOUSE_CAPTURE_LOST,
132 wxMouseEventHandler( WX_VIEW_CONTROLS::onCaptureLost ), nullptr, this );
133#endif
134
135#ifndef __WXOSX__
136 if( m_parentPanel->EnableTouchEvents( wxTOUCH_ZOOM_GESTURE | wxTOUCH_PAN_GESTURES ) )
137 {
138 m_parentPanel->Connect( wxEVT_GESTURE_ZOOM,
139 wxZoomGestureEventHandler( WX_VIEW_CONTROLS::onZoomGesture ),
140 nullptr, this );
141
142 m_parentPanel->Connect( wxEVT_GESTURE_PAN,
143 wxPanGestureEventHandler( WX_VIEW_CONTROLS::onPanGesture ), nullptr,
144 this );
145 }
146#endif
147
148 m_cursorWarped = false;
149
150 m_panTimer.SetOwner( this );
151 Connect( wxEVT_TIMER, wxTimerEventHandler( WX_VIEW_CONTROLS::onTimer ), nullptr, this );
152
156}
157
158
160{
161#if defined USE_MOUSE_CAPTURE
162 if( m_parentPanel->HasCapture() )
163 m_parentPanel->ReleaseMouse();
164#endif
165}
166
167
169{
171
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
249 if( m_settings.m_motionPanModifier != WXK_NONE
250 && wxGetKeyState( static_cast<wxKeyCode>( m_settings.m_motionPanModifier ) ) )
251 {
252 if( !m_metaPanning )
253 {
254 m_metaPanning = true;
255 m_metaPanStart = mousePos;
256 aEvent.StopPropagation();
257 }
258 else
259 {
260 VECTOR2D d = m_metaPanStart - mousePos;
261 m_metaPanStart = mousePos;
262 VECTOR2D delta = m_view->ToWorld( d, false );
264 aEvent.StopPropagation();
265 }
266
267 if( m_updateCursor )
268 m_cursorPos = GetClampedCoords( m_view->ToWorld( mousePos ) );
269 else
270 m_updateCursor = true;
271
272 aEvent.Skip();
273 return;
274 }
275 else
276 {
277 m_metaPanning = false;
278 }
279
281 handleCursorCapture( x, y );
282
284 isAutoPanning = handleAutoPanning( aEvent );
285
286 if( !isAutoPanning && aEvent.Dragging() )
287 {
288 if( m_state == DRAG_PANNING )
289 {
290 static bool justWarped = false;
291 int warpX = 0;
292 int warpY = 0;
293 wxSize parentSize = m_parentPanel->GetClientSize();
294
295 if( x < 0 )
296 {
297 warpX = parentSize.x;
298 }
299 else if( x >= parentSize.x )
300 {
301 warpX = -parentSize.x;
302 }
303
304 if( y < 0 )
305 {
306 warpY = parentSize.y;
307 }
308 else if( y >= parentSize.y )
309 {
310 warpY = -parentSize.y;
311 }
312
313 if( !justWarped )
314 {
315 VECTOR2D d = m_dragStartPoint - mousePos;
316 m_dragStartPoint = mousePos;
317 VECTOR2D delta = m_view->ToWorld( d, false );
319 aEvent.StopPropagation();
320 }
321
322 if( warpX || warpY )
323 {
324 if( !justWarped )
325 {
326 if( m_infinitePanWorks && KIPLATFORM::UI::WarpPointer( m_parentPanel, x + warpX, y + warpY ) )
327 {
328 m_dragStartPoint += VECTOR2D( warpX, warpY );
329 justWarped = true;
330 }
331 }
332 else
333 {
334 justWarped = false;
335 }
336 }
337 else
338 {
339 justWarped = false;
340 }
341 }
342 else if( m_state == DRAG_ZOOMING )
343 {
344 static bool justWarped = false;
345 int warpY = 0;
346 wxSize parentSize = m_parentPanel->GetClientSize();
347
348 if( y < 0 )
349 {
350 warpY = parentSize.y;
351 }
352 else if( y >= parentSize.y )
353 {
354 warpY = -parentSize.y;
355 }
356
357 if( !justWarped )
358 {
359 VECTOR2D d = m_dragStartPoint - mousePos;
360 m_dragStartPoint = mousePos;
361
362 double scale = exp( d.y * m_settings.m_zoomSpeed * 0.001 );
363
364 wxLogTrace( traceZoomScroll, wxString::Format( "dy: %f scale: %f", d.y, scale ) );
365
367 aEvent.StopPropagation();
368 }
369
370 if( warpY )
371 {
372 if( !justWarped )
373 {
375 m_dragStartPoint += VECTOR2D( 0, warpY );
376 justWarped = true;
377 }
378 else
379 justWarped = false;
380 }
381 else
382 {
383 justWarped = false;
384 }
385 }
386 }
387
388 if( m_updateCursor ) // do not update the cursor position if it was explicitly set
389 m_cursorPos = GetClampedCoords( m_view->ToWorld( mousePos ) );
390 else
391 m_updateCursor = true;
392
393 aEvent.Skip();
394}
395
396
397void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& aEvent )
398{
399 const double wheelPanSpeed = 0.001;
400 const int axis = aEvent.GetWheelAxis();
401
402 if( axis == wxMOUSE_WHEEL_HORIZONTAL && !m_settings.m_horizontalPan )
403 return;
404
405 // Pick the modifier, if any. Shift beats control beats alt, we don't support more than one.
406 int nMods = 0;
407 int modifiers = 0;
408
409 if( aEvent.ShiftDown() )
410 {
411 nMods += 1;
412 modifiers = WXK_SHIFT;
413 }
414
415 if( aEvent.ControlDown() )
416 {
417 nMods += 1;
418 modifiers = modifiers == 0 ? WXK_CONTROL : modifiers;
419 }
420
421 if( aEvent.AltDown() )
422 {
423 nMods += 1;
424 modifiers = modifiers == 0 ? WXK_ALT : modifiers;
425 }
426
427 // Zero or one modifier is view control
428 if( nMods <= 1 )
429 {
430 // Restrict zoom handling to the vertical axis, otherwise horizontal
431 // scrolling events (e.g. touchpads and some mice) end up interpreted
432 // as vertical scroll events and confuse the user.
433 if( modifiers == m_settings.m_scrollModifierZoom && axis == wxMOUSE_WHEEL_VERTICAL )
434 {
435 const int rotation = aEvent.GetWheelRotation() * ( m_settings.m_scrollReverseZoom ? -1 : 1 );
436 const double zoomScale = m_zoomController->GetScaleForRotation( rotation );
437
439 {
441 m_view->SetScale( m_view->GetScale() * zoomScale );
442 }
443 else
444 {
445 const VECTOR2D anchor = m_view->ToWorld( VECTOR2D( aEvent.GetX(), aEvent.GetY() ) );
446 m_view->SetScale( m_view->GetScale() * zoomScale, anchor );
447 }
448
449 // Refresh the zoom level and mouse position on message panel
450 // (mouse position has not changed, only the zoom level has changed):
451 refreshMouse( true );
452 }
453 else
454 {
455 // Scrolling
456 VECTOR2D scrollVec = m_view->ToWorld( m_view->GetScreenPixelSize(), false )
457 * ( (double) aEvent.GetWheelRotation() * wheelPanSpeed );
458 double scrollX = 0.0;
459 double scrollY = 0.0;
460 bool hReverse = false;
461
462 if( axis != wxMOUSE_WHEEL_HORIZONTAL )
464
465 if( axis == wxMOUSE_WHEEL_HORIZONTAL || modifiers == m_settings.m_scrollModifierPanH )
466 {
467 if( hReverse )
468 scrollX = scrollVec.x;
469 else
470 scrollX = ( axis == wxMOUSE_WHEEL_HORIZONTAL ) ? scrollVec.x : -scrollVec.x;
471 }
472 else
473 {
474 scrollY = -scrollVec.y;
475 }
476
477 VECTOR2D delta( scrollX, scrollY );
478
480 refreshMouse( true );
481 }
482
483 // Do not skip this event, otherwise wxWidgets will fire
484 // 3 wxEVT_SCROLLWIN_LINEUP or wxEVT_SCROLLWIN_LINEDOWN (normal wxWidgets behavior)
485 // and we do not want that.
486 }
487 else
488 {
489 // When we have multiple mods, forward it for tool handling
490 aEvent.Skip();
491 }
492}
493
494
495void WX_VIEW_CONTROLS::onMagnify( wxMouseEvent& aEvent )
496{
497 // Scale based on the magnification from our underlying magnification event.
498 VECTOR2D anchor = m_view->ToWorld( VECTOR2D( aEvent.GetX(), aEvent.GetY() ) );
499 m_view->SetScale( m_view->GetScale() * ( aEvent.GetMagnification() + 1.0f ), anchor );
500
501 aEvent.Skip();
502}
503
504
506{
507 m_state = aNewState;
508}
509
510
511void WX_VIEW_CONTROLS::onButton( wxMouseEvent& aEvent )
512{
513 switch( m_state )
514 {
515 case IDLE:
516 case AUTO_PANNING:
517 if( ( aEvent.MiddleDown() && m_settings.m_dragMiddle == MOUSE_DRAG_ACTION::PAN )
518 || ( aEvent.RightDown() && m_settings.m_dragRight == MOUSE_DRAG_ACTION::PAN ) )
519 {
520 m_dragStartPoint = VECTOR2D( aEvent.GetX(), aEvent.GetY() );
523
524#if defined USE_MOUSE_CAPTURE
525 if( !m_parentPanel->HasCapture() )
526 m_parentPanel->CaptureMouse();
527#endif
528 }
529 else if( ( aEvent.MiddleDown() && m_settings.m_dragMiddle == MOUSE_DRAG_ACTION::ZOOM )
530 || ( aEvent.RightDown() && m_settings.m_dragRight == MOUSE_DRAG_ACTION::ZOOM ) )
531 {
532 m_dragStartPoint = VECTOR2D( aEvent.GetX(), aEvent.GetY() );
535
536#if defined USE_MOUSE_CAPTURE
537 if( !m_parentPanel->HasCapture() )
538 m_parentPanel->CaptureMouse();
539#endif
540 }
541
542 if( aEvent.LeftUp() )
543 setState( IDLE ); // Stop autopanning when user release left mouse button
544
545 break;
546
547 case DRAG_ZOOMING:
548 case DRAG_PANNING:
549 if( aEvent.MiddleUp() || aEvent.LeftUp() || aEvent.RightUp() )
550 {
551 setState( IDLE );
553
554#if defined USE_MOUSE_CAPTURE
555 if( !m_settings.m_cursorCaptured && m_parentPanel->HasCapture() )
556 m_parentPanel->ReleaseMouse();
557#endif
558 }
559
560 break;
561 }
562
563 aEvent.Skip();
564}
565
566
567void WX_VIEW_CONTROLS::onEnter( wxMouseEvent& aEvent )
568{
569 // Avoid stealing focus from text controls
570 // This is particularly important for users using On-Screen-Keyboards
571 // They may move the mouse over the canvas to reach the keyboard
573 {
574 return;
575 }
576
577#if defined( _WIN32 ) || defined( __WXGTK__ )
578 // Win32 and some *nix WMs transmit mouse move and wheel events to all controls below the
579 // mouse regardless of focus. Forcing the focus here will cause the EDA FRAMES to immediately
580 // become the top level active window.
581 if( m_parentPanel->GetParent() != nullptr )
582 {
583 // this assumes the parent panel's parent is the eda window
585 {
587 }
588 }
589#else
591#endif
592}
593
594
595void WX_VIEW_CONTROLS::onLeave( wxMouseEvent& aEvent )
596{
597#if !defined USE_MOUSE_CAPTURE
598 onMotion( aEvent );
599#endif
600}
601
602
603void WX_VIEW_CONTROLS::onCaptureLost( wxMouseEvent& aEvent )
604{
605 // This method must be present to suppress the capture-lost assertion
606
607 // Set the flag to allow calling m_parentPanel->CaptureMouse()
608 // Note: One cannot call m_parentPanel->CaptureMouse() twice, this is not accepted
609 // by wxWidgets (MSW specific) so we need this guard
611}
612
613
614void WX_VIEW_CONTROLS::onTimer( wxTimerEvent& aEvent )
615{
616 switch( m_state )
617 {
618 case AUTO_PANNING:
619 {
621 {
622 setState( IDLE );
623 return;
624 }
625
626#ifdef __WXMSW__
627 // Hackfix: It's possible for the mouse to leave the canvas
628 // without triggering any leave events on windows
629 // Use a MSW only wx function
630 if( !m_parentPanel->IsMouseInWindow() )
631 {
632 m_panTimer.Stop();
633 setState( IDLE );
634 return;
635 }
636#endif
637
638 if( !m_parentPanel->HasFocus() && !m_parentPanel->StatusPopupHasFocus() )
639 {
640 setState( IDLE );
641 return;
642 }
643
644 double borderSize = std::min( m_settings.m_autoPanMargin * m_view->GetScreenPixelSize().x,
646
647 // When the mouse cursor is outside the area with no pan,
648 // m_panDirection is the dist to this area limit ( in pixels )
649 // It will be used also as pan value (the pan speed depends on this dist).
651
652 // When the mouse cursor is outside the area with no pan, the pan value
653 // is accelerated depending on the dist between the area and the cursor
654 float accel = 0.5f + ( m_settings.m_autoPanAcceleration / 5.0f );
655
656 // For a small mouse cursor dist to area, just use the distance.
657 // But for a dist > borderSize / 2, use an accelerated pan value
658
659 if( dir.EuclideanNorm() >= borderSize ) // far from area limits
660 dir = dir.Resize( borderSize * accel );
661 else if( dir.EuclideanNorm() > borderSize / 2 ) // Near from area limits
662 dir = dir.Resize( borderSize );
663
664 dir = m_view->ToWorld( dir, false );
665 m_view->SetCenter( m_view->GetCenter() + dir );
666
667 refreshMouse( true );
668
669 m_panTimer.Start();
670 }
671 break;
672
673 case IDLE: // Just remove unnecessary warnings
674 case DRAG_PANNING:
675 case DRAG_ZOOMING: break;
676 }
677}
678
679
680void WX_VIEW_CONTROLS::onZoomGesture( wxZoomGestureEvent& aEvent )
681{
682 if( aEvent.IsGestureStart() )
683 {
685 m_gestureLastPos = VECTOR2D( aEvent.GetPosition().x, aEvent.GetPosition().y );
686 }
687
688 VECTOR2D evtPos( aEvent.GetPosition().x, aEvent.GetPosition().y );
689 VECTOR2D deltaWorld = m_view->ToWorld( evtPos - m_gestureLastPos, false );
690
691 m_view->SetCenter( m_view->GetCenter() - deltaWorld );
692
693 m_view->SetScale( m_view->GetScale() * aEvent.GetZoomFactor() / m_gestureLastZoomFactor,
694 m_view->ToWorld( evtPos ) );
695
696 m_gestureLastZoomFactor = aEvent.GetZoomFactor();
697 m_gestureLastPos = evtPos;
698
699 refreshMouse( true );
700}
701
702
703void WX_VIEW_CONTROLS::onPanGesture( wxPanGestureEvent& aEvent )
704{
705 VECTOR2I screenDelta( aEvent.GetDelta().x, aEvent.GetDelta().y );
706 VECTOR2D deltaWorld = m_view->ToWorld( screenDelta, false );
707
708 m_view->SetCenter( m_view->GetCenter() - deltaWorld );
709
710 refreshMouse( true );
711}
712
713
714void WX_VIEW_CONTROLS::onScroll( wxScrollWinEvent& aEvent )
715{
716 const double linePanDelta = 0.05;
717 const double pagePanDelta = 0.5;
718
719 int type = aEvent.GetEventType();
720 int dir = aEvent.GetOrientation();
721
722 if( type == wxEVT_SCROLLWIN_THUMBTRACK )
723 {
724 auto center = m_view->GetCenter();
725 const auto& boundary = m_view->GetBoundary();
726
727 // Flip scroll direction in flipped view
728 const double xstart = ( m_view->IsMirroredX() ? boundary.GetRight() : boundary.GetLeft() );
729 const double xdelta = ( m_view->IsMirroredX() ? -1 : 1 );
730
731 if( dir == wxHORIZONTAL )
732 center.x = xstart + xdelta * ( aEvent.GetPosition() / m_scrollScale.x );
733 else
734 center.y = boundary.GetTop() + aEvent.GetPosition() / m_scrollScale.y;
735
737 }
738 else if( type == wxEVT_SCROLLWIN_THUMBRELEASE || type == wxEVT_SCROLLWIN_TOP || type == wxEVT_SCROLLWIN_BOTTOM )
739 {
740 // Do nothing on thumb release, we don't care about it.
741 // We don't have a concept of top or bottom in our viewport, so ignore those events.
742 }
743 else
744 {
745 double dist = 0;
746
747 if( type == wxEVT_SCROLLWIN_PAGEUP )
748 {
749 dist = pagePanDelta;
750 }
751 else if( type == wxEVT_SCROLLWIN_PAGEDOWN )
752 {
753 dist = -pagePanDelta;
754 }
755 else if( type == wxEVT_SCROLLWIN_LINEUP )
756 {
757 dist = linePanDelta;
758 }
759 else if( type == wxEVT_SCROLLWIN_LINEDOWN )
760 {
761 dist = -linePanDelta;
762 }
763 else
764 {
765 wxCHECK_MSG( false, /* void */, wxT( "Unhandled event type" ) );
766 }
767
768 VECTOR2D scroll = m_view->ToWorld( m_view->GetScreenPixelSize(), false ) * dist;
769
770 double scrollX = 0.0;
771 double scrollY = 0.0;
772
773 if( dir == wxHORIZONTAL )
774 scrollX = -scroll.x;
775 else
776 scrollY = -scroll.y;
777
778 VECTOR2D delta( scrollX, scrollY );
779
781 }
782
784}
785
786
788{
789#if defined USE_MOUSE_CAPTURE
790 // Note: for some reason, m_parentPanel->HasCapture() can be false even if CaptureMouse()
791 // was called (i.e. mouse was captured, so when need to test m_MouseCapturedLost to be
792 // sure a wxEVT_MOUSE_CAPTURE_LOST event was fired before. Otherwise wxMSW complains
793 // The IsModalDialogFocused is checked because it's possible to start a capture
794 // due to event ordering while a modal dialog was just opened, the mouse capture steels focus
795 // from the modal and causes odd behavior
796 if( aEnabled && !m_parentPanel->HasCapture() && m_parentPanel->m_MouseCapturedLost
798 {
799 m_parentPanel->CaptureMouse();
800
801 // Clear the flag to allow calling m_parentPanel->CaptureMouse()
802 // Calling it without calling ReleaseMouse() is not accepted by wxWidgets (MSW specific)
804 }
805 else if( !aEnabled && m_parentPanel->HasCapture() && m_state != DRAG_PANNING && m_state != DRAG_ZOOMING )
806 {
807 m_parentPanel->ReleaseMouse();
808
809 // Mouse is released, calling CaptureMouse() is allowed now:
811 }
812#endif
814}
815
816
818{
820 {
821 setState( IDLE );
822
823#if defined USE_MOUSE_CAPTURE
824 if( !m_settings.m_cursorCaptured && m_parentPanel->HasCapture() )
825 m_parentPanel->ReleaseMouse();
826#endif
827 }
828
829 m_metaPanning = false;
830}
831
832
833VECTOR2D WX_VIEW_CONTROLS::GetMousePosition( bool aWorldCoordinates ) const
834{
835 wxPoint msp = getMouseScreenPosition();
836 VECTOR2D screenPos( msp.x, msp.y );
837
838 return aWorldCoordinates ? GetClampedCoords( m_view->ToWorld( screenPos ) ) : screenPos;
839}
840
841
843{
844 GAL* gal = m_view->GetGAL();
845
846 if( aEnableSnapping && gal->GetGridSnapping() )
847 {
848 return gal->GetGridPoint( m_cursorPos );
849 }
850 else
851 {
852 return m_cursorPos;
853 }
854}
855
856
858{
860 {
862 }
863 else
864 {
865 return GetClampedCoords( GetRawCursorPosition( aEnableSnapping ) );
866 }
867}
868
869
870void WX_VIEW_CONTROLS::SetCursorPosition( const VECTOR2D& aPosition, bool aWarpView, bool aTriggeredByArrows,
871 long aArrowCommand )
872{
873 m_updateCursor = false;
874
875 VECTOR2D clampedPosition = GetClampedCoords( aPosition );
876
877 if( aTriggeredByArrows )
878 {
882 m_cursorWarped = false;
883 }
884 else
885 {
889 m_cursorWarped = true;
890 }
891
892 WarpMouseCursor( clampedPosition, true, aWarpView );
893 m_cursorPos = clampedPosition;
894}
895
896
897void WX_VIEW_CONTROLS::SetCrossHairCursorPosition( const VECTOR2D& aPosition, bool aWarpView = true )
898{
899 m_updateCursor = false;
900
901 VECTOR2D clampedPosition = GetClampedCoords( aPosition );
902
903 const VECTOR2I& screenSize = m_view->GetGAL()->GetScreenPixelSize();
904 BOX2I screen( VECTOR2I( 0, 0 ), screenSize );
905 VECTOR2D screenPos = m_view->ToScreen( clampedPosition );
906
907 if( aWarpView && !screen.Contains( screenPos ) )
908 m_view->SetCenter( clampedPosition );
909
910 m_cursorPos = clampedPosition;
911}
912
913
914void WX_VIEW_CONTROLS::WarpMouseCursor( const VECTOR2D& aPosition, bool aWorldCoordinates, bool aWarpView )
915{
916 if( aWorldCoordinates )
917 {
918 const VECTOR2I& screenSize = m_view->GetGAL()->GetScreenPixelSize();
919 BOX2I screen( VECTOR2I( 0, 0 ), screenSize );
920 VECTOR2D clampedPosition = GetClampedCoords( aPosition );
921 VECTOR2D screenPos = m_view->ToScreen( clampedPosition );
922
923 if( !screen.Contains( screenPos ) )
924 {
925 if( aWarpView )
926 {
927 m_view->SetCenter( clampedPosition );
928 KIPLATFORM::UI::WarpPointer( m_parentPanel, screenSize.x / 2, screenSize.y / 2 );
929 }
930 }
931 else
932 {
933 KIPLATFORM::UI::WarpPointer( m_parentPanel, screenPos.x, screenPos.y );
934 }
935 }
936 else
937 {
938 KIPLATFORM::UI::WarpPointer( m_parentPanel, aPosition.x, aPosition.y );
939 }
940
941 // If we are not refreshing because of mouse movement, don't set the modifiers because we
942 // are refreshing for keyboard movement, which uses the same modifiers for other actions
944}
945
946
948{
949 const VECTOR2I& screenSize = m_view->GetGAL()->GetScreenPixelSize();
950 VECTOR2D screenCenter( screenSize / 2 );
951
952 if( GetMousePosition( false ) != screenCenter )
953 {
954 VECTOR2D newCenter = GetCursorPosition();
955
956 if( KIPLATFORM::UI::WarpPointer( m_parentPanel, screenCenter.x, screenCenter.y ) )
957 {
958 m_view->SetCenter( newCenter );
959 m_dragStartPoint = screenCenter;
960 }
961 }
962}
963
964
966{
967 int border = std::min( m_settings.m_autoPanMargin * m_view->GetScreenPixelSize().x,
969 border += 2;
970
971 VECTOR2D topLeft( border, border );
972 VECTOR2D botRight( m_view->GetScreenPixelSize().x - border, m_view->GetScreenPixelSize().y - border );
973
974 topLeft = m_view->ToWorld( topLeft );
975 botRight = m_view->ToWorld( botRight );
976
977 VECTOR2D pos = GetMousePosition( true );
978
979 if( pos.x < topLeft.x )
980 pos.x = topLeft.x;
981 else if( pos.x > botRight.x )
982 pos.x = botRight.x;
983
984 if( pos.y < topLeft.y )
985 pos.y = topLeft.y;
986 else if( pos.y > botRight.y )
987 pos.y = botRight.y;
988
989 SetCursorPosition( pos, false, false, 0 );
990
991 if( aWarpMouseCursor )
992 WarpMouseCursor( pos, true );
993}
994
995
996bool WX_VIEW_CONTROLS::handleAutoPanning( const wxMouseEvent& aEvent )
997{
998 VECTOR2I p( aEvent.GetX(), aEvent.GetY() );
1000
1002 {
1003 // last cursor move event came from keyboard cursor control. If auto-panning is enabled
1004 // and the next position is inside the autopan zone, check if it really came from a mouse
1005 // event, otherwise disable autopan temporarily. Also temporarily disable autopan if the
1006 // cursor is in the autopan zone because the application warped the cursor.
1007
1008 m_cursorWarped = false;
1009 return true;
1010 }
1011
1012 m_cursorWarped = false;
1013
1014 // Compute areas where autopanning is active
1015 int borderStart = std::min( m_settings.m_autoPanMargin * m_view->GetScreenPixelSize().x,
1017 borderStart = std::max( borderStart, 2 );
1018 int borderEndX = m_view->GetScreenPixelSize().x - borderStart;
1019 int borderEndY = m_view->GetScreenPixelSize().y - borderStart;
1020
1021 if( p.x < borderStart )
1022 m_panDirection.x = -( borderStart - p.x );
1023 else if( p.x > borderEndX )
1024 m_panDirection.x = ( p.x - borderEndX );
1025 else
1026 m_panDirection.x = 0;
1027
1028 if( p.y < borderStart )
1029 m_panDirection.y = -( borderStart - p.y );
1030 else if( p.y > borderEndY )
1031 m_panDirection.y = ( p.y - borderEndY );
1032 else
1033 m_panDirection.y = 0;
1034
1035 bool borderHit = ( m_panDirection.x != 0 || m_panDirection.y != 0 );
1036
1037 switch( m_state )
1038 {
1039 case AUTO_PANNING:
1040 if( !borderHit )
1041 {
1042 m_panTimer.Stop();
1043 setState( IDLE );
1044
1045 return false;
1046 }
1047
1048 return true;
1049
1050 case IDLE:
1051 if( borderHit )
1052 {
1054 m_panTimer.Start( (int) ( 250.0 / 60.0 ), true );
1055
1056 return true;
1057 }
1058
1059 return false;
1060
1061 case DRAG_PANNING:
1062 case DRAG_ZOOMING: return false;
1063 }
1064
1065 wxCHECK_MSG( false, false, wxT( "This line should never be reached" ) );
1066
1067 return false;
1068}
1069
1070
1072{
1074 {
1075 bool warp = false;
1076 wxSize parentSize = m_parentPanel->GetClientSize();
1077
1078 if( x < 0 )
1079 {
1080 x = 0;
1081 warp = true;
1082 }
1083 else if( x >= parentSize.x )
1084 {
1085 x = parentSize.x - 1;
1086 warp = true;
1087 }
1088
1089 if( y < 0 )
1090 {
1091 y = 0;
1092 warp = true;
1093 }
1094 else if( y >= parentSize.y )
1095 {
1096 y = parentSize.y - 1;
1097 warp = true;
1098 }
1099
1100 if( warp )
1102 }
1103}
1104
1105
1106void WX_VIEW_CONTROLS::refreshMouse( bool aSetModifiers )
1107{
1108 // Notify tools that the cursor position has changed in the world coordinates
1109 wxMouseEvent moveEvent( EVT_REFRESH_MOUSE );
1110 wxPoint msp = getMouseScreenPosition();
1111 moveEvent.SetX( msp.x );
1112 moveEvent.SetY( msp.y );
1113
1114 if( aSetModifiers )
1115 {
1116 // Set the modifiers state
1117 moveEvent.SetControlDown( wxGetKeyState( WXK_CONTROL ) );
1118 moveEvent.SetShiftDown( wxGetKeyState( WXK_SHIFT ) );
1119 moveEvent.SetAltDown( wxGetKeyState( WXK_ALT ) );
1120 }
1121
1122 m_cursorPos = GetClampedCoords( m_view->ToWorld( VECTOR2D( msp.x, msp.y ) ) );
1123 wxPostEvent( m_parentPanel, moveEvent );
1124}
1125
1126
1128{
1129 wxPoint msp = KIPLATFORM::UI::GetMousePosition();
1130 m_parentPanel->ScreenToClient( &msp.x, &msp.y );
1131 return msp;
1132}
1133
1134
1136{
1137 const BOX2D viewport = m_view->GetViewport();
1138 const BOX2D& boundary = m_view->GetBoundary();
1139
1140 m_scrollScale.x = 2e3 / viewport.GetWidth(); // TODO it does not have to be updated so often
1141 m_scrollScale.y = 2e3 / viewport.GetHeight();
1142 VECTOR2I newScroll( ( viewport.Centre().x - boundary.GetLeft() ) * m_scrollScale.x,
1143 ( viewport.Centre().y - boundary.GetTop() ) * m_scrollScale.y );
1144
1145 // We add the width of the scroll bar thumb to the range because the scroll range is given by
1146 // the full bar while the position is given by the left/top position of the thumb
1147 VECTOR2I newRange( m_scrollScale.x * boundary.GetWidth() + m_parentPanel->GetScrollThumb( wxSB_HORIZONTAL ),
1148 m_scrollScale.y * boundary.GetHeight() + m_parentPanel->GetScrollThumb( wxSB_VERTICAL ) );
1149
1150 // Flip scroll direction in flipped view
1151 if( m_view->IsMirroredX() )
1152 newScroll.x = ( boundary.GetRight() - viewport.Centre().x ) * m_scrollScale.x;
1153
1154 // Adjust scrollbars only if it is needed. Otherwise there are cases when canvas is continuously
1155 // refreshed (Windows)
1156 if( m_scrollPos != newScroll || newRange.x != m_parentPanel->GetScrollRange( wxSB_HORIZONTAL )
1157 || newRange.y != m_parentPanel->GetScrollRange( wxSB_VERTICAL ) )
1158 {
1159 m_parentPanel->SetScrollbars( 1, 1, newRange.x, newRange.y, newScroll.x, newScroll.y, true );
1160 m_scrollPos = newScroll;
1161
1162#if !defined( __APPLE__ ) && !defined( WIN32 )
1163 // Trigger a mouse refresh to get the canvas update in GTK (re-draws the scrollbars).
1164 // Note that this causes an infinite loop on OSX and Windows (in certain cases) as it
1165 // generates a paint event.
1166 refreshMouse( false );
1167#endif
1168 }
1169}
1170
1171
1172void WX_VIEW_CONTROLS::ForceCursorPosition( bool aEnabled, const VECTOR2D& aPosition )
1173{
1174 VECTOR2D clampedPosition = GetClampedCoords( aPosition );
1175
1177 m_settings.m_forcedPosition = clampedPosition;
1178}
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:66
double GetScale() const
Definition: view.h:276
BOX2D GetViewport() const
Return the current viewport visible area rectangle.
Definition: view.cpp:530
const VECTOR2D & GetCenter() const
Return the center point of this VIEW (in world space coordinates).
Definition: view.h:346
virtual void SetScale(double aScale, VECTOR2D aAnchor={ 0, 0 })
Set the scaling factor, zooming around a given anchor point.
Definition: view.cpp:570
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:486
const VECTOR2I & GetScreenPixelSize() const
Return the size of the our rendering area in pixels.
Definition: view.cpp:1202
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:202
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:467
bool IsMirroredX() const
Return true if view is flipped across the X axis.
Definition: view.h:250
const BOX2D & GetBoundary() const
Definition: view.h:305
void SetCenter(const VECTOR2D &aCenter)
Set the center point of the VIEW (i.e.
Definition: view.cpp:596
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.
VECTOR2D m_metaPanStart
Last mouse position when panning via the meta key.
bool m_metaPanning
True if we are panning via the meta key.
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:395
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition: pgm_base.cpp:565
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: eda_group.h:33
wxPoint GetMousePosition()
Returns the mouse position in screen coordinates.
Definition: wxgtk/ui.cpp:683
void InfiniteDragReleaseWindow()
On Wayland, allows the cursor to freely move again after a drag (see InfiniteDragPrepareWindow).
Definition: wxgtk/ui.cpp:677
bool WarpPointer(wxWindow *aWindow, int aX, int aY)
Move the mouse cursor to a specific position relative to the window.
Definition: wxgtk/ui.cpp:316
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:670
KICOMMON_API bool IsInputControlFocused(wxWindow *aFocus=nullptr)
Check if a input control has focus.
Definition: ui_common.cpp:271
KICOMMON_API bool IsModalDialogFocused()
Definition: ui_common.cpp:326
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:902
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.
int m_motionPanModifier
What modifier key pans the view when the mouse moves with it held.
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
VECTOR2I center
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.