src/hbinput/inputwidgets/hbinputcharpreviewpane.cpp
changeset 0 16d8024aca5e
child 1 f7ac710697a9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hbinput/inputwidgets/hbinputcharpreviewpane.cpp	Mon Apr 19 14:02:13 2010 +0300
@@ -0,0 +1,408 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+// Qt includes
+#include <QGraphicsLinearLayout>
+#include <QSignalMapper>
+#include <QPainter>
+#include <QSizePolicy>
+
+#if QT_VERSION >= 0x040600
+#include <QGraphicsDropShadowEffect>
+#endif
+
+#include <hbeffect.h>
+#include <hbinputsettingproxy.h>
+#include <hbmainwindow.h>
+#include <hbcolorscheme.h>
+#include <hbframedrawer.h>
+#include <hbframeitem.h>
+#include <hbdeviceprofile.h>
+#include <private/hbdialog_p.h>
+#include <hbtextitem.h>
+#include <hbmainwindow.h>
+#include <hbinstance.h>
+
+#include "hbinputpreviewlabel.h"
+#include "hbinputcharpreviewpane.h"
+
+const int HbPreviewZoomDelta = 7;
+const qreal HbPreviewBoundaryDelta = 1.5;
+const qreal HbBoundaryLabelWidthFactor = 0.75;
+const qreal HbLabelwidthFactor = 0.50;
+/// @cond
+
+/*
+Character preview widget for Accented characters.
+Implements character preview for characters mapped in the preview Pane.
+*/
+class HbAccentedCharPreviewPane: public HbWidget
+{
+public:
+    /*!
+    Constructor.
+    @param parent of the widget.
+    */
+    HbAccentedCharPreviewPane(QGraphicsItem *parent = 0)
+        :HbWidget(parent),
+        mFramePrim(0),
+        mTextItem(0)
+    {
+        mFramePrim = static_cast<HbFrameItem*>(style()->createPrimitive(HbStyle::P_Popup_background, this));
+        mTextItem = static_cast<HbTextItem*>(style()->createPrimitive(HbStyle::P_Label_text, this));
+    }
+    /*!
+    update the text and frame primitives
+    */
+    void updatePrimitives()
+    {
+        if (mFramePrim) {
+            mFramePrim->frameDrawer().setFrameType(HbFrameDrawer::ThreePiecesHorizontal);
+            mFramePrim->frameDrawer().setFrameGraphicsName("qtg_fr_character_preview");
+            mTextItem->setFontSpec(HbFontSpec(HbFontSpec::Primary));
+            mTextItem->setAlignment(Qt::AlignCenter);
+        }
+    }
+    /*!
+    Destroys the object.
+    */
+    ~HbAccentedCharPreviewPane() {
+    }
+public:
+    HbFrameItem* mFramePrim;
+    HbTextItem* mTextItem;
+};
+
+class HbCharPreviewPanePrivate: public HbDialogPrivate
+{
+    Q_DECLARE_PUBLIC(HbCharPreviewPane)
+
+public:
+    HbCharPreviewPanePrivate();
+    ~HbCharPreviewPanePrivate();
+    void clearCharacters();
+    void updateCharacters();
+    void init();
+
+// private slots
+    void _q_showAccentedPreviewPane(QString character, QRectF sceneBoundingRect);
+    void _q_hideAccentedPreviewPane();
+    void _q_hidePreviewPanePopup();
+public:
+    QStringList mCharacterList;
+    QSignalMapper *mReleaseMapper;
+    QGraphicsLinearLayout* mCandLayout;
+    HbFrameItem* mFramePrim;
+    QSizeF mItemSize;
+    HbAccentedCharPreviewPane* mAccentedPreviewPane;
+};
+
+void HbCharPreviewPanePrivate::init()
+{
+    Q_Q(HbCharPreviewPane);
+    mFramePrim = static_cast<HbFrameItem*>(q->primitive(HbStyle::P_Popup_background));
+
+    if (!mFramePrim) {
+        mFramePrim = static_cast<HbFrameItem*>(q->style()->createPrimitive(HbStyle::P_Popup_background, q));
+    }
+}
+
+HbCharPreviewPanePrivate::HbCharPreviewPanePrivate()
+    : mReleaseMapper(0),
+    mCandLayout(0),
+    mFramePrim(0)
+{
+    mAccentedPreviewPane = new HbAccentedCharPreviewPane();
+}
+
+HbCharPreviewPanePrivate::~HbCharPreviewPanePrivate()
+{
+    if(mAccentedPreviewPane) {
+        delete mAccentedPreviewPane;
+    }
+    if(mReleaseMapper) {
+        delete mReleaseMapper;
+    }
+}
+
+void HbCharPreviewPanePrivate::clearCharacters()
+{
+    Q_Q(HbCharPreviewPane);
+    for (int i = mCandLayout->count() - 1; i >= 0; i--) {
+        QGraphicsLayoutItem* layoutitem = mCandLayout->itemAt(i);
+        mCandLayout->removeAt(i);
+        delete layoutitem;
+    }
+    mCandLayout->updateGeometry();
+    q->adjustSize();
+}
+
+void HbCharPreviewPanePrivate::updateCharacters()
+{
+    Q_Q(HbCharPreviewPane);
+	// need to set the minimum size to an invalid value here in order to make sure that the size does not become 0
+	mCandLayout->setMinimumSize(-1,-1);
+    for (int i = 0; i < mCharacterList.count(); i++) {
+        HbPreviewLabel* label = new HbPreviewLabel(mCharacterList[i]);
+        label->setPreferredHeight(mItemSize.height() + HbPreviewZoomDelta);
+        if (mCharacterList.count() > 1 && i != mCharacterList.count()-1) {
+            label->setPreferredWidth(HbBoundaryLabelWidthFactor * mItemSize.width());
+            label->setTextGeometry(mItemSize.width(), mItemSize.height());
+        } else {
+            label->setPreferredWidth(HbLabelwidthFactor * mItemSize.width());
+            label->setTextGeometry(mItemSize.width(), mItemSize.height());
+        }
+
+        QObject::connect(label, SIGNAL(showAccentedPreview(QString,QRectF)), q, SLOT(_q_showAccentedPreviewPane(QString,QRectF)));
+        QObject::connect(label, SIGNAL(selected()), mReleaseMapper, SLOT(map()));
+        QObject::connect(label, SIGNAL(hideAccentedPreview()), q, SLOT(_q_hideAccentedPreviewPane()));
+        QObject::connect(label, SIGNAL(hidePreview()), q, SLOT(_q_hidePreviewPanePopup()));
+        mReleaseMapper->setMapping(label, mCharacterList[i]);
+        mCandLayout->addItem(label);
+        mCandLayout->setItemSpacing(i, 0.0);
+    }
+
+    mCandLayout->setContentsMargins(mItemSize.width() / 4, 0, mItemSize.width() / 4, 0);
+    mCandLayout->updateGeometry();
+    q->adjustSize();
+}
+/*!
+Sets the character for preview and shows in it's Pane.
+@param character The character for preview.
+@param itemSceneBoundingRect of the QGraphicsItem.
+*/
+void HbCharPreviewPanePrivate::_q_showAccentedPreviewPane(QString character, QRectF itemSceneBoundingRect)
+{
+    Q_Q(HbCharPreviewPane);
+    mAccentedPreviewPane->setZValue(q->zValue()+1);
+    q->scene()->addItem(mAccentedPreviewPane);
+    // let's validate.
+    if (!itemSceneBoundingRect.isValid()) {
+        return;
+    }
+	QColor color = HbColorScheme::color("qtc_editor_normal");
+    // we need to show the accented char preview preview just above the
+    // passed QRectF of the item which is passed.
+    QPointF pos = itemSceneBoundingRect.topLeft();
+    pos.setY(pos.y() - mItemSize.height() +  HbPreviewZoomDelta + HbPreviewBoundaryDelta);
+
+    // let's adjust x position of the character preview pane so that it
+    // is aligned at the center of the items for which we want to show
+    // the preview.
+    pos.setX(itemSceneBoundingRect.x() - itemSceneBoundingRect.width()/4);
+
+    // set final position for the character preview pane
+    mAccentedPreviewPane->setPos(pos);
+    mAccentedPreviewPane->mTextItem->setText(character);
+    if (color.isValid()) {
+        mAccentedPreviewPane->mTextItem->setTextColor(color);
+    }
+    mAccentedPreviewPane->updatePrimitives();
+    QSizeF paneSize = itemSceneBoundingRect.size();
+    QRectF rect;
+    rect.setWidth(HbBoundaryLabelWidthFactor * mItemSize.width());
+    rect.setHeight(mItemSize.height());
+    rect.setY(paneSize.height()/2 - mItemSize.height()/2 - HbPreviewZoomDelta - HbPreviewBoundaryDelta);
+    mAccentedPreviewPane->mTextItem->setGeometry(rect);
+
+    // show it!
+    mAccentedPreviewPane->show();
+}
+/*
+hides the accented single character preview pane whenever user tries to hover on it
+as the the character is inputed in the editor only when mouse is released from preview pane
+*/
+void HbCharPreviewPanePrivate::_q_hideAccentedPreviewPane()
+{
+    mAccentedPreviewPane->hide();
+}
+
+/*
+hides the accented single character preview pane as well as charcters Preview Pane
+*/
+void HbCharPreviewPanePrivate::_q_hidePreviewPanePopup()
+{
+    Q_Q(HbCharPreviewPane);
+    mAccentedPreviewPane->hide();
+    if (q->isVisible()) {
+        q->hide();
+    }
+}
+
+/// @endcond
+
+/*!
+@proto
+@hbinput
+\class HbCharPreviewPane
+\brief Character preview widget for virtual keyboards.
+
+
+Implements character preview for virtual keyboards. Shows a list of clickable
+characters and maps the clicks to owning keyboard's charFromPreviewSelected slot.
+For first level of preview popup we have a linear layout, we create a HbPreviewLabel
+and add the labels to this layout. For second level of preview popup as user clicks
+on the lebel of preview pane we display preview of the accented character on the preview pane.
+
+\sa HbInputVkbWidget
+\sa HbPreviewLabel
+*/
+/*!
+Constructor.
+@param parent of the widget.
+*/
+HbCharPreviewPane::HbCharPreviewPane(QGraphicsItem* parent)
+    : HbDialog(*new HbCharPreviewPanePrivate, parent)
+{
+    Q_D(HbCharPreviewPane);
+
+    d->q_ptr = this;
+
+    d->mCandLayout = new QGraphicsLinearLayout(Qt::Horizontal);
+    setLayout(d->mCandLayout);
+
+    d->setPriority(HbPopupPrivate::VirtualKeyboard + 1);  // Should be visible on top of VKB
+
+    // set some properties
+    setFocusPolicy(Qt::ClickFocus);
+    setModal(false);
+    setDismissPolicy(HbPopup::TapAnywhere);
+    setBackgroundFaded(false);
+
+#if QT_VERSION >= 0x040600
+    // Make sure the preview pane never steals focus.
+    setFlag(QGraphicsItem::ItemIsPanel, true);
+    setActive(false);
+
+    // enable drop shadow for the preview pane
+    QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect;
+    effect->setBlurRadius(8);
+    setGraphicsEffect(effect);
+#endif
+
+    // signal mapper for getting events
+    d->mReleaseMapper = new QSignalMapper(this);
+
+    QObject::connect(d->mReleaseMapper, SIGNAL(mapped(QString)), this, SIGNAL(charFromPreviewSelected(QString)));
+    setTimeout(NoTimeout);
+    d->init();
+
+    // This is important we need to switch off all the effects.
+    // if we dont switch off the effect, and if there is a call to 'show' while a 'hide' animation is
+    // in progress the hide call will be ignored.
+    // this will lead to a problem where we will not able to see all the character
+    // preview in case the user is typing very fast.
+#ifdef HB_EFFECTS
+    HbEffect::disable(this);
+#endif // HB_EFFECTS
+}
+
+/*!
+Destroys the object.
+*/
+HbCharPreviewPane::~HbCharPreviewPane()
+{
+}
+
+/*!
+Sets the list of characters for preview.
+@param characterList The character preview list.
+@param itemSceneBoundingRect of the QGraphicsItem.
+*/
+void HbCharPreviewPane::showCharacters(const QStringList& characterList, const QRectF &itemSceneBoundingRect)
+{
+    Q_D(HbCharPreviewPane);
+    // let's validate.
+    if (!itemSceneBoundingRect.isValid()) {
+        return;
+    }
+
+    if (characterList.size() > 1) {
+        setModal(true);
+    } else {
+        setModal(false);
+    }
+
+    d->mCharacterList = characterList;
+    // let's store items size.
+    d->mItemSize = itemSceneBoundingRect.size();
+
+    // we need to clear previous character.
+    d->clearCharacters();
+
+    // update new candidates
+    d->updateCharacters();
+
+    updateGeometry();
+
+    // we need to show the preview just above the
+    // passed QRectF of the item which is passed.
+    QPointF pos = itemSceneBoundingRect.topLeft();
+    pos.setY(pos.y() - size().height());
+
+    // let's adjust x position of the character preview pane so that it
+    // is aligned at the center of the items for which we want to show
+    // the preview.
+    pos.setX(itemSceneBoundingRect.center().x() - size().width()/2);
+
+    // We need to adjust the character preview pane's postion
+    // such that it is visible in in the current screen.
+    if (pos.x() < 0) {
+        pos.setX(0);
+    } else {
+        const int screenWidth = HbDeviceProfile::profile(this).logicalSize().width();
+        const qreal requiredWidth = pos.x() + (geometry().width());
+        if ( requiredWidth > screenWidth) {
+            pos.setX(screenWidth-(geometry().width()));
+        }
+    }
+
+    // set final position for the character preview pane
+    setPos(pos);
+
+    // we need to reset mousePressLocation to None.
+    // We are handling character preview pane a bit differently than a usual popup.
+    // A HbDialog closes the popup on a mouse release. And there is a problem  when we
+    // have long pressed on a button and the preview pane is showing  set of characters,
+    // same time if we do a long press on another button preview will be shown on the next
+    // button but as soon as we release the button HbDialog's internal logic closes the
+    // preview pane. since popup closes on mouse release event. To aviod this situation we
+    // need to reset mousePressLocation. Since this behaviour is very specific to preview pane
+    // we need to fix it here.
+    d->mousePressLocation = HbPopupPrivate::None;
+
+    // show it!
+    show();
+}
+
+void HbCharPreviewPane::updatePrimitives()
+{
+    Q_D(HbCharPreviewPane);
+    d->mFramePrim->frameDrawer().setFrameType(HbFrameDrawer::ThreePiecesHorizontal);
+    d->mFramePrim->frameDrawer().setFrameGraphicsName("qtg_fr_character_preview");
+    d->mFramePrim->setGeometry(boundingRect());
+}
+
+#include "moc_hbinputcharpreviewpane.cpp"
+// End Of File