Added autopanning functionality to WX_VIEW_CONTROLS.

This commit is contained in:
Maciej Suminski 2013-08-22 18:42:53 +02:00
parent 875c0f7062
commit 961a8c2eca
3 changed files with 170 additions and 43 deletions

View File

@ -24,7 +24,6 @@
*/
#include <wx/wx.h>
#include <wx/window.h>
#include <view/view.h>
#include <view/wx_view_controls.h>
@ -33,9 +32,11 @@ using namespace KiGfx;
WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, wxWindow* aParentPanel ) :
VIEW_CONTROLS( aView ),
m_state( IDLE ),
m_autoPanEnabled( false ),
m_grabMouse( false ),
m_autoPanMargin( 0.1 ),
m_autoPanSpeed( 0.15 ),
m_autoPanCornerRatio( 0.1 ),
m_parentPanel( aParentPanel )
{
m_parentPanel->Connect( wxEVT_MOTION, wxMouseEventHandler(
@ -50,22 +51,40 @@ WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, wxWindow* aParentPanel ) :
m_parentPanel->Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler(
WX_VIEW_CONTROLS::onEnter ), NULL, this );
#endif
m_panTimer.SetOwner( this );
this->Connect( wxEVT_TIMER, wxTimerEventHandler(
WX_VIEW_CONTROLS::onTimer ), NULL, this );
}
void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
{
if( aEvent.Dragging() && m_isDragPanning )
{
VECTOR2D mousePoint( aEvent.GetX(), aEvent.GetY() );
if( aEvent.Dragging() )
{
if( m_state == DRAG_PANNING )
{
VECTOR2D d = m_dragStartPoint - mousePoint;
VECTOR2D delta = m_view->ToWorld( d, false );
m_view->SetCenter( m_lookStartPoint + delta );
m_parentPanel->Refresh();
aEvent.StopPropagation();
}
else
{
aEvent.Skip();
}
}
else
{
if( m_autoPanEnabled )
handleAutoPanning( aEvent );
}
aEvent.Skip();
// DeletePendingEvents();
}
@ -122,16 +141,25 @@ void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& aEvent )
void WX_VIEW_CONTROLS::onButton( wxMouseEvent& aEvent )
{
switch( m_state )
{
case IDLE:
case AUTO_PANNING:
if( aEvent.MiddleDown() )
{
m_isDragPanning = true;
m_dragStartPoint = VECTOR2D( aEvent.GetX(), aEvent.GetY() );
m_lookStartPoint = m_view->GetCenter();
m_state = DRAG_PANNING;
}
else if( aEvent.MiddleUp() )
break;
case DRAG_PANNING:
if( aEvent.MiddleUp() )
{
m_isDragPanning = false;
m_state = IDLE;
}
break;
};
aEvent.Skip();
}
@ -141,3 +169,90 @@ void WX_VIEW_CONTROLS::onEnter( wxMouseEvent& aEvent )
{
m_parentPanel->SetFocus();
}
void WX_VIEW_CONTROLS::onTimer( wxTimerEvent& aEvent )
{
switch( m_state )
{
case AUTO_PANNING:
{
double borderSize = std::min( m_autoPanMargin * m_view->GetScreenPixelSize().x,
m_autoPanMargin * m_view->GetScreenPixelSize().y );
VECTOR2D dir( m_panDirection );
if( dir.EuclideanNorm() > borderSize )
dir = dir.Resize( borderSize );
dir = m_view->ToWorld( dir, false );
// wxLogDebug( "AutoPanningTimer: dir %.4f %.4f sped %.4f", dir.x, dir.y, m_autoPanSpeed );
m_view->SetCenter( m_view->GetCenter() + dir * m_autoPanSpeed );
wxPaintEvent redrawEvent;
wxPostEvent( m_parentPanel, redrawEvent );
}
break;
}
DeletePendingEvents();
m_panTimer.DeletePendingEvents();
}
void WX_VIEW_CONTROLS::SetGrabMouse( bool aEnabled )
{
m_grabMouse = aEnabled;
if( aEnabled )
m_parentPanel->CaptureMouse();
else
m_parentPanel->ReleaseMouse();
}
void WX_VIEW_CONTROLS::handleAutoPanning( wxMouseEvent& aEvent )
{
VECTOR2D p( aEvent.GetX(), aEvent.GetY() );
// Compute areas where autopanning is active
double borderStart = std::min( m_autoPanMargin * m_view->GetScreenPixelSize().x,
m_autoPanMargin * m_view->GetScreenPixelSize().y );
double borderEndX = m_view->GetScreenPixelSize().x - borderStart;
double borderEndY = m_view->GetScreenPixelSize().y - borderStart;
m_panDirection = VECTOR2D();
if( p.x < borderStart )
m_panDirection.x = -( borderStart - p.x );
else if( p.x > borderEndX )
m_panDirection.x = ( p.x - borderEndX );
if( p.y < borderStart )
m_panDirection.y = -( borderStart - p.y );
else if( p.y > borderEndY )
m_panDirection.y = ( p.y - borderEndY );
bool borderHit = ( m_panDirection.x != 0 || m_panDirection.y != 0 );
switch( m_state )
{
case AUTO_PANNING:
if( !borderHit )
{
m_panTimer.Stop();
m_state = IDLE;
}
break;
case IDLE:
if( borderHit )
{
m_state = AUTO_PANNING;
m_panTimer.Start( (int) ( 1000.0 / 60.0 ) );
}
break;
}
}

