PyBitmessage/src/kivymd/snackbar.py

116 lines
4.1 KiB
Python
Raw Normal View History

# -*- 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