gui: keyboard: support longpress label offset, code cleanup

To position the longpress label:
<longpress font="..." textcolor="..." x="5" y="0"/>
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
This commit is contained in:
that
2015-06-25 21:51:37 +02:00
committed by Dees Troy
parent 983be2a3fb
commit f6b2066ff3
2 changed files with 119 additions and 149 deletions

View File

@@ -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<KeyLabel>::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;
drawKeys = true;
}
unsigned char keychar = key.key;
if (!keychar)
continue;
// 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 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;
// 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);
}
// 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<KeyLabel>::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 - 5 - textW; // TODO: configure these offsets
int textY = keyY + 0;
gr_textEx(textX, textY, text.c_str(), fontResource);
}
// Highlight current key
if (hasHighlight && &key == currentKey && highlightRenderCount != 0) {
gr_color(mHighlightColor.red, mHighlightColor.green, mHighlightColor.blue, mHighlightColor.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<MAX_KEYBOARD_ROWS; indexy++) {
for (int indexx=0; indexx<MAX_KEYBOARD_KEYS; indexx++) {
if ((int)lay.keys[indexy][indexx].key == KEYBOARD_LAYOUT && (int)lay.keys[indexy][indexx].layout == lay.revert_layout) {
int boxheight, boxwidth, x;
if (indexy == 0)
boxheight = lay.row_end_y[indexy];
else
boxheight = lay.row_end_y[indexy] - lay.row_end_y[indexy - 1];
if (indexx == 0) {
x = mRenderX;
boxwidth = lay.keys[indexy][indexx].end_x;
} else {
x = mRenderX + lay.keys[indexy][indexx - 1].end_x;
boxwidth = lay.keys[indexy][indexx].end_x - lay.keys[indexy][indexx - 1].end_x;
}
gr_fill(x, mRenderY + lay.row_end_y[indexy - 1], boxwidth, boxheight);
}
}
}
}
// TODO: integrate with key drawing
if (hasHighlight && highlightRenderCount != 0) {
int boxheight, boxwidth, x;
if (rowY == 0)
boxheight = lay.row_end_y[rowY];
else
boxheight = lay.row_end_y[rowY] - lay.row_end_y[rowY - 1];
if (colX == 0) {
x = mRenderX;
boxwidth = lay.keys[rowY][colX].end_x;
} else {
x = mRenderX + lay.keys[rowY][colX - 1].end_x;
boxwidth = lay.keys[rowY][colX].end_x - lay.keys[rowY][colX - 1].end_x;
}
gr_color(mHighlightColor.red, mHighlightColor.green, mHighlightColor.blue, mHighlightColor.alpha);
gr_fill(x, mRenderY + lay.row_end_y[rowY - 1], boxwidth, boxheight);
if (highlightRenderCount > 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");

View File

@@ -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