src/hbcore/vkbhosts/private/hbvkbgeometrylogic_p.cpp
changeset 28 b7da29130b0e
child 30 80e4d18b72f5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hbcore/vkbhosts/private/hbvkbgeometrylogic_p.cpp	Fri Sep 17 08:32:10 2010 +0300
@@ -0,0 +1,224 @@
+/****************************************************************************
+**
+** 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 HbCore 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 "hbvkbgeometrylogic_p.h"
+
+#include <QtGlobal>
+#include <hbglobal.h>
+
+const qreal HbCursorLineMargin = 15.0;
+const qreal HbContainerBorderMargin = 20.0;
+const qreal HbEditorExtraMargin = 17.0;
+
+/*!
+    \class HbVkbGeometryLogicPrivate
+    \brief Calculates screen movement in cases the keyboard would overlap with editor
+
+    This class contains calculations and logic to move screen in cases, when upcoming
+    keyboard would overlap the editor so, that text written could not be seen. Idea is
+    to minimize the movement as much as possible.
+
+*/
+
+/*!
+    \internal
+    \brief Construct current state object screen status.
+
+    Constructor to create status object based on given parameters. These parameters
+    are used to calculate possible movement vector for container.
+
+    \param screenSize       Size of screen.
+    \param keybadSize       Size of keyboard.
+    \param sceneArea        Size of view area, to which container belongs.
+    \param isVkbOpen        Information about current status of VKB.
+    \param hideTitlebar     Should titlebar hiding be calculated?
+    \param hideStatusbar    Should statusbar hiding be calculated?
+    \param containerArea    Area of editor's top item.
+    \param editorArea       Area of editor itself.
+    \param cursorArea       Area of cursor inside editor.
+*/
+HbVkbGeometryLogicPrivate::HbVkbGeometryLogicPrivate(
+        const QSizeF& screenSize,
+        const QSizeF& keypadSize,
+        const QRectF& sceneArea,
+        bool isVkbOpen,
+        bool hideTitlebar,
+        bool hideStatusbar,
+        const QRectF& containerArea,
+        const QRectF& editorArea,
+        const QRectF& cursorArea)
+{
+    // We need to consider situation, when keyboard is already on the screen, in
+    // which case, titlebar and statusbar are already hidden, thus bigger visible area
+    // is already in use, so no adjustments needed.
+    if ( isVkbOpen ) {
+        mVisibleArea = QRectF(0.0, 0.0, screenSize.width(), screenSize.height() - keypadSize.height());
+        mAdjust = 0.0;
+    } else if ( hideTitlebar || hideStatusbar ) {
+        // Without titlebar and statusbar, the visible area is from the top of the screen
+        // to the top of the keyboard. Also, container needs to move slightly, when
+        // bars are going to be closed.
+        mVisibleArea = QRectF(0.0, 0.0, screenSize.width(), screenSize.height() - keypadSize.height());
+        mAdjust = mVisibleArea.top() - sceneArea.top();
+    } else {
+        // When titlebar and statusbar are visible, visible area is going to be from
+        // bottom of the titlebar to top of the keyboard. No container movement needed.
+        mVisibleArea = QRectF(0.0, 0.0, screenSize.width(), sceneArea.height() - keypadSize.height());
+        mAdjust = 0.0;
+    }
+
+    // Find out the container area.
+    mContainerArea = containerArea;
+    mContainerArea.adjust(0.0, -HbContainerBorderMargin, 0.0, HbContainerBorderMargin);
+    mContainerArea.translate(QPointF(0, mAdjust));
+
+    // Find out the editor bounding box and add a small margin to height.
+    mEditorArea = editorArea;
+    mEditorArea.adjust(0.0, -HbCursorLineMargin, 0.0, HbCursorLineMargin);
+    mEditorArea.translate(QPointF(0, mAdjust));
+
+    // Finally, get cursor size and adjust it little bit
+    mCursorArea = cursorArea;
+    mCursorArea.adjust(0.0, -HbEditorExtraMargin, 0.0, HbEditorExtraMargin);
+    mCursorArea.translate(QPointF(0, mAdjust));
+}
+
+/*!
+    \internal
+    \brief Check the source area fits inside target area.
+*/
+bool HbVkbGeometryLogicPrivate::fitsArea(const QRectF& target, const QRectF& source) const
+{
+    return source.width() <= target.width() && source.height() <= target.height();
+}
+
+/*!
+    \internal
+    \brief Checks, whether the container fits into the visible area.
+
+    When keyboard opens, the screen will contain visible area and the keyboard area.
+    This method checks, whether container will fit the visible area.
+
+    \return True, when fits. Otherwise false.
+*/
+bool HbVkbGeometryLogicPrivate::containerFitsVisibleArea() const
+{
+     return fitsArea(mVisibleArea, mContainerArea);
+}
+
+/*!
+    \internal
+    \brief Checks, whether the editor fits into the visible area.
+
+    When keyboard opens, the screen will contain visible area and the keyboard area.
+    This method check, whether editor itself can be fitted to screen. This is needed
+    when the container cannot fit the screen, so the editor needs to be positioned.
+
+    \return
+*/
+bool HbVkbGeometryLogicPrivate::editorFitsVisibleArea() const
+{
+    return fitsArea(mVisibleArea, mEditorArea);
+}
+
+/*!
+    \internal
+    \brief Check if container is fully visible.
+
+    \return True, when fully inside visible area, otherwise false.
+*/
+bool HbVkbGeometryLogicPrivate::isContainerVisible() const
+{
+    return mVisibleArea.contains(mContainerArea);
+}
+
+/*!
+    \internal
+    \return True, when editor inside visible area
+*/
+bool HbVkbGeometryLogicPrivate::isEditorVisible() const
+{
+    return mVisibleArea.contains(mEditorArea);
+}
+
+/*!
+    \internal
+    \return True, when cursor inside visible area
+*/
+bool HbVkbGeometryLogicPrivate::isCursorVisible() const
+{
+    // Check wheter cursor inside the visible area.
+    return mVisibleArea.contains(mCursorArea);
+}
+
+/*!
+    \internal
+    \brief Calculates movement vector for viewport.
+
+    \return True, when container needs to be moved.
+*/
+bool HbVkbGeometryLogicPrivate::calculateContainerMovement(QPointF& vector) const
+{
+    // In case editor or cursor inside visible area, no extra movement needed.
+    if ( isCursorVisible() ) {
+        vector.rx() = 0.0;
+        vector.ry() = mAdjust;
+        return false;
+    }
+
+    // At this point we know, that cursor is not inside of visible area,
+    // after VKB has been shown. To make it bit prettier, let's check, if we can
+    // move and fit the whole editor into the screen at once.
+    if ( !isEditorVisible() && editorFitsVisibleArea() ) {
+        // Editor is not in screen but fits there, so simply move the whole editor
+        // to screen. Only thing yet to check is, which direction the editor needs
+        // to be moved.
+        if ( mEditorArea.top() <= mVisibleArea.top() ) {
+            vector = QPointF(0.0, -mEditorArea.top());
+        } else {
+            // In case editor is not inside visible area, move editor until it is.
+            vector = QPointF(0.0, mVisibleArea.bottom() - mEditorArea.bottom());
+        }
+
+        vector.ry() += mAdjust;
+
+        // Vector has been calculated, so finish the story and return.
+        return true;
+    }
+
+    // At this point we know, that cursor is not visible and the editor does not fit
+    // into the visible area. Here we need to move editor, so that the cursor can be
+    // seen in the visible area. There are two ways to do this.
+    // 1) Move container, until bottom of editor is reached OR
+    // 2) Move container, until cursor hits top of the screen
+    int cursorMove = (int)(mVisibleArea.top() - mCursorArea.top());
+    int editorMove = (int)(mVisibleArea.bottom() - mEditorArea.bottom());
+
+    // Choose smaller movement (notice usage of negative values)
+    vector = QPointF(0.0, cursorMove >= editorMove ? cursorMove : editorMove);
+
+    vector.ry() += mAdjust;
+    return true;
+}