/kivymd/snackbar.py
https://gitlab.com/nickyspag/KivyMD · Python · 115 lines · 102 code · 12 blank · 1 comment · 11 complexity · e601b8c4d6c6316dcb8a4cb2804ef372 MD5 · raw file
- # -*- 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