[gnome-builder] theatrics: teach IdeBoxTheatric to animate icons
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] theatrics: teach IdeBoxTheatric to animate icons
- Date: Thu, 25 Aug 2016 18:38:57 +0000 (UTC)
commit ecd3e85be37ab5fbdc9359ba534c536582ef628f
Author: Christian Hergert <chergert redhat com>
Date: Thu Aug 25 11:38:01 2016 -0700
theatrics: teach IdeBoxTheatric to animate icons
This allows us to do some nifty animations with icons similar to that of
the Firefox downloads animation. Since we do not create a subsurface or
overlay window, the animation is captive to the parent window dimensions.
Generally this is fine.
libide/theatrics/ide-box-theatric.c | 140 +++++++++++++++++++++++++++++------
1 files changed, 118 insertions(+), 22 deletions(-)
---
diff --git a/libide/theatrics/ide-box-theatric.c b/libide/theatrics/ide-box-theatric.c
index d470091..2d8101e 100644
--- a/libide/theatrics/ide-box-theatric.c
+++ b/libide/theatrics/ide-box-theatric.c
@@ -26,15 +26,24 @@
struct _IdeBoxTheatric
{
- GObject parent_instance;
+ GObject parent_instance;
- GtkWidget *target;
- GtkWidget *toplevel;
- GdkRectangle area;
- GdkRectangle last_area;
- GdkRGBA background_rgba;
+ GtkWidget *target;
+ GtkWidget *toplevel;
+
+ GIcon *icon;
+ cairo_surface_t *icon_surface;
+ guint icon_surface_size;
+
+ GdkRectangle area;
+ GdkRectangle last_area;
+ GdkRGBA background_rgba;
+ gdouble alpha;
+
+ guint draw_handler;
- guint draw_handler;
+ guint background_set : 1;
+ guint pixbuf_failed : 1;
};
enum {
@@ -42,6 +51,7 @@ enum {
PROP_ALPHA,
PROP_BACKGROUND,
PROP_HEIGHT,
+ PROP_ICON,
PROP_TARGET,
PROP_WIDTH,
PROP_X,
@@ -66,13 +76,15 @@ get_toplevel_rect (IdeBoxTheatric *theatric,
}
static gboolean
-on_toplevel_draw (GtkWidget *widget,
- cairo_t *cr,
- IdeBoxTheatric *theatric)
+on_toplevel_draw (GtkWidget *widget,
+ cairo_t *cr,
+ IdeBoxTheatric *self)
{
GdkRectangle area;
- get_toplevel_rect (theatric, &area);
+ g_assert (IDE_IS_BOX_THEATRIC (self));
+
+ get_toplevel_rect (self, &area);
#if 0
g_print ("Drawing on %s at %d,%d %dx%d\n",
@@ -80,11 +92,66 @@ on_toplevel_draw (GtkWidget *widget,
area.x, area.y, area.width, area.height);
#endif
- ide_cairo_rounded_rectangle (cr, &area, 3, 3);
- gdk_cairo_set_source_rgba (cr, &theatric->background_rgba);
- cairo_fill (cr);
+ if (self->background_set)
+ {
+ GdkRGBA bg;
+
+ bg = self->background_rgba;
+ bg.alpha = self->alpha;
- theatric->last_area = area;
+ ide_cairo_rounded_rectangle (cr, &area, 3, 3);
+ gdk_cairo_set_source_rgba (cr, &bg);
+ cairo_fill (cr);
+ }
+
+ /* Load an icon if necessary and cache the surface */
+ if (self->icon != NULL && self->icon_surface == NULL && !self->pixbuf_failed)
+ {
+ g_autoptr(GtkIconInfo) icon_info = NULL;
+ GtkIconTheme *icon_theme;
+ gint width;
+
+ width = area.width * 4;
+ icon_theme = gtk_icon_theme_get_default ();
+ icon_info = gtk_icon_theme_lookup_by_gicon (icon_theme,
+ self->icon,
+ width,
+ GTK_ICON_LOOKUP_FORCE_SIZE);
+
+ if (icon_info != NULL)
+ {
+ GdkWindow *window = gtk_widget_get_window (widget);
+ g_autoptr(GdkPixbuf) pixbuf = NULL;
+ GtkStyleContext *context;
+
+ context = gtk_widget_get_style_context (self->target);
+ pixbuf = gtk_icon_info_load_symbolic_for_context (icon_info, context, NULL, NULL);
+
+ if (pixbuf != NULL)
+ {
+ self->icon_surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 0, window);
+ self->icon_surface_size = width;
+ self->pixbuf_failed = FALSE;
+ }
+ else
+ {
+ self->pixbuf_failed = TRUE;
+ }
+ }
+ }
+
+ if (self->icon_surface != NULL)
+ {
+ cairo_translate (cr, area.x, area.y);
+ cairo_rectangle (cr, 0, 0, area.width, area.height);
+ cairo_scale (cr,
+ area.width / (gdouble)self->icon_surface_size,
+ area.height / (gdouble)self->icon_surface_size);
+ cairo_set_source_surface (cr, self->icon_surface, 0, 0);
+ cairo_paint_with_alpha (cr, self->alpha);
+ }
+
+ self->last_area = area;
return FALSE;
}
@@ -137,6 +204,9 @@ ide_box_theatric_dispose (GObject *object)
self->target = NULL;
}
+ g_clear_pointer (&self->icon_surface, cairo_surface_destroy);
+ g_clear_object (&self->icon);
+
G_OBJECT_CLASS (ide_box_theatric_parent_class)->dispose (object);
}
@@ -151,7 +221,7 @@ ide_box_theatric_get_property (GObject *object,
switch (prop_id)
{
case PROP_ALPHA:
- g_value_set_double (value, theatric->background_rgba.alpha);
+ g_value_set_double (value, theatric->alpha);
break;
case PROP_BACKGROUND:
@@ -163,6 +233,10 @@ ide_box_theatric_get_property (GObject *object,
g_value_set_int (value, theatric->area.height);
break;
+ case PROP_ICON:
+ g_value_set_object (value, theatric->icon);
+ break;
+
case PROP_TARGET:
g_value_set_object (value, theatric->target);
break;
@@ -195,16 +269,24 @@ ide_box_theatric_set_property (GObject *object,
switch (prop_id)
{
case PROP_ALPHA:
- theatric->background_rgba.alpha = g_value_get_double (value);
+ theatric->alpha = g_value_get_double (value);
break;
case PROP_BACKGROUND:
{
- gdouble old_alpha = theatric->background_rgba.alpha;
-
- gdk_rgba_parse (&theatric->background_rgba,
- g_value_get_string (value));
- theatric->background_rgba.alpha = old_alpha;
+ const gchar *str = g_value_get_string (value);
+
+ if (str == NULL)
+ {
+ gdk_rgba_parse (&theatric->background_rgba, "#000000");
+ theatric->background_rgba.alpha = 0;
+ theatric->background_set = FALSE;
+ }
+ else
+ {
+ gdk_rgba_parse (&theatric->background_rgba, str);
+ theatric->background_set = TRUE;
+ }
}
break;
@@ -212,6 +294,13 @@ ide_box_theatric_set_property (GObject *object,
theatric->area.height = g_value_get_int (value);
break;
+ case PROP_ICON:
+ g_clear_pointer (&theatric->icon_surface, cairo_surface_destroy);
+ g_clear_object (&theatric->icon);
+ theatric->icon = g_value_dup_object (value);
+ theatric->pixbuf_failed = FALSE;
+ break;
+
case PROP_TARGET:
theatric->target = g_value_get_object (value);
theatric->toplevel = gtk_widget_get_toplevel (theatric->target);
@@ -279,6 +368,13 @@ ide_box_theatric_class_init (IdeBoxTheatricClass *klass)
0,
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ properties [PROP_ICON] =
+ g_param_spec_object ("icon",
+ "Icon",
+ "The GIcon to render over the background",
+ G_TYPE_ICON,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
properties[PROP_TARGET] =
g_param_spec_object ("target",
"Target",
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]