mirror of
https://github.com/esphome/esphome.git
synced 2024-12-13 08:54:54 +01:00
Add support for text alignment to TextPanel
This commit is contained in:
parent
255d851125
commit
fa27e8eafc
3 changed files with 76 additions and 4 deletions
|
@ -8,6 +8,8 @@ namespace esphome {
|
||||||
namespace graphical_layout {
|
namespace graphical_layout {
|
||||||
|
|
||||||
static const char *const TAG = "textpanel";
|
static const char *const TAG = "textpanel";
|
||||||
|
static const int TEXT_ALIGN_X_MASK = (int)display::TextAlign::RIGHT | (int)display::TextAlign::CENTER_HORIZONTAL;
|
||||||
|
static const int TEXT_ALIGN_Y_MASK = (int)display::TextAlign::BOTTOM | (int)display::TextAlign::BASELINE | (int)display::TextAlign::CENTER_VERTICAL;
|
||||||
|
|
||||||
void TextPanel::dump_config(int indent_depth, int additional_level_depth) {
|
void TextPanel::dump_config(int indent_depth, int additional_level_depth) {
|
||||||
ESP_LOGCONFIG(TAG, "%*sText: %s", indent_depth, "", this->text_.c_str());
|
ESP_LOGCONFIG(TAG, "%*sText: %s", indent_depth, "", this->text_.c_str());
|
||||||
|
@ -18,15 +20,61 @@ display::Rect TextPanel::measure_item_internal(display::Display *display) {
|
||||||
int y1;
|
int y1;
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
|
display->get_text_bounds(0, 0, this->text_.c_str(), this->font_, this->text_align_, &x1, &y1, &width,
|
||||||
display->get_text_bounds(0, 0, this->text_.c_str(), this->font_, display::TextAlign::TOP_LEFT, &x1, &y1, &width,
|
|
||||||
&height);
|
&height);
|
||||||
|
|
||||||
return display::Rect(0, 0, width, height);
|
return display::Rect(0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextPanel::render_internal(display::Display *display, display::Rect bounds) {
|
void TextPanel::render_internal(display::Display *display, display::Rect bounds) {
|
||||||
display->print(0, 0, this->font_, this->foreground_color_, display::TextAlign::TOP_LEFT, this->text_.c_str());
|
int width, height, x_offset, baseline;
|
||||||
|
|
||||||
|
this->font_->measure(this->text_.c_str(), &width, &x_offset, &baseline, &height);
|
||||||
|
|
||||||
|
const auto x_align = display::TextAlign(int(this->text_align_) & TEXT_ALIGN_X_MASK);
|
||||||
|
const auto y_align = display::TextAlign(int(this->text_align_) & TEXT_ALIGN_Y_MASK);
|
||||||
|
|
||||||
|
display::Rect text_bounds(0, 0, bounds.w, bounds.h);
|
||||||
|
|
||||||
|
switch (x_align) {
|
||||||
|
case display::TextAlign::RIGHT: {
|
||||||
|
bounds.x = bounds.w - width;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case display::TextAlign::CENTER_HORIZONTAL: {
|
||||||
|
bounds.x = (bounds.w - width) / 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case display::TextAlign::LEFT:
|
||||||
|
default: {
|
||||||
|
// LEFT
|
||||||
|
bounds.x = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (y_align) {
|
||||||
|
case display::TextAlign::BOTTOM: {
|
||||||
|
bounds.y = bounds.h - height;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case display::TextAlign::BASELINE: {
|
||||||
|
bounds.y = (bounds.h - height) + baseline;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case display::TextAlign::CENTER_VERTICAL: {
|
||||||
|
bounds.y = (bounds.h - height) / 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case display::TextAlign::TOP:
|
||||||
|
default: {
|
||||||
|
bounds.y = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rendered_alignment = display::TextAlign::TOP_LEFT;
|
||||||
|
display->print(bounds.x, bounds.y, this->font_, this->foreground_color_, rendered_alignment, this->text_.c_str());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace graphical_layout
|
} // namespace graphical_layout
|
||||||
|
|
|
@ -23,11 +23,13 @@ class TextPanel : public LayoutItem {
|
||||||
void set_font(display::BaseFont *font) { this->font_ = font; };
|
void set_font(display::BaseFont *font) { this->font_ = font; };
|
||||||
void set_foreground_color(Color foreground_color) { this->foreground_color_ = foreground_color; };
|
void set_foreground_color(Color foreground_color) { this->foreground_color_ = foreground_color; };
|
||||||
void set_background_color(Color background_color) { this->background_color_ = background_color; };
|
void set_background_color(Color background_color) { this->background_color_ = background_color; };
|
||||||
|
void set_text_align(display::TextAlign text_align) { this->text_align_ = text_align; };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int item_padding_{0};
|
int item_padding_{0};
|
||||||
std::string text_{};
|
std::string text_{};
|
||||||
display::BaseFont *font_{nullptr};
|
display::BaseFont *font_{nullptr};
|
||||||
|
display::TextAlign text_align_{display::TextAlign::TOP_LEFT};
|
||||||
Color foreground_color_{COLOR_ON};
|
Color foreground_color_{COLOR_ON};
|
||||||
Color background_color_{COLOR_OFF};
|
Color background_color_{COLOR_OFF};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.components import font, color
|
from esphome.components import font, color
|
||||||
|
from esphome.components.display import display_ns
|
||||||
|
|
||||||
graphical_layout_ns = cg.esphome_ns.namespace("graphical_layout")
|
graphical_layout_ns = cg.esphome_ns.namespace("graphical_layout")
|
||||||
TextPanel = graphical_layout_ns.class_("TextPanel")
|
TextPanel = graphical_layout_ns.class_("TextPanel")
|
||||||
|
TextAlign = display_ns.enum("TextAlign", is_class=True)
|
||||||
|
|
||||||
CONF_ITEM_PADDING = "item_padding"
|
CONF_ITEM_PADDING = "item_padding"
|
||||||
CONF_TEXT_PANEL = "text_panel"
|
CONF_TEXT_PANEL = "text_panel"
|
||||||
|
@ -11,8 +13,24 @@ CONF_FONT = "font"
|
||||||
CONF_FOREGROUND_COLOR = "foreground_color"
|
CONF_FOREGROUND_COLOR = "foreground_color"
|
||||||
CONF_BACKGROUND_COLOR = "background_color"
|
CONF_BACKGROUND_COLOR = "background_color"
|
||||||
CONF_TEXT = "text"
|
CONF_TEXT = "text"
|
||||||
|
CONF_TEXT_ALIGN = "text_align"
|
||||||
|
|
||||||
|
|
||||||
|
TEXT_ALIGN = {
|
||||||
|
"TOP_LEFT": TextAlign.TOP_LEFT,
|
||||||
|
"TOP_CENTER": TextAlign.TOP_CENTER,
|
||||||
|
"TOP_RIGHT": TextAlign.TOP_RIGHT,
|
||||||
|
"CENTER_LEFT": TextAlign.CENTER_LEFT,
|
||||||
|
"CENTER": TextAlign.CENTER,
|
||||||
|
"CENTER_RIGHT": TextAlign.CENTER_RIGHT,
|
||||||
|
"BASELINE_LEFT": TextAlign.BASELINE_LEFT,
|
||||||
|
"BASELINE_CENTER": TextAlign.BASELINE_CENTER,
|
||||||
|
"BASELINE_RIGHT": TextAlign.BASELINE_RIGHT,
|
||||||
|
"BOTTOM_LEFT": TextAlign.BOTTOM_LEFT,
|
||||||
|
"BOTTOM_CENTER": TextAlign.BOTTOM_CENTER,
|
||||||
|
"BOTTOM_RIGHT": TextAlign.BOTTOM_RIGHT,
|
||||||
|
}
|
||||||
|
|
||||||
def get_config_schema(base_item_schema, item_type_schema):
|
def get_config_schema(base_item_schema, item_type_schema):
|
||||||
return base_item_schema.extend(
|
return base_item_schema.extend(
|
||||||
{
|
{
|
||||||
|
@ -22,6 +40,7 @@ def get_config_schema(base_item_schema, item_type_schema):
|
||||||
cv.Optional(CONF_FOREGROUND_COLOR): cv.use_id(color.ColorStruct),
|
cv.Optional(CONF_FOREGROUND_COLOR): cv.use_id(color.ColorStruct),
|
||||||
cv.Optional(CONF_BACKGROUND_COLOR): cv.use_id(color.ColorStruct),
|
cv.Optional(CONF_BACKGROUND_COLOR): cv.use_id(color.ColorStruct),
|
||||||
cv.Required(CONF_TEXT): cv.templatable(cv.string),
|
cv.Required(CONF_TEXT): cv.templatable(cv.string),
|
||||||
|
cv.Optional(CONF_TEXT_ALIGN): cv.enum(TEXT_ALIGN, upper=True)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -46,4 +65,7 @@ async def config_to_layout_item(pvariable_builder, item_config, child_item_build
|
||||||
text = await cg.templatable(item_config[CONF_TEXT], args=[], output_type=str)
|
text = await cg.templatable(item_config[CONF_TEXT], args=[], output_type=str)
|
||||||
cg.add(var.set_text(text))
|
cg.add(var.set_text(text))
|
||||||
|
|
||||||
|
if text_align := item_config.get(CONF_TEXT_ALIGN):
|
||||||
|
cg.add(var.set_text_align(text_align))
|
||||||
|
|
||||||
return var
|
return var
|
||||||
|
|
Loading…
Reference in a new issue