116 lines
4.1 KiB
Python
116 lines
4.1 KiB
Python
|
# -*- coding: utf-8 -*-
|
||
|
from collections import deque
|
||
|
from kivy.animation import Animation
|
||
|
from kivy.clock import Clock
|
||
|
from kivy.core.window import Window
|
||
|
from kivy.lang import Builder
|
||
|
from kivy.metrics import dp
|
||
|
from kivy.properties import ObjectProperty, StringProperty, NumericProperty
|
||
|
from kivy.uix.relativelayout import RelativeLayout
|
||
|
from kivymd.material_resources import DEVICE_TYPE
|
||
|
|
||
|
Builder.load_string('''
|
||
|
#:import Window kivy.core.window.Window
|
||
|
#:import get_color_from_hex kivy.utils.get_color_from_hex
|
||
|
#:import MDFlatButton kivymd.button.MDFlatButton
|
||
|
#:import MDLabel kivymd.label.MDLabel
|
||
|
#:import DEVICE_TYPE kivymd.material_resources.DEVICE_TYPE
|
||
|
<_SnackbarWidget>
|
||
|
canvas:
|
||
|
Color:
|
||
|
rgb: get_color_from_hex('323232')
|
||
|
Rectangle:
|
||
|
size: self.size
|
||
|
size_hint_y: None
|
||
|
size_hint_x: 1 if DEVICE_TYPE == 'mobile' else None
|
||
|
height: dp(48) if _label.texture_size[1] < dp(30) else dp(80)
|
||
|
width: dp(24) + _label.width + _spacer.width + root.padding_right if root.button_text == '' else dp(24) + \
|
||
|
_label.width + _spacer.width + _button.width + root.padding_right
|
||
|
top: 0
|
||
|
x: 0 if DEVICE_TYPE == 'mobile' else Window.width/2 - self.width/2
|
||
|
BoxLayout:
|
||
|
width: Window.width - root.padding_right - _spacer.width - dp(24) if DEVICE_TYPE == 'mobile' and \
|
||
|
root.button_text == '' else Window.width - root.padding_right - _button.width - _spacer.width - dp(24) \
|
||
|
if DEVICE_TYPE == 'mobile' else _label.texture_size[0] if (dp(568) - root.padding_right - _button.width - \
|
||
|
_spacer.width - _label.texture_size[0] - dp(24)) >= 0 else (dp(568) - root.padding_right - _button.width - \
|
||
|
_spacer.width - dp(24))
|
||
|
size_hint_x: None
|
||
|
x: dp(24)
|
||
|
MDLabel:
|
||
|
id: _label
|
||
|
text: root.text
|
||
|
size: self.texture_size
|
||
|
BoxLayout:
|
||
|
id: _spacer
|
||
|
size_hint_x: None
|
||
|
x: _label.right
|
||
|
width: 0
|
||
|
MDFlatButton:
|
||
|
id: _button
|
||
|
text: root.button_text
|
||
|
size_hint_x: None
|
||
|
x: _spacer.right if root.button_text != '' else root.right
|
||
|
center_y: root.height/2
|
||
|
on_release: root.button_callback()
|
||
|
''')
|
||
|
|
||
|
|
||
|
class _SnackbarWidget(RelativeLayout):
|
||
|
text = StringProperty()
|
||
|
button_text = StringProperty()
|
||
|
button_callback = ObjectProperty()
|
||
|
duration = NumericProperty()
|
||
|
padding_right = NumericProperty(dp(24))
|
||
|
|
||
|
def __init__(self, text, duration, button_text='', button_callback=None,
|
||
|
**kwargs):
|
||
|
super(_SnackbarWidget, self).__init__(**kwargs)
|
||
|
self.text = text
|
||
|
self.button_text = button_text
|
||
|
self.button_callback = button_callback
|
||
|
self.duration = duration
|
||
|
self.ids['_label'].text_size = (None, None)
|
||
|
|
||
|
def begin(self):
|
||
|
if self.button_text == '':
|
||
|
self.remove_widget(self.ids['_button'])
|
||
|
else:
|
||
|
self.ids['_spacer'].width = dp(16) if \
|
||
|
DEVICE_TYPE == "mobile" else dp(40)
|
||
|
self.padding_right = dp(16)
|
||
|
Window.add_widget(self)
|
||
|
anim = Animation(y=0, duration=.3, t='out_quad')
|
||
|
anim.start(self)
|
||
|
Clock.schedule_once(lambda dt: self.die(), self.duration)
|
||
|
|
||
|
def die(self):
|
||
|
anim = Animation(top=0, duration=.3, t='out_quad')
|
||
|
anim.bind(on_complete=lambda *args: _play_next(self))
|
||
|
anim.bind(on_complete=lambda *args: Window.remove_widget(self))
|
||
|
anim.start(self)
|
||
|
|
||
|
|
||
|
queue = deque()
|
||
|
playing = False
|
||
|
|
||
|
|
||
|
def make(text, button_text=None, button_callback=None, duration=3):
|
||
|
if button_text is not None and button_callback is not None:
|
||
|
queue.append(_SnackbarWidget(text=text,
|
||
|
button_text=button_text,
|
||
|
button_callback=button_callback,
|
||
|
duration=duration))
|
||
|
else:
|
||
|
queue.append(_SnackbarWidget(text=text,
|
||
|
duration=duration))
|
||
|
_play_next()
|
||
|
|
||
|
|
||
|
def _play_next(dying_widget=None):
|
||
|
global playing
|
||
|
if (dying_widget or not playing) and len(queue) > 0:
|
||
|
playing = True
|
||
|
queue.popleft().begin()
|
||
|
elif len(queue) == 0:
|
||
|
playing = False
|