midori/katze/katze-throbber.c
Christian Dywan 58255d19aa Do not localize object properties, except WebSettings
Property name localization is only useful if the
strings are meant to be used in a user interface,
such as is the case with WebSettings, or for
graphical interface builders, which are not of
our concern, since we don't use Glade and friends
and nobody else is going to use our widgets.

In short, make translation work much easier.
2008-10-15 03:32:11 +02:00

888 lines
27 KiB
C

/*
Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
See the file COPYING for the full license text.
*/
#include "katze-throbber.h"
#include "katze-utils.h"
#include <glib/gi18n.h>
struct _KatzeThrobber
{
GtkMisc parent_instance;
GtkIconSize icon_size;
gchar* icon_name;
GdkPixbuf* pixbuf;
gchar* stock_id;
gboolean animated;
gchar* static_icon_name;
GdkPixbuf* static_pixbuf;
gchar* static_stock_id;
gint index;
gint timer_id;
gint width;
gint height;
};
G_DEFINE_TYPE (KatzeThrobber, katze_throbber, GTK_TYPE_MISC)
enum
{
PROP_0,
PROP_ICON_SIZE,
PROP_ICON_NAME,
PROP_PIXBUF,
PROP_ANIMATED,
PROP_STATIC_ICON_NAME,
PROP_STATIC_PIXBUF,
PROP_STATIC_STOCK_ID
};
static void
katze_throbber_dispose (GObject* object);
static void
katze_throbber_set_property (GObject* object,
guint prop_id,
const GValue* value,
GParamSpec* pspec);
static void
katze_throbber_get_property (GObject* object,
guint prop_id,
GValue* value,
GParamSpec* pspec);
static void
katze_throbber_destroy (GtkObject* object);
static void
katze_throbber_realize (GtkWidget* widget);
static void
katze_throbber_unrealize (GtkWidget* widget);
static void
katze_throbber_map (GtkWidget* widget);
static void
katze_throbber_unmap (GtkWidget* widget);
static void
katze_throbber_style_set (GtkWidget* widget,
GtkStyle* style);
static void
katze_throbber_screen_changed (GtkWidget* widget,
GdkScreen* screen_prev);
static void
katze_throbber_size_request (GtkWidget* widget,
GtkRequisition* requisition);
static gboolean
katze_throbber_expose_event (GtkWidget* widget,
GdkEventExpose* event);
static void
icon_theme_changed (KatzeThrobber* throbber);
static gboolean
katze_throbber_timeout (KatzeThrobber* throbber);
static void
katze_throbber_timeout_destroy (KatzeThrobber* throbber);
static void
katze_throbber_class_init (KatzeThrobberClass* class)
{
GObjectClass* gobject_class = G_OBJECT_CLASS (class);
gobject_class->dispose = katze_throbber_dispose;
gobject_class->set_property = katze_throbber_set_property;
gobject_class->get_property = katze_throbber_get_property;
GtkObjectClass* object_class = GTK_OBJECT_CLASS (class);
object_class->destroy = katze_throbber_destroy;
GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (class);
widget_class->realize = katze_throbber_realize;
widget_class->unrealize = katze_throbber_unrealize;
widget_class->map = katze_throbber_map;
widget_class->unmap = katze_throbber_unmap;
widget_class->style_set = katze_throbber_style_set;
widget_class->screen_changed = katze_throbber_screen_changed;
widget_class->size_request = katze_throbber_size_request;
widget_class->expose_event = katze_throbber_expose_event;
GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT;
g_object_class_install_property (gobject_class,
PROP_ICON_SIZE,
g_param_spec_int (
"icon-size",
"Icon size",
"Symbolic size to use for the animation",
0, G_MAXINT, GTK_ICON_SIZE_MENU,
flags));
g_object_class_install_property (gobject_class,
PROP_ICON_NAME,
g_param_spec_string (
"icon-name",
"Icon Name",
"The name of an icon containing animation frames",
"process-working",
flags));
g_object_class_install_property (gobject_class,
PROP_PIXBUF,
g_param_spec_object (
"pixbuf",
"Pixbuf",
"A GdkPixbuf containing animation frames",
GDK_TYPE_PIXBUF,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_ANIMATED,
g_param_spec_boolean (
"animated",
"Animated",
"Whether the throbber should be animated",
FALSE,
flags));
g_object_class_install_property (gobject_class,
PROP_STATIC_ICON_NAME,
g_param_spec_string (
"static-icon-name",
"Static Icon Name",
"The name of an icon to be used as the static image",
NULL,
flags));
g_object_class_install_property (gobject_class,
PROP_PIXBUF,
g_param_spec_object (
"static-pixbuf",
"Static Pixbuf",
"A GdkPixbuf to be used as the static image",
GDK_TYPE_PIXBUF,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_STATIC_STOCK_ID,
g_param_spec_string (
"static-stock-id",
"Static Stock ID",
"The stock ID of an icon to be used as the static image",
NULL,
flags));
}
static void
katze_throbber_init (KatzeThrobber *throbber)
{
GTK_WIDGET_SET_FLAGS (throbber, GTK_NO_WINDOW);
throbber->timer_id = -1;
}
static void
katze_throbber_dispose (GObject* object)
{
KatzeThrobber* throbber = KATZE_THROBBER (object);
if (G_UNLIKELY (throbber->timer_id >= 0))
g_source_remove (throbber->timer_id);
(*G_OBJECT_CLASS (katze_throbber_parent_class)->dispose) (object);
}
static void
katze_throbber_destroy (GtkObject* object)
{
KatzeThrobber* throbber = KATZE_THROBBER (object);
katze_assign (throbber->icon_name, NULL);
katze_object_assign (throbber->pixbuf, NULL);
katze_assign (throbber->static_icon_name, NULL);
katze_object_assign (throbber->static_pixbuf, NULL);
katze_assign (throbber->static_stock_id, NULL);
GTK_OBJECT_CLASS (katze_throbber_parent_class)->destroy (object);
}
static void
katze_throbber_set_property (GObject* object,
guint prop_id,
const GValue* value,
GParamSpec* pspec)
{
KatzeThrobber* throbber = KATZE_THROBBER (object);
switch (prop_id)
{
case PROP_ICON_SIZE:
katze_throbber_set_icon_size (throbber, g_value_get_int (value));
break;
case PROP_ICON_NAME:
katze_throbber_set_icon_name (throbber, g_value_get_string (value));
break;
case PROP_PIXBUF:
katze_throbber_set_pixbuf (throbber, g_value_get_object (value));
break;
case PROP_ANIMATED:
katze_throbber_set_animated (throbber, g_value_get_boolean (value));
break;
case PROP_STATIC_ICON_NAME:
katze_throbber_set_static_icon_name (throbber, g_value_get_string (value));
break;
case PROP_STATIC_PIXBUF:
katze_throbber_set_static_pixbuf (throbber, g_value_get_object (value));
break;
case PROP_STATIC_STOCK_ID:
katze_throbber_set_static_stock_id (throbber, g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
katze_throbber_get_property (GObject* object,
guint prop_id,
GValue* value,
GParamSpec* pspec)
{
KatzeThrobber* throbber = KATZE_THROBBER (object);
switch (prop_id)
{
case PROP_ICON_SIZE:
g_value_set_int (value, katze_throbber_get_icon_size (throbber));
break;
case PROP_ICON_NAME:
g_value_set_string (value, katze_throbber_get_icon_name (throbber));
break;
case PROP_PIXBUF:
g_value_set_object (value, katze_throbber_get_pixbuf (throbber));
break;
case PROP_ANIMATED:
g_value_set_boolean (value, katze_throbber_get_animated (throbber));
break;
case PROP_STATIC_ICON_NAME:
g_value_set_string (value, katze_throbber_get_static_icon_name (throbber));
break;
case PROP_STATIC_PIXBUF:
g_value_set_object (value, katze_throbber_get_static_pixbuf (throbber));
break;
case PROP_STATIC_STOCK_ID:
g_value_set_string (value, katze_throbber_get_static_stock_id (throbber));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
/**
* katze_throbber_new:
*
* Creates a new throbber widget.
*
* Return value: a new #KatzeThrobber
**/
GtkWidget*
katze_throbber_new (void)
{
KatzeThrobber* throbber = g_object_new (KATZE_TYPE_THROBBER,
NULL);
return GTK_WIDGET (throbber);
}
/**
* katze_throbber_set_icon_size:
* @throbber: a #KatzeThrobber
* @icon_size: the new icon size
*
* Sets the desired size of the throbber image. The animation and static image
* will be displayed in this size. If a pixbuf is used for the animation every
* single frame is assumed to have this size.
**/
void
katze_throbber_set_icon_size (KatzeThrobber* throbber,
GtkIconSize icon_size)
{
GtkSettings* gtk_settings;
g_return_if_fail (KATZE_IS_THROBBER (throbber));
gtk_settings = gtk_widget_get_settings (GTK_WIDGET (throbber));
g_return_if_fail (gtk_icon_size_lookup_for_settings (gtk_settings,
icon_size,
&throbber->width,
&throbber->height));
throbber->icon_size = icon_size;
g_object_notify (G_OBJECT (throbber), "icon-size");
gtk_widget_queue_draw (GTK_WIDGET (throbber));
}
/**
* katze_throbber_set_icon_name:
* @throbber: a #KatzeThrobber
* @icon_name: an icon name or %NULL
*
* Sets the name of an icon that should provide the animation frames.
*
* The pixbuf is automatically invalidated.
**/
void
katze_throbber_set_icon_name (KatzeThrobber* throbber,
const gchar* icon_name)
{
g_return_if_fail (KATZE_IS_THROBBER (throbber));
katze_assign (throbber->icon_name, g_strdup (icon_name));
if (icon_name)
icon_theme_changed (throbber);
g_object_notify (G_OBJECT (throbber), "icon-name");
}
/**
* katze_throbber_set_pixbuf:
* @throbber: a #KatzeThrobber
* @pixbuf: a #GdkPixbuf or %NULL
*
* Sets the pixbuf that should provide the animation frames. Every frame
* is assumed to have the icon size of the throbber, which can be specified
* with katze_throbber_set_icon_size ().
*
* The icon name is automatically invalidated.
**/
void
katze_throbber_set_pixbuf (KatzeThrobber* throbber,
GdkPixbuf* pixbuf)
{
g_return_if_fail (KATZE_IS_THROBBER (throbber));
g_return_if_fail (!pixbuf || GDK_IS_PIXBUF (pixbuf));
katze_object_assign (throbber->pixbuf, pixbuf);
g_object_freeze_notify (G_OBJECT (throbber));
if (pixbuf)
{
g_object_ref (pixbuf);
katze_assign (throbber->icon_name, NULL);
g_object_notify (G_OBJECT (throbber), "icon-name");
}
gtk_widget_queue_draw (GTK_WIDGET (throbber));
g_object_notify (G_OBJECT (throbber), "pixbuf");
g_object_thaw_notify (G_OBJECT (throbber));
}
/**
* katze_throbber_set_animated:
* @throbber: a #KatzeThrobber
* @animated: %TRUE to animate the throbber
*
* Sets the animation state of the throbber.
**/
void
katze_throbber_set_animated (KatzeThrobber* throbber,
gboolean animated)
{
g_return_if_fail (KATZE_IS_THROBBER (throbber));
if (G_UNLIKELY (throbber->animated == animated))
return;
throbber->animated = animated;
if (animated && (throbber->timer_id < 0))
throbber->timer_id = g_timeout_add_full (
G_PRIORITY_LOW, 50,
(GSourceFunc)katze_throbber_timeout,
throbber,
(GDestroyNotify)katze_throbber_timeout_destroy);
gtk_widget_queue_draw (GTK_WIDGET (throbber));
g_object_notify (G_OBJECT (throbber), "animated");
}
/**
* katze_throbber_set_static_icon_name:
* @throbber: a #KatzeThrobber
* @icon_name: an icon name or %NULL
*
* Sets the name of an icon that should provide the static image.
*
* The static pixbuf and stock ID are automatically invalidated.
**/
void
katze_throbber_set_static_icon_name (KatzeThrobber* throbber,
const gchar* icon_name)
{
g_return_if_fail (KATZE_IS_THROBBER (throbber));
katze_assign (throbber->static_icon_name, g_strdup (icon_name));
g_object_freeze_notify (G_OBJECT (throbber));
if (icon_name)
{
katze_assign (throbber->static_stock_id, NULL);
icon_theme_changed (throbber);
g_object_notify (G_OBJECT (throbber), "static-pixbuf");
g_object_notify (G_OBJECT (throbber), "static-stock-id");
}
g_object_notify (G_OBJECT (throbber), "static-icon-name");
g_object_thaw_notify (G_OBJECT (throbber));
}
/**
* katze_throbber_set_static_pixbuf:
* @throbber: a #KatzeThrobber
* @pixbuf: a #GdkPixbuf or %NULL
*
* Sets the pixbuf that should provide the static image. The pixbuf is
* assumed to have the icon size of the throbber, which can be specified
* with katze_throbber_set_icon_size ().
*
* The static icon name and stock ID are automatically invalidated.
**/
void
katze_throbber_set_static_pixbuf (KatzeThrobber* throbber,
GdkPixbuf* pixbuf)
{
g_return_if_fail (KATZE_IS_THROBBER (throbber));
g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
katze_object_assign (throbber->static_pixbuf, pixbuf);
g_object_freeze_notify (G_OBJECT (throbber));
if (pixbuf)
{
g_object_ref (pixbuf);
katze_assign (throbber->static_icon_name, NULL);
katze_assign (throbber->static_stock_id, NULL);
gtk_widget_queue_draw (GTK_WIDGET (throbber));
g_object_notify (G_OBJECT (throbber), "static-icon-name");
g_object_notify (G_OBJECT (throbber), "static-stock-id");
}
g_object_notify (G_OBJECT (throbber), "static-pixbuf");
g_object_thaw_notify (G_OBJECT (throbber));
}
/**
* katze_throbber_set_static_stock_id:
* @throbber: a #KatzeThrobber
* @stock_id: a stock ID or %NULL
*
* Sets the stock ID of an icon that should provide the static image.
*
* The static icon name and pixbuf are automatically invalidated.
**/
void
katze_throbber_set_static_stock_id (KatzeThrobber* throbber,
const gchar* stock_id)
{
g_return_if_fail (KATZE_IS_THROBBER (throbber));
g_object_freeze_notify (G_OBJECT (throbber));
if (stock_id)
{
GtkStockItem stock_item;
g_return_if_fail (gtk_stock_lookup (stock_id, &stock_item));
g_object_notify (G_OBJECT (throbber), "static-icon-name");
g_object_notify (G_OBJECT (throbber), "static-pixbuf");
}
katze_assign (throbber->static_stock_id, g_strdup (stock_id));
if (stock_id)
icon_theme_changed (throbber);
g_object_notify (G_OBJECT (throbber), "static-stock-id");
g_object_thaw_notify (G_OBJECT (throbber));
}
/**
* katze_throbber_get_icon_size:
* @throbber: a #KatzeThrobber
*
* Retrieves the size of the throbber.
*
* Return value: the size of the throbber
**/
GtkIconSize
katze_throbber_get_icon_size (KatzeThrobber* throbber)
{
g_return_val_if_fail (KATZE_IS_THROBBER (throbber), GTK_ICON_SIZE_INVALID);
return throbber->icon_size;
}
/**
* katze_throbber_get_icon_name:
* @throbber: a #KatzeThrobber
*
* Retrieves the name of the icon providing the animation frames.
*
* Return value: the name of the icon providing the animation frames, or %NULL
**/
const gchar*
katze_throbber_get_icon_name (KatzeThrobber* throbber)
{
g_return_val_if_fail (KATZE_IS_THROBBER (throbber), NULL);
return throbber->icon_name;
}
/**
* katze_throbber_get_pixbuf:
* @throbber: a #KatzeThrobber
*
* Retrieves the #GdkPixbuf providing the animation frames if an icon name
* or pixbuf is available. The caller of this function does not own a
* reference to the returned pixbuf.
*
* Return value: the pixbuf providing the animation frames, or %NULL
**/
GdkPixbuf*
katze_throbber_get_pixbuf (KatzeThrobber* throbber)
{
g_return_val_if_fail (KATZE_IS_THROBBER (throbber), NULL);
return throbber->pixbuf;
}
/**
* katze_throbber_get_animated:
* @throbber: a #KatzeThrobber
*
* Retrieves the status of the animation, whcih can be animated or static.
*
* Return value: %TRUE if the throbber is animated
**/
gboolean
katze_throbber_get_animated (KatzeThrobber* throbber)
{
g_return_val_if_fail (KATZE_IS_THROBBER (throbber), FALSE);
return throbber->animated;
}
/**
* katze_throbber_get_static_icon_name:
* @throbber: a #KatzeThrobber
*
* Retrieves the name of the icon providing the static image, if an icon name
* for the static image was specified.
*
* Return value: the name of the icon providing the static image, or %NULL
**/
const gchar*
katze_throbber_get_static_icon_name (KatzeThrobber* throbber)
{
g_return_val_if_fail (KATZE_IS_THROBBER (throbber), NULL);
return throbber->static_icon_name;
}
/**
* katze_throbber_get_static pixbuf:
* @throbber: a #KatzeThrobber
*
* Retrieves the #GdkPixbuf providing the static image, if an icon name, a
* pixbuf or a stock ID for the static image was specified. The caller of this
* function does not own a reference to the returned pixbuf.
*
* Return value: the pixbuf providing the static image, or %NULL
**/
GdkPixbuf*
katze_throbber_get_static_pixbuf (KatzeThrobber* throbber)
{
g_return_val_if_fail (KATZE_IS_THROBBER (throbber), NULL);
return throbber->static_pixbuf;
}
/**
* katze_throbber_get_static_stock_id:
* @throbber: a #KatzeThrobber
*
* Retrieves the stock ID of the icon providing the static image, if a
* stock ID for the static image was specified.
*
* Return value: the stock ID of the icon providing the static image, or %NULL
**/
const gchar*
katze_throbber_get_static_stock_id (KatzeThrobber* throbber)
{
g_return_val_if_fail (KATZE_IS_THROBBER (throbber), NULL);
return throbber->static_stock_id;
}
static void
katze_throbber_realize (GtkWidget* widget)
{
(*GTK_WIDGET_CLASS (katze_throbber_parent_class)->realize) (widget);
icon_theme_changed (KATZE_THROBBER (widget));
}
static void
katze_throbber_unrealize (GtkWidget* widget)
{
if (GTK_WIDGET_CLASS (katze_throbber_parent_class)->unrealize)
GTK_WIDGET_CLASS (katze_throbber_parent_class)->unrealize (widget);
}
static void
pixbuf_assign_icon (GdkPixbuf** pixbuf,
const gchar* icon_name,
KatzeThrobber* throbber)
{
GdkScreen* screen;
GtkIconTheme* icon_theme;
if (*pixbuf)
g_object_unref (*pixbuf);
screen = gtk_widget_get_screen (GTK_WIDGET (throbber));
icon_theme = gtk_icon_theme_get_for_screen (screen);
*pixbuf = gtk_icon_theme_load_icon (icon_theme,
icon_name,
MAX (throbber->width, throbber->height),
(GtkIconLookupFlags) 0,
NULL);
}
static void
icon_theme_changed (KatzeThrobber* throbber)
{
if (throbber->icon_name)
pixbuf_assign_icon (&throbber->pixbuf,
throbber->icon_name, throbber);
if (throbber->static_icon_name)
pixbuf_assign_icon (&throbber->static_pixbuf,
throbber->static_icon_name, throbber);
else if (throbber->static_stock_id)
katze_object_assign (throbber->static_pixbuf,
gtk_widget_render_icon (GTK_WIDGET (throbber),
throbber->static_stock_id,
throbber->icon_size,
NULL));
g_object_freeze_notify (G_OBJECT (throbber));
g_object_notify (G_OBJECT (throbber), "pixbuf");
g_object_notify (G_OBJECT (throbber), "static-pixbuf");
g_object_thaw_notify (G_OBJECT (throbber));
gtk_widget_queue_draw (GTK_WIDGET (throbber));
}
static void
katze_throbber_map (GtkWidget* widget)
{
(*GTK_WIDGET_CLASS (katze_throbber_parent_class)->map) (widget);
}
static void
katze_throbber_unmap (GtkWidget* widget)
{
if (GTK_WIDGET_CLASS (katze_throbber_parent_class)->unmap)
GTK_WIDGET_CLASS (katze_throbber_parent_class)->unmap (widget);
}
static gboolean
katze_throbber_timeout (KatzeThrobber* throbber)
{
throbber->index++;
gtk_widget_queue_draw (GTK_WIDGET (throbber));
return throbber->animated;
}
static void
katze_throbber_timeout_destroy (KatzeThrobber* throbber)
{
throbber->index = 0;
throbber->timer_id = -1;
}
static void
katze_throbber_style_set (GtkWidget* widget,
GtkStyle* prev_style)
{
if (GTK_WIDGET_CLASS (katze_throbber_parent_class)->style_set)
GTK_WIDGET_CLASS (katze_throbber_parent_class)->style_set (widget,
prev_style);
icon_theme_changed (KATZE_THROBBER (widget));
}
static void
katze_throbber_screen_changed (GtkWidget* widget,
GdkScreen* prev_screen)
{
if (GTK_WIDGET_CLASS (katze_throbber_parent_class)->screen_changed)
GTK_WIDGET_CLASS (katze_throbber_parent_class)->screen_changed (
widget,
prev_screen);
icon_theme_changed (KATZE_THROBBER (widget));
}
static void
katze_throbber_size_request (GtkWidget* widget,
GtkRequisition* requisition)
{
KatzeThrobber* throbber = KATZE_THROBBER (widget);
requisition->width = throbber->width;
requisition->height = throbber->height;
GTK_WIDGET_CLASS (katze_throbber_parent_class)->size_request (widget,
requisition);
}
static gboolean
katze_throbber_expose_event (GtkWidget* widget,
GdkEventExpose* event)
{
KatzeThrobber* throbber = KATZE_THROBBER (widget);
if (G_UNLIKELY (!throbber->width || !throbber->height))
return TRUE;
if (G_UNLIKELY (!throbber->pixbuf && !throbber->static_pixbuf))
if (throbber->animated && !throbber->pixbuf && !throbber->icon_name)
return TRUE;
if (!throbber->animated && (throbber->static_pixbuf
|| throbber->static_icon_name || throbber->static_stock_id))
{
if (G_UNLIKELY (!throbber->static_pixbuf && throbber->static_icon_name))
{
icon_theme_changed (KATZE_THROBBER (widget));
if (!throbber->static_pixbuf)
{
g_warning (_("Named icon '%s' couldn't be loaded"),
throbber->static_icon_name);
katze_assign (throbber->static_icon_name, NULL);
g_object_notify (G_OBJECT (throbber), "static-icon-name");
return TRUE;
}
}
else if (G_UNLIKELY (!throbber->static_pixbuf && throbber->static_stock_id))
{
icon_theme_changed (KATZE_THROBBER (widget));
if (!throbber->static_pixbuf)
{
g_warning (_("Stock icon '%s' couldn't be loaded"),
throbber->static_stock_id);
katze_assign (throbber->static_stock_id, NULL);
g_object_notify (G_OBJECT (throbber), "static-stock-id");
return TRUE;
}
}
gdk_draw_pixbuf (event->window, NULL, throbber->static_pixbuf,
0, 0,
widget->allocation.x,
widget->allocation.y,
throbber->width, throbber->height,
GDK_RGB_DITHER_NONE, 0, 0);
}
else
{
if (G_UNLIKELY (throbber->icon_name && !throbber->pixbuf))
{
icon_theme_changed (KATZE_THROBBER (widget));
if (!throbber->pixbuf)
{
g_warning (_("Icon '%s' couldn't be loaded"), throbber->icon_name);
katze_assign (throbber->icon_name, NULL);
g_object_notify (G_OBJECT (throbber), "icon-name");
return TRUE;
}
}
if (G_UNLIKELY (!throbber->pixbuf))
return TRUE;
gint cols = gdk_pixbuf_get_width (throbber->pixbuf) / throbber->width;
gint rows = gdk_pixbuf_get_height (throbber->pixbuf) / throbber->height;
if (G_LIKELY (cols > 0 && rows > 0))
{
gint index = throbber->index % (cols * rows);
if (G_LIKELY (throbber->timer_id >= 0))
index = MAX (index, 1);
guint x = (index % cols) * throbber->width;
guint y = (index / cols) * throbber->height;
gdk_draw_pixbuf (event->window, NULL, throbber->pixbuf,
x, y,
widget->allocation.x,
widget->allocation.y,
throbber->width, throbber->height,
GDK_RGB_DITHER_NONE, 0, 0);
}
else
{
g_warning (_("Animation frames are broken"));
katze_assign (throbber->icon_name, NULL);
katze_object_assign (throbber->pixbuf, NULL);
g_object_freeze_notify (G_OBJECT (throbber));
g_object_notify (G_OBJECT (throbber), "icon-name");
g_object_notify (G_OBJECT (throbber), "pixbuf");
g_object_thaw_notify (G_OBJECT (throbber));
}
}
return TRUE;
}