9
|
1 /*
|
|
2 * (SLIK) SimpLIstic sKin functions
|
|
3 * (C) 2004 John Ellis
|
475
|
4 * Copyright (C) 2008 The Geeqie Team
|
9
|
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"
|
442
|
17
|
9
|
18 #include <stdio.h>
|
|
19 #include <stdlib.h>
|
|
20 #include <string.h>
|
442
|
21
|
9
|
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 }
|