Add clock, forecast, graph, sun, timer and person cards with wide tiles
Any tile can now be double width: pack() in runtime_model.h places wide tiles in the left column and the manager preview follows the same rules. New cards: built-in clock (digital or analog, screen.clock), five-day weather forecast on a wide weather card fed by weather.get_forecasts, history sparkline for sensors, sunrise/sunset (sun.sun), live kitchen timer (timer.*, tap starts or pauses) and presence (person.*). The manager pre-computes time-zone and forecast extras in a new 'x' object and refuses layouts with new domains until the screen runs 0.2.14. The self-test follows the packing, checks custom card parts and wide widths, and diagnostics/send_layout.py pushes a demo layout of every card type for render checks without Home Assistant. App 0.2.12, firmware 0.2.14. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -30,3 +30,30 @@ int main() {
|
||||
for(size_t i=0;i<m.count;++i){m.tiles[i].received=true;m.tiles[i].state="off";}
|
||||
assert(m.ready());
|
||||
}
|
||||
// Built-in and new Home Assistant domains, plus wide-tile packing.
|
||||
static void test_domains_and_packing() {
|
||||
using namespace runtime_tiles;
|
||||
Model m; bool changed = false;
|
||||
assert(valid_entity("screen.clock") && !valid_entity("screen.other"));
|
||||
assert(valid_entity("sun.sun") && valid_entity("timer.kitchen") && valid_entity("person.max"));
|
||||
assert(m.set_layout({"screen.clock", "weather.home", "light.a", "sensor.b", "person.max", "timer.egg", "sun.sun"}, "Thuis", changed));
|
||||
assert(m.tiles[0].available() && !m.tiles[1].available()); // built-in cards need no HA state
|
||||
m.tiles[4].state = "home"; assert(m.tiles[4].active());
|
||||
m.tiles[5].state = "active"; assert(m.tiles[5].active());
|
||||
m.tiles[5].state = "idle"; assert(!m.tiles[5].active());
|
||||
std::array<Placement, MAX_TILES> p;
|
||||
assert(pack(m.tiles, 0, p) == 1);
|
||||
assert(pack(m.tiles, m.count, p) == 2 && p[6].page == 1 && p[6].slot == 0);
|
||||
// A wide tile after a left-column tile skips the right column.
|
||||
m.tiles[1].wide = true;
|
||||
assert(pack(m.tiles, m.count, p) == 2);
|
||||
assert(p[0].slot == 0 && p[1].slot == 2 && p[2].slot == 4 && p[3].slot == 5);
|
||||
assert(p[4].page == 1 && p[4].slot == 0 && p[6].page == 1 && p[6].slot == 2);
|
||||
// Wide tiles ending exactly on a page boundary do not open an empty page.
|
||||
for (auto &t : m.tiles) t.wide = false;
|
||||
m.tiles[0].wide = m.tiles[2].wide = true;
|
||||
assert(pack(m.tiles, 3, p) == 1 && p[0].slot == 0 && p[1].slot == 2 && p[2].slot == 4);
|
||||
m.tiles[3].wide = true;
|
||||
assert(pack(m.tiles, 4, p) == 2 && p[3].page == 1 && p[3].slot == 0);
|
||||
}
|
||||
struct RunExtra { RunExtra() { test_domains_and_packing(); } } run_extra;
|
||||
|
||||
Reference in New Issue
Block a user