Source code for abacura.widgets.resizehandle

from __future__ import annotations

from rich.segment import Segment

from textual import log, events
from textual.geometry import Offset, Size
from textual.strip import Strip
from textual.widget import Widget



from typing import TYPE_CHECKING, Literal


[docs]class ResizeHandle(Widget): """A handle for resizing a panel. This is a child of the panel, and is positioned on the edge of the panel. The panel can use min-width, min-height, max-width, and max-height to limit the size. """ DEFAULT_CSS = """ ResizeHandle { width: auto; height: auto; background: $panel; color: rgba(128,128,128,0); } ResizeHandle:hover { background: $panel-lighten-1; color: rgba(128,128,128,0.3); } ResizeHandle.-active { background: $panel-darken-1; } """ def __init__( self, target: Widget, side: Literal["left", "right", "top", "bottom"], *, name: str | None = None, id: str | None = None, classes: str | None = None, disabled: bool = False ) -> None: super().__init__(name=name, id=id, classes=classes, disabled=disabled) self._target = target self._resizing = False self._start_size: Size | None = None self._start_mouse_position: Offset | None = None self._side: Literal["left", "right", "top", "bottom"] = side self._horizontal_resize = side in ("left", "right") self.styles.dock = side # type: ignore
[docs] def on_mouse_down(self, event: events.MouseDown) -> None: if self.disabled or self._resizing: return self.capture_mouse() self._resizing = True self._start_size = self._target.outer_size self._start_mouse_position = event.screen_offset self.add_class("-active")
[docs] def on_mouse_up(self, event: events.MouseUp) -> None: self.release_mouse() self._resizing = False self._start_size = None self._start_mouse_position = None self.remove_class("-active")
[docs] def on_mouse_move(self, event: events.MouseMove) -> None: if not self._resizing: return assert self._start_size is not None and self._start_mouse_position is not None diff = event.screen_offset - self._start_mouse_position match self._side: case "left": self._target.styles.width = self._start_size.width - diff.x case "right": self._target.styles.width = self._start_size.width + diff.x case "top": self._target.styles.height = self._start_size.height - diff.y case "bottom": self._target.styles.height = self._start_size.height + diff.y
[docs] def get_content_width(self, container: Size, viewport: Size) -> int: return container.width if not self._horizontal_resize else 1
[docs] def get_content_height(self, container: Size, viewport: Size, width: int) -> int: return container.height if self._horizontal_resize else 1
[docs] def render_line(self, y: int) -> Strip: # char = "⣿" if self._horizontal_resize else "⠶" # char = "┃" if self._horizontal_resize else "━" # char = "│" if self._horizontal_resize else "─" char = "║" if self._horizontal_resize else "═" * self.size.width return Strip([Segment(char, self.rich_style)])