updated copyright in source files
[geeqie.git] / src / ui_spinner.c
1 /*
2  * (SLIK) SimpLIstic sKin functions
3  * (C) 2004 John Ellis
4  * Copyright (C) 2008 The Geeqie Team
5  *
6  * Author: John Ellis
7  *
8  * This software is released under the GNU General Public License (GNU GPL).
9  * Please read the included file COPYING for more information.
10  * This software comes with no warranty of any kind, use at your own risk!
11  */
12
13 #ifdef HAVE_CONFIG_H
14 #  include "config.h"
15 #endif
16 #include "intl.h"
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21
22 #include <gtk/gtk.h>
23
24 #include "ui_spinner.h"
25
26 #include "ui_icons.h"
27 #include "ui_fileops.h"
28
29
30 #define SPINNER_FRAMES 19
31
32
33 /*
34  *-----------------------------------------------------------------------------
35  * spinner utility
36  *-----------------------------------------------------------------------------
37  */
38
39 typedef struct _SpinnerData SpinnerData;
40 struct _SpinnerData {
41         GtkWidget *image;
42         GList *list;            /* list of pixbufs */
43         gint frame;
44         gint timer_id;
45 };
46
47 static void spinner_set_frame(SpinnerData *sp, gint frame)
48 {
49         GdkPixbuf *pb;
50
51         pb = g_list_nth_data(sp->list, frame);
52         if (pb) gtk_image_set_from_pixbuf(GTK_IMAGE(sp->image), pb);
53
54         sp->frame = frame;
55 }
56
57 static void spinner_increment_frame(SpinnerData *sp)
58 {
59         sp->frame++;
60         if (sp->frame >= g_list_length(sp->list)) sp->frame = 1;
61         spinner_set_frame(sp, sp->frame);
62 }
63
64 static gboolean spinner_loop_cb(gpointer data)
65 {
66         SpinnerData *sp = data;
67
68         if (sp->list) spinner_increment_frame(sp);
69
70         return TRUE;
71 }
72
73 static void spinner_set_timeout(SpinnerData *sp, gint interval)
74 {
75         if (!sp) return;
76
77         if (sp->timer_id != -1)
78                 {
79                 g_source_remove(sp->timer_id);
80                 sp->timer_id = -1;
81                 }
82
83         if (interval > 0)
84                 {
85                 sp->timer_id = g_timeout_add(interval, spinner_loop_cb, sp);
86                 }
87         else if (interval < 0)
88                 {
89                 spinner_set_frame(sp, 0);
90                 }
91
92         gtk_widget_set_sensitive(sp->image, (interval >= 0));
93 }
94
95 static void spinner_destroy_cb(GtkWidget *widget, gpointer data)
96 {
97         SpinnerData *sp = data;
98         GList *work;
99
100         spinner_set_timeout(sp, 0);
101
102         work = sp->list;
103         while (work)
104                 {
105                 GdkPixbuf *pb = work->data;
106                 work = work->next;
107
108                 g_object_unref(pb);
109                 }
110         g_list_free(sp->list);
111         g_free(sp);
112 }
113
114 GtkWidget *spinner_new(const gchar *path, gint interval)
115 {
116         SpinnerData *sp;
117
118         sp = g_new0(SpinnerData, 1);
119         sp->list = NULL;
120         sp->timer_id = -1;
121
122         if (path)
123                 {
124                 gchar *pathl;
125                 GdkPixbuf *pb;
126                 gint n;
127                 gchar *buf;
128
129                 pathl = path_from_utf8(path);
130
131                 n = 0;
132                 buf = g_strdup_printf("%s%02d.png", pathl, n);
133                 while ((pb = gdk_pixbuf_new_from_file(buf, NULL)))
134                         {
135                         sp->list = g_list_append(sp->list, pb);
136
137                         n++;
138                         g_free(buf);
139                         buf = g_strdup_printf("%s%02d.png", pathl, n);
140                         }
141                 g_free(buf);
142
143                 g_free(pathl);
144                 }
145
146         if (!sp->list)
147                 {
148                 GdkPixbuf *pb;
149                 gint n;
150                 gint w, h;
151
152                 pb = gdk_pixbuf_new_from_inline (-1, icon_spinner, FALSE, NULL);
153                 w = gdk_pixbuf_get_width(pb);
154                 h = gdk_pixbuf_get_height(pb) / SPINNER_FRAMES;
155                 for (n = 0; n < SPINNER_FRAMES; n++)
156                         {
157                         sp->list = g_list_append(sp->list,
158                                                  gdk_pixbuf_new_subpixbuf(pb, 0, n * h, w, h));
159                         }
160                 /* pb pixels is inline static, so the subpixbufs in sp->list will be ok */
161                 g_object_unref(pb);
162                 }
163
164         if (sp->list)
165                 {
166                 GdkPixbuf *pb;
167
168                 pb = sp->list->data;
169                 sp->image = gtk_image_new_from_pixbuf(pb);
170                 }
171         else
172                 {
173                 sp->image = gtk_image_new_from_stock(GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_DIALOG);
174                 }
175
176         g_object_set_data(G_OBJECT(sp->image), "spinner", sp);
177
178         g_signal_connect(G_OBJECT(sp->image), "destroy",
179                          G_CALLBACK(spinner_destroy_cb), sp);
180
181         spinner_set_timeout(sp, interval);
182
183         return sp->image;
184 }
185
186 void spinner_set_interval(GtkWidget *spinner, gint interval)
187 {
188         SpinnerData *sp;
189
190         sp = g_object_get_data(G_OBJECT(spinner), "spinner");
191
192         spinner_set_timeout(sp, interval);
193 }
194
195 void spinner_step(GtkWidget *spinner, gint reset)
196 {
197         SpinnerData *sp;
198
199         sp = g_object_get_data(G_OBJECT(spinner), "spinner");
200         if (sp->timer_id != -1)
201                 {
202                 printf("spinner warning: attempt to step with timer set\n");
203                 return;
204                 }
205
206         if (reset)
207                 {
208                 spinner_set_frame(sp, 0);
209                 }
210         else
211                 {
212                 spinner_increment_frame(sp);
213                 }
214 }