diff --git a/src/textual/demo/demo_app.py b/src/textual/demo/demo_app.py index abadf35da2..9fc391f96e 100644 --- a/src/textual/demo/demo_app.py +++ b/src/textual/demo/demo_app.py @@ -13,8 +13,8 @@ class DemoApp(App): CSS = """ .column { - align: center top; - &>*{ max-width: 100; } + align: center top; + &>*{ max-width: 100; } } Screen .-maximized { margin: 1 2; @@ -37,25 +37,25 @@ class DemoApp(App): Binding( "h", "app.switch_mode('home')", - "home", + "Home", tooltip="Show the home screen", ), Binding( "g", "app.switch_mode('game')", - "game", + "Game", tooltip="Unwind with a Textual game", ), Binding( "p", "app.switch_mode('projects')", - "projects", + "Projects", tooltip="A selection of Textual projects", ), Binding( "w", "app.switch_mode('widgets')", - "widgets", + "Widgets", tooltip="Test the builtin widgets", ), Binding( @@ -93,3 +93,13 @@ def action_maximize(self) -> None: title="Maximize", severity="warning", ) + + def check_action(self, action: str, parameters: tuple[object, ...]) -> bool | None: + """Disable switching to a mode we are already on.""" + if ( + action == "switch_mode" + and parameters + and self.current_mode == parameters[0] + ): + return None + return True diff --git a/src/textual/demo/game.py b/src/textual/demo/game.py index 8a8e6797e5..ecb33eead8 100644 --- a/src/textual/demo/game.py +++ b/src/textual/demo/game.py @@ -26,7 +26,7 @@ from textual.reactive import reactive from textual.screen import ModalScreen, Screen from textual.timer import Timer -from textual.widgets import Button, Digits, Footer, Select, Static +from textual.widgets import Button, Digits, Footer, Markdown, Select, Static @dataclass @@ -447,13 +447,13 @@ def action_move(self, direction: str) -> None: return blank = self.get_tile(None).position if direction == "up": - position = blank + (0, -1) - elif direction == "down": position = blank + (0, +1) + elif direction == "down": + position = blank + (0, -1) elif direction == "left": - position = blank + (-1, 0) - elif direction == "right": position = blank + (+1, 0) + elif direction == "right": + position = blank + (-1, 0) try: tile = self.get_tile_at(position) except IndexError: @@ -503,15 +503,54 @@ def on_tile_clicked(self, event: events.Click) -> None: self.move_tile(tile) +class GameInstructions(containers.VerticalGroup): + DEFAULT_CSS = """\ + GameInstructions { + layer: instructions; + width: 60; + background: $panel; + border: thick $primary-darken-2; + Markdown { + background: $panel; + } + + } + +""" + INSTRUCTIONS = """\ +# Instructions + +This is an implementation of the *sliding tile puzzle*. + +The board consists of a number of tiles and a blank space. +After shuffling, the goal is to restore the original "image" by moving a square either horizontally or vertically into the blank space. + +This version is like the physical game, but rather than an image, you need to restore code. + """ + + def compose(self) -> ComposeResult: + yield Markdown(self.INSTRUCTIONS) + with containers.Center(): + yield Button("New Game", action="screen.new_game", variant="success") + + class GameScreen(PageScreen): """The screen containing the game.""" + DEFAULT_CSS = """ + GameScreen{ + align: center middle; + layers: instructions game; + } + """ + BINDINGS = [ ("s", "shuffle", "Shuffle"), ("n", "new_game", "New Game"), ] def compose(self) -> ComposeResult: + yield GameInstructions() yield Game("\n" * 100, "", dimensions=(4, 4), tile_size=(16, 8)) yield Footer() @@ -532,8 +571,10 @@ async def new_game(self, new_game: NewGame | None) -> None: await game.recompose() game.focus() - def on_mount(self) -> None: - self.action_new_game() + def check_action(self, action: str, parameters: tuple[object, ...]) -> bool | None: + if action == "shuffle" and self.query_one(Game).state == "waiting": + return None + return True if __name__ == "__main__": diff --git a/src/textual/demo/page.py b/src/textual/demo/page.py index 35a98df387..4d5d15c13d 100644 --- a/src/textual/demo/page.py +++ b/src/textual/demo/page.py @@ -59,7 +59,7 @@ class PageScreen(Screen): Binding( "c", "show_code", - "show code", + "Show code", tooltip="Show the code used to generate this screen", ) ]