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
This commit is contained in:
Michael Davidson 2023-12-31 13:03:26 +11:00
parent 046065b307
commit feef234ddd
No known key found for this signature in database
GPG key ID: B8D1A99712B8B0EB
3 changed files with 22 additions and 8 deletions

View file

@ -28,7 +28,7 @@ void TextRunPanel::dump_config(int indent_depth, int additional_level_depth) {
void TextRunPanel::setup_complete() { void TextRunPanel::setup_complete() {
if (!this->can_wrap_at_character_.has_value()) { if (!this->can_wrap_at_character_.has_value()) {
ESP_LOGD(TAG, "No custom can_wrap_at_character provided. Will use default implementation"); 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); 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.offset = i;
can_wrap_at_args.character = text.at(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) { if (can_wrap) {
ESP_LOGVV(TAG, "Can break at '%c'. String is '%s'", can_wrap_at_args.character, partial_line.c_str()); 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; calculated_layout->bounds.h += total_y_offset;
} }
bool TextRunPanel::default_can_wrap_at_character(CanWrapAtCharacterArguments *args) { bool TextRunPanel::default_can_wrap_at_character(const CanWrapAtCharacterArguments &args) {
switch (args->character) { switch (args.character) {
case ' ': case ' ':
case '\t': case '\t':
case '\n': case '\n':

View file

@ -37,8 +37,8 @@ class TextRun {
TemplatableValue<std::string> text_{}; TemplatableValue<std::string> text_{};
display::BaseFont *font_{nullptr}; display::BaseFont *font_{nullptr};
Color foreground_color_{display::COLOR_ON}; Color foreground_color_{COLOR_ON};
Color background_color_{display::COLOR_OFF}; Color background_color_{COLOR_OFF};
}; };
class CalculatedTextRun { class CalculatedTextRun {
@ -72,7 +72,7 @@ class TextRunPanel : public LayoutItem {
void dump_config(int indent_depth, int additional_level_depth) override; void dump_config(int indent_depth, int additional_level_depth) override;
void setup_complete() 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); CalculatedLayout determine_layout(display::Display *display, display::Rect bounds, bool apply_alignment);
void apply_alignment_to_layout(CalculatedLayout *layout); void apply_alignment_to_layout(CalculatedLayout *layout);
@ -92,7 +92,7 @@ class TextRunPanel : public LayoutItem {
display::TextAlign text_align_{display::TextAlign::TOP_LEFT}; display::TextAlign text_align_{display::TextAlign::TOP_LEFT};
int min_width_{0}; int min_width_{0};
int max_width_{0}; int max_width_{0};
TemplatableValue<bool, CanWrapAtCharacterArguments *> can_wrap_at_character_{}; TemplatableValue<bool, const CanWrapAtCharacterArguments &> can_wrap_at_character_{};
bool debug_outline_runs_{false}; bool debug_outline_runs_{false};
}; };

View file

@ -8,6 +8,10 @@ graphical_layout_ns = cg.esphome_ns.namespace("graphical_layout")
TextRunPanel = graphical_layout_ns.class_("TextRunPanel") TextRunPanel = graphical_layout_ns.class_("TextRunPanel")
TextAlign = display_ns.enum("TextAlign", is_class=True) TextAlign = display_ns.enum("TextAlign", is_class=True)
TextRun = graphical_layout_ns.class_("TextRun") 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_TEXT_RUN_PANEL = "text_run_panel"
CONF_FONT = "font" CONF_FONT = "font"
@ -16,6 +20,7 @@ CONF_TEXT_ALIGN = "text_align"
CONF_MAX_WIDTH = "max_width" CONF_MAX_WIDTH = "max_width"
CONF_MIN_WIDTH = "min_width" CONF_MIN_WIDTH = "min_width"
CONF_RUNS = "runs" CONF_RUNS = "runs"
CONF_CAN_WRAP_AT_CHARACTER = "can_wrap_at_character"
CONF_DEBUG_OUTLINE_RUNS = "debug_outline_runs" CONF_DEBUG_OUTLINE_RUNS = "debug_outline_runs"
TEXT_ALIGN = { 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.Optional(CONF_TEXT_ALIGN): cv.enum(TEXT_ALIGN, upper=True),
cv.Required(CONF_MAX_WIDTH): cv.int_range(min=0), 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_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.Optional(CONF_DEBUG_OUTLINE_RUNS, default=False): cv.boolean,
cv.Required(CONF_RUNS): cv.All( cv.Required(CONF_RUNS): cv.All(
cv.ensure_list(RUN_SCHEMA), cv.Length(min=1) 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): if text_align := item_config.get(CONF_TEXT_ALIGN):
cg.add(var.set_text_align(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] debug_outline_runs = item_config[CONF_DEBUG_OUTLINE_RUNS]
if debug_outline_runs: if debug_outline_runs:
cg.add(var.set_debug_outline_runs(debug_outline_runs)) cg.add(var.set_debug_outline_runs(debug_outline_runs))