Forty-eight tiles, a tile over the whole page and tiles that go to a page (0.2.74)

Max asked for many more tiles, a tile that takes the whole page as a light
switch you push without looking, and tiles that go to a page. The limit is
one tile per slot of the eight pages, 48, and the firmware keeps its tile
list on the heap sized to the layout (PSRAM on a Guition). A tile's size can
be `full`: one big button that lights up in the state colour while on, or the
double-width card's head with its small slider, direct controls or graph at
the bottom and the value the double-width card had no room for in between;
the clock, the forecast (with an hours strip) and the sun path fill the page.
Navigation tiles are the built-in entities screen.page_1 to screen.page_8:
an arrow or a chosen icon, the name and "Page n", a tap opens that page.
The app sends the three only to firmware 0.2.62+, the editor (the Vue port of
this round by the editor session, 00c9a4e) offers Normal / Double-width /
Full page and "Goes to page", and Claude in Home Assistant gets size: full and
the page tiles. Built-in tiles now send a chosen icon as its codepoint.

Found and fixed by the new host harness before release: the one-second tick
moved the analog clock's second hand (part 18) on a full forecast's hour label
during a page switch and corrupted it. Firmware 0.2.62; both C++ and Python
suites, host harness 37/37 on both boards, hardware pass on both bench boards
in docs/TEST_RESULTS_0274.md.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Max Gramser
2026-09-18 08:44:44 +02:00
parent 00c9a4e4f3
commit bb25353089
29 changed files with 948 additions and 128 deletions
+11 -7
View File
@@ -2,7 +2,8 @@
The list lives in screen_manager/app/tile_icons.py. Every Material Design Icons
font of a board profile gets exactly those glyphs (the first font carries the
list as a YAML anchor, the smaller sizes reuse it), and the editor gets a subset
list as a YAML anchor, the smaller sizes reuse it); the big font of the full-page
card (id ending in _big) gets tile_icons.BIG_GLYPHS as its own anchor, and the editor gets a subset
of the same TTF so its mockup shows the glyphs the screen draws. The top bar
mockup also gets Roboto 400/500 with the glyphs of header_bar.GLYPHS, so text
widths in the editor match the screen. Run tools/generate_packages.py afterwards;
@@ -45,18 +46,21 @@ def verify():
if len(tile_icons.ICONS) != sum(len(icons) for _, icons in tile_icons.GROUPS):
raise SystemExit('An icon appears in more than one group')
def glyph_list():
lines = [' glyphs: &tile_icons # GENERATED by tools/generate_icons.py from screen_manager/app/tile_icons.py']
lines += [f' - "\\U000{code}" # {name}' for name, code in tile_icons.GLYPHS.items()]
def glyph_list(anchor='tile_icons', names=None):
lines = [f' glyphs: &{anchor} # GENERATED by tools/generate_icons.py from screen_manager/app/tile_icons.py']
chosen = tile_icons.GLYPHS if names is None else {name: tile_icons.GLYPHS[name] for name in names}
lines += [f' - "\\U000{code}" # {name}' for name, code in chosen.items()]
return '\n'.join(lines) + '\n'
def profile(text):
blocks = list(FONT_BLOCK.finditer(text))
if len(blocks) != 3:
raise SystemExit(f'Expected three icon fonts, found {len(blocks)}')
if len(blocks) != 4:
raise SystemExit(f'Expected four icon fonts, found {len(blocks)}')
out, last = [], 0
for index, block in enumerate(blocks):
out += [text[last:block.start()], block[1], glyph_list() if index == 0 else ' glyphs: *tile_icons\n']
big = re.search(r'id: \w+_big\n', block[1])
glyphs = glyph_list('tile_icons_big', tile_icons.BIG_GLYPHS) if big else glyph_list() if index == 0 else ' glyphs: *tile_icons\n'
out += [text[last:block.start()], block[1], glyphs]
last = block.end()
return ''.join(out) + text[last:]