"""The classroom's look: its measurements and its palette. The DVD control bar, Parent Call and the Presentations library all draw themselves, and they share this so they cannot drift apart: one set of measurements, one palette, one look. """ import os from pathlib import Path from classroom_config import scaled TEMPLATE = Path("/etc/ekklesia-classroom/overlay/style.css.in") # Every measurement in the template, at UI_SCALE=1.0. MEASUREMENTS = { "dock-radius": 24, "dock-padding-v": 8, "dock-padding-h": 10, "button-radius": 16, "button-padding": 6, "button-size": 44, "button-spinner": 38, "clock-radius": 16, "clock-padding-v": 7, "clock-padding-h": 12, "clock-font": 17, } def render(scale, template=None): """Resolve the measurement tokens in the stylesheet template.""" css = (template or TEMPLATE).read_text() for token, value in MEASUREMENTS.items(): css = css.replace(f"@{token}@", str(scaled(value, scale))) return css # ---------------------------------------------------------- the palette def load_colours(): """The session's own palette, read from the colour scheme in use. There is one set of design tokens in this classroom, and they live in a Plasma colour scheme. Reading them here rather than repeating them means this card follows classroom-theme light and dark without knowing that either exists. """ palette = { "window": "#141c20", "view": "#0f171a", "text": "#e6edef", "dim": "#93a5aa", "accent": "#4fb3a8", "on_accent": "#0e1518", "negative": "#e36a6a", "neutral": "#e0b15c", "positive": "#6fcf97", "line": "#25333a", } scheme = "EkklesiaDark" for path in ( os.path.expanduser("~/.config/kdeglobals"), "/etc/ekklesia-classroom/xdg/kdeglobals", "/etc/xdg/kdeglobals", ): try: with open(path, "r", encoding="utf-8") as handle: section = None for line in handle: line = line.strip() if line.startswith("["): section = line elif section and section.startswith("[General]") and \ line.startswith("ColorScheme="): scheme = line.split("=", 1)[1].strip() break except OSError: continue else: if scheme: break def rgb(value): parts = [part.strip() for part in value.split(",")] if len(parts) != 3: return None try: return "#%02x%02x%02x" % tuple(int(part) for part in parts) except ValueError: return None try: with open(f"/usr/share/color-schemes/{scheme}.colors", "r", encoding="utf-8") as handle: group = None for line in handle: line = line.strip() if line.startswith("["): group = line continue if "=" not in line or group is None: continue key, value = (part.strip() for part in line.split("=", 1)) colour = rgb(value) if colour is None: continue if group == "[Colors:Window]": if key == "BackgroundNormal": palette["window"] = colour elif key == "ForegroundNormal": palette["text"] = colour elif key == "ForegroundInactive": palette["dim"] = colour elif key == "ForegroundNegative": palette["negative"] = colour elif key == "ForegroundNeutral": palette["neutral"] = colour elif key == "ForegroundPositive": palette["positive"] = colour elif key == "BackgroundAlternate": palette["line"] = colour elif group == "[Colors:View]" and key == "BackgroundNormal": palette["view"] = colour elif group == "[Colors:Selection]": if key == "BackgroundNormal": palette["accent"] = colour elif key == "ForegroundNormal": palette["on_accent"] = colour except OSError: pass return palette