WIP Lua Theming- style classes

custom
ailurux 1 year ago
parent 20c2816a7b
commit 1133d46215
  1. 4
      lua/browser.lua
  2. 93
      lua/main.lua
  3. 127
      lua/theme_dark.lua
  4. 106
      lua/theme_light.lua
  5. 6
      lua/widgets.lua
  6. 25
      src/lua/lua_theme.cpp
  7. 2
      src/ui/include/themes.hpp
  8. 2
      src/ui/modal.cpp
  9. 5
      src/ui/screen_lua.cpp
  10. 64
      src/ui/themes.cpp

@ -6,6 +6,7 @@ local queue = require("queue")
local playing = require("playing") local playing = require("playing")
local styles = require("styles") local styles = require("styles")
local playback = require("playback") local playback = require("playback")
local theme = require("theme")
local browser = {} local browser = {}
@ -43,9 +44,10 @@ function browser.create(opts)
pad_right = 4, pad_right = 4,
pad_bottom = 2, pad_bottom = 2,
bg_opa = lvgl.OPA(100), bg_opa = lvgl.OPA(100),
bg_color = "#fafafa",
scrollbar_mode = lvgl.SCROLLBAR_MODE.OFF, scrollbar_mode = lvgl.SCROLLBAR_MODE.OFF,
} }
theme.set_style(header, "header")
header:Label { header:Label {
text = opts.breadcrumb, text = opts.breadcrumb,

@ -35,97 +35,8 @@ GLOBAL_BINDINGS = {
end), end),
} }
local lvgl = require("lvgl") local theme_light = require("theme_dark")
local my_theme = { theme.set(theme_light)
base = {
{lvgl.PART.MAIN, lvgl.Style {
bg_opa = lvgl.OPA(0),
text_font = font.fusion_12,
text_color = "#000000",
}},
{lvgl.STATE.FOCUSED, lvgl.Style {
bg_opa = lvgl.OPA(100),
bg_color = "#E3F2FD",
}},
},
button = {
{lvgl.PART.MAIN, lvgl.Style {
pad_left = 2,
pad_right = 2,
pad_top = 1,
pad_bottom = 1,
bg_color = "#ffffff",
radius = 5,
}},
},
bar = {
{lvgl.PART.MAIN, lvgl.Style {
bg_opa = lvgl.OPA(100),
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff
}},
},
slider = {
{lvgl.PART.MAIN, lvgl.Style {
bg_opa = lvgl.OPA(100),
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff
}},
{lvgl.PART.INDICATOR, lvgl.Style {
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff
bg_color = "#2196F3",
}},
{lvgl.PART.KNOB, lvgl.Style {
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff
pad_all = 2,
bg_color = "#ffffff",
shadow_width = 5,
shadow_opa = lvgl.OPA(100)
}},
{lvgl.STATE.FOCUSED, lvgl.Style {
bg_color = "#BBDEFB",
}},
},
switch = {
{lvgl.PART.MAIN, lvgl.Style {
bg_opa = lvgl.OPA(100),
width = 28,
height = 18,
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff
}},
{lvgl.PART.INDICATOR, lvgl.Style {
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff
bg_color = "#9E9E9E",
}},
{lvgl.PART.INDICATOR | lvgl.STATE.CHECKED, lvgl.Style {
bg_color = "#2196F3",
}},
{lvgl.PART.KNOB, lvgl.Style {
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff
pad_all = 2,
bg_opa = lvgl.OPA(100),
bg_color = "#ffffff",
}},
},
dropdown = {
{lvgl.PART.MAIN, lvgl.Style{
radius = 2,
pad_all = 2,
border_width = 1,
border_color = "#2196F3",
border_side = 15, -- LV_BORDER_SIDE_FULL
}}
},
dropdownlist = {
{lvgl.PART.MAIN, lvgl.Style{
radius = 2,
pad_all = 2,
border_width = 1,
border_color = "#607D8B",
bg_opa = lvgl.OPA(100),
bg_color = "#ffffff"
}}
}
}
theme.set(my_theme)
local backstack = require("backstack") local backstack = require("backstack")
local main_menu = require("main_menu") local main_menu = require("main_menu")

