L3-Bataille-Navale/source/gui/widget/Scroller.py

121 lines
3.2 KiB
Python

from typing import TYPE_CHECKING, Callable, Any
import pyglet.image
from source.gui.sprite import Sprite
from source.gui.widget.abc import BoxWidget
from source.type import Distance, Percentage
from source.utils import dict_prefix
if TYPE_CHECKING:
from source.gui.scene.abc import Scene
class Scroller(BoxWidget):
def __init__(self, scene: "Scene",
texture_background: pyglet.image.AbstractImage,
texture_cursor: pyglet.image.AbstractImage,
x: Distance = 0,
y: Distance = 0,
width: Distance = None,
height: Distance = None,
from_: float = 0,
value: float = 0.5,
to: float = 1,
cursor_width: Distance = 0.1,
text_transform: Callable[[float], Any] = lambda value: value,
**kwargs):
super().__init__(scene, x, y, width, height)
self.cursor_width = cursor_width
self.text_transform = text_transform
self.background = Sprite(
img=texture_background,
**dict_prefix("background_", kwargs)
)
self.cursor = Sprite(
img=texture_cursor,
**dict_prefix("cursor_", kwargs)
)
self.label = pyglet.text.Label(
anchor_x="center", anchor_y="center",
**dict_prefix("label_", kwargs)
)
self._from = from_
self._to = to
self.value = value
# refresh
def _refresh(self):
# background
self.background.x, self.background.y = self.x, self.y
self.background.width, self.background.height = self.width, self.height
# cursor
self.cursor.width = self.width * self.cursor_width
self.cursor.height = self.height
self.cursor.y = self.y
self.cursor.x = (
# the base offset
self.x
# position the cursor relatively to the start and the end of the range
+ (self.value - self.from_) / (self.to - self.from_) * self.background.width
# center the cursor with its own width
- (self.cursor.width / 2)
)
# label
self.label.x = self.x + (self.width / 2)
self.label.y = self.y + (self.height / 2)
self.label.text = str(self.text_transform(self.value))
# property
def on_pressed(self, rel_x: int, rel_y: int, button: int, modifiers: int):
self.value = rel_x / self.width
@property
def value(self):
return self._value
@value.setter
def value(self, value: float):
if not self.from_ <= value <= self.to: raise ValueError(f"The value is not in range")
self._value = value
self._refresh()
@property
def from_(self):
return self._from
@from_.setter
def from_(self, from_: float):
self._from = from_
self._refresh()
@property
def to(self):
return self._to
@to.setter
def to(self, to: float):
self._to = to
self._refresh()
# event
def on_resize(self, width: int, height: int):
self._refresh()
def draw(self):
self.background.draw()
self.cursor.draw()
self.label.draw()