mirror of
https://github.com/esphome/esphome.git
synced 2024-12-12 08:24:55 +01:00
Add the FixedDimensionPanel
This renders a single child (you'd likely want that child to be a Vertical or Horizontal Stack Panel) with constrained dimensions. For example to achieve a fixed two column 50/50 display you could have a layout of; Root - Horizontal Stack - Fixed Dimension (50% display width) - Vertical Stack - Text, Display, etc... - Fixed Dimension (50% display width) - Vertical Stack - More elements...
This commit is contained in:
parent
1b411a55e4
commit
46285b20f8
4 changed files with 115 additions and 1 deletions
|
@ -6,6 +6,7 @@ from . import horizontal_stack
|
|||
from . import vertical_stack
|
||||
from . import text_panel
|
||||
from . import display_rendering_panel
|
||||
from . import fixed_dimension_panel
|
||||
|
||||
graphical_layout_ns = cg.esphome_ns.namespace("graphical_layout")
|
||||
RootLayoutComponent = graphical_layout_ns.class_("RootLayoutComponent", cg.Component)
|
||||
|
@ -51,6 +52,9 @@ ITEM_TYPE_SCHEMA = cv.typed_schema(
|
|||
display_rendering_panel.CONF_DISPLAY_RENDERING_PANEL: display_rendering_panel.get_config_schema(
|
||||
BASE_ITEM_SCHEMA, item_type_schema
|
||||
),
|
||||
fixed_dimension_panel.CONF_FIXED_DIMENSION_PANEL: fixed_dimension_panel.get_config_schema(
|
||||
BASE_ITEM_SCHEMA, item_type_schema
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -59,6 +63,7 @@ CODE_GENERATORS = {
|
|||
horizontal_stack.CONF_HORIZONTAL_STACK: horizontal_stack.config_to_layout_item,
|
||||
vertical_stack.CONF_VERTICAL_STACK: vertical_stack.config_to_layout_item,
|
||||
display_rendering_panel.CONF_DISPLAY_RENDERING_PANEL: display_rendering_panel.config_to_layout_item,
|
||||
fixed_dimension_panel.CONF_FIXED_DIMENSION_PANEL: fixed_dimension_panel.config_to_layout_item,
|
||||
}
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
|
@ -100,6 +105,7 @@ async def to_code(config):
|
|||
)
|
||||
cg.add(var.set_layout_root(layout_var))
|
||||
else:
|
||||
raise f"Do not know how to build type {layout_type}"
|
||||
err = f"Do not know how to build type {layout_type}"
|
||||
raise RuntimeError(f"Do not know how to build type {layout_type}")
|
||||
|
||||
cg.add_define("USE_GRAPHICAL_LAYOUT")
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
#include "fixed_dimension_panel.h"
|
||||
|
||||
#include "esphome/components/display/display.h"
|
||||
#include "esphome/components/display/rect.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace graphical_layout {
|
||||
|
||||
static const char *const TAG = "fixeddimensionpanel";
|
||||
|
||||
void FixedDimensionPanel::dump_config(int indent_depth, int additional_level_depth) {
|
||||
ESP_LOGCONFIG(TAG, "%*sWidth: %i (Will use display width: %s)", indent_depth, "", this->width_.value(), YESNO(this->width_.value() < 1));
|
||||
ESP_LOGCONFIG(TAG, "%*sHeight: %i (Will use display height: %s)", indent_depth, "", this->height_.value(), YESNO(this->height_.value() < 1));
|
||||
this->child_->dump_config(indent_depth + additional_level_depth, additional_level_depth);
|
||||
}
|
||||
|
||||
display::Rect FixedDimensionPanel::measure_item_internal(display::Display *display) {
|
||||
display::Rect rect(0, 0, this->width_.value(), this->height_.value());
|
||||
if (rect.w < 1) {
|
||||
rect.w = display->get_width();
|
||||
}
|
||||
if (rect.h < 1) {
|
||||
rect.h = display->get_height();
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
|
||||
void FixedDimensionPanel::render_internal(display::Display *display, display::Rect bounds) {
|
||||
this->child_->render_internal(display, bounds);
|
||||
}
|
||||
|
||||
} // namespace graphical_layout
|
||||
} // namespace esphome
|
28
esphome/components/graphical_layout/fixed_dimension_panel.h
Normal file
28
esphome/components/graphical_layout/fixed_dimension_panel.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#include "esphome/components/graphical_layout/graphical_layout.h"
|
||||
#include "esphome/core/automation.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace graphical_layout {
|
||||
|
||||
/** The FixedDimensionPanel is a UI element which will render a single child with constrained dimensions
|
||||
*/
|
||||
class FixedDimensionPanel : public LayoutItem {
|
||||
public:
|
||||
display::Rect measure_item_internal(display::Display *display) override;
|
||||
void render_internal(display::Display *display, display::Rect bounds) override;
|
||||
void dump_config(int indent_depth, int additional_level_depth) override;
|
||||
|
||||
void set_child(LayoutItem *child) { this->child_ = child; };
|
||||
template<typename V> void set_width(V width) { this->width_ = width; };
|
||||
template<typename V> void set_height(V height) { this->height_ = height; }
|
||||
|
||||
protected:
|
||||
LayoutItem *child_{nullptr};
|
||||
TemplatableValue<int> width_{0};
|
||||
TemplatableValue<int> height_{0};
|
||||
};
|
||||
|
||||
} // namespace graphical_layout
|
||||
} // namespace esphome
|
46
esphome/components/graphical_layout/fixed_dimension_panel.py
Normal file
46
esphome/components/graphical_layout/fixed_dimension_panel.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_TYPE, CONF_WIDTH, CONF_HEIGHT
|
||||
|
||||
graphical_layout_ns = cg.esphome_ns.namespace("graphical_layout")
|
||||
FixedDimensionPanel = graphical_layout_ns.class_("FixedDimensionPanel")
|
||||
|
||||
CONF_ITEM_PADDING = "item_padding"
|
||||
CONF_FIXED_DIMENSION_PANEL = "fixed_dimension_panel"
|
||||
CONF_CHILD = "child"
|
||||
|
||||
|
||||
def get_config_schema(base_item_schema, item_type_schema):
|
||||
return base_item_schema.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(FixedDimensionPanel),
|
||||
cv.Optional(CONF_ITEM_PADDING, default=0): cv.int_,
|
||||
cv.Required(CONF_CHILD): item_type_schema,
|
||||
cv.Optional(CONF_WIDTH, default=-1): cv.templatable(cv.int_range(min=-1)),
|
||||
cv.Optional(CONF_HEIGHT, default=-1): cv.templatable(cv.int_range(min=-1)),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def config_to_layout_item(pvariable_builder, item_config, child_item_builder):
|
||||
var = await pvariable_builder(item_config)
|
||||
|
||||
width = await cg.templatable(item_config[CONF_WIDTH], args=[], output_type=cg.int_)
|
||||
cg.add(var.set_width(width))
|
||||
|
||||
height = await cg.templatable(
|
||||
item_config[CONF_HEIGHT], args=[], output_type=cg.int_
|
||||
)
|
||||
cg.add(var.set_height(height))
|
||||
|
||||
child_item_config = item_config[CONF_CHILD]
|
||||
child_item_type = child_item_config[CONF_TYPE]
|
||||
if child_item_type in child_item_builder:
|
||||
child_item_var = await child_item_builder[child_item_type](
|
||||
pvariable_builder, child_item_config, child_item_builder
|
||||
)
|
||||
cg.add(var.set_child(child_item_var))
|
||||
else:
|
||||
raise f"Do not know how to build type {child_item_type}"
|
||||
|
||||
return var
|
Loading…
Reference in a new issue