@ -0,0 +1,127 @@
local lvgl = require("lvgl")
local font = require("font")
local background_color = "#242933"
local background_muted = "#353c4b"
local text_color = "#fefefe"
local highlight_color = "#ff0077"
local theme_dark = {
base = {
{lvgl.PART.MAIN, lvgl.Style {
bg_opa = lvgl.OPA(0),
text_font = font.fusion_12,
text_color = text_color,
}},
},
root = {
{lvgl.PART.MAIN, lvgl.Style {
bg_opa = lvgl.OPA(100),
bg_color = background_color, -- Root background color
}},
},
header = {
{lvgl.PART.MAIN, lvgl.Style {
bg_opa = lvgl.OPA(100),
bg_color = background_muted,
}},
},
button = {
{lvgl.PART.MAIN, lvgl.Style {
pad_left = 2,
pad_right = 2,
pad_top = 1,
pad_bottom = 1,
bg_color = background_color,
radius = 5,
}},
{lvgl.PART.MAIN | lvgl.STATE.FOCUSED, lvgl.Style {
bg_opa = lvgl.OPA(100),
bg_color = highlight_color,
}},
},
listbutton = {
{lvgl.PART.MAIN | lvgl.STATE.FOCUSED, lvgl.Style {
bg_opa = lvgl.OPA(100),
bg_color = highlight_color,
}},
},
bar = {
{lvgl.PART.MAIN, lvgl.Style {
bg_opa = lvgl.OPA(100),
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff
}},
},
slider = {
{lvgl.PART.MAIN, lvgl.Style {
bg_opa = lvgl.OPA(100),
bg_color = background_muted,
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff
}},
{lvgl.PART.INDICATOR, lvgl.Style {
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff
bg_color = highlight_color,
}},
{lvgl.PART.KNOB, lvgl.Style {
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff
pad_all = 2,
bg_color = background_color,
shadow_width = 5,
shadow_opa = lvgl.OPA(100)
}},
{lvgl.PART.MAIN | lvgl.STATE.FOCUSED, lvgl.Style {
bg_color = background_muted,
}},
{lvgl.PART.KNOB | lvgl.STATE.FOCUSED, lvgl.Style {
bg_color = highlight_color,
}},
},
switch = {
{lvgl.PART.MAIN, lvgl.Style {
bg_opa = lvgl.OPA(100),
width = 28,
height = 12,
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff
}},
{lvgl.PART.MAIN | lvgl.STATE.FOCUSED, lvgl.Style {
bg_color = background_muted,
}},
{lvgl.PART.INDICATOR, lvgl.Style {
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff
bg_color = background_muted,
}},
{lvgl.PART.INDICATOR | lvgl.STATE.CHECKED, lvgl.Style {
bg_color = highlight_color,
}},
{lvgl.PART.KNOB, lvgl.Style {
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff
pad_all = 2,
bg_opa = lvgl.OPA(100),
bg_color = text_color,
}},
},
dropdown = {
{lvgl.PART.MAIN, lvgl.Style{
radius = 2,
pad_all = 2,
border_width = 1,
border_color = text_color,
border_side = 15, -- LV_BORDER_SIDE_FULL
}},
{lvgl.PART.MAIN | lvgl.STATE.FOCUSED, lvgl.Style {
border_color = highlight_color,
}},
},
dropdownlist = {
{lvgl.PART.MAIN, lvgl.Style{
radius = 2,
pad_all = 2,
border_width = 1,
border_color = text_color,
bg_opa = lvgl.OPA(100),
bg_color = background_color
}},
}
}
return theme_dark

@ -0,0 +1,106 @@
local lvgl = require("lvgl")
local font = require("font")
local background_color = "#FFFFFF"
local background_muted = "#FFFFFF"
local text_color = "#000000"
local highlight_color = "#E3F2FD"
local theme_light = {
base = {
{lvgl.PART.MAIN, lvgl.Style {
bg_opa = lvgl.OPA(0),
bg_color = background_color, -- Root background color
text_font = font.fusion_12,
text_color = text_color,
}},
{lvgl.STATE.FOCUSED, lvgl.Style {
bg_opa = lvgl.OPA(100),
bg_color = highlight_color,
}},
},
root = {
{lvgl.PART.MAIN, lvgl.Style {
bg_opa = lvgl.OPA(100),
bg_color = background_color, -- Root background color
}},
},
button = {
{lvgl.PART.MAIN, lvgl.Style {
pad_left = 2,
pad_right = 2,
pad_top = 1,
pad_bottom = 1,
bg_color = background_color,
radius = 5,
}},
},
bar = {
{lvgl.PART.MAIN, lvgl.Style {
bg_opa = lvgl.OPA(100),
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff
}},
},
slider = {
{lvgl.PART.MAIN, lvgl.Style {
bg_opa = lvgl.OPA(100),
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff
}},
{lvgl.PART.INDICATOR, lvgl.Style {
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff
bg_color = highlight_color,
}},
{lvgl.PART.KNOB, lvgl.Style {
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff
pad_all = 2,
bg_color = background_color,
shadow_width = 5,
shadow_opa = lvgl.OPA(100)
}},
{lvgl.STATE.FOCUSED, lvgl.Style {
bg_color = highlight_color,
}},
},
switch = {
{lvgl.PART.MAIN, lvgl.Style {
bg_opa = lvgl.OPA(100),
width = 28,
height = 18,
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff
}},
{lvgl.PART.INDICATOR, lvgl.Style {
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff
bg_color = background_muted,
}},
{lvgl.PART.INDICATOR | lvgl.STATE.CHECKED, lvgl.Style {
bg_color = highlight_color,
}},
{lvgl.PART.KNOB, lvgl.Style {
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff
pad_all = 2,
bg_opa = lvgl.OPA(100),
bg_color = background_color,
}},
},
dropdown = {
{lvgl.PART.MAIN, lvgl.Style{
radius = 2,
pad_all = 2,
border_width = 1,
border_color = "#2196F3",
border_side = 15, -- LV_BORDER_SIDE_FULL
}}
},
dropdownlist = {
{lvgl.PART.MAIN, lvgl.Style{
radius = 2,
pad_all = 2,
border_width = 1,
border_color = "#607D8B",
bg_opa = lvgl.OPA(100),
bg_color = background_color
}}
}
}
return theme_light

