From 3e3d8b95e77a0ba076c70fa5ce067dc6f5a7214f Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 4 Nov 2019 18:31:50 +0100 Subject: [PATCH] Menus can now have a title and a Cancel button --- .../thirdparty/libopenui/src/bitmapbuffer.h | 23 ++++-- radio/src/thirdparty/libopenui/src/choice.cpp | 3 + radio/src/thirdparty/libopenui/src/choice.h | 6 ++ .../libopenui/src/libopenui_defines.h | 3 + radio/src/thirdparty/libopenui/src/menu.cpp | 69 ++++++++++++----- radio/src/thirdparty/libopenui/src/menu.h | 77 +++++++++++++------ 6 files changed, 134 insertions(+), 47 deletions(-) diff --git a/radio/src/thirdparty/libopenui/src/bitmapbuffer.h b/radio/src/thirdparty/libopenui/src/bitmapbuffer.h index 808435001..8945c6254 100644 --- a/radio/src/thirdparty/libopenui/src/bitmapbuffer.h +++ b/radio/src/thirdparty/libopenui/src/bitmapbuffer.h @@ -108,6 +108,17 @@ class BitmapBufferBase this->offsetY = offsetY; } + inline void clearOffset() + { + setOffset(0, 0); + } + + inline void reset() + { + clearOffset(); + clearClippingRect(); + } + coord_t getOffsetX() const { return offsetX; @@ -146,8 +157,8 @@ class BitmapBufferBase inline const pixel_t * getPixelPtr(coord_t x, coord_t y) const { #if defined(PCBX10) && !defined(SIMU) - x = width - x - 1; - y = height - y - 1; + x = _width - x - 1; + y = _height - y - 1; #endif return &data[y * _width + x]; } @@ -284,8 +295,8 @@ class BitmapBuffer: public BitmapBufferBase inline const pixel_t * getPixelPtr(coord_t x, coord_t y) const { #if defined(PCBX10) && !defined(SIMU) - x = width - x - 1; - y = height - y - 1; + x = _width - x - 1; + y = _height - y - 1; #endif return &data[y * _width + x]; } @@ -293,8 +304,8 @@ class BitmapBuffer: public BitmapBufferBase inline pixel_t * getPixelPtr(coord_t x, coord_t y) { #if defined(PCBX10) && !defined(SIMU) - x = width - x - 1; - y = height - y - 1; + x = _width - x - 1; + y = _height - y - 1; #endif return &data[y * _width + x]; } diff --git a/radio/src/thirdparty/libopenui/src/choice.cpp b/radio/src/thirdparty/libopenui/src/choice.cpp index 34de099f9..57c084d8e 100644 --- a/radio/src/thirdparty/libopenui/src/choice.cpp +++ b/radio/src/thirdparty/libopenui/src/choice.cpp @@ -55,6 +55,9 @@ void Choice::onEvent(event_t event) void Choice::openMenu() { auto menu = new Menu(); + if (!menuTitle.empty()) + menu->setTitle(menuTitle); + auto value = getValue(); int count = 0; int current = -1; diff --git a/radio/src/thirdparty/libopenui/src/choice.h b/radio/src/thirdparty/libopenui/src/choice.h index 6930f8192..1442bdcf2 100644 --- a/radio/src/thirdparty/libopenui/src/choice.h +++ b/radio/src/thirdparty/libopenui/src/choice.h @@ -80,10 +80,16 @@ class Choice : public ChoiceBase { textHandler = std::move(handler); } + void setMenuTitle(const std::string value) + { + menuTitle = std::move(value); + } + protected: const char * values = nullptr; int16_t vmin = 0; int16_t vmax = 0; + std::string menuTitle; std::function getValue; std::function setValue; std::function isValueAvailable; diff --git a/radio/src/thirdparty/libopenui/src/libopenui_defines.h b/radio/src/thirdparty/libopenui/src/libopenui_defines.h index d613b2bdc..ab3a6e324 100644 --- a/radio/src/thirdparty/libopenui/src/libopenui_defines.h +++ b/radio/src/thirdparty/libopenui/src/libopenui_defines.h @@ -101,6 +101,9 @@ #define SCROLLBAR_COLOR COLOR(SCROLLBAR_COLOR_INDEX) #define MENU_COLOR COLOR(MENU_COLOR_INDEX) #define MENU_BGCOLOR COLOR(MENU_BGCOLOR_INDEX) +#define MENU_LINE_COLOR COLOR(MENU_LINE_COLOR_INDEX) +#define MENU_HIGHLIGHT_COLOR COLOR(MENU_HIGHLIGHT_COLOR_INDEX) +#define MENU_HIGHLIGHT_BGCOLOR COLOR(MENU_HIGHLIGHT_BGCOLOR_INDEX) #define CUSTOM_COLOR COLOR(CUSTOM_COLOR_INDEX) #endif diff --git a/radio/src/thirdparty/libopenui/src/menu.cpp b/radio/src/thirdparty/libopenui/src/menu.cpp index 9a79f2358..ceacfc7a5 100644 --- a/radio/src/thirdparty/libopenui/src/menu.cpp +++ b/radio/src/thirdparty/libopenui/src/menu.cpp @@ -18,14 +18,16 @@ */ #include "menu.h" +#include "font.h" MenuWindow::MenuWindow(Menu * parent): - Window(parent, {LCD_W / 2 - 100, LCD_H / 2, 200, 0}, OPAQUE) + Window(parent, {(LCD_W - MENUS_WIDTH) / 2, (LCD_H - MENUS_WIDTH) / 2, MENUS_WIDTH, 0}, OPAQUE), + body(this, {0, 0, width(), height()}, OPAQUE) { - setFocus(); + body.setFocus(); } -void MenuWindow::select(int index) +void MenuBody::select(int index) { selectedIndex = index; if (innerHeight > height()) { @@ -35,7 +37,7 @@ void MenuWindow::select(int index) } #if defined(HARDWARE_KEYS) -void MenuWindow::onEvent(event_t event) +void MenuBody::onEvent(event_t event) { TRACE_WINDOWS("%s received event 0x%X", getWindowDebugString().c_str(), event); @@ -61,7 +63,7 @@ void MenuWindow::onEvent(event_t event) #endif #if defined(HARDWARE_TOUCH) -bool MenuWindow::onTouchEnd(coord_t x, coord_t y) +bool MenuBody::onTouchEnd(coord_t x, coord_t y) { int index = y / MENUS_LINE_HEIGHT; lines[index].onPress(); @@ -69,13 +71,18 @@ bool MenuWindow::onTouchEnd(coord_t x, coord_t y) } #endif -void MenuWindow::paint(BitmapBuffer * dc) +void MenuBody::paint(BitmapBuffer * dc) { - int width = (innerHeight > height() ? 195 : 200); dc->clear(MENU_BGCOLOR); - for (auto i = 0; i < lines.size(); i++) { + + for (auto i = 0; i < (int)lines.size(); i++) { auto & line = lines[i]; - LcdFlags flags = (selectedIndex == (int) i ? HIGHLIGHT_COLOR : MENU_COLOR); + LcdFlags flags = MENU_COLOR; + if (selectedIndex == i) { + flags = MENU_HIGHLIGHT_COLOR; + if (MENU_HIGHLIGHT_BGCOLOR != MENU_BGCOLOR) + dc->drawSolidFilledRect(0, i * MENUS_LINE_HEIGHT, width(), MENUS_LINE_HEIGHT, MENU_HIGHLIGHT_BGCOLOR); + } if (line.drawLine) { line.drawLine(dc, 0, i * MENUS_LINE_HEIGHT /*+ (lineHeight - 20) / 2*/, flags); } @@ -84,38 +91,64 @@ void MenuWindow::paint(BitmapBuffer * dc) dc->drawText(10, i * MENUS_LINE_HEIGHT + (MENUS_LINE_HEIGHT - 20) / 2, text[0] == '\0' ? "---" : text, flags); } if (i > 0) { - dc->drawSolidHorizontalLine(0, i * MENUS_LINE_HEIGHT - 1, width, DISABLE_COLOR); + dc->drawSolidHorizontalLine(0, i * MENUS_LINE_HEIGHT - 1, MENUS_WIDTH, MENU_LINE_COLOR); } } } +void MenuWindow::paint(BitmapBuffer * dc) +{ + // the background + dc->clear(MENU_BGCOLOR); + + // the title + if (!title.empty()) { + dc->drawText(MENUS_WIDTH / 2, (MENUS_HEADER_HEIGHT - getFontHeight(FONT(BOLD))) / 2, title.c_str(), CENTERED | FONT(BOLD)); + dc->drawSolidHorizontalLine(0, MENUS_HEADER_HEIGHT - 1, MENUS_WIDTH, MENU_LINE_COLOR); + } + + // the cancel button + if (MENUS_FOOTER_HEIGHT > 0) { + dc->drawText(MENUS_WIDTH / 2, height() - MENUS_FOOTER_HEIGHT + (MENUS_FOOTER_HEIGHT - getFontHeight(FONT(BOLD))) / 2, "Cancel", CENTERED); + dc->drawSolidHorizontalLine(0, height() - MENUS_FOOTER_HEIGHT, MENUS_WIDTH, MENU_LINE_COLOR); + } +} + void Menu::updatePosition() { if (!toolbar) { // there is no navigation bar at the left, we may center the window on screen - int count = min(MENUS_MAX_LINES, menuWindow.lines.size()); - coord_t h = count * MENUS_LINE_HEIGHT - 1; - menuWindow.setTop((LCD_H - h) / 2 + 20); - menuWindow.setHeight(h); + auto headerHeight = menuWindow.title.empty() ? 0 : MENUS_HEADER_HEIGHT; + auto bodyHeight = limit(MENUS_MIN_HEIGHT, menuWindow.body.lines.size() * MENUS_LINE_HEIGHT - 1, MENUS_MAX_HEIGHT); + menuWindow.setTop((LCD_H - headerHeight - bodyHeight - MENUS_FOOTER_HEIGHT) / 2 + MENUS_OFFSET_TOP); + menuWindow.setHeight(headerHeight + bodyHeight + MENUS_FOOTER_HEIGHT); + menuWindow.body.setTop(headerHeight); + menuWindow.body.setHeight(bodyHeight); } - menuWindow.setInnerHeight(menuWindow.lines.size() * MENUS_LINE_HEIGHT - 1); + menuWindow.body.setInnerHeight(menuWindow.body.lines.size() * MENUS_LINE_HEIGHT - 1); +} + +void Menu::setTitle(const std::string text) +{ + menuWindow.setTitle(text); + updatePosition(); } void Menu::addLine(const std::string & text, std::function onPress) { - menuWindow.addLine(text, std::move(onPress)); + menuWindow.body.addLine(text, std::move(onPress)); updatePosition(); } void Menu::addCustomLine(std::function drawLine, std::function onPress) { - menuWindow.addCustomLine(drawLine, std::move(onPress)); + menuWindow.body.addCustomLine(drawLine, std::move(onPress)); updatePosition(); } void Menu::removeLines() { - menuWindow.removeLines(); + menuWindow.body.removeLines(); updatePosition(); } diff --git a/radio/src/thirdparty/libopenui/src/menu.h b/radio/src/thirdparty/libopenui/src/menu.h index bcfb87d5d..fe0356a17 100644 --- a/radio/src/thirdparty/libopenui/src/menu.h +++ b/radio/src/thirdparty/libopenui/src/menu.h @@ -26,12 +26,14 @@ #include "mainwindow.h" class Menu; +class MenuWindow; -class MenuWindow: public Window { +class MenuBody: public Window { + friend class MenuWindow; friend class Menu; class MenuLine { - friend class MenuWindow; + friend class MenuBody; public: MenuLine(std::string text, std::function onPress): @@ -57,19 +59,21 @@ class MenuWindow: public Window { }; public: - explicit MenuWindow(Menu * parent); - -#if defined(DEBUG_WINDOWS) - std::string getName() override + MenuBody(Window * parent, const rect_t & rect, WindowFlags flags): + Window(parent, rect, flags) { - return "MenuWindow"; + setPageHeight(MENUS_LINE_HEIGHT); } + + void select(int index); + +#if defined(HARDWARE_KEYS) + void onEvent(event_t event) override; #endif - void setCancelHandler(std::function handler) - { - onCancel = handler; - } +#if defined(HARDWARE_TOUCH) + bool onTouchEnd(coord_t x, coord_t y) override; +#endif void addLine(const std::string & text, std::function onPress) { @@ -89,18 +93,13 @@ class MenuWindow: public Window { invalidate(); } - void select(int index); + void setCancelHandler(std::function handler) + { + onCancel = handler; + } void paint(BitmapBuffer * dc) override; -#if defined(HARDWARE_KEYS) - void onEvent(event_t event) override; -#endif - -#if defined(HARDWARE_TOUCH) - bool onTouchEnd(coord_t x, coord_t y) override; -#endif - protected: std::vector lines; #if defined(HARDWARE_TOUCH) @@ -111,6 +110,36 @@ class MenuWindow: public Window { std::function onCancel; }; +class MenuWindow: public Window { + friend class Menu; + + public: + explicit MenuWindow(Menu * parent); + + ~MenuWindow() override + { + body.detach(); + } + +#if defined(DEBUG_WINDOWS) + std::string getName() override + { + return "MenuWindow"; + } +#endif + + void setTitle(const std::string text) + { + title = std::move(text); + } + + void paint(BitmapBuffer * dc) override; + + protected: + MenuBody body; + std::string title; +}; + class Menu : public Window { public: Menu() : @@ -129,7 +158,7 @@ class Menu : public Window { void setCancelHandler(std::function handler) { - menuWindow.setCancelHandler(handler); + menuWindow.body.setCancelHandler(handler); } void deleteLater() @@ -157,15 +186,17 @@ class Menu : public Window { menuWindow.setHeight(toolbar->height()); } + void setTitle(const std::string text); + void addLine(const std::string & text, std::function onPress); void addCustomLine(std::function drawLine, std::function onPress); void removeLines(); - void select(int index) + inline void select(int index) { - menuWindow.select(index); + menuWindow.body.select(index); } #if defined(HARDWARE_KEYS)