Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGonzalo Odiard <godiard@gmail.com>2014-07-11 18:17:17 (GMT)
committer Gonzalo Odiard <godiard@gmail.com>2014-07-14 11:00:10 (GMT)
commit1c3df79715ccbf5c4ac5f1a0ab51c925ad7b007a (patch)
treefd4c11b588d6e91178449349bf09674c8a5b0f95
parentbcde5c0b81bf6a1143dda8f6db041dbce2c1eefe (diff)
Implement flip animation
-rw-r--r--svgcard.py161
1 files changed, 100 insertions, 61 deletions
diff --git a/svgcard.py b/svgcard.py
index 0ed0642..012d820 100644
--- a/svgcard.py
+++ b/svgcard.py
@@ -23,6 +23,7 @@ import cairo
from gi.repository import Gtk
from gi.repository import Gdk
+from gi.repository import GObject
from gi.repository import GdkPixbuf
from gi.repository import Pango
from gi.repository import PangoCairo
@@ -38,7 +39,7 @@ import model
_logger = logging.getLogger('memorize-activity')
radio = style.zoom(60)
-BORDER_WIDTH = style.zoom(12)
+BORDER_WIDTH = style.zoom(10)
class SvgCard(Gtk.EventBox):
@@ -69,6 +70,12 @@ class SvgCard(Gtk.EventBox):
self.show_jpeg = False
self.show_text = False
self.size = size
+ # animation data
+ self._steps_scales = [0.66, 0.33, 0.1, 0.33, 0.66]
+ self._animation_steps = len(self._steps_scales)
+ self._on_animation = False
+ self._animation_step = 0
+
self.align = align
self.text_layouts = [None, None]
self.font_name = font_name
@@ -104,66 +111,26 @@ class SvgCard(Gtk.EventBox):
self.show_all()
def __draw_cb(self, widget, context):
- if self._cached_surface[self.flipped]:
- context.set_source_surface(self._cached_surface[self.flipped])
- context.paint()
- else:
- self._cached_surface[self.flipped] = \
- context.get_target().create_similar(cairo.CONTENT_COLOR_ALPHA,
- self.size, self.size)
- cache_context = cairo.Context(self._cached_surface[self.flipped])
-
- icon_data = self.props[self.current_face]
-
- cache_context.save()
- self.draw_round_rect(cache_context, 0, 0, self.size, self.size,
- radio)
- r, g, b, a = icon_data['fill_color'].get_rgba()
- cache_context.set_source_rgb(r, g, b)
- cache_context.fill_preserve()
-
- r, g, b, a = icon_data['stroke_color'].get_rgba()
- cache_context.set_source_rgb(r, g, b)
- cache_context.set_line_width(BORDER_WIDTH)
- cache_context.stroke()
- cache_context.restore()
-
- if self.show_jpeg:
- Gdk.cairo_set_source_pixbuf(cache_context, self.jpeg,
- theme.SVG_PAD, theme.SVG_PAD)
- cache_context.paint()
-
- if self.show_text:
- cache_context.save()
- props = self.props[self.flipped and 'front_text' or
- 'back_text']
- layout = self.text_layouts[self.flipped]
-
- if not layout:
- layout = self.text_layouts[self.flipped] = \
- self.create_text_layout(props['card_text'])
-
- width, height = layout.get_pixel_size()
- y = (self.size - height) / 2
- if self.flipped:
- if self.align == '2': # top
- y = 0
- elif self.align == '3': # bottom
- y = self.size - height
-
- x = (self.size - width) / 2
- cache_context.set_source_rgb(1, 1, 1)
- cache_context.translate(x, y)
- PangoCairo.update_layout(cache_context, layout)
- PangoCairo.show_layout(cache_context, layout)
- cache_context.fill()
- cache_context.restore()
-
- # paint the cached surface over the widget
- context.set_source_surface(self._cached_surface[self.flipped])
- context.paint()
-
- if self._highlighted:
+ flipped = self.flipped
+ highlighted = self._highlighted
+ if self._on_animation:
+ if self._animation_step > self._animation_steps / 2:
+ flipped = not self.flipped
+
+ if not self._cached_surface[flipped]:
+ self._prepare_cached_surface(context, flipped)
+
+ if self._on_animation:
+ scale = self._steps_scales[self._animation_step]
+ context.translate(0, self.size * (1 - scale) / 2)
+ context.scale(1.0, scale)
+ self._animation_step += 1
+ highlighted = False
+
+ context.set_source_surface(self._cached_surface[flipped])
+ context.paint()
+
+ if highlighted:
self.draw_round_rect(context, 0, 0, self.size, self.size, radio)
context.set_source_rgb(1., 1., 1.)
context.set_line_width(6)
@@ -171,6 +138,61 @@ class SvgCard(Gtk.EventBox):
return False
+ def _prepare_cached_surface(self, context, flipped):
+ self._cached_surface[flipped] = \
+ context.get_target().create_similar(cairo.CONTENT_COLOR_ALPHA,
+ self.size, self.size)
+ cache_context = cairo.Context(self._cached_surface[flipped])
+
+ if flipped:
+ icon_data = self.props['front']
+ else:
+ icon_data = self.props['back']
+
+ cache_context.save()
+ self.draw_round_rect(cache_context, 0, 0, self.size, self.size,
+ radio)
+ r, g, b, a = icon_data['fill_color'].get_rgba()
+ cache_context.set_source_rgb(r, g, b)
+ cache_context.fill_preserve()
+
+ r, g, b, a = icon_data['stroke_color'].get_rgba()
+ cache_context.set_source_rgb(r, g, b)
+ cache_context.set_line_width(BORDER_WIDTH)
+ cache_context.stroke()
+ cache_context.restore()
+
+ if self.show_jpeg:
+ Gdk.cairo_set_source_pixbuf(cache_context, self.jpeg,
+ theme.SVG_PAD, theme.SVG_PAD)
+ cache_context.paint()
+
+ if self.show_text:
+ cache_context.save()
+ props = self.props[flipped and 'front_text' or
+ 'back_text']
+ layout = self.text_layouts[flipped]
+
+ if not layout:
+ layout = self.text_layouts[flipped] = \
+ self.create_text_layout(props['card_text'])
+
+ width, height = layout.get_pixel_size()
+ y = (self.size - height) / 2
+ if flipped:
+ if self.align == '2': # top
+ y = 0
+ elif self.align == '3': # bottom
+ y = self.size - height
+
+ x = (self.size - width) / 2
+ cache_context.set_source_rgb(1, 1, 1)
+ cache_context.translate(x, y)
+ PangoCairo.update_layout(cache_context, layout)
+ PangoCairo.show_layout(cache_context, layout)
+ cache_context.fill()
+ cache_context.restore()
+
def set_border(self, stroke_color, fill_color):
"""
style_color, fill_color: str with format #RRGGBB
@@ -237,6 +259,23 @@ class SvgCard(Gtk.EventBox):
speak.voice.by_lang(self.get_speak())
speaking_face.face.say(self.get_text())
+ self._animation_step = 0
+ self._on_animation = True
+ self._animate_flip()
+ else:
+ self._finish_flip()
+
+ def _animate_flip(self):
+ logging.error('_animate_flip')
+ if self._animation_step < self._animation_steps - 1:
+ self.queue_draw()
+ GObject.timeout_add(100, self._animate_flip)
+ else:
+ self._finish_flip()
+ return False
+
+ def _finish_flip(self):
+ self._on_animation = False
self.current_face = 'front'
self.flipped = True
self.queue_draw()