@ -5,6 +5,7 @@ local font = require("font")
local backstack = require("backstack") local backstack = require("backstack")
local styles = require("styles") local styles = require("styles")
local database = require("database") local database = require("database")
local theme = require("theme")
local widgets = {} local widgets = {}
@ -66,10 +67,7 @@ function widgets.StatusBar(parent, opts)
} }
if not opts.transparent_bg then if not opts.transparent_bg then
status_bar.root:set { theme.set_style(status_bar.root, "header");
bg_opa = lvgl.OPA(100),
bg_color = "#fafafa",
}
end end
if opts.back_cb then if opts.back_cb then

@ -22,17 +22,19 @@
namespace lua { namespace lua {
static auto set_theme(lua_State* L) -> int { static auto set_style(lua_State* L) -> int {
// lv_style_t* style = luavgl_to_style(L, -1); // Get the object and class name from the stack
// if (style == NULL) { if (lua_type(L, -1) == LUA_TSTRING) {
// ESP_LOGI("DANIEL", "Style was null or malformed??"); std::string class_name = lua_tostring(L, -1);
// return 0; lv_obj_t* obj = luavgl_to_obj(L, -2);
// } if (obj != NULL) {
ui::themes::Theme::instance()->ApplyStyle(obj, class_name);
// ESP_LOGI("DANIEL", "GOT ONE!"); }
// themes::Theme::instance()->...; }
return 0;
}
/* table is in the stack at index 't' */ static auto set_theme(lua_State* L) -> int {
std::string class_name; std::string class_name;
lua_pushnil(L); /* first key */ lua_pushnil(L); /* first key */
while (lua_next(L, -2) != 0) { while (lua_next(L, -2) != 0) {
@ -61,7 +63,6 @@ static auto set_theme(lua_State* L) -> int {
return 0; return 0;
} else { } else {
ui::themes::Theme::instance()->AddStyle(class_name, selector, style); ui::themes::Theme::instance()->AddStyle(class_name, selector, style);
ESP_LOGI("DANIEL", "Got style for class %s with selector %d", class_name.c_str(), selector);
} }
} }
lua_pop(L, 1); lua_pop(L, 1);
@ -75,7 +76,7 @@ static auto set_theme(lua_State* L) -> int {
return 0; return 0;
} }
static const struct luaL_Reg kThemeFuncs[] = {{"set", set_theme}, {NULL, NULL}}; static const struct luaL_Reg kThemeFuncs[] = {{"set", set_theme}, {"set_style", set_style}, {NULL, NULL}};
static auto lua_theme(lua_State* L) -> int { static auto lua_theme(lua_State* L) -> int {
luaL_newlib(L, kThemeFuncs); luaL_newlib(L, kThemeFuncs);

@ -22,7 +22,7 @@ class Theme {
public: public:
void Apply(void); void Apply(void);
void Callback(lv_obj_t* obj); void Callback(lv_obj_t* obj);
void ApplyStyle(lv_obj_t* obj, Style style); void ApplyStyle(lv_obj_t* obj, std::string style_key);
void AddStyle(std::string key, int selector, lv_style_t* style); void AddStyle(std::string key, int selector, lv_style_t* style);

@ -41,8 +41,6 @@ Modal::Modal(Screen* host)
lv_obj_set_style_bg_opa(root_, LV_OPA_COVER, 0); lv_obj_set_style_bg_opa(root_, LV_OPA_COVER, 0);
lv_obj_set_style_bg_color(root_, lv_color_white(), 0); lv_obj_set_style_bg_color(root_, lv_color_white(), 0);
themes::Theme::instance()->ApplyStyle(root_, themes::Style::kPopup);
host_->modal_group(group_); host_->modal_group(group_);
} }

@ -8,13 +8,16 @@
#include "core/lv_obj_tree.h" #include "core/lv_obj_tree.h"
#include "lua.hpp" #include "lua.hpp"
#include "themes.hpp"
#include "luavgl.h" #include "luavgl.h"
namespace ui { namespace ui {
namespace screens { namespace screens {
Lua::Lua() : s_(nullptr), obj_ref_() {} Lua::Lua() : s_(nullptr), obj_ref_() {
themes::Theme::instance()->ApplyStyle(root_, "root");
}
Lua::~Lua() { Lua::~Lua() {
if (s_ && obj_ref_) { if (s_ && obj_ref_) {

@ -44,6 +44,8 @@ void Theme::Callback(lv_obj_t* obj) {
std::string class_name; std::string class_name;
if (lv_obj_check_type(obj, &lv_btn_class)) { if (lv_obj_check_type(obj, &lv_btn_class)) {
class_name = "button"; class_name = "button";
} else if (lv_obj_check_type(obj, &lv_list_btn_class)) {
class_name = "listbutton";
} else if (lv_obj_check_type(obj, &lv_bar_class)) { } else if (lv_obj_check_type(obj, &lv_bar_class)) {
class_name = "bar"; class_name = "bar";
} else if (lv_obj_check_type(obj, &lv_slider_class)) { } else if (lv_obj_check_type(obj, &lv_slider_class)) {
@ -65,65 +67,11 @@ void Theme::Callback(lv_obj_t* obj) {
} }
void Theme::ApplyStyle(lv_obj_t* obj, Style style) { void Theme::ApplyStyle(lv_obj_t* obj, std::string style_key) {
switch (style) { if (auto search = style_map.find(style_key); search != style_map.end()) {
case Style::kTopBar: for (const auto& pair : search->second) {
lv_obj_set_style_pad_bottom(obj, 1, LV_PART_MAIN); lv_obj_add_style(obj, pair.second, pair.first);
lv_obj_set_style_shadow_width(obj, 6, LV_PART_MAIN);
lv_obj_set_style_shadow_opa(obj, LV_OPA_COVER, LV_PART_MAIN);
lv_obj_set_style_shadow_ofs_x(obj, 0, LV_PART_MAIN);
break;
case Style::kPopup:
lv_obj_set_style_shadow_width(obj, 6, LV_PART_MAIN);
lv_obj_set_style_shadow_opa(obj, LV_OPA_COVER, LV_PART_MAIN);
lv_obj_set_style_shadow_ofs_x(obj, 0, LV_PART_MAIN);
lv_obj_set_style_shadow_ofs_y(obj, 0, LV_PART_MAIN);
lv_obj_set_style_radius(obj, 5, LV_PART_MAIN);
lv_obj_set_style_bg_opa(obj, LV_OPA_COVER, LV_PART_MAIN);
lv_obj_set_style_bg_color(obj, lv_color_white(), LV_PART_MAIN);
lv_obj_set_style_pad_top(obj, 2, LV_PART_MAIN);
lv_obj_set_style_pad_bottom(obj, 2, LV_PART_MAIN);
lv_obj_set_style_pad_left(obj, 2, LV_PART_MAIN);
lv_obj_set_style_pad_right(obj, 2, LV_PART_MAIN);
break;
case Style::kTab:
lv_obj_set_style_radius(obj, 0, LV_PART_MAIN);
lv_obj_set_style_border_width(obj, 1, LV_STATE_CHECKED);
lv_obj_set_style_border_color(obj, lv_palette_main(LV_PALETTE_BLUE),
LV_STATE_CHECKED);
lv_obj_set_style_border_side(obj, LV_BORDER_SIDE_BOTTOM,
LV_STATE_CHECKED);
break;
case Style::kButtonPrimary:
lv_obj_set_style_border_width(obj, 1, LV_PART_MAIN);
lv_obj_set_style_border_color(obj, lv_palette_main(LV_PALETTE_BLUE),
LV_PART_MAIN);
lv_obj_set_style_border_side(obj, LV_BORDER_SIDE_FULL, LV_PART_MAIN);
break;
case Style::kMenuSubheadFirst:
case Style::kMenuSubhead:
lv_obj_set_style_text_color(obj, lv_palette_darken(LV_PALETTE_GREY, 3),
LV_PART_MAIN);
lv_obj_set_style_text_align(obj, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN);
lv_obj_set_style_border_width(obj, 1, LV_PART_MAIN);
lv_obj_set_style_border_color(obj, lv_palette_lighten(LV_PALETTE_GREY, 3),
LV_PART_MAIN);
if (style == Style::kMenuSubhead) {
lv_obj_set_style_border_side(
obj, LV_BORDER_SIDE_TOP | LV_BORDER_SIDE_BOTTOM, LV_PART_MAIN);
} else {
lv_obj_set_style_border_side(obj, LV_BORDER_SIDE_BOTTOM, LV_PART_MAIN);
} }
break;
default:
break;
} }
} }

Loading…
Cancel
Save