From 24193578f04f54df1cff6ef5caf45e0895081df3 Mon Sep 17 00:00:00 2001 From: rachytski Date: Mon, 3 Oct 2011 13:35:05 +0300 Subject: [PATCH] added screen rotation support. --- map/events.hpp | 20 +++++++++++++++ map/framework.cpp | 22 ++++++++++++++++ map/framework.hpp | 7 +++++ map/navigator.cpp | 22 ++++++++++++++++ map/navigator.hpp | 6 +++++ map/render_policy.cpp | 15 +++++++++++ map/render_policy.hpp | 4 +++ qt/draw_widget.cpp | 59 +++++++++++++++++++++++++++++++++++++++---- qt/draw_widget.hpp | 4 +++ 9 files changed, 154 insertions(+), 5 deletions(-) diff --git a/map/events.hpp b/map/events.hpp index cb9d9bf99e..6c8ad98dfb 100644 --- a/map/events.hpp +++ b/map/events.hpp @@ -22,6 +22,26 @@ public: m2::PointD Pos() const { return m_pt; } }; +class RotateEvent +{ + double m_Angle; +public: + RotateEvent(double x1, double y1, double x2, double y2) + { + double dx = x2 - x1; + double dy = y2 - y1; + double len = sqrt(dx * dx + dy * dy); + dy /= len; + dx /= len; + m_Angle = atan2(dy, dx); + } + + double Angle() const + { + return m_Angle; + } +}; + class ScaleEvent { m2::PointD m_Pt1, m_Pt2; diff --git a/map/framework.cpp b/map/framework.cpp index 4504d8c5c9..2e066fc5c0 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -531,6 +531,28 @@ void Framework::StopDrag(DragEvent const & e) m_renderPolicy->StopDrag(pos, m_timer.ElapsedSeconds()); } +template +void Framework::StartRotate(RotateEvent const & e) +{ + m_navigator.StartRotate(e.Angle(), m_timer.ElapsedSeconds()); + m_renderPolicy->StartRotate(e.Angle(), m_timer.ElapsedSeconds()); +} + +template +void Framework::DoRotate(RotateEvent const & e) +{ + m_navigator.DoRotate(e.Angle(), m_timer.ElapsedSeconds()); + m_renderPolicy->DoRotate(e.Angle(), m_timer.ElapsedSeconds()); +} + +template +void Framework::StopRotate(RotateEvent const & e) +{ + m_navigator.StopRotate(e.Angle(), m_timer.ElapsedSeconds()); + m_renderPolicy->StopRotate(e.Angle(), m_timer.ElapsedSeconds()); +} + + template void Framework::Move(double azDir, double factor) { diff --git a/map/framework.hpp b/map/framework.hpp index eeb9fa2562..dce076fbd1 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -243,6 +243,13 @@ public: void Move(double azDir, double factor); //@} + /// @name Rotation implementation + //@{ + void StartRotate(RotateEvent const & e); + void DoRotate(RotateEvent const & e); + void StopRotate(RotateEvent const & e); + //@} + /// @name Scaling. //@{ void ScaleToPoint(ScaleToPointEvent const & e); diff --git a/map/navigator.cpp b/map/navigator.cpp index b47034b747..4d95a66753 100644 --- a/map/navigator.cpp +++ b/map/navigator.cpp @@ -171,6 +171,28 @@ ScreenBase const Navigator::ShrinkAndScaleInto(ScreenBase const & screen, m2::Re return res; } +void Navigator::StartRotate(double a, double /*timeInSec*/) +{ + m_StartAngle = a; + m_StartScreen = m_Screen; + m_InAction = true; +} + +void Navigator::DoRotate(double a, double /*timeInSec*/) +{ + ScreenBase tmp = m_StartScreen; + tmp.Rotate(a - m_StartAngle); + m_StartAngle = a; + m_Screen = tmp; + m_StartScreen = tmp; +} + +void Navigator::StopRotate(double a, double timeInSec) +{ + DoRotate(a, timeInSec); + m_InAction = false; +} + void Navigator::StartDrag(m2::PointD const & pt, double /*timeInSec*/) { //LOG(LDEBUG, (pt.x, pt.y)); diff --git a/map/navigator.hpp b/map/navigator.hpp index 342e54daad..f3b287fc8d 100644 --- a/map/navigator.hpp +++ b/map/navigator.hpp @@ -34,6 +34,10 @@ public: void DoDrag(m2::PointD const & pt, double timeInSec); void StopDrag(m2::PointD const & pt, double timeInSec, bool animate); + void StartRotate(double Angle, double timeInSec); + void DoRotate(double Angle, double timeInSec); + void StopRotate(double Angle, double timeInSec); + void StartScale(m2::PointD const & pt1, m2::PointD const & pt2, double timeInSec); void DoScale(m2::PointD const & org, m2::PointD const & p1, m2::PointD const & p2); void DoScale(m2::PointD const & pt1, m2::PointD const & pt2, double timeInSec); @@ -84,6 +88,8 @@ private: m2::PointD m_StartPt2; // Second Last point for scaling. m2::PointD m_LastPt2; + // Start value of rotation angle + double m_StartAngle; // Current screen speed in post-dragging animation. double m_DragAnimationSpeed; // Move direction of the screen in post-dragging animation. diff --git a/map/render_policy.cpp b/map/render_policy.cpp index b83e4ad097..977d34e0e9 100644 --- a/map/render_policy.cpp +++ b/map/render_policy.cpp @@ -70,6 +70,21 @@ void RenderPolicy::StopScale(m2::PointD const &, m2::PointD const &, double) m_windowHandle->invalidate(); } +void RenderPolicy::StartRotate(double a, double) +{ + m_windowHandle->invalidate(); +} + +void RenderPolicy::DoRotate(double a, double) +{ + m_windowHandle->invalidate(); +} + +void RenderPolicy::StopRotate(double a, double) +{ + m_windowHandle->invalidate(); +} + void RenderPolicy::BeginFrame(shared_ptr const & e, ScreenBase const & s) {} diff --git a/map/render_policy.hpp b/map/render_policy.hpp index d791819dde..ed9cdb3db6 100644 --- a/map/render_policy.hpp +++ b/map/render_policy.hpp @@ -68,5 +68,9 @@ public: virtual void StartScale(m2::PointD const & pt1, m2::PointD const & pt2, double timeInSec); virtual void DoScale(m2::PointD const & pt1, m2::PointD const & pt2, double timeInSec); virtual void StopScale(m2::PointD const & pt1, m2::PointD const & pt2, double timeInSec); + + virtual void StartRotate(double a, double timeInSec); + virtual void DoRotate(double a, double timeInSec); + virtual void StopRotate(double a, double timeInSec); /// @} }; diff --git a/qt/draw_widget.cpp b/qt/draw_widget.cpp index 670a2a2624..c868d7370f 100644 --- a/qt/draw_widget.cpp +++ b/qt/draw_widget.cpp @@ -20,6 +20,7 @@ namespace qt m_handle(new WindowHandle()), m_framework(FrameworkFactory::CreateFramework(m_handle, 0)), m_isDrag(false), + m_isRotate(false), m_redrawInterval(100), m_pScale(0), m_isInitialized(false), @@ -234,7 +235,12 @@ namespace qt DragEvent get_drag_event(QMouseEvent * e) { QPoint const p = e->pos(); - return DragEvent(DragEvent(p.x(), p.y())); + return DragEvent(p.x(), p.y()); + } + + RotateEvent get_rotate_event(QPoint const & pt, QPoint const & centerPt) + { + return RotateEvent(centerPt.x(), centerPt.y(), pt.x(), pt.y()); } } @@ -244,10 +250,21 @@ namespace qt if (e->button() == Qt::LeftButton) { - m_framework->StartDrag(get_drag_event(e)); + if (e->modifiers() & Qt::ControlModifier) + { + /// starting rotation + m_framework->StartRotate(get_rotate_event(e->pos(), this->rect().center())); + setCursor(Qt::CrossCursor); + m_isRotate = true; + } + else + { + /// starting drag + m_framework->StartDrag(get_drag_event(e)); - setCursor(Qt::CrossCursor); - m_isDrag = true; + setCursor(Qt::CrossCursor); + m_isDrag = true; + } } } @@ -272,6 +289,9 @@ namespace qt if (m_isDrag) m_framework->DoDrag(get_drag_event(e)); + + if (m_isRotate) + m_framework->DoRotate(get_rotate_event(e->pos(), this->rect().center())); } void DrawWidget::mouseReleaseEvent(QMouseEvent * e) @@ -279,9 +299,38 @@ namespace qt base_type::mouseReleaseEvent(e); StopDragging(e); + StopRotating(e); + emit ViewportChanged(); } + void DrawWidget::keyReleaseEvent(QKeyEvent * e) + { + base_type::keyReleaseEvent(e); + + StopRotating(e); + + emit ViewportChanged(); + } + + void DrawWidget::StopRotating(QMouseEvent * e) + { + if (m_isRotate && (e->button() == Qt::LeftButton)) + { + m_framework->StopRotate(get_rotate_event(e->pos(), this->rect().center())); + setCursor(Qt::ArrowCursor); + m_isRotate = false; + } + } + + void DrawWidget::StopRotating(QKeyEvent * e) + { + if (m_isRotate && (e->key() == Qt::Key_Control)) + { + m_framework->StopRotate(get_rotate_event(this->mapFromGlobal(QCursor::pos()), this->rect().center())); + } + } + void DrawWidget::StopDragging(QMouseEvent * e) { if (m_isDrag && e->button() == Qt::LeftButton) @@ -305,7 +354,7 @@ namespace qt void DrawWidget::wheelEvent(QWheelEvent * e) { - if (!m_isDrag) + if ((!m_isDrag) && (!m_isRotate)) { /// if we are inside the timer, cancel it if (m_timer->isActive()) diff --git a/qt/draw_widget.hpp b/qt/draw_widget.hpp index 254a7235f9..5e95e9ef93 100644 --- a/qt/draw_widget.hpp +++ b/qt/draw_widget.hpp @@ -43,6 +43,7 @@ namespace qt auto_ptr m_videoTimer; bool m_isDrag; + bool m_isRotate; QTimer * m_timer; QTimer * m_animTimer; @@ -109,11 +110,14 @@ namespace qt virtual void mouseMoveEvent(QMouseEvent * e); virtual void mouseReleaseEvent(QMouseEvent * e); virtual void wheelEvent(QWheelEvent * e); + virtual void keyReleaseEvent(QKeyEvent * e); //@} private: void UpdateScaleControl(); void StopDragging(QMouseEvent * e); + void StopRotating(QMouseEvent * e); + void StopRotating(QKeyEvent * e); QScaleSlider * m_pScale; };