Merge pull request 'themes' (#58) from themes into main
Reviewed-on: https://codeberg.org/cool-tech-zone/tangara-fw/pulls/58 Reviewed-by: cooljqln <cooljqln@noreply.codeberg.org>custom
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 590 B After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 621 B After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 581 B After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 617 B After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 593 B After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 626 B After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 8.5 KiB |
@ -0,0 +1,176 @@ |
|||||||
|
local lvgl = require("lvgl") |
||||||
|
local font = require("font") |
||||||
|
|
||||||
|
local background_color = "#5a5474" |
||||||
|
local background_muted = "#464258" |
||||||
|
local text_color = "#eeeeee" |
||||||
|
local highlight_color = "#9773d3" |
||||||
|
local icon_enabled_color = "#eeeeee" |
||||||
|
local icon_disabled_color = "#6d6d69" |
||||||
|
|
||||||
|
local theme_dark = { |
||||||
|
base = { |
||||||
|
{lvgl.PART.MAIN, lvgl.Style { |
||||||
|
bg_opa = lvgl.OPA(0), |
||||||
|
text_font = font.fusion_12, |
||||||
|
}}, |
||||||
|
}, |
||||||
|
root = { |
||||||
|
{lvgl.PART.MAIN, lvgl.Style { |
||||||
|
bg_opa = lvgl.OPA(100), |
||||||
|
bg_color = background_color, -- Root background color |
||||||
|
bg_grad_dir = 1, |
||||||
|
bg_grad_color = "#1d0e38", |
||||||
|
text_color = text_color |
||||||
|
}}, |
||||||
|
}, |
||||||
|
header = { |
||||||
|
{lvgl.PART.MAIN, lvgl.Style { |
||||||
|
bg_opa = lvgl.OPA(100), |
||||||
|
bg_color = background_muted, |
||||||
|
}}, |
||||||
|
}, |
||||||
|
pop_up = { |
||||||
|
{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, |
||||||
|
img_recolor_opa = 180, |
||||||
|
img_recolor = highlight_color, |
||||||
|
radius = 5, |
||||||
|
}}, |
||||||
|
{lvgl.PART.MAIN | lvgl.STATE.FOCUSED, lvgl.Style { |
||||||
|
bg_opa = lvgl.OPA(100), |
||||||
|
bg_color = highlight_color, |
||||||
|
img_recolor_opa = 0, |
||||||
|
}}, |
||||||
|
}, |
||||||
|
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_muted, |
||||||
|
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, |
||||||
|
}}, |
||||||
|
{lvgl.PART.INDICATOR | lvgl.STATE.CHECKED, lvgl.Style { |
||||||
|
bg_color = highlight_color, |
||||||
|
}}, |
||||||
|
}, |
||||||
|
switch = { |
||||||
|
{lvgl.PART.MAIN, lvgl.Style { |
||||||
|
bg_opa = lvgl.OPA(100), |
||||||
|
width = 28, |
||||||
|
height = 8, |
||||||
|
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff |
||||||
|
bg_color = background_muted, |
||||||
|
border_color = highlight_color, |
||||||
|
}}, |
||||||
|
{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_muted, |
||||||
|
}}, |
||||||
|
{lvgl.PART.KNOB | lvgl.STATE.FOCUSED, lvgl.Style { |
||||||
|
bg_color = highlight_color, |
||||||
|
}}, |
||||||
|
}, |
||||||
|
dropdown = { |
||||||
|
{lvgl.PART.MAIN, lvgl.Style{ |
||||||
|
radius = 2, |
||||||
|
pad_all = 2, |
||||||
|
border_width = 1, |
||||||
|
border_color = background_muted, |
||||||
|
border_side = 15, -- LV_BORDER_SIDE_FULL |
||||||
|
bg_color = background_color, |
||||||
|
}}, |
||||||
|
{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 = highlight_color, |
||||||
|
bg_opa = lvgl.OPA(100), |
||||||
|
bg_color = background_color |
||||||
|
}}, |
||||||
|
{lvgl.PART.SELECTED | lvgl.STATE.CHECKED, lvgl.Style { |
||||||
|
bg_color = highlight_color, |
||||||
|
}}, |
||||||
|
}, |
||||||
|
database_indicator = { |
||||||
|
{lvgl.PART.MAIN, lvgl.Style { |
||||||
|
img_recolor_opa = 180, |
||||||
|
img_recolor = highlight_color, |
||||||
|
}}, |
||||||
|
}, |
||||||
|
settings_title = { |
||||||
|
{lvgl.PART.MAIN, lvgl.Style { |
||||||
|
pad_top = 2, |
||||||
|
pad_bottom = 4, |
||||||
|
text_font = font.fusion_10, |
||||||
|
text_color = highlight_color, |
||||||
|
}}, |
||||||
|
}, |
||||||
|
icon_disabled = { |
||||||
|
{lvgl.PART.MAIN, lvgl.Style { |
||||||
|
img_recolor_opa = 180, |
||||||
|
img_recolor = icon_disabled_color, |
||||||
|
}}, |
||||||
|
}, |
||||||
|
icon_enabled = { |
||||||
|
{lvgl.PART.MAIN, lvgl.Style { |
||||||
|
img_recolor_opa = 180, |
||||||
|
img_recolor = icon_enabled_color, |
||||||
|
}}, |
||||||
|
}, |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
return theme_dark |
@ -0,0 +1,174 @@ |
|||||||
|
local lvgl = require("lvgl") |
||||||
|
local font = require("font") |
||||||
|
|
||||||
|
local background_color = "#ffffff" |
||||||
|
local background_muted = "#fafafa" |
||||||
|
local text_color = "#000000" |
||||||
|
local highlight_color = "#ce93d8" |
||||||
|
local icon_enabled_color = "#2c2c2c" |
||||||
|
local icon_disabled_color = "#999999" |
||||||
|
|
||||||
|
local theme_light = { |
||||||
|
base = { |
||||||
|
{lvgl.PART.MAIN, lvgl.Style { |
||||||
|
bg_opa = lvgl.OPA(0), |
||||||
|
text_font = font.fusion_12, |
||||||
|
}}, |
||||||
|
}, |
||||||
|
root = { |
||||||
|
{lvgl.PART.MAIN, lvgl.Style { |
||||||
|
bg_opa = lvgl.OPA(100), |
||||||
|
bg_color = background_color, -- Root background color |
||||||
|
text_color = text_color |
||||||
|
}}, |
||||||
|
}, |
||||||
|
header = { |
||||||
|
{lvgl.PART.MAIN, lvgl.Style { |
||||||
|
bg_opa = lvgl.OPA(100), |
||||||
|
bg_color = background_muted, |
||||||
|
}}, |
||||||
|
}, |
||||||
|
pop_up = { |
||||||
|
{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, |
||||||
|
img_recolor_opa = 180, |
||||||
|
img_recolor = highlight_color, |
||||||
|
radius = 5, |
||||||
|
}}, |
||||||
|
{lvgl.PART.MAIN | lvgl.STATE.FOCUSED, lvgl.Style { |
||||||
|
bg_opa = lvgl.OPA(100), |
||||||
|
bg_color = highlight_color, |
||||||
|
img_recolor_opa = 0, |
||||||
|
}}, |
||||||
|
}, |
||||||
|
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_muted, |
||||||
|
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, |
||||||
|
}}, |
||||||
|
{lvgl.PART.INDICATOR | lvgl.STATE.CHECKED, lvgl.Style { |
||||||
|
bg_color = highlight_color, |
||||||
|
}}, |
||||||
|
}, |
||||||
|
switch = { |
||||||
|
{lvgl.PART.MAIN, lvgl.Style { |
||||||
|
bg_opa = lvgl.OPA(100), |
||||||
|
width = 28, |
||||||
|
height = 8, |
||||||
|
radius = 32767, -- LV_RADIUS_CIRCLE = 0x7fff |
||||||
|
bg_color = background_muted, |
||||||
|
border_color = highlight_color, |
||||||
|
}}, |
||||||
|
{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_muted, |
||||||
|
}}, |
||||||
|
{lvgl.PART.KNOB | lvgl.STATE.FOCUSED, lvgl.Style { |
||||||
|
bg_color = highlight_color, |
||||||
|
}}, |
||||||
|
}, |
||||||
|
dropdown = { |
||||||
|
{lvgl.PART.MAIN, lvgl.Style{ |
||||||
|
radius = 2, |
||||||
|
pad_all = 2, |
||||||
|
border_width = 1, |
||||||
|
border_color = background_muted, |
||||||
|
border_side = 15, -- LV_BORDER_SIDE_FULL |
||||||
|
bg_color = background_color, |
||||||
|
}}, |
||||||
|
{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 = highlight_color, |
||||||
|
bg_opa = lvgl.OPA(100), |
||||||
|
bg_color = background_color |
||||||
|
}}, |
||||||
|
{lvgl.PART.SELECTED | lvgl.STATE.CHECKED, lvgl.Style { |
||||||
|
bg_color = highlight_color, |
||||||
|
}}, |
||||||
|
}, |
||||||
|
database_indicator = { |
||||||
|
{lvgl.PART.MAIN, lvgl.Style { |
||||||
|
img_recolor_opa = 180, |
||||||
|
img_recolor = highlight_color, |
||||||
|
}}, |
||||||
|
}, |
||||||
|
settings_title = { |
||||||
|
{lvgl.PART.MAIN, lvgl.Style { |
||||||
|
pad_top = 2, |
||||||
|
pad_bottom = 4, |
||||||
|
text_font = font.fusion_10, |
||||||
|
text_color = highlight_color, |
||||||
|
}}, |
||||||
|
}, |
||||||
|
icon_disabled = { |
||||||
|
{lvgl.PART.MAIN, lvgl.Style { |
||||||
|
img_recolor_opa = 180, |
||||||
|
img_recolor = icon_disabled_color, |
||||||
|
}}, |
||||||
|
}, |
||||||
|
icon_enabled = { |
||||||
|
{lvgl.PART.MAIN, lvgl.Style { |
||||||
|
img_recolor_opa = 180, |
||||||
|
img_recolor = icon_enabled_color, |
||||||
|
}}, |
||||||
|
}, |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
return theme_light |
@ -0,0 +1,15 @@ |
|||||||
|
/*
|
||||||
|
* Copyright 2024 ailurux <ailuruxx@gmail.com> |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: GPL-3.0-only |
||||||
|
*/ |
||||||
|
|
||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "lua.hpp" |
||||||
|
|
||||||
|
namespace lua { |
||||||
|
|
||||||
|
auto RegisterThemeModule(lua_State*) -> void; |
||||||
|
|
||||||
|
} // namespace lua
|
@ -0,0 +1,89 @@ |
|||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2023 ailurux <ailuruxx@gmail.com> |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: GPL-3.0-only |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "lua_version.hpp" |
||||||
|
|
||||||
|
#include <string> |
||||||
|
|
||||||
|
#include "bridge.hpp" |
||||||
|
#include "lua.hpp" |
||||||
|
|
||||||
|
#include "esp_app_desc.h" |
||||||
|
#include "esp_log.h" |
||||||
|
#include "lauxlib.h" |
||||||
|
#include "lua.h" |
||||||
|
#include "lua_thread.hpp" |
||||||
|
#include "luavgl.h" |
||||||
|
#include "themes.hpp" |
||||||
|
|
||||||
|
namespace lua { |
||||||
|
|
||||||
|
static auto set_style(lua_State* L) -> int { |
||||||
|
// Get the object and class name from the stack
|
||||||
|
std::string class_name = luaL_checkstring(L, -1); |
||||||
|
lv_obj_t* obj = luavgl_to_obj(L, -2); |
||||||
|
if (obj != NULL) { |
||||||
|
ui::themes::Theme::instance()->ApplyStyle(obj, class_name); |
||||||
|
} |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static auto set_theme(lua_State* L) -> int { |
||||||
|
std::string class_name; |
||||||
|
luaL_checktype(L, -1, LUA_TTABLE); |
||||||
|
lua_pushnil(L); /* first key */ |
||||||
|
while (lua_next(L, -2) != 0) { |
||||||
|
/* uses 'key' (at index -2) and 'value' (at index -1) */ |
||||||
|
if (lua_type(L, -2) == LUA_TSTRING) { |
||||||
|
class_name = lua_tostring(L, -2); |
||||||
|
} |
||||||
|
if (lua_type(L, -1) == LUA_TTABLE) { |
||||||
|
// Nesting
|
||||||
|
lua_pushnil(L); // First key
|
||||||
|
while (lua_next(L, -2) != 0) { |
||||||
|
// Nesting the second
|
||||||
|
int selector = -1; |
||||||
|
lua_pushnil(L); // First key
|
||||||
|
while (lua_next(L, -2) != 0) { |
||||||
|
int idx = lua_tointeger(L, -2); |
||||||
|
if (idx == 1) { |
||||||
|
// Selector
|
||||||
|
selector = lua_tointeger(L, -1); |
||||||
|
} else if (idx == 2) { |
||||||
|
// Style
|
||||||
|
lv_style_t* style = luavgl_to_style(L, -1); |
||||||
|
if (style == NULL) { |
||||||
|
ESP_LOGI("lua_theme", "Style was null or malformed"); |
||||||
|
return 0; |
||||||
|
} else { |
||||||
|
ui::themes::Theme::instance()->AddStyle(class_name, selector, style); |
||||||
|
} |
||||||
|
} |
||||||
|
lua_pop(L, 1);
|
||||||
|
} |
||||||
|
lua_pop(L, 1);
|
||||||
|
} |
||||||
|
} |
||||||
|
/* removes 'value'; keeps 'key' for next iteration */ |
||||||
|
lua_pop(L, 1); |
||||||
|
} |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static const struct luaL_Reg kThemeFuncs[] = {{"set", set_theme}, {"set_style", set_style}, {NULL, NULL}}; |
||||||
|
|
||||||
|
static auto lua_theme(lua_State* L) -> int { |
||||||
|
luaL_newlib(L, kThemeFuncs); |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
auto RegisterThemeModule(lua_State* L) -> void { |
||||||
|
luaL_requiref(L, "theme", lua_theme, true); |
||||||
|
lua_pop(L, 1); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace lua
|