1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
3
* @file libbling/bling-spinner.c A apple-esque spinner widger
5
* @Copyright (C) 2007 John Stowers, Neil Jagdish Patel.
7
* This library is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2 of the License, or (at your option) any later version.
12
* This library is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this library; if not, write to the
19
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20
* Boston, MA 02111-1307, USA.
22
* Code adapted from egg-spinner
23
* by Christian Hergert <christian.hergert@gmail.com>
33
#include "bling-spinner.h"
35
#define BLING_SPINNER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), BLING_TYPE_SPINNER, BlingSpinnerPrivate))
37
G_DEFINE_TYPE (BlingSpinner, bling_spinner, GTK_TYPE_DRAWING_AREA);
46
struct _BlingSpinnerPrivate
57
static void bling_spinner_class_init(BlingSpinnerClass *klass);
58
static void bling_spinner_init(BlingSpinner *spinner);
59
static void bling_spinner_finalize (GObject *gobject);
60
static void bling_spinner_set_property(GObject *gobject, guint prop_id, const GValue *value, GParamSpec *pspec);
61
static gboolean bling_spinner_expose(GtkWidget *widget, GdkEventExpose *event);
62
static void bling_spinner_screen_changed (GtkWidget* widget, GdkScreen* old_screen);
64
static GtkDrawingAreaClass *parent_class;
66
/* DRAWING FUNCTIONS */
68
draw (GtkWidget *widget, cairo_t *cr)
76
BlingSpinnerPrivate *priv;
78
priv = BLING_SPINNER_GET_PRIVATE (widget);
80
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
82
width = widget->allocation.width;
83
height = widget->allocation.height;
85
if ( (width < 12) || (height <12) )
86
gtk_widget_set_size_request(widget, 12, 12);
88
//x = widget->allocation.x + widget->allocation.width / 2;
89
//y = widget->allocation.y + widget->allocation.height / 2;
90
x = widget->allocation.width / 2;
91
y = widget->allocation.height / 2;
92
radius = MIN (widget->allocation.width / 2,
93
widget->allocation.height / 2);
94
half = priv->lines / 2;
96
/*FIXME: render in B&W for non transparency */
98
for (i = 0; i < priv->lines; i++) {
99
int inset = 0.7 * radius;
100
/* transparency is a function of time and intial value */
101
double t = (double) ((i + priv->lines - priv->current)
102
% priv->lines) / priv->lines;
106
cairo_set_source_rgba (cr, 0, 0, 0, t);
107
//cairo_set_line_width (cr, 2 * cairo_get_line_width (cr));
108
cairo_set_line_width (cr, 2.0);
110
x + (radius - inset) * cos (i * M_PI / half),
111
y + (radius - inset) * sin (i * M_PI / half));
113
x + radius * cos (i * M_PI / half),
114
y + radius * sin (i * M_PI / half));
122
/* GOBJECT INIT CODE */
124
bling_spinner_class_init(BlingSpinnerClass *klass)
126
GObjectClass *gobject_class;
127
GtkWidgetClass *widget_class;
129
parent_class = g_type_class_peek_parent(klass);
131
gobject_class = G_OBJECT_CLASS(klass);
132
g_type_class_add_private (gobject_class, sizeof (BlingSpinnerPrivate));
133
gobject_class->set_property = bling_spinner_set_property;
134
gobject_class->finalize = bling_spinner_finalize;
136
widget_class = GTK_WIDGET_CLASS(klass);
137
widget_class->expose_event = bling_spinner_expose;
138
widget_class->screen_changed = bling_spinner_screen_changed;
140
g_object_class_install_property(gobject_class, PROP_NUM_LINES,
141
g_param_spec_uint("lines", "Num Lines",
142
"The number of lines to animate",
144
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
149
bling_spinner_init (BlingSpinner *spinner)
151
BlingSpinnerPrivate *priv;
153
priv = BLING_SPINNER_GET_PRIVATE (spinner);
157
GTK_WIDGET_SET_FLAGS (GTK_WIDGET (spinner), GTK_NO_WINDOW);
161
bling_spinner_expose (GtkWidget *widget, GdkEventExpose *event)
165
/* get cairo context */
166
cr = gdk_cairo_create (gtk_widget_get_window (widget));
168
/* set a clip region for the expose event */
170
event->area.x, event->area.y,
171
event->area.width, event->area.height);
174
cairo_translate (cr, event->area.x, event->area.y);
176
/* draw clip region */
186
bling_spinner_screen_changed (GtkWidget* widget, GdkScreen* old_screen)
188
BlingSpinner *spinner;
189
GdkScreen* new_screen;
190
GdkColormap* colormap;
192
spinner = BLING_SPINNER(widget);
194
new_screen = gtk_widget_get_screen (widget);
195
colormap = gdk_screen_get_rgba_colormap (new_screen);
198
colormap = gdk_screen_get_rgb_colormap (new_screen);
200
gtk_widget_set_colormap (widget, colormap);
204
bling_spinner_timeout (gpointer data)
206
BlingSpinner *spinner;
207
BlingSpinnerPrivate *priv;
209
spinner = BLING_SPINNER (data);
210
priv = BLING_SPINNER_GET_PRIVATE (spinner);
212
if (priv->current + 1 >= priv->lines) {
218
gtk_widget_queue_draw (GTK_WIDGET (data));
224
bling_spinner_set_property(GObject *gobject, guint prop_id,
225
const GValue *value, GParamSpec *pspec)
227
BlingSpinner *spinner;
228
BlingSpinnerPrivate *priv;
230
spinner = BLING_SPINNER(gobject);
231
priv = BLING_SPINNER_GET_PRIVATE (spinner);
236
priv->lines = g_value_get_uint(value);
239
G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec);
245
bling_spinner_finalize (GObject *gobject)
247
BlingSpinner *spinner;
248
BlingSpinnerPrivate *priv;
250
spinner = BLING_SPINNER(gobject);
251
priv = BLING_SPINNER_GET_PRIVATE (spinner);
253
if (priv->timeout != 0) {
254
g_source_remove (priv->timeout);
262
* Returns a default spinner. Not yet started.
264
* Returns: a new #BlingSpinner
267
bling_spinner_new (void)
269
return g_object_new (BLING_TYPE_SPINNER, NULL);
273
* bling_spinner_start
275
* Starts the animation
278
bling_spinner_start (BlingSpinner *spinner)
280
BlingSpinnerPrivate *priv;
282
g_return_if_fail (BLING_IS_SPINNER (spinner));
284
priv = BLING_SPINNER_GET_PRIVATE (spinner);
285
if (priv->timeout != 0)
287
priv->timeout = g_timeout_add (80, bling_spinner_timeout, spinner);
293
* Stops the animation
296
bling_spinner_stop (BlingSpinner *spinner)
298
BlingSpinnerPrivate *priv;
300
g_return_if_fail (BLING_IS_SPINNER (spinner));
302
priv = BLING_SPINNER_GET_PRIVATE (spinner);
303
if (priv->timeout == 0)
305
g_source_remove (priv->timeout);