telutils/dialpad/src/dialpadkeypad.cpp
changeset 39 cee7e9e0906c
parent 32 1f002146abb4
child 50 2313cb430f28
--- a/telutils/dialpad/src/dialpadkeypad.cpp	Tue Jul 06 14:53:02 2010 +0300
+++ b/telutils/dialpad/src/dialpadkeypad.cpp	Wed Aug 18 10:19:22 2010 +0300
@@ -25,9 +25,12 @@
 #include <hbinputsettingproxy.h>
 #include <hbinputlanguage.h>
 #include <hbapplication.h>
+#include <hbcolorscheme.h>
 #include <hblineedit.h>
-#include <hbinputbutton.h>
+#include <hbfontspec.h>
+#include <hbevent.h>
 
+#include "dialpadnumericbutton.h"
 #include "dialpadkeypad.h"
 #include "dialpadbutton.h"
 #include "dialpadinputfield.h"
@@ -36,7 +39,12 @@
 static const int DialpadColumnCount = 3;
 static const QLatin1String handsetIcon("qtg_mono_call");
 static const QLatin1String vmbxIcon("qtg_mono_voice_mailbox");
-static const qreal DialpadKeypadBorderWidth = 0.25;
+// layout values in units
+static const qreal DialpadPrimaryTextSize = 5.5;
+static const qreal DialpadSecondaryTextSize = 4.0;
+static const qreal DialpadIconSize = 4.0;
+static const qreal DialpadPrimaryTextLeftMargin  = 1.5;
+static const qreal DialpadPrimarySecondaryMargin  = 0.75;
 
 static const int DialpadKeyCodeTable[DialpadRowCount*DialpadColumnCount] =
 {
@@ -53,7 +61,8 @@
     QGraphicsItem* parent) :
     HbInputButtonGroup(parent),
     mMainWindow(mainWindow),
-    mInputField(inputField)
+    mInputField(inputField),
+    mMaxPrimaryLineWidth(0)
 {
     setObjectName("keypad");
 
@@ -70,12 +79,12 @@
 
     // create keypad
     setGridSize(QSize(DialpadColumnCount, DialpadRowCount));
-    setButtonBorderSize(DialpadKeypadBorderWidth);
+    setButtonBorderSize(0);    
 
     QList<HbInputButton*> buttons;
 
     for (int i = 0; i < DialpadRowCount * DialpadColumnCount; ++i) {
-        HbInputButton *item = new HbInputButton(
+        DialpadNumericButton *item = new DialpadNumericButton(
             DialpadKeyCodeTable[i],
             QPoint(i % DialpadColumnCount, i / DialpadColumnCount));
         buttons.append(item);
@@ -114,13 +123,16 @@
     // set button texts
     setButtonTexts();
     // set button icons
-    button(0)->setIcon(HbIcon(vmbxIcon),
-        HbInputButton::ButtonIconIndexSecondaryFirstRow);
+    button(0)->setIcon(HbIcon(vmbxIcon));
 
     // update button texts when input language is changed
     connect(HbInputSettingProxy::instance(),
             SIGNAL(globalInputLanguageChanged(HbInputLanguage)),
             this,SLOT(setButtonTexts()));
+
+    updateColorArray();
+
+    mUnit = HbDeviceProfile::profile(this).unitValue();
 }
 
 DialpadKeypad::~DialpadKeypad()
@@ -144,10 +156,8 @@
             if (keyCode == Qt::Key_Asterisk) {
                 // asterisk is not localized
                 QChar asterisk('*');
-                button(i)->setText(asterisk,
-                    HbInputButton::ButtonTextIndexPrimary);
-                button(i)->setText("+",
-                    HbInputButton::ButtonTextIndexSecondaryFirstRow);
+                button(i)->setText(asterisk);
+                button(i)->setSecondaryText(QLatin1String("+"));
                 mGeneratedChar.insert(Qt::Key_Asterisk, asterisk);
                 continue;
             }
@@ -155,10 +165,7 @@
             if (keyCode == Qt::Key_NumberSign) {
                 // number sign is not localized
                 QChar numberSign('#');
-                button(i)->setText(numberSign,
-                    HbInputButton::ButtonTextIndexPrimary);
-                button(i)->setText(" ",
-                    HbInputButton::ButtonTextIndexSecondaryFirstRow);
+                button(i)->setText(numberSign);
                 mGeneratedChar.insert(Qt::Key_NumberSign, numberSign);
                 continue;
             }
@@ -175,11 +182,11 @@
                 QChar numberChar =
                     HbInputUtils::findFirstNumberCharacterBoundToKey(
                         key,
-                        inputLanguage.language());
+                        inputLanguage.language(),
+                        HbInputUtils::inputDigitType(inputLanguage.language()));
 
                 // button text
-                button(i)->setText(numberChar,
-                    HbInputButton::ButtonTextIndexPrimary);
+                button(i)->setText(numberChar);
                 mGeneratedChar.insert(keyCode,numberChar);
 
                 // additional text (letters)
@@ -194,12 +201,8 @@
 
                 QString characters = key->characters(HbModifierNone);
 
-                if (numberOfCharacters==0 && keyCode!=Qt::Key_1) {
-                    button(i)->setText(" ",
-                        HbInputButton::ButtonTextIndexSecondaryFirstRow);
-                } else {
-                    button(i)->setText(characters.left(numberOfCharacters),
-                        HbInputButton::ButtonTextIndexSecondaryFirstRow);
+                if (numberOfCharacters!=0 && keyCode!=Qt::Key_1) {
+                    button(i)->setSecondaryText(characters.left(numberOfCharacters));
                 }
             }
         }
