Break zoom control into a self-contained controller
This is done to avoid a big chunk of conditionally-compiled code in the middle of the event function. Also separates the zoom logic from the WX_VIEW_CONTROLS object and isolates it in a separate class behind a clearer interface. Add some simple tests for sane steps on GTK+3-sized scroll steps.
This commit is contained in:
parent
90139d540c
commit
5a0318968f
|
@ -243,6 +243,7 @@ Some available masks:
|
||||||
* `GAL_CACHED_CONTAINER`
|
* `GAL_CACHED_CONTAINER`
|
||||||
* `PNS`
|
* `PNS`
|
||||||
* `CN`
|
* `CN`
|
||||||
|
* `SCROLL_ZOOM` - for the scroll-wheel zooming logic in GAL
|
||||||
* Plugin-specific (including "standard" KiCad formats):
|
* Plugin-specific (including "standard" KiCad formats):
|
||||||
* `3D_CACHE`
|
* `3D_CACHE`
|
||||||
* `3D_SG`
|
* `3D_SG`
|
||||||
|
|
|
@ -46,6 +46,7 @@ set( GAL_SRCS
|
||||||
view/view_controls.cpp
|
view/view_controls.cpp
|
||||||
view/view_overlay.cpp
|
view/view_overlay.cpp
|
||||||
view/wx_view_controls.cpp
|
view/wx_view_controls.cpp
|
||||||
|
view/zoom_controller.cpp
|
||||||
|
|
||||||
# OpenGL GAL
|
# OpenGL GAL
|
||||||
gal/opengl/opengl_gal.cpp
|
gal/opengl/opengl_gal.cpp
|
||||||
|
|
|
@ -27,11 +27,6 @@
|
||||||
* @brief wxLogTrace helper implementation.
|
* @brief wxLogTrace helper implementation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <wx/defs.h>
|
|
||||||
#include <wx/string.h>
|
|
||||||
#include <wx/event.h>
|
|
||||||
#include <wx/arrstr.h>
|
|
||||||
|
|
||||||
#include <trace_helpers.h>
|
#include <trace_helpers.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,6 +43,7 @@ const wxChar* const traceAutoSave = wxT( "KICAD_AUTOSAVE" );
|
||||||
const wxChar* const tracePathsAndFiles = wxT( "KICAD_PATHS_AND_FILES" );
|
const wxChar* const tracePathsAndFiles = wxT( "KICAD_PATHS_AND_FILES" );
|
||||||
const wxChar* const traceLocale = wxT( "KICAD_LOCALE" );
|
const wxChar* const traceLocale = wxT( "KICAD_LOCALE" );
|
||||||
const wxChar* const traceScreen = wxT( "KICAD_SCREEN" );
|
const wxChar* const traceScreen = wxT( "KICAD_SCREEN" );
|
||||||
|
const wxChar* const traceZoomScroll = wxT( "KICAD_ZOOM_SCROLL" );
|
||||||
|
|
||||||
|
|
||||||
wxString dump( const wxArrayString& aArray )
|
wxString dump( const wxArrayString& aArray )
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include <view/view.h>
|
#include <view/view.h>
|
||||||
#include <view/wx_view_controls.h>
|
#include <view/wx_view_controls.h>
|
||||||
|
#include <view/zoom_controller.h>
|
||||||
#include <gal/graphics_abstraction_layer.h>
|
#include <gal/graphics_abstraction_layer.h>
|
||||||
#include <tool/tool_dispatcher.h>
|
#include <tool/tool_dispatcher.h>
|
||||||
|
|
||||||
|
@ -35,6 +36,20 @@ using namespace KIGFX;
|
||||||
|
|
||||||
const wxEventType WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE = wxNewEventType();
|
const wxEventType WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE = wxNewEventType();
|
||||||
|
|
||||||
|
|
||||||
|
static std::unique_ptr<ZOOM_CONTROLLER> GetZoomControllerForPlatform()
|
||||||
|
{
|
||||||
|
#ifdef __WXMAC__
|
||||||
|
// On Apple pointer devices, wheel events occur frequently and with
|
||||||
|
// smaller rotation values. For those devices, let's handle zoom
|
||||||
|
// based on the rotation amount rather than the time difference.
|
||||||
|
return std::make_unique<CONSTANT_ZOOM_CONTROLLER>( CONSTANT_ZOOM_CONTROLLER::MAC_SCALE );
|
||||||
|
#else
|
||||||
|
return std::make_unique<ACCELERATING_ZOOM_CONTROLLER>( 500 );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, wxScrolledCanvas* aParentPanel ) :
|
WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, wxScrolledCanvas* aParentPanel ) :
|
||||||
VIEW_CONTROLS( aView ), m_state( IDLE ), m_parentPanel( aParentPanel ),
|
VIEW_CONTROLS( aView ), m_state( IDLE ), m_parentPanel( aParentPanel ),
|
||||||
m_scrollScale( 1.0, 1.0 ), m_cursorPos( 0, 0 ), m_updateCursor( true )
|
m_scrollScale( 1.0, 1.0 ), m_cursorPos( 0, 0 ), m_updateCursor( true )
|
||||||
|
@ -72,12 +87,19 @@ WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, wxScrolledCanvas* aParentPanel
|
||||||
m_parentPanel->Connect( wxEVT_SCROLLWIN_PAGEDOWN,
|
m_parentPanel->Connect( wxEVT_SCROLLWIN_PAGEDOWN,
|
||||||
wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), NULL, this );
|
wxScrollWinEventHandler( WX_VIEW_CONTROLS::onScroll ), NULL, this );
|
||||||
|
|
||||||
|
m_zoomController = GetZoomControllerForPlatform();
|
||||||
|
|
||||||
m_panTimer.SetOwner( this );
|
m_panTimer.SetOwner( this );
|
||||||
this->Connect( wxEVT_TIMER,
|
this->Connect( wxEVT_TIMER,
|
||||||
wxTimerEventHandler( WX_VIEW_CONTROLS::onTimer ), NULL, this );
|
wxTimerEventHandler( WX_VIEW_CONTROLS::onTimer ), NULL, this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WX_VIEW_CONTROLS::~WX_VIEW_CONTROLS()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
|
void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
|
||||||
{
|
{
|
||||||
bool isAutoPanning = false;
|
bool isAutoPanning = false;
|
||||||
|
@ -110,7 +132,6 @@ void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
|
||||||
void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& aEvent )
|
void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& aEvent )
|
||||||
{
|
{
|
||||||
const double wheelPanSpeed = 0.001;
|
const double wheelPanSpeed = 0.001;
|
||||||
const double zoomLevelScale = 1.2; // The minimal step value when changing the current zoom level
|
|
||||||
|
|
||||||
// mousewheelpan disabled:
|
// mousewheelpan disabled:
|
||||||
// wheel + ctrl -> horizontal scrolling;
|
// wheel + ctrl -> horizontal scrolling;
|
||||||
|
@ -153,46 +174,8 @@ void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& aEvent )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Zooming
|
int rotation = aEvent.GetWheelRotation();
|
||||||
wxLongLong timeStamp = wxGetLocalTimeMillis();
|
double zoomScale = m_zoomController->GetScaleForRotation( rotation );
|
||||||
double timeDiff = timeStamp.ToDouble() - m_timeStamp.ToDouble();
|
|
||||||
int rotation = aEvent.GetWheelRotation();
|
|
||||||
double zoomScale = 1.0;
|
|
||||||
|
|
||||||
#ifdef __WXMAC__
|
|
||||||
// On Apple pointer devices, wheel events occur frequently and with
|
|
||||||
// smaller rotation values. For those devices, let's handle zoom
|
|
||||||
// based on the rotation amount rather than the time difference.
|
|
||||||
|
|
||||||
// Unused
|
|
||||||
( void )timeDiff;
|
|
||||||
|
|
||||||
rotation = ( rotation > 0 ) ? std::min( rotation , 100 )
|
|
||||||
: std::max( rotation , -100 );
|
|
||||||
|
|
||||||
double dscale = rotation * 0.01;
|
|
||||||
zoomScale = ( rotation > 0 ) ? (1 + dscale) : 1/(1 - dscale);
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
m_timeStamp = timeStamp;
|
|
||||||
|
|
||||||
// Set scaling speed depending on scroll wheel event interval
|
|
||||||
if( timeDiff < 500 && timeDiff > 0 )
|
|
||||||
{
|
|
||||||
zoomScale = 2.05 - timeDiff / 500;
|
|
||||||
|
|
||||||
// be sure zoomScale value is significant
|
|
||||||
zoomScale = std::max( zoomScale, zoomLevelScale );
|
|
||||||
|
|
||||||
if( rotation < 0 )
|
|
||||||
zoomScale = 1.0 / zoomScale;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
zoomScale = ( rotation > 0 ) ? zoomLevelScale : 1/zoomLevelScale;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if( IsCursorWarpingEnabled() )
|
if( IsCursorWarpingEnabled() )
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
|
||||||
|
* Copyright (C) 2013-2015 CERN
|
||||||
|
* Copyright (C) 2012-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||||
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <view/zoom_controller.h>
|
||||||
|
|
||||||
|
#include <trace_helpers.h>
|
||||||
|
|
||||||
|
#include <wx/log.h>
|
||||||
|
#include <wx/time.h> // For timestamping events
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
using namespace KIGFX;
|
||||||
|
|
||||||
|
|
||||||
|
ACCELERATING_ZOOM_CONTROLLER::ACCELERATING_ZOOM_CONTROLLER( unsigned aAccTimeout )
|
||||||
|
: m_lastTimeStamp( getTimeStamp() ), m_accTimeout( aAccTimeout )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double ACCELERATING_ZOOM_CONTROLLER::GetScaleForRotation( int aRotation )
|
||||||
|
{
|
||||||
|
// The minimal step value when changing the current zoom level
|
||||||
|
const double zoomLevelScale = 1.2;
|
||||||
|
|
||||||
|
const auto timeStamp = getTimeStamp();
|
||||||
|
auto timeDiff = timeStamp - m_lastTimeStamp;
|
||||||
|
|
||||||
|
m_lastTimeStamp = timeStamp;
|
||||||
|
|
||||||
|
wxLogTrace( traceZoomScroll,
|
||||||
|
wxString::Format( "Rot %d, time diff: %ldms", aRotation, timeDiff ) );
|
||||||
|
|
||||||
|
double zoomScale;
|
||||||
|
|
||||||
|
// Set scaling speed depending on scroll wheel event interval
|
||||||
|
if( timeDiff < m_accTimeout && timeDiff > 0 )
|
||||||
|
{
|
||||||
|
zoomScale = 2.05 - timeDiff / m_accTimeout;
|
||||||
|
|
||||||
|
// be sure zoomScale value is significant
|
||||||
|
zoomScale = std::max( zoomScale, zoomLevelScale );
|
||||||
|
|
||||||
|
if( aRotation < 0 )
|
||||||
|
zoomScale = 1.0 / zoomScale;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
zoomScale = ( aRotation > 0 ) ? zoomLevelScale : 1 / zoomLevelScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxLogTrace( traceZoomScroll, wxString::Format( " Zoom factor: %f", zoomScale ) );
|
||||||
|
|
||||||
|
return zoomScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double ACCELERATING_ZOOM_CONTROLLER::getTimeStamp() const
|
||||||
|
{
|
||||||
|
return wxGetLocalTimeMillis().ToDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CONSTANT_ZOOM_CONTROLLER::CONSTANT_ZOOM_CONTROLLER( double aScale ) : m_scale( aScale )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double CONSTANT_ZOOM_CONTROLLER::GetScaleForRotation( int aRotation )
|
||||||
|
{
|
||||||
|
wxLogTrace( traceZoomScroll, wxString::Format( "Rot %d", aRotation ) );
|
||||||
|
|
||||||
|
aRotation = ( aRotation > 0 ) ? std::min( aRotation, 100 ) : std::max( aRotation, -100 );
|
||||||
|
|
||||||
|
double dscale = aRotation * m_scale;
|
||||||
|
|
||||||
|
double zoom_scale = ( aRotation > 0 ) ? ( 1 + dscale ) : 1 / ( 1 - dscale );
|
||||||
|
|
||||||
|
wxLogTrace( traceZoomScroll, wxString::Format( " Zoom factor: %f", zoom_scale ) );
|
||||||
|
|
||||||
|
return zoom_scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
// need these until C++17
|
||||||
|
constexpr double CONSTANT_ZOOM_CONTROLLER::MAC_SCALE;
|
||||||
|
constexpr double CONSTANT_ZOOM_CONTROLLER::GTK3_SCALE;
|
|
@ -30,6 +30,10 @@
|
||||||
#ifndef _TRACE_HELPERS_H_
|
#ifndef _TRACE_HELPERS_H_
|
||||||
#define _TRACE_HELPERS_H_
|
#define _TRACE_HELPERS_H_
|
||||||
|
|
||||||
|
#include <wx/arrstr.h>
|
||||||
|
#include <wx/event.h>
|
||||||
|
#include <wx/string.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup trace_env_vars Trace Environment Variables
|
* @defgroup trace_env_vars Trace Environment Variables
|
||||||
*
|
*
|
||||||
|
@ -58,7 +62,6 @@ extern const wxChar* const traceFindReplace;
|
||||||
*/
|
*/
|
||||||
extern const wxChar* const kicadTraceCoords;
|
extern const wxChar* const kicadTraceCoords;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flag to enable wxKeyEvent debug tracing.
|
* Flag to enable wxKeyEvent debug tracing.
|
||||||
*/
|
*/
|
||||||
|
@ -109,6 +112,12 @@ extern const wxChar* const traceLocale;
|
||||||
*/
|
*/
|
||||||
extern const wxChar* const traceScreen;
|
extern const wxChar* const traceScreen;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag to enable debug output of zoom-scrolling calculations in
|
||||||
|
* #KIGFX::ZOOM_CONTROLER and derivatives.
|
||||||
|
*/
|
||||||
|
extern const wxChar* const traceZoomScroll;
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -35,10 +35,15 @@
|
||||||
|
|
||||||
#include <view/view_controls.h>
|
#include <view/view_controls.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class EDA_DRAW_PANEL_GAL;
|
class EDA_DRAW_PANEL_GAL;
|
||||||
|
|
||||||
namespace KIGFX
|
namespace KIGFX
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class ZOOM_CONTROLLER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class WX_VIEW_CONTROLS
|
* Class WX_VIEW_CONTROLS
|
||||||
* is a specific implementation of class VIEW_CONTROLS for wxWidgets library.
|
* is a specific implementation of class VIEW_CONTROLS for wxWidgets library.
|
||||||
|
@ -47,8 +52,7 @@ class WX_VIEW_CONTROLS : public VIEW_CONTROLS, public wxEvtHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WX_VIEW_CONTROLS( VIEW* aView, wxScrolledCanvas* aParentPanel );
|
WX_VIEW_CONTROLS( VIEW* aView, wxScrolledCanvas* aParentPanel );
|
||||||
virtual ~WX_VIEW_CONTROLS()
|
virtual ~WX_VIEW_CONTROLS();
|
||||||
{}
|
|
||||||
|
|
||||||
/// Handler functions
|
/// Handler functions
|
||||||
void onWheel( wxMouseEvent& aEvent );
|
void onWheel( wxMouseEvent& aEvent );
|
||||||
|
@ -146,9 +150,6 @@ private:
|
||||||
/// Current direction of panning (only autopanning mode)
|
/// Current direction of panning (only autopanning mode)
|
||||||
VECTOR2D m_panDirection;
|
VECTOR2D m_panDirection;
|
||||||
|
|
||||||
/// Used for determining time intervals between scroll & zoom events
|
|
||||||
wxLongLong m_timeStamp;
|
|
||||||
|
|
||||||
/// Timer repsonsible for handling autopanning
|
/// Timer repsonsible for handling autopanning
|
||||||
wxTimer m_panTimer;
|
wxTimer m_panTimer;
|
||||||
|
|
||||||
|
@ -163,6 +164,9 @@ private:
|
||||||
|
|
||||||
/// Flag deciding whether the cursor position should be calculated using the mouse position
|
/// Flag deciding whether the cursor position should be calculated using the mouse position
|
||||||
bool m_updateCursor;
|
bool m_updateCursor;
|
||||||
|
|
||||||
|
/// a ZOOM_CONTROLLER that determines zoom steps. This is platform-specific.
|
||||||
|
std::unique_ptr<ZOOM_CONTROLLER> m_zoomController;
|
||||||
};
|
};
|
||||||
} // namespace KIGFX
|
} // namespace KIGFX
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013-2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file zoom_control.h
|
||||||
|
* @brief ZOOM_CONTROLLER class definition.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ZOOM_CONTROLLER_H
|
||||||
|
#define __ZOOM_CONTROLLER_H
|
||||||
|
|
||||||
|
|
||||||
|
namespace KIGFX
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class that handles the response of the zoom scale to external inputs
|
||||||
|
*/
|
||||||
|
class ZOOM_CONTROLLER
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~ZOOM_CONTROLLER() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the scale factor produced by a given mousewheel rotation
|
||||||
|
* @param aRotation rotation of the mouse wheel (this comes from
|
||||||
|
* wxMouseEvent::GetWheelRotation())
|
||||||
|
* @return the scale factor to scroll by
|
||||||
|
*/
|
||||||
|
virtual double GetScaleForRotation( int aRotation ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class that zooms faster if scroll events happen very close together.
|
||||||
|
*/
|
||||||
|
class ACCELERATING_ZOOM_CONTROLLER : public ZOOM_CONTROLLER
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @param aAccTimeout the timeout - if a scoll happens within this timeframe,
|
||||||
|
* the zoom will be faster
|
||||||
|
*/
|
||||||
|
ACCELERATING_ZOOM_CONTROLLER( unsigned aAccTimeout );
|
||||||
|
|
||||||
|
double GetScaleForRotation( int aRotation ) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* @return the timestamp of an event at the current time. Monotonic.
|
||||||
|
*/
|
||||||
|
double getTimeStamp() const;
|
||||||
|
|
||||||
|
/// The timestamp of the last event
|
||||||
|
double m_lastTimeStamp;
|
||||||
|
/// The timeout value
|
||||||
|
unsigned m_accTimeout;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A ZOOM_CONTROLLER that zooms by a fixed factor based only on the magnitude
|
||||||
|
* of the scroll wheel rotation.
|
||||||
|
*/
|
||||||
|
class CONSTANT_ZOOM_CONTROLLER : public ZOOM_CONTROLLER
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @param aScale a scaling parameter that adjusts the magnitude of the
|
||||||
|
* scroll. This factor might be dependent on the platform for comfort.
|
||||||
|
*/
|
||||||
|
CONSTANT_ZOOM_CONTROLLER( double aScale );
|
||||||
|
|
||||||
|
double GetScaleForRotation( int aRotation ) override;
|
||||||
|
|
||||||
|
/// A suitable (magic) scale factor for GTK3 systems
|
||||||
|
static constexpr double GTK3_SCALE = 0.001;
|
||||||
|
|
||||||
|
/// A suitable (magic) scale factor for Mac systems
|
||||||
|
static constexpr double MAC_SCALE = 0.01;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// The scale factor set by the constructor.
|
||||||
|
double m_scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace KIGFX
|
||||||
|
|
||||||
|
#endif
|
|
@ -41,6 +41,8 @@ add_executable( qa_common
|
||||||
test_utf8.cpp
|
test_utf8.cpp
|
||||||
|
|
||||||
geometry/test_fillet.cpp
|
geometry/test_fillet.cpp
|
||||||
|
|
||||||
|
view/test_zoom_controller.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 KiCad Developers, see CHANGELOG.TXT for contributors.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/test/test_case_template.hpp>
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
|
#include <view/zoom_controller.h>
|
||||||
|
|
||||||
|
|
||||||
|
// All these tests are of a class in KIGFX
|
||||||
|
using namespace KIGFX;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declares a struct as the Boost test fixture.
|
||||||
|
*/
|
||||||
|
BOOST_AUTO_TEST_SUITE( ZoomController )
|
||||||
|
|
||||||
|
|
||||||
|
struct CONST_ZOOM_CASE
|
||||||
|
{
|
||||||
|
double scale_factor;
|
||||||
|
int scroll_amount;
|
||||||
|
double exp_zoom_in;
|
||||||
|
double exp_zoom_out;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some "sane" examples for steps, scale factors and results.
|
||||||
|
* These should be actual examples that could be encountered
|
||||||
|
*
|
||||||
|
* TODO: Add more cases for, eg, Mac
|
||||||
|
*/
|
||||||
|
static const std::vector<CONST_ZOOM_CASE> const_zoom_cases = {
|
||||||
|
// A single scroll step on a GTK3 Linux system
|
||||||
|
// 120 is the standard wheel delta, so it's what you might expect
|
||||||
|
// from a single scroll wheel detent.
|
||||||
|
{ CONSTANT_ZOOM_CONTROLLER::GTK3_SCALE, 120, 1.1, 1 / 1.1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check basic setting and getting of values
|
||||||
|
*/
|
||||||
|
BOOST_AUTO_TEST_CASE( ConstController )
|
||||||
|
{
|
||||||
|
// How close we need to be (not very, this is a subjective thing anyway)
|
||||||
|
const double tol_percent = 10;
|
||||||
|
|
||||||
|
double scale_for_step;
|
||||||
|
|
||||||
|
for( const auto& c : const_zoom_cases )
|
||||||
|
{
|
||||||
|
CONSTANT_ZOOM_CONTROLLER zoom_ctrl( c.scale_factor );
|
||||||
|
|
||||||
|
scale_for_step = zoom_ctrl.GetScaleForRotation( c.scroll_amount );
|
||||||
|
BOOST_CHECK_CLOSE( scale_for_step, c.exp_zoom_in, tol_percent );
|
||||||
|
|
||||||
|
scale_for_step = zoom_ctrl.GetScaleForRotation( -c.scroll_amount );
|
||||||
|
BOOST_CHECK_CLOSE( scale_for_step, c.exp_zoom_out, tol_percent );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Testing the accelerated version without making a very slow test is a little
|
||||||
|
* tricky and would need a mock timestamping interface, which complicates the
|
||||||
|
* real interface a bit and does not really seem worth the effort.
|
||||||
|
*/
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
Loading…
Reference in New Issue