signage-ng/signage/fader.py

166 lines
5.4 KiB
Python
Raw Permalink Normal View History

2018-09-05 21:03:23 +00:00
import time
import random
from kivy.clock import Clock
from kivy.uix.screenmanager import ScreenManager, FadeTransition
from kivy.uix.screenmanager import Screen as BaseScreen
2018-09-06 15:45:36 +00:00
from kivy.uix.relativelayout import RelativeLayout
import kivy.uix.screenmanager
from kivy.properties import StringProperty, NumericProperty, BooleanProperty, ObjectProperty, OptionProperty
class NodeBehavior(object):
'''Screen is an element intended to be used with a :class:`ScreenManager`.
Check module documentation for more information.
:Events:
`on_pre_enter`: ()
Event fired when the screen is about to be used: the entering
animation is started.
`on_enter`: ()
Event fired when the screen is displayed: the entering animation is
complete.
`on_pre_leave`: ()
Event fired when the screen is about to be removed: the leaving
animation is started.
`on_leave`: ()
Event fired when the screen is removed: the leaving animation is
finished.
.. versionchanged:: 1.6.0
Events `on_pre_enter`, `on_enter`, `on_pre_leave` and `on_leave` were
added.
'''
name = StringProperty('')
'''
Name of the screen which must be unique within a :class:`ScreenManager`.
This is the name used for :attr:`ScreenManager.current`.
:attr:`name` is a :class:`~kivy.properties.StringProperty` and defaults to
''.
'''
manager = ObjectProperty(None, allownone=True)
''':class:`ScreenManager` object, set when the screen is added to a
manager.
:attr:`manager` is an :class:`~kivy.properties.ObjectProperty` and
defaults to None, read-only.
'''
transition_progress = NumericProperty(0.)
'''Value that represents the completion of the current transition, if any
is occurring.
If a transition is in progress, whatever the mode, the value will change
from 0 to 1. If you want to know if it's an entering or leaving animation,
check the :attr:`transition_state`.
:attr:`transition_progress` is a :class:`~kivy.properties.NumericProperty`
and defaults to 0.
'''
transition_state = OptionProperty('out', options=('in', 'out'))
'''Value that represents the state of the transition:
- 'in' if the transition is going to show your screen
- 'out' if the transition is going to hide your screen
After the transition is complete, the state will retain it's last value (in
or out).
:attr:`transition_state` is an :class:`~kivy.properties.OptionProperty` and
defaults to 'out'.
'''
__events__ = ('on_pre_enter', 'on_enter', 'on_pre_leave', 'on_leave')
2018-09-05 21:03:23 +00:00
interval = NumericProperty(0.0)
2018-09-06 15:45:36 +00:00
def on_pre_enter(self, *args):
pass
def on_enter(self, *args):
pass
def on_pre_leave(self, *args):
pass
def on_leave(self, *args):
pass
def __repr__(self):
return '<Screen name=%r>' % self.name
class Node(NodeBehavior, RelativeLayout):
pass
kivy.uix.screenmanager.Screen = NodeBehavior
2018-09-05 21:03:23 +00:00
Screen = Node
class Fader(ScreenManager):
interval = NumericProperty(5.0)
view_start = NumericProperty(5.0)
2018-09-06 13:20:12 +00:00
show_progress = BooleanProperty(True)
2018-09-05 21:03:23 +00:00
_interval = None
2018-09-06 13:20:12 +00:00
_progress_interval = None
2018-09-05 21:03:23 +00:00
def __init__(self, **kwargs):
super(Fader, self).__init__(**kwargs)
if 'transition' not in kwargs:
self.transition = FadeTransition()
from kivy.graphics import Color, Rectangle
with self.canvas.after:
Color(1., 1., 1., 0.2)
2018-09-06 13:20:12 +00:00
self.progress_rect = Rectangle(pos=self.pos, size=(0, 0))
2018-09-05 21:03:23 +00:00
2018-09-06 13:20:12 +00:00
self.on_show_progress(None, self.show_progress)
2018-09-05 21:03:23 +00:00
self.rotate_screens(0)
def update_rect(self, *args):
2018-09-06 13:20:12 +00:00
if not self.show_progress:
return
2018-09-05 21:03:23 +00:00
progress = ((time.time() - self.view_start)/self.current_interval)
self.progress_rect.pos = self.pos
self.progress_rect.size = (self.size[0] * progress, 10)
2018-09-06 13:20:12 +00:00
def on_show_progress(self, instance, value):
if self._progress_interval:
self._progress_interval.cancel()
self._progress_interval = None
if value:
self._progress_interval = Clock.schedule_interval(self.update_rect, 0)
self.progress_rect.size = (0, 0)
2018-09-05 21:03:23 +00:00
def on_interval(self, instance, value):
if self._interval:
self._interval.cancel()
self._interval = Clock.schedule_once(
self.rotate_screens, self.current_interval)
def add_widget(self, screen):
"""Just wrap everything in Screen"""
2018-09-06 15:45:36 +00:00
if not isinstance(screen, NodeBehavior):
print ('Wrapping!', screen)
s = Node()
2018-09-05 21:03:23 +00:00
s.add_widget(screen)
screen = s
return super(Fader, self).add_widget(screen)
def generate_ids(self):
"""Generates random IDs for all screens without set name"""
2018-09-06 15:45:36 +00:00
for i, c in enumerate(self.screens):
2018-09-05 21:03:23 +00:00
if not c.name:
2018-09-06 15:45:36 +00:00
c.name = 'screen_%i_%s' % (i, type(c))
2018-09-05 21:03:23 +00:00
def rotate_screens(self, dt):
self.generate_ids()
self.current = self.next()
self.view_start = time.time()
self._interval = Clock.schedule_once(
self.rotate_screens, self.current_interval)
@property
def current_interval(self):
if self.current_screen and self.current_screen.interval:
return self.current_screen.interval
return self.interval