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:
263
gui/keyboard.cpp
263
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<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");
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user