Files
website/tools/content/tui/image_picker.py
T

69 lines
2.6 KiB
Python

from rich.text import Text
from textual import on
from textual.app import ComposeResult
from textual.binding import Binding
from textual.containers import Vertical
from textual.screen import ModalScreen
from textual.widgets import Input, Label, OptionList
from textual.widgets.option_list import Option
import static_images
class ImagePicker(ModalScreen[str | None]):
BINDINGS = [
Binding("escape", "cancel", "Cancel"),
Binding("down", "focus_list", "List", show=False),
]
def __init__(self, current: str = "", start_filter: str = ""):
super().__init__()
self.current = current
self.start_filter = start_filter
self.images: list[dict] = []
def compose(self) -> ComposeResult:
with Vertical(classes="dialog picker"):
yield Label("Pick an image from static/", classes="dialog-title")
yield Input(value=self.start_filter, placeholder="Type to filter, Enter to pick", id="image-filter")
yield OptionList(id="image-list")
yield Label("", id="image-count", classes="field-label")
def on_mount(self):
self.images = static_images.list_images()
self.show_images(self.start_filter)
def show_images(self, text: str):
query = text.strip().lower()
matches = [image for image in self.images if query in image["path"].lower()]
option_list = self.query_one(OptionList)
option_list.clear_options()
option_list.add_options(
Option(Text.assemble(image["path"], (" " + static_images.format_size(image["size"]), "dim")), id=image["path"])
for image in matches
)
current_index = next((index for index, image in enumerate(matches) if image["path"] == self.current), 0)
if matches:
option_list.highlighted = current_index
self.query_one("#image-count", Label).update(f"{len(matches)} of {len(self.images)} images")
@on(Input.Changed, "#image-filter")
def filter_changed(self, event: Input.Changed):
self.show_images(event.value)
@on(Input.Submitted, "#image-filter")
def pick_highlighted(self):
option_list = self.query_one(OptionList)
if option_list.highlighted is not None and option_list.option_count:
self.dismiss(option_list.get_option_at_index(option_list.highlighted).id)
@on(OptionList.OptionSelected)
def pick_option(self, event: OptionList.OptionSelected):
self.dismiss(event.option.id)
def action_focus_list(self):
self.query_one(OptionList).focus()
def action_cancel(self):
self.dismiss(None)