Resolution-flexible UI: render SSD1333 (176×176) and SSD1351 (128×128) from shared geometry#453
Merged
Merged
Conversation
…from shared geometry Adapt the PiFinder UI to render at the display's resolution instead of a hardcoded 128x128, so the 1.91" 176x176 SSD1333 and the 1.5" 128x128 SSD1351 share one codebase. Geometry (row counts, line positions, text anchors, image scaling, entry-box grids, scroll bars) derives from display_class.resX/resY + font metrics; a small set of per-display knobs (font sizes, titlebar_height, menu_visible_items) is hand-tuned per panel. - ui/layout.py (new): carousel_layout / list_layout / rows_below_titlebar / center_box_row -- the shared geometry helpers. - displays.py: Layout176 mixin + DisplayPygame_176 / DisplayHeadless176; menu_visible_items knob (must be odd). - Screens derive layout from resolution: base, text_menu, object_list, object_details, chart, preview, align, console, status, sqm, equipment, software, log, location_list, the time/date/location/radec/text entry grids, and the SQM calibration/sweep/correction screens, ui_utils. - Three 176-panel fixes from hardware validation: carousel selection box keeps clearance from the row above; help screens normalize to the device resolution (no luma size-assert crash); the radial marking-menu radius scales with resolution so labels stay inside their slices. - docs/adr/0009 + docs/ax/ui: the hybrid (derive geometry + per-display knobs) decision. Boot splash (splash.py) is intentionally deferred to new_hardware_features: its panel auto-detection needs hardware_detect (the rev-4 battery marker), which isn't on main yet, and on main the splash is always 128 (scaling would be a no-op). Validated at 128 and 176: ruff + mypy clean (pre-existing pandas/requests stub errors only); pytest -m "smoke or unit" -> 285 passed; a crash-sweep of 16 screens through the real device.display() path renders cleanly at both resolutions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
brickbots
added a commit
that referenced
this pull request
Jun 5, 2026
The focus-quality (HFD) strip was added in #449 before the resolution-flexible UI work in #453. #453 converted the camera preview's image resize and star selectors to derive from the display resolution but never touched draw_focus_strip(), which kept 128-only literals: strip_top = 90 # bottom-band top plot_top = +9 # V-curve top clearance plot_bottom = -10 # V-curve bottom clearance bottom label = -9 On the 176x176 SSD1333 panel strip_top=90 lands mid-screen (~51% down) instead of as a bottom band, stranding the exposure/matched-star labels high up with a large empty gap above the readout, and the bottom detected-star label clips at the screen edge. Derive the geometry instead (ADR 0009): - strip_top: a fixed fraction of screen height (res_y - res_y*38/128), so the band stays ~30% of the screen on any panel. - label-row clearances: from self.fonts.small.height, so the rows track the (larger) small font on the 176 panel and never collide with the V-curve. The 128 small font is 9 px, so strip_top+9 == strip_top+small_h, res_y-10 == res_y-small_h-1, and res_y-9 == res_y-small_h: the 128 layout is reproduced pixel-for-pixel (zero regression), while the 176 layout becomes a correct proportional bottom band. Verified headless on both DisplayHeadless (128) and DisplayHeadless176 (176). Docs: update the CONTEXT.md focus-strip glossary entry, which described a fixed "~38 px" band, to note it scales with the display. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adapts the UI to render at the display's resolution instead of a hardcoded 128×128, so the new 1.91″ 176×176 SSD1333 and the existing 1.5″ 128×128 SSD1351 share one codebase. Layout (row counts, line positions, text anchors, image scaling, entry-box grids, scroll bars) derives from
display_class.resX/resY+ font metrics; a small set of per-display knobs (font sizes,titlebar_height,menu_visible_items) is hand-tuned per panel. The hybrid approach (derive geometry + per-display knobs) is recorded indocs/adr/0009-resolution-flexible-ui-hybrid.md.What's in it (29 files, +1032 / −423)
ui/layout.py(new) — the geometry engine:carousel_layout,list_layout,rows_below_titlebar,center_box_row.displays.py—Layout176mixin,DisplayPygame_176/DisplayHeadless176, themenu_visible_itemsknob (must be odd).image.size == device.sizeassert crash on 176);docs/adr/0009+docs/ax/ui— the hybrid decision + resolution terminology.Deferred to
new_hardware_featuressplash.py) is intentionally not in this PR. Its panel auto-detection depends onhardware_detect(the rev-4 battery marker), which isn't onmainyet; and onmainthe splash always runs at 128, so the resolution scaling would be a no-op. It lands with NHF.Validation (at both 128 and 176)
ruff check+ruff formatclean;mypyclean (only pre-existing pandas/requests stub errors inplot.py/comets.py/software.py).pytest -m "smoke or unit"→ 285 passed.device.display()path renders cleanly at 128 and 176 (every screen produces aresX×resYimage the device accepts).Notes for reviewers
main(post the SSD1333 base merge). Independent ofnew_hardware_features.main's versions here; onlypreview.pyneeded manual work (main's focus-strip rework had replaced the reticle the resolution patch targeted). A quick on-panel pass on the re-derived screens is worthwhile before merge.🤖 Generated with Claude Code