Allow lists for some style properties;

Label can now be a text or text_sensor component.
This commit is contained in:
clydebarrow 2024-05-12 22:39:42 +10:00
parent 6fd04d73dc
commit 91d972877d
7 changed files with 64 additions and 18 deletions

View File

@ -237,7 +237,7 @@ STYLE_PROPS = {
"border_color": lv_color,
"border_opa": lv.opacity,
"border_post": cv.boolean,
"border_side": lv.one_of(
"border_side": lv.several_of(
df.LvConstant(
"LV_BORDER_SIDE_", "NONE", "TOP", "BOTTOM", "LEFT", "RIGHT", "INTERNAL"
)
@ -281,7 +281,7 @@ STYLE_PROPS = {
df.LvConstant("LV_TEXT_ALIGN_", "LEFT", "CENTER", "RIGHT", "AUTO")
),
"text_color": lv_color,
"text_decor": lv.one_of(
"text_decor": lv.several_of(
df.LvConstant("LV_TEXT_DECOR_", "NONE", "UNDERLINE", "STRIKETHROUGH")
),
"text_font": lv.font,
@ -893,7 +893,7 @@ TILE_SCHEMA = any_widget_schema(
cv.Required(CONF_ROW): lv_int,
cv.Required(df.CONF_COLUMN): lv_int,
cv.GenerateID(df.CONF_TILE_ID): cv.declare_id(ty.lv_tile_t),
cv.Optional(df.CONF_DIR, default="ALL"): lv.one_of(df.TILE_DIRECTIONS),
cv.Optional(df.CONF_DIR, default="ALL"): lv.several_of(df.TILE_DIRECTIONS),
}
)
@ -961,6 +961,8 @@ async def styles_to_code(styles):
if value := style.get(prop):
if isinstance(validator, LValidator):
value = await validator.process(value)
if isinstance(value, list):
value = "|".join(value)
cgen(f"lv_style_set_{prop}({svar}, {value})")
@ -1203,8 +1205,11 @@ async def tileview_to_code(var: Widget, config: dict):
tile_obj = cg.Pvariable(w_id, cg.nullptr, type_=ty.lv_obj_t)
tile = Widget(tile_obj, ty.lv_tile_t)
widget_map[w_id] = tile
dirs = wc[df.CONF_DIR]
if isinstance(dirs, list):
dirs = "|".join(dirs)
init.append(
f"{tile.obj} = lv_tileview_add_tile({var.obj}, {wc[df.CONF_COLUMN]}, {wc[CONF_ROW]}, {wc[df.CONF_DIR]})"
f"{tile.obj} = lv_tileview_add_tile({var.obj}, {wc[df.CONF_COLUMN]}, {wc[CONF_ROW]}, {dirs})"
)
ext_init = await widget_to_code(wc, w_type, tile)
init.extend(ext_init)
@ -2074,6 +2079,15 @@ async def action_to_code(action, action_id, widg: Widget, template_arg, args):
async def update_to_code(config, action_id, widget: Widget, init, template_arg, args):
if config is not None:
init.extend(await set_obj_properties(widget, config))
if (
widget.type.value_property is not None
and widget.type.value_property in config
):
init.append(
f"""
lv_event_send({widget.obj}, LV_EVENT_VALUE_CHANGED, nullptr);
"""
)
return await action_to_code(init, action_id, widget, template_arg, args)

View File

@ -121,6 +121,10 @@ def one_of(consts: LvConstant):
return validator
def several_of(consts: LvConstant):
return cv.ensure_list(one_of(consts))
def join_enums(enums, prefix=""):
return "|".join(map(lambda e: f"(int){prefix}{e.upper()}", enums))

View File

@ -5,7 +5,7 @@ from esphome.components import text
from . import add_init_lambda, LVGL_SCHEMA, get_widget, Widget
from .defines import CONF_WIDGET, CONF_LVGL_ID
from .lv_validation import requires_component
from .types import lv_textarea_t, lvgl_ns
from .types import lvgl_ns, LvText
LVGLText = lvgl_ns.class_("LVGLText", text.Text)
@ -13,7 +13,7 @@ CONFIG_SCHEMA = cv.All(
text.TEXT_SCHEMA.extend(LVGL_SCHEMA).extend(
{
cv.GenerateID(): cv.declare_id(LVGLText),
cv.Required(CONF_WIDGET): cv.use_id(lv_textarea_t),
cv.Required(CONF_WIDGET): cv.use_id(LvText),
}
),
requires_component("text"),
@ -25,10 +25,18 @@ async def to_code(config):
paren = await cg.get_variable(config[CONF_LVGL_ID])
widget = await get_widget(config[CONF_WIDGET])
assert isinstance(widget, Widget)
init = widget.set_event_cb(
f"{var}->publish_state({widget.get_value()});", "LV_EVENT_VALUE_CHANGED"
)
value = widget.get_value()
publish = f"{var}->publish_state({value})"
init = widget.set_event_cb(publish, "LV_EVENT_VALUE_CHANGED")
init.append(f"{var}->set_control_lambda([] (std::string text) {{")
init.extend(widget.set_property("text", "text.c_str()"))
init.append("})")
init.extend(
[
f"""
lv_event_send({widget.obj}, {paren}->get_custom_change_event(), nullptr);
{publish};
}})""",
publish,
]
)
await add_init_lambda(paren, init)

View File

@ -13,13 +13,13 @@ from . import (
)
from .defines import CONF_WIDGET, CONF_LVGL_ID
from .lv_validation import requires_component
from .types import lv_textarea_t
from .types import LvText
BASE_SCHEMA = text_sensor_schema(TextSensor).extend(LVGL_SCHEMA)
CONFIG_SCHEMA = cv.All(
BASE_SCHEMA.extend(
{
cv.Required(CONF_WIDGET): cv.use_id(lv_textarea_t),
cv.Required(CONF_WIDGET): cv.use_id(LvText),
}
),
requires_component("text_sensor"),

View File

@ -1,6 +1,8 @@
import esphome.codegen as cg
from esphome import automation
from esphome.components.key_provider import KeyProvider
from esphome.components.lvgl.defines import CONF_TEXT
from esphome.const import CONF_VALUE
uint16_t_ptr = cg.uint16.operator("ptr")
lvgl_ns = cg.esphome_ns.namespace("lvgl")
@ -44,6 +46,7 @@ class LvType(cg.MockObjClass):
self.value = kwargs.pop("lvalue", lambda w: w.obj)
self.has_on_value = kwargs.pop("has_on_value", False)
self.animated = kwargs.pop("animated", False)
self.value_property = None
def get_arg_type(self):
return self.args[0][0] if len(self.args) else None
@ -57,6 +60,18 @@ class LvNumber(LvType):
lvalue=lambda w: w.get_number_value(),
has_on_value=True,
)
self.value_property = CONF_VALUE
class LvText(LvType):
def __init__(self, *args, **kwargs):
super().__init__(
*args,
largs=[(cg.std_string, "text")],
lvalue=lambda w: w.get_property("text")[0],
**kwargs,
)
self.value_property = CONF_TEXT
class LvBoolean(LvType):
@ -83,7 +98,6 @@ class LvSelect(LvType):
lv_obj_t = LvType("lv_obj_t")
LvBtnmBtn = LvBoolean(str(cg.uint16), parents=(lv_pseudo_button_t,))
lv_label_t = LvType("lv_label_t")
lv_dropdown_list_t = LvType("lv_dropdown_list_t")
lv_meter_t = LvType("lv_meter_t")
lv_btn_t = LvBoolean("lv_btn_t")
@ -100,7 +114,6 @@ lv_disp_t_ptr = cg.global_ns.struct("lv_disp_t").operator("ptr")
lv_canvas_t = LvType("lv_canvas_t")
lv_dropdown_t = LvSelect("lv_dropdown_t")
lv_roller_t = LvSelect("lv_roller_t", animated=True)
lv_led_t = LvType("lv_led_t")
lv_switch_t = LvBoolean("lv_switch_t")
lv_table_t = LvType("lv_table_t")
lv_chart_t = LvType("lv_chart_t")
@ -116,10 +129,13 @@ lv_keyboard_t = LvType(
largs=[(cg.const_char_ptr, "text")],
lvalue=lambda w: f"lv_textarea_get_text({w.obj})",
)
lv_textarea_t = LvType(
lv_label_t = LvText(
"lv_label_t",
)
lv_led_t = LvType("lv_led_t")
lv_textarea_t = LvText(
"lv_textarea_t",
largs=[(cg.const_char_ptr, "text")],
lvalue=lambda w: f"lv_textarea_get_text({w.obj})",
has_on_value=True,
)

View File

@ -76,6 +76,8 @@ class Widget:
return [f"lv_{ltype}_get_{prop}({self.obj})"]
def set_style(self, prop, value, state):
if isinstance(value, list):
value = "|".join(value)
return [f"lv_obj_set_style_{prop}({self.obj}, {value}, {state})"]
def set_event_cb(self, code, *varargs):

View File

@ -126,6 +126,8 @@ lvgl:
text_color: 0xFFFFFF
width: 100%
height: 30
border_side: [left, top]
text_decor: [underline, strikethrough]
theme:
obj:
border_width: 1
@ -501,7 +503,7 @@ lvgl:
tiles:
- img:
tile_id: cat_tile
dir: VER
dir: [LEFT, top]
row: 0
column: 0
align: center