mirror of https://github.com/esphome/esphome.git
Flex fixes
This commit is contained in:
parent
66cbb3c010
commit
c771182630
|
@ -59,6 +59,7 @@ from esphome.const import (
|
|||
CONF_DISPLAY_ID,
|
||||
CONF_ON_IDLE,
|
||||
CONF_MAX_LENGTH,
|
||||
CONF_TYPE,
|
||||
)
|
||||
from esphome.cpp_generator import LambdaExpression
|
||||
|
||||
|
@ -212,11 +213,12 @@ lv_brightness = LValidator(
|
|||
cv.percentage, cg.float_, Sensor, "get_state()", retmapper=lambda x: int(x * 255)
|
||||
)
|
||||
|
||||
cell_alignments = lv.one_of(df.LV_CELL_ALIGNMENTS)
|
||||
grid_alignments = lv.one_of(df.LV_GRID_ALIGNMENTS)
|
||||
cell_alignments = df.LV_CELL_ALIGNMENTS.one_of
|
||||
grid_alignments = df.LV_GRID_ALIGNMENTS.one_of
|
||||
flex_alignments = df.LV_FLEX_ALIGNMENTS.one_of
|
||||
|
||||
STYLE_PROPS = {
|
||||
"align": lv.one_of(df.CHILD_ALIGNMENTS),
|
||||
"align": df.CHILD_ALIGNMENTS.one_of,
|
||||
"arc_opa": lv.opacity,
|
||||
"arc_color": lv_color,
|
||||
"arc_rounded": lv_bool,
|
||||
|
@ -224,10 +226,8 @@ STYLE_PROPS = {
|
|||
"anim_time": lv_milliseconds,
|
||||
"bg_color": lv_color,
|
||||
"bg_grad_color": lv_color,
|
||||
"bg_dither_mode": lv.one_of(
|
||||
df.LvConstant("LV_DITHER_", "NONE", "ORDERED", "ERR_DIFF")
|
||||
),
|
||||
"bg_grad_dir": lv.one_of(df.LvConstant("LV_GRAD_DIR_", "NONE", "HOR", "VER")),
|
||||
"bg_dither_mode": df.LvConstant("LV_DITHER_", "NONE", "ORDERED", "ERR_DIFF").one_of,
|
||||
"bg_grad_dir": df.LvConstant("LV_GRAD_DIR_", "NONE", "HOR", "VER").one_of,
|
||||
"bg_grad_stop": lv.stop_value,
|
||||
"bg_img_opa": lv.opacity,
|
||||
"bg_img_recolor": lv_color,
|
||||
|
@ -244,12 +244,6 @@ STYLE_PROPS = {
|
|||
),
|
||||
"border_width": cv.positive_int,
|
||||
"clip_corner": lv_bool,
|
||||
"grid_cell_x_align": cell_alignments,
|
||||
"grid_cell_y_align": cell_alignments,
|
||||
"grid_cell_row_pos": cv.positive_int,
|
||||
"grid_cell_column_pos": cv.positive_int,
|
||||
"grid_cell_row_span": cv.positive_int,
|
||||
"grid_cell_column_span": cv.positive_int,
|
||||
"height": lv.size,
|
||||
"img_recolor": lv_color,
|
||||
"img_recolor_opa": lv.opacity,
|
||||
|
@ -277,9 +271,9 @@ STYLE_PROPS = {
|
|||
"shadow_opa": lv.opacity,
|
||||
"shadow_spread": cv.int_,
|
||||
"shadow_width": cv.positive_int,
|
||||
"text_align": lv.one_of(
|
||||
df.LvConstant("LV_TEXT_ALIGN_", "LEFT", "CENTER", "RIGHT", "AUTO")
|
||||
),
|
||||
"text_align": df.LvConstant(
|
||||
"LV_TEXT_ALIGN_", "LEFT", "CENTER", "RIGHT", "AUTO"
|
||||
).one_of,
|
||||
"text_color": lv_color,
|
||||
"text_decor": lv.several_of(
|
||||
df.LvConstant("LV_TEXT_DECOR_", "NONE", "UNDERLINE", "STRIKETHROUGH")
|
||||
|
@ -299,7 +293,7 @@ STYLE_PROPS = {
|
|||
"max_width": lv.pixels_or_percent,
|
||||
"min_height": lv.pixels_or_percent,
|
||||
"min_width": lv.pixels_or_percent,
|
||||
"radius": cv.Any(lv.size, lv.one_of(df.LvConstant("LV_RADIUS_", "CIRCLE"))),
|
||||
"radius": cv.Any(lv.size, df.LvConstant("LV_RADIUS_", "CIRCLE").one_of),
|
||||
"width": lv.size,
|
||||
"x": lv.pixels_or_percent,
|
||||
"y": lv.pixels_or_percent,
|
||||
|
@ -313,15 +307,6 @@ def validate_max_min(config):
|
|||
return config
|
||||
|
||||
|
||||
def validate_layout(config):
|
||||
if config.get(df.CONF_LAYOUT) == "LV_LAYOUT_GRID":
|
||||
if df.CONF_GRID_ROWS not in config or df.CONF_GRID_COLUMNS not in config:
|
||||
raise cv.Invalid("grid layout requires grid_rows and grid_columns")
|
||||
elif any((key in config) for key in list(GRID_CONTAINER_SCHEMA.keys())):
|
||||
raise cv.Invalid("grid items apply to grid layout only")
|
||||
return config
|
||||
|
||||
|
||||
def modify_schema(widget_type):
|
||||
lv_type = ty.get_widget_type(widget_type)
|
||||
schema = (
|
||||
|
@ -436,9 +421,9 @@ TEXT_SCHEMA = cv.Schema(
|
|||
STYLE_SCHEMA = cv.Schema({cv.Optional(k): v for k, v in STYLE_PROPS.items()}).extend(
|
||||
{
|
||||
cv.Optional(df.CONF_STYLES): cv.ensure_list(cv.use_id(ty.lv_style_t)),
|
||||
cv.Optional(df.CONF_SCROLLBAR_MODE): lv.one_of(
|
||||
df.LvConstant("LV_SCROLLBAR_MODE_", "OFF", "ON", "ACTIVE", "AUTO")
|
||||
),
|
||||
cv.Optional(df.CONF_SCROLLBAR_MODE): df.LvConstant(
|
||||
"LV_SCROLLBAR_MODE_", "OFF", "ON", "ACTIVE", "AUTO"
|
||||
).one_of,
|
||||
}
|
||||
)
|
||||
STATE_SCHEMA = cv.Schema(
|
||||
|
@ -446,14 +431,14 @@ STATE_SCHEMA = cv.Schema(
|
|||
).extend(STYLE_SCHEMA)
|
||||
SET_STATE_SCHEMA = cv.Schema({cv.Optional(state): lv_bool for state in df.STATES})
|
||||
FLAG_SCHEMA = cv.Schema({cv.Optional(flag): cv.boolean for flag in df.OBJ_FLAGS})
|
||||
FLAG_LIST = cv.ensure_list(lv.one_of(df.LvConstant("LV_OBJ_FLAG_", df.OBJ_FLAGS)))
|
||||
FLAG_LIST = cv.ensure_list(df.LvConstant("LV_OBJ_FLAG_", df.OBJ_FLAGS).one_of)
|
||||
|
||||
BAR_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.Optional(CONF_VALUE): lv_float,
|
||||
cv.Optional(CONF_MIN_VALUE, default=0): cv.int_,
|
||||
cv.Optional(CONF_MAX_VALUE, default=100): cv.int_,
|
||||
cv.Optional(CONF_MODE, default="NORMAL"): lv.one_of(df.BAR_MODES),
|
||||
cv.Optional(CONF_MODE, default="NORMAL"): df.BAR_MODES.one_of,
|
||||
cv.Optional(df.CONF_ANIMATED, default=True): lv.animated,
|
||||
}
|
||||
)
|
||||
|
@ -518,9 +503,9 @@ IMG_SCHEMA = {
|
|||
cv.Optional(df.CONF_OFFSET_X): lv.size,
|
||||
cv.Optional(df.CONF_OFFSET_Y): lv.size,
|
||||
cv.Optional(df.CONF_ANTIALIAS): lv_bool,
|
||||
cv.Optional(CONF_MODE): lv.one_of(
|
||||
df.LvConstant("LV_IMG_SIZE_MODE_", "VIRTUAL", "REAL")
|
||||
),
|
||||
cv.Optional(CONF_MODE): df.LvConstant(
|
||||
"LV_IMG_SIZE_MODE_", "VIRTUAL", "REAL"
|
||||
).one_of,
|
||||
}
|
||||
|
||||
# Schema for a single button in a btnmatrix
|
||||
|
@ -560,7 +545,7 @@ ARC_SCHEMA = cv.Schema(
|
|||
cv.Optional(df.CONF_END_ANGLE, default=45): lv.angle,
|
||||
cv.Optional(CONF_ROTATION, default=0.0): lv.angle,
|
||||
cv.Optional(df.CONF_ADJUSTABLE, default=False): bool,
|
||||
cv.Optional(CONF_MODE, default="NORMAL"): lv.one_of(df.ARC_MODES),
|
||||
cv.Optional(CONF_MODE, default="NORMAL"): df.ARC_MODES.one_of,
|
||||
cv.Optional(df.CONF_CHANGE_RATE, default=720): cv.uint16_t,
|
||||
}
|
||||
)
|
||||
|
@ -692,7 +677,7 @@ PAGE_SCHEMA = {
|
|||
LABEL_SCHEMA = TEXT_SCHEMA.extend(
|
||||
{
|
||||
cv.Optional(df.CONF_RECOLOR): lv_bool,
|
||||
cv.Optional(df.CONF_LONG_MODE): lv.one_of(df.LV_LONG_MODES),
|
||||
cv.Optional(df.CONF_LONG_MODE): df.LV_LONG_MODES.one_of,
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -712,7 +697,7 @@ DROPDOWN_BASE_SCHEMA = cv.Schema(
|
|||
{
|
||||
cv.Optional(df.CONF_SYMBOL): lv_text,
|
||||
cv.Optional(df.CONF_SELECTED_INDEX): cv.templatable(cv.int_),
|
||||
cv.Optional(df.CONF_DIR, default="BOTTOM"): lv.one_of(df.DIRECTIONS),
|
||||
cv.Optional(df.CONF_DIR, default="BOTTOM"): df.DIRECTIONS.one_of,
|
||||
cv.Optional(df.CONF_DROPDOWN_LIST): part_schema(df.CONF_DROPDOWN_LIST),
|
||||
}
|
||||
)
|
||||
|
@ -729,7 +714,7 @@ ROLLER_BASE_SCHEMA = cv.Schema(
|
|||
{
|
||||
cv.Optional(df.CONF_SELECTED_INDEX): cv.templatable(cv.int_),
|
||||
cv.Optional(df.CONF_VISIBLE_ROW_COUNT): lv_int,
|
||||
cv.Optional(CONF_MODE, default="NORMAL"): lv.one_of(df.ROLLER_MODES),
|
||||
cv.Optional(CONF_MODE, default="NORMAL"): df.ROLLER_MODES.one_of,
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -775,7 +760,7 @@ SPINBOX_MODIFY_SCHEMA = {
|
|||
}
|
||||
|
||||
KEYBOARD_SCHEMA = {
|
||||
cv.Optional(CONF_MODE, default="TEXT_UPPER"): lv.one_of(df.KEYBOARD_MODES),
|
||||
cv.Optional(CONF_MODE, default="TEXT_UPPER"): df.KEYBOARD_MODES.one_of,
|
||||
cv.Optional(df.CONF_TEXTAREA): cv.use_id(ty.lv_textarea_t),
|
||||
}
|
||||
|
||||
|
@ -787,22 +772,11 @@ LVGL_SCHEMA = cv.Schema(
|
|||
)
|
||||
|
||||
|
||||
def get_layout(layout=cv.UNDEFINED, flow="ROW_WRAP"):
|
||||
return cv.Schema(
|
||||
{
|
||||
cv.Optional(df.CONF_FLEX_FLOW, default=flow): lv.one_of(df.FLEX_FLOWS),
|
||||
cv.Optional(df.CONF_LAYOUT, default=layout): lv.one_of(
|
||||
df.LvConstant("LV_LAYOUT_", "FLEX", "GRID")
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
ALIGN_TO_SCHEMA = {
|
||||
cv.Optional(df.CONF_ALIGN_TO): cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_ID): cv.use_id(ty.lv_obj_t),
|
||||
cv.Required(df.CONF_ALIGN): lv.one_of(df.ALIGN_ALIGNMENTS),
|
||||
cv.Required(df.CONF_ALIGN): df.ALIGN_ALIGNMENTS.one_of,
|
||||
cv.Optional(df.CONF_X, default=0): lv.pixels_or_percent,
|
||||
cv.Optional(df.CONF_Y, default=0): lv.pixels_or_percent,
|
||||
}
|
||||
|
@ -819,25 +793,50 @@ def grid_free_space(value):
|
|||
|
||||
|
||||
grid_spec = cv.Any(
|
||||
lv.size, lv.one_of(df.LvConstant("LV_GRID_", "CONTENT")), grid_free_space
|
||||
lv.size, df.LvConstant("LV_GRID_", "CONTENT").one_of, grid_free_space
|
||||
)
|
||||
|
||||
GRID_CONTAINER_SCHEMA = {
|
||||
cv.Optional(df.CONF_GRID_ROWS): grid_spec,
|
||||
cv.Optional(df.CONF_GRID_COLUMNS): grid_spec,
|
||||
cv.Optional(df.CONF_GRID_COLUMN_ALIGN): grid_alignments,
|
||||
cv.Optional(df.CONF_GRID_ROW_ALIGN): grid_alignments,
|
||||
LAYOUT_SCHEMA = {
|
||||
cv.Optional(df.CONF_LAYOUT): cv.typed_schema(
|
||||
{
|
||||
df.TYPE_GRID: {
|
||||
cv.Required(df.CONF_GRID_ROWS): grid_spec,
|
||||
cv.Required(df.CONF_GRID_COLUMNS): grid_spec,
|
||||
cv.Optional(df.CONF_GRID_COLUMN_ALIGN): grid_alignments,
|
||||
cv.Optional(df.CONF_GRID_ROW_ALIGN): grid_alignments,
|
||||
},
|
||||
df.TYPE_FLEX: {
|
||||
cv.Optional(df.CONF_FLEX_FLOW): df.FLEX_FLOWS.one_of,
|
||||
cv.Optional(df.CONF_FLEX_ALIGN_MAIN, default="start"): flex_alignments,
|
||||
cv.Optional(df.CONF_FLEX_ALIGN_CROSS, default="start"): flex_alignments,
|
||||
cv.Optional(df.CONF_FLEX_ALIGN_TRACK, default="start"): flex_alignments,
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
GRID_CELL_SCHEMA = {
|
||||
cv.Optional(df.CONF_GRID_CELL_X_ALIGN, default="start"): cell_alignments,
|
||||
cv.Optional(df.CONF_GRID_CELL_Y_ALIGN, default="start"): cell_alignments,
|
||||
cv.Optional(df.CONF_GRID_CELL_ROW_POS, default=1): cv.positive_int,
|
||||
cv.Optional(df.CONF_GRID_CELL_COLUMN_POS, default=1): cv.positive_int,
|
||||
cv.Optional(df.CONF_GRID_CELL_ROW_SPAN, default=1): cv.positive_int,
|
||||
cv.Optional(df.CONF_GRID_CELL_COLUMN_SPAN, default=1): cv.positive_int,
|
||||
}
|
||||
|
||||
FLEX_OBJ_SCHEMA = {
|
||||
cv.Optional(df.CONF_FLEX_GROW, default=1): cv.int_,
|
||||
}
|
||||
|
||||
|
||||
def obj_schema(wtype: str):
|
||||
return cv.Schema(
|
||||
return (
|
||||
part_schema(wtype)
|
||||
.extend(FLAG_SCHEMA)
|
||||
.extend(GRID_CONTAINER_SCHEMA)
|
||||
.extend(LAYOUT_SCHEMA)
|
||||
.extend(automation_schema(ty.get_widget_type(wtype)))
|
||||
.extend(ALIGN_TO_SCHEMA)
|
||||
.extend(get_layout())
|
||||
.extend(
|
||||
cv.Schema(
|
||||
{
|
||||
|
@ -846,7 +845,10 @@ def obj_schema(wtype: str):
|
|||
}
|
||||
)
|
||||
)
|
||||
).add_extra(validate_max_min)
|
||||
)
|
||||
|
||||
|
||||
WIDGET_SCHEMAS = {}
|
||||
|
||||
|
||||
def container_schema(widget_type, extras=None):
|
||||
|
@ -859,12 +861,13 @@ def container_schema(widget_type, extras=None):
|
|||
|
||||
# Delayed evaluation for recursion
|
||||
def validator(value):
|
||||
widgets = cv.Schema(
|
||||
{
|
||||
cv.Optional(df.CONF_WIDGETS): cv.ensure_list(WIDGET_SCHEMA),
|
||||
}
|
||||
)
|
||||
result = schema.extend(widgets)
|
||||
result = schema
|
||||
ltype = df.TYPE_NONE
|
||||
if layout := value.get(df.CONF_LAYOUT):
|
||||
if not isinstance(layout, dict):
|
||||
raise cv.Invalid("Layout value must be a dict")
|
||||
ltype = layout.get(CONF_TYPE)
|
||||
result = result.extend(WIDGET_SCHEMAS[ltype])
|
||||
if value == SCHEMA_EXTRACT:
|
||||
return result
|
||||
return result(value)
|
||||
|
@ -873,7 +876,7 @@ def container_schema(widget_type, extras=None):
|
|||
|
||||
|
||||
def widget_schema(name, extras=None):
|
||||
validator = cv.All(container_schema(name, extras=extras), validate_layout)
|
||||
validator = container_schema(name, extras=extras)
|
||||
if required := lv.REQUIRED_COMPONENTS.get(name):
|
||||
validator = cv.All(validator, lv.requires_component(required))
|
||||
return cv.Exclusive(name, df.CONF_WIDGETS), validator
|
||||
|
@ -916,6 +919,20 @@ MSGBOX_SCHEMA = STYLE_SCHEMA.extend(
|
|||
}
|
||||
)
|
||||
|
||||
# All widget schemas must be defined before this.
|
||||
|
||||
WIDGET_SCHEMAS[df.TYPE_GRID] = {
|
||||
cv.Optional(df.CONF_WIDGETS): cv.ensure_list(any_widget_schema(GRID_CELL_SCHEMA))
|
||||
}
|
||||
WIDGET_SCHEMAS[df.TYPE_FLEX] = {
|
||||
cv.Optional(df.CONF_WIDGETS): cv.ensure_list(any_widget_schema(FLEX_OBJ_SCHEMA))
|
||||
}
|
||||
WIDGET_SCHEMAS[df.TYPE_NONE] = {
|
||||
cv.Optional(df.CONF_WIDGETS): cv.ensure_list(any_widget_schema())
|
||||
}
|
||||
|
||||
ALL_STYLES = {**STYLE_PROPS, **GRID_CELL_SCHEMA, **FLEX_OBJ_SCHEMA}
|
||||
|
||||
|
||||
async def get_color_value(value):
|
||||
if isinstance(value, Lambda):
|
||||
|
@ -1028,7 +1045,7 @@ def add_define(macro, value="1"):
|
|||
|
||||
def collect_props(config):
|
||||
props = {}
|
||||
for prop in [*STYLE_PROPS, *df.OBJ_FLAGS, df.CONF_STYLES, CONF_GROUP]:
|
||||
for prop in [*ALL_STYLES, *df.OBJ_FLAGS, df.CONF_STYLES, CONF_GROUP]:
|
||||
if prop in config:
|
||||
props[prop] = config[prop]
|
||||
return props
|
||||
|
@ -1053,25 +1070,37 @@ def collect_parts(config):
|
|||
async def set_obj_properties(widget: Widget, config):
|
||||
"""Return a list of C++ statements to apply properties to an ty.lv_obj_t"""
|
||||
init = []
|
||||
if config.get(df.CONF_LAYOUT) == "LV_LAYOUT_GRID":
|
||||
lv.lv_uses.add("GRID")
|
||||
wid = config[CONF_ID]
|
||||
if df.CONF_GRID_CELL_ROW_SPAN not in config:
|
||||
config[df.CONF_GRID_CELL_ROW_SPAN] = 1
|
||||
if df.CONF_GRID_CELL_COLUMN_SPAN not in config:
|
||||
config[df.CONF_GRID_CELL_COLUMN_SPAN] = 1
|
||||
for key in (df.CONF_GRID_COLUMN_ALIGN, df.CONF_GRID_COLUMN_ALIGN):
|
||||
init.extend(widget.set_property(key, config))
|
||||
rows = "{" + ",".join(config[df.CONF_GRID_ROWS]) + ", LV_GRID_TEMPLATE_LAST}"
|
||||
row_id = ID(f"{wid}_row_dsc", is_declaration=True, type=ty.lv_coord_t)
|
||||
row_array = cg.static_const_array(row_id, cg.RawExpression(rows))
|
||||
init.extend(widget.set_style("grid_row_dsc_array", row_array, 0))
|
||||
columns = (
|
||||
"{" + ",".join(config[df.CONF_GRID_COLUMNS]) + ", LV_GRID_TEMPLATE_LAST}"
|
||||
if layout := config.get(df.CONF_LAYOUT):
|
||||
layout_type: str = layout[CONF_TYPE].upper()
|
||||
lv.lv_uses.add(layout_type)
|
||||
init.extend(
|
||||
widget.set_property(df.CONF_LAYOUT, f"LV_LAYOUT_{layout_type}", ltype="obj")
|
||||
)
|
||||
column_id = ID(f"{wid}_column_dsc", is_declaration=True, type=ty.lv_coord_t)
|
||||
column_array = cg.static_const_array(column_id, cg.RawExpression(columns))
|
||||
init.extend(widget.set_style("grid_column_dsc_array", column_array, 0))
|
||||
if layout_type.lower() == df.TYPE_GRID:
|
||||
wid = config[CONF_ID]
|
||||
rows = (
|
||||
"{" + ",".join(layout[df.CONF_GRID_ROWS]) + ", LV_GRID_TEMPLATE_LAST}"
|
||||
)
|
||||
row_id = ID(f"{wid}_row_dsc", is_declaration=True, type=ty.lv_coord_t)
|
||||
row_array = cg.static_const_array(row_id, cg.RawExpression(rows))
|
||||
init.extend(widget.set_style("grid_row_dsc_array", row_array, 0))
|
||||
columns = (
|
||||
"{"
|
||||
+ ",".join(layout[df.CONF_GRID_COLUMNS])
|
||||
+ ", LV_GRID_TEMPLATE_LAST}"
|
||||
)
|
||||
column_id = ID(f"{wid}_column_dsc", is_declaration=True, type=ty.lv_coord_t)
|
||||
column_array = cg.static_const_array(column_id, cg.RawExpression(columns))
|
||||
init.extend(widget.set_style("grid_column_dsc_array", column_array, 0))
|
||||
if layout_type.lower() == df.TYPE_FLEX:
|
||||
lv.lv_uses.add(df.TYPE_FLEX)
|
||||
init.extend(widget.set_property(df.CONF_FLEX_FLOW, layout, ltype="obj"))
|
||||
main = layout[df.CONF_FLEX_ALIGN_MAIN]
|
||||
cross = layout[df.CONF_FLEX_ALIGN_CROSS]
|
||||
track = layout[df.CONF_FLEX_ALIGN_TRACK]
|
||||
init.append(
|
||||
f"lv_obj_set_flex_align({widget.obj}, {main}, {cross}, {track})"
|
||||
)
|
||||
parts = collect_parts(config)
|
||||
for part, states in parts.items():
|
||||
for state, props in states.items():
|
||||
|
@ -1082,10 +1111,10 @@ async def set_obj_properties(widget: Widget, config):
|
|||
f"lv_obj_add_style({widget.obj}, {style_id}, {lv_state})"
|
||||
)
|
||||
for prop, value in {
|
||||
k: v for k, v in props.items() if k in STYLE_PROPS
|
||||
k: v for k, v in props.items() if k in ALL_STYLES
|
||||
}.items():
|
||||
if isinstance(STYLE_PROPS[prop], LValidator):
|
||||
value = await STYLE_PROPS[prop].process(value)
|
||||
if isinstance(ALL_STYLES[prop], LValidator):
|
||||
value = await ALL_STYLES[prop].process(value)
|
||||
init.extend(widget.set_style(prop, value, lv_state))
|
||||
if group := add_group(config.get(CONF_GROUP)):
|
||||
init.append(f"lv_group_add_obj({group}, {widget.obj})")
|
||||
|
@ -1104,12 +1133,6 @@ async def set_obj_properties(widget: Widget, config):
|
|||
clrs = lv.join_enums(flag_clr, "LV_OBJ_FLAG_")
|
||||
init.extend(widget.clear_flag(clrs))
|
||||
|
||||
if layout := config.get(df.CONF_LAYOUT):
|
||||
layout = layout.upper()
|
||||
init.extend(widget.set_property("layout", layout, ltype="obj"))
|
||||
if layout == "LV_LAYOUT_FLEX":
|
||||
lv.lv_uses.add("FLEX")
|
||||
init.extend(widget.set_property("flex_flow", config, ltype="obj"))
|
||||
if states := config.get(CONF_STATE):
|
||||
adds = set()
|
||||
clears = set()
|
||||
|
@ -1259,7 +1282,7 @@ async def led_to_code(var: Widget, config):
|
|||
|
||||
SHOW_SCHEMA = LVGL_SCHEMA.extend(
|
||||
{
|
||||
cv.Optional(df.CONF_ANIMATION, default="NONE"): lv.one_of(df.LV_ANIM),
|
||||
cv.Optional(df.CONF_ANIMATION, default="NONE"): df.LV_ANIM.one_of,
|
||||
cv.Optional(CONF_TIME, default="50ms"): lv_milliseconds,
|
||||
}
|
||||
)
|
||||
|
@ -2071,7 +2094,7 @@ async def action_to_code(action, action_id, widg: Widget, template_arg, args):
|
|||
if nc := widg.check_null():
|
||||
action.insert(0, nc)
|
||||
lamb = await cg.process_lambda(Lambda(";\n".join([*action, ""])), args)
|
||||
var = cg.new_Pvariable(action_id, template_arg, lamb[0])
|
||||
var = cg.new_Pvariable(action_id, template_arg, lamb)
|
||||
return var
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
from esphome.schema_extractors import schema_extractor, SCHEMA_EXTRACT
|
||||
import esphome.config_validation as cv
|
||||
|
||||
|
||||
class LvConstant:
|
||||
def __init__(self, prefix: str, *choices):
|
||||
self.prefix = prefix
|
||||
|
@ -6,6 +10,23 @@ class LvConstant:
|
|||
def extend(self, *choices):
|
||||
return LvConstant(self.prefix, *(self.choices + choices))
|
||||
|
||||
@property
|
||||
def one_of(self):
|
||||
"""Allow one of a list of choices, mapped to upper case, and prepend the choice with the prefix.
|
||||
It's also permitted to include the prefix in the value"""
|
||||
|
||||
@schema_extractor("one_of")
|
||||
def validator(value):
|
||||
if value == SCHEMA_EXTRACT:
|
||||
return self.choices
|
||||
if isinstance(value, str) and value.startswith(self.prefix):
|
||||
return cv.one_of(
|
||||
*list(map(lambda v: self.prefix + v, self.choices)), upper=True
|
||||
)(value)
|
||||
return self.prefix + cv.one_of(*self.choices, upper=True)(value)
|
||||
|
||||
return validator
|
||||
|
||||
|
||||
# Widgets
|
||||
CONF_ANIMIMG = "animimg"
|
||||
|
@ -50,6 +71,12 @@ CONF_TICK_STYLE = "tick_style"
|
|||
CONF_CURSOR = "cursor"
|
||||
CONF_TEXTAREA_PLACEHOLDER = "textarea_placeholder"
|
||||
|
||||
# Layout types
|
||||
|
||||
TYPE_FLEX = "flex"
|
||||
TYPE_GRID = "grid"
|
||||
TYPE_NONE = "none"
|
||||
|
||||
LV_FONTS = list(map(lambda size: f"montserrat_{size}", range(8, 50, 2))) + [
|
||||
"dejavu_16_persian_hebrew",
|
||||
"simsun_16_cjk",
|
||||
|
@ -240,12 +267,15 @@ BTNMATRIX_CTRLS = (
|
|||
"CUSTOM_2",
|
||||
)
|
||||
|
||||
LV_CELL_ALIGNMENTS = LvConstant(
|
||||
"LV_GRID_ALIGNMENT_",
|
||||
LV_BASE_ALIGNMENTS = (
|
||||
"START",
|
||||
"CENTER",
|
||||
"END",
|
||||
)
|
||||
LV_CELL_ALIGNMENTS = LvConstant(
|
||||
"LV_GRID_ALIGN_",
|
||||
*LV_BASE_ALIGNMENTS,
|
||||
)
|
||||
LV_GRID_ALIGNMENTS = LV_CELL_ALIGNMENTS.extend(
|
||||
"STRETCH",
|
||||
"SPACE_EVENLY",
|
||||
|
@ -253,6 +283,14 @@ LV_GRID_ALIGNMENTS = LV_CELL_ALIGNMENTS.extend(
|
|||
"SPACE_BETWEEN",
|
||||
)
|
||||
|
||||
LV_FLEX_ALIGNMENTS = LvConstant(
|
||||
"LV_FLEX_ALIGN_",
|
||||
*LV_BASE_ALIGNMENTS,
|
||||
"SPACE_EVENLY",
|
||||
"SPACE_AROUND",
|
||||
"SPACE_BETWEEN",
|
||||
)
|
||||
|
||||
LV_CHART_TYPES = (
|
||||
"NONE",
|
||||
"LINE",
|
||||
|
@ -299,11 +337,17 @@ CONF_END_ANGLE = "end_angle"
|
|||
CONF_END_VALUE = "end_value"
|
||||
CONF_FLAGS = "flags"
|
||||
CONF_FLEX_FLOW = "flex_flow"
|
||||
CONF_FLEX_ALIGN_MAIN = "flex_align_main"
|
||||
CONF_FLEX_ALIGN_CROSS = "flex_align_cross"
|
||||
CONF_FLEX_ALIGN_TRACK = "flex_align_track"
|
||||
CONF_FLEX_GROW = "flex_grow"
|
||||
CONF_FULL_REFRESH = "full_refresh"
|
||||
CONF_GRID_CELL_ROW_POS = "grid_cell_row_pos"
|
||||
CONF_GRID_CELL_COLUMN_POS = "grid_cell_column_pos"
|
||||
CONF_GRID_CELL_ROW_SPAN = "grid_cell_row_span"
|
||||
CONF_GRID_CELL_COLUMN_SPAN = "grid_cell_column_span"
|
||||
CONF_GRID_CELL_X_ALIGN = "grid_cell_x_align"
|
||||
CONF_GRID_CELL_Y_ALIGN = "grid_cell_y_align"
|
||||
CONF_GRID_COLUMN_ALIGN = "grid_column_align"
|
||||
CONF_GRID_COLUMNS = "grid_columns"
|
||||
CONF_GRID_ROW_ALIGN = "grid_row_align"
|
||||
|
|
|
@ -94,7 +94,7 @@ def bool_(value):
|
|||
def animated(value):
|
||||
if isinstance(value, bool):
|
||||
value = "ON" if value else "OFF"
|
||||
return one_of(LvConstant("LV_ANIM_", "OFF", "ON"))(value)
|
||||
return LvConstant("LV_ANIM_", "OFF", "ON").one_of(value)
|
||||
|
||||
|
||||
def key_code(value):
|
||||
|
@ -104,25 +104,8 @@ def key_code(value):
|
|||
return value
|
||||
|
||||
|
||||
def one_of(consts: LvConstant):
|
||||
"""Allow one of a list of choices, mapped to upper case, and prepend the choice with the prefix.
|
||||
It's also permitted to include the prefix in the value"""
|
||||
|
||||
@schema_extractor("one_of")
|
||||
def validator(value):
|
||||
if value == SCHEMA_EXTRACT:
|
||||
return consts.choices
|
||||
if isinstance(value, str) and value.startswith(consts.prefix):
|
||||
return cv.one_of(
|
||||
*list(map(lambda v: consts.prefix + v, consts.choices)), upper=True
|
||||
)(value)
|
||||
return consts.prefix + cv.one_of(*consts.choices, upper=True)(value)
|
||||
|
||||
return validator
|
||||
|
||||
|
||||
def several_of(consts: LvConstant):
|
||||
return cv.ensure_list(one_of(consts))
|
||||
return cv.ensure_list(consts.one_of)
|
||||
|
||||
|
||||
def join_enums(enums, prefix=""):
|
||||
|
@ -185,14 +168,13 @@ def size(value):
|
|||
|
||||
@schema_extractor("one_of")
|
||||
def opacity(value):
|
||||
consts = LvConstant("LV_OPA_", "TRANSP", "COVER")
|
||||
if value == SCHEMA_EXTRACT:
|
||||
return ["TRANSP", "COVER", "..%"]
|
||||
value = cv.Any(cv.percentage, one_of(LvConstant("LV_OPA_", "TRANSP", "COVER")))(
|
||||
value
|
||||
)
|
||||
if isinstance(value, str):
|
||||
return value
|
||||
return int(value * 255)
|
||||
return consts.choices
|
||||
value = cv.Any(cv.percentage, consts.one_of)(value)
|
||||
if isinstance(value, float):
|
||||
return int(value * 255)
|
||||
return value
|
||||
|
||||
|
||||
def stop_value(value):
|
||||
|
|
|
@ -158,14 +158,15 @@ lvgl:
|
|||
pad_all: 0
|
||||
widgets:
|
||||
- btn:
|
||||
layout: grid
|
||||
grid_rows: 2
|
||||
grid_columns: 2
|
||||
grid_cell_row_span: 2
|
||||
grid_cell_column_span: 2
|
||||
layout:
|
||||
type: grid
|
||||
grid_rows: 2
|
||||
grid_columns: 2
|
||||
checkable: true
|
||||
widgets:
|
||||
- label:
|
||||
grid_cell_row_span: 2
|
||||
grid_cell_column_span: 2
|
||||
align: center
|
||||
id: my_label_id
|
||||
text: "Test Toggle Button"
|
||||
|
@ -401,9 +402,10 @@ lvgl:
|
|||
format: "Spinbox value is %f"
|
||||
args: [x]
|
||||
- btn:
|
||||
layout: grid
|
||||
grid_rows: 2
|
||||
grid_columns: 2
|
||||
layout:
|
||||
type: grid
|
||||
grid_rows: 2
|
||||
grid_columns: 2
|
||||
id: spin_down
|
||||
on_click:
|
||||
- lvgl.spinbox.decrement: spinbox_id
|
||||
|
@ -411,6 +413,9 @@ lvgl:
|
|||
id: spinbox_id
|
||||
value: 100
|
||||
- img:
|
||||
layout:
|
||||
type: flex
|
||||
flex_flow: column_wrap
|
||||
align: CENTER
|
||||
src: cat_image
|
||||
id: img_id
|
||||
|
|
Loading…
Reference in New Issue