@@ -229,12 +232,15 @@
 
 void DialpadKeypad::sendKeyPressEvent(const QKeyEvent& event)
 {
+    updateButtonLabels();
     mPressedNumericKey = event.key();
     postKeyEvent(QEvent::KeyPress, event.key());
 }
 
 void DialpadKeypad::sendKeyReleaseEvent(const QKeyEvent& event)
 {
+    updateButtonLabels();
+
     if (mPressedNumericKey) {
         // short press, update editor here
         sendKeyEventToEditor(QEvent::KeyPress, event.key());
@@ -246,7 +252,6 @@
 void DialpadKeypad::sendLongPressEvent(const QKeyEvent& event)
 {
     sendKeyEventToEditor(QEvent::KeyPress, event.key());
-    resetButtons();
     mPressedNumericKey = 0;
 }
 
@@ -275,3 +280,298 @@
 {
     return *mCallButton;
 }
+
+DialpadNumericButton* DialpadKeypad::button(int i) const
+{
+    return static_cast<DialpadNumericButton*>(HbInputButtonGroup::button(i));
+}
+
+void DialpadKeypad::updateButtonLabels()
+{
+    // update numeric buttons according to button state (pressed/released)
+    updateIconColor();
+    updateTextLayouts(rect().size());
+}
+
+void DialpadKeypad::paint(
+    QPainter* painter,
+    const QStyleOptionGraphicsItem* option,
+    QWidget* widget)
+{
+    Q_UNUSED(option);
+    Q_UNUSED(widget);
+
+    // Paints empty buttons
+    HbInputButtonGroup::paint(painter,option,widget);
+
+    qreal cellWidth = boundingRect().width() / gridSize().width();
+    qreal cellHeight = boundingRect().height() / gridSize().height();
+
+    // Draw icons
+    for (int i = 0; i < DialpadRowCount * DialpadColumnCount; i++) {
+        DialpadNumericButton *item = button(i);
+
+        if (!item->icon().isNull()) {
+            // icon is centered to button
+            qreal x = (item->position().x() * cellWidth) + (cellWidth / 2) -
+                      ((DialpadIconSize * mUnit) / 2);
+            qreal y = (item->position().y() * cellHeight) +  (cellHeight / 2) -
+                      ((DialpadIconSize * mUnit) / 2);
+
+            qreal width = DialpadIconSize * mUnit;
+            qreal height = DialpadIconSize * mUnit;
+
+            Qt::Alignment alignment =
+                static_cast<Qt::Alignment>(Qt::AlignVCenter | Qt::AlignHCenter);
+            item->icon().paint(painter,
+                               QRectF(x,y,width,height),
+                               Qt::KeepAspectRatio,
+                               alignment);
+        }                      
+    }
+
+    // Draw texts
+    QPen origPen = painter->pen();
+    for (int i = 0; i < mTextLayouts.count(); ++i) {
+        if (i==SecondaryText) {
+            // dimmed in normal state
+            painter->setPen(mColors.at(Pressed+1));
+        } else {
+            // otherwise normal or pressed color
+            painter->setPen(mColors.at(i/TextTypeCount));
+        }
+        mTextLayouts.at(i)->draw(painter, QPointF(0, 0));
+    }
+    painter->setPen(origPen);
+}
+
+void DialpadKeypad::updateColorArray()
+{
+    mColors.clear();
+
+    QColor normalColor = HbColorScheme::color("qtc_input_button_normal");
+    mColors.insert(Normal, normalColor);
+
+    QColor pressedColor = HbColorScheme::color("qtc_input_button_pressed");
+    mColors.insert(Pressed, pressedColor);
+
+    // this is used for alphabets shown dimmed, use alpha until exact color
+    // is specified
+    QColor disabledColor = HbColorScheme::color("qtc_input_button_normal");
+    disabledColor.setAlpha(128);
+    mColors.insert(Pressed+1, disabledColor);
+}
+
+void DialpadKeypad::updateIconColor()
+{
+    for (int i = 0; i < (DialpadRowCount * DialpadColumnCount); i++) {
+        DialpadNumericButton *item = button(i);
+
+        if (item->state()==HbInputButton::ButtonStatePressed) {
+            item->icon().setColor(mColors.at(Pressed));
+        } else {
+            item->icon().setColor(mColors.at(Normal));
+        }
+    }
+}
+
+void DialpadKeypad::cancelButtonPress()
+{
+    HbInputButtonGroup::cancelButtonPress();
+    updateButtonLabels();
+}
+
+void DialpadKeypad::setGeometry(const QRectF &rect)
+{
+    HbInputButtonGroup::setGeometry(rect);
+    updateTextLayouts(rect.size());
+}
+
+void DialpadKeypad::changeEvent(QEvent *event)
+{
+    HbInputButtonGroup::changeEvent(event);
+
+    if (event->type() == HbEvent::ThemeChanged) {
+        updateColorArray();
+        updateIconColor();
+    }
+}
+
+void DialpadKeypad::updateTextLayouts(const QSizeF &size)
+{
+    if (!size.width() && !size.height()) {
+        return;
+    }
+
+    // get normal and pressed state texts
+    QList<QString> textContent;
+    resolveTextContent(textContent);
+
+    // layout the texts
+    createTextLayouts(size, textContent);
+}
+
+void DialpadKeypad::resolveTextContent(QList<QString> &content)
+{
+    QString normalState;
+    QString normalStateSecondary;
+    QString pressedState;
+    QString pressedStateSecondary;
+
+    for (int i = 0; i < (DialpadRowCount*DialpadColumnCount); i++) {
+        DialpadNumericButton *item = button(i);
+        if (item->state()==HbInputButton::ButtonStatePressed) {
+            if (item->text().length()) {
+                pressedState.append(item->text());
+                pressedState.append(QChar(QChar::LineSeparator));
+            }
+
+            if (item->secondaryText().length()) {
+                pressedStateSecondary.append(item->secondaryText());
+                pressedStateSecondary.append(QChar(QChar::LineSeparator));
+            }
+        } else { // ButtonStateNormal
+            if (item->text().length()) {
+                normalState.append(item->text());
+                normalState.append(QChar(QChar::LineSeparator));
+            }
+
+            if (item->secondaryText().length()) {
+                normalStateSecondary.append(item->secondaryText());
+                normalStateSecondary.append(QChar(QChar::LineSeparator));
+            }
+        }
+    }
+
+    content.insert(PrimaryText, normalState);
+    content.insert(SecondaryText, normalStateSecondary);
+    content.insert(TextTypeCount + Pressed, pressedState);
+    content.insert(StateCount + SecondaryText, pressedStateSecondary);
+}
+
+void DialpadKeypad::createTextLayouts(
+    const QSizeF &size, const QList<QString> &content)
+{
+    // clear old layouts
+    qDeleteAll(mTextLayouts);
+    mTextLayouts.clear();
+
+    if (content.count()==2) {
+        // line width is measured only when all buttons are in normal state
+        mMaxPrimaryLineWidth = 0;
+    }
+
+    QFont primaryfFont = HbFontSpec(HbFontSpec::Primary).font();
+    primaryfFont.setPixelSize(DialpadPrimaryTextSize * mUnit);
+
+    QFont secondaryFont = HbFontSpec(HbFontSpec::Secondary).font();
+    secondaryFont.setPixelSize(DialpadSecondaryTextSize * mUnit);
+
+    for (int i=0; i < (StateCount*TextTypeCount); i++ ) {
+        QString text = content.at(i);
+
+        if (!text.isNull()) {
+            QTextLayout* textLayout;
+            int type;
+
+            if (i%TextTypeCount) {
+                textLayout = new QTextLayout(text,secondaryFont);
+                type = SecondaryText;
+            } else {
+                textLayout = new QTextLayout(text,primaryfFont);
+                type = PrimaryText;
+            }
+
+            mTextLayouts.append(textLayout);
+
+            textLayout->beginLayout();
+
+            int state = (i>=TextTypeCount) ? Pressed : Normal;
+
+            layoutTextLines(size,*textLayout,state,type);
+
+            textLayout->endLayout();
+
+            textLayout->setCacheEnabled(true);
+        }
+    }
+}
+
+void DialpadKeypad::layoutTextLines(
+    const QSizeF &size,
+    QTextLayout &textLayout,
+    int state,
+    int type)
+{
+    QFontMetricsF fontMetrics(textLayout.font());
+    qreal textHeight = fontMetrics.height();
+
+    qreal cellWidth = size.width() / gridSize().width();
+    qreal cellHeight = size.height() / gridSize().height();
+    qreal maxLineWidth = 0;
+
+    for (int j = 0; j < (DialpadRowCount*DialpadColumnCount); j++) {
+        DialpadNumericButton *item = button(j);
+
+        if ((type==PrimaryText && item->text().isNull()) ||
+            (type==SecondaryText && item->secondaryText().isNull())) {
+            continue; // no text for this button -> next button
+        }
+
+        if ( ( state==Normal &&
+               item->state()==HbInputButton::ButtonStateReleased ) ||
+             ( state==Pressed &&
+               item->state()==HbInputButton::ButtonStatePressed ) ) {
+
+            QTextLine line = textLayout.createLine();
+
+            qreal textPositionX = 0;
+            qreal textPositionY = 0;
+
+            if (line.isValid()) {
+                line.setNumColumns(item->text().length());
+                // layout text line
+                if (type==SecondaryText) {
+                    if (j==9) {
+                        // + is centered to button
+                        qreal lineWidth = fontMetrics.width(item->text());
+                        textPositionX = (item->position().x() * cellWidth) +
+                                        (cellWidth / 2) -
+                                        (lineWidth / 2);
+                        textPositionY = (item->position().y() +
+                                        (0.5 * item->size().height())) *
+                                        cellHeight - (0.5 * textHeight);
+
+                    } else {
+                        textPositionX = (item->position().x() * cellWidth) +
+                                        (DialpadPrimaryTextLeftMargin * mUnit) +
+                                        mMaxPrimaryLineWidth +
+                                        (DialpadPrimarySecondaryMargin * mUnit)
+                                        + buttonBorderSize();
+                        textPositionY = (item->position().y() +
+                                        (0.5 * item->size().height())) *
+                                        cellHeight - (0.5 * textHeight);
+                    }                    
+                } else {
+                    textPositionX = (item->position().x() * cellWidth) +
+                                    (DialpadPrimaryTextLeftMargin * mUnit)
+                                    + buttonBorderSize();
+                    textPositionY = (item->position().y() +
+                                    (0.5 * item->size().height())) *
+                                    cellHeight - (0.5 * textHeight);
+
+                    // store line width, for drawing secondary text
+                    qreal lineWidth = fontMetrics.width(item->text());
+                    if (mMaxPrimaryLineWidth == 0 && (j>0 && j<10) &&
+                        lineWidth > maxLineWidth) {
+                        maxLineWidth = lineWidth;
+                    }
+                }
+            }
+
+            line.setPosition(QPointF(textPositionX, textPositionY));
+        }
+    }
+
+    mMaxPrimaryLineWidth = maxLineWidth;
+}