tests/benchmarks/uimodels/GraphicsViewBenchmark/widgets/scroller.cpp
changeset 3 41300fa6a67c
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     5 **
       
     6 ** This file is part of the examples of the Qt Toolkit.
       
     7 **
       
     8 ** $QT_BEGIN_LICENSE:LGPL$
       
     9 ** No Commercial Usage
       
    10 ** This file contains pre-release code and may not be distributed.
       
    11 ** You may use this file in accordance with the terms and conditions
       
    12 ** contained in the either Technology Preview License Agreement or the
       
    13 ** Beta Release License Agreement.
       
    14 **
       
    15 ** GNU Lesser General Public License Usage
       
    16 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    17 ** General Public License version 2.1 as published by the Free Software
       
    18 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    19 ** packaging of this file.  Please review the following information to
       
    20 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    22 **
       
    23 ** In addition, as a special exception, Nokia gives you certain
       
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
       
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
       
    26 ** package.
       
    27 **
       
    28 ** GNU General Public License Usage
       
    29 ** Alternatively, this file may be used under the terms of the GNU
       
    30 ** General Public License version 3.0 as published by the Free Software
       
    31 ** Foundation and appearing in the file LICENSE.GPL included in the
       
    32 ** packaging of this file.  Please review the following information to
       
    33 ** ensure the GNU General Public License version 3.0 requirements will be
       
    34 ** met: http://www.gnu.org/copyleft/gpl.html.
       
    35 **
       
    36 ** If you are unsure which license is appropriate for your use, please
       
    37 ** contact the sales department at http://qt.nokia.com/contact.
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <QScrollBar>
       
    43 #include <QEvent>
       
    44 #include <QGraphicsSceneMouseEvent>
       
    45 #include <QGraphicsView>
       
    46 #include <QDebug>
       
    47 
       
    48 #include "scroller.h"
       
    49 #include "scroller_p.h"
       
    50 #include "abstractscrollarea.h"
       
    51 #include "scrollbar.h"
       
    52 
       
    53 const int ScrollStep = 1;
       
    54 const int UpdateScrollingInterval = 55;
       
    55 const int UpdateScrollingSmoothInterval = 0;
       
    56 static const qreal MaxScrollingSpeed = 48.0;
       
    57 
       
    58 ScrollerPrivate::ScrollerPrivate(Scroller *scroller)
       
    59     : m_scrollArea(0)
       
    60     , m_scrollFactor(1.0)
       
    61     , m_state(Stopped)
       
    62     , q_ptr(scroller)
       
    63     , m_eventViewport(0)
       
    64 {
       
    65 }
       
    66 
       
    67 ScrollerPrivate::~ScrollerPrivate()
       
    68 {
       
    69 }
       
    70 
       
    71 void ScrollerPrivate::stopScrolling()
       
    72 {
       
    73     m_state = ScrollerPrivate::Started;
       
    74     m_cursorPos = QCursor::pos();
       
    75     m_speed = QPoint(0, 0);
       
    76 
       
    77     if (m_scrollTimer.isActive())
       
    78         m_scrollTimer.stop();
       
    79 }
       
    80 
       
    81 //Maps screen coordinates to scrollArea coordinates though current m_eventViewport widget 
       
    82 QPointF ScrollerPrivate::mapToScrollArea(const QPoint &point)
       
    83 {
       
    84     if (!m_scrollArea || !m_eventViewport)
       
    85         return point;
       
    86 
       
    87     QObject *vparent = m_eventViewport->parent();
       
    88     if (!vparent)
       
    89         return point;
       
    90 
       
    91     QGraphicsView *view = qobject_cast<QGraphicsView*>(vparent);
       
    92     if (!view)
       
    93         return point;
       
    94 
       
    95     QPoint pt = view->mapFromGlobal(point);
       
    96     return m_scrollArea->mapFromScene(view->mapToScene(pt));
       
    97 }
       
    98 
       
    99 bool ScrollerPrivate::eventFilter(QObject *obj, QEvent *event)
       
   100 {
       
   101     if (obj != m_scrollArea
       
   102         || (event->type() != QEvent::GraphicsSceneMouseMove
       
   103             && event->type() != QEvent::GraphicsSceneMousePress
       
   104             && event->type() != QEvent::GraphicsSceneMouseRelease
       
   105             /*&& event->type() != QEvent::GraphicsSceneKeyPressed
       
   106             && event->type() != QEvent::GraphicsSceneKeyReleased*/))
       
   107         return false;
       
   108 
       
   109     QGraphicsSceneMouseEvent* mouseEvent = 
       
   110         static_cast<QGraphicsSceneMouseEvent*>(event);
       
   111 
       
   112     m_eventViewport = mouseEvent->widget();
       
   113 
       
   114     bool eventConsumed = false;
       
   115 
       
   116     switch (m_state) {
       
   117     case ScrollerPrivate::Stopped:
       
   118         if (mouseEvent->type() == QEvent::GraphicsSceneMousePress &&
       
   119             mouseEvent->buttons() == Qt::LeftButton) {
       
   120             m_cursorPos = QCursor::pos();
       
   121             m_speed = QPointF(0.0, 0.0);
       
   122             m_state = Started;
       
   123         }
       
   124 
       
   125         eventConsumed = true;
       
   126         break;
       
   127 
       
   128     case ScrollerPrivate::Started:
       
   129         if (mouseEvent->type() == QEvent::GraphicsSceneMouseMove) {
       
   130             m_cursorPos = QCursor::pos();
       
   131             m_state = ManualScrolling;
       
   132 
       
   133             if (!m_scrollTimer.isActive()) 
       
   134                 m_scrollTimer.start(UpdateScrollingInterval);
       
   135             else {
       
   136                 m_scrollTimer.stop();
       
   137                 m_scrollTimer.start(UpdateScrollingInterval);
       
   138             }
       
   139 
       
   140         } else if (mouseEvent->type() == QEvent::MouseButtonRelease) {
       
   141             m_speed = QPoint(0, 0);
       
   142             m_state = Stopped;
       
   143 
       
   144             if (m_scrollTimer.isActive())
       
   145                 m_scrollTimer.stop();
       
   146         }
       
   147         eventConsumed = true;
       
   148         break;
       
   149 
       
   150     case ScrollerPrivate::ManualScrolling:
       
   151         if (mouseEvent->type() == QEvent::GraphicsSceneMouseMove &&
       
   152             m_scrollArea->viewport()->boundingRect().contains(mouseEvent->pos()) ) {
       
   153 
       
   154             ScrollBar *hscroll = m_scrollArea->horizontalScrollBar();
       
   155             ScrollBar *vscroll = m_scrollArea->verticalScrollBar();
       
   156 
       
   157             QPointF d = m_scrollFactor * (mapToScrollArea(QCursor::pos()) - mapToScrollArea(m_cursorPos)); 
       
   158 
       
   159             hscroll->setSliderPosition(hscroll->sliderPosition() - d.x());
       
   160             vscroll->setSliderPosition(vscroll->sliderPosition() - d.y());
       
   161 
       
   162             if (m_lastCursorTime.elapsed() > UpdateScrollingInterval) {
       
   163                 m_speed = mapToScrollArea(QCursor::pos()) - mapToScrollArea(m_cursorPos);
       
   164                 m_lastCursorTime.restart();
       
   165             }
       
   166 
       
   167             m_lastFrameTime.restart();
       
   168 
       
   169             m_cursorPos = QCursor::pos();
       
   170         } else if (mouseEvent->type() == QEvent::GraphicsSceneMouseRelease) {
       
   171             m_state = AutoScrolling;
       
   172             m_scrollSlowAccum = 0;
       
   173             if (m_scrollTimer.isActive()) {
       
   174                 m_scrollTimer.stop();
       
   175                 m_scrollTimer.start(UpdateScrollingSmoothInterval);
       
   176             }
       
   177         }
       
   178         eventConsumed = true;
       
   179         break;
       
   180 
       
   181     case ScrollerPrivate::AutoScrolling:
       
   182         if (mouseEvent->type() == QEvent::GraphicsSceneMousePress) {
       
   183             stopScrolling();
       
   184         } else if (mouseEvent->type() == QEvent::MouseButtonRelease) {
       
   185             m_state = Stopped;
       
   186         }
       
   187         eventConsumed  = true;
       
   188         break;
       
   189 
       
   190     default:
       
   191         break;
       
   192     }
       
   193 
       
   194     return eventConsumed;
       
   195 }
       
   196 
       
   197 void ScrollerPrivate::updateScrolling()
       
   198 {
       
   199     bool scrollOngoing = false;
       
   200 
       
   201     if (!m_scrollArea) {
       
   202         m_scrollTimer.stop();
       
   203         return;
       
   204     }
       
   205 
       
   206     if (m_state == ManualScrolling) {
       
   207         scrollOngoing = true;
       
   208         m_speed = mapToScrollArea(QCursor::pos()) - mapToScrollArea(m_cursorPos);
       
   209         m_cursorPos = QCursor::pos();
       
   210     } else if (m_state == AutoScrolling) {
       
   211         scrollOngoing = true;
       
   212 
       
   213 
       
   214         qreal x = qMax(-MaxScrollingSpeed, qMin(m_speed.x(), MaxScrollingSpeed));
       
   215         qreal y = qMax(-MaxScrollingSpeed, qMin(m_speed.y(), MaxScrollingSpeed));
       
   216 
       
   217         int sinceLast = m_lastFrameTime.elapsed();
       
   218         int slowdown = (ScrollStep * sinceLast) + m_scrollSlowAccum;
       
   219         m_scrollSlowAccum = slowdown & 0x3F;
       
   220         slowdown >>= 6;
       
   221 
       
   222         if (x > 0)
       
   223             x= qMax(qreal(0.0), x - slowdown);
       
   224         else
       
   225             x = qMin(qreal(0.0), x + slowdown);
       
   226 
       
   227         if (y > 0)
       
   228             y = qMax(qreal(0.0), y - slowdown);
       
   229         else
       
   230             y = qMin(qreal(0.0), y + slowdown);
       
   231 
       
   232         m_speed = QPoint(x,y);
       
   233 
       
   234         if (m_speed != QPoint(0,0)) {
       
   235             QPointF d;
       
   236 
       
   237             int xstep = (int(m_speed.x()) * sinceLast)>>6; // >>6 ~= *60 /1000 (==*64 /1024)
       
   238             int ystep = (int(m_speed.y()) * sinceLast)>>6;
       
   239             //qDebug() << sinceLast << "speedy" << speed.y()<<"ystep" << ystep;
       
   240             QPoint step = QPoint(xstep,ystep);
       
   241 
       
   242             if (ystep > 0)
       
   243                 d = (m_scrollArea->pos() + step);
       
   244             else
       
   245                 d = -(m_scrollArea->pos() - step);
       
   246 
       
   247             ScrollBar *hscroll = m_scrollArea->horizontalScrollBar();
       
   248             ScrollBar *vscroll = m_scrollArea->verticalScrollBar();
       
   249 
       
   250             hscroll->setSliderPosition(hscroll->sliderPosition() - m_scrollFactor * d.x());
       
   251             vscroll->setSliderPosition(vscroll->sliderPosition() - m_scrollFactor * d.y());
       
   252         } else { 
       
   253             m_state = Stopped;
       
   254             scrollOngoing = false;
       
   255         }
       
   256     }
       
   257 
       
   258     m_lastFrameTime.restart();
       
   259 
       
   260     if (!scrollOngoing)
       
   261         m_scrollTimer.stop();
       
   262 }
       
   263 
       
   264 
       
   265 Scroller::Scroller(QObject *parent)
       
   266     : QObject(parent), d_ptr(new ScrollerPrivate(this))
       
   267 {
       
   268     Q_D(Scroller);
       
   269     connect(&d->m_scrollTimer, SIGNAL(timeout()), this, SLOT(updateScrolling()));
       
   270 }
       
   271 
       
   272 Scroller::~Scroller()
       
   273 {
       
   274     delete d_ptr;
       
   275 }
       
   276 
       
   277 void Scroller::setScrollable(AbstractScrollArea *area)
       
   278 {
       
   279     Q_D(Scroller);
       
   280 
       
   281     if (!area)
       
   282         return;
       
   283 
       
   284     d->m_scrollArea = area;
       
   285 }
       
   286 
       
   287 void Scroller::setScrollFactor(qreal scrollFactor)
       
   288 {
       
   289     Q_D(Scroller);
       
   290 
       
   291     d->m_scrollFactor = scrollFactor;
       
   292 }
       
   293 
       
   294 bool Scroller::eventFilter(QObject *obj, QEvent *event)
       
   295 {
       
   296     Q_D(Scroller);
       
   297     return d->eventFilter(obj, event);
       
   298 }
       
   299 
       
   300 void Scroller::stopScrolling()
       
   301 {
       
   302     Q_D(Scroller);
       
   303     d->stopScrolling();
       
   304 }
       
   305 #include "moc_scroller.cpp"