View File

@ -46,16 +46,6 @@ class VIEW;
class VIEW_CONTROLS
{
public:
/**
* Possible modes for panning (JUMP means that view is updated less often, resulting in
* not so responsive user interface).
*/
enum PanMode {
SMOOTH = 1,
JUMP = 2
};
VIEW_CONTROLS( VIEW* aView ) : m_view( aView ) {};
virtual ~VIEW_CONTROLS() {};
@ -89,13 +79,6 @@ public:
*/
virtual void SetPanSpeed( float aSpeed ) {};
/**
* Function SetPanMode
* Enables specified mode for panning.
* @param aMode is a new mode used for VIEW panning.
*/
virtual void SetPanMode( PanMode aMode ) {};
/**
* Function SetZoomSpeed
* Determines how much zoom factor should be affected on one zoom event (eg. mouse wheel).

View File

@ -52,27 +52,55 @@ public:
WX_VIEW_CONTROLS( VIEW* aView, wxWindow* aParentPanel );
~WX_VIEW_CONTROLS() {};
/// Handler functions
void onWheel( wxMouseEvent& aEvent );
void onMotion( wxMouseEvent& aEvent );
void onButton( wxMouseEvent& aEvent );
void onEnter( wxMouseEvent& aEvent );
void onTimer( wxTimerEvent& aEvent );
void SetEventDispatcher( TOOL_DISPATCHER *aEventDispatcher );
/**
* Function SetGrabMouse()
* Enables/disables mouse cursor grabbing (limits the movement field only to the panel area).
*
* @param aEnabled says whether the option should enabled or disabled.
*/
void SetGrabMouse( bool aEnabled );
/**
* Function SetAutoPan()
* Enables/disables autopanning (panning when mouse cursor reaches the panel border).
*
* @param aEnabled says whether the option should enabled or disabled.
*/
void SetAutoPan( bool aEnabled )
{
m_autoPanEnabled = true;
}
private:
enum State {
IDLE = 1,
DRAG_PANNING,
AUTO_PANNING,
};
void handleAutoPanning( wxMouseEvent& aEvent );
/// Current state of VIEW_CONTROLS
State m_state;
/// Options for WX_VIEW_CONTROLS
bool m_isDragPanning;
bool m_isAutoPanning;
bool m_autoPanEnabled;
bool m_needRedraw;
bool m_grabMouse;
/// Distance from cursor to VIEW edge when panning is active.
double m_autoPanMargin;
float m_autoPanMargin;
/// How fast is panning when in auto mode.
double m_autoPanSpeed;
float m_autoPanSpeed;
/// TODO
double m_autoPanCornerRatio;
float m_autoPanAcceleration;
/// Panel that is affected by VIEW_CONTROLS
wxWindow* m_parentPanel;
@ -80,10 +108,11 @@ private:
/// Stores information about point where event started.
VECTOR2D m_dragStartPoint;
VECTOR2D m_lookStartPoint;
VECTOR2D m_panDirection;
/// Used for determining time intervals between events.
wxLongLong m_timeStamp;
TOOL_DISPATCHER* m_eventDispatcher;
wxTimer m_panTimer;
};
} // namespace KiGfx