--- a/src/hbcore/vkbhosts/private/hbvkbgeometrylogic_p.cpp Fri Sep 17 08:32:10 2010 +0300
+++ b/src/hbcore/vkbhosts/private/hbvkbgeometrylogic_p.cpp Mon Oct 04 00:38:12 2010 +0300
@@ -32,6 +32,7 @@
const qreal HbContainerBorderMargin = 20.0;
const qreal HbEditorExtraMargin = 17.0;
+
/*!
\class HbVkbGeometryLogicPrivate
\brief Calculates screen movement in cases the keyboard would overlap with editor
@@ -42,6 +43,7 @@
*/
+
/*!
\internal
\brief Construct current state object screen status.
@@ -63,17 +65,21 @@
const QSizeF& screenSize,
const QSizeF& keypadSize,
const QRectF& sceneArea,
+ bool isPopupType,
bool isVkbOpen,
bool hideTitlebar,
bool hideStatusbar,
const QRectF& containerArea,
const QRectF& editorArea,
const QRectF& cursorArea)
+ :
+ mIsPopupType(isPopupType)
{
// 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 ) {
+ // is already in use, so no adjustments needed. Popups can always use full visible
+ // area.
+ if ( isVkbOpen || isPopupType ) {
mVisibleArea = QRectF(0.0, 0.0, screenSize.width(), screenSize.height() - keypadSize.height());
mAdjust = 0.0;
} else if ( hideTitlebar || hideStatusbar ) {
@@ -89,22 +95,103 @@
mAdjust = 0.0;
}
- // Find out the container area.
+ // Find out the container area. No margin adjustments for popups.
mContainerArea = containerArea;
- mContainerArea.adjust(0.0, -HbContainerBorderMargin, 0.0, HbContainerBorderMargin);
+ if (isPopupType) {
+ 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.adjust(0.0, -HbEditorExtraMargin, 0.0, HbEditorExtraMargin);
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.adjust(0.0, -HbCursorLineMargin, 0.0, HbCursorLineMargin);
mCursorArea.translate(QPointF(0, mAdjust));
}
+
+/*!
+ \internal
+ \brief Check the source area fits inside target area.
+*/
+bool HbVkbGeometryLogicPrivate::minimunMovement(QPointF& vector) const
+{
+ vector.rx() = 0.0;
+ vector.ry() = mAdjust;
+ return false;
+}
+
+
+/*!
+ \internal
+ \brief Calculates vector to move given area to visible area.
+ \param areaToMove contains rectangle, which needs to be moved to visible area.
+
+ When moving editor to visible area, we need to consider situation, where
+ margins of the editor border may make editor look like it is outside of the
+ container. So every check we made, we need to compare against editor border
+ and container border.
+
+ \return Vector to visible area.
+*/
+bool HbVkbGeometryLogicPrivate::calculateVectorToVisibleArea(QPointF& vector, const QRectF& areaToMove) const
+{
+ qreal aTop = areaToMove.top();
+ qreal vTop = mVisibleArea.top();
+ qreal cTop = mContainerArea.top();
+
+ qreal aBottom = areaToMove.bottom();
+ qreal vBottom = mVisibleArea.bottom();
+ qreal cBottom = mContainerArea.bottom();
+
+ QRectF areaOfInterest = areaToMove;
+
+ // To simplify everything, first check, whether there is need to inspect
+ // container movement issues or not.
+ if ( !mContainerArea.contains(areaOfInterest) ) {
+ // Now we know, that area we are supposed to move, cannot be used
+ // in situations, when too close to borders and movement direction
+ // tells us to move container.
+ bool shouldMoveUp = aBottom > vBottom;
+ bool areaBelowContainer = aBottom > cBottom;
+ bool shouldMoveDown = aTop < vTop;
+ bool areaAboveContainer = aTop < cTop;
+
+ if ( ( areaBelowContainer && shouldMoveUp ) ||
+ ( areaAboveContainer && shouldMoveDown ) ) {
+ areaOfInterest = mContainerArea;
+ }
+ }
+
+ // Area is inside container. Before anything, check if we
+ // can move the container at least little bit. But it cannot be moved
+ // too low.
+ if ( areaOfInterest != mContainerArea && aTop < vTop ) {
+ qreal upward = aTop - mAdjust;
+
+ if ( upward < 0 ) {
+ vector.ry() -= upward;
+ return true;
+ } else {
+ return false;
+ }
+
+ // Vector calculation is simple, just figure out direction.
+ } else if ( aTop < vTop ) {
+ vector = QPointF(0.0, -aTop);
+ return true;
+
+ } else {
+ vector = QPointF(0.0, vBottom - areaOfInterest.bottom());
+ return true;
+ }
+}
+
+
/*!
\internal
\brief Check the source area fits inside target area.
@@ -114,6 +201,7 @@
return source.width() <= target.width() && source.height() <= target.height();
}
+
/*!
\internal
\brief Checks, whether the container fits into the visible area.
@@ -128,6 +216,7 @@
return fitsArea(mVisibleArea, mContainerArea);
}
+
/*!
\internal
\brief Checks, whether the editor fits into the visible area.
@@ -143,6 +232,7 @@
return fitsArea(mVisibleArea, mEditorArea);
}
+
/*!
\internal
\brief Check if container is fully visible.
@@ -154,71 +244,132 @@
return mVisibleArea.contains(mContainerArea);
}
+
/*!
\internal
- \return True, when editor inside visible area
+ \return
*/
bool HbVkbGeometryLogicPrivate::isEditorVisible() const
{
return mVisibleArea.contains(mEditorArea);
}
+
/*!
\internal
- \return True, when cursor inside visible area
+ \return
*/
bool HbVkbGeometryLogicPrivate::isCursorVisible() const
{
- // Check wheter cursor inside the visible area.
+ // Check whether cursor inside the visible area.
return mVisibleArea.contains(mCursorArea);
}
+
/*!
\internal
- \brief Calculates movement vector for viewport.
-
- \return True, when container needs to be moved.
+ \return
*/
bool HbVkbGeometryLogicPrivate::calculateContainerMovement(QPointF& vector) const
{
+ // Clear any data away from the vector
+ vector = QPointF(0, 0);
+
+ // First check against invalid case. If cursor is not inside container, the
+ // data provided is incorrect.
+ if ( !mContainerArea.contains(mCursorArea) ) {
+ return false;
+
+ } else if ( containerFitsVisibleArea() ) {
+ return calculateContainerVector(vector);
+
+ } else if ( mIsPopupType ) {
+ return calculatePopupVector(vector);
+
// In case editor or cursor inside visible area, no extra movement needed.
- if ( isCursorVisible() ) {
- vector.rx() = 0.0;
- vector.ry() = mAdjust;
- return false;
- }
+ } else if ( isCursorVisible() ) {
+ return minimunMovement(vector);
// 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());
- }
+ } else if ( !isEditorVisible() && editorFitsVisibleArea() ) {
+ return calculateEditorVector(vector);
- 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());
+ } else {
+ int cursorMove = static_cast<int>(mVisibleArea.top() - mCursorArea.top());
+ int editorMove = static_cast<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;
+ }
+}
+
+
+/*!
+ \internal
+ \return
+*/
+bool HbVkbGeometryLogicPrivate::calculateContainerVector(QPointF& vector) const
+{
+ if ( isContainerVisible() ) {
+ return minimunMovement(vector);
+ }
- // Choose smaller movement (notice usage of negative values)
- vector = QPointF(0.0, cursorMove >= editorMove ? cursorMove : editorMove);
+ bool result = calculateVectorToVisibleArea(vector, mContainerArea);
+ vector.ry() += mAdjust;
+ return result;
+}
+
+
+/*!
+ \internal
+ \brief Calculate vector to adjust popup location properly.
+
+ Goal of these calculations are to guarrantee, that the buttons are always
+ visible for user, so that the popup can be closed without closing VKB first.
+ This is achieved by trying to move popup bottom to edge of visible area,
+ and then check, whether the editor is still seen or not. If not, then adjust
+ the editor so, that it can be seen.
+
+ \return True, when movement needed
+*/
+bool HbVkbGeometryLogicPrivate::calculatePopupVector(QPointF& vector) const
+{
+ qreal mBottom = mContainerArea.bottom();
+ qreal vBottom = mVisibleArea.bottom();
+ vector.ry() += vBottom - mBottom;
+
+ QRectF newEditorPos = mEditorArea.translated(vector);
+ if (!mVisibleArea.contains(newEditorPos)) {
+ QPointF temp(0,0);
+ calculateVectorToVisibleArea(temp, newEditorPos);
+ vector += temp;
+ }
vector.ry() += mAdjust;
+
return true;
}
+
+
+/*!
+ \internal
+ \return
+*/
+bool HbVkbGeometryLogicPrivate::calculateEditorVector(QPointF& vector) const
+{
+ bool result = calculateVectorToVisibleArea(vector, mEditorArea);
+ vector.ry() += mAdjust;
+ return result;
+}
+