prole/installer/screen.py
chrisfu aad4c9c919 installer: switch workstation build to Docker, drop Vagrant
- Remove Vagrant from dependency checks and UI; use Docker for workstation build.\n- Add WORKSTATION_VERSION ARG + OCI version label in workstation/Dockerfile; tag image as prole-workstation:<version>.\n- Add installer.workstation helpers: parse version, compose canonical docker build (auto platform flags on Apple Silicon).\n- Refactor install.py Workstation page to display/execute docker build; write logs to logs/workstation-docker-<ts>.log; update summary links.\n- Update Deploy page copy: "Build workstation Docker image".\n- Centralize footer buttons styling/layout with installer.screen.create_nav_footer and use it from install.py.\n- Update installer package docs to describe Docker-based workstation helpers.
2025-12-03 22:55:21 -08:00

75 lines
2.8 KiB
Python

"""
Shared UI helpers for the Prole installer screens.
These routines are intentionally lightweight wrappers around the existing
Tk Canvas used by the installer, to reduce clutter in install.py.
"""
from __future__ import annotations
import tkinter as tk
from tkinter import ttk
def render_title(app, text: str, y: int = 40):
"""Render a section title on the main background canvas."""
if getattr(app, 'bg_canvas', None) is None:
return
item = app.bg_canvas.create_text(40, y, anchor='nw', text=text, fill='#111', font=('Helvetica Neue', 22, 'bold'))
app._canvas_items.append(item)
def render_paragraph(app, text: str, y: int, wrap: int = 860):
"""Render a paragraph on the main background canvas."""
if getattr(app, 'bg_canvas', None) is None:
return
item = app.bg_canvas.create_text(40, y, anchor='nw', text=text, fill='#1d1d1f', font=('Helvetica', 12), width=wrap)
app._canvas_items.append(item)
def create_nav_footer(parent, buttons: list[tuple[int, str]], commands: dict[int, callable] | None = None,
style_name: str = 'Nav.TButton') -> dict[int, ttk.Button]:
"""Create a right-aligned navigation footer with uniform button styling.
Parameters:
- parent: the container (typically the root installer container)
- buttons: list of (button_id, title) in the order to display
- commands: optional mapping of button_id -> callback function
- style_name: ttk style to apply to all buttons
Returns: {button_id: ttk.Button}
Examples:
create_nav_footer(footer, [(1, 'Next')])
create_nav_footer(footer, [(1, 'Prev'), (2, 'Next')])
create_nav_footer(footer, [(1, 'Exit')])
"""
# Ensure a consistent style for navigation buttons
try:
style = ttk.Style()
# Safe to call configure multiple times; last one wins
style.configure(style_name, padding=(12, 6), font=('Helvetica', 12))
except Exception:
pass
footer = ttk.Frame(parent)
footer.pack(fill='x', side='bottom')
# Flexible spacer to push buttons to the right
spacer = ttk.Frame(footer)
spacer.pack(side='left', expand=True, fill='x')
cmds = commands or {}
btn_map: dict[int, ttk.Button] = {}
for btn_id, title in buttons:
cmd = cmds.get(btn_id)
b = ttk.Button(footer, text=title, style=style_name, command=cmd)
# Right-aligned order (pack to the right in the declared order)
# Small extra right padding on the last (right-most) button
pad = (0, 20) if title.lower() in ('finish', 'exit', 'done') else (0, 8)
b.pack(side='right', padx=pad, pady=12)
btn_map[btn_id] = b
# Return both the frame and button map if needed later by callers
btn_map['_footer'] = footer # type: ignore[index]
return btn_map