Commit 961a8c2e authored by Maciej Suminski's avatar Maciej Suminski
Browse files

Added autopanning functionality to WX_VIEW_CONTROLS.

parent 875c0f70
Loading
Loading
Loading
Loading
+133 −18
Original line number Original line Diff line number Diff line
@@ -24,7 +24,6 @@
 */
 */


#include <wx/wx.h>
#include <wx/wx.h>
#include <wx/window.h>


#include <view/view.h>
#include <view/view.h>
#include <view/wx_view_controls.h>
#include <view/wx_view_controls.h>
@@ -33,9 +32,11 @@ using namespace KiGfx;


WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, wxWindow* aParentPanel ) :
WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, wxWindow* aParentPanel ) :
    VIEW_CONTROLS( aView ),
    VIEW_CONTROLS( aView ),
    m_state( IDLE ),
    m_autoPanEnabled( false ),
    m_grabMouse( false ),
    m_autoPanMargin( 0.1 ),
    m_autoPanMargin( 0.1 ),
    m_autoPanSpeed( 0.15 ),
    m_autoPanSpeed( 0.15 ),
    m_autoPanCornerRatio( 0.1 ),
    m_parentPanel( aParentPanel )
    m_parentPanel( aParentPanel )
{
{
    m_parentPanel->Connect( wxEVT_MOTION, wxMouseEventHandler(
    m_parentPanel->Connect( wxEVT_MOTION, wxMouseEventHandler(
@@ -50,23 +51,41 @@ WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, wxWindow* aParentPanel ) :
    m_parentPanel->Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler(
    m_parentPanel->Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler(
                                WX_VIEW_CONTROLS::onEnter ), NULL, this );
                                WX_VIEW_CONTROLS::onEnter ), NULL, this );
#endif
#endif

    m_panTimer.SetOwner( this );
    this->Connect( wxEVT_TIMER, wxTimerEventHandler(
                                WX_VIEW_CONTROLS::onTimer ), NULL, this );
}
}




void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
{
    if( aEvent.Dragging() && m_isDragPanning )
{
{
    VECTOR2D mousePoint( aEvent.GetX(), aEvent.GetY() );
    VECTOR2D mousePoint( aEvent.GetX(), aEvent.GetY() );

    if( aEvent.Dragging() )
    {
        if( m_state == DRAG_PANNING )
        {
            VECTOR2D   d = m_dragStartPoint - mousePoint;
            VECTOR2D   d = m_dragStartPoint - mousePoint;
            VECTOR2D   delta = m_view->ToWorld( d, false );
            VECTOR2D   delta = m_view->ToWorld( d, false );


            m_view->SetCenter( m_lookStartPoint + delta );
            m_view->SetCenter( m_lookStartPoint + delta );
            m_parentPanel->Refresh();
            m_parentPanel->Refresh();
            aEvent.StopPropagation();
        }
        }

        else
        {
            aEvent.Skip();
            aEvent.Skip();
        }
        }
    }
    else
    {
        if( m_autoPanEnabled )
            handleAutoPanning( aEvent );
    }

//    DeletePendingEvents();
}




void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& aEvent )
void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& aEvent )
@@ -122,16 +141,25 @@ void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& aEvent )


void WX_VIEW_CONTROLS::onButton( wxMouseEvent& aEvent )
void WX_VIEW_CONTROLS::onButton( wxMouseEvent& aEvent )
{
{
    switch( m_state )
    {
    case IDLE:
    case AUTO_PANNING:
        if( aEvent.MiddleDown() )
        if( aEvent.MiddleDown() )
        {
        {
        m_isDragPanning     = true;
            m_dragStartPoint = VECTOR2D( aEvent.GetX(), aEvent.GetY() );
            m_dragStartPoint = VECTOR2D( aEvent.GetX(), aEvent.GetY() );
            m_lookStartPoint = m_view->GetCenter();
            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();
    aEvent.Skip();
}
}
@@ -141,3 +169,90 @@ void WX_VIEW_CONTROLS::onEnter( wxMouseEvent& aEvent )
{
{
    m_parentPanel->SetFocus();
    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;
    }
}
+0 −17
Original line number Original line Diff line number Diff line
@@ -46,16 +46,6 @@ class VIEW;
class VIEW_CONTROLS
class VIEW_CONTROLS
{
{
public:
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 ) {};
    VIEW_CONTROLS( VIEW* aView ) : m_view( aView ) {};
    virtual ~VIEW_CONTROLS() {};
    virtual ~VIEW_CONTROLS() {};


@@ -89,13 +79,6 @@ public:
     */
     */
    virtual void SetPanSpeed( float aSpeed ) {};
    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
     * Function SetZoomSpeed
     * Determines how much zoom factor should be affected on one zoom event (eg. mouse wheel).
     * Determines how much zoom factor should be affected on one zoom event (eg. mouse wheel).
+37 −8
Original line number Original line Diff line number Diff line
@@ -52,27 +52,55 @@ public:
    WX_VIEW_CONTROLS( VIEW* aView, wxWindow* aParentPanel );
    WX_VIEW_CONTROLS( VIEW* aView, wxWindow* aParentPanel );
    ~WX_VIEW_CONTROLS() {};
    ~WX_VIEW_CONTROLS() {};


    /// Handler functions
    void    onWheel( wxMouseEvent& aEvent );
    void    onWheel( wxMouseEvent& aEvent );
    void    onMotion( wxMouseEvent& aEvent );
    void    onMotion( wxMouseEvent& aEvent );
    void    onButton( wxMouseEvent& aEvent );
    void    onButton( wxMouseEvent& aEvent );
    void    onEnter( 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:
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
    /// Options for WX_VIEW_CONTROLS
    bool        m_isDragPanning;
    bool        m_isAutoPanning;
    bool        m_autoPanEnabled;
    bool        m_autoPanEnabled;
    bool        m_needRedraw;
    bool        m_needRedraw;
    bool        m_grabMouse;


    /// Distance from cursor to VIEW edge when panning is active.
    /// Distance from cursor to VIEW edge when panning is active.
    double      m_autoPanMargin;
    float       m_autoPanMargin;
    /// How fast is panning when in auto mode.
    /// How fast is panning when in auto mode.
    double      m_autoPanSpeed;
    float       m_autoPanSpeed;
    /// TODO
    /// TODO
    double      m_autoPanCornerRatio;
    float       m_autoPanAcceleration;


    /// Panel that is affected by VIEW_CONTROLS
    /// Panel that is affected by VIEW_CONTROLS
    wxWindow*   m_parentPanel;
    wxWindow*   m_parentPanel;
@@ -80,10 +108,11 @@ private:
    /// Stores information about point where event started.
    /// Stores information about point where event started.
    VECTOR2D    m_dragStartPoint;
    VECTOR2D    m_dragStartPoint;
    VECTOR2D    m_lookStartPoint;
    VECTOR2D    m_lookStartPoint;
    VECTOR2D    m_panDirection;


    /// Used for determining time intervals between events.
    /// Used for determining time intervals between events.
    wxLongLong  m_timeStamp;
    wxLongLong  m_timeStamp;
    TOOL_DISPATCHER* m_eventDispatcher;
    wxTimer     m_panTimer;
};
};
} // namespace KiGfx
} // namespace KiGfx