nodes/menu.pyΒΆ

Part of Klondike Solitaire.

 1"""Title menu shown before the first deal.
 2
 3A full-rect ``Control`` that dims the table behind it and offers the two
 4entry points: a fresh deal, or resuming the save on disk (offered only when
 5a save file exists). Everything is anchored, so the card stays centred at
 6any window size.
 7"""
 8
 9from __future__ import annotations
10
11from collections.abc import Callable
12
13from simvx.core.ui import AnchorPreset, Button, Control, Label, Panel
14
15CARD_W = 520
16BUTTON_H = 46
17
18
19class TitleMenu(Control):
20    """Dimmed title card with New game / Continue / Quit."""
21
22    def __init__(
23        self, *, on_new_game: Callable[[], None], on_continue: Callable[[], None] | None, on_quit: Callable[[], None]
24    ) -> None:
25        super().__init__(name="TitleMenu")
26        self.set_anchor_preset(AnchorPreset.FULL_RECT)
27        self.z_index = 6000  # above the cards and the HUD
28
29        dim = self.add_child(Panel(name="Dim"))
30        dim.set_anchor_preset(AnchorPreset.FULL_RECT)
31        dim.bg_colour = (0.03, 0.12, 0.07, 0.72)
32
33        rows = [("New game", "MenuNewGame", on_new_game)]
34        if on_continue is not None:
35            rows.append(("Continue saved game", "MenuContinue", on_continue))
36        rows.append(("Quit", "MenuQuit", on_quit))
37
38        card_h = 190 + len(rows) * (BUTTON_H + 14)
39        card = self.add_child(Panel(name="Card"))
40        card.set_anchor_preset(AnchorPreset.CENTER)
41        card.margin_left, card.margin_right = -CARD_W * 0.5, CARD_W * 0.5
42        card.margin_top, card.margin_bottom = -card_h * 0.5, card_h * 0.5
43        card.bg_colour = (0.04, 0.09, 0.14, 0.94)
44
45        self._line(card, "Klondike Solitaire", top=26, height=44, size=32.0, colour=(1.0, 0.95, 0.6, 1.0), name="Title")
46        self._line(
47            card,
48            "SimVX port inspired by zaccnz/solitaire",
49            top=76,
50            height=22,
51            size=15.0,
52            colour=(0.82, 0.88, 0.94, 1.0),
53            name="Credit",
54        )
55
56        y = 120
57        for label, name, handler in rows:
58            button = card.add_child(Button(label, on_press=handler, name=name))
59            button.set_anchor_preset(AnchorPreset.TOP_WIDE)
60            button.margin_left, button.margin_right = 90, 90
61            button.margin_top, button.margin_bottom = y, y + BUTTON_H
62            button.font_size = 18.0
63            y += BUTTON_H + 14
64
65        self._line(
66            card,
67            "Drag cards onto piles, or click a card to auto-move it",
68            top=y + 8,
69            height=22,
70            size=14.0,
71            colour=(0.78, 0.85, 0.92, 1.0),
72            name="Hint",
73        )
74
75    def _line(
76        self,
77        parent: Control,
78        text: str,
79        *,
80        top: float,
81        height: float,
82        size: float,
83        colour: tuple[float, float, float, float],
84        name: str,
85    ) -> Label:
86        label = parent.add_child(Label(text, name=name))
87        label.set_anchor_preset(AnchorPreset.TOP_WIDE)
88        label.margin_top, label.margin_bottom = top, top + height
89        label.font_size = size
90        label.alignment = "center"
91        label.text_colour = colour
92        return label
93
94
95__all__ = ["TitleMenu"]