diff --git a/companion/src/firmwares/edgetx/yaml_screendata.cpp b/companion/src/firmwares/edgetx/yaml_screendata.cpp index df67ec693..fae6c7436 100644 --- a/companion/src/firmwares/edgetx/yaml_screendata.cpp +++ b/companion/src/firmwares/edgetx/yaml_screendata.cpp @@ -65,7 +65,13 @@ Node convert::encode(const ZoneOptionValueTyped& rhs) value["source"] = rhs.value.sourceValue; break; case ZOV_Color: - value["color"] = color_to_hex(rhs.value.colorValue); + if (rhs.value.colorValue & 0x80000000) { + value["color"] = color_to_hex(rhs.value.colorValue & 0xFFFFFF); + } else { + std::string s("COLIDX"); + s += std::to_string(rhs.value.colorValue); + value["color"] = s; + } break; default: break; @@ -86,7 +92,17 @@ bool convert::decode(const Node& node, value["boolValue"] >> rhs.value.boolValue; value["stringValue"] >> rhs.value.stringValue; value["source"] >> rhs.value.sourceValue; - value["color"] >> rhs.value.colorValue; + std::string s; + value["color"] >> s; + if (s.substr(0, 6) == "COLIDX") { + // Index color + rhs.value.colorValue = stoi(s.substr(6)); + } else { + unsigned int c; + sscanf(s.c_str(), "0x%x", &c); + // Mark as RGB color + rhs.value.colorValue = c | 0x80000000; + } } } return true; diff --git a/radio/src/gui/colorlcd/LvglWrapper.cpp b/radio/src/gui/colorlcd/LvglWrapper.cpp index 8eac03776..7be938b27 100644 --- a/radio/src/gui/colorlcd/LvglWrapper.cpp +++ b/radio/src/gui/colorlcd/LvglWrapper.cpp @@ -173,29 +173,13 @@ static void keyboardDriverRead(lv_indev_drv_t *drv, lv_indev_data_t *data) } } -static void copy_ts_to_indev_data(const TouchState &st, lv_indev_data_t *data) -{ - data->point.x = st.x; - data->point.y = st.y; -} - -static lv_indev_data_t touch_data_backup; - -static void backup_touch_data(lv_indev_data_t* data) -{ - memcpy(&touch_data_backup, data, sizeof(lv_indev_data_t)); -} - -static void copy_touch_data_backup(lv_indev_data_t* data) -{ - memcpy(data, &touch_data_backup, sizeof(lv_indev_data_t)); -} - extern "C" void touchDriverRead(lv_indev_drv_t *drv, lv_indev_data_t *data) { #if defined(HARDWARE_TOUCH) + static lv_indev_data_t touch_data_backup; + if(!touchPanelEventOccured()) { - copy_touch_data_backup(data); + memcpy(data, &touch_data_backup, sizeof(lv_indev_data_t)); return; } @@ -218,14 +202,16 @@ extern "C" void touchDriverRead(lv_indev_drv_t *drv, lv_indev_data_t *data) if(st.event == TE_NONE) { TRACE("TE_NONE"); - } else if(st.event == TE_DOWN || st.event == TE_SLIDE) { - TRACE("INDEV_STATE_PRESSED"); - data->state = LV_INDEV_STATE_PRESSED; - copy_ts_to_indev_data(st, data); } else { - TRACE("INDEV_STATE_RELEASED"); - data->state = LV_INDEV_STATE_RELEASED; - copy_ts_to_indev_data(st, data); + if(st.event == TE_DOWN || st.event == TE_SLIDE) { + TRACE("TE_PRESSED"); + data->state = LV_INDEV_STATE_PRESSED; + } else { + TRACE("TE_RELEASED"); + data->state = LV_INDEV_STATE_RELEASED; + } + data->point.x = st.x; + data->point.y = st.y; } static bool onebeep=true; // TODO... This probably needs to be fixed in the driver it's sending two events @@ -237,8 +223,8 @@ extern "C" void touchDriverRead(lv_indev_drv_t *drv, lv_indev_data_t *data) } else { onebeep = true; } - - backup_touch_data(data); + + memcpy(&touch_data_backup, data, sizeof(lv_indev_data_t)); #endif } diff --git a/radio/src/gui/colorlcd/color_editor.cpp b/radio/src/gui/colorlcd/color_editor.cpp index 0bba354c8..11fd142c6 100644 --- a/radio/src/gui/colorlcd/color_editor.cpp +++ b/radio/src/gui/colorlcd/color_editor.cpp @@ -45,7 +45,7 @@ class ColorBar : public FormField nullptr); etx_std_style(lvobj, LV_PART_MAIN, PAD_ZERO); - etx_obj_add_style(lvobj, styles->border_color_edit, LV_PART_MAIN | LV_STATE_EDITED); + etx_obj_add_style(lvobj, styles->border_color[COLOR_THEME_EDIT_INDEX], LV_PART_MAIN | LV_STATE_EDITED); etx_obj_add_style(lvobj, styles->outline_color_edit, LV_PART_MAIN | LV_STATE_EDITED); } @@ -289,7 +289,9 @@ class HSVColorType : public BarColorType public: HSVColorType(Window* parent, uint32_t color) : BarColorType(parent) { - auto r = GET_RED(color), g = GET_GREEN(color), b = GET_BLUE(color); + auto rgb = COLOR_VAL(colorToRGB(color)); + + auto r = GET_RED(rgb), g = GET_GREEN(rgb), b = GET_BLUE(rgb); float values[MAX_BARS]; RGBtoHSV(r, g, b, values[0], values[1], values[2]); values[1] *= MAX_SATURATION; // convert the proper base @@ -322,7 +324,7 @@ class HSVColorType : public BarColorType uint32_t getRGB() override { - return HSVtoRGB(bars[0]->value, bars[1]->value, bars[2]->value); + return COLOR2FLAGS(HSVtoRGB(bars[0]->value, bars[1]->value, bars[2]->value)) | RGB_FLAG; } protected: @@ -335,7 +337,9 @@ class RGBColorType : public BarColorType public: RGBColorType(Window* parent, uint32_t color) : BarColorType(parent) { - auto r = GET_RED(color), g = GET_GREEN(color), b = GET_BLUE(color); + auto rgb = COLOR_VAL(colorToRGB(color)); + + auto r = GET_RED(rgb), g = GET_GREEN(rgb), b = GET_BLUE(rgb); float values[MAX_BARS]; values[0] = r; values[1] = g; @@ -354,7 +358,7 @@ class RGBColorType : public BarColorType uint32_t getRGB() override { - return RGB(bars[0]->value, bars[1]->value, bars[2]->value); + return RGB2FLAGS(bars[0]->value, bars[1]->value, bars[2]->value); } protected: @@ -392,8 +396,7 @@ class ThemeColorType : public ColorType auto btn = new TextButton(parent, rect_t{}, " "); etx_bg_color(btn->getLvObj(), (LcdColorIndex)color); btn->setPressHandler([=]() { - auto cv = lcdColorTable[color]; - m_color = RGB(GET_RED(cv), GET_GREEN(cv), GET_BLUE(cv)); + m_color = COLOR2FLAGS(color); lv_event_send(parent->getParent()->getParent()->getLvObj(), LV_EVENT_VALUE_CHANGED, nullptr); return 0; diff --git a/radio/src/gui/colorlcd/color_list.cpp b/radio/src/gui/colorlcd/color_list.cpp index 7b4306d13..53290dff1 100644 --- a/radio/src/gui/colorlcd/color_list.cpp +++ b/radio/src/gui/colorlcd/color_list.cpp @@ -78,7 +78,7 @@ static void color_swatch_constructor(const lv_obj_class_t *class_p, { etx_obj_add_style(obj, styles->bg_opacity_cover, LV_PART_MAIN); etx_obj_add_style(obj, styles->border_thin, LV_PART_MAIN); - etx_obj_add_style(obj, styles->border_color_black, LV_PART_MAIN); + etx_obj_add_style(obj, styles->border_color[COLOR_BLACK_INDEX], LV_PART_MAIN); } static const lv_obj_class_t color_swatch_class = { diff --git a/radio/src/gui/colorlcd/color_picker.cpp b/radio/src/gui/colorlcd/color_picker.cpp index 393143509..1847b3a47 100644 --- a/radio/src/gui/colorlcd/color_picker.cpp +++ b/radio/src/gui/colorlcd/color_picker.cpp @@ -48,7 +48,10 @@ class ColorEditorPopup : public BaseDialog void updateColor(uint32_t c) { m_color = c; - uint8_t r = GET_RED(c), g = GET_GREEN(c), b = GET_BLUE(c); + + auto rgb = COLOR_VAL(colorToRGB(m_color)); + + uint8_t r = GET_RED(rgb), g = GET_GREEN(rgb), b = GET_BLUE(rgb); colorPad->setColor(r, g, b); @@ -157,8 +160,8 @@ class ColorEditorPopup : public BaseDialog }; ColorPicker::ColorPicker(Window* parent, const rect_t& rect, - std::function getValue, - std::function setValue) : + std::function getValue, + std::function setValue) : Button(parent, {rect.x, rect.y, ColorEditorPopup::COLOR_PAD_WIDTH, ColorEditorPopup::COLOR_PAD_HEIGHT}), setValue(std::move(setValue)) { @@ -180,7 +183,8 @@ void ColorPicker::updateColor(uint32_t c) { color = c; + auto rgb = COLOR_VAL(colorToRGB(color)); auto lvcolor = - lv_color_make(GET_RED(color), GET_GREEN(color), GET_BLUE(color)); + lv_color_make(GET_RED(rgb), GET_GREEN(rgb), GET_BLUE(rgb)); lv_obj_set_style_bg_color(lvobj, lvcolor, LV_PART_MAIN); } diff --git a/radio/src/gui/colorlcd/color_picker.h b/radio/src/gui/colorlcd/color_picker.h index b120b751b..bb1814f79 100644 --- a/radio/src/gui/colorlcd/color_picker.h +++ b/radio/src/gui/colorlcd/color_picker.h @@ -26,14 +26,14 @@ class ColorPicker : public Button { uint32_t color; - std::function setValue; + std::function setValue; void updateColor(uint32_t c); public: ColorPicker(Window* parent, const rect_t& rect, - std::function getValue, - std::function setValue = nullptr); + std::function getValue, + std::function setValue = nullptr); void setColor(uint32_t c); uint32_t getColor() const { return color; } diff --git a/radio/src/gui/colorlcd/colors.cpp b/radio/src/gui/colorlcd/colors.cpp index da67682b5..cd14da7c5 100644 --- a/radio/src/gui/colorlcd/colors.cpp +++ b/radio/src/gui/colorlcd/colors.cpp @@ -142,6 +142,16 @@ LcdColorIndex indexFromColor(uint32_t lcdFlags) return CUSTOM_COLOR_INDEX; } +// Return flags with RGB color value instead of indexed theme color +LcdFlags colorToRGB(LcdFlags colorFlags) +{ + // RGB or indexed color? + if (colorFlags & RGB_FLAG) + return colorFlags; + + return (colorFlags & 0xFFFF) | COLOR(COLOR_VAL(colorFlags)) | RGB_FLAG; +} + /** * Helper function to translate a colorFlags value to a lv_color_t suitable * for passing to an lv_obj function diff --git a/radio/src/gui/colorlcd/colors.h b/radio/src/gui/colorlcd/colors.h index 7bed5b818..27faf4eb2 100644 --- a/radio/src/gui/colorlcd/colors.h +++ b/radio/src/gui/colorlcd/colors.h @@ -139,4 +139,6 @@ extern uint32_t HSVtoRGB(float H, float S, float V); extern void RGBtoHSV(uint8_t R, uint8_t G, uint8_t B, float& fH, float& fS, float& fV); +LcdFlags colorToRGB(LcdFlags colorFlags); + lv_color_t makeLvColor(uint32_t colorFlags); diff --git a/radio/src/gui/colorlcd/curve.cpp b/radio/src/gui/colorlcd/curve.cpp index 6c500914d..fffce35ef 100644 --- a/radio/src/gui/colorlcd/curve.cpp +++ b/radio/src/gui/colorlcd/curve.cpp @@ -153,7 +153,7 @@ Curve::Curve(Window* parent, const rect_t& rect, etx_solid_bg(p, COLOR_THEME_PRIMARY2_INDEX); etx_obj_add_style(p, styles->circle, LV_PART_MAIN); etx_obj_add_style(p, styles->border, LV_PART_MAIN); - etx_obj_add_style(p, styles->border_color_dark, LV_PART_MAIN); + etx_obj_add_style(p, styles->border_color[COLOR_THEME_SECONDARY1_INDEX], LV_PART_MAIN); lv_obj_set_size(p, 9, 9); lv_obj_add_flag(p, LV_OBJ_FLAG_HIDDEN); pointDots[i] = p; @@ -174,7 +174,7 @@ Curve::Curve(Window* parent, const rect_t& rect, etx_solid_bg(posPoint, COLOR_THEME_PRIMARY2_INDEX); etx_obj_add_style(posPoint, styles->circle, LV_PART_MAIN); etx_obj_add_style(posPoint, styles->border, LV_PART_MAIN); - etx_obj_add_style(posPoint, styles->border_color_active, LV_PART_MAIN); + etx_obj_add_style(posPoint, styles->border_color[COLOR_THEME_ACTIVE_INDEX], LV_PART_MAIN); lv_obj_set_size(posPoint, 9, 9); updatePosition(); diff --git a/radio/src/gui/colorlcd/custom_failsafe.cpp b/radio/src/gui/colorlcd/custom_failsafe.cpp index e3fbb2894..3ed909280 100644 --- a/radio/src/gui/colorlcd/custom_failsafe.cpp +++ b/radio/src/gui/colorlcd/custom_failsafe.cpp @@ -34,7 +34,7 @@ class ChannelFailsafeBargraph : public Window Window(parent, rect), channel(channel) { etx_obj_add_style(lvobj, styles->border_thin, LV_PART_MAIN); - etx_obj_add_style(lvobj, styles->border_color_black, LV_PART_MAIN); + etx_obj_add_style(lvobj, styles->border_color[COLOR_BLACK_INDEX], LV_PART_MAIN); outputsBar = new OutputChannelBar(this, {0, 1, width() - 2, ChannelBar::BAR_HEIGHT}, channel, false, false); diff --git a/radio/src/gui/colorlcd/layouts/layout2x4.cpp b/radio/src/gui/colorlcd/layouts/layout2x4.cpp index 8f405375e..12f366039 100644 --- a/radio/src/gui/colorlcd/layouts/layout2x4.cpp +++ b/radio/src/gui/colorlcd/layouts/layout2x4.cpp @@ -25,9 +25,9 @@ const ZoneOption OPTIONS_LAYOUT_2x4[] = { LAYOUT_COMMON_OPTIONS, {"Panel1 background", ZoneOption::Bool, OPTION_VALUE_BOOL(true)}, - {" Color", ZoneOption::Color, OPTION_VALUE_UNSIGNED(RGB(77, 112, 203))}, + {" Color", ZoneOption::Color, RGB2FLAGS(77, 112, 203)}, {"Panel2 background", ZoneOption::Bool, OPTION_VALUE_BOOL(true)}, - {" Color", ZoneOption::Color, OPTION_VALUE_UNSIGNED(RGB(77, 112, 203))}, + {" Color", ZoneOption::Color, RGB2FLAGS(77, 112, 203)}, LAYOUT_OPTIONS_END}; class Layout2x4 : public Layout @@ -92,17 +92,8 @@ class Layout2x4 : public Layout lv_obj_add_flag(panel2, LV_OBJ_FLAG_HIDDEN); } - LcdFlags color = - COLOR2FLAGS(getOptionValue(OPTION_PANEL1_COLOR)->unsignedValue); - if (color != panel1Color) { - panel1Color = color; - lv_obj_set_style_bg_color(panel1, makeLvColor(panel1Color), LV_PART_MAIN); - } - color = COLOR2FLAGS(getOptionValue(OPTION_PANEL2_COLOR)->unsignedValue); - if (color != panel2Color) { - panel2Color = color; - lv_obj_set_style_bg_color(panel2, makeLvColor(panel2Color), LV_PART_MAIN); - } + etx_bg_color_from_flags(panel1, getOptionValue(OPTION_PANEL1_COLOR)->unsignedValue); + etx_bg_color_from_flags(panel2, getOptionValue(OPTION_PANEL2_COLOR)->unsignedValue); } }; diff --git a/radio/src/gui/colorlcd/page.cpp b/radio/src/gui/colorlcd/page.cpp index 5c552f058..63cf1796c 100644 --- a/radio/src/gui/colorlcd/page.cpp +++ b/radio/src/gui/colorlcd/page.cpp @@ -25,9 +25,8 @@ #include "themes/etx_lv_theme.h" #include "view_main.h" -PageHeader::PageHeader(Page* parent, EdgeTxIcon icon) : - Window(parent, {0, 0, LCD_W, EdgeTxStyles::MENU_HEADER_HEIGHT}), - icon(icon) +PageHeader::PageHeader(Window* parent, EdgeTxIcon icon) : + Window(parent, {0, 0, LCD_W, EdgeTxStyles::MENU_HEADER_HEIGHT}) { setWindowFlag(NO_FOCUS | OPAQUE); @@ -41,6 +40,21 @@ PageHeader::PageHeader(Page* parent, EdgeTxIcon icon) : "", COLOR_THEME_PRIMARY2); } +PageHeader::PageHeader(Window* parent, const char* iconFile) : + Window(parent, {0, 0, LCD_W, EdgeTxStyles::MENU_HEADER_HEIGHT}) +{ + setWindowFlag(NO_FOCUS | OPAQUE); + + etx_solid_bg(lvobj, COLOR_THEME_SECONDARY1_INDEX); + + new HeaderIcon(this, iconFile); + + title = new StaticText(this, + {PAGE_TITLE_LEFT, PAGE_TITLE_TOP, + LCD_W - PAGE_TITLE_LEFT, EdgeTxStyles::PAGE_LINE_HEIGHT}, + "", COLOR_THEME_PRIMARY2); +} + StaticText* PageHeader::setTitle2(std::string txt) { if (title2 == nullptr) { diff --git a/radio/src/gui/colorlcd/page.h b/radio/src/gui/colorlcd/page.h index 80660f954..3a34a27c6 100644 --- a/radio/src/gui/colorlcd/page.h +++ b/radio/src/gui/colorlcd/page.h @@ -30,7 +30,8 @@ class Page; class PageHeader : public Window { public: - PageHeader(Page* parent, EdgeTxIcon icon); + PageHeader(Window* parent, EdgeTxIcon icon); + PageHeader(Window* parent, const char* iconFile); void setTitle(std::string txt) { title->setText(std::move(txt)); } StaticText* setTitle2(std::string txt); @@ -39,7 +40,6 @@ class PageHeader : public Window static constexpr coord_t PAGE_TITLE_TOP = 2; protected: - EdgeTxIcon icon; StaticText* title; StaticText* title2 = nullptr; }; diff --git a/radio/src/gui/colorlcd/popups.cpp b/radio/src/gui/colorlcd/popups.cpp index 0b2c453e4..51fa865a8 100644 --- a/radio/src/gui/colorlcd/popups.cpp +++ b/radio/src/gui/colorlcd/popups.cpp @@ -126,7 +126,7 @@ static void bubble_popup_constructor(const lv_obj_class_t* class_p, lv_obj_t* ob etx_obj_add_style(obj, bubble_popup, LV_PART_MAIN); etx_bg_color(obj, COLOR_WHITE_INDEX, LV_PART_MAIN); etx_txt_color(obj, COLOR_BLACK_INDEX, LV_PART_MAIN); - etx_obj_add_style(obj, styles->border_color_black, LV_PART_MAIN); + etx_obj_add_style(obj, styles->border_color[COLOR_BLACK_INDEX], LV_PART_MAIN); } static const lv_obj_class_t bubble_popup_class = { diff --git a/radio/src/gui/colorlcd/select_fab_carousel.cpp b/radio/src/gui/colorlcd/select_fab_carousel.cpp index 7f58648fb..e3e2c53fc 100644 --- a/radio/src/gui/colorlcd/select_fab_carousel.cpp +++ b/radio/src/gui/colorlcd/select_fab_carousel.cpp @@ -34,7 +34,7 @@ static void etx_quick_button_constructor(const lv_obj_class_t* class_p, etx_obj_add_style(obj, styles->pad_medium, LV_PART_MAIN); etx_obj_add_style(obj, styles->border, LV_PART_MAIN | LV_STATE_FOCUSED); - etx_obj_add_style(obj, styles->border_color_white, + etx_obj_add_style(obj, styles->border_color[COLOR_WHITE_INDEX], LV_PART_MAIN | LV_STATE_FOCUSED); } @@ -60,7 +60,7 @@ static void etx_quick_icon_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj) { etx_obj_add_style(obj, styles->border, LV_PART_MAIN); - etx_obj_add_style(obj, styles->border_color_white, LV_PART_MAIN); + etx_obj_add_style(obj, styles->border_color[COLOR_WHITE_INDEX], LV_PART_MAIN); etx_obj_add_style(obj, styles->outline, LV_PART_MAIN); lv_obj_set_style_outline_color(obj, lv_color_black(), LV_PART_MAIN); etx_obj_add_style(obj, styles->circle, LV_PART_MAIN); diff --git a/radio/src/gui/colorlcd/special_functions.cpp b/radio/src/gui/colorlcd/special_functions.cpp index acd1e8cea..7edd0eb9f 100644 --- a/radio/src/gui/colorlcd/special_functions.cpp +++ b/radio/src/gui/colorlcd/special_functions.cpp @@ -53,7 +53,7 @@ static void sf_enable_state_constructor(const lv_obj_class_t *class_p, etx_obj_add_style(obj, sf_enable_state_style, LV_PART_MAIN); etx_obj_add_style(obj, styles->outline_color_light, LV_PART_MAIN); etx_obj_add_style(obj, styles->border, LV_PART_MAIN); - etx_obj_add_style(obj, styles->border_color_dark, LV_PART_MAIN); + etx_obj_add_style(obj, styles->border_color[COLOR_THEME_SECONDARY1_INDEX], LV_PART_MAIN); etx_obj_add_style(obj, styles->bg_opacity_cover, LV_PART_MAIN); etx_bg_color(obj, COLOR_THEME_ACTIVE_INDEX, LV_STATE_CHECKED); } diff --git a/radio/src/gui/colorlcd/standalone_lua.cpp b/radio/src/gui/colorlcd/standalone_lua.cpp index 74f15a59b..ed84e71e1 100644 --- a/radio/src/gui/colorlcd/standalone_lua.cpp +++ b/radio/src/gui/colorlcd/standalone_lua.cpp @@ -23,31 +23,7 @@ #include "translations.h" #include "view_main.h" - -constexpr uint32_t FIELD_PADDING_LEFT = 3; -constexpr coord_t POPUP_HEADER_HEIGHT = 30; - -extern BitmapBuffer* luaLcdBuffer; - -void LuaPopup::paint(BitmapBuffer* dc, uint8_t type, const char* text, - const char* info) -{ - // popup background - dc->drawSolidFilledRect(0, 0, rect.w, POPUP_HEADER_HEIGHT, COLOR_THEME_FOCUS); - - const char* title = text; // TODO: based on 'type' - - // title bar - dc->drawText(FIELD_PADDING_LEFT, - (POPUP_HEADER_HEIGHT - getFontHeight(FONT(STD))) / 2, title, - COLOR_THEME_PRIMARY2); - - dc->drawSolidFilledRect(0, POPUP_HEADER_HEIGHT, rect.w, - rect.h - POPUP_HEADER_HEIGHT, COLOR_THEME_SECONDARY3); - - dc->drawText(FIELD_PADDING_LEFT, POPUP_HEADER_HEIGHT + EdgeTxStyles::PAGE_LINE_HEIGHT, info, - COLOR_THEME_SECONDARY1); -} +#include "dma2d.h" void StandaloneLuaWindow::redraw_cb(lv_event_t* e) { @@ -59,26 +35,15 @@ void StandaloneLuaWindow::redraw_cb(lv_event_t* e) if (widget) { lv_draw_ctx_t* draw_ctx = lv_event_get_draw_ctx(e); - lv_area_t a, clipping, obj_coords; - lv_area_copy(&a, draw_ctx->buf_area); - lv_area_copy(&clipping, draw_ctx->clip_area); - lv_obj_get_coords(target, &obj_coords); - - auto w = a.x2 - a.x1 + 1; - auto h = a.y2 - a.y1 + 1; + auto w = draw_ctx->buf_area->x2 - draw_ctx->buf_area->x1 + 1; + auto h = draw_ctx->buf_area->y2 - draw_ctx->buf_area->y1 + 1; TRACE_WINDOWS("Draw %s", widget->getWindowDebugString().c_str()); - BitmapBuffer buf = {BMP_RGB565, (uint16_t)w, (uint16_t)h, - (uint16_t*)draw_ctx->buf}; - - buf.setDrawCtx(draw_ctx); - - buf.setOffset(obj_coords.x1 - a.x1, obj_coords.y1 - a.y1); - buf.setClippingRect(clipping.x1 - a.x1, clipping.x2 + 1 - a.x1, - clipping.y1 - a.y1, clipping.y2 + 1 - a.y1); - - buf.drawBitmap(0 - buf.getOffsetX(), 0 - buf.getOffsetY(), &widget->lcdBuffer); + // Standalone script always redraws full screen + DMAWait(); + DMACopyBitmap((uint16_t*)draw_ctx->buf, w, h, 0, 0, + widget->lcdBuffer->getData(), w, h, 0, 0, w, h); } } @@ -87,9 +52,7 @@ StandaloneLuaWindow* StandaloneLuaWindow::_instance; StandaloneLuaWindow::StandaloneLuaWindow(bool useLvgl) : Window(MainWindow::instance(), {0, 0, LCD_W, LCD_H}), - useLvgl(useLvgl), - lcdBuffer(BMP_RGB565, LCD_W, LCD_H), - popup({50, 73, LCD_W - 100, LCD_H - 146}) + useLvgl(useLvgl) { setWindowFlag(OPAQUE); @@ -98,6 +61,7 @@ StandaloneLuaWindow::StandaloneLuaWindow(bool useLvgl) : if (useLvglLayout()) { padAll(PAD_ZERO); etx_scrollbar(lvobj); + lv_obj_t* lbl = lv_label_create(lvobj); lv_obj_set_pos(lbl, 0, 0); lv_obj_set_size(lbl, LCD_W, LCD_H); @@ -109,8 +73,10 @@ StandaloneLuaWindow::StandaloneLuaWindow(bool useLvgl) : luaLvglManager = this; } else { - lcdBuffer.clear(); - lcdBuffer.drawText(LCD_W / 2, LCD_H / 2 - 20, STR_LOADING, + lcdBuffer = new BitmapBuffer(BMP_RGB565, LCD_W, LCD_H); + + lcdBuffer->clear(); + lcdBuffer->drawText(LCD_W / 2, LCD_H / 2 - 20, STR_LOADING, FONT(L) | COLOR_THEME_PRIMARY2 | CENTERED); lv_obj_clear_flag(lvobj, LV_OBJ_FLAG_SCROLLABLE); lv_obj_clear_flag(lvobj, LV_OBJ_FLAG_CLICK_FOCUSABLE); @@ -155,6 +121,9 @@ void StandaloneLuaWindow::deleteLater(bool detach, bool trash) { if (_deleted) return; + if (lcdBuffer) delete lcdBuffer; + lcdBuffer = nullptr; + luaLvglManager = nullptr; Layer::pop(this); @@ -176,14 +145,13 @@ void StandaloneLuaWindow::checkEvents() Window::checkEvents(); // Set global LUA LCD buffer - luaLcdBuffer = &lcdBuffer; + luaLcdBuffer = lcdBuffer; if (luaState != INTERPRETER_RELOAD_PERMANENT_SCRIPTS) { - // if LUA finished a full cycle, - // invalidate to display the screen buffer - bool useLvgl = useLvglLayout(); if (luaTask(true)) { - if (useLvgl && !hasError) { + if (useLvglLayout() && !hasError) { + // if LUA finished a full cycle, + // call update functions PROTECT_LUA() { if (!callRefs(lsScripts)) { luaShowError(); @@ -193,6 +161,8 @@ void StandaloneLuaWindow::checkEvents() } UNPROTECT_LUA(); } else { + // if LUA finished a full cycle, + // invalidate to display the screen buffer invalidate(); } } @@ -217,23 +187,37 @@ void StandaloneLuaWindow::onEvent(event_t evt) LuaEventHandler::onEvent(evt); } +void StandaloneLuaWindow::popupPaint(BitmapBuffer* dc, coord_t x, coord_t y, coord_t w, coord_t h, + const char* text, const char* info) +{ + // popup background + dc->drawSolidFilledRect(x, y, w, POPUP_HEADER_HEIGHT, COLOR_THEME_FOCUS); + + // title bar + dc->drawText(x + PAD_SMALL, + y + (POPUP_HEADER_HEIGHT - getFontHeight(FONT(STD))) / 2, text, + COLOR_THEME_PRIMARY2); + + dc->drawSolidFilledRect(x, y + POPUP_HEADER_HEIGHT, w, + h - POPUP_HEADER_HEIGHT, COLOR_THEME_SECONDARY3); + + dc->drawText(x + PAD_SMALL, y + POPUP_HEADER_HEIGHT + EdgeTxStyles::PAGE_LINE_HEIGHT, info, + COLOR_THEME_SECONDARY1); +} + bool StandaloneLuaWindow::displayPopup(event_t event, uint8_t type, const char* text, const char* info, bool& result) { + if (useLvgl) return true; + // transparent background - lcdBuffer.drawFilledRect(0, 0, LCD_W, LCD_H, SOLID, COLOR_THEME_PRIMARY1, - OPACITY(5)); + lcdBuffer->drawFilledRect(0, 0, LCD_W, LCD_H, SOLID, COLOR_THEME_PRIMARY1, + OPACITY(5)); - // center pop-up - lcdBuffer.setOffset(LCD_W / 2 - popup.rect.w / 2, - LCD_H / 2 - popup.rect.h / 2); + popupPaint(lcdBuffer, POPUP_X, POPUP_Y, LCD_W - POPUP_X * 2, LCD_H - POPUP_Y * 2, text, info); - // draw it, then clear the offset - popup.paint(&lcdBuffer, type, text, info); - lcdBuffer.clearOffset(); - - TRACE("displayPopup(event = 0x%x)", event); + // TRACE("displayPopup(event = 0x%x)", event); if (event == EVT_KEY_BREAK(KEY_EXIT)) { result = false; return true; diff --git a/radio/src/gui/colorlcd/standalone_lua.h b/radio/src/gui/colorlcd/standalone_lua.h index 5ec992341..5065dda9c 100644 --- a/radio/src/gui/colorlcd/standalone_lua.h +++ b/radio/src/gui/colorlcd/standalone_lua.h @@ -26,13 +26,6 @@ #include "lua/lua_api.h" #include "lua/lua_widget.h" -struct LuaPopup -{ - rect_t rect; - LuaPopup(rect_t r) : rect(r) {} - void paint(BitmapBuffer* dc, uint8_t type, const char* text, const char* info); -}; - class StandaloneLuaWindow : public Window, public LuaEventHandler, public LuaLvglManager { static StandaloneLuaWindow* _instance; @@ -64,6 +57,10 @@ public: bool isWidget() override { return false; } + static LAYOUT_VAL(POPUP_HEADER_HEIGHT, 30, 30); + static LAYOUT_VAL(POPUP_X, 50, 40); + static LAYOUT_VAL(POPUP_Y, 70, 110); + protected: lv_obj_t* prevScreen = nullptr; lv_obj_t* errorModal = nullptr; @@ -73,10 +70,11 @@ protected: bool useLvgl = false; // GFX - BitmapBuffer lcdBuffer; + BitmapBuffer *lcdBuffer = nullptr; // pop-ups - LuaPopup popup; + void popupPaint(BitmapBuffer* dc, coord_t x, coord_t y, coord_t w, coord_t h, + const char* text, const char* info); // run LUA code void runLua(event_t evt); diff --git a/radio/src/gui/colorlcd/theme_manager.cpp b/radio/src/gui/colorlcd/theme_manager.cpp index f17af54e8..934a7ae9d 100644 --- a/radio/src/gui/colorlcd/theme_manager.cpp +++ b/radio/src/gui/colorlcd/theme_manager.cpp @@ -509,6 +509,9 @@ HeaderDateTime::HeaderDateTime(Window* parent, coord_t x, coord_t y) : etx_txt_color(time, COLOR_THEME_PRIMARY2_INDEX); etx_font(time, FONT_XS_INDEX); + lv_obj_add_flag(lvobj, LV_OBJ_FLAG_EVENT_BUBBLE); + lv_obj_clear_flag(lvobj, LV_OBJ_FLAG_CLICKABLE); + checkEvents(); } @@ -534,10 +537,10 @@ void HeaderDateTime::checkEvents() } } -void HeaderDateTime::setColor(uint32_t color) +void HeaderDateTime::setColor(LcdFlags color) { - lv_obj_set_style_text_color(date, makeLvColor(color), LV_PART_MAIN); - lv_obj_set_style_text_color(time, makeLvColor(color), LV_PART_MAIN); + etx_txt_color_from_flags(date, color); + etx_txt_color_from_flags(time, color); } HeaderIcon::HeaderIcon(Window* parent, EdgeTxIcon icon) : @@ -546,13 +549,19 @@ HeaderIcon::HeaderIcon(Window* parent, EdgeTxIcon icon) : (new StaticIcon(this, 0, 0, icon, COLOR_THEME_PRIMARY2))->center(width(), height()); } +HeaderIcon::HeaderIcon(Window* parent, const char* iconFile) : + StaticIcon(parent, 0, 0, ICON_TOPLEFT_BG, COLOR_THEME_FOCUS) +{ + (new StaticIcon(this, 0, 0, iconFile, COLOR_THEME_PRIMARY2))->center(width(), height()); +} + UsbSDConnected::UsbSDConnected() : Window(MainWindow::instance(), {0, 0, LCD_W, LCD_H}) { setWindowFlag(OPAQUE); etx_solid_bg(lvobj, COLOR_THEME_PRIMARY1_INDEX); - dateTime = new HeaderDateTime(this, LCD_W - TopBar::HDR_DATE_XO, HDR_DATE_Y); + new HeaderDateTime(this, LCD_W - TopBar::HDR_DATE_XO, HDR_DATE_Y); auto icon = new StaticIcon(this, 0, 0, ICON_USB_PLUGGED, COLOR_THEME_PRIMARY2); lv_obj_center(icon->getLvObj()); diff --git a/radio/src/gui/colorlcd/theme_manager.h b/radio/src/gui/colorlcd/theme_manager.h index 2b7eb9b73..9f79c9177 100644 --- a/radio/src/gui/colorlcd/theme_manager.h +++ b/radio/src/gui/colorlcd/theme_manager.h @@ -163,7 +163,7 @@ class HeaderDateTime : public Window public: HeaderDateTime(Window* parent, int x, int y); - void setColor(uint32_t color); + void setColor(LcdFlags color); static LAYOUT_VAL(HDR_DATE_WIDTH, 45, 45) static LAYOUT_VAL(HDR_DATE_HEIGHT, 12, 12) @@ -181,6 +181,7 @@ class HeaderIcon : public StaticIcon { public: HeaderIcon(Window *parent, EdgeTxIcon icon); + HeaderIcon(Window *parent, const char* iconFile); }; class UsbSDConnected : public Window @@ -189,7 +190,4 @@ class UsbSDConnected : public Window UsbSDConnected(); static LAYOUT_VAL(HDR_DATE_Y, 6, 6) - - protected: - HeaderDateTime* dateTime = nullptr; }; diff --git a/radio/src/gui/colorlcd/themes/etx_lv_theme.cpp b/radio/src/gui/colorlcd/themes/etx_lv_theme.cpp index eb68aa359..98b1f788b 100644 --- a/radio/src/gui/colorlcd/themes/etx_lv_theme.cpp +++ b/radio/src/gui/colorlcd/themes/etx_lv_theme.cpp @@ -234,17 +234,13 @@ EdgeTxStyles::EdgeTxStyles() lv_style_init(&txt_color[i]); lv_style_init(&img_color[i]); lv_style_set_img_recolor_opa(&img_color[i], LV_OPA_COVER); + lv_style_init(&border_color[i]); + lv_style_init(&arc_color[i]); } - lv_style_init(&border_color_dark); - lv_style_init(&border_color_normal); - lv_style_init(&border_color_focus); - lv_style_init(&border_color_active); - lv_style_init(&border_color_edit); lv_style_init(&outline_color_light); lv_style_init(&outline_color_normal); lv_style_init(&outline_color_focus); lv_style_init(&outline_color_edit); - lv_style_init(&arc_color); lv_style_init(&graph_border); lv_style_init(&graph_dashed); lv_style_init(&graph_line); @@ -281,13 +277,6 @@ EdgeTxStyles::EdgeTxStyles() lv_style_set_line_width(&div_line_white, 1); lv_style_set_line_opa(&div_line_white, LV_OPA_COVER); - lv_style_init(&bg_color_grey); - lv_style_set_bg_color(&bg_color_grey, lv_palette_main(LV_PALETTE_GREY)); - lv_style_init(&border_color_black); - lv_style_set_border_color(&border_color_black, lv_color_black()); - lv_style_init(&border_color_white); - lv_style_set_border_color(&border_color_white, lv_color_white()); - // Fonts for (int i = FONT_STD_INDEX; i < FONTS_COUNT; i += 1) { lv_style_init(&font[i]); @@ -315,9 +304,12 @@ void EdgeTxStyles::applyColors() // Always update colors in case theme changes for (int i = 0; i < TOTAL_COLOR_COUNT; i += 1) { - lv_style_set_bg_color(&bg_color[i], makeLvColor(COLOR(i))); - lv_style_set_text_color(&txt_color[i], makeLvColor(COLOR(i))); - lv_style_set_img_recolor(&img_color[i], makeLvColor(COLOR(i))); + auto c = makeLvColor(COLOR(i)); + lv_style_set_bg_color(&bg_color[i], c); + lv_style_set_text_color(&txt_color[i], c); + lv_style_set_img_recolor(&img_color[i], c); + lv_style_set_border_color(&border_color[i], c); + lv_style_set_arc_color(&arc_color[i], c); } lv_style_set_line_color(&graph_border, makeLvColor(COLOR_THEME_SECONDARY2)); @@ -330,17 +322,6 @@ void EdgeTxStyles::applyColors() lv_style_set_line_color(&div_line_black, makeLvColor(COLOR_THEME_PRIMARY1)); lv_style_set_line_color(&div_line_white, makeLvColor(COLOR_THEME_PRIMARY2)); - lv_style_set_border_color(&border_color_dark, - makeLvColor(COLOR_THEME_SECONDARY1)); - lv_style_set_border_color(&border_color_normal, - makeLvColor(COLOR_THEME_SECONDARY2)); - lv_style_set_border_color(&border_color_focus, - makeLvColor(COLOR_THEME_FOCUS)); - lv_style_set_border_color(&border_color_active, - makeLvColor(COLOR_THEME_ACTIVE)); - lv_style_set_border_color(&border_color_edit, - makeLvColor(COLOR_THEME_EDIT)); - lv_style_set_outline_color(&outline_color_light, makeLvColor(COLOR_THEME_SECONDARY3)); lv_style_set_outline_color(&outline_color_normal, @@ -349,11 +330,9 @@ void EdgeTxStyles::applyColors() makeLvColor(COLOR_THEME_FOCUS)); lv_style_set_outline_color(&outline_color_edit, makeLvColor(COLOR_THEME_EDIT)); - - lv_style_set_arc_color(&arc_color, makeLvColor(COLOR_THEME_SECONDARY1)); } -static EdgeTxStyles *mainStyles = nullptr; +static EdgeTxStyles* mainStyles = nullptr; static EdgeTxStyles* previewStyles = nullptr; EdgeTxStyles* styles = nullptr; @@ -401,24 +380,92 @@ void etx_font(lv_obj_t* obj, FontIndex fontIdx, lv_style_selector_t selector) etx_obj_add_style(obj, styles->font[fontIdx], selector); } +void etx_remove_bg_color(lv_obj_t* obj, lv_style_selector_t selector) +{ + // Remove styles + for (int i = 0; i < TOTAL_COLOR_COUNT; i += 1) + lv_obj_remove_style(obj, &styles->bg_color[i], selector); +} + void etx_bg_color(lv_obj_t* obj, LcdColorIndex colorIdx, lv_style_selector_t selector) { // Remove old style first - for (int i = 0; i < TOTAL_COLOR_COUNT; i += 1) - lv_obj_remove_style(obj, &styles->bg_color[i], selector); + etx_remove_bg_color(obj, selector); etx_obj_add_style(obj, styles->bg_color[colorIdx], selector); } +void etx_bg_color_from_flags(lv_obj_t* obj, LcdFlags colorFlags, + lv_style_selector_t selector) +{ + if (colorFlags & RGB_FLAG) { + etx_remove_bg_color(obj, selector); + lv_obj_set_style_bg_color(obj, + makeLvColor(colorToRGB(colorFlags)), selector); + } else { + lv_obj_remove_local_style_prop(obj, LV_STYLE_BG_COLOR, selector); + etx_bg_color(obj, (LcdColorIndex)COLOR_VAL(colorFlags), selector); + } +} + +void etx_remove_txt_color(lv_obj_t* obj, lv_style_selector_t selector) +{ + // Remove styles + for (int i = 0; i < TOTAL_COLOR_COUNT; i += 1) + lv_obj_remove_style(obj, &styles->txt_color[i], selector); +} + void etx_txt_color(lv_obj_t* obj, LcdColorIndex colorIdx, lv_style_selector_t selector) { // Remove old style first - for (int i = 0; i < TOTAL_COLOR_COUNT; i += 1) - lv_obj_remove_style(obj, &styles->txt_color[i], selector); + etx_remove_txt_color(obj, selector); etx_obj_add_style(obj, styles->txt_color[colorIdx], selector); } +void etx_txt_color_from_flags(lv_obj_t* obj, LcdFlags colorFlags, + lv_style_selector_t selector) +{ + if (colorFlags & RGB_FLAG) { + etx_remove_txt_color(obj, selector); + lv_obj_set_style_text_color(obj, + makeLvColor(colorToRGB(colorFlags)), selector); + } else { + lv_obj_remove_local_style_prop(obj, LV_STYLE_TEXT_COLOR, selector); + etx_txt_color(obj, (LcdColorIndex)COLOR_VAL(colorFlags), selector); + } +} + +void etx_remove_border_color(lv_obj_t* obj, lv_style_selector_t selector) +{ + // Remove styles + for (int i = 0; i < TOTAL_COLOR_COUNT; i += 1) + lv_obj_remove_style(obj, &styles->border_color[i], selector); +} + +void etx_border_color(lv_obj_t* obj, LcdColorIndex colorIdx, + lv_style_selector_t selector) +{ + // Remove old style first + etx_remove_border_color(obj, selector); + etx_obj_add_style(obj, styles->border_color[colorIdx], selector); +} + +void etx_remove_arc_color(lv_obj_t* obj, lv_style_selector_t selector) +{ + // Remove styles + for (int i = 0; i < TOTAL_COLOR_COUNT; i += 1) + lv_obj_remove_style(obj, &styles->arc_color[i], selector); +} + +void etx_arc_color(lv_obj_t* obj, LcdColorIndex colorIdx, + lv_style_selector_t selector) +{ + // Remove old style first + etx_remove_arc_color(obj, selector); + etx_obj_add_style(obj, styles->arc_color[colorIdx], selector); +} + void etx_img_color(lv_obj_t* obj, LcdColorIndex colorIdx, lv_style_selector_t selector) { @@ -433,7 +480,7 @@ void etx_std_ctrl_colors(lv_obj_t* obj, lv_style_selector_t selector) etx_solid_bg(obj, COLOR_THEME_PRIMARY2_INDEX, selector); etx_txt_color(obj, COLOR_THEME_SECONDARY1_INDEX, selector); - etx_obj_add_style(obj, styles->border_color_focus, + etx_obj_add_style(obj, styles->border_color[COLOR_THEME_FOCUS_INDEX], selector | LV_STATE_FOCUSED); etx_bg_color(obj, COLOR_THEME_ACTIVE_INDEX, selector | LV_STATE_CHECKED); @@ -446,7 +493,7 @@ void etx_std_ctrl_colors(lv_obj_t* obj, lv_style_selector_t selector) void etx_std_settings(lv_obj_t* obj, lv_style_selector_t selector) { etx_obj_add_style(obj, styles->border, selector); - etx_obj_add_style(obj, styles->border_color_normal, selector); + etx_obj_add_style(obj, styles->border_color[COLOR_THEME_SECONDARY2_INDEX], selector); etx_obj_add_style(obj, styles->rounded, selector); etx_obj_add_style(obj, styles->outline, selector | LV_STATE_FOCUSED); @@ -500,7 +547,7 @@ void etx_std_style(lv_obj_t* obj, lv_style_selector_t selector, void etx_scrollbar(lv_obj_t* obj) { etx_obj_add_style(obj, styles->scrollbar, LV_PART_SCROLLBAR); - etx_obj_add_style(obj, styles->bg_color_grey, LV_PART_SCROLLBAR); + etx_obj_add_style(obj, styles->bg_color[COLOR_GREY_INDEX], LV_PART_SCROLLBAR); etx_obj_add_style(obj, styles->bg_opacity_cover, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); lv_obj_set_scrollbar_mode(obj, LV_SCROLLBAR_MODE_AUTO); @@ -519,7 +566,7 @@ lv_obj_t* etx_create(const lv_obj_class_t* class_p, lv_obj_t* parent) static void textarea_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj) { etx_obj_add_style(obj, styles->border, LV_PART_MAIN); - etx_obj_add_style(obj, styles->border_color_normal, LV_PART_MAIN); + etx_obj_add_style(obj, styles->border_color[COLOR_THEME_SECONDARY2_INDEX], LV_PART_MAIN); etx_obj_add_style(obj, styles->rounded, LV_PART_MAIN); etx_std_ctrl_colors(obj, LV_PART_MAIN); etx_obj_add_style(obj, styles->pad_textarea, LV_PART_MAIN); diff --git a/radio/src/gui/colorlcd/themes/etx_lv_theme.h b/radio/src/gui/colorlcd/themes/etx_lv_theme.h index 7ea909292..e3d27f9d7 100644 --- a/radio/src/gui/colorlcd/themes/etx_lv_theme.h +++ b/radio/src/gui/colorlcd/themes/etx_lv_theme.h @@ -84,11 +84,25 @@ void etx_solid_bg(lv_obj_t* obj, void etx_font(lv_obj_t* obj, FontIndex fontIdx, lv_style_selector_t selector = LV_PART_MAIN); +void etx_remove_bg_color(lv_obj_t* obj, lv_style_selector_t selector = LV_PART_MAIN); void etx_bg_color(lv_obj_t* obj, LcdColorIndex colorIdx, lv_style_selector_t selector = LV_PART_MAIN); +void etx_bg_color_from_flags(lv_obj_t* obj, LcdFlags colorFlags, + lv_style_selector_t selector = LV_PART_MAIN); +void etx_remove_txt_color(lv_obj_t* obj, lv_style_selector_t selector = LV_PART_MAIN); void etx_txt_color(lv_obj_t* obj, LcdColorIndex colorIdx, lv_style_selector_t selector = LV_PART_MAIN); +void etx_txt_color_from_flags(lv_obj_t* obj, LcdFlags colorFlags, + lv_style_selector_t selector = LV_PART_MAIN); + +void etx_remove_border_color(lv_obj_t* obj, lv_style_selector_t selector = LV_PART_MAIN); +void etx_border_color(lv_obj_t* obj, LcdColorIndex colorIdx, + lv_style_selector_t selector = LV_PART_MAIN); + +void etx_remove_arc_color(lv_obj_t* obj, lv_style_selector_t selector = LV_PART_MAIN); +void etx_arc_color(lv_obj_t* obj, LcdColorIndex colorIdx, + lv_style_selector_t selector = LV_PART_MAIN); void etx_img_color(lv_obj_t* obj, LcdColorIndex colorIdx, lv_style_selector_t selector = LV_PART_MAIN); @@ -122,19 +136,12 @@ class EdgeTxStyles lv_style_t bg_color[TOTAL_COLOR_COUNT]; lv_style_t txt_color[TOTAL_COLOR_COUNT]; lv_style_t img_color[TOTAL_COLOR_COUNT]; - lv_style_t border_color_dark; - lv_style_t border_color_normal; - lv_style_t border_color_black; - lv_style_t border_color_white; - lv_style_t border_color_focus; - lv_style_t border_color_active; - lv_style_t border_color_edit; + lv_style_t border_color[TOTAL_COLOR_COUNT]; + lv_style_t arc_color[TOTAL_COLOR_COUNT]; lv_style_t outline_color_light; lv_style_t outline_color_normal; lv_style_t outline_color_focus; lv_style_t outline_color_edit; - lv_style_t bg_color_grey; - lv_style_t arc_color; lv_style_t graph_border; lv_style_t graph_dashed; lv_style_t graph_line; diff --git a/radio/src/gui/colorlcd/view_about.cpp b/radio/src/gui/colorlcd/view_about.cpp index 431cfff3c..aa7ae1305 100644 --- a/radio/src/gui/colorlcd/view_about.cpp +++ b/radio/src/gui/colorlcd/view_about.cpp @@ -41,14 +41,11 @@ const std::string edgetx_url = "https://edgetx.org"; AboutUs::AboutUs() : BaseDialog(MainWindow::instance(), STR_ABOUT_US, true, 220, LV_SIZE_CONTENT) { - new StaticText(form, rect_t{0, 0, LV_PCT(100), LV_SIZE_CONTENT}, + new StaticText(form, {0, 0, LV_PCT(100), LV_SIZE_CONTENT}, about_str + "\n" + copyright_str, COLOR_THEME_SECONDARY1 | CENTERED); - auto qrBox = new Window(form, {0, 0, LV_PCT(100), 160}); - auto qr = lv_qrcode_create(qrBox->getLvObj(), 150, - makeLvColor(COLOR_THEME_SECONDARY1), - makeLvColor(COLOR_THEME_SECONDARY3)); - lv_qrcode_update(qr, edgetx_url.c_str(), edgetx_url.length()); - lv_obj_center(qr); + auto qrBox = new Window(form, {0, 0, LV_PCT(100), QR_SZ}); + auto qr = new QRCode(qrBox, 0, 0, QR_SZ, edgetx_url); + lv_obj_center(qr->getLvObj()); } diff --git a/radio/src/gui/colorlcd/view_about.h b/radio/src/gui/colorlcd/view_about.h index 9db224110..bf2631875 100644 --- a/radio/src/gui/colorlcd/view_about.h +++ b/radio/src/gui/colorlcd/view_about.h @@ -25,4 +25,6 @@ class AboutUs : public BaseDialog { public: AboutUs(); + + static LAYOUT_VAL(QR_SZ, 150, 150) }; diff --git a/radio/src/gui/colorlcd/widget.cpp b/radio/src/gui/colorlcd/widget.cpp index b97f88a1e..f3073ea79 100644 --- a/radio/src/gui/colorlcd/widget.cpp +++ b/radio/src/gui/colorlcd/widget.cpp @@ -262,24 +262,12 @@ void WidgetFactory::initPersistentData(Widget::PersistentData* persistentData, for (const ZoneOption* option = options; option->name; option++, i++) { TRACE("WidgetFactory::initPersistentData() setting option '%s'", option->name); - // TODO compiler bug? The CPU freezes ... persistentData->options[i++] = - // option->deflt; auto optVal = &persistentData->options[i]; auto optType = zoneValueEnumFromType(option->type); if (setDefault || optVal->type != optType) { // reset to default value memcpy(&optVal->value, &option->deflt, sizeof(ZoneOptionValue)); optVal->type = optType; - if (option->type == ZoneOption::Color) { - // If color value is in defaultColors - change it to current theme - // color - for (int i = 1; i < LCD_COLOR_COUNT - 1; i += 1) { - if (optVal->value.unsignedValue == defaultColors[i]) { - optVal->value.unsignedValue = lcdColorTable[i]; - break; - } - } - } } } } diff --git a/radio/src/gui/colorlcd/widget_settings.cpp b/radio/src/gui/colorlcd/widget_settings.cpp index db2001ba6..e630009ef 100644 --- a/radio/src/gui/colorlcd/widget_settings.cpp +++ b/radio/src/gui/colorlcd/widget_settings.cpp @@ -168,12 +168,11 @@ WidgetSettings::WidgetSettings(Window* parent, Widget* w) : case ZoneOption::Color: new ColorPicker( line, rect_t{}, - [=]() -> int { // getValue - return (int)widget->getOptionValue(optIdx)->unsignedValue; + [=]() -> uint32_t { // getValue + return widget->getOptionValue(optIdx)->unsignedValue; }, - [=](int newValue) { // setValue - widget->getOptionValue(optIdx)->unsignedValue = - (uint32_t)newValue; + [=](uint32_t newValue) { // setValue + widget->getOptionValue(optIdx)->unsignedValue = newValue; SET_DIRTY(); }); break; diff --git a/radio/src/gui/colorlcd/widgets/gauge.cpp b/radio/src/gui/colorlcd/widgets/gauge.cpp index deb2c3e7a..7e15594fc 100644 --- a/radio/src/gui/colorlcd/widgets/gauge.cpp +++ b/radio/src/gui/colorlcd/widgets/gauge.cpp @@ -39,9 +39,6 @@ class GaugeWidget : public Widget etx_obj_add_style(valueText->getLvObj(), styles->text_align_right, LV_STATE_USER_1); - lv_style_init(&style); - lv_style_set_bg_opa(&style, LV_OPA_COVER); - auto box = lv_obj_create(lvobj); lv_obj_set_pos(box, 0, 16); lv_obj_set_size(box, lv_pct(100), 16); @@ -51,7 +48,7 @@ class GaugeWidget : public Widget bar = lv_obj_create(box); lv_obj_set_pos(bar, 0, 0); lv_obj_clear_flag(bar, LV_OBJ_FLAG_CLICKABLE); - lv_obj_add_style(bar, &style, LV_PART_MAIN); + etx_obj_add_style(bar, styles->bg_opacity_cover, LV_PART_MAIN); update(); } @@ -84,9 +81,7 @@ class GaugeWidget : public Widget else lv_obj_clear_state(valueText->getLvObj(), LV_STATE_USER_1); - lv_color_t color; - color.full = persistentData->options[3].value.unsignedValue; - lv_style_set_bg_color(&style, color); + etx_bg_color_from_flags(bar, persistentData->options[3].value.unsignedValue); } static const ZoneOption options[]; @@ -96,7 +91,6 @@ class GaugeWidget : public Widget StaticText* sourceText = nullptr; DynamicNumber* valueText = nullptr; lv_obj_t* bar = nullptr; - lv_style_t style; void checkEvents() override { @@ -118,8 +112,7 @@ const ZoneOption GaugeWidget::options[] = { OPTION_VALUE_SIGNED(-RESX), OPTION_VALUE_SIGNED(RESX)}, {STR_MAX, ZoneOption::Integer, OPTION_VALUE_SIGNED(RESX), OPTION_VALUE_SIGNED(-RESX), OPTION_VALUE_SIGNED(RESX)}, - {STR_COLOR, ZoneOption::Color, - OPTION_VALUE_UNSIGNED(COLOR_THEME_WARNING >> 16)}, + {STR_COLOR, ZoneOption::Color, COLOR2FLAGS(COLOR_THEME_WARNING_INDEX)}, {nullptr, ZoneOption::Bool}}; BaseWidgetFactory gaugeWidget("Gauge", GaugeWidget::options, diff --git a/radio/src/gui/colorlcd/widgets/modelbmp.cpp b/radio/src/gui/colorlcd/widgets/modelbmp.cpp index 18246e8fc..3df4952d9 100644 --- a/radio/src/gui/colorlcd/widgets/modelbmp.cpp +++ b/radio/src/gui/colorlcd/widgets/modelbmp.cpp @@ -34,9 +34,6 @@ class ModelBitmapWidget : public Widget Widget::PersistentData* persistentData) : Widget(factory, parent, rect, persistentData) { - lv_style_init(&style); - lv_obj_add_style(lvobj, &style, LV_PART_MAIN); - etx_obj_add_style(lvobj, styles->bg_opacity_transparent, LV_PART_MAIN); etx_obj_add_style(lvobj, styles->bg_opacity_cover, LV_PART_MAIN | ETX_STATE_BG_FILL); @@ -66,8 +63,6 @@ class ModelBitmapWidget : public Widget void update() override { - lv_color_t color; - isLarge = rect.h >= 96 && rect.w >= 120; // get font size from options[1] @@ -79,8 +74,7 @@ class ModelBitmapWidget : public Widget etx_txt_color(label->getLvObj(), COLOR_THEME_SECONDARY1_INDEX, LV_PART_MAIN); } else { - color.full = persistentData->options[0].value.unsignedValue; - lv_obj_set_style_text_color(label->getLvObj(), color, LV_PART_MAIN); + etx_txt_color_from_flags(label->getLvObj(), persistentData->options[0].value.unsignedValue); } // Set label position @@ -89,9 +83,8 @@ class ModelBitmapWidget : public Widget else lv_obj_set_pos(label->getLvObj(), 0, 0); - // get font color from options[3] - color.full = persistentData->options[3].value.unsignedValue; - lv_style_set_bg_color(&style, color); + // get fill color from options[3] + etx_bg_color_from_flags(lvobj, persistentData->options[3].value.unsignedValue); // Set background opacity from options[2] if (persistentData->options[2].value.boolValue) @@ -127,7 +120,6 @@ class ModelBitmapWidget : public Widget bool isLarge = false; // std::unique_ptr buffer; uint32_t deps_hash = 0; - lv_style_t style; StaticText* label = nullptr; StaticImage* image = nullptr; @@ -135,12 +127,10 @@ class ModelBitmapWidget : public Widget }; const ZoneOption ModelBitmapWidget::options[] = { - {STR_COLOR, ZoneOption::Color, - OPTION_VALUE_UNSIGNED(COLOR_THEME_SECONDARY1 >> 16)}, + {STR_COLOR, ZoneOption::Color, COLOR2FLAGS(COLOR_THEME_SECONDARY1_INDEX)}, {STR_SIZE, ZoneOption::TextSize, OPTION_VALUE_UNSIGNED(FONT_STD_INDEX)}, {STR_FILL_BACKGROUND, ZoneOption::Bool, OPTION_VALUE_BOOL(false)}, - {STR_BG_COLOR, ZoneOption::Color, - OPTION_VALUE_UNSIGNED(COLOR_THEME_SECONDARY3 >> 16)}, + {STR_BG_COLOR, ZoneOption::Color, COLOR2FLAGS(COLOR_THEME_SECONDARY3_INDEX)}, {STR_USE_THEME_COLOR, ZoneOption::Bool, OPTION_VALUE_BOOL(true)}, {nullptr, ZoneOption::Bool}}; diff --git a/radio/src/gui/colorlcd/widgets/outputs.cpp b/radio/src/gui/colorlcd/widgets/outputs.cpp index 0f23a1d14..40093f939 100644 --- a/radio/src/gui/colorlcd/widgets/outputs.cpp +++ b/radio/src/gui/colorlcd/widgets/outputs.cpp @@ -43,7 +43,7 @@ class ChannelValue : public Window lv_obj_clear_flag(lvobj, LV_OBJ_FLAG_CLICKABLE); etx_obj_add_style(lvobj, styles->border_thin, LV_PART_MAIN); - etx_obj_add_style(lvobj, styles->border_color_black, LV_PART_MAIN); + etx_obj_add_style(lvobj, styles->border_color[COLOR_BLACK_INDEX], LV_PART_MAIN); padAll(PAD_ZERO); @@ -51,28 +51,30 @@ class ChannelValue : public Window lv_style_set_width(&style, lv_pct(100)); lv_style_set_height(&style, lv_pct(100)); - lv_color_t color; - color.full = txtColor >> 16u; - lv_style_set_text_color(&style, color); - color.full = barColor >> 16u; - lv_style_set_bg_color(&style, color); + // lv_color_t color; + // color.full = txtColor >> 16u; + // lv_style_set_text_color(&style, color); + // color.full = barColor >> 16u; + // lv_style_set_bg_color(&style, color); bar = lv_obj_create(lvobj); lv_obj_set_style_bg_opa(bar, LV_OPA_COVER, LV_PART_MAIN); - lv_obj_add_style(bar, &style, LV_PART_MAIN); lv_obj_clear_flag(bar, LV_OBJ_FLAG_CLICKABLE); lv_obj_set_size(bar, 0, ROW_HEIGHT - 1); + etx_bg_color_from_flags(bar, barColor); valueLabel = lv_label_create(lvobj); etx_font(valueLabel, FONT_XS_INDEX); etx_obj_add_style(valueLabel, styles->text_align_right, LV_PART_MAIN); + etx_txt_color_from_flags(valueLabel, txtColor); lv_obj_add_style(valueLabel, &style, LV_PART_MAIN); lv_label_set_text(valueLabel, ""); chanLabel = lv_label_create(lvobj); etx_font(chanLabel, FONT_XS_INDEX); etx_obj_add_style(chanLabel, styles->text_align_left, LV_PART_MAIN); - lv_obj_add_style(chanLabel, &style, LV_PART_MAIN); + etx_txt_color_from_flags(chanLabel, txtColor); + lv_label_set_text(chanLabel, ""); chanHasName = g_model.limitData[channel].name[0] != 0; setChannel(); @@ -168,9 +170,7 @@ class OutputsWidget : public Widget void update() override { // get background color from options[2] - lv_color_t color; - color.full = persistentData->options[2].value.unsignedValue; - lv_style_set_bg_color(&style, color); + etx_bg_color_from_flags(lvobj, persistentData->options[2].value.unsignedValue); // Set background opacity from options[1] if (persistentData->options[1].value.boolValue) @@ -179,8 +179,8 @@ class OutputsWidget : public Widget lv_obj_clear_state(lvobj, ETX_STATE_BG_FILL); // Colors - txtColor = COLOR2FLAGS(persistentData->options[3].value.unsignedValue); - barColor = COLOR2FLAGS(persistentData->options[4].value.unsignedValue); + txtColor = persistentData->options[3].value.unsignedValue; + barColor = persistentData->options[4].value.unsignedValue; // Setup channels firstChan = persistentData->options[0].value.unsignedValue; @@ -221,12 +221,9 @@ const ZoneOption OutputsWidget::options[] = { {STR_FIRST_CHANNEL, ZoneOption::Integer, OPTION_VALUE_UNSIGNED(1), OPTION_VALUE_UNSIGNED(1), OPTION_VALUE_UNSIGNED(32)}, {STR_FILL_BACKGROUND, ZoneOption::Bool, OPTION_VALUE_BOOL(false)}, - {STR_BG_COLOR, ZoneOption::Color, - OPTION_VALUE_UNSIGNED(COLOR_THEME_SECONDARY3 >> 16)}, - {STR_TEXT_COLOR, ZoneOption::Color, - OPTION_VALUE_UNSIGNED(COLOR_THEME_PRIMARY1 >> 16)}, - {STR_COLOR, ZoneOption::Color, - OPTION_VALUE_UNSIGNED(COLOR_THEME_SECONDARY1 >> 16)}, + {STR_BG_COLOR, ZoneOption::Color, COLOR2FLAGS(COLOR_THEME_SECONDARY3_INDEX)}, + {STR_TEXT_COLOR, ZoneOption::Color, COLOR2FLAGS(COLOR_THEME_PRIMARY1_INDEX)}, + {STR_COLOR, ZoneOption::Color, COLOR2FLAGS(COLOR_THEME_SECONDARY1_INDEX)}, {nullptr, ZoneOption::Bool}}; BaseWidgetFactory outputsWidget("Outputs", diff --git a/radio/src/gui/colorlcd/widgets/radio_info.cpp b/radio/src/gui/colorlcd/widgets/radio_info.cpp index e80bdc7dc..2bdda83e8 100644 --- a/radio/src/gui/colorlcd/widgets/radio_info.cpp +++ b/radio/src/gui/colorlcd/widgets/radio_info.cpp @@ -107,17 +107,10 @@ class RadioInfoWidget : public TopBarWidget void update() override { - lv_color_t color; - // get colors from options - color.full = persistentData->options[2].value.unsignedValue; - lv_obj_set_style_bg_color(batteryFill, color, LV_PART_MAIN); - - color.full = persistentData->options[1].value.unsignedValue; - lv_obj_set_style_bg_color(batteryFill, color, LV_PART_MAIN | LV_STATE_USER_1); - - color.full = persistentData->options[0].value.unsignedValue; - lv_obj_set_style_bg_color(batteryFill, color, LV_PART_MAIN | LV_STATE_USER_2); + etx_bg_color_from_flags(batteryFill, persistentData->options[2].value.unsignedValue, LV_PART_MAIN); + etx_bg_color_from_flags(batteryFill, persistentData->options[1].value.unsignedValue, LV_STATE_USER_1); + etx_bg_color_from_flags(batteryFill, persistentData->options[0].value.unsignedValue, LV_STATE_USER_2); } void checkEvents() override @@ -230,9 +223,9 @@ class RadioInfoWidget : public TopBarWidget }; const ZoneOption RadioInfoWidget::options[] = { - {STR_LOW_BATT_COLOR, ZoneOption::Color, RGB(0xF4, 0x43, 0x36)}, - {STR_MID_BATT_COLOR, ZoneOption::Color, RGB(0xFF, 0xC1, 0x07)}, - {STR_HIGH_BATT_COLOR, ZoneOption::Color, RGB(0x4C, 0xAF, 0x50)}, + {STR_LOW_BATT_COLOR, ZoneOption::Color, RGB2FLAGS(0xF4, 0x43, 0x36)}, + {STR_MID_BATT_COLOR, ZoneOption::Color, RGB2FLAGS(0xFF, 0xC1, 0x07)}, + {STR_HIGH_BATT_COLOR, ZoneOption::Color, RGB2FLAGS(0x4C, 0xAF, 0x50)}, {nullptr, ZoneOption::Bool}}; BaseWidgetFactory RadioInfoWidget("Radio Info", RadioInfoWidget::options, @@ -252,9 +245,7 @@ class DateTimeWidget : public TopBarWidget void update() override { // get color from options - LcdFlags color = - COLOR2FLAGS(persistentData->options[0].value.unsignedValue); - dateTime->setColor(color); + dateTime->setColor(persistentData->options[0].value.unsignedValue); } HeaderDateTime* dateTime = nullptr; @@ -268,8 +259,7 @@ class DateTimeWidget : public TopBarWidget }; const ZoneOption DateTimeWidget::options[] = { - {STR_COLOR, ZoneOption::Color, - OPTION_VALUE_UNSIGNED(COLOR_THEME_PRIMARY2 >> 16)}, + {STR_COLOR, ZoneOption::Color, COLOR2FLAGS(COLOR_THEME_PRIMARY2_INDEX)}, {nullptr, ZoneOption::Bool}}; BaseWidgetFactory DateTimeWidget("Date Time", diff --git a/radio/src/gui/colorlcd/widgets/text.cpp b/radio/src/gui/colorlcd/widgets/text.cpp index 7aeade541..8d239b4c9 100644 --- a/radio/src/gui/colorlcd/widgets/text.cpp +++ b/radio/src/gui/colorlcd/widgets/text.cpp @@ -61,9 +61,7 @@ class TextWidget : public Widget lv_label_set_text(label, persistentData->options[0].value.stringValue); // get font color from options[1] - lv_color_t color; - color.full = persistentData->options[1].value.unsignedValue; - lv_style_set_text_color(&style, color); + etx_txt_color_from_flags(label, persistentData->options[1].value.unsignedValue); // get font size from options[2] lv_style_set_text_font( &style, getFont(persistentData->options[2].value.unsignedValue << 8)); @@ -85,8 +83,7 @@ class TextWidget : public Widget const ZoneOption TextWidget::options[] = { {STR_TEXT, ZoneOption::String, OPTION_VALUE_STRING(TEXT_WIDGET_DEFAULT_LABEL)}, - {STR_COLOR, ZoneOption::Color, - OPTION_VALUE_UNSIGNED(COLOR_THEME_SECONDARY1 >> 16)}, + {STR_COLOR, ZoneOption::Color, COLOR2FLAGS(COLOR_THEME_SECONDARY1_INDEX)}, {STR_SIZE, ZoneOption::TextSize, OPTION_VALUE_UNSIGNED(0)}, {STR_SHADOW, ZoneOption::Bool, OPTION_VALUE_BOOL(false)}, {STR_ALIGNMENT, ZoneOption::Align, OPTION_VALUE_UNSIGNED(ALIGN_LEFT)}, diff --git a/radio/src/gui/colorlcd/widgets/timer.cpp b/radio/src/gui/colorlcd/widgets/timer.cpp index 78303930f..07afe9509 100644 --- a/radio/src/gui/colorlcd/widgets/timer.cpp +++ b/radio/src/gui/colorlcd/widgets/timer.cpp @@ -92,7 +92,7 @@ class TimerWidget : public Widget lv_obj_set_style_arc_width(timerArc, TMR_ARC_W, LV_PART_MAIN); lv_obj_set_style_arc_opa(timerArc, LV_OPA_COVER, LV_PART_INDICATOR); lv_obj_set_style_arc_width(timerArc, TMR_ARC_W, LV_PART_INDICATOR); - etx_obj_add_style(timerArc, styles->arc_color, LV_PART_INDICATOR); + etx_obj_add_style(timerArc, styles->arc_color[COLOR_THEME_SECONDARY1_INDEX], LV_PART_INDICATOR); lv_obj_add_flag(timerArc, LV_OBJ_FLAG_HIDDEN); update(); diff --git a/radio/src/gui/colorlcd/widgets/value.cpp b/radio/src/gui/colorlcd/widgets/value.cpp index b2d2b66b5..351fec123 100644 --- a/radio/src/gui/colorlcd/widgets/value.cpp +++ b/radio/src/gui/colorlcd/widgets/value.cpp @@ -168,10 +168,8 @@ class ValueWidget : public Widget mixsrc_t field = persistentData->options[0].value.unsignedValue; // get color from options[1] - lv_color_t color; - color.full = persistentData->options[1].value.unsignedValue; - lv_style_set_text_color(&labelStyle, color); - lv_style_set_text_color(&valueStyle, color); + etx_txt_color_from_flags(label, persistentData->options[1].value.unsignedValue); + etx_txt_color_from_flags(value, persistentData->options[1].value.unsignedValue); // get label alignment from options[3] LcdFlags lblAlign = persistentData->options[3].value.unsignedValue; @@ -260,8 +258,7 @@ class ValueWidget : public Widget const ZoneOption ValueWidget::options[] = { {STR_SOURCE, ZoneOption::Source, OPTION_VALUE_UNSIGNED(MIXSRC_FIRST_STICK)}, - {STR_COLOR, ZoneOption::Color, - OPTION_VALUE_UNSIGNED(COLOR_THEME_PRIMARY2 >> 16)}, + {STR_COLOR, ZoneOption::Color, COLOR2FLAGS(COLOR_THEME_PRIMARY2_INDEX)}, {STR_SHADOW, ZoneOption::Bool, OPTION_VALUE_BOOL(false)}, {STR_ALIGN_LABEL, ZoneOption::Align, OPTION_VALUE_UNSIGNED(ALIGN_LEFT)}, {STR_ALIGN_VALUE, ZoneOption::Align, OPTION_VALUE_UNSIGNED(ALIGN_LEFT)}, diff --git a/radio/src/gui/colorlcd/widgets_setup.cpp b/radio/src/gui/colorlcd/widgets_setup.cpp index 54fbce00f..84c4b2608 100644 --- a/radio/src/gui/colorlcd/widgets_setup.cpp +++ b/radio/src/gui/colorlcd/widgets_setup.cpp @@ -54,7 +54,7 @@ SetupWidgetsPageSlot::SetupWidgetsPageSlot(Window* parent, const rect_t& rect, }); etx_obj_add_style(lvobj, styles->border, LV_STATE_FOCUSED); - etx_obj_add_style(lvobj, styles->border_color_focus, LV_STATE_FOCUSED); + etx_obj_add_style(lvobj, styles->border_color[COLOR_THEME_FOCUS_INDEX], LV_STATE_FOCUSED); lv_style_init(&borderStyle); lv_style_set_line_width(&borderStyle, 2); diff --git a/radio/src/lua/api_colorlcd.cpp b/radio/src/lua/api_colorlcd.cpp index 3978450a1..4bc14de1f 100644 --- a/radio/src/lua/api_colorlcd.cpp +++ b/radio/src/lua/api_colorlcd.cpp @@ -66,16 +66,6 @@ static int8_t getTextVerticalOffset(LcdFlags flags) return text_vertical_offset[font_index] - vcenter; } -// Return flags with RGB color value instead of indexed theme color -LcdFlags flagsRGB(LcdFlags flags) -{ - // RGB or indexed color? - if (flags & RGB_FLAG) - return flags; - else - return (flags & 0xFFFF) | COLOR(COLOR_VAL(flags)) | RGB_FLAG; -} - /*luadoc @function lcd.refresh() @@ -107,7 +97,7 @@ static int luaLcdClear(lua_State * L) { if (luaLcdAllowed && luaLcdBuffer) { LcdFlags flags = luaL_optunsigned(L, 1, COLOR2FLAGS(COLOR_THEME_SECONDARY3_INDEX)); - flags = flagsRGB(flags); + flags = colorToRGB(flags); luaLcdBuffer->clear(flags); } return 0; @@ -154,7 +144,7 @@ static int luaLcdDrawPoint(lua_State *L) int x = luaL_checkinteger(L, 1); int y = luaL_checkinteger(L, 2); LcdFlags flags = luaL_optunsigned(L, 3, 0); - flags = flagsRGB(flags); + flags = colorToRGB(flags); // drawPixel uses color value directly; hence COLOR_VAL again luaLcdBuffer->drawPixel(x, y, COLOR_VAL(flags)); @@ -191,7 +181,7 @@ static int luaLcdDrawLine(lua_State *L) coord_t y2 = luaL_checkunsigned(L, 4); uint8_t pat = luaL_checkunsigned(L, 5); LcdFlags flags = luaL_optunsigned(L, 6, 0); - flags = flagsRGB(flags); + flags = colorToRGB(flags); if (x1 > LCD_W || y1 > LCD_H || x2 > LCD_W || y2 > LCD_H) return 0; @@ -230,13 +220,13 @@ static void drawString(lua_State *L, const char * s, LcdFlags flags) if (invers) { // Find inverse color or read from optional Lua argument - LcdFlags color = flagsRGB(flags); + LcdFlags color = colorToRGB(flags); LcdFlags invColor = luaL_optunsigned(L, 5, ~0u); // ~0 is impossible for color flag! if (invColor == ~0u) { RGB_SPLIT(COLOR_VAL(color), r, g, b); invColor = COLOR2FLAGS(RGB_JOIN(31 - r, 63 - g, 31 - b)); } else - invColor = flagsRGB(invColor); + invColor = colorToRGB(invColor); flags = (flags & 0xFFFF) | invColor; // Draw color box @@ -254,7 +244,7 @@ static void drawString(lua_State *L, const char * s, LcdFlags flags) return; if (flags & SHADOWED) luaLcdBuffer->drawText(x+1, y+1, s, flags & 0xFFFF); // force black - flags = (flags & 0xFFFF) | flagsRGB(flags); + flags = (flags & 0xFFFF) | colorToRGB(flags); } luaLcdBuffer->drawText(x, y, s, flags); @@ -338,13 +328,13 @@ static int luaLcdDrawTextLines(lua_State *L) if (invers) { // Find inverse color or read from optional Lua argument - LcdFlags color = flagsRGB(flags); + LcdFlags color = colorToRGB(flags); LcdFlags invColor = luaL_optunsigned(L, 7, ~0u); // ~0 is impossible for color flag! if (invColor == ~0u) { RGB_SPLIT(COLOR_VAL(color), r, g, b); invColor = COLOR2FLAGS(RGB_JOIN(31 - r, 63 - g, 31 - b)); } else - invColor = flagsRGB(invColor); + invColor = colorToRGB(invColor); flags = (flags & 0xFFFF) | invColor; // Draw color box @@ -354,7 +344,7 @@ static int luaLcdDrawTextLines(lua_State *L) return 0; if (flags & SHADOWED) luaLcdBuffer->drawTextLines(x+1, y+1, w, h, s, flags & 0xFFFF); // force black - flags = (flags & 0xFFFF) | flagsRGB(flags); + flags = (flags & 0xFFFF) | colorToRGB(flags); } luaLcdBuffer->drawTextLines(x, y, w, h, s, flags); @@ -447,7 +437,7 @@ static int luaLcdDrawChannel(lua_State *L) } } LcdFlags flags = luaL_optunsigned(L, 4, 0); - flags = flagsRGB(flags); + flags = colorToRGB(flags); getvalue_t value = getValue(channel); luaLcdBuffer->drawSensorCustomValue(x, y, (channel-MIXSRC_FIRST_TELEM)/3, value, flags); @@ -477,7 +467,7 @@ static int luaLcdDrawSwitch(lua_State *L) int y = luaL_checkinteger(L, 2); int s = luaL_checkinteger(L, 3); LcdFlags flags = luaL_optunsigned(L, 4, 0); - flags = flagsRGB(flags); + flags = colorToRGB(flags); luaLcdBuffer->drawSwitch(x, y, s, flags); return 0; @@ -505,7 +495,7 @@ static int luaLcdDrawSource(lua_State *L) int y = luaL_checkinteger(L, 2); int s = luaL_checkinteger(L, 3); LcdFlags flags = luaL_optunsigned(L, 4, 0); - flags = flagsRGB(flags); + flags = colorToRGB(flags); luaLcdBuffer->drawSource(x, y, s, flags); return 0; @@ -759,7 +749,7 @@ static int luaLcdDrawBitmapPattern(lua_State *L) auto x = luaL_checkunsigned(L, 2); auto y = luaL_checkunsigned(L, 3); auto flags = luaL_optunsigned(L, 4, 0); - flags = flagsRGB(flags); + flags = colorToRGB(flags); luaLcdBuffer->drawBitmapPattern(x, y, reinterpret_cast(m), flags); } @@ -798,7 +788,7 @@ static int luaLcdDrawBitmapPatternPie(lua_State *L) auto startAngle = luaL_checkinteger(L, 4); auto endAngle = luaL_checkinteger(L, 5); auto flags = luaL_optunsigned(L, 6, 0); - flags = flagsRGB(flags); + flags = colorToRGB(flags); luaLcdBuffer->drawBitmapPatternPie(x, y, reinterpret_cast(m), flags, startAngle, endAngle); } @@ -834,7 +824,7 @@ static int luaLcdDrawRectangle(lua_State *L) int h = luaL_checkinteger(L, 4); LcdFlags flags = luaL_optunsigned(L, 5, 0); - flags = flagsRGB(flags); + flags = colorToRGB(flags); unsigned int t = luaL_optunsigned(L, 6, 1); uint8_t opacity = luaL_optunsigned(L, 7, 0) & 0x0F; @@ -871,7 +861,7 @@ static int luaLcdDrawFilledRectangle(lua_State *L) int h = luaL_checkinteger(L, 4); LcdFlags flags = luaL_optunsigned(L, 5, 0); - flags = flagsRGB(flags); + flags = colorToRGB(flags); uint8_t opacity = luaL_optunsigned(L, 6, 0) & 0x0F; luaLcdBuffer->drawFilledRect(x, y, w, h, SOLID, flags, opacity); @@ -906,7 +896,7 @@ static int luaLcdInvertRect(lua_State *L) int h = luaL_checkinteger(L, 4); LcdFlags flags = luaL_optunsigned(L, 5, 0); - flags = flagsRGB(flags); + flags = colorToRGB(flags); luaLcdBuffer->invertRect(x, y, w, h, flags); @@ -944,7 +934,7 @@ static int luaLcdDrawGauge(lua_State *L) int num = luaL_checkinteger(L, 5); int den = luaL_checkinteger(L, 6); LcdFlags flags = luaL_optunsigned(L, 7, 0); - flags = flagsRGB(flags); + flags = colorToRGB(flags); luaLcdBuffer->drawRect(x, y, w, h, 1, 0xff, flags); uint16_t len = limit((uint16_t)1, uint16_t(w*num/den), uint16_t(w)); @@ -967,7 +957,7 @@ Please notice that changing theme colors affects not only other Lua widgets, but static int luaLcdSetColor(lua_State *L) { unsigned int index = COLOR_VAL(luaL_checkunsigned(L, 1)); - uint16_t color = COLOR_VAL(flagsRGB(luaL_checkunsigned(L, 2))); + uint16_t color = COLOR_VAL(colorToRGB(luaL_checkunsigned(L, 2))); if (index < LCD_COLOR_COUNT && lcdColorTable[index] != color) { lcdColorTable[index] = color; @@ -994,7 +984,7 @@ static int luaLcdGetColor(lua_State *L) { LcdFlags flags = luaL_checkunsigned(L, 1); if ((flags & RGB_FLAG) || (COLOR_VAL(flags) & 0xFF) < LCD_COLOR_COUNT) - lua_pushunsigned(L, flagsRGB(flags) & (COLOR_MASK(~0u) | RGB_FLAG)); + lua_pushunsigned(L, colorToRGB(flags) & (COLOR_MASK(~0u) | RGB_FLAG)); else lua_pushnil(L); return 1; @@ -1058,7 +1048,7 @@ static int luaLcdDrawCircle(lua_State *L) coord_t y = luaL_checkunsigned(L, 2); coord_t r = luaL_checkunsigned(L, 3); LcdFlags flags = luaL_optunsigned(L, 4, 0); - flags = flagsRGB(flags); + flags = colorToRGB(flags); luaLcdBuffer->drawCircle(x, y, r, flags); @@ -1087,7 +1077,7 @@ static int luaLcdDrawFilledCircle(lua_State *L) coord_t y = luaL_checkunsigned(L, 2); coord_t r = luaL_checkunsigned(L, 3); LcdFlags flags = luaL_optunsigned(L, 4, 0); - flags = flagsRGB(flags); + flags = colorToRGB(flags); luaLcdBuffer->drawFilledCircle(x, y, r, flags); @@ -1117,7 +1107,7 @@ static int luaLcdDrawTriangle(lua_State *L) coord_t x3 = luaL_checkunsigned(L, 5); coord_t y3 = luaL_checkunsigned(L, 6); LcdFlags flags = luaL_optunsigned(L, 7, 0); - flags = flagsRGB(flags); + flags = colorToRGB(flags); luaLcdBuffer->drawLine(x1, y1, x2, y2, SOLID, flags); luaLcdBuffer->drawLine(x2, y2, x3, y3, SOLID, flags); @@ -1149,7 +1139,7 @@ static int luaLcdDrawFilledTriangle(lua_State *L) coord_t x3 = luaL_checkunsigned(L, 5); coord_t y3 = luaL_checkunsigned(L, 6); LcdFlags flags = luaL_optunsigned(L, 7, 0); - flags = flagsRGB(flags); + flags = colorToRGB(flags); luaLcdBuffer->drawFilledTriangle(x1, y1, x2, y2, x3, y3, flags); @@ -1182,7 +1172,7 @@ static int luaLcdDrawArc(lua_State *L) int start = luaL_checkunsigned(L, 4); int end = luaL_checkunsigned(L, 5); LcdFlags flags = luaL_optunsigned(L, 6, 0); - flags = flagsRGB(flags); + flags = colorToRGB(flags); if (r > 0) luaLcdBuffer->drawAnnulusSector(x, y, r - 1, r, start, end, flags); @@ -1216,7 +1206,7 @@ static int luaLcdDrawPie(lua_State *L) int start = luaL_checkunsigned(L, 4); int end = luaL_checkunsigned(L, 5); LcdFlags flags = luaL_optunsigned(L, 6, 0); - flags = flagsRGB(flags); + flags = colorToRGB(flags); if (r > 0) luaLcdBuffer->drawAnnulusSector(x, y, 0, r, start, end, flags); @@ -1251,7 +1241,7 @@ static int luaLcdDrawAnnulus(lua_State *L) int start = luaL_checkunsigned(L, 5); int end = luaL_checkunsigned(L, 6); LcdFlags flags = luaL_optunsigned(L, 7, 0); - flags = flagsRGB(flags); + flags = colorToRGB(flags); luaLcdBuffer->drawAnnulusSector(x, y, r1, r2, start, end, flags); @@ -1288,7 +1278,7 @@ static int luaLcdDrawLineWithClipping(lua_State *L) coord_t ymax = luaL_checkunsigned(L, 8); uint8_t pat = luaL_checkunsigned(L, 9); LcdFlags flags = luaL_optunsigned(L, 10, 0); - flags = flagsRGB(flags); + flags = colorToRGB(flags); // backup clipping rect coord_t dc_xmin; coord_t dc_xmax; coord_t dc_ymin; coord_t dc_ymax; @@ -1393,7 +1383,7 @@ static int luaLcdDrawHudRectangle(lua_State *L) coord_t ymin = luaL_checkunsigned(L, 5); coord_t ymax = luaL_checkunsigned(L, 6); LcdFlags flags = luaL_optunsigned(L, 7, 0); - flags = flagsRGB(flags); + flags = colorToRGB(flags); drawHudRectangle(luaLcdBuffer, pitch, roll, xmin, xmax, ymin, ymax, flags); diff --git a/radio/src/lua/api_colorlcd_lvgl.cpp b/radio/src/lua/api_colorlcd_lvgl.cpp index b12c3c4f4..4c14d4b7d 100644 --- a/radio/src/lua/api_colorlcd_lvgl.cpp +++ b/radio/src/lua/api_colorlcd_lvgl.cpp @@ -69,6 +69,11 @@ static int luaLvglImage(lua_State *L) return luaLvglObj(L, [=]() { return new LvglWidgetImage(); }); } +static int luaLvglQRCode(lua_State *L) +{ + return luaLvglObj(L, [=]() { return new LvglWidgetQRCode(); }); +} + static int luaLvglMeter(lua_State *L) { return luaLvglObj(L, [=]() { return new LvglWidgetMeter(); }); @@ -217,6 +222,8 @@ static void buildLvgl(lua_State *L, int srcIndex, int refIndex) lvobj = new LvglWidgetArc(); else if (strcasecmp(p.type, "image") == 0) lvobj = new LvglWidgetImage(); + else if (strcasecmp(p.type, "qrcode") == 0) + lvobj = new LvglWidgetQRCode(); else if (strcasecmp(p.type, "meter") == 0) lvobj = new LvglWidgetMeter(); else if (!luaLvglManager->isWidget()) { @@ -232,6 +239,8 @@ static void buildLvgl(lua_State *L, int srcIndex, int refIndex) lvobj = new LvglWidgetChoice(); else if (strcasecmp(p.type, "slider") == 0) lvobj = new LvglWidgetSlider(); + else if (strcasecmp(p.type, "page") == 0) + lvobj = new LvglWidgetPage(); } if (lvobj) { lvobj->getParams(L, -1); @@ -278,6 +287,7 @@ LROT_FUNCENTRY(rectangle, luaLvglRectangle) LROT_FUNCENTRY(circle, luaLvglCircle) LROT_FUNCENTRY(arc, luaLvglArc) LROT_FUNCENTRY(image, luaLvglImage) +LROT_FUNCENTRY(qrcode, luaLvglQRCode) LROT_FUNCENTRY(meter, luaLvglMeter) LROT_FUNCENTRY(button, luaLvglButton) LROT_FUNCENTRY(toggle, luaLvglToggle) diff --git a/radio/src/lua/interface.cpp b/radio/src/lua/interface.cpp index 7236cb983..e3fa2db94 100644 --- a/radio/src/lua/interface.cpp +++ b/radio/src/lua/interface.cpp @@ -897,7 +897,7 @@ static void luaLoadScripts(bool init, const char * filename = nullptr) StandaloneLuaWindow::setup(true); #endif luaError(lsScripts, sid.state); - continue; + break; } } // Skip the rest of the loop if we did not get a new script diff --git a/radio/src/lua/lua_api.h b/radio/src/lua/lua_api.h index a8f343a72..40e75e7ec 100644 --- a/radio/src/lua/lua_api.h +++ b/radio/src/lua/lua_api.h @@ -71,8 +71,6 @@ extern LuaWidget* runningFS; class LuaLvglManager; extern LuaLvglManager* luaLvglManager; -LcdFlags flagsRGB(LcdFlags flags); - extern lua_State* lsWidgets; extern uint32_t luaExtraMemoryUsage; void luaInitThemesAndWidgets(); diff --git a/radio/src/lua/lua_lvgl_widget.cpp b/radio/src/lua/lua_lvgl_widget.cpp index 86aecaf92..d3601de24 100644 --- a/radio/src/lua/lua_lvgl_widget.cpp +++ b/radio/src/lua/lua_lvgl_widget.cpp @@ -21,8 +21,10 @@ #include "lua_widget.h" #include "opentx.h" +#include "page.h" #include "slider.h" #include "toggleswitch.h" +#include "lua_event.h" //----------------------------------------------------------------------------- @@ -200,7 +202,6 @@ void LvglWidgetObject::parseParam(lua_State *L, const char *key) getColorFunction = luaL_ref(L, LUA_REGISTRYINDEX); } else { color = luaL_checkunsigned(L, -1); - color = flagsRGB(color); } } else if (!strcmp(key, "visible")) { getVisibleFunction = luaL_ref(L, LUA_REGISTRYINDEX); @@ -278,12 +279,17 @@ void LvglWidgetBorderedObject::setColor(LcdFlags color) { if (color != currentColor) { currentColor = color; - if (filled) - lv_obj_set_style_bg_color(window->getLvObj(), - makeLvColor(flagsRGB(color)), LV_PART_MAIN); - else - lv_obj_set_style_border_color(window->getLvObj(), - makeLvColor(flagsRGB(color)), LV_PART_MAIN); + if (filled) { + etx_bg_color_from_flags(window->getLvObj(), color); + } else { + if (color & RGB_FLAG) { + etx_remove_border_color(window->getLvObj()); + lv_obj_set_style_border_color(window->getLvObj(), + makeLvColor(colorToRGB(color)), LV_PART_MAIN); + } else { + etx_border_color(window->getLvObj(), (LcdColorIndex)COLOR_VAL(color)); + } + } } } @@ -407,8 +413,13 @@ void LvglWidgetLabel::setColor(LcdFlags color) { if (color != currentColor) { currentColor = color; - lv_obj_set_style_text_color(window->getLvObj(), - makeLvColor(flagsRGB(color)), LV_PART_MAIN); + if (color & RGB_FLAG) { + etx_remove_txt_color(window->getLvObj()); + lv_obj_set_style_text_color(window->getLvObj(), + makeLvColor(colorToRGB(color)), LV_PART_MAIN); + } else { + etx_txt_color(window->getLvObj(), (LcdColorIndex)COLOR_VAL(color)); + } } } @@ -488,8 +499,13 @@ void LvglWidgetArc::setColor(LcdFlags color) { if (color != currentColor) { currentColor = color; - lv_obj_set_style_arc_color(window->getLvObj(), makeLvColor(flagsRGB(color)), - LV_PART_INDICATOR); + if (color & RGB_FLAG) { + etx_remove_arc_color(window->getLvObj()); + lv_obj_set_style_arc_color(window->getLvObj(), makeLvColor(colorToRGB(color)), + LV_PART_INDICATOR); + } else { + etx_arc_color(window->getLvObj(), (LcdColorIndex)COLOR_VAL(color), LV_PART_INDICATOR); + } } } @@ -565,6 +581,24 @@ void LvglWidgetImage::build(lua_State *L) //----------------------------------------------------------------------------- +void LvglWidgetQRCode::parseParam(lua_State *L, const char *key) +{ + if (!strcmp(key, "data")) { + data = luaL_checkstring(L, -1); + } else if (!strcmp(key, "bgColor")) { + bgColor = luaL_checkunsigned(L, -1); + } else { + LvglWidgetObject::parseParam(L, key); + } +} + +void LvglWidgetQRCode::build(lua_State *L) +{ + window = new QRCode(lvglManager->getCurrentParent(), x, y, w, data, colorToRGB(color), colorToRGB(bgColor)); +} + +//----------------------------------------------------------------------------- + class LvglWidgetScaleIndicator : public LvglWidgetObjectBase { public: @@ -606,7 +640,7 @@ class LvglWidgetScaleArc : public LvglWidgetScaleIndicator meter = parent; indic = - lv_meter_add_arc(meter, scale, w, makeLvColor(flagsRGB(color)), rmod); + lv_meter_add_arc(meter, scale, w, makeLvColor(colorToRGB(color)), rmod); if (hasStart) lv_meter_set_indicator_start_value(meter, indic, startPos); if (hasEnd) lv_meter_set_indicator_end_value(meter, indic, endPos); } @@ -614,7 +648,7 @@ class LvglWidgetScaleArc : public LvglWidgetScaleIndicator protected: uint8_t w = 0; int8_t rmod = 0; - LcdFlags color = COLOR_THEME_PRIMARY1; + LcdFlags color = COLOR2FLAGS(COLOR_THEME_PRIMARY1_INDEX); bool hasStart = false, hasEnd = false; int16_t startPos = 0, endPos = 0; @@ -676,15 +710,16 @@ class LvglWidgetScaleLines : public LvglWidgetScaleIndicator meter = parent; indic = lv_meter_add_scale_lines( - meter, scale, makeLvColor(flagsRGB(startColor)), - makeLvColor(flagsRGB(endColor)), localFade, wmod); + meter, scale, makeLvColor(colorToRGB(startColor)), + makeLvColor(colorToRGB(endColor)), localFade, wmod); if (hasStart) lv_meter_set_indicator_start_value(meter, indic, startPos); if (hasEnd) lv_meter_set_indicator_end_value(meter, indic, endPos); } protected: int8_t wmod = 0; - LcdFlags startColor = COLOR_THEME_PRIMARY1, endColor = COLOR_THEME_PRIMARY1; + LcdFlags startColor = COLOR2FLAGS(COLOR_THEME_PRIMARY1_INDEX); + LcdFlags endColor = COLOR2FLAGS(COLOR_THEME_PRIMARY1_INDEX); bool hasStart = false, hasEnd = false; int16_t startPos = 0, endPos = 0; bool localFade = false; @@ -741,13 +776,13 @@ class LvglWidgetScaleNeedle : public LvglWidgetScaleIndicator meter = parent; indic = lv_meter_add_needle_line(meter, scale, w, - makeLvColor(flagsRGB(color)), rmod); + makeLvColor(colorToRGB(color)), rmod); } protected: uint8_t w = 0; int8_t rmod = 0; - LcdFlags color = COLOR_THEME_PRIMARY1; + LcdFlags color = COLOR2FLAGS(COLOR_THEME_PRIMARY1_INDEX); int getPosFunction = 0; @@ -792,11 +827,11 @@ class LvglWidgetMeterScale : public LvglWidgetObjectBase if (ticks) { lv_meter_set_scale_ticks(meter, scale, ticks, tickWidth, tickLen, - makeLvColor(flagsRGB(tickColor))); + makeLvColor(colorToRGB(tickColor))); if (majorNth) lv_meter_set_scale_major_ticks( meter, scale, majorNth, majorWidth, majorLen, - makeLvColor(flagsRGB(majorColor)), labelGap); + makeLvColor(colorToRGB(majorColor)), labelGap); } lv_meter_set_scale_range(meter, scale, scaleMin, scaleMax, scaleAngle, @@ -804,8 +839,7 @@ class LvglWidgetMeterScale : public LvglWidgetObjectBase if (centerDotSize > 0) { lv_obj_set_style_size(meter, centerDotSize, LV_PART_INDICATOR); - lv_obj_set_style_bg_color(meter, makeLvColor(flagsRGB(centerDotColor)), - LV_PART_INDICATOR); + etx_bg_color_from_flags(meter, centerDotColor, LV_PART_INDICATOR); lv_obj_set_style_bg_opa(meter, LV_OPA_COVER, LV_PART_INDICATOR); lv_obj_set_style_radius(meter, LV_RADIUS_CIRCLE, LV_PART_INDICATOR); } @@ -823,9 +857,10 @@ class LvglWidgetMeterScale : public LvglWidgetObjectBase uint8_t ticks = 0, majorNth = 0; uint8_t tickWidth = 0, majorWidth = 0; uint8_t tickLen = 0, majorLen = 0; - LcdFlags tickColor = COLOR_THEME_PRIMARY1, majorColor = COLOR_THEME_PRIMARY1; + LcdFlags tickColor = COLOR2FLAGS(COLOR_THEME_PRIMARY1); + LcdFlags majorColor = COLOR2FLAGS(COLOR_THEME_PRIMARY1); uint8_t labelGap = 0, centerDotSize = 0; - LcdFlags centerDotColor = COLOR_THEME_PRIMARY1; + LcdFlags centerDotColor = COLOR2FLAGS(COLOR_THEME_PRIMARY1_INDEX); void parseParam(lua_State *L, const char *key) override { @@ -952,6 +987,7 @@ void LvglWidgetTextButton::setText(const char *s) void LvglWidgetTextButton::build(lua_State *L) { + if (h == LV_SIZE_CONTENT) h = 0; window = new TextButton(lvglManager->getCurrentParent(), {x, y, w, h}, txt, [=]() { pcallSimpleFunc(L, pressFunction); @@ -1158,6 +1194,7 @@ void LvglWidgetChoice::clearRefs(lua_State *L) void LvglWidgetChoice::build(lua_State *L) { + if (h == LV_SIZE_CONTENT) h = 0; window = new Choice( lvglManager->getCurrentParent(), {x, y, w, h}, values, 0, values.size() - 1, [=]() { return pcallGetIntVal(L, getFunction) - 1; }, @@ -1198,3 +1235,86 @@ void LvglWidgetSlider::build(lua_State *L) } //----------------------------------------------------------------------------- + +class WidgetPage : public NavWindow, public LuaEventHandler +{ + public: + WidgetPage(Window *parent, std::function backAction, + std::string title, std::string subtitle, std::string iconFile) : + NavWindow(parent, {0, 0, LCD_W, LCD_H}), backAction(std::move(backAction)) + { + if (iconFile.empty()) + header = new PageHeader(this, ICON_EDGETX); + else + header = new PageHeader(this, iconFile.c_str()); + + body = new Window( + this, {0, EdgeTxStyles::MENU_HEADER_HEIGHT, LCD_W, LCD_H - EdgeTxStyles::MENU_HEADER_HEIGHT}); + body->setWindowFlag(NO_FOCUS); + + header->setTitle(title); + header->setTitle2(subtitle); + + etx_solid_bg(lvobj); + lv_obj_set_style_max_height(body->getLvObj(), LCD_H - EdgeTxStyles::MENU_HEADER_HEIGHT, + LV_PART_MAIN); + etx_scrollbar(body->getLvObj()); + + body->padAll(PAD_ZERO); + +#if defined(HARDWARE_TOUCH) + addBackButton(); +#endif + } + + Window *getBody() { return body; } + + protected: + std::function backAction; + PageHeader *header = nullptr; + Window *body = nullptr; + + bool bubbleEvents() override { return true; } + + void onClicked() override { Keyboard::hide(false); LuaEventHandler::onClicked(); } + + void onCancel() override { backAction(); } + + void onEvent(event_t evt) override + { + LuaEventHandler::onEvent(evt); + } + + protected: +}; + +void LvglWidgetPage::parseParam(lua_State *L, const char *key) +{ + if (!strcmp(key, "back")) { + backActionFunction = luaL_ref(L, LUA_REGISTRYINDEX); + } else if (!strcmp(key, "title")) { + title = luaL_checkstring(L, -1); + } else if (!strcmp(key, "subtitle")) { + subtitle = luaL_checkstring(L, -1); + } else if (!strcmp(key, "icon")) { + iconFile = luaL_checkstring(L, -1); + } else { + LvglWidgetObject::parseParam(L, key); + } +} + +void LvglWidgetPage::clearRefs(lua_State *L) +{ + clearRef(L, backActionFunction); + LvglWidgetObject::clearRefs(L); +} + +void LvglWidgetPage::build(lua_State *L) +{ + auto page = new WidgetPage( + lvglManager->getCurrentParent(), + [=]() { pcallSimpleFunc(L, backActionFunction); }, title, subtitle, iconFile); + window = page->getBody(); +} + +//----------------------------------------------------------------------------- diff --git a/radio/src/lua/lua_lvgl_widget.h b/radio/src/lua/lua_lvgl_widget.h index b33087713..0a634a988 100644 --- a/radio/src/lua/lua_lvgl_widget.h +++ b/radio/src/lua/lua_lvgl_widget.h @@ -87,7 +87,7 @@ class LvglWidgetObject : public LvglWidgetObjectBase LcdFlags currentColor = -1; coord_t x = 0, y = 0, w = LV_SIZE_CONTENT, h = LV_SIZE_CONTENT; - LcdFlags color = COLOR_THEME_SECONDARY1; + LcdFlags color = COLOR2FLAGS(COLOR_THEME_SECONDARY1_INDEX); int getColorFunction = 0; int getVisibleFunction = 0; int getSizeFunction = 0; @@ -248,6 +248,22 @@ class LvglWidgetImage : public LvglWidgetObject //----------------------------------------------------------------------------- +class LvglWidgetQRCode : public LvglWidgetObject +{ + public: + LvglWidgetQRCode() : LvglWidgetObject() {} + + void build(lua_State *L) override; + + protected: + std::string data; + LcdFlags bgColor = COLOR2FLAGS(COLOR_THEME_SECONDARY3_INDEX); + + void parseParam(lua_State *L, const char *key) override; +}; + +//----------------------------------------------------------------------------- + class LvglWidgetMeterScale; class LvglWidgetMeter : public LvglWidgetRoundObject @@ -403,3 +419,22 @@ class LvglWidgetSlider : public LvglWidgetObject }; //----------------------------------------------------------------------------- + +class LvglWidgetPage : public LvglWidgetObject +{ + public: + LvglWidgetPage() : LvglWidgetObject() {} + + void build(lua_State *L) override; + void clearRefs(lua_State *L) override; + + protected: + int backActionFunction = 0; + std::string title; + std::string subtitle; + std::string iconFile; + + void parseParam(lua_State *L, const char *key) override; +}; + +//----------------------------------------------------------------------------- diff --git a/radio/src/lua/lua_widget.cpp b/radio/src/lua/lua_widget.cpp index b1e01c51a..ad7e1206c 100644 --- a/radio/src/lua/lua_widget.cpp +++ b/radio/src/lua/lua_widget.cpp @@ -330,8 +330,8 @@ void LuaWidget::update() lua_pushstring(lsWidgets, &str[0]); lua_settable(lsWidgets, -3); } else if (option->type == ZoneOption::Color) { - int32_t value = persistentData->options[i].value.signedValue; - l_pushtableint(option->name, COLOR2FLAGS(value) | RGB_FLAG); + int32_t value = persistentData->options[i].value.unsignedValue; + l_pushtableint(option->name, value); } else { int32_t value = persistentData->options[i].value.signedValue; l_pushtableint(option->name, value); diff --git a/radio/src/lua/lua_widget_factory.cpp b/radio/src/lua/lua_widget_factory.cpp index 4e7975ca2..a1163a543 100644 --- a/radio/src/lua/lua_widget_factory.cpp +++ b/radio/src/lua/lua_widget_factory.cpp @@ -96,8 +96,8 @@ Widget* LuaWidgetFactory::create(Window* parent, const rect_t& rect, lua_pushstring(lsWidgets, &str[0]); lua_settable(lsWidgets, -3); } else if (option->type == ZoneOption::Color) { - int32_t value = persistentData->options[i].value.signedValue; - l_pushtableint(option->name, COLOR2FLAGS(value) | RGB_FLAG); + int32_t value = persistentData->options[i].value.unsignedValue; + l_pushtableint(option->name, value); } else { int32_t value = persistentData->options[i].value.signedValue; l_pushtableint(option->name, value); diff --git a/radio/src/lua/widgets.cpp b/radio/src/lua/widgets.cpp index d5aab912e..f7746c89f 100644 --- a/radio/src/lua/widgets.cpp +++ b/radio/src/lua/widgets.cpp @@ -185,8 +185,7 @@ ZoneOption *createOptionsArray(int reference, uint8_t maxOptions) // TRACE("default unsigned = %u", option->deflt.unsignedValue); } else if (option->type == ZoneOption::Color) { luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number - option->deflt.unsignedValue = - COLOR_VAL(flagsRGB(lua_tounsigned(lsWidgets, -1))); + option->deflt.unsignedValue = lua_tounsigned(lsWidgets, -1); // TRACE("default unsigned = %u", option->deflt.unsignedValue); } else if (option->type == ZoneOption::Bool) { luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number diff --git a/radio/src/main.cpp b/radio/src/main.cpp index 7b73cb157..a7cdbae9b 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -191,8 +191,9 @@ void handleUsbConnection() #if defined(COLORLCD) usbConnectedWindow->deleteLater(); usbConnectedWindow = nullptr; -#endif +#else pushEvent(EVT_ENTRY); +#endif } else if (getSelectedUsbMode() == USB_SERIAL_MODE) { serialStop(SP_VCP); } diff --git a/radio/src/storage/storage_common.cpp b/radio/src/storage/storage_common.cpp index 39ae74b47..6e1ea7139 100644 --- a/radio/src/storage/storage_common.cpp +++ b/radio/src/storage/storage_common.cpp @@ -160,8 +160,6 @@ void postModelLoad(bool alarms) // Load 'date time' widget if slot is empty if (g_model.topbarData.zones[MAX_TOPBAR_ZONES-1].widgetName[0] == 0) { strAppend(g_model.topbarData.zones[MAX_TOPBAR_ZONES-1].widgetName, "Date Time", WIDGET_NAME_LEN); - g_model.topbarData.zones[MAX_TOPBAR_ZONES-1].widgetData.options[0].type = ZOV_Color; - g_model.topbarData.zones[MAX_TOPBAR_ZONES-1].widgetData.options[0].value.unsignedValue = 0xFFFFFF; storageDirty(EE_MODEL); } // Load 'radio info' widget if slot is empty diff --git a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp index 9bfeb6d9e..9f8c15fa0 100644 --- a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp @@ -541,33 +541,45 @@ bool w_zov_source(void* user, uint8_t* data, uint32_t bitoffs, void r_zov_color(void* user, uint8_t* data, uint32_t bitoffs, const char* val, uint8_t val_len) { - if (val_len < sizeof("0xFFFFFF")-1 - || val[0] != '0' - || val[1] != 'x') - return; - - val += 2; val_len -= 2; - data += bitoffs >> 3UL; auto p_val = reinterpret_cast(data); - auto rgb24 = yaml_hex2uint(val, val_len); - p_val->unsignedValue = - RGB((rgb24 & 0xFF0000) >> 16, (rgb24 & 0xFF00) >> 8, rgb24 & 0xFF); + if (strncmp(val, "COLIDX", 6) == 0) { + val += 6; val_len -= 6; + p_val->unsignedValue = COLOR2FLAGS(yaml_str2uint(val, val_len)); + } else { + if (val_len < sizeof("0xFFFFFF")-1 + || val[0] != '0' + || val[1] != 'x') + return; + + val += 2; val_len -= 2; + + auto rgb24 = yaml_hex2uint(val, val_len); + p_val->unsignedValue = + RGB2FLAGS((rgb24 & 0xFF0000) >> 16, (rgb24 & 0xFF00) >> 8, rgb24 & 0xFF); + } } bool w_zov_color(void* user, uint8_t* data, uint32_t bitoffs, yaml_writer_func wf, void* opaque) { data += bitoffs >> 3UL; - auto p_val = reinterpret_cast(data); + auto p_val = (reinterpret_cast(data))->unsignedValue; - uint32_t color = (uint32_t)GET_RED(p_val->unsignedValue) << 16 | - (uint32_t)GET_GREEN(p_val->unsignedValue) << 8 | - (uint32_t)GET_BLUE(p_val->unsignedValue); + if (p_val & RGB_FLAG) { + p_val = COLOR_VAL(p_val); + uint32_t color = (uint32_t)GET_RED(p_val) << 16 | + (uint32_t)GET_GREEN(p_val) << 8 | + (uint32_t)GET_BLUE(p_val); - if (!wf(opaque, "0x", 2)) return false; - return wf(opaque, yaml_rgb2hex(color), 3 * 2); + if (!wf(opaque, "0x", 2)) return false; + return wf(opaque, yaml_rgb2hex(color), 3 * 2); + } else { + if (!wf(opaque, "COLIDX", 6)) return false; + const char* str = yaml_unsigned2str(COLOR_VAL(p_val)); + return wf(opaque, str, strlen(str)); + } } #endif diff --git a/radio/src/thirdparty/libopenui/src/bitmapbuffer.h b/radio/src/thirdparty/libopenui/src/bitmapbuffer.h index 02182e962..ff3377234 100644 --- a/radio/src/thirdparty/libopenui/src/bitmapbuffer.h +++ b/radio/src/thirdparty/libopenui/src/bitmapbuffer.h @@ -142,7 +142,7 @@ class BitmapBuffer void resizeToLVGL(coord_t w, coord_t h); - uint8_t* to8bitMask(size_t* size) const; + MaskBitmap* to8bitMask(size_t* size) const; void drawBitmapPattern(coord_t x, coord_t y, const MaskBitmap* bmp, LcdFlags flags, coord_t offset = 0, coord_t width = 0); diff --git a/radio/src/thirdparty/libopenui/src/bitmapbuffer_draw_extra.cpp b/radio/src/thirdparty/libopenui/src/bitmapbuffer_draw_extra.cpp index dd390cb9f..f48a4891f 100644 --- a/radio/src/thirdparty/libopenui/src/bitmapbuffer_draw_extra.cpp +++ b/radio/src/thirdparty/libopenui/src/bitmapbuffer_draw_extra.cpp @@ -708,27 +708,29 @@ void BitmapBuffer::drawAnnulusSector(coord_t x, coord_t y, #endif } -uint8_t *BitmapBuffer::to8bitMask(size_t *size) const +MaskBitmap *BitmapBuffer::to8bitMask(size_t *size) const { + static uint8_t grayScale[16] = {255, 238, 221, 204, 187, 170, 153, 136, 119, 102, 85, 68, 51, 34, 17, 0}; + *size = width() * height() + 4; - uint8_t *mask = (uint8_t *)malloc(*size); - ((uint16_t *)mask)[0] = width(); - ((uint16_t *)mask)[1] = height(); + MaskBitmap *mask = (MaskBitmap*)malloc(*size); + mask->width = width(); + mask->height = height(); + const pixel_t *p = getPixelPtrAbs(0, 0); + int ofs = 0; if (getFormat() == BMP_ARGB4444) { - auto ofs = 4u; for (int i = width() * height(); i > 0; i--) { ARGB_SPLIT(*p, a __attribute__((unused)), r, g, b); - auto v = ((uint32_t)r + (uint32_t)g + (uint32_t)b) / 3; - mask[ofs++] = ((OPACITY_MAX - v) << 4); + int v = (r + g + b) / 3; + mask->data[ofs++] = grayScale[v]; MOVE_TO_NEXT_RIGHT_PIXEL(p); } } else { // BMP_RGB565 - auto ofs = 4u; for (int i = width() * height(); i > 0; i--) { - auto v = - ((GET_RED(*p) >> 1) + (GET_GREEN(*p) >> 2) + (GET_BLUE(*p) >> 1)) / 3; - mask[ofs++] = ((OPACITY_MAX - v) << 4); + RGB_SPLIT(*p, r, g, b); + int v = ((r + (g >> 1) + b) / 3) >> 1; + mask->data[ofs++] = grayScale[v]; MOVE_TO_NEXT_RIGHT_PIXEL(p); } } diff --git a/radio/src/thirdparty/libopenui/src/button_matrix.cpp b/radio/src/thirdparty/libopenui/src/button_matrix.cpp index 4860a85dc..ea1687619 100644 --- a/radio/src/thirdparty/libopenui/src/button_matrix.cpp +++ b/radio/src/thirdparty/libopenui/src/button_matrix.cpp @@ -32,7 +32,7 @@ static void btnmatrix_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj) etx_std_style(obj, LV_PART_ITEMS, PAD_LARGE); - etx_obj_add_style(obj, styles->border_color_focus, + etx_obj_add_style(obj, styles->border_color[COLOR_THEME_FOCUS_INDEX], LV_PART_ITEMS | LV_STATE_EDITED); } diff --git a/radio/src/thirdparty/libopenui/src/libopenui_defines.h b/radio/src/thirdparty/libopenui/src/libopenui_defines.h index f1289d0ff..e5cad30c5 100644 --- a/radio/src/thirdparty/libopenui/src/libopenui_defines.h +++ b/radio/src/thirdparty/libopenui/src/libopenui_defines.h @@ -20,9 +20,9 @@ #include "debug.h" #include "hal.h" +#include "opentx_types.h" #include "colors.h" #include "keys.h" -#include "opentx_types.h" // Used by Lua API #define INVERS 0x01u diff --git a/radio/src/thirdparty/libopenui/src/slider.cpp b/radio/src/thirdparty/libopenui/src/slider.cpp index 1c8cdf201..5fb13945a 100644 --- a/radio/src/thirdparty/libopenui/src/slider.cpp +++ b/radio/src/thirdparty/libopenui/src/slider.cpp @@ -45,8 +45,8 @@ static void slider_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj) etx_obj_add_style(obj, styles->bg_opacity_cover, LV_PART_KNOB); etx_obj_add_style(obj, slider_knob, LV_PART_KNOB); - etx_obj_add_style(obj, styles->border_color_dark, LV_PART_KNOB); - etx_obj_add_style(obj, styles->border_color_focus, + etx_obj_add_style(obj, styles->border_color[COLOR_THEME_SECONDARY1_INDEX], LV_PART_MAIN); + etx_obj_add_style(obj, styles->border_color[COLOR_THEME_FOCUS_INDEX], LV_PART_KNOB | LV_STATE_FOCUSED); } diff --git a/radio/src/thirdparty/libopenui/src/static.cpp b/radio/src/thirdparty/libopenui/src/static.cpp index 668ebf75d..f3c559b38 100644 --- a/radio/src/thirdparty/libopenui/src/static.cpp +++ b/radio/src/thirdparty/libopenui/src/static.cpp @@ -157,6 +157,37 @@ StaticIcon::StaticIcon(Window* parent, coord_t x, coord_t y, EdgeTxIcon icon, etx_img_color(lvobj, currentColor, LV_PART_MAIN); } +StaticIcon::StaticIcon(Window* parent, coord_t x, coord_t y, const char* filename, + LcdFlags color) : + Window(parent, rect_t{x, y, 0, 0}, lv_canvas_create), + currentColor(indexFromColor(color)) +{ + setWindowFlag(NO_FOCUS); + + lv_obj_clear_flag(lvobj, LV_OBJ_FLAG_CLICKABLE); + + auto bm = BitmapBuffer::loadBitmap(filename, BMP_RGB565); + if (bm) { + size_t size; + mask = bm->to8bitMask(&size); + if (mask) { + setSize(mask->width, mask->height); + lv_canvas_set_buffer(lvobj, (void*)mask->data, mask->width, mask->height, + LV_IMG_CF_ALPHA_8BIT); + } + delete bm; + } + + etx_img_color(lvobj, currentColor, LV_PART_MAIN); +} + +void StaticIcon::deleteLater(bool detach, bool trash) +{ + if (_deleted) return; + if (mask) free(mask); + mask = nullptr; +} + void StaticIcon::setColor(LcdColorIndex color) { if (currentColor != color) { @@ -325,3 +356,13 @@ void StaticLZ4Image::deleteLater(bool detach, bool trash) Window::deleteLater(detach, trash); } } + +//----------------------------------------------------------------------------- + +QRCode::QRCode(Window *parent, coord_t x, coord_t y, coord_t sz, std::string data, + LcdFlags color, LcdFlags bgColor) : + Window(parent, {x, y, sz, sz}) +{ + auto qr = lv_qrcode_create(lvobj, sz, makeLvColor(color), makeLvColor(bgColor)); + lv_qrcode_update(qr, data.c_str(), data.length()); +} diff --git a/radio/src/thirdparty/libopenui/src/static.h b/radio/src/thirdparty/libopenui/src/static.h index 3f764aa83..1ff63925e 100644 --- a/radio/src/thirdparty/libopenui/src/static.h +++ b/radio/src/thirdparty/libopenui/src/static.h @@ -123,6 +123,10 @@ class StaticIcon : public Window public: StaticIcon(Window *parent, coord_t x, coord_t y, EdgeTxIcon icon, LcdFlags color); + StaticIcon(Window *parent, coord_t x, coord_t y, const char* filename, + LcdFlags color); + + void deleteLater(bool detach = true, bool trash = true) override; #if defined(DEBUG_WINDOWS) std::string getName() const override { return "StaticIcon"; } @@ -134,6 +138,7 @@ class StaticIcon : public Window protected: LcdColorIndex currentColor; + MaskBitmap* mask = nullptr; }; //----------------------------------------------------------------------------- @@ -159,6 +164,8 @@ class StaticImage : public Window lv_obj_t *image = nullptr; }; +//----------------------------------------------------------------------------- + class StaticBitmap : public Window { public: @@ -178,6 +185,8 @@ class StaticBitmap : public Window BitmapBuffer *img = nullptr; }; +//----------------------------------------------------------------------------- + class StaticLZ4Image : public Window { public: @@ -193,3 +202,18 @@ class StaticLZ4Image : public Window void deleteLater(bool detach, bool trash) override; }; + +//----------------------------------------------------------------------------- + +class QRCode : public Window +{ + public: + QRCode(Window *parent, coord_t x, coord_t y, coord_t sz, std::string data, + LcdFlags color = COLOR_THEME_SECONDARY1, LcdFlags bgColor = COLOR_THEME_SECONDARY3); + +#if defined(DEBUG_WINDOWS) + std::string getName() const override { return "QRCode"; } +#endif + + protected: +}; diff --git a/radio/src/thirdparty/libopenui/src/table.cpp b/radio/src/thirdparty/libopenui/src/table.cpp index 25298f908..b9ce5f942 100644 --- a/radio/src/thirdparty/libopenui/src/table.cpp +++ b/radio/src/thirdparty/libopenui/src/table.cpp @@ -41,7 +41,7 @@ static void table_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj) etx_solid_bg(obj, COLOR_THEME_PRIMARY2_INDEX, LV_PART_ITEMS); etx_txt_color(obj, COLOR_THEME_PRIMARY1_INDEX, LV_PART_ITEMS); etx_obj_add_style(obj, table_cell, LV_PART_ITEMS); - etx_obj_add_style(obj, styles->border_color_normal, LV_PART_ITEMS); + etx_obj_add_style(obj, styles->border_color[COLOR_THEME_SECONDARY2_INDEX], LV_PART_ITEMS); etx_bg_color(obj, COLOR_THEME_FOCUS_INDEX, LV_PART_ITEMS | LV_STATE_EDITED); etx_txt_color(obj, COLOR_THEME_PRIMARY2_INDEX, LV_PART_ITEMS | LV_STATE_EDITED);