Updated software keyboard to center, and provice press indicators
This commit is contained in:
+144
-29
@@ -79,7 +79,8 @@ const char * const KEYBOARD_NUMBERS[] = {
|
||||
KEYBOARD_SET_LETTERS KEYBOARD_SPACE KEYBOARD_ENTER
|
||||
};
|
||||
|
||||
const char * const * const KEYBOARD_LAYOUTS[] = {
|
||||
#define NUMBER_OF_KEYBOARD_LAYOUTS 4
|
||||
const char * const * const KEYBOARD_LAYOUTS[NUMBER_OF_KEYBOARD_LAYOUTS] = {
|
||||
KEYBOARD_UPPERCASE,
|
||||
KEYBOARD_LOWERCASE,
|
||||
KEYBOARD_LOWERCASE,
|
||||
@@ -97,70 +98,169 @@ TextKeyboard::~TextKeyboard()
|
||||
_instance = nullptr;
|
||||
}
|
||||
|
||||
int TextKeyboard::getCharWidth(const char c)
|
||||
{
|
||||
if (int8_t(c) < 0) return KEYBOARD_BITMAP_WIDTH;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case ' ': return 15;
|
||||
case KEYBOARD_SPACE[0]: return KEYBOARD_SPACE_WIDTH;
|
||||
case KEYBOARD_ENTER[0]: return KEYBOARD_ENTER_WIDTH;
|
||||
default: return KEYBOARD_CHAR_WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int TextKeyboard::calculateMaxWidth()
|
||||
{
|
||||
int maxWidth = 0;
|
||||
for (uint8_t i = 0; i < NUMBER_OF_KEYBOARD_LAYOUTS; i++) {
|
||||
int lineWidth = 0;
|
||||
const char * c = layout[i];
|
||||
while (*c) {
|
||||
lineWidth += getCharWidth(*c);
|
||||
maxWidth = max(lineWidth, maxWidth);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
return maxWidth;
|
||||
}
|
||||
|
||||
void TextKeyboard::paint(BitmapBuffer * dc)
|
||||
{
|
||||
lcdSetColor(RGB(0xE0, 0xE0, 0xE0));
|
||||
dc->clear(CUSTOM_COLOR);
|
||||
|
||||
for (uint8_t i=0; i<4; i++) {
|
||||
coord_t y = 15 + i * 40;
|
||||
coord_t x = 15;
|
||||
// center the keyboard
|
||||
coord_t start_x = (dc->width() - calculateMaxWidth()) / 2;
|
||||
|
||||
for (uint8_t i = 0; i < NUMBER_OF_KEYBOARD_LAYOUTS; i++) {
|
||||
coord_t y = KEYBOARD_OFFSET_Y + i * KEYBOARD_ROW_HEIGHT;
|
||||
coord_t x = start_x;
|
||||
const char * c = layout[i];
|
||||
|
||||
while (*c) {
|
||||
if (*c == ' ') {
|
||||
x += 15;
|
||||
}
|
||||
else if (*c == KEYBOARD_SPACE[0]) {
|
||||
if (*c == KEYBOARD_SPACE[0]) {
|
||||
// spacebar
|
||||
dc->drawBitmapPattern(x, y, LBM_KEY_SPACEBAR, COLOR_THEME_SECONDARY1);
|
||||
x += 135;
|
||||
}
|
||||
else if (*c == KEYBOARD_ENTER[0]) {
|
||||
// enter
|
||||
dc->drawSolidFilledRect(x, y-2, 80, 25, COLOR_THEME_DISABLED);
|
||||
dc->drawText(x+40, y, "ENTER", CENTERED);
|
||||
x += 80;
|
||||
dc->drawSolidFilledRect(x, y - 2, KEYBOARD_ENTER_WIDTH, 25, COLOR_THEME_DISABLED);
|
||||
dc->drawText(x + KEYBOARD_ENTER_WIDTH / 2, y + 2, "ENTER", CENTERED);
|
||||
}
|
||||
else if (int8_t(*c) < 0) {
|
||||
dc->drawBitmapPattern(x, y, LBM_SPECIAL_KEYS[uint8_t(*c - 128)], COLOR_THEME_SECONDARY1);
|
||||
x += 45;
|
||||
const uint8_t *pBitmap = LBM_SPECIAL_KEYS[uint8_t(*c - 128)];
|
||||
uint8_t bitmapWidth = *pBitmap, bitmapHeight = *(pBitmap + 2);
|
||||
if (touched && *c == touch_key) {
|
||||
dc->drawSolidFilledRect(x - 2, y + 3, bitmapWidth + 4, bitmapHeight + 4, COLOR_THEME_SECONDARY2);
|
||||
}
|
||||
|
||||
dc->drawBitmapPattern(x, y + 5, pBitmap, COLOR_THEME_SECONDARY1);
|
||||
}
|
||||
else {
|
||||
dc->drawSizedText(x, y, c, 1);
|
||||
x += 30;
|
||||
if (touched && *c == touch_key) {
|
||||
dc->drawSolidFilledRect(x - KEYBOARD_CHAR_WIDTH / 2, y - ((KEYBOARD_ROW_HEIGHT - 16) / 2), KEYBOARD_CHAR_WIDTH, KEYBOARD_ROW_HEIGHT, COLOR_THEME_FOCUS);
|
||||
}
|
||||
dc->drawSizedText(x, y, c, 1, CENTERED);
|
||||
}
|
||||
x += getCharWidth(*c);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TextKeyboard::onTouchStart(coord_t x, coord_t y)
|
||||
{
|
||||
// remove the centering. If x < 0 then this is an invalid touch event
|
||||
x -= (this->width() - calculateMaxWidth()) / 2;
|
||||
if (x < 0) {
|
||||
if (touched) {
|
||||
touched = false;
|
||||
invalidate();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
touched = false;
|
||||
|
||||
uint8_t row = max<coord_t>(0, y - 5) / KEYBOARD_ROW_HEIGHT;
|
||||
const char * key = layout[row];
|
||||
|
||||
while(*key) {
|
||||
if (*key == KEYBOARD_SPACE[0] && x <= KEYBOARD_SPACE_WIDTH) {
|
||||
touch_key = KEYBOARD_SPACE[0];
|
||||
touched = true;
|
||||
break;
|
||||
}
|
||||
else if (*key == KEYBOARD_ENTER[0] && x <= KEYBOARD_ENTER_WIDTH) {
|
||||
touch_key = KEYBOARD_ENTER[0];
|
||||
touched = true;
|
||||
break;
|
||||
}
|
||||
else if (int8_t(*key) < 0 && x <= KEYBOARD_BITMAP_WIDTH) {
|
||||
if (uint8_t(*key) == 128) {
|
||||
touch_key = KEYBOARD_BACKSPACE[0];
|
||||
touched = true;
|
||||
break;
|
||||
} else {
|
||||
touched = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (*key != ' ' && (x >= -(KEYBOARD_CHAR_WIDTH / 2) && x <= KEYBOARD_CHAR_WIDTH / 2)) {
|
||||
touch_key = *key;
|
||||
touched = true;
|
||||
break;
|
||||
}
|
||||
|
||||
x -= getCharWidth(*key);
|
||||
key++;
|
||||
|
||||
if (touched) {
|
||||
invalidate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TextKeyboard::onTouchEnd(coord_t x, coord_t y)
|
||||
{
|
||||
// remove the centering width, if x < 0 then this is an invalid touch on a centered keyboard.
|
||||
x -= (this->width() - calculateMaxWidth()) / 2;
|
||||
if (x < 0) {
|
||||
touched = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
onKeyPress();
|
||||
|
||||
uint8_t row = max<coord_t>(0, y - 5) / 40;
|
||||
if (touched)
|
||||
invalidate();
|
||||
touched = false;
|
||||
|
||||
uint8_t row = max<coord_t>(0, y - 5) / KEYBOARD_ROW_HEIGHT;
|
||||
|
||||
const char * key = layout[row];
|
||||
while (*key) {
|
||||
if (*key == ' ') {
|
||||
x -= 15;
|
||||
}
|
||||
else if (*key == KEYBOARD_SPACE[0]) {
|
||||
if (x <= 135) {
|
||||
if (*key == KEYBOARD_SPACE[0]) {
|
||||
if (x <= KEYBOARD_SPACE_WIDTH) {
|
||||
pushEvent(EVT_VIRTUAL_KEY(' '));
|
||||
return true;
|
||||
}
|
||||
x -= 135;
|
||||
}
|
||||
else if (*key == KEYBOARD_ENTER[0]) {
|
||||
if (x <= 80) {
|
||||
if (x <= KEYBOARD_ENTER_WIDTH) {
|
||||
// enter
|
||||
hide();
|
||||
return true;
|
||||
}
|
||||
x -= 80;
|
||||
}
|
||||
else if (int8_t(*key) < 0) {
|
||||
if (x <= 45) {
|
||||
if (x <= KEYBOARD_BITMAP_WIDTH) {
|
||||
uint8_t specialKey = *key;
|
||||
if (specialKey == 128) {
|
||||
// backspace
|
||||
@@ -172,17 +272,32 @@ bool TextKeyboard::onTouchEnd(coord_t x, coord_t y)
|
||||
}
|
||||
break;
|
||||
}
|
||||
x -= 45;
|
||||
}
|
||||
else {
|
||||
if (x <= 30) {
|
||||
if (x <= KEYBOARD_CHAR_WIDTH && *key != ' ') {
|
||||
pushEvent(EVT_VIRTUAL_KEY(*key));
|
||||
return true;
|
||||
}
|
||||
x -= 30;
|
||||
}
|
||||
x -= getCharWidth(*key);
|
||||
key++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TextKeyboard::onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY)
|
||||
{
|
||||
if (touched)
|
||||
invalidate();
|
||||
|
||||
touched = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(HARDWARE_KEYS)
|
||||
void TextKeyboard::onEvent(event_t event)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -29,6 +29,13 @@
|
||||
#define KEYBOARD_SET_LETTERS "\203"
|
||||
#define KEYBOARD_SET_NUMBERS "\204"
|
||||
|
||||
#define KEYBOARD_OFFSET_Y 15
|
||||
#define KEYBOARD_ROW_HEIGHT 40
|
||||
#define KEYBOARD_CHAR_WIDTH 30
|
||||
#define KEYBOARD_SPACE_WIDTH 135
|
||||
#define KEYBOARD_ENTER_WIDTH 80
|
||||
#define KEYBOARD_BITMAP_WIDTH 45
|
||||
|
||||
class TextKeyboard : public Keyboard {
|
||||
public:
|
||||
TextKeyboard();
|
||||
@@ -53,10 +60,22 @@ class TextKeyboard : public Keyboard {
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
bool onTouchEnd(coord_t x, coord_t y) override;
|
||||
bool onTouchStart(coord_t x, coord_t y) override;
|
||||
bool onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY) override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
#if defined(HARDWARE_KEYS)
|
||||
void onEvent(event_t event) override;
|
||||
#endif
|
||||
|
||||
static TextKeyboard * _instance;
|
||||
const char * const * layout;
|
||||
private:
|
||||
int calculateMaxWidth();
|
||||
int getCharWidth(const char c);
|
||||
|
||||
char touch_key = -128;
|
||||
bool touched = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -170,6 +170,9 @@ void TextEdit::onEvent(event_t event)
|
||||
|
||||
case EVT_KEY_BREAK(KEY_EXIT):
|
||||
changeEnd();
|
||||
#if defined(SOFTWARE_KEYBOARD)
|
||||
Keyboard::hide();
|
||||
#endif
|
||||
FormField::onEvent(event);
|
||||
break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user