gui: keyboard: introduce struct Layout and simplify caps handling

Also minor cleanups:
- move array limits from #defines to a protected enum
- zero fill layouts in ctor

Change-Id: I8fe0f8465ebc646ad3bf3cc3f8490dbdd384f43d
This commit is contained in:
that
2015-03-15 00:56:57 +01:00
parent e79878b7b6
commit d86f49d3f7
2 changed files with 71 additions and 78 deletions

View File

@@ -44,11 +44,15 @@ GUIKeyboard::GUIKeyboard(xml_node<>* node)
xml_node<>* keylayout;
xml_node<>* keyrow;
for (layoutindex=0; layoutindex<MAX_KEYBOARD_LAYOUTS; layoutindex++)
keyboardImg[layoutindex] = NULL;
for (layoutindex=0; layoutindex<MAX_KEYBOARD_LAYOUTS; layoutindex++) {
layouts[layoutindex].keyboardImg = NULL;
memset(layouts[layoutindex].keys, 0, sizeof(Layout::keys));
memset(layouts[layoutindex].row_end_y, 0, sizeof(Layout::row_end_y));
}
mRendered = false;
currentLayout = 1;
CapsLockOn = false;
KeyboardHeight = KeyboardWidth = 0;
if (!node) return;
@@ -56,6 +60,7 @@ GUIKeyboard::GUIKeyboard(xml_node<>* node)
mHighlightColor = LoadAttrColor(FindNode(node, "highlight"), "color", &hasHighlight);
mCapsHighlightColor = LoadAttrColor(FindNode(node, "capshighlight"), "color", &hasCapsHighlight);
// compatibility ugliness: resources should be specified in the layouts themselves instead
// Load the images for the different layouts
child = FindNode(node, "layout");
if (child)
@@ -64,7 +69,7 @@ GUIKeyboard::GUIKeyboard(xml_node<>* node)
strcpy(resource, "resource1");
attr = child->first_attribute(resource);
while (attr && layoutindex < (MAX_KEYBOARD_LAYOUTS + 1)) {
keyboardImg[layoutindex - 1] = LoadAttrImage(child, resource);
layouts[layoutindex - 1].keyboardImg = LoadAttrImage(child, resource);
layoutindex++;
resource[8] = (char)(layoutindex + 48);
@@ -73,10 +78,10 @@ GUIKeyboard::GUIKeyboard(xml_node<>* node)
}
// Check the first image to get height and width
if (keyboardImg[0] && keyboardImg[0]->GetResource())
if (layouts[0].keyboardImg && layouts[0].keyboardImg->GetResource())
{
KeyboardWidth = keyboardImg[0]->GetWidth();
KeyboardHeight = keyboardImg[0]->GetHeight();
KeyboardWidth = layouts[0].keyboardImg->GetWidth();
KeyboardHeight = layouts[0].keyboardImg->GetHeight();
}
// Load all of the layout maps
@@ -90,29 +95,15 @@ GUIKeyboard::GUIKeyboard(xml_node<>* node)
return;
}
Layout& lay = layouts[layoutindex - 1];
child = keylayout->first_node("keysize");
if (child) {
attr = child->first_attribute("height");
if (attr)
keyHeight = scale_theme_y(atoi(attr->value()));
else
keyHeight = 0;
attr = child->first_attribute("width");
if (attr)
keyWidth = scale_theme_x(atoi(attr->value()));
else
keyWidth = 0;
attr = child->first_attribute("capslock");
if (attr)
caps_tracking[layoutindex - 1].capslock = atoi(attr->value());
else
caps_tracking[layoutindex - 1].capslock = 1;
attr = child->first_attribute("revert_layout");
if (attr)
caps_tracking[layoutindex - 1].revert_layout = atoi(attr->value());
else
caps_tracking[layoutindex - 1].revert_layout = -1;
}
keyHeight = LoadAttrIntScaleY(child, "height", 0);
keyWidth = LoadAttrIntScaleX(child, "width", 0);
// compatibility ugliness: capslock="0" means that this is the caps layout. Also it has nothing to do with keysize.
lay.is_caps = (LoadAttrInt(child, "capslock", 1) == 0);
// compatibility ugliness: revert_layout has nothing to do with keysize.
lay.revert_layout = LoadAttrInt(child, "revert_layout", -1);
rowindex = 1;
Yindex = 0;
@@ -126,7 +117,7 @@ GUIKeyboard::GUIKeyboard(xml_node<>* node)
}
Yindex += keyHeight;
row_heights[layoutindex - 1][rowindex - 1] = Yindex;
lay.row_end_y[rowindex - 1] = Yindex;
keyindex = 1;
Xindex = 0;
@@ -146,7 +137,7 @@ GUIKeyboard::GUIKeyboard(xml_node<>* node)
return;
}
if (ParseKey(keyinfo, keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1], Xindex, keyWidth, false))
if (ParseKey(keyinfo, lay.keys[rowindex - 1][keyindex - 1], Xindex, keyWidth, false))
LOGERR("Invalid key info on layout%i, row%i, key%02i.\n", layoutindex, rowindex, keyindex);
@@ -161,7 +152,7 @@ GUIKeyboard::GUIKeyboard(xml_node<>* node)
return;
}
if (ParseKey(keyinfo, keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1], Xindex, keyWidth, true))
if (ParseKey(keyinfo, lay.keys[rowindex - 1][keyindex - 1], Xindex, keyWidth, true))
LOGERR("Invalid long press key info on layout%i, row%i, long%02i.\n", layoutindex, rowindex, keyindex);
}
keyindex++;
@@ -239,30 +230,30 @@ int GUIKeyboard::Render(void)
return 0;
}
int ret = 0;
Layout& lay = layouts[currentLayout - 1];
if (keyboardImg[currentLayout - 1] && keyboardImg[currentLayout - 1]->GetResource())
gr_blit(keyboardImg[currentLayout - 1]->GetResource(), 0, 0, KeyboardWidth, KeyboardHeight, mRenderX, mRenderY);
if (lay.keyboardImg && lay.keyboardImg->GetResource())
gr_blit(lay.keyboardImg->GetResource(), 0, 0, KeyboardWidth, KeyboardHeight, mRenderX, mRenderY);
// Draw highlight for capslock
if (hasCapsHighlight && caps_tracking[currentLayout - 1].capslock == 0 && caps_tracking[currentLayout - 1].set_capslock) {
int boxheight, boxwidth, x;
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)keyboard_keys[currentLayout - 1][indexy][indexx].key == KEYBOARD_LAYOUT && (int)keyboard_keys[currentLayout - 1][indexy][indexx].layout == caps_tracking[currentLayout - 1].revert_layout) {
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 = row_heights[currentLayout - 1][indexy];
boxheight = lay.row_end_y[indexy];
else
boxheight = row_heights[currentLayout - 1][indexy] - row_heights[currentLayout - 1][indexy - 1];
boxheight = lay.row_end_y[indexy] - lay.row_end_y[indexy - 1];
if (indexx == 0) {
x = mRenderX;
boxwidth = keyboard_keys[currentLayout - 1][indexy][indexx].end_x;
boxwidth = lay.keys[indexy][indexx].end_x;
} else {
x = mRenderX + keyboard_keys[currentLayout - 1][indexy][indexx - 1].end_x;
boxwidth = keyboard_keys[currentLayout - 1][indexy][indexx].end_x - keyboard_keys[currentLayout - 1][indexy][indexx - 1].end_x;
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 + row_heights[currentLayout - 1][indexy - 1], boxwidth, boxheight);
gr_fill(x, mRenderY + lay.row_end_y[indexy - 1], boxwidth, boxheight);
}
}
}
@@ -271,24 +262,24 @@ int GUIKeyboard::Render(void)
if (hasHighlight && highlightRenderCount != 0) {
int boxheight, boxwidth, x;
if (rowY == 0)
boxheight = row_heights[currentLayout - 1][rowY];
boxheight = lay.row_end_y[rowY];
else
boxheight = row_heights[currentLayout - 1][rowY] - row_heights[currentLayout - 1][rowY - 1];
boxheight = lay.row_end_y[rowY] - lay.row_end_y[rowY - 1];
if (colX == 0) {
x = mRenderX;
boxwidth = keyboard_keys[currentLayout - 1][rowY][colX].end_x;
boxwidth = lay.keys[rowY][colX].end_x;
} else {
x = mRenderX + keyboard_keys[currentLayout - 1][rowY][colX - 1].end_x;
boxwidth = keyboard_keys[currentLayout - 1][rowY][colX].end_x - keyboard_keys[currentLayout - 1][rowY][colX - 1].end_x;
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 + row_heights[currentLayout - 1][rowY - 1], boxwidth, boxheight);
gr_fill(x, mRenderY + lay.row_end_y[rowY - 1], boxwidth, boxheight);
if (highlightRenderCount > 0)
highlightRenderCount--;
} else
mRendered = true;
return ret;
return 0;
}
int GUIKeyboard::Update(void)
@@ -317,10 +308,12 @@ GUIKeyboard::Key* GUIKeyboard::HitTestKey(int x, int y)
int rely = y - mRenderY;
int relx = x - mRenderX;
Layout& lay = layouts[currentLayout - 1];
// Find the correct row
int row;
for (row = 0; row < MAX_KEYBOARD_ROWS; ++row) {
if (row_heights[currentLayout - 1][row] > rely)
if (lay.row_end_y[row] > rely)
break;
}
if (row == MAX_KEYBOARD_ROWS)
@@ -330,7 +323,7 @@ GUIKeyboard::Key* GUIKeyboard::HitTestKey(int x, int y)
int col;
int x1 = 0;
for (col = 0; col < MAX_KEYBOARD_KEYS; ++col) {
Key& key = keyboard_keys[currentLayout - 1][row][col];
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;
@@ -409,26 +402,15 @@ int GUIKeyboard::NotifyTouch(TOUCH_STATE state, int x, int y)
return 0;
} else {
Key& key = *initial_key;
Layout& lay = layouts[currentLayout - 1];
if (state == TOUCH_RELEASE && was_held == 0) {
DataManager::Vibrate("tw_keyboard_vibrate");
if ((int)key.key < KEYBOARD_SPECIAL_KEYS && (int)key.key > 0) {
// Regular key
PageManager::NotifyKeyboard(key.key);
if (caps_tracking[currentLayout - 1].capslock == 0 && !caps_tracking[currentLayout - 1].set_capslock) {
// caps lock was not set, change layouts
currentLayout = caps_tracking[currentLayout - 1].revert_layout;
mRendered = false;
}
} else if ((int)key.key == KEYBOARD_LAYOUT) {
if ((int)key.key == KEYBOARD_LAYOUT) {
// Switch layouts
if (caps_tracking[currentLayout - 1].capslock == 0 && key.layout == caps_tracking[currentLayout - 1].revert_layout) {
if (!caps_tracking[currentLayout - 1].set_capslock) {
caps_tracking[currentLayout - 1].set_capslock = 1; // Set the caps lock
} else {
caps_tracking[currentLayout - 1].set_capslock = 0; // Unset the caps lock and change layouts
currentLayout = key.layout;
}
if (lay.is_caps && key.layout == lay.revert_layout && !CapsLockOn) {
CapsLockOn = true; // Set the caps lock
} else {
CapsLockOn = false; // Unset the caps lock and change layouts
currentLayout = key.layout;
}
mRendered = false;
@@ -437,6 +419,14 @@ int GUIKeyboard::NotifyTouch(TOUCH_STATE state, int x, int y)
highlightRenderCount = 0;
// Send action notification
PageManager::NotifyKeyboard(key.key);
} else if ((int)key.key < KEYBOARD_SPECIAL_KEYS && (int)key.key > 0) {
// Regular key
PageManager::NotifyKeyboard(key.key);
if (!CapsLockOn && lay.is_caps) {
// caps lock was not set, change layouts
currentLayout = lay.revert_layout;
mRendered = false;
}
}
} else if (state == TOUCH_HOLD) {
was_held = 1;

View File

@@ -815,9 +815,6 @@ protected:
int sUpdate;
};
#define MAX_KEYBOARD_LAYOUTS 5
#define MAX_KEYBOARD_ROWS 9
#define MAX_KEYBOARD_KEYS 20
#define KEYBOARD_ACTION 253
#define KEYBOARD_LAYOUT 254
#define KEYBOARD_SWIPE_LEFT 252
@@ -852,23 +849,29 @@ protected:
int layout;
};
int ParseKey(const char* keyinfo, Key& key, int& Xindex, int keyWidth, bool longpress);
struct capslock_tracking_struct
enum {
MAX_KEYBOARD_LAYOUTS = 5,
MAX_KEYBOARD_ROWS = 9,
MAX_KEYBOARD_KEYS = 20
};
struct Layout
{
int capslock;
int set_capslock;
ImageResource* keyboardImg;
struct Key keys[MAX_KEYBOARD_ROWS][MAX_KEYBOARD_KEYS];
int row_end_y[MAX_KEYBOARD_ROWS];
bool is_caps;
int revert_layout;
};
Layout layouts[MAX_KEYBOARD_LAYOUTS];
// Find key at screen coordinates
Key* HitTestKey(int x, int y);
ImageResource* keyboardImg[MAX_KEYBOARD_LAYOUTS];
struct Key keyboard_keys[MAX_KEYBOARD_LAYOUTS][MAX_KEYBOARD_ROWS][MAX_KEYBOARD_KEYS];
struct capslock_tracking_struct caps_tracking[MAX_KEYBOARD_LAYOUTS];
bool mRendered;
std::string mVariable;
int currentLayout;
int row_heights[MAX_KEYBOARD_LAYOUTS][MAX_KEYBOARD_ROWS];
bool CapsLockOn;
unsigned int KeyboardWidth, KeyboardHeight;
int rowY, colX, highlightRenderCount;
bool hasHighlight, hasCapsHighlight;