Files
katrain-qt/katrain/gui/widgets/selection_slider.py
T
2020-06-21 11:53:15 +02:00

137 lines
4.2 KiB
Python

from kivy.lang import Builder
from kivy.uix.widget import Widget
from kivy.properties import (
NumericProperty,
ListProperty,
BooleanProperty,
)
from kivymd.uix.label import MDLabel
from kivymd.uix.selectioncontrol import Thumb
class SelectionSlider(Widget):
__events__ = ["on_select"]
active = BooleanProperty(False)
hint = BooleanProperty(True)
index = NumericProperty(0) # selected index
values = ListProperty([(0, "")]) # (value:numeric,label:string) pairs
normalized_pos = NumericProperty(0) # slider relative pos from 0-1
px_pos = NumericProperty(0) # actual px pos
padding = NumericProperty("16sp")
track_color = ListProperty([1, 1, 1, 0.3])
thumb_color = ListProperty([0.5, 0.5, 0.5, 1])
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.bind(
size=self.set_index_and_positions,
pos=self.set_index_and_positions,
values=self.set_index_and_positions,
index=self.set_index_and_positions,
)
def set_index_and_positions(self, *_args):
self.index = max(0, min(self.index, len(self.values) - 1))
self.normalized_pos = self.index / (len(self.values) - 1)
self.px_pos = self.x + self.padding + self.normalized_pos * (self.width - 2 * self.padding)
@property
def value(self):
return self.values[self.index][0]
def set_value(self, set_value): # set to closest value
eq_value = sorted([(abs(v - set_value), i) for i, (v, l) in enumerate(self.values)])
self.index = eq_value[0][1]
def set_from_pos(self, pos):
norm_value = (pos[0] - self.x - self.padding) / (self.width - 2 * self.padding)
self.index = round(norm_value * (len(self.values) - 1))
def on_touch_down(self, touch):
if self.disabled or not self.collide_point(*touch.pos):
return
if touch.is_mouse_scrolling:
if "down" in touch.button or "left" in touch.button:
self.index += 1
if "up" in touch.button or "right" in touch.button:
self.index -= 1
else:
touch.grab(self)
self.active = True
self.set_from_pos(touch.pos)
return True
def on_touch_move(self, touch):
if touch.grab_current == self:
self.set_from_pos(touch.pos)
return True
def on_touch_up(self, touch):
if touch.grab_current == self:
self.set_from_pos(touch.pos)
self.active = False
self.dispatch("on_select", self.value)
return True
def on_select(self, value):
pass
KV = """
#:import i18n katrain.core.lang.i18n
<SelectionSlider>:
id: slider
canvas:
Clear
Color:
rgba:
self.track_color
Rectangle:
size:
(self.width - self.padding*2, dp(4))
pos:
(self.x + self.padding, self.center_y - dp(4))
Color:
rgba:
self.thumb_color
Rectangle:
size:
((self.width-self.padding*2)*self.normalized_pos, sp(4))
pos:
(self.x + self.padding, self.center_y - dp(4))
Thumb:
id: thumb
size_hint: None, None
size:
((dp(24), dp(24)) if root.active else (dp(16), dp(16)))
pos:
(slider.px_pos - dp(8), slider.center_y - thumb.height/2 - dp(2))
color:
root.thumb_color
elevation:
4 if root.active else 2
MDCard:
id: hint_box
size_hint: None, None
md_bg_color: [1, 1, 1, 1] if root.active else [0, 0, 0, 0]
elevation: 4 if root.active else 0
size:
(max(dp(28), label.texture_size[0]+4) , dp(28))
pos:
(slider.px_pos - dp(9), slider.center_y - hint_box.height / 2 + dp(30))
Label:
id: label
text: slider.values[slider.index][1]
font_size: dp(12)
lang_change_tracking: i18n._('') # for font
halign: "center"
color: root.thumb_color if root.active else [0, 0, 0, 0]
"""
Builder.load_string(KV)