src/hbinput/inputwidgets/hbinputbutton.cpp
changeset 34 ed14f46c0e55
parent 7 923ff622b8b9
equal deleted inserted replaced
31:7516d6d86cf5 34:ed14f46c0e55
    23 **
    23 **
    24 ****************************************************************************/
    24 ****************************************************************************/
    25 
    25 
    26 #include "hbinputbutton.h"
    26 #include "hbinputbutton.h"
    27 
    27 
       
    28 #include <QTime>
       
    29 #include <hbdeviceprofile.h>
       
    30 
       
    31 /*!
       
    32 @stable
       
    33 @hbinput
       
    34 \class HbInputButton
       
    35 \brief Provides vkb button definitions used by HbInputButtonGroup
       
    36 
       
    37 \sa HbInputButtonGroup
       
    38 */
       
    39 
    28 /// @cond
    40 /// @cond
       
    41 
       
    42 // Defines how much the button size should be increased from its original size.
       
    43 const qreal HbInputThresholdMultiplier = 0.25;
       
    44 
       
    45 // Threshold for touch point position comparison
       
    46 const qreal HbInputTouchThreshold = 5.0;
       
    47 
       
    48 // Timeout for increased touch down region
       
    49 const int HbInputInstantTouchTimeout = 500;
       
    50 
       
    51 // Threshold for increased touch down region in mm
       
    52 const qreal HbInputInstantTouchThreshold = 3.5;
       
    53 
       
    54 const QPoint HbInputInvalidPoint = QPoint(-1, -1);
    29 
    55 
    30 class HbInputButtonPrivate
    56 class HbInputButtonPrivate
    31 {
    57 {
    32 public:
    58 public:
    33     HbInputButtonPrivate();
    59     HbInputButtonPrivate();
    38 
    64 
    39     void setDefaultGraphics(int keyCode);
    65     void setDefaultGraphics(int keyCode);
    40 
    66 
    41     HbInputButton::HbInputButtonType mType;
    67     HbInputButton::HbInputButtonType mType;
    42     HbInputButton::HbInputButtonState mState;
    68     HbInputButton::HbInputButtonState mState;
       
    69     HbInputButton::HbInputButtonState mPreviousState;
    43     QPoint mPosition;
    70     QPoint mPosition;
    44     QSize mSize;
    71     QSize mSize;
    45     int mKeyCode;
    72     int mKeyCode;
    46     bool mAutoRepeat;
    73     bool mAutoRepeat;
    47     QList<QString> mTexts;
    74     QList<QString> mTexts;
    48     QString mMappedCharacters;
    75     QString mMappedCharacters;
    49     QList<HbIcon> mIcons;
    76     QList<HbIcon> mIcons;
    50     QRectF mBoundingRect;
    77     QRectF mBoundingRect;
       
    78     QPointF mTouchPoint;
       
    79     QPointF mLastInteractionPoint;
       
    80     bool mTap;
       
    81     QTime mTouchTime;
       
    82     qreal mTouchThreshold;
    51 };
    83 };
    52 
    84 
    53 HbInputButtonPrivate::HbInputButtonPrivate()
    85 HbInputButtonPrivate::HbInputButtonPrivate()
    54     : mType(HbInputButton::ButtonTypeNormal), mState(HbInputButton::ButtonStateReleased),
    86     : mType(HbInputButton::ButtonTypeNormal), mState(HbInputButton::ButtonStateReleased),
    55       mPosition(0, 0), mSize(1, 1), mKeyCode(-1), mAutoRepeat(false)
    87       mPreviousState(HbInputButton::ButtonStateReleased), mPosition(0, 0), mSize(1, 1),
       
    88       mKeyCode(-1), mAutoRepeat(false), mTouchPoint(HbInputInvalidPoint),
       
    89       mLastInteractionPoint(HbInputInvalidPoint), mTap(false)
    56 {
    90 {
    57     for (int i = 0; i < HbInputButton::ButtonTextIndexCount; ++i) {
    91     for (int i = 0; i < HbInputButton::ButtonTextIndexCount; ++i) {
    58         mTexts.append("");
    92         mTexts.append("");
    59     }
    93     }
    60 
    94 
    61     for (int i = 0; i < HbInputButton::ButtonIconIndexCount; ++i) {
    95     for (int i = 0; i < HbInputButton::ButtonIconIndexCount; ++i) {
    62         mIcons.append(HbIcon());
    96         mIcons.append(HbIcon());
    63     }
    97     }
       
    98 
       
    99     // Convert millimeters to pixels
       
   100     mTouchThreshold = HbDeviceProfile::current().ppmValue() * HbInputInstantTouchThreshold;
    64 }
   101 }
    65 
   102 
    66 HbInputButtonPrivate::HbInputButtonPrivate(int keyCode, const QPoint &position, const QSize &size)
   103 HbInputButtonPrivate::HbInputButtonPrivate(int keyCode, const QPoint &position, const QSize &size)
    67     : mType(HbInputButton::ButtonTypeNormal), mState(HbInputButton::ButtonStateReleased),
   104     : mType(HbInputButton::ButtonTypeNormal), mState(HbInputButton::ButtonStateReleased),
    68       mPosition(position), mSize(size), mKeyCode(keyCode), mAutoRepeat(false)
   105       mPreviousState(HbInputButton::ButtonStateReleased), mPosition(position),
       
   106       mSize(size), mKeyCode(keyCode), mAutoRepeat(false), mTouchPoint(HbInputInvalidPoint),
       
   107       mLastInteractionPoint(HbInputInvalidPoint), mTap(false)
    69 {
   108 {
    70     for (int i = 0; i < HbInputButton::ButtonTextIndexCount; ++i) {
   109     for (int i = 0; i < HbInputButton::ButtonTextIndexCount; ++i) {
    71         mTexts.append("");
   110         mTexts.append("");
    72     }
   111     }
    73 
   112 
    90     }
   129     }
    91 
   130 
    92     if (mKeyCode == HbInputButton::ButtonKeyCodeDelete || mKeyCode == HbInputButton::ButtonKeyCodeSpace) {
   131     if (mKeyCode == HbInputButton::ButtonKeyCodeDelete || mKeyCode == HbInputButton::ButtonKeyCodeSpace) {
    93         mAutoRepeat = true;
   132         mAutoRepeat = true;
    94     }
   133     }
       
   134 
       
   135     // Convert millimeters to pixels
       
   136     mTouchThreshold = HbDeviceProfile::current().ppmValue() * HbInputInstantTouchThreshold;
    95 }
   137 }
    96 
   138 
    97 HbInputButtonPrivate::HbInputButtonPrivate(HbInputButton::HbInputButtonType type, HbInputButton::HbInputButtonState state,
   139 HbInputButtonPrivate::HbInputButtonPrivate(HbInputButton::HbInputButtonType type, HbInputButton::HbInputButtonState state,
    98         const QPoint &position, const QSize &size, int keyCode, bool autoRepeat,
   140         const QPoint &position, const QSize &size, int keyCode, bool autoRepeat,
    99         const QList<QString> &texts, const QString &mappedCharacters, const QList<HbIcon> &icons)
   141         const QList<QString> &texts, const QString &mappedCharacters, const QList<HbIcon> &icons)
   100     : mType(type), mState(state), mPosition(position), mSize(size), mKeyCode(keyCode), mAutoRepeat(autoRepeat),
   142     : mType(type), mState(state), mPreviousState(state), mPosition(position), mSize(size),
   101       mMappedCharacters(mappedCharacters)
   143       mKeyCode(keyCode), mAutoRepeat(autoRepeat), mMappedCharacters(mappedCharacters),
       
   144       mTouchPoint(HbInputInvalidPoint), mLastInteractionPoint(HbInputInvalidPoint), mTap(false)
   102 {
   145 {
   103     for (int i = 0; i < HbInputButton::ButtonTextIndexCount; ++i) {
   146     for (int i = 0; i < HbInputButton::ButtonTextIndexCount; ++i) {
   104         if (i < texts.count()) {
   147         if (i < texts.count()) {
   105             mTexts.append(texts.at(i));
   148             mTexts.append(texts.at(i));
   106         } else {
   149         } else {
   120         mSize.setWidth(1);
   163         mSize.setWidth(1);
   121     }
   164     }
   122     if (mSize.height() < 1) {
   165     if (mSize.height() < 1) {
   123         mSize.setHeight(1);
   166         mSize.setHeight(1);
   124     }
   167     }
       
   168 
       
   169     // Convert millimeters to pixels
       
   170     mTouchThreshold = HbDeviceProfile::current().ppmValue() * HbInputInstantTouchThreshold;
   125 }
   171 }
   126 
   172 
   127 void HbInputButtonPrivate::setDefaultGraphics(int keyCode)
   173 void HbInputButtonPrivate::setDefaultGraphics(int keyCode)
   128 {
   174 {
   129     switch(keyCode) {
   175     switch(keyCode) {
   130         case HbInputButton::ButtonKeyCodeDelete:
   176     case HbInputButton::ButtonKeyCodeDelete:
   131             mIcons.replace(HbInputButton::ButtonTextIndexPrimary, HbIcon(HbInputButtonIconDelete));
   177         mIcons.replace(HbInputButton::ButtonTextIndexPrimary, HbIcon(HbInputButtonIconDelete));
   132             break;
   178         break;
   133         case HbInputButton::ButtonKeyCodeShift:
   179     case HbInputButton::ButtonKeyCodeShift:
   134             mIcons.replace(HbInputButton::ButtonTextIndexPrimary, HbIcon(HbInputButtonIconShift));
   180         mIcons.replace(HbInputButton::ButtonTextIndexPrimary, HbIcon(HbInputButtonIconShift));
   135             break;
   181         break;
   136         case HbInputButton::ButtonKeyCodeSymbol:
   182     case HbInputButton::ButtonKeyCodeSymbol:
   137             mIcons.replace(HbInputButton::ButtonTextIndexPrimary, HbIcon(HbInputButtonIconSymbol));
   183         mIcons.replace(HbInputButton::ButtonTextIndexPrimary, HbIcon(HbInputButtonIconSymbol));
   138             break;
   184         break;
   139         case HbInputButton::ButtonKeyCodeEnter:
   185     case HbInputButton::ButtonKeyCodeEnter:
   140             mIcons.replace(HbInputButton::ButtonTextIndexPrimary, HbIcon(HbInputButtonIconEnter));
   186         mIcons.replace(HbInputButton::ButtonTextIndexPrimary, HbIcon(HbInputButtonIconEnter));
   141             break;
   187         break;
   142         case HbInputButton::ButtonKeyCodeSpace:
   188     case HbInputButton::ButtonKeyCodeSpace:
   143             mIcons.replace(HbInputButton::ButtonTextIndexPrimary, HbIcon(HbInputButtonIconSpace));
   189         mIcons.replace(HbInputButton::ButtonTextIndexPrimary, HbIcon(HbInputButtonIconSpace));
   144             break;
   190         break;
   145         case HbInputButton::ButtonKeyCodeAlphabet:
   191     case HbInputButton::ButtonKeyCodeAlphabet:
   146             mIcons.replace(HbInputButton::ButtonTextIndexPrimary, HbIcon(HbInputButtonIconSymbol));
   192         mIcons.replace(HbInputButton::ButtonTextIndexPrimary, HbIcon(HbInputButtonIconSymbol));
   147             break;
   193         break;
   148         case HbInputButton::ButtonKeyCodeSmiley:
   194     case HbInputButton::ButtonKeyCodeSmiley:
   149             mIcons.replace(HbInputButton::ButtonTextIndexPrimary, HbIcon(HbInputButtonIconSmiley));
   195         mIcons.replace(HbInputButton::ButtonTextIndexPrimary, HbIcon(HbInputButtonIconSmiley));
   150             break;
   196         break;
   151         default:
   197     default:
   152             break;
   198         break;
   153     }
   199     }
   154 }
   200 }
   155 
   201 
   156 /// @endcond
   202 /// @endcond
       
   203 
       
   204 /*!
       
   205     \enum HbInputButton::HbInputButtonKeyCode
       
   206 
       
   207     This enum defines a set of predefined key codes for input button. ButtonKeyCodeCustom should
       
   208     always be the last item so that all values bigger than ButtonKeyCodeCustom can be interpreted
       
   209     as custom key codes
       
   210  */
       
   211 
       
   212 /*!
       
   213     \enum HbInputButton::HbInputButtonType
       
   214 
       
   215     This enum defines different button types. Button's graphics, text layout and functionality
       
   216     depend of the this type. ButtonTypeCount should always be the last value.
       
   217  */
       
   218 
       
   219 /*!
       
   220     \enum HbInputButton::HbInputButtonState
       
   221 
       
   222     This enum defines button states. State mostly affects the button's visual look in addition
       
   223     to what can be done with the button (i.e. no interaction with disabled buttons, released and
       
   224     latched buttons can be pressed). ButtonStateCount should always be the last value.
       
   225  */
       
   226 
       
   227 /*!
       
   228     \enum HbInputButton::HbInputButtonTextIndex
       
   229 
       
   230     This enum defines set of text indices that can be used when setting texts to different parts of
       
   231     a button using setText function. ButtonTextIndexCount should always be the last value.
       
   232  */
       
   233 
       
   234 /*!
       
   235     \enum HbInputButton::HbInputButtonIconIndex
       
   236 
       
   237     This enum defines set of icon indices that can be used when setting icons to different parts of
       
   238     a button using setIcon function. ButtonIconIndexCount should always be the last value.
       
   239  */
   157 
   240 
   158 /*!
   241 /*!
   159 Constructor
   242 Constructor
   160 */
   243 */
   161 HbInputButton::HbInputButton()
   244 HbInputButton::HbInputButton()
   208     return d->mType;
   291     return d->mType;
   209 }
   292 }
   210 
   293 
   211 /*!
   294 /*!
   212 Updates button's state.
   295 Updates button's state.
       
   296 State change sequence latched, pressed, released will result
       
   297 in a latched state. Otherwise the new state will be the given state.
   213 
   298 
   214 \sa state
   299 \sa state
   215 */
   300 */
   216 void HbInputButton::setState(HbInputButtonState state)
   301 void HbInputButton::setState(HbInputButtonState state)
   217 {
   302 {
   218     Q_D(HbInputButton);
   303     Q_D(HbInputButton);
   219 
   304 
   220     d->mState = state;
   305     if (state == ButtonStateReleased) {
       
   306         d->mTap = false;
       
   307         clearLastTriggeredPosition();
       
   308     }
       
   309 
       
   310     if (d->mState == ButtonStatePressed &&
       
   311         d->mPreviousState == ButtonStateLatched &&
       
   312         state == ButtonStateReleased) {
       
   313         d->mState = d->mPreviousState;
       
   314     } else {
       
   315         d->mPreviousState = d->mState;
       
   316         d->mState = state;
       
   317     }
   221 }
   318 }
   222 
   319 
   223 /*!
   320 /*!
   224 Returns button's state.
   321 Returns button's state.
   225 
   322 
   515     Q_D(const HbInputButton);
   612     Q_D(const HbInputButton);
   516 
   613 
   517     return d->mBoundingRect;
   614     return d->mBoundingRect;
   518 }
   615 }
   519 
   616 
       
   617 /*!
       
   618 \brief Returns an active touch area for current button.
       
   619 
       
   620 Button contains bounding rectangle for actual size of the item, while touch area
       
   621 can actually extend over buttons physical boundaries. This is to make interacting
       
   622 with button easier.
       
   623 
       
   624 \return Active touch area as a rectangle, centered to its button.
       
   625 \sa setBoundingRect
       
   626 */
       
   627 QRectF HbInputButton::activeTouchArea() const
       
   628 {
       
   629     Q_D(const HbInputButton);
       
   630 
       
   631     QRectF threshold(d->mBoundingRect);
       
   632 
       
   633     qreal mod_w = d->mBoundingRect.width() * HbInputThresholdMultiplier;
       
   634     qreal mod_h = d->mBoundingRect.height() * HbInputThresholdMultiplier;
       
   635     threshold.adjust(-mod_w, -mod_h, mod_w, mod_h);
       
   636 
       
   637     return threshold;
       
   638 }
       
   639 
       
   640 /*!
       
   641 \brief Set position where last user interaction occurred.
       
   642 */
       
   643 void HbInputButton::setLastTriggeredPosition(const QPointF &position)
       
   644 {
       
   645     Q_D(HbInputButton);
       
   646 
       
   647     d->mLastInteractionPoint = position;
       
   648 }
       
   649 
       
   650 /*!
       
   651 \brief Clear last user interaction data.
       
   652 */
       
   653 void HbInputButton::clearLastTriggeredPosition()
       
   654 {
       
   655     Q_D(HbInputButton);
       
   656 
       
   657     d->mLastInteractionPoint = HbInputInvalidPoint;
       
   658 }
       
   659 
       
   660 /*!
       
   661 Checks whether the new touch point position is close enough to the previous
       
   662 one that hit this button so that the new touch point can
       
   663 be interpreted as the same as the old one.
       
   664 */
       
   665 bool HbInputButton::wasTriggeredAt(const QPointF &position) const
       
   666 {
       
   667     Q_D(const HbInputButton);
       
   668 
       
   669     QRectF rect(d->mLastInteractionPoint.x() - HbInputTouchThreshold, d->mLastInteractionPoint.y() - HbInputTouchThreshold,
       
   670                 2 * HbInputTouchThreshold, 2 * HbInputTouchThreshold);
       
   671 
       
   672     return rect.contains(position);
       
   673 }
       
   674 
       
   675 /*!
       
   676 \brief Set position where the button was first touched.
       
   677 */
       
   678 void HbInputButton::setTouchPointPosition(const QPointF &position)
       
   679 {
       
   680     Q_D(HbInputButton);
       
   681 
       
   682     d->mTouchPoint = position;
       
   683     d->mTap = true;
       
   684     d->mTouchTime.start();
       
   685 }
       
   686 
       
   687 /*!
       
   688 Returns the current touch position which in case of
       
   689 a short tap is the touch down position and otherwise the
       
   690 last triggered position.
       
   691 */
       
   692 QPointF HbInputButton::currentTouchPointPosition() const
       
   693 {
       
   694     Q_D(const HbInputButton);
       
   695 
       
   696     if (d->mTap) {
       
   697         return d->mTouchPoint;
       
   698     }
       
   699     return d->mLastInteractionPoint;
       
   700 }
       
   701 
       
   702 /*!
       
   703 \brief Checks whether move to given \a position should be ignored or processed normally
       
   704 
       
   705 True is returned if given position is close enough to touch down point during
       
   706 short timeout after the button has been pressed or after timeout if the
       
   707 position is inside button's active touch area. Otherwise false is returned and
       
   708 move event should be handled normally.
       
   709 */
       
   710 bool HbInputButton::suppressMoveEvent(const QPointF &position)
       
   711 {
       
   712     Q_D(HbInputButton);
       
   713 
       
   714     // Check if the timeout from the touch down event has passed
       
   715     if (d->mTap && d->mTouchTime.elapsed() < HbInputInstantTouchTimeout) {
       
   716         // Create rectangle around touch down position
       
   717         QRectF rect(d->mTouchPoint.x() - d->mTouchThreshold, d->mTouchPoint.y() - d->mTouchThreshold,
       
   718                     2 * d->mTouchThreshold, 2 * d->mTouchThreshold);
       
   719 
       
   720         // If inside created rectangle, update last position and ignore the event
       
   721         if (rect.contains(position)) {
       
   722             setLastTriggeredPosition(position);
       
   723             return true;
       
   724         }
       
   725     // Check if new position is still inside active button
       
   726     } else if (activeTouchArea().contains(position)) {
       
   727         setLastTriggeredPosition(position);
       
   728         d->mTap = false;
       
   729         return true;
       
   730     }
       
   731 
       
   732     d->mTap = false;
       
   733     return false;
       
   734 }
       
   735 
   520 // End of file
   736 // End of file