src/hbinput/inputwidgets/hbinputvirtualrocker.cpp
changeset 0 16d8024aca5e
child 1 f7ac710697a9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hbinput/inputwidgets/hbinputvirtualrocker.cpp	Mon Apr 19 14:02:13 2010 +0300
@@ -0,0 +1,332 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (developer.feedback@nokia.com)
+**
+** This file is part of the HbInput module of the UI Extensions for Mobile.
+**
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at developer.feedback@nokia.com.
+**
+****************************************************************************/
+#include <QGraphicsSceneMouseEvent>
+#include <QPixmap>
+#include <QBitmap>
+#include <QPainter>
+#include <QCoreApplication>
+#include <QDir>
+#include <QDebug>
+#include <hbicon.h>
+#include <hbinputsettingproxy.h>
+#include <hbwidgetfeedback.h>
+
+#include "hbinputvkbwidget.h"
+#include "hbinputvirtualrocker.h"
+
+/// @cond
+
+const qreal HbRockerXThreshold = 5.0;
+const qreal HbRockerYThreshold = 50.0;
+const qreal HbRockerDimOpacity = 1.0;
+const qreal HbRockerNormalOpacity = 1.0;
+const qreal HbRockerWidth = 50.0;
+const int HbIconWidth = 30;
+const int HbPointerWidth = 15;
+
+
+class HbInputVirtualRockerPrivate
+{
+public:
+    explicit HbInputVirtualRockerPrivate(HbInputVirtualRocker *rocker, HbInputVkbWidget* parent = 0);
+    ~HbInputVirtualRockerPrivate();
+    int rockerEventRepeats(qreal distance);
+    void setCenter();
+
+public:
+    HbInputVirtualRocker *q_ptr;
+    HbIcon* mIconNormal;
+    HbInputVirtualRocker::RockerSelectionMode mShifted;
+    QPointF mLastPoint;
+    QPointF mCenterPosition;
+    QPointF mPointerPosition;
+    QPointF mMousePressPoint;
+    HbInputVkbWidget* mKeyboard;
+    bool mPressed;
+};
+
+HbInputVirtualRockerPrivate::HbInputVirtualRockerPrivate(HbInputVirtualRocker *rocker, HbInputVkbWidget* parent)
+        : q_ptr(rocker),
+          mIconNormal(0),
+          mShifted(HbInputVirtualRocker::RockerSelectionModeOff),
+          mLastPoint(0.0,0.0),
+          mCenterPosition(0.0,0.0),
+          mMousePressPoint(0.0,0.0),
+          mKeyboard(parent),
+          mPressed(false)
+{
+    mIconNormal = new HbIcon("qtg_graf_trackpoint_normal" );
+    mIconNormal->setSize( QSizeF( HbIconWidth, HbIconWidth ));
+}
+
+HbInputVirtualRockerPrivate::~HbInputVirtualRockerPrivate()
+{
+    delete mIconNormal;
+}
+
+int HbInputVirtualRockerPrivate::rockerEventRepeats(qreal distance)
+{
+    // cursor move multiplier for cursor moving signals, depending on the rocker move speed
+    int repeats = 1;
+    if (distance > 30){
+        repeats = 30;
+    } else if (distance > 20) {
+        repeats = 10;
+    } else if(distance > 10) {
+        repeats = 2;
+    }
+    return repeats;
+}
+
+void HbInputVirtualRockerPrivate::setCenter()
+{
+    if(mCenterPosition.isNull()){
+        mCenterPosition.setX(q_ptr->pos().x()+HbRockerWidth/2);
+        mCenterPosition.setY(q_ptr->pos().y()+HbRockerWidth/2);
+    }
+    mPointerPosition.setX((HbRockerWidth - HbPointerWidth)/2);
+    mPointerPosition.setY((HbRockerWidth - HbPointerWidth)/2);
+}
+
+/// @endcond
+
+/*!
+@alpha
+@hbinput
+\class HbInputVirtualRocker
+\brief Virtual rocker widget for generating direction events from virtual keyboards.
+
+Virtual rocker is a virtual version of a mouse pointer decive commonly used in many laptop PC keyboards.
+It is typically embedded into virtual keyboards. It generates direction events which can be used for
+moving editor cursor, highlighting text, etc.
+
+User first presses virtual rocker widget and then slides finger to desired direction. The widget
+will emit direction events based on the direction of finger momvement, relative to the starting point.
+When the finger is lifted, rocker widget returns to normal state and stops sending events.
+
+Double clicking will start selection mode. Rocker appearance changes and direction events have shift modifier on
+but otherwise it behaves in similar manner as described above.
+
+\sa HbInputVkbWidget
+*/
+/*!
+\enum HbInputVirtualRocker::RockerDirection
+
+This enum defines virtual rocker directions.
+*/
+/*!
+\enum HbInputVirtualRocker::RockerSelectionMode
+
+This enum defines virtual rocker selection modes.
+*/
+
+/*!
+Constructs the object.
+*/
+HbInputVirtualRocker::HbInputVirtualRocker(HbInputVkbWidget* parent)
+    : HbWidget(parent), d_ptr(new HbInputVirtualRockerPrivate(this, parent))
+{
+    setOpacity(HbRockerDimOpacity);
+}
+
+/*!
+Constructs the object.
+*/
+HbInputVirtualRocker::HbInputVirtualRocker(HbInputVirtualRockerPrivate &dd, QGraphicsWidget* parent)
+    : HbWidget(parent), d_ptr(&dd)
+{
+    setOpacity(HbRockerDimOpacity);
+}
+
+/*!
+Destroys the widget.
+*/
+HbInputVirtualRocker::~HbInputVirtualRocker()
+{
+    delete d_ptr;
+}
+
+/*!
+    \reimp
+    \sa QGraphicsWidget.
+*/
+void HbInputVirtualRocker::mousePressEvent(QGraphicsSceneMouseEvent* event)
+{
+    Q_D(HbInputVirtualRocker);
+
+    QPointF position = event->pos();
+    QPointF delta = position - QPointF(HbRockerWidth/2, HbRockerWidth/2);
+
+    qreal squareDistance = delta.y()*delta.y() + delta.x()*delta.x();
+    qreal squareRadius = HbRockerWidth*HbRockerWidth/4;
+    if (squareRadius > squareDistance) {
+        // the touch point is inside circle which diameter is HbRockerWidth
+        d->setCenter();
+        d->mLastPoint = position;
+        d->mMousePressPoint = position;
+        if (d->mKeyboard) {
+            d->mKeyboard->setKeyboardDimmed(true);
+        }
+        HbWidgetFeedback::triggered(this, Hb::InstantPressed);
+        setOpacity(HbRockerNormalOpacity);
+        d->mPressed = true;
+    } else {
+        // outside of circle: give event to a push button
+        event->ignore();
+    }
+}
+
+/*!
+    \reimp
+    \sa QGraphicsWidget.
+*/
+void HbInputVirtualRocker::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
+{
+    Q_UNUSED(event)
+    Q_D(HbInputVirtualRocker);
+
+    if (d->mKeyboard) {
+        d->mKeyboard->setKeyboardDimmed(false);
+        setOpacity(HbRockerDimOpacity);
+    }
+    d->mPressed = false;
+    update();
+    d->setCenter();
+    d->mShifted = RockerSelectionModeOff;
+    HbWidgetFeedback::triggered(this, Hb::InstantReleased);
+}
+
+/*!
+    \reimp
+    \sa QGraphicsWidget.
+*/
+void HbInputVirtualRocker::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
+{
+    Q_D(HbInputVirtualRocker);
+
+    if (event->buttons() != 0) {
+        QPointF delta = event->pos() - d->mLastPoint;
+        QPointF deltaPressLoc = event->pos() - d->mMousePressPoint;
+        int repeats = 1;
+
+        HbWidgetFeedback::triggered(this, Hb::InstantDraggedOver);
+
+        if (delta.x() > HbRockerXThreshold) {
+            repeats = d->rockerEventRepeats( delta.x() );
+            for (int i = 0; i < repeats; i++) {
+                emit rockerDirection(HbRockerDirectionRight, d->mShifted);
+            }
+            d->mLastPoint = event->pos();
+        } else if (delta.x() < -HbRockerXThreshold) {
+            repeats = d->rockerEventRepeats( -delta.x() );
+            for (int i = 0; i < repeats; i++) {
+                emit rockerDirection(HbRockerDirectionLeft, d->mShifted);
+            }
+            d->mLastPoint = event->pos();
+        }
+
+        if (delta.y() > HbRockerYThreshold) {
+            repeats = d->rockerEventRepeats(delta.y());
+            emit rockerDirection(HbRockerDirectionDown, d->mShifted);
+            d->mLastPoint = event->pos();
+        } else if (delta.y() < -HbRockerYThreshold) {
+            emit rockerDirection(HbRockerDirectionUp, d->mShifted);
+            d->mLastPoint = event->pos();
+        }
+
+        d->mPointerPosition = HbIconWidth * deltaPressLoc / d->mCenterPosition.x() / 2
+            + QPointF((HbRockerWidth-HbPointerWidth)/2, (HbRockerWidth-HbPointerWidth)/2);
+
+        update();
+
+    }
+}
+
+/*!
+    \reimp
+    \sa QGraphicsWidget.
+*/
+void HbInputVirtualRocker::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
+{
+    Q_UNUSED(event)
+    Q_D(HbInputVirtualRocker);
+
+    if (d->mShifted == RockerSelectionModeOff) {
+        d->mShifted = RockerSelectionModeOn;
+    } else {
+        d->mShifted = RockerSelectionModeOff;
+    }
+
+    // dim the keypad.
+    if (d->mKeyboard) {
+        d->mKeyboard->setKeyboardDimmed(true);
+    }
+    setOpacity(HbRockerNormalOpacity);
+}
+
+/*!
+    \reimp
+    \sa QGraphicsWidget.
+*/
+void HbInputVirtualRocker::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
+{
+    Q_UNUSED(option)
+    Q_UNUSED(widget)
+    Q_D(HbInputVirtualRocker);
+
+    painter->setRenderHint(QPainter::Antialiasing, true);
+
+    if (d->mIconNormal &&
+        !d->mIconNormal->isNull()) {
+        // We have icon, lets draw it.
+
+        d->mIconNormal->paint(painter, rect(), Qt::IgnoreAspectRatio);
+        if (d->mPressed) {
+            painter->setBrush(Qt::blue);
+            painter->setPen(Qt::blue);
+            painter->drawEllipse(static_cast<int>(d->mPointerPosition.x()),
+                                 static_cast<int>(d->mPointerPosition.y()),
+                                 HbPointerWidth, HbPointerWidth);
+        }
+
+    } else {
+        // Otherwise just draw a white ellipse as a fallback.
+        painter->setBrush(Qt::white);
+        painter->setPen(Qt::white);
+        painter->drawEllipse(boundingRect());
+    }
+}
+
+/*!
+Returns true if virtual rocker is in selection state, ie. it sends event with shift modifier
+on.
+*/
+HbInputVirtualRocker::RockerSelectionMode HbInputVirtualRocker::selectionMode() const
+{
+    Q_D(const HbInputVirtualRocker);
+    return d->mShifted;
+}
+
+// End of file