Files

55 lines
1.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from __future__ import annotations
from typing import List, Tuple
from PIL import ImageDraw
from .base import SelectableList
from .item import ListItem
class ListView(SelectableList):
"""Compact scrolling list shows up to *max_visible* items at once.
The visible window is kept centred on the selected item and scrolls
as the selection moves.
``font_size`` is forwarded to :pymeth:`ListItem.render` so the
underlying render function can use it (e.g. for PIL ``draw.text``).
Pass ``None`` to let render functions use their own default.
"""
def __init__(self, *args, font_size: int | None = None, **kwargs):
super().__init__(*args, **kwargs)
self.font_size = font_size
def _get_visible_window(self) -> Tuple[List[ListItem], int]:
"""Return (visible_items, start_offset)."""
total = len(self._items)
if total <= self.max_visible:
return self._items, 0
start = max(0, self.selected_index - self.max_visible // 2)
start = min(start, total - self.max_visible)
end = start + self.max_visible
return self._items[start:end], start
def render(self, draw: ImageDraw.ImageDraw, y_start: int) -> None:
if not self._items:
return
visible_items, start = self._get_visible_window()
fs = self.font_size or 10
kwargs = {} if self.font_size is None else {'font_size': self.font_size}
for idx, item in enumerate(visible_items):
actual_idx = start + idx
y_pos = y_start + idx * self.item_height
if actual_idx == self.selected_index:
self._draw_highlight(draw, self.x_offset, y_pos + fs // 2, font_size=fs)
item.render(draw, (self.x_offset, y_pos), fill='white', **kwargs)
else:
item.render(draw, (self.x_offset, y_pos), fill='black', **kwargs)