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
|