From feef234dddae028aeaaffe2417c886b8675dc918 Mon Sep 17 00:00:00 2001 From: Michael Davidson Date: Sun, 31 Dec 2023 13:03:26 +1100 Subject: [PATCH] Add can_wrap_at_character - allows for overriding how lines are wrapped This can be used if the default characters do not work for a user or to support languages other than English --- .../components/graphical_layout/text_run_panel.cpp | 8 ++++---- .../components/graphical_layout/text_run_panel.h | 8 ++++---- .../components/graphical_layout/text_run_panel.py | 14 ++++++++++++++ 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/esphome/components/graphical_layout/text_run_panel.cpp b/esphome/components/graphical_layout/text_run_panel.cpp index 685c6a1751..b836bedf17 100644 --- a/esphome/components/graphical_layout/text_run_panel.cpp +++ b/esphome/components/graphical_layout/text_run_panel.cpp @@ -28,7 +28,7 @@ void TextRunPanel::dump_config(int indent_depth, int additional_level_depth) { void TextRunPanel::setup_complete() { if (!this->can_wrap_at_character_.has_value()) { ESP_LOGD(TAG, "No custom can_wrap_at_character provided. Will use default implementation"); - this->can_wrap_at_character_ = [this](CanWrapAtCharacterArguments *args) { + this->can_wrap_at_character_ = [this](const CanWrapAtCharacterArguments &args) { return this->default_can_wrap_at_character(args); }; } @@ -102,7 +102,7 @@ CalculatedLayout TextRunPanel::determine_layout(display::Display *display, displ can_wrap_at_args.offset = i; can_wrap_at_args.character = text.at(i); - bool can_wrap = this->can_wrap_at_character_.value(&can_wrap_at_args); + bool can_wrap = this->can_wrap_at_character_.value(can_wrap_at_args); if (can_wrap) { ESP_LOGVV(TAG, "Can break at '%c'. String is '%s'", can_wrap_at_args.character, partial_line.c_str()); @@ -264,8 +264,8 @@ void TextRunPanel::apply_alignment_to_layout(CalculatedLayout *calculated_layout calculated_layout->bounds.h += total_y_offset; } -bool TextRunPanel::default_can_wrap_at_character(CanWrapAtCharacterArguments *args) { - switch (args->character) { +bool TextRunPanel::default_can_wrap_at_character(const CanWrapAtCharacterArguments &args) { + switch (args.character) { case ' ': case '\t': case '\n': diff --git a/esphome/components/graphical_layout/text_run_panel.h b/esphome/components/graphical_layout/text_run_panel.h index 3fc1e9c790..43c37c5dcb 100644 --- a/esphome/components/graphical_layout/text_run_panel.h +++ b/esphome/components/graphical_layout/text_run_panel.h @@ -37,8 +37,8 @@ class TextRun { TemplatableValue text_{}; display::BaseFont *font_{nullptr}; - Color foreground_color_{display::COLOR_ON}; - Color background_color_{display::COLOR_OFF}; + Color foreground_color_{COLOR_ON}; + Color background_color_{COLOR_OFF}; }; class CalculatedTextRun { @@ -72,7 +72,7 @@ class TextRunPanel : public LayoutItem { void dump_config(int indent_depth, int additional_level_depth) override; void setup_complete() override; - bool default_can_wrap_at_character(CanWrapAtCharacterArguments *args); + bool default_can_wrap_at_character(const CanWrapAtCharacterArguments &args); CalculatedLayout determine_layout(display::Display *display, display::Rect bounds, bool apply_alignment); void apply_alignment_to_layout(CalculatedLayout *layout); @@ -92,7 +92,7 @@ class TextRunPanel : public LayoutItem { display::TextAlign text_align_{display::TextAlign::TOP_LEFT}; int min_width_{0}; int max_width_{0}; - TemplatableValue can_wrap_at_character_{}; + TemplatableValue can_wrap_at_character_{}; bool debug_outline_runs_{false}; }; diff --git a/esphome/components/graphical_layout/text_run_panel.py b/esphome/components/graphical_layout/text_run_panel.py index 35021a7e9b..47ef3c1497 100644 --- a/esphome/components/graphical_layout/text_run_panel.py +++ b/esphome/components/graphical_layout/text_run_panel.py @@ -8,6 +8,10 @@ graphical_layout_ns = cg.esphome_ns.namespace("graphical_layout") TextRunPanel = graphical_layout_ns.class_("TextRunPanel") TextAlign = display_ns.enum("TextAlign", is_class=True) TextRun = graphical_layout_ns.class_("TextRun") +CanWrapAtCharacterArguments = graphical_layout_ns.struct("CanWrapAtCharacterArguments") +CanWrapAtCharacterArgumentsConstRef = CanWrapAtCharacterArguments.operator( + "const" +).operator("ref") CONF_TEXT_RUN_PANEL = "text_run_panel" CONF_FONT = "font" @@ -16,6 +20,7 @@ CONF_TEXT_ALIGN = "text_align" CONF_MAX_WIDTH = "max_width" CONF_MIN_WIDTH = "min_width" CONF_RUNS = "runs" +CONF_CAN_WRAP_AT_CHARACTER = "can_wrap_at_character" CONF_DEBUG_OUTLINE_RUNS = "debug_outline_runs" TEXT_ALIGN = { @@ -51,6 +56,7 @@ def get_config_schema(base_item_schema, item_type_schema): cv.Optional(CONF_TEXT_ALIGN): cv.enum(TEXT_ALIGN, upper=True), cv.Required(CONF_MAX_WIDTH): cv.int_range(min=0), cv.Optional(CONF_MIN_WIDTH, default=0): cv.int_range(min=0), + cv.Optional(CONF_CAN_WRAP_AT_CHARACTER): cv.returning_lambda, cv.Optional(CONF_DEBUG_OUTLINE_RUNS, default=False): cv.boolean, cv.Required(CONF_RUNS): cv.All( cv.ensure_list(RUN_SCHEMA), cv.Length(min=1) @@ -71,6 +77,14 @@ async def config_to_layout_item(pvariable_builder, item_config, child_item_build if text_align := item_config.get(CONF_TEXT_ALIGN): cg.add(var.set_text_align(text_align)) + if can_wrap_at_character_config := item_config.get(CONF_CAN_WRAP_AT_CHARACTER): + can_wrap_at_character = await cg.process_lambda( + can_wrap_at_character_config, + [(CanWrapAtCharacterArgumentsConstRef, "args")], + return_type=cg.bool_, + ) + cg.add(var.set_can_wrap_at(can_wrap_at_character)) + debug_outline_runs = item_config[CONF_DEBUG_OUTLINE_RUNS] if debug_outline_runs: cg.add(var.set_debug_outline_runs(debug_outline_runs))