You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
spiel/spiel/deck.py

98 lines
3.0 KiB
Python

from __future__ import annotations
from collections.abc import Callable, Iterator, Mapping, Sequence
from dataclasses import dataclass, field
from typing import Type, overload
from spiel.slide import Content, Slide
from spiel.transitions.protocol import Transition
from spiel.transitions.swipe import Swipe
@dataclass
class Deck(Sequence[Slide]):
"""
Represents a "deck" of "slides": a presentation.
"""
name: str
"""The name of the [`Deck`][spiel.Deck], which will be displayed in the footer."""
default_transition: Type[Transition] | None = Swipe
"""\
The default slide transition animation;
used if the slide being moved to does not specify its own transition.
Defaults to the [`Swipe`][spiel.Swipe] transition.
Set to `None` for no transition animation.
"""
_slides: list[Slide] = field(default_factory=list)
def slide(
self,
title: str = "",
bindings: Mapping[str, Callable[..., None]] | None = None,
transition: Type[Transition] | None = None,
) -> Callable[[Content], Content]:
"""
A decorator that creates a new slide in the deck,
with the decorated function as the [`Slide.content`][spiel.Slide.content].
Args:
title: The title to display for the slide.
bindings: A mapping of
[keys](https://textual.textualize.io/guide/input/#key)
to callables to be executed when those keys are pressed,
when on this slide.
transition: The transition animation to use when moving to this slide.
Set to `None` to use the
[`Deck.default_transition`][spiel.Deck.default_transition]
of the deck this slide is in.
"""
def slideify(content: Content) -> Content:
self.add_slides(
Slide(
title=title,
content=content,
bindings=bindings or {},
transition=transition,
)
)
return content
return slideify
def add_slides(self, *slides: Slide) -> None:
"""
Add `Slide`s to a `Deck`.
This function is primarily useful when adding multiple slides at once,
probably generated programmatically.
If adding a single slide, prefer the [`Deck.slide`][spiel.Deck.slide] decorator.
Args:
*slides: The `Slide`s to add.
"""
self._slides.extend(slides)
def __len__(self) -> int:
return len(self._slides)
@overload
def __getitem__(self, item: int) -> Slide:
return self._slides[item]
@overload
def __getitem__(self, item: slice) -> Sequence[Slide]:
return self._slides[item]
def __getitem__(self, item: int | slice) -> Slide | Sequence[Slide]:
return self._slides[item]
def __iter__(self) -> Iterator[Slide]:
yield from self._slides
def __contains__(self, item: object) -> bool:
return item in self._slides