From 1c1d5428394bb3cb683892d70a91e05b726e4259 Mon Sep 17 00:00:00 2001 From: "kkoenig1@optonline.com" Date: Wed, 25 Aug 2021 12:28:22 -0400 Subject: [PATCH 1/7] Updated software keyboard to center, and provice press indicators --- .../libopenui/src/keyboard_text.cpp | 173 +++++++++++++++--- .../thirdparty/libopenui/src/keyboard_text.h | 19 ++ .../src/thirdparty/libopenui/src/textedit.cpp | 3 + 3 files changed, 166 insertions(+), 29 deletions(-) diff --git a/radio/src/thirdparty/libopenui/src/keyboard_text.cpp b/radio/src/thirdparty/libopenui/src/keyboard_text.cpp index cbf3860a5..92553d743 100644 --- a/radio/src/thirdparty/libopenui/src/keyboard_text.cpp +++ b/radio/src/thirdparty/libopenui/src/keyboard_text.cpp @@ -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(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(0, y - 5) / 40; + if (touched) + invalidate(); + touched = false; + + uint8_t row = max(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 diff --git a/radio/src/thirdparty/libopenui/src/keyboard_text.h b/radio/src/thirdparty/libopenui/src/keyboard_text.h index afc8cfef2..732e6e2c3 100644 --- a/radio/src/thirdparty/libopenui/src/keyboard_text.h +++ b/radio/src/thirdparty/libopenui/src/keyboard_text.h @@ -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; }; diff --git a/radio/src/thirdparty/libopenui/src/textedit.cpp b/radio/src/thirdparty/libopenui/src/textedit.cpp index 45d4997dd..0e023d354 100644 --- a/radio/src/thirdparty/libopenui/src/textedit.cpp +++ b/radio/src/thirdparty/libopenui/src/textedit.cpp @@ -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; From 9ee4d2b726ccab7f128ee682c9ab1d272c01ed0f Mon Sep 17 00:00:00 2001 From: "kkoenig1@optonline.com" Date: Wed, 25 Aug 2021 15:31:32 -0400 Subject: [PATCH 2/7] hide numeric keyboard on RETURN key --- radio/src/thirdparty/libopenui/src/numberedit.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/radio/src/thirdparty/libopenui/src/numberedit.cpp b/radio/src/thirdparty/libopenui/src/numberedit.cpp index 91d87e3bf..bba57e9e0 100644 --- a/radio/src/thirdparty/libopenui/src/numberedit.cpp +++ b/radio/src/thirdparty/libopenui/src/numberedit.cpp @@ -106,6 +106,15 @@ void NumberEdit::onEvent(event_t event) case EVT_KEY_FIRST(KEY_EXIT): return; + case EVT_KEY_BREAK(KEY_EXIT): + changeEnd(); +#if defined(SOFTWARE_KEYBOARD) + Keyboard::hide(); +#endif + FormField::onEvent(event); + break; + + #if defined(HARDWARE_TOUCH) case EVT_VIRTUAL_KEY_PLUS: setValue(getValue() + getStep()); From 2f30482115a235f5abad12b4b90090081a3d0b4b Mon Sep 17 00:00:00 2001 From: "kkoenig1@optonline.com" Date: Wed, 25 Aug 2021 15:56:59 -0400 Subject: [PATCH 3/7] fix issue with compile --- radio/src/thirdparty/libopenui/src/numberedit.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/radio/src/thirdparty/libopenui/src/numberedit.cpp b/radio/src/thirdparty/libopenui/src/numberedit.cpp index bba57e9e0..63792a42b 100644 --- a/radio/src/thirdparty/libopenui/src/numberedit.cpp +++ b/radio/src/thirdparty/libopenui/src/numberedit.cpp @@ -107,7 +107,6 @@ void NumberEdit::onEvent(event_t event) return; case EVT_KEY_BREAK(KEY_EXIT): - changeEnd(); #if defined(SOFTWARE_KEYBOARD) Keyboard::hide(); #endif From 75110d2f0dbc41582ef083e4a6b9dfc48fd2470f Mon Sep 17 00:00:00 2001 From: "kkoenig1@optonline.com" Date: Wed, 25 Aug 2021 15:59:38 -0400 Subject: [PATCH 4/7] modified to fix issue with return --- radio/src/thirdparty/libopenui/src/numberedit.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/radio/src/thirdparty/libopenui/src/numberedit.cpp b/radio/src/thirdparty/libopenui/src/numberedit.cpp index 63792a42b..f6e9934b1 100644 --- a/radio/src/thirdparty/libopenui/src/numberedit.cpp +++ b/radio/src/thirdparty/libopenui/src/numberedit.cpp @@ -110,7 +110,6 @@ void NumberEdit::onEvent(event_t event) #if defined(SOFTWARE_KEYBOARD) Keyboard::hide(); #endif - FormField::onEvent(event); break; From 36e048cde3c48c01b2fdbe26d1daccfe893ece88 Mon Sep 17 00:00:00 2001 From: "kkoenig1@optonline.com" Date: Wed, 25 Aug 2021 16:53:47 -0400 Subject: [PATCH 5/7] fixing stuff --- .../src/thirdparty/libopenui/src/numberedit.cpp | 17 +++-------------- radio/src/thirdparty/libopenui/src/numberedit.h | 2 -- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/radio/src/thirdparty/libopenui/src/numberedit.cpp b/radio/src/thirdparty/libopenui/src/numberedit.cpp index f6e9934b1..eacc2b86e 100644 --- a/radio/src/thirdparty/libopenui/src/numberedit.cpp +++ b/radio/src/thirdparty/libopenui/src/numberedit.cpp @@ -103,14 +103,11 @@ void NumberEdit::onEvent(event_t event) } #endif - case EVT_KEY_FIRST(KEY_EXIT): - return; - - case EVT_KEY_BREAK(KEY_EXIT): + case EVT_KEY_FIRST(KEY_EXIT): #if defined(SOFTWARE_KEYBOARD) - Keyboard::hide(); + Keyboard::hide(); #endif - break; + break; #if defined(HARDWARE_TOUCH) @@ -174,11 +171,3 @@ bool NumberEdit::onTouchEnd(coord_t, coord_t) } #endif -void NumberEdit::onFocusLost() -{ -#if defined(SOFTWARE_KEYBOARD) - Keyboard::hide(); -#endif - - FormField::onFocusLost(); -} diff --git a/radio/src/thirdparty/libopenui/src/numberedit.h b/radio/src/thirdparty/libopenui/src/numberedit.h index 67ff5da90..180889c90 100644 --- a/radio/src/thirdparty/libopenui/src/numberedit.h +++ b/radio/src/thirdparty/libopenui/src/numberedit.h @@ -67,8 +67,6 @@ class NumberEdit : public BaseNumberEdit bool onTouchEnd(coord_t x, coord_t y) override; #endif - void onFocusLost() override; - protected: std::function displayFunction; std::string prefix; From 8a1089538fa2b2a9eaaf4ce10e52ce513353ebf7 Mon Sep 17 00:00:00 2001 From: "kkoenig1@optonline.com" Date: Thu, 26 Aug 2021 17:26:28 -0400 Subject: [PATCH 6/7] trying to fix scrolling to correct positon when keyboard pops up --- .../thirdparty/libopenui/src/CMakeLists.txt | 1 + .../libopenui/src/keyboard_base.cpp | 103 ++++++++++++++++++ .../thirdparty/libopenui/src/keyboard_base.h | 58 ++-------- .../thirdparty/libopenui/src/numberedit.cpp | 1 + .../src/thirdparty/libopenui/src/textedit.cpp | 4 +- radio/src/thirdparty/libopenui/src/window.h | 5 + 6 files changed, 122 insertions(+), 50 deletions(-) create mode 100644 radio/src/thirdparty/libopenui/src/keyboard_base.cpp diff --git a/radio/src/thirdparty/libopenui/src/CMakeLists.txt b/radio/src/thirdparty/libopenui/src/CMakeLists.txt index 98bcf5f78..c1a9671d3 100644 --- a/radio/src/thirdparty/libopenui/src/CMakeLists.txt +++ b/radio/src/thirdparty/libopenui/src/CMakeLists.txt @@ -42,5 +42,6 @@ if(SOFTWARE_KEYBOARD) ${LIBOPENUI_SRC} keyboard_text.cpp keyboard_number.cpp + keyboard_base.cpp ) endif() diff --git a/radio/src/thirdparty/libopenui/src/keyboard_base.cpp b/radio/src/thirdparty/libopenui/src/keyboard_base.cpp new file mode 100644 index 000000000..a74e6516b --- /dev/null +++ b/radio/src/thirdparty/libopenui/src/keyboard_base.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) OpenTX + * + * Source: + * https://github.com/opentx/libopenui + * + * This file is a part of libopenui library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ +#include "keyboard_base.h" + +void Keyboard::hide() +{ + if (activeKeyboard) { + activeKeyboard->clearField(); + activeKeyboard = nullptr; + } +} + +void Keyboard::clearField() +{ + detach(); + if (fields) { + fields->setHeight(oldHeight); + fields = nullptr; + } + if (fieldContainer) { + fieldContainer->setHeight(LCD_H - 0 - fieldContainer->top()); + fieldContainer = nullptr; + } + if (field) { + field->setEditMode(false); + field = nullptr; + } +} + +void Keyboard::setField(FormField* newField) +{ + if (activeKeyboard) { + if (activeKeyboard == this) return; + activeKeyboard->clearField(); + } + activeKeyboard = this; + attach(MainWindow::instance()); + + fieldContainer = getFieldContainer(newField); + if (fieldContainer) { + coord_t newWindowHeight = LCD_H - height(); + + fieldContainer->setHeight(newWindowHeight); + + std::list children = fieldContainer->getChildren(); + fields = *std::next(children.begin()); + + rect_t scrollRect = { + fieldContainer->left(), + fields->top(), // this will remove the title from the screen to provide extra visible space. + fieldContainer->width(), + fieldContainer->height() + }; + // both should be the same height as we are scrolled to the right position + fieldContainer->scrollTo(scrollRect); + oldHeight = fields->height(); + fields->setHeight(newWindowHeight); + + // now we need to calculate the offset of the field in the fields scroll container + coord_t offsetX = 0, offsetY = 0; + Window* parentWindow = newField->getParent(); + while (parentWindow && parentWindow != fieldContainer) { + offsetX += parentWindow->left(); + offsetY += parentWindow->top(); + parentWindow = parentWindow->getParent(); + } + + scrollRect = { + offsetX, + offsetY + 69, + fieldContainer->width(), + fieldContainer->height() + }; + fields->scrollTo(scrollRect); + + invalidate(); + newField->setEditMode(true); + field = newField; + } else { + clearField(); + } +} + +Window* Keyboard::getFieldContainer(FormField* field) +{ + return field->getFullScreenWindow(); +} diff --git a/radio/src/thirdparty/libopenui/src/keyboard_base.h b/radio/src/thirdparty/libopenui/src/keyboard_base.h index fb6859eb8..2240d183c 100644 --- a/radio/src/thirdparty/libopenui/src/keyboard_base.h +++ b/radio/src/thirdparty/libopenui/src/keyboard_base.h @@ -25,61 +25,21 @@ class Keyboard: public FormWindow { public: - explicit Keyboard(coord_t height): - FormWindow(nullptr, {0, LCD_H - height, LCD_W, height}, OPAQUE) + explicit Keyboard(coord_t height) : FormWindow(nullptr, {0, LCD_H - height, LCD_W, height}, OPAQUE) { } - static void hide() - { - if (activeKeyboard) { - activeKeyboard->clearField(); - activeKeyboard = nullptr; - } - } + static void hide(); protected: static Keyboard * activeKeyboard; - FormField * field = nullptr; - Window * fieldContainer = nullptr; + FormField *field = nullptr; + Window *fieldContainer = nullptr; + Window *fields = nullptr; + coord_t oldHeight = 0; - void setField(FormField * newField) - { - if (activeKeyboard) { - if (activeKeyboard == this) - return; - activeKeyboard->clearField(); - } - activeKeyboard = this; - attach(MainWindow::instance()); - fieldContainer = getFieldContainer(newField); - if (fieldContainer) { - fieldContainer->setHeight(LCD_H - height() - fieldContainer->top()); - fieldContainer->scrollTo(newField); - invalidate(); - newField->setEditMode(true); - field = newField; - } else { - clearField(); - } - } - - void clearField() - { - detach(); - if (fieldContainer) { - fieldContainer->setHeight(LCD_H - 0 - fieldContainer->top()); - fieldContainer = nullptr; - } - if (field) { - field->setEditMode(false); - field = nullptr; - } - } - - Window * getFieldContainer(FormField * field) - { - return field->getFullScreenWindow(); - } + void setField(FormField *newField); + void clearField(); + Window *getFieldContainer(FormField * field); }; diff --git a/radio/src/thirdparty/libopenui/src/numberedit.cpp b/radio/src/thirdparty/libopenui/src/numberedit.cpp index eacc2b86e..f9d56fbbd 100644 --- a/radio/src/thirdparty/libopenui/src/numberedit.cpp +++ b/radio/src/thirdparty/libopenui/src/numberedit.cpp @@ -106,6 +106,7 @@ void NumberEdit::onEvent(event_t event) case EVT_KEY_FIRST(KEY_EXIT): #if defined(SOFTWARE_KEYBOARD) Keyboard::hide(); + return; #endif break; diff --git a/radio/src/thirdparty/libopenui/src/textedit.cpp b/radio/src/thirdparty/libopenui/src/textedit.cpp index 0e023d354..b2aa9ef94 100644 --- a/radio/src/thirdparty/libopenui/src/textedit.cpp +++ b/radio/src/thirdparty/libopenui/src/textedit.cpp @@ -170,10 +170,12 @@ void TextEdit::onEvent(event_t event) case EVT_KEY_BREAK(KEY_EXIT): changeEnd(); + FormField::onEvent(event); + #if defined(SOFTWARE_KEYBOARD) Keyboard::hide(); #endif - FormField::onEvent(event); + setFocus(SET_FOCUS_DEFAULT, this); break; case EVT_KEY_LONG(KEY_ENTER): diff --git a/radio/src/thirdparty/libopenui/src/window.h b/radio/src/thirdparty/libopenui/src/window.h index a3cbbb964..6902eb4e4 100644 --- a/radio/src/thirdparty/libopenui/src/window.h +++ b/radio/src/thirdparty/libopenui/src/window.h @@ -144,6 +144,11 @@ class Window focusHandler = std::move(handler); } + const std::list getChildren() + { + return children; + } + virtual void deleteLater(bool detach = true, bool trash = true); void clear(); From 95f696bfefa8ce74bff297625aa894b4bddd7020 Mon Sep 17 00:00:00 2001 From: kevinkoenig Date: Fri, 27 Aug 2021 13:11:11 -0400 Subject: [PATCH 7/7] fix scroll position --- .../libopenui/src/keyboard_base.cpp | 91 ++++++++++++------- .../thirdparty/libopenui/src/keyboard_base.h | 12 ++- .../libopenui/src/keyboard_text.cpp | 4 +- 3 files changed, 66 insertions(+), 41 deletions(-) diff --git a/radio/src/thirdparty/libopenui/src/keyboard_base.cpp b/radio/src/thirdparty/libopenui/src/keyboard_base.cpp index a74e6516b..e8444eda2 100644 --- a/radio/src/thirdparty/libopenui/src/keyboard_base.cpp +++ b/radio/src/thirdparty/libopenui/src/keyboard_base.cpp @@ -1,8 +1,8 @@ /* - * Copyright (C) OpenTX + * Copyright (C) EdgeTX * * Source: - * https://github.com/opentx/libopenui + * https://github.com/edgetx/libopenui * * This file is a part of libopenui library. * @@ -43,7 +43,24 @@ void Keyboard::clearField() } } -void Keyboard::setField(FormField* newField) +coord_t calcScrollOffsetForField(FormField *newField, Window *topWindow) +{ + // now we need to calculate the offset of the field in the fields scroll container + // start with the current fields top and walk the hierarchy to calculate positon + coord_t offsetY = newField->top(); + + Window* parentWindow = newField->getParent(); + while (parentWindow && parentWindow != topWindow) { + offsetY += parentWindow->top(); + parentWindow = parentWindow->getParent(); + } + + // try and place it in the middle of the screen. The containing window MUST have + // already been resized + return offsetY - topWindow->height() / 2; +} + +void Keyboard::attachKeyboard() { if (activeKeyboard) { if (activeKeyboard == this) return; @@ -51,44 +68,50 @@ void Keyboard::setField(FormField* newField) } activeKeyboard = this; attach(MainWindow::instance()); +} + + +// this routine finds the window that is a FormWindow. This is the window +// that contains all of the editable fields. This is the window that needs +// to be scrolled into view. +FormWindow *Keyboard::findFormWindow() +{ + if (fieldContainer) { + auto children = fieldContainer->getChildren(); + auto k = children.begin(); + while (k != children.end()) + { + FormWindow *a = dynamic_cast(*k); + if (a) + return a; + k++; + } + } + + return nullptr; +} + +void Keyboard::setField(FormField* newField) +{ + attachKeyboard(); fieldContainer = getFieldContainer(newField); if (fieldContainer) { - coord_t newWindowHeight = LCD_H - height(); + coord_t newHeight = LCD_H - height(); + fieldContainer->setHeight(newHeight); - fieldContainer->setHeight(newWindowHeight); + fields = findFormWindow(); + if (fields) { + // scroll the header of the window out of view to get more space to + // see the field being edited + fieldContainer->setScrollPositionY(fields->top()); + oldHeight = fields->height(); + fields->setHeight(newHeight); - std::list children = fieldContainer->getChildren(); - fields = *std::next(children.begin()); - - rect_t scrollRect = { - fieldContainer->left(), - fields->top(), // this will remove the title from the screen to provide extra visible space. - fieldContainer->width(), - fieldContainer->height() - }; - // both should be the same height as we are scrolled to the right position - fieldContainer->scrollTo(scrollRect); - oldHeight = fields->height(); - fields->setHeight(newWindowHeight); - - // now we need to calculate the offset of the field in the fields scroll container - coord_t offsetX = 0, offsetY = 0; - Window* parentWindow = newField->getParent(); - while (parentWindow && parentWindow != fieldContainer) { - offsetX += parentWindow->left(); - offsetY += parentWindow->top(); - parentWindow = parentWindow->getParent(); + coord_t offsetY = calcScrollOffsetForField(newField, fields); + fields->setScrollPositionY(offsetY); } - scrollRect = { - offsetX, - offsetY + 69, - fieldContainer->width(), - fieldContainer->height() - }; - fields->scrollTo(scrollRect); - invalidate(); newField->setEditMode(true); field = newField; diff --git a/radio/src/thirdparty/libopenui/src/keyboard_base.h b/radio/src/thirdparty/libopenui/src/keyboard_base.h index 2240d183c..d55c55239 100644 --- a/radio/src/thirdparty/libopenui/src/keyboard_base.h +++ b/radio/src/thirdparty/libopenui/src/keyboard_base.h @@ -1,8 +1,8 @@ /* - * Copyright (C) OpenTX + * Copyright (C) EdgeTX * * Source: - * https://github.com/opentx/libopenui + * https://github.com/edgetx/libopenui * * This file is a part of libopenui library. * @@ -34,12 +34,14 @@ class Keyboard: public FormWindow protected: static Keyboard * activeKeyboard; FormField *field = nullptr; - Window *fieldContainer = nullptr; - Window *fields = nullptr; - coord_t oldHeight = 0; + Window *fieldContainer = nullptr; + FormWindow *fields = nullptr; + coord_t oldHeight = 0; void setField(FormField *newField); void clearField(); Window *getFieldContainer(FormField * field); + void attachKeyboard(); + FormWindow *findFormWindow(); }; diff --git a/radio/src/thirdparty/libopenui/src/keyboard_text.cpp b/radio/src/thirdparty/libopenui/src/keyboard_text.cpp index 92553d743..9f827bbbf 100644 --- a/radio/src/thirdparty/libopenui/src/keyboard_text.cpp +++ b/radio/src/thirdparty/libopenui/src/keyboard_text.cpp @@ -174,7 +174,7 @@ void TextKeyboard::paint(BitmapBuffer * dc) bool TextKeyboard::onTouchStart(coord_t x, coord_t y) { - // remove the centering. If x < 0 then this is an invalid touch event + // remove the centering. If x < 0 then this is an invalid touch event x -= (this->width() - calculateMaxWidth()) / 2; if (x < 0) { if (touched) { @@ -274,7 +274,7 @@ bool TextKeyboard::onTouchEnd(coord_t x, coord_t y) } } else { - if (x <= KEYBOARD_CHAR_WIDTH && *key != ' ') { + if (*key != ' ' && (x >= -(KEYBOARD_CHAR_WIDTH / 2) && x <= KEYBOARD_CHAR_WIDTH / 2)) { pushEvent(EVT_VIRTUAL_KEY(*key)); return true; }