193 lines
7.1 KiB
Python
193 lines
7.1 KiB
Python
|
|
from LUIObject import LUIObject
|
|
from LUILayouts import LUIHorizontalStretchedLayout
|
|
from LUILabel import LUILabel
|
|
from LUIInitialState import LUIInitialState
|
|
|
|
__all__ = ["LUIButton"]
|
|
|
|
|
|
class LUIButton(LUIObject):
|
|
|
|
""" Simple button, containing three sprites and a label. """
|
|
|
|
def __init__(self, text="Button", template="ButtonDefault", **kwargs):
|
|
""" Constructs a new button. The template controls which sprites to use.
|
|
If the template is "ButtonDefault" for example, the sprites
|
|
"ButtonDefault_Left", "ButtonDefault" and "ButtonDefault_Right" will
|
|
be used. The sprites used when the button is pressed should be named
|
|
"ButtonDefaultFocus_Left" and so on then.
|
|
|
|
If an explicit width is set on the button, the button will stick to
|
|
that width, otherwise it will automatically resize to fit the label """
|
|
LUIObject.__init__(self, x=0, y=0, solid=True)
|
|
self._template = template
|
|
self._layout = LUIHorizontalStretchedLayout(
|
|
parent=self, prefix=self._template, width="100%")
|
|
self._label = LUILabel(parent=self, text=text)
|
|
self._label.z_offset = 1
|
|
self._label.center_vertical = True
|
|
self._label.margin = 0, 20, 0, 20
|
|
self.margin.left = -1
|
|
self._hovered = False
|
|
self._pressed = False
|
|
self._use_custom_texture = False
|
|
self._custom_texture = None
|
|
self._custom_uv = None
|
|
self._custom_texture_hover = None
|
|
self._custom_uv_hover = None
|
|
self._custom_texture_pressed = None
|
|
self._custom_uv_pressed = None
|
|
LUIInitialState.init(self, kwargs)
|
|
|
|
def _apply_stretch_sizes(self):
|
|
"""Ensure internal sprites stretch to the button size."""
|
|
try:
|
|
layout = getattr(self, '_layout', None)
|
|
if layout is not None:
|
|
if hasattr(layout, 'width'):
|
|
layout.width = "100%"
|
|
if hasattr(layout, 'height'):
|
|
layout.height = "100%"
|
|
inner = getattr(layout, '_layout', None)
|
|
if inner is not None:
|
|
if hasattr(inner, 'width'):
|
|
inner.width = "100%"
|
|
if hasattr(inner, 'height'):
|
|
inner.height = "100%"
|
|
for attr in ('_sprite_left', '_sprite_mid', '_sprite_right'):
|
|
spr = getattr(layout, attr, None)
|
|
if spr is not None:
|
|
if hasattr(spr, 'height'):
|
|
spr.height = "100%"
|
|
if attr == '_sprite_mid' and hasattr(spr, 'width'):
|
|
spr.width = "100%"
|
|
except Exception:
|
|
pass
|
|
|
|
def _apply_custom_texture(self, state="normal"):
|
|
"""Apply custom texture based on state: normal/hover/pressed."""
|
|
if not self._use_custom_texture:
|
|
return
|
|
|
|
tex = None
|
|
uv = None
|
|
if state == "pressed" and self._custom_texture_pressed is not None:
|
|
tex = self._custom_texture_pressed
|
|
uv = self._custom_uv_pressed
|
|
elif state == "hover" and self._custom_texture_hover is not None:
|
|
tex = self._custom_texture_hover
|
|
uv = self._custom_uv_hover
|
|
else:
|
|
tex = self._custom_texture
|
|
uv = self._custom_uv
|
|
|
|
if tex is None:
|
|
return
|
|
|
|
layout = getattr(self, "_layout", None)
|
|
if layout is None:
|
|
return
|
|
for attr in ("_sprite_left", "_sprite_mid", "_sprite_right"):
|
|
spr = getattr(layout, attr, None)
|
|
if spr is None:
|
|
continue
|
|
try:
|
|
if hasattr(spr, "set_texture"):
|
|
spr.set_texture(tex, resize=False)
|
|
if uv and hasattr(spr, "set_uv_range"):
|
|
u0, v0, u1, v1 = uv
|
|
spr.set_uv_range(u0, v0, u1, v1)
|
|
except Exception:
|
|
pass
|
|
|
|
# Hide left/right caps for single-image mode
|
|
try:
|
|
if hasattr(layout, "_sprite_left") and layout._sprite_left is not None:
|
|
layout._sprite_left.width = 0
|
|
if hasattr(layout, "_sprite_right") and layout._sprite_right is not None:
|
|
layout._sprite_right.width = 0
|
|
except Exception:
|
|
pass
|
|
|
|
self._apply_stretch_sizes()
|
|
|
|
def set_custom_textures(self, normal_tex, normal_uv=None, hover_tex=None, hover_uv=None, pressed_tex=None, pressed_uv=None):
|
|
"""Set custom textures for normal/hover/pressed states."""
|
|
self._use_custom_texture = True
|
|
self._custom_texture = normal_tex
|
|
self._custom_uv = normal_uv
|
|
self._custom_texture_hover = hover_tex
|
|
self._custom_uv_hover = hover_uv
|
|
self._custom_texture_pressed = pressed_tex
|
|
self._custom_uv_pressed = pressed_uv
|
|
if self._hovered:
|
|
self._apply_custom_texture("hover")
|
|
else:
|
|
self._apply_custom_texture("normal")
|
|
|
|
def set_custom_texture(self, texture, uv=None):
|
|
"""Use a single texture for the button background."""
|
|
self.set_custom_textures(texture, uv, None, None, None, None)
|
|
|
|
def clear_custom_texture(self):
|
|
"""Restore default template textures."""
|
|
self._use_custom_texture = False
|
|
self._custom_texture = None
|
|
self._custom_uv = None
|
|
self._custom_texture_hover = None
|
|
self._custom_uv_hover = None
|
|
self._custom_texture_pressed = None
|
|
self._custom_uv_pressed = None
|
|
try:
|
|
self._layout.prefix = self._template
|
|
self._apply_stretch_sizes()
|
|
except Exception:
|
|
pass
|
|
|
|
@property
|
|
def text(self):
|
|
""" Returns the current label text of the button """
|
|
return self._label.text
|
|
|
|
@text.setter
|
|
def text(self, text):
|
|
""" Sets the label text of the button """
|
|
self._label.text = text
|
|
|
|
def on_mousedown(self, event):
|
|
""" Internal on_mousedown handler. Do not override """
|
|
self._pressed = True
|
|
if self._use_custom_texture:
|
|
self._apply_custom_texture("pressed")
|
|
else:
|
|
self._layout.prefix = self._template + "Focus"
|
|
self._apply_stretch_sizes()
|
|
self._label.margin.top = 1
|
|
|
|
def on_mouseup(self, event):
|
|
""" Internal on_mouseup handler. Do not override """
|
|
self._pressed = False
|
|
if self._use_custom_texture:
|
|
if self._hovered:
|
|
self._apply_custom_texture("hover")
|
|
else:
|
|
self._apply_custom_texture("normal")
|
|
else:
|
|
self._layout.prefix = self._template
|
|
self._apply_stretch_sizes()
|
|
self._label.margin.top = 0
|
|
|
|
def on_mouseover(self, event):
|
|
""" Internal mouseover handler """
|
|
self._hovered = True
|
|
if self._use_custom_texture and not self._pressed:
|
|
self._apply_custom_texture("hover")
|
|
|
|
def on_mouseout(self, event):
|
|
""" Internal mouseout handler """
|
|
self._hovered = False
|
|
self._pressed = False
|
|
if self._use_custom_texture:
|
|
self._apply_custom_texture("normal")
|