69 lines
2.6 KiB
Python
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)
|