[display] Build on_page_change with build_callback_automation and compile it out when unused (#20456)

This commit is contained in:
J. Nick Koston
2026-10-11 09:23:05 -10:00
committed by GitHub
parent 78c7cd725d
commit c130e2808b
4 changed files with 32 additions and 42 deletions
+14 -16
View File
@@ -21,7 +21,6 @@ from esphome.const import (
CONF_PAGES,
CONF_ROTATION,
CONF_TO,
CONF_TRIGGER_ID,
CONF_UPDATE_INTERVAL,
CONF_WIDTH,
SCHEDULER_DONT_RUN,
@@ -39,14 +38,13 @@ DisplayPage = display_ns.class_("DisplayPage")
DisplayPagePtr = DisplayPage.operator("ptr")
DisplayRef = Display.operator("ref")
DisplayPageShowAction = display_ns.class_("DisplayPageShowAction", automation.Action)
DisplayOnPageChangeTrigger = display_ns.class_(
"DisplayOnPageChangeTrigger", automation.Trigger
)
CONF_ON_PAGE_CHANGE = "on_page_change"
CONF_SHOW_TEST_CARD = "show_test_card"
CONF_UNSPECIFIED = "unspecified"
_request_page_change_slot = cg.slot_counter("DISPLAY_PAGE_CHANGE_CALLBACK_COUNT")
DISPLAY_ROTATIONS = {
0: display_ns.DISPLAY_ROTATION_0_DEGREES,
90: display_ns.DISPLAY_ROTATION_90_DEGREES,
@@ -99,9 +97,6 @@ FULL_DISPLAY_SCHEMA = BASIC_DISPLAY_SCHEMA.extend(
),
cv.Optional(CONF_ON_PAGE_CHANGE): automation.validate_automation(
{
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
DisplayOnPageChangeTrigger
),
cv.Optional(CONF_FROM): cv.use_id(DisplayPage),
cv.Optional(CONF_TO): cv.use_id(DisplayPage),
}
@@ -137,15 +132,18 @@ async def setup_display_core_(var, config):
pages.append(page)
cg.add(var.set_pages(pages))
for conf in config.get(CONF_ON_PAGE_CHANGE, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
if CONF_FROM in conf:
page = await cg.get_variable(conf[CONF_FROM])
cg.add(trigger.set_from(page))
if CONF_TO in conf:
page = await cg.get_variable(conf[CONF_TO])
cg.add(trigger.set_to(page))
await automation.build_automation(
trigger, [(DisplayPagePtr, "from"), (DisplayPagePtr, "to")], conf
_request_page_change_slot(str(var))
checks = []
for key, name in ((CONF_FROM, "from"), (CONF_TO, "to")):
if (page_id := conf.get(key)) is not None:
page = await cg.get_variable(page_id)
checks.append(f"{name} == ::{page}")
await automation.build_callback_automation(
var,
"add_on_page_change_callback",
[(DisplayPagePtr, "from"), (DisplayPagePtr, "to")],
conf,
when=" && ".join(checks) or None,
)
if config.get(CONF_SHOW_TEST_CARD):
cg.add(var.show_test_card())
+7 -10
View File
@@ -678,12 +678,14 @@ void Display::set_pages(std::vector<DisplayPage *> pages) {
}
void Display::show_page(DisplayPage *page) {
this->previous_page_ = this->page_;
#ifdef DISPLAY_PAGE_CHANGE_CALLBACK_COUNT
DisplayPage *previous = this->page_;
this->page_ = page;
if (this->previous_page_ != this->page_) {
for (auto *t : on_page_change_triggers_)
t->process(this->previous_page_, this->page_);
}
if (previous != page)
this->page_change_callback_.call(previous, page);
#else
this->page_ = page;
#endif
}
void Display::do_update_() {
@@ -700,11 +702,6 @@ void Display::do_update_() {
this->clear_clipping_();
}
void DisplayOnPageChangeTrigger::process(DisplayPage *from, DisplayPage *to) {
if ((this->from_ == nullptr || this->from_ == from) && (this->to_ == nullptr || this->to_ == to))
this->trigger(from, to);
}
void Display::strftime(int x, int y, BaseFont *font, Color color, Color background, TextAlign align, const char *format,
ESPTime time) {
char buffer[64];
+10 -16
View File
@@ -7,6 +7,8 @@
#include "esphome/core/color.h"
#include "esphome/core/automation.h"
#include "esphome/core/defines.h"
#include "esphome/core/helpers.h"
#include "esphome/core/time.h"
#include "esphome/core/log.h"
#include "display_color_utils.h"
@@ -173,7 +175,6 @@ enum RegularPolygonDrawing {
class Display;
class DisplayPage;
class DisplayOnPageChangeTrigger;
/** Optimized display writer that uses function pointers for stateless lambdas.
*
@@ -702,7 +703,11 @@ class Display : public PollingComponent {
const DisplayPage *get_active_page() const { return this->page_; }
void add_on_page_change_trigger(DisplayOnPageChangeTrigger *t) { this->on_page_change_triggers_.push_back(t); }
#ifdef DISPLAY_PAGE_CHANGE_CALLBACK_COUNT
template<typename F> void add_on_page_change_callback(F &&callback) {
this->page_change_callback_.add(std::forward<F>(callback));
}
#endif
/// Internal method to set the display rotation with.
virtual void set_rotation(DisplayRotation rotation);
@@ -809,8 +814,9 @@ class Display : public PollingComponent {
DisplayRotation rotation_{DISPLAY_ROTATION_0_DEGREES};
display_writer_t writer_{};
DisplayPage *page_{nullptr};
DisplayPage *previous_page_{nullptr};
std::vector<DisplayOnPageChangeTrigger *> on_page_change_triggers_;
#ifdef DISPLAY_PAGE_CHANGE_CALLBACK_COUNT
StaticCallbackManager<DISPLAY_PAGE_CHANGE_CALLBACK_COUNT, void(DisplayPage *, DisplayPage *)> page_change_callback_;
#endif
bool auto_clear_enabled_{true};
std::vector<Rect> clipping_rectangle_;
uint8_t wdt_pixel_counter_{0};
@@ -850,18 +856,6 @@ template<typename... Ts> class DisplayPageShowAction final : public Action<Ts...
}
};
class DisplayOnPageChangeTrigger final : public Trigger<DisplayPage *, DisplayPage *> {
public:
explicit DisplayOnPageChangeTrigger(Display *parent) { parent->add_on_page_change_trigger(this); }
void process(DisplayPage *from, DisplayPage *to);
void set_from(DisplayPage *p) { this->from_ = p; }
void set_to(DisplayPage *p) { this->to_ = p; }
protected:
DisplayPage *from_{nullptr};
DisplayPage *to_{nullptr};
};
const LogString *text_align_to_string(TextAlign textalign);
} // namespace esphome::display
+1
View File
@@ -63,6 +63,7 @@
#define USE_DEEP_SLEEP_ON_WAKE
#define USE_DEVICES
#define USE_DISPLAY
#define DISPLAY_PAGE_CHANGE_CALLBACK_COUNT 1
#define USE_ENTITY_DEVICE_CLASS
#define USE_ENTITY_ICON
#define USE_ENTITY_UNIT_OF_MEASUREMENT