This commit is contained in:
Sam Parkinson 2016-04-21 07:37:06 +10:00
commit 66c01ba2c6

View File

@ -24,9 +24,6 @@ Example:
from gi.repository import Gtk from gi.repository import Gtk
from sugar3.graphics.animator import Animator, Animation from sugar3.graphics.animator import Animator, Animation
# Construct a 5 second animator
animator = Animator(5)
# Construct a window to animate # Construct a window to animate
w = Gtk.Window() w = Gtk.Window()
w.connect('destroy', Gtk.main_quit) w.connect('destroy', Gtk.main_quit)
@ -34,6 +31,9 @@ Example:
w.connect('realize', lambda self: animator.start()) w.connect('realize', lambda self: animator.start())
w.show() w.show()
# Construct a 5 second animator
animator = Animator(5, widget=w)
# Create an animation subclass to animate the widget # Create an animation subclass to animate the widget
class SizeAnimation(Animation): class SizeAnimation(Animation):
def __init__(self): def __init__(self):
@ -80,6 +80,11 @@ class Animator(GObject.GObject):
per second (frames per second) per second (frames per second)
easing (int): the desired easing mode, either `EASE_OUT_EXPO` easing (int): the desired easing mode, either `EASE_OUT_EXPO`
or `EASE_IN_EXPO` or `EASE_IN_EXPO`
widget (:class:`Gtk.Widget`): one of the widgets that the animation
is acting on. If supplied and if the user's Gtk+ version
supports it, the animation will run on the frame clock of the
widget, resulting in a smoother animation and the fps value
will be disregarded.
.. note:: .. note::
@ -92,12 +97,13 @@ class Animator(GObject.GObject):
'completed': (GObject.SignalFlags.RUN_FIRST, None, ([])), 'completed': (GObject.SignalFlags.RUN_FIRST, None, ([])),
} }
def __init__(self, duration, fps=20, easing=EASE_OUT_EXPO): def __init__(self, duration, fps=20, easing=EASE_OUT_EXPO, widget=None):
GObject.GObject.__init__(self) GObject.GObject.__init__(self)
self._animations = [] self._animations = []
self._duration = duration self._duration = duration
self._interval = 1.0 / fps self._interval = 1.0 / fps
self._easing = easing self._easing = easing
self._widget = widget
self._timeout_sid = 0 self._timeout_sid = 0
self._start_time = None self._start_time = None
@ -127,6 +133,12 @@ class Animator(GObject.GObject):
self.stop() self.stop()
self._start_time = time.time() self._start_time = time.time()
if hasattr(self._widget, 'add_tick_callback'):
self._timeout_sid = self._widget.add_tick_callback(
self._next_frame_cb, None)
# Make sure the 1st frame is animated so we get ticks
self._next_frame_cb()
else:
self._timeout_sid = GLib.timeout_add( self._timeout_sid = GLib.timeout_add(
int(self._interval * 1000), self._next_frame_cb) int(self._interval * 1000), self._next_frame_cb)
@ -134,12 +146,17 @@ class Animator(GObject.GObject):
''' '''
Stop the animation and emit the `completed` signal Stop the animation and emit the `completed` signal
''' '''
if self._timeout_sid: if self._timeout_sid and \
not hasattr(self._widget, 'add_tick_callback'):
GObject.source_remove(self._timeout_sid) GObject.source_remove(self._timeout_sid)
self._timeout_sid = 0 self._timeout_sid = 0
self.emit('completed') self.emit('completed')
if self._timeout_sid and hasattr(self._widget, 'add_tick_callback'):
self._widget.remove_tick_callback(self._timeout_sid)
self._timeout_sid = 0
self.emit('completed')
def _next_frame_cb(self): def _next_frame_cb(self, *args):
current_time = min(self._duration, time.time() - self._start_time) current_time = min(self._duration, time.time() - self._start_time)
current_time = max(current_time, 0.0) current_time = max(current_time, 0.0)