From f6b2066ff3b5dbe469424ecffdc024082b7d7395 Mon Sep 17 00:00:00 2001 From: that Date: Thu, 25 Jun 2015 21:51:37 +0200 Subject: gui: keyboard: support longpress label offset, code cleanup To position the longpress label: x and y is the distance from the upper right corner. - extract method GUIKeyboard::DrawKey - clean up handling of currently pressed key - integrate key highlighting into main key drawing loops Change-Id: I80ccf2975d30cffa2a48627a74ab3693c84e4fa4 --- gui/keyboard.cpp | 265 ++++++++++++++++++++++++------------------------------- gui/objects.hpp | 5 +- 2 files changed, 120 insertions(+), 150 deletions(-) diff --git a/gui/keyboard.cpp b/gui/keyboard.cpp index 8ab2280a1..f35a5d318 100644 --- a/gui/keyboard.cpp +++ b/gui/keyboard.cpp @@ -35,7 +35,7 @@ GUIKeyboard::GUIKeyboard(xml_node<>* node) : GUIObject(node) { int layoutindex, rowindex, keyindex, Xindex, Yindex, keyHeight = 0, keyWidth = 0; - rowY = colX = -1; + currentKey = NULL; highlightRenderCount = 0; hasHighlight = hasCapsHighlight = false; char resource[10], layout[8], row[5], key[6], longpress[7]; @@ -79,6 +79,7 @@ GUIKeyboard::GUIKeyboard(xml_node<>* node) child = FindNode(node, "longpress"); mLongpressFont = PageManager::GetResources()->FindFont(LoadAttrString(child, "font", "keylabel-longpress")); mLongpressFontColor = LoadAttrColor(child, "textcolor", COLOR(128,128,128,255)); + LoadPlacement(child, &longpressOffsetX, &longpressOffsetY); LoadKeyLabels(node, 0); // load global key labels @@ -270,6 +271,78 @@ void GUIKeyboard::LoadKeyLabels(xml_node<>* parent, int layout) } } +void GUIKeyboard::DrawKey(Key& key, int keyX, int keyY, int keyW, int keyH) +{ + unsigned char keychar = key.key; + if (!keychar) + return; + + // key background + COLOR& c = (keychar >= 32 && keychar < 127) ? mKeyColorAlphanumeric : mKeyColorOther; + gr_color(c.red, c.green, c.blue, c.alpha); + keyX += mKeyMarginX; + keyY += mKeyMarginY; + keyW -= mKeyMarginX * 2; + keyH -= mKeyMarginY * 2; + gr_fill(keyX, keyY, keyW, keyH); + + // key label + FontResource* labelFont = mFont; + string labelText; + ImageResource* labelImage = NULL; + if (keychar > 32 && keychar < 127) { + labelText = (char) keychar; + gr_color(mFontColor.red, mFontColor.green, mFontColor.blue, mFontColor.alpha); + } + else { + // search for a special key label + for (std::vector::iterator it = mKeyLabels.begin(); it != mKeyLabels.end(); ++it) { + if (it->layout_from > 0 && it->layout_from != currentLayout) + continue; // this label is for another layout + if (it->key == key.key && it->layout_to == key.layout) + { + // found a label + labelText = it->text; + labelImage = it->image; + break; + } + } + labelFont = mSmallFont; + gr_color(mFontColorSmall.red, mFontColorSmall.green, mFontColorSmall.blue, mFontColorSmall.alpha); + } + + if (labelImage) + { + int w = labelImage->GetWidth(); + int h = labelImage->GetHeight(); + int x = keyX + (keyW - w) / 2; + int y = keyY + (keyH - h) / 2; + gr_blit(labelImage->GetResource(), 0, 0, w, h, x, y); + } + else if (!labelText.empty()) + { + void* fontResource = labelFont->GetResource(); + int textW = gr_measureEx(labelText.c_str(), fontResource); + int textH = labelFont->GetHeight(); + int textX = keyX + (keyW - textW) / 2; + int textY = keyY + (keyH - textH) / 2; + gr_textEx(textX, textY, labelText.c_str(), fontResource); + } + + // longpress key label (only if font is defined) + keychar = key.longpresskey; + if (keychar > 32 && keychar < 127 && mLongpressFont->GetResource()) { + void* fontResource = mLongpressFont->GetResource(); + gr_color(mLongpressFontColor.red, mLongpressFontColor.green, mLongpressFontColor.blue, mLongpressFontColor.alpha); + string text(1, keychar); + int textH = mLongpressFont->GetHeight(); + int textW = gr_measureEx(text.c_str(), fontResource); + int textX = keyX + keyW - longpressOffsetX - textW; + int textY = keyY + longpressOffsetY; + gr_textEx(textX, textY, text.c_str(), fontResource); + } +} + int GUIKeyboard::Render(void) { if (!isConditionTrue()) @@ -280,159 +353,55 @@ int GUIKeyboard::Render(void) Layout& lay = layouts[currentLayout - 1]; + bool drawKeys = false; if (lay.keyboardImg && lay.keyboardImg->GetResource()) + // keyboard is image based gr_blit(lay.keyboardImg->GetResource(), 0, 0, mRenderW, mRenderH, mRenderX, mRenderY); else { + // keyboard is software drawn + // fill background gr_color(mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, mBackgroundColor.alpha); gr_fill(mRenderX, mRenderY, mRenderW, mRenderH); - // draw keys - int y1 = 0; - for (int row = 0; row < MAX_KEYBOARD_ROWS; ++row) { - int rowY = mRenderY + y1; - int rowH = lay.row_end_y[row] - y1; - y1 = lay.row_end_y[row]; - int x1 = 0; - for (int col = 0; col < MAX_KEYBOARD_KEYS; ++col) { - Key& key = lay.keys[row][col]; - int keyY = rowY; - int keyH = rowH; - int keyX = mRenderX + x1; - int keyW = key.end_x - x1; - x1 = key.end_x; - - unsigned char keychar = key.key; - if (!keychar) - continue; - - // draw a single key - // key background - COLOR& c = (keychar >= 32 && keychar < 127) ? mKeyColorAlphanumeric : mKeyColorOther; - gr_color(c.red, c.green, c.blue, c.alpha); - keyX += mKeyMarginX; - keyY += mKeyMarginY; - keyW -= mKeyMarginX * 2; - keyH -= mKeyMarginY * 2; - gr_fill(keyX, keyY, keyW, keyH); - - // key label - FontResource* labelFont = mFont; - string labelText; - ImageResource* labelImage = NULL; - if (keychar > 32 && keychar < 127) { - labelText = (char) keychar; - gr_color(mFontColor.red, mFontColor.green, mFontColor.blue, mFontColor.alpha); - } - else { - /* - static const char* shiftLabels[] = {"abc", "ABC", "?123", "~\\{"}; - switch (keychar) { - case KEYBOARD_LAYOUT: - labelText = shiftLabels[key.layout - 1]; - break; - case KEYBOARD_BACKSPACE: - labelText = "Bksp"; - break; - case KEYBOARD_ACTION: - labelText = "Enter"; - break; - } - */ - // search for a special key label - for (std::vector::iterator it = mKeyLabels.begin(); it != mKeyLabels.end(); ++it) { - if (it->layout_from > 0 && it->layout_from != currentLayout) - continue; // this label is for another layout - if (it->key == key.key && it->layout_to == key.layout) - { - // found a label - labelText = it->text; - labelImage = it->image; - break; - } - } - labelFont = mSmallFont; - gr_color(mFontColorSmall.red, mFontColorSmall.green, mFontColorSmall.blue, mFontColorSmall.alpha); - } - - if (labelImage) - { - int w = labelImage->GetWidth(); - int h = labelImage->GetHeight(); - int x = keyX + (keyW - w) / 2; - int y = keyY + (keyH - h) / 2; - gr_blit(labelImage->GetResource(), 0, 0, w, h, x, y); - } - else if (!labelText.empty()) - { - void* fontResource = labelFont->GetResource(); - int textW = gr_measureEx(labelText.c_str(), fontResource); - int textH = labelFont->GetHeight(); - int textX = keyX + (keyW - textW) / 2; - int textY = keyY + (keyH - textH) / 2; - gr_textEx(textX, textY, labelText.c_str(), fontResource); - } + drawKeys = true; + } - // longpress key label (only if font is defined) - keychar = key.longpresskey; - if (keychar > 32 && keychar < 127 && mLongpressFont->GetResource()) { - void* fontResource = mLongpressFont->GetResource(); - gr_color(mLongpressFontColor.red, mLongpressFontColor.green, mLongpressFontColor.blue, mLongpressFontColor.alpha); - string text(1, keychar); - int textH = mLongpressFont->GetHeight(); - int textW = gr_measureEx(text.c_str(), fontResource); - int textX = keyX + keyW - 5 - textW; // TODO: configure these offsets - int textY = keyY + 0; - gr_textEx(textX, textY, text.c_str(), fontResource); - } + // draw keys + int y1 = 0; + for (int row = 0; row < MAX_KEYBOARD_ROWS; ++row) { + int rowY = mRenderY + y1; + int rowH = lay.row_end_y[row] - y1; + y1 = lay.row_end_y[row]; + int x1 = 0; + for (int col = 0; col < MAX_KEYBOARD_KEYS; ++col) { + Key& key = lay.keys[row][col]; + int keyY = rowY; + int keyH = rowH; + int keyX = mRenderX + x1; + int keyW = key.end_x - x1; + x1 = key.end_x; + + // Draw key for software drawn keyboard + if (drawKeys) + DrawKey(key, keyX, keyY, keyW, keyH); + + // Draw highlight for capslock + if (hasCapsHighlight && lay.is_caps && CapsLockOn && (int)key.key == KEYBOARD_LAYOUT && key.layout == lay.revert_layout) { + gr_color(mCapsHighlightColor.red, mCapsHighlightColor.green, mCapsHighlightColor.blue, mCapsHighlightColor.alpha); + gr_fill(keyX, keyY, keyW, keyH); } - } - } - // Draw highlight for capslock - // TODO: integrate with key drawing - if (hasCapsHighlight && lay.is_caps && CapsLockOn) { - gr_color(mCapsHighlightColor.red, mCapsHighlightColor.green, mCapsHighlightColor.blue, mCapsHighlightColor.alpha); - for (int indexy=0; indexy 0) - highlightRenderCount--; - } else + if (!hasHighlight || highlightRenderCount == 0) mRendered = true; - + else if (highlightRenderCount > 0) + highlightRenderCount--; return 0; } @@ -477,8 +446,6 @@ GUIKeyboard::Key* GUIKeyboard::HitTestKey(int x, int y) Key& key = lay.keys[row][col]; if (x1 <= relx && relx < key.end_x && key.key != 0) { // This is the key that was pressed! - rowY = row; - colX = col; return &key; } x1 = key.end_x; @@ -489,7 +456,6 @@ GUIKeyboard::Key* GUIKeyboard::HitTestKey(int x, int y) int GUIKeyboard::NotifyTouch(TOUCH_STATE state, int x, int y) { static int was_held = 0, startX = 0; - static Key* initial_key = 0; if (!isConditionTrue()) return -1; @@ -498,8 +464,8 @@ int GUIKeyboard::NotifyTouch(TOUCH_STATE state, int x, int y) case TOUCH_START: was_held = 0; startX = x; - initial_key = HitTestKey(x, y); - if (initial_key) + currentKey = HitTestKey(x, y); + if (currentKey) highlightRenderCount = -1; else highlightRenderCount = 0; @@ -528,7 +494,7 @@ int GUIKeyboard::NotifyTouch(TOUCH_STATE state, int x, int y) // fall through case TOUCH_HOLD: case TOUCH_REPEAT: - if (!initial_key) { + if (!currentKey) { if (highlightRenderCount != 0) { highlightRenderCount = 0; mRendered = false; @@ -544,15 +510,16 @@ int GUIKeyboard::NotifyTouch(TOUCH_STATE state, int x, int y) mRendered = false; } - if (HitTestKey(x, y) != initial_key) { + if (HitTestKey(x, y) != currentKey) { // We dragged off of the starting key + currentKey = NULL; if (highlightRenderCount != 0) { highlightRenderCount = 0; mRendered = false; } return 0; } else { - Key& key = *initial_key; + Key& key = *currentKey; Layout& lay = layouts[currentLayout - 1]; if (state == TOUCH_RELEASE && was_held == 0) { DataManager::Vibrate("tw_keyboard_vibrate"); diff --git a/gui/objects.hpp b/gui/objects.hpp index 881b39050..be1f9734f 100644 --- a/gui/objects.hpp +++ b/gui/objects.hpp @@ -853,6 +853,7 @@ protected: }; int ParseKey(const char* keyinfo, Key& key, int& Xindex, int keyWidth, bool longpress); void LoadKeyLabels(xml_node<>* parent, int layout); + void DrawKey(Key& key, int keyX, int keyY, int keyW, int keyH); enum { MAX_KEYBOARD_LAYOUTS = 5, @@ -886,7 +887,8 @@ protected: std::string mVariable; int currentLayout; bool CapsLockOn; - int rowY, colX, highlightRenderCount; + int highlightRenderCount; + Key* currentKey; bool hasHighlight, hasCapsHighlight; COLOR mHighlightColor; COLOR mCapsHighlightColor; @@ -895,6 +897,7 @@ protected: FontResource* mFont; // for main key labels FontResource* mSmallFont; // for key labels like "?123" FontResource* mLongpressFont; // for the small longpress label in the upper right corner + int longpressOffsetX, longpressOffsetY; // distance of the longpress label from the key corner COLOR mLongpressFontColor; COLOR mBackgroundColor; // keyboard background color COLOR mKeyColorAlphanumeric; // key background color -- cgit v1.2.3