Add first implementation of a DisplayRenderingPanel

Makes use of a standard display_writer_t style Lambda so users can use arbitrary APIs from the Display Rendering Engine within the layout engine
This commit is contained in:
Michael Davidson 2023-12-19 22:38:02 +11:00
parent 5c2c8935ce
commit 00caf53dc4
No known key found for this signature in database
GPG key ID: B8D1A99712B8B0EB
4 changed files with 95 additions and 0 deletions

View file

@ -5,6 +5,7 @@ from esphome.const import CONF_ID
from . import horizontal_stack
from . import vertical_stack
from . import text_panel
from . import display_rendering_panel
graphical_layout_ns = cg.esphome_ns.namespace("graphical_layout")
RootLayoutComponent = graphical_layout_ns.class_("RootLayoutComponent", cg.Component)
@ -68,6 +69,14 @@ ITEM_TYPE_SCHEMA = cv.typed_schema(
),
}
),
display_rendering_panel.CONF_TYPE: BASE_ITEM_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(display_rendering_panel.DisplayRenderingPanel),
cv.Required(display_rendering_panel.CONF_WIDTH): cv.templatable(cv.int_range(min=1)),
cv.Required(display_rendering_panel.CONF_HEIGHT): cv.templatable(cv.int_range(min=1)),
cv.Required(display_rendering_panel.CONF_LAMBDA): cv.lambda_,
}
),
}
)
@ -75,6 +84,7 @@ CODE_GENERATORS = {
text_panel.CONF_TYPE: text_panel.config_to_layout_item,
horizontal_stack.CONF_TYPE: horizontal_stack.config_to_layout_item,
vertical_stack.CONF_TYPE: vertical_stack.config_to_layout_item,
display_rendering_panel.CONF_TYPE: display_rendering_panel.config_to_layout_item,
}
CONFIG_SCHEMA = cv.Schema(

View file

@ -0,0 +1,26 @@
#include "display_rendering_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 = "displayrenderingpanel";
void DisplayRenderingPanel::dump_config(int indent_depth, int additional_level_depth) {
ESP_LOGCONFIG(TAG, "%*sDimensions: %ix%i", indent_depth, "", this->width_, this->height_);
ESP_LOGCONFIG(TAG, "%*sHas drawing lambda: %s", indent_depth, "", YESNO(this->lambda_ != nullptr));
}
const display::Rect DisplayRenderingPanel::measure_item(display::Display *display) {
return display::Rect(0, 0, this->width_, this->width_);
}
void DisplayRenderingPanel::render(display::Display *display, display::Rect bounds) {
this->lambda_(*display);
}
} // namespace graphical_layout
} // namespace esphome

View file

@ -0,0 +1,32 @@
#pragma once
#include "esphome/components/graphical_layout/graphical_layout.h"
#include "esphome/components/font/font.h"
namespace esphome {
namespace graphical_layout {
/* See display.h for original declaration */
using display_writer_t = std::function<void(display::Display &)>;
/** The DisplayRenderingPanel is a UI item that renders a custom lambda to the display whilst
* participating in the layout process
*/
class DisplayRenderingPanel : public LayoutItem {
public:
const display::Rect measure_item(display::Display *display);
void render(display::Display *display, display::Rect bounds);
void dump_config(int indent_depth, int additional_level_depth);
void set_width(int width) { this->width_ = width; };
void set_height(int height) { this->height_ = height; };
void set_lambda(display_writer_t lambda) { this->lambda_ = lambda; };
protected:
int width_{0};
int height_{0};
display_writer_t lambda_{nullptr};
};
} // namespace graphical_layout
} // namespace esphome

View file

@ -0,0 +1,27 @@
import esphome.codegen as cg
from esphome.const import CONF_ID
from esphome.components.display import DisplayRef
graphical_layout_ns = cg.esphome_ns.namespace("graphical_layout")
DisplayRenderingPanel = graphical_layout_ns.class_("DisplayRenderingPanel")
CONF_TYPE = "display_rendering_panel"
CONF_HEIGHT = "height"
CONF_WIDTH = "width"
CONF_LAMBDA = "lambda"
async def config_to_layout_item(item_config, child_item_builder):
var = cg.new_Pvariable(item_config[CONF_ID])
width = await cg.templatable(item_config[CONF_WIDTH], args=[], output_type=int)
cg.add(var.set_width(width))
height = await cg.templatable(item_config[CONF_HEIGHT], args=[], output_type=int)
cg.add(var.set_height(height))
lambda_ = await cg.process_lambda(
item_config[CONF_LAMBDA], [(DisplayRef, "it")], return_type=cg.void
)
cg.add(var.set_lambda(lambda_))
return var