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; }