From 6b70baf63ae61f01742a2308a72ccac4efae80a8 Mon Sep 17 00:00:00 2001 From: "kkoenig1@optonline.com" Date: Sat, 8 Jan 2022 04:23:23 -0500 Subject: [PATCH] 1. basic changes to mirror libopnui window hierararchy to lvgl object hierarchy 2. basic scroll support 3. Basic layer support (still pretty broken), multiple screen support 4. Preliminary impelemntation of TextEdit using lvgl. 5. Preliminary implementation of StaticText using lvgl. 6. Preliminary implementation of TextButton using lvgl. --- radio/src/thirdparty/libopenui/src/button.cpp | 104 ++++++++---- radio/src/thirdparty/libopenui/src/button.h | 21 +-- radio/src/thirdparty/libopenui/src/form.cpp | 4 +- radio/src/thirdparty/libopenui/src/form.h | 8 +- radio/src/thirdparty/libopenui/src/layer.h | 15 ++ .../src/thirdparty/libopenui/src/mainwindow.h | 2 +- .../thirdparty/libopenui/src/modal_window.cpp | 2 +- radio/src/thirdparty/libopenui/src/static.cpp | 56 +++---- radio/src/thirdparty/libopenui/src/static.h | 17 +- .../src/thirdparty/libopenui/src/textedit.cpp | 149 +++++++++++++----- radio/src/thirdparty/libopenui/src/textedit.h | 10 +- radio/src/thirdparty/libopenui/src/window.cpp | 37 ++++- radio/src/thirdparty/libopenui/src/window.h | 6 +- 13 files changed, 302 insertions(+), 129 deletions(-) diff --git a/radio/src/thirdparty/libopenui/src/button.cpp b/radio/src/thirdparty/libopenui/src/button.cpp index 22107365a..f5f61f1e0 100644 --- a/radio/src/thirdparty/libopenui/src/button.cpp +++ b/radio/src/thirdparty/libopenui/src/button.cpp @@ -76,44 +76,82 @@ void Button::checkEvents() checkHandler(); } + +TextButton::TextButton(FormGroup* parent, const rect_t& rect, std::string text, + std::function pressHandler, + WindowFlags windowFlags, + LcdFlags textFlags) : + Button(parent, rect, std::move(pressHandler), windowFlags, textFlags), + text(std::move(text)) +{ + if (lvobj != nullptr) { + lv_obj_del(lvobj); + } + lvobj = lv_btn_create(parent->getLvObj()); + lv_obj_set_pos(lvobj, rect.x, rect.y); /*Set its position*/ + lv_obj_set_size(lvobj, rect.w, rect.h); /*Set its size*/ + setTextFlags(textFlags | COLOR_THEME_PRIMARY1); + +#if 1 + auto color = COLOR_VAL(COLOR_THEME_PRIMARY2); + auto r = GET_RED(color), g = GET_GREEN(color), b = GET_BLUE(color); + + lv_style_init(&style_btn); + lv_style_set_radius(&style_btn, 0); + lv_obj_set_style_bg_color(lvobj, lv_color_make(r, g, b), LV_PART_MAIN); + + lv_obj_add_style(lvobj, &style_btn,0); + + label = lv_label_create(lvobj); + lv_label_set_text(label, this->text.c_str()); + lv_obj_center(label); + color = COLOR_VAL(this->getTextFlags()); + lv_obj_set_style_text_color(label, lv_color_make(GET_RED(color), GET_GREEN(color), GET_BLUE(color)), LV_PART_MAIN); +#endif +} + +TextButton::~TextButton() +{ +} + void TextButton::paint(BitmapBuffer * dc) { - auto textColor = getTextFlags(); - auto bgColor = COLOR_THEME_SECONDARY2; + // auto textColor = getTextFlags(); + // auto bgColor = COLOR_THEME_SECONDARY2; - if (bgColorHandler) { - bgColor = bgColorHandler(); - } else if (checked()) { - bgColor = COLOR_THEME_ACTIVE; - } else if (hasFocus()) { - bgColor = COLOR_THEME_FOCUS; - textColor = COLOR_THEME_PRIMARY2; - } + // if (bgColorHandler) { + // bgColor = bgColorHandler(); + // } else if (checked()) { + // bgColor = COLOR_THEME_ACTIVE; + // } else if (hasFocus()) { + // bgColor = COLOR_THEME_FOCUS; + // textColor = COLOR_THEME_PRIMARY2; + // } - if (checked()) { - if (hasFocus()) { - dc->drawSolidRect(0, 0, rect.w, rect.h, 2, COLOR_THEME_FOCUS); - dc->drawSolidFilledRect(3, 3, rect.w - 6, rect.h - 6, bgColor); - } else { - dc->drawSolidFilledRect(0, 0, rect.w, rect.h, bgColor); - } - } - else { - dc->drawSolidFilledRect(0, 0, rect.w, rect.h, bgColor); - if (windowFlags & BUTTON_BACKGROUND) { - if (hasFocus()) { - textColor = COLOR_THEME_PRIMARY2; - } - } else if (hasFocus()) { - dc->drawSolidRect(0, 0, rect.w, rect.h, 2, COLOR_THEME_FOCUS); - } - else { - dc->drawSolidRect(0, 0, rect.w, rect.h, 1, COLOR_THEME_SECONDARY2); - } - } + // if (checked()) { + // if (hasFocus()) { + // dc->drawSolidRect(0, 0, rect.w, rect.h, 2, COLOR_THEME_FOCUS); + // dc->drawSolidFilledRect(3, 3, rect.w - 6, rect.h - 6, bgColor); + // } else { + // dc->drawSolidFilledRect(0, 0, rect.w, rect.h, bgColor); + // } + // } + // else { + // dc->drawSolidFilledRect(0, 0, rect.w, rect.h, bgColor); + // if (windowFlags & BUTTON_BACKGROUND) { + // if (hasFocus()) { + // textColor = COLOR_THEME_PRIMARY2; + // } + // } else if (hasFocus()) { + // dc->drawSolidRect(0, 0, rect.w, rect.h, 2, COLOR_THEME_FOCUS); + // } + // else { + // dc->drawSolidRect(0, 0, rect.w, rect.h, 1, COLOR_THEME_SECONDARY2); + // } + // } - dc->drawText(rect.w / 2, 1 + (rect.h - getFontHeight(textFlags)) / 2, - text.c_str(), CENTERED | textColor); + // dc->drawText(rect.w / 2, 1 + (rect.h - getFontHeight(textFlags)) / 2, + // text.c_str(), CENTERED | textColor); } void IconButton::paint(BitmapBuffer * dc) diff --git a/radio/src/thirdparty/libopenui/src/button.h b/radio/src/thirdparty/libopenui/src/button.h index 725cd3ce7..fa8078329 100644 --- a/radio/src/thirdparty/libopenui/src/button.h +++ b/radio/src/thirdparty/libopenui/src/button.h @@ -87,19 +87,18 @@ class Button: public FormField void onPress(); }; + +extern void my_btn_event_cb(lv_event_t * e); + class TextButton: public Button { public: TextButton(FormGroup* parent, const rect_t& rect, std::string text, std::function pressHandler = nullptr, WindowFlags windowFlags = BUTTON_BACKGROUND | OPAQUE, - LcdFlags textFlags = 0) : - Button(parent, rect, std::move(pressHandler), windowFlags, textFlags), - text(std::move(text)) - { - setTextFlags(textFlags | COLOR_THEME_PRIMARY1); - } - + LcdFlags textFlags = 0); + ~TextButton(); + #if defined(DEBUG_WINDOWS) std::string getName() const override { @@ -111,6 +110,7 @@ class TextButton: public Button { if (value != text) { text = std::move(value); + lv_label_set_text(label, text.c_str()); invalidate(); } } @@ -123,8 +123,11 @@ class TextButton: public Button void paint(BitmapBuffer* dc) override; protected: - std::string text; - std::function bgColorHandler = nullptr; + lv_obj_t * label = nullptr; + lv_style_t style_btn; + + std::string text; + std::function bgColorHandler = nullptr; }; class IconButton: public Button diff --git a/radio/src/thirdparty/libopenui/src/form.cpp b/radio/src/thirdparty/libopenui/src/form.cpp index 8d88327fc..6bfa3b07f 100644 --- a/radio/src/thirdparty/libopenui/src/form.cpp +++ b/radio/src/thirdparty/libopenui/src/form.cpp @@ -21,8 +21,8 @@ #include "bitmapbuffer.h" #include "libopenui_config.h" -FormField::FormField(Window * parent, const rect_t & rect, WindowFlags windowFlags, LcdFlags textFlags) : - Window(parent, rect, windowFlags, textFlags) +FormField::FormField(Window * parent, const rect_t & rect, WindowFlags windowFlags, LcdFlags textFlags, bool isScreen) : + Window(parent, rect, windowFlags, textFlags, isScreen) { if (!(windowFlags & NO_FOCUS)) { auto * form = dynamic_cast(parent); diff --git a/radio/src/thirdparty/libopenui/src/form.h b/radio/src/thirdparty/libopenui/src/form.h index f04483c46..871189a5e 100644 --- a/radio/src/thirdparty/libopenui/src/form.h +++ b/radio/src/thirdparty/libopenui/src/form.h @@ -30,7 +30,7 @@ constexpr WindowFlags FORM_FLAGS_LAST = FORM_NO_BORDER; class FormField: public Window { public: - FormField(Window * parent, const rect_t & rect, WindowFlags windowFlags = 0, LcdFlags textFlags = 0); + FormField(Window * parent, const rect_t & rect, WindowFlags windowFlags = 0, LcdFlags textFlags = 0, bool isScreen = false); virtual void changeEnd(bool forceChanged = false) { @@ -128,7 +128,7 @@ class FormField: public Window class FormGroup: public FormField { public: - FormGroup(Window * parent, const rect_t & rect, WindowFlags windowflags = 0) : + FormGroup(Window * parent, const rect_t & rect, WindowFlags windowflags = 0, bool isScreen = false) : FormField(parent, rect, windowflags) { } @@ -212,8 +212,8 @@ class FormGroup: public FormField class FormWindow: public FormGroup { public: - FormWindow(Window * parent, const rect_t & rect, WindowFlags windowFlags = 0) : - FormGroup(parent, rect, windowFlags) + FormWindow(Window * parent, const rect_t & rect, WindowFlags windowFlags = 0, bool isScreen = false) : + FormGroup(parent, rect, windowFlags, isScreen) { } diff --git a/radio/src/thirdparty/libopenui/src/layer.h b/radio/src/thirdparty/libopenui/src/layer.h index 970b5e742..691ce3258 100644 --- a/radio/src/thirdparty/libopenui/src/layer.h +++ b/radio/src/thirdparty/libopenui/src/layer.h @@ -20,6 +20,7 @@ #pragma once #include "window.h" +extern lv_obj_t * canvas; class Layer { @@ -36,10 +37,20 @@ class Layer static void push(Window * window) { + // if (window->getLvObj()->parent != nullptr) { + // TRACE("Layers must have lvgl parent to be null"); + // return; + // } + if (!stack.empty()) { Layer & parentLayer = stack.back(); parentLayer.focus = Window::getFocus(); } + + // layers are screens in lvgl + lv_scr_load(window->getLvObj()); + lv_obj_set_parent(canvas, window->getLvObj()); + stack.emplace_back(Layer(window)); #if defined(DEBUG_WINDOWS) @@ -55,6 +66,8 @@ class Layer if (stack.back().main == window) { stack.pop_back(); const auto & back = stack.back(); + lv_obj_set_parent(canvas, back.main->getLvObj()); + lv_scr_load(back.main->getLvObj()); // load the screen. if (back.focus) { back.focus->setFocus(SET_FOCUS_DEFAULT); } @@ -63,6 +76,8 @@ class Layer // TODO it would be better to do it in reverse order for (auto it = stack.begin(); it != stack.end(); it++) { if (it->main == window) { + lv_obj_set_parent(canvas, it->main->getLvObj()); + lv_scr_load(it->main->getLvObj()); stack.erase(it); break; } diff --git a/radio/src/thirdparty/libopenui/src/mainwindow.h b/radio/src/thirdparty/libopenui/src/mainwindow.h index d8bf8f62b..d02f9889c 100644 --- a/radio/src/thirdparty/libopenui/src/mainwindow.h +++ b/radio/src/thirdparty/libopenui/src/mainwindow.h @@ -28,7 +28,7 @@ class MainWindow: public Window protected: // singleton MainWindow(): - Window(nullptr, {0, 0, LCD_W, LCD_H}), + Window(nullptr, {0, 0, LCD_W, LCD_H}, 0, 0, true), invalidatedRect(rect) { Layer::push(this); diff --git a/radio/src/thirdparty/libopenui/src/modal_window.cpp b/radio/src/thirdparty/libopenui/src/modal_window.cpp index b33983164..ee8c67fe4 100644 --- a/radio/src/thirdparty/libopenui/src/modal_window.cpp +++ b/radio/src/thirdparty/libopenui/src/modal_window.cpp @@ -23,7 +23,7 @@ #include "layer.h" ModalWindow::ModalWindow(Window * parent, bool closeWhenClickOutside): - Window(parent->getFullScreenWindow(), {0, 0, LCD_W, LCD_H}), + Window(parent->getFullScreenWindow(), {0, 0, LCD_W, LCD_H}, 0, 0, true), closeWhenClickOutside(closeWhenClickOutside) { Layer::push(this); diff --git a/radio/src/thirdparty/libopenui/src/static.cpp b/radio/src/thirdparty/libopenui/src/static.cpp index 64d5f62c6..3d1b09bfd 100644 --- a/radio/src/thirdparty/libopenui/src/static.cpp +++ b/radio/src/thirdparty/libopenui/src/static.cpp @@ -22,35 +22,35 @@ void StaticText::paint(BitmapBuffer * dc) { - if (bgColor) { - dc->drawSolidFilledRect(0, 0, rect.w, rect.h, bgColor); - } + // if (bgColor) { + // dc->drawSolidFilledRect(0, 0, rect.w, rect.h, bgColor); + // } - coord_t x; - if (textFlags & CENTERED) - x = rect.w / 2; - else if (textFlags & RIGHT) - x = rect.w; - else - x = 0; + // coord_t x; + // if (textFlags & CENTERED) + // x = rect.w / 2; + // else if (textFlags & RIGHT) + // x = rect.w; + // else + // x = 0; - coord_t y = (textFlags & VCENTERED) ? (rect.h - getFontHeight(textFlags)) / 2 - : FIELD_PADDING_TOP; + // coord_t y = (textFlags & VCENTERED) ? (rect.h - getFontHeight(textFlags)) / 2 + // : FIELD_PADDING_TOP; - auto start = text.c_str(); - auto nextline = findNextLine(start); - if (nextline) { - auto current = start; - do { - dc->drawText(x, y, - text.substr(current - start, nextline - current).c_str(), - textFlags); - current = nextline + 1; - nextline = findNextLine(current); - y += getFontHeight(textFlags) + 2; - } while (nextline); - dc->drawText(x, y, current, textFlags); - } else { - dc->drawText(x, y, start, textFlags); - } + // auto start = text.c_str(); + // auto nextline = findNextLine(start); + // if (nextline) { + // auto current = start; + // do { + // dc->drawText(x, y, + // text.substr(current - start, nextline - current).c_str(), + // textFlags); + // current = nextline + 1; + // nextline = findNextLine(current); + // y += getFontHeight(textFlags) + 2; + // } while (nextline); + // dc->drawText(x, y, current, textFlags); + // } else { + // dc->drawText(x, y, start, textFlags); + // } } diff --git a/radio/src/thirdparty/libopenui/src/static.h b/radio/src/thirdparty/libopenui/src/static.h index f7beee158..7c8c18545 100644 --- a/radio/src/thirdparty/libopenui/src/static.h +++ b/radio/src/thirdparty/libopenui/src/static.h @@ -29,7 +29,18 @@ class StaticText: public Window Window(parent, rect, windowFlags, textFlags), text(std::move(text)) { + label = lv_label_create(lvobj); + lv_label_set_text(label, this->text.c_str()); + + auto color = COLOR_VAL(textFlags); + lv_obj_set_style_text_color(label, lv_color_make(GET_RED(color), GET_GREEN(color), GET_BLUE(color)), LV_PART_MAIN); + if (textFlags & CENTERED) + lv_obj_center(label); + if (textFlags & FONT(BOLD)) { + } + if (windowFlags & BUTTON_BACKGROUND) { + lv_obj_set_style_bg_opa(lvobj, LV_OPA_100, LV_PART_MAIN); setBackgroundColor(COLOR_THEME_SECONDARY2); } } @@ -47,16 +58,20 @@ class StaticText: public Window { if (text != value) { text = std::move(value); - invalidate(); + lv_label_set_text(label, this->text.c_str()); + // invalidate(); } } void setBackgroundColor(LcdFlags color) { bgColor = color; + auto actualColor = COLOR_VAL(bgColor); + lv_obj_set_style_bg_color(lvobj, lv_color_make(GET_RED(actualColor), GET_GREEN(actualColor), GET_BLUE(actualColor)), LV_PART_MAIN); } protected: + lv_obj_t *label = nullptr; std::string text; LcdFlags bgColor = 0; }; diff --git a/radio/src/thirdparty/libopenui/src/textedit.cpp b/radio/src/thirdparty/libopenui/src/textedit.cpp index c82a56605..74a087724 100644 --- a/radio/src/thirdparty/libopenui/src/textedit.cpp +++ b/radio/src/thirdparty/libopenui/src/textedit.cpp @@ -42,44 +42,111 @@ #include "clipboard.h" #endif + +static void ta_event_cb(lv_event_t * e) +{ + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * ta = lv_event_get_target(e); + if(code == LV_EVENT_CLICKED || code == LV_EVENT_FOCUSED) { + /*Focus on the clicked text area*/ + if(kb != NULL) + lv_keyboard_set_textarea(kb, ta); + else { + /*Create a keyboard*/ + kb = lv_keyboard_create(lv_scr_act()); + lv_obj_set_size(kb, LV_HOR_RES, LV_VER_RES / 2); + lv_keyboard_set_textarea(kb, ta); + } + } + else if (code == LV_EVENT_DEFOCUSED) { + if (kb != nullptr) { + lv_obj_del(kb); + kb = nullptr; + } + } + else if(code == LV_EVENT_READY) { + LV_LOG_USER("Ready, current text: %s", lv_textarea_get_text(ta)); + } +} + +TextEdit::TextEdit(Window * parent, const rect_t & rect, char * value, uint8_t length, + LcdFlags windowFlags, const char * _extra_chars) : + FormField(parent, rect, windowFlags), + value(value), + length(length) +{ + if (getLvObj() != nullptr) { + lv_obj_del(lvobj); + } + + lvobj = lv_textarea_create(parent->getLvObj()); + lv_obj_add_event_cb(lvobj, ta_event_cb, LV_EVENT_ALL, NULL); + lv_obj_set_pos(lvobj, rect.x, rect.y); + lv_obj_set_size(lvobj, rect.w, rect.h); + lv_obj_set_scrollbar_mode(lvobj, LV_SCROLLBAR_MODE_OFF); + lv_obj_set_style_border_width(lvobj, 0, LV_PART_MAIN); + lv_obj_set_style_radius(lvobj, 0, LV_PART_MAIN); + lv_obj_set_style_pad_top(lvobj, 2, LV_PART_MAIN); + lv_obj_set_style_pad_bottom(lvobj, 2, LV_PART_MAIN); + lv_obj_set_style_pad_left(lvobj, 4, LV_PART_MAIN); + lv_obj_set_style_pad_right(lvobj, 4, LV_PART_MAIN); + + + lv_textarea_set_password_mode(lvobj, false); + lv_textarea_set_one_line(lvobj, true); + lv_textarea_set_text(lvobj, value); + lv_textarea_set_placeholder_text(lvobj, "---"); + lv_textarea_set_max_length(lvobj, length); + + lv_obj_set_style_text_font(lvobj, &lv_font_montserrat_12, LV_PART_MAIN); + lv_obj_set_style_text_line_space(lvobj, 0, LV_PART_MAIN); + + auto color = COLOR_VAL(COLOR_THEME_SECONDARY1); + auto label = lv_textarea_get_label(lvobj); + lv_obj_set_style_text_color(label, lv_color_make(GET_RED(color), GET_GREEN(color), GET_BLUE(color)), LV_PART_MAIN); + + extra_chars = (_extra_chars) ? _extra_chars : extra_chars_default; +} + + void TextEdit::paint(BitmapBuffer * dc) { - FormField::paint(dc); +// FormField::paint(dc); - if (editMode) { - dc->drawSizedText(FIELD_PADDING_LEFT, FIELD_PADDING_TOP, value, length, - COLOR_THEME_PRIMARY2); - coord_t left = (cursorPos == 0 ? 0 : getTextWidth(value, cursorPos)); -#if defined(SOFTWARE_KEYBOARD) - dc->drawSolidFilledRect(left + 2, 2, 2, height() - 4, COLOR_THEME_PRIMARY2); -#else - char s[] = {value[cursorPos], '\0'}; - dc->drawSolidFilledRect(FIELD_PADDING_LEFT + left - 1, - FIELD_PADDING_TOP - 1, getTextWidth(s, 1) + 1, - height() - 2, COLOR_THEME_PRIMARY2); - dc->drawText(FIELD_PADDING_LEFT + left, FIELD_PADDING_TOP, s, - COLOR_THEME_SECONDARY1); -#endif - } else { - const char * displayedValue = value; - LcdFlags textColor = COLOR_THEME_PRIMARY2; - if (hasFocus()) { - if (strlen(value) == 0) { - displayedValue = "---"; - } - textColor = COLOR_THEME_PRIMARY2; - } - else { - if (strlen(value) == 0) { - displayedValue = "---"; - textColor = COLOR_THEME_DISABLED; - } - else { - textColor = COLOR_THEME_SECONDARY1; - } - } - dc->drawSizedText(FIELD_PADDING_LEFT, FIELD_PADDING_TOP, displayedValue, length, textColor); - } +// if (editMode) { +// dc->drawSizedText(FIELD_PADDING_LEFT, FIELD_PADDING_TOP, value, length, +// COLOR_THEME_PRIMARY2); +// coord_t left = (cursorPos == 0 ? 0 : getTextWidth(value, cursorPos)); +// #if defined(SOFTWARE_KEYBOARD) +// dc->drawSolidFilledRect(left + 2, 2, 2, height() - 4, COLOR_THEME_PRIMARY2); +// #else +// char s[] = {value[cursorPos], '\0'}; +// dc->drawSolidFilledRect(FIELD_PADDING_LEFT + left - 1, +// FIELD_PADDING_TOP - 1, getTextWidth(s, 1) + 1, +// height() - 2, COLOR_THEME_PRIMARY2); +// dc->drawText(FIELD_PADDING_LEFT + left, FIELD_PADDING_TOP, s, +// COLOR_THEME_SECONDARY1); +// #endif +// } else { +// const char * displayedValue = value; +// LcdFlags textColor = COLOR_THEME_PRIMARY2; +// if (hasFocus()) { +// if (strlen(value) == 0) { +// displayedValue = "---"; +// } +// textColor = COLOR_THEME_PRIMARY2; +// } +// else { +// if (strlen(value) == 0) { +// displayedValue = "---"; +// textColor = COLOR_THEME_DISABLED; +// } +// else { +// textColor = COLOR_THEME_SECONDARY1; +// } +// } +// dc->drawSizedText(FIELD_PADDING_LEFT, FIELD_PADDING_TOP, displayedValue, length, textColor); +// } } void TextEdit::trim() @@ -254,9 +321,9 @@ bool TextEdit::onTouchEnd(coord_t x, coord_t y) setFocus(SET_FOCUS_DEFAULT); } -#if defined(SOFTWARE_KEYBOARD) - TextKeyboard::show(this); -#endif +// #if defined(SOFTWARE_KEYBOARD) +// TextKeyboard::show(this); +// #endif coord_t rest = x; for (cursorPos = 0; cursorPos < length; cursorPos++) { @@ -276,9 +343,9 @@ bool TextEdit::onTouchEnd(coord_t x, coord_t y) void TextEdit::onFocusLost() { -#if defined(SOFTWARE_KEYBOARD) - TextKeyboard::hide(); -#endif +// #if defined(SOFTWARE_KEYBOARD) +// TextKeyboard::hide(); +// #endif changeEnd(); FormField::onFocusLost(); diff --git a/radio/src/thirdparty/libopenui/src/textedit.h b/radio/src/thirdparty/libopenui/src/textedit.h index 975f40e1a..e5e8d0539 100644 --- a/radio/src/thirdparty/libopenui/src/textedit.h +++ b/radio/src/thirdparty/libopenui/src/textedit.h @@ -23,17 +23,13 @@ const char extra_chars_default[] = ":;<=>"; +static lv_obj_t *kb = nullptr; + class TextEdit : public FormField { friend class TextKeyboard; public: - TextEdit(Window * parent, const rect_t & rect, char * value, uint8_t length, LcdFlags windowFlags = 0, const char * _extra_chars = nullptr) : - FormField(parent, rect, windowFlags), - value(value), - length(length) - { - extra_chars = (_extra_chars) ? _extra_chars : extra_chars_default; - } + TextEdit(Window * parent, const rect_t & rect, char * value, uint8_t length, LcdFlags windowFlags = 0, const char * _extra_chars = nullptr); #if defined(DEBUG_WINDOWS) std::string getName() const override diff --git a/radio/src/thirdparty/libopenui/src/window.cpp b/radio/src/thirdparty/libopenui/src/window.cpp index 28ba8c027..04971ba3a 100644 --- a/radio/src/thirdparty/libopenui/src/window.cpp +++ b/radio/src/thirdparty/libopenui/src/window.cpp @@ -19,13 +19,29 @@ #include "window.h" #include "touch.h" +#include "mainwindow.h" Window * Window::focusWindow = nullptr; Window * Window::slidingWindow = nullptr; Window * Window::capturedWindow = nullptr; std::list Window::trash; -Window::Window(Window * parent, const rect_t & rect, WindowFlags windowFlags, LcdFlags textFlags): + +static void window_event_cb(lv_event_t * e) +{ + lv_event_code_t code = lv_event_get_code(e); + Window *window = (Window *) lv_event_get_user_data(e); + if (code == LV_EVENT_GET_SELF_SIZE) { + lv_point_t * p = (lv_point_t *)lv_event_get_param(e); + if (p->x >= 0) { + p->x = window->getInnerWidth(); + } + if (p->y >= 0) + p->y = window->getInnerHeight(); + } +} + +Window::Window(Window * parent, const rect_t & rect, WindowFlags windowFlags, LcdFlags textFlags, bool isScreen) : parent(parent), rect(rect), innerWidth(rect.w), @@ -33,6 +49,18 @@ Window::Window(Window * parent, const rect_t & rect, WindowFlags windowFlags, Lc windowFlags(windowFlags), textFlags(textFlags) { + lvobj = lv_obj_create(isScreen ? nullptr : parent != nullptr ? parent->lvobj : nullptr); + lv_obj_set_pos(lvobj, rect.x, rect.y); + lv_obj_set_size(lvobj, rect.w, rect.h); + + lv_obj_set_style_pad_all(lvobj, 0, LV_PART_MAIN); + lv_obj_set_style_bg_opa(lvobj, LV_OPA_TRANSP, LV_PART_MAIN); + lv_obj_set_style_border_width(lvobj, 0, LV_PART_MAIN); + lv_obj_set_style_radius(lvobj, 0, LV_PART_MAIN); + lv_obj_set_scrollbar_mode(lvobj, LV_SCROLLBAR_MODE_OFF); + lv_obj_clear_flag(lvobj, LV_OBJ_FLAG_SCROLL_ELASTIC); + lv_obj_add_event_cb(lvobj, window_event_cb, LV_EVENT_ALL, this); + if (parent) { parent->addChild(this, windowFlags & PUSH_FRONT); if (!(windowFlags & TRANSPARENT)) { @@ -44,6 +72,11 @@ Window::Window(Window * parent, const rect_t & rect, WindowFlags windowFlags, Lc Window::~Window() { TRACE_WINDOWS("Destroy %p %s", this, getWindowDebugString().c_str()); + if (lvobj != nullptr) + { + lv_obj_del(lvobj); + lvobj = nullptr; + } if (focusWindow == this) { focusWindow = nullptr; @@ -153,6 +186,7 @@ void Window::setScrollPositionX(coord_t value) auto newScrollPosition = max(0, min(innerWidth - width(), value)); if (newScrollPosition != scrollPositionX) { scrollPositionX = newScrollPosition; + lv_obj_scroll_to_x(lvobj, scrollPositionX, LV_ANIM_OFF); invalidate(); } } @@ -167,6 +201,7 @@ void Window::setScrollPositionY(coord_t value) if (newScrollPosition != scrollPositionY) { scrollPositionY = newScrollPosition; + lv_obj_scroll_to_y(lvobj, value, LV_ANIM_OFF); invalidate(); } } diff --git a/radio/src/thirdparty/libopenui/src/window.h b/radio/src/thirdparty/libopenui/src/window.h index 8f731010f..d8fcc5361 100644 --- a/radio/src/thirdparty/libopenui/src/window.h +++ b/radio/src/thirdparty/libopenui/src/window.h @@ -30,6 +30,7 @@ #include "libopenui_defines.h" #include "libopenui_helpers.h" #include "libopenui_config.h" +#include "../../lvgl/src/lvgl.h" typedef uint32_t WindowFlags; @@ -63,7 +64,7 @@ class Window friend class GridLayout; public: - Window(Window * parent, const rect_t & rect, WindowFlags windowFlags = 0, LcdFlags textFlags = 0); + Window(Window * parent, const rect_t & rect, WindowFlags windowFlags = 0, LcdFlags textFlags = 0, bool isScreen = false); virtual ~Window(); @@ -384,7 +385,10 @@ class Window return _deleted; } + inline lv_obj_t *getLvObj() { return lvobj; } + protected: + lv_obj_t *lvobj = nullptr; Window * parent; std::list children; rect_t rect;