Fix typo in Readme file
[geeqie.git] / src / ui-spinner.cc
1 /*
2  * Copyright (C) 2004 John Ellis
3  * Copyright (C) 2008 - 2016 The Geeqie Team
4  *
5  * Author: John Ellis
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program 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
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include "main.h"
23 #include "ui-spinner.h"
24
25 #include "ui_icons.h"
26 #include "ui-fileops.h"
27
28
29 #define SPINNER_FRAMES 19
30
31
32 /*
33  *-----------------------------------------------------------------------------
34  * spinner utility
35  *-----------------------------------------------------------------------------
36  */
37
38 typedef struct _SpinnerData SpinnerData;
39 struct _SpinnerData {
40         GtkWidget *image;
41         GList *list;            /* list of pixbufs */
42         guint frame;
43         guint timer_id; /* event source id */
44 };
45
46 static void spinner_set_frame(SpinnerData *sp, guint frame)
47 {
48         GdkPixbuf *pb;
49
50         pb = static_cast<GdkPixbuf *>(g_list_nth_data(sp->list, frame));
51         if (pb) gtk_image_set_from_pixbuf(GTK_IMAGE(sp->image), pb);
52
53         sp->frame = frame;
54 }
55
56 static void spinner_increment_frame(SpinnerData *sp)
57 {
58         sp->frame++;
59         if (sp->frame >= g_list_length(sp->list)) sp->frame = 1;
60         spinner_set_frame(sp, sp->frame);
61 }
62
63 static gboolean spinner_loop_cb(gpointer data)
64 {
65         SpinnerData *sp = static_cast<SpinnerData *>(data);
66
67         if (sp->list) spinner_increment_frame(sp);
68
69         return TRUE;
70 }
71
72 static void spinner_set_timeout(SpinnerData *sp, gint interval)
73 {
74         if (!sp) return;
75
76         if (sp->timer_id)
77                 {
78                 g_source_remove(sp->timer_id);
79                 sp->timer_id = 0;
80                 }
81
82         if (interval > 0)
83                 {
84                 sp->timer_id = g_timeout_add(interval, spinner_loop_cb, sp);
85                 }
86         else if (interval < 0)
87                 {
88                 spinner_set_frame(sp, 0);
89                 }
90
91         gtk_widget_set_sensitive(sp->image, (interval >= 0));
92 }
93
94 static void spinner_destroy_cb(GtkWidget *UNUSED(widget), gpointer data)
95 {
96         SpinnerData *sp = static_cast<SpinnerData *>(data);
97         GList *work;
98
99         spinner_set_timeout(sp, 0);
100
101         work = sp->list;
102         while (work)
103                 {
104                 GdkPixbuf *pb = static_cast<GdkPixbuf *>(work->data);
105                 work = work->next;
106
107                 g_object_unref(pb);
108                 }
109         g_list_free(sp->list);
110         g_free(sp);
111 }
112
113 GtkWidget *spinner_new(const gchar *path, gint interval)
114 {
115         SpinnerData *sp;
116
117         sp = g_new0(SpinnerData, 1);
118
119         if (path)
120                 {
121                 gchar *pathl;
122                 GdkPixbuf *pb;
123                 gint n;
124                 gchar *buf;
125
126                 pathl = path_from_utf8(path);
127
128                 n = 0;
129                 buf = g_strdup_printf("%s%02d.png", pathl, n);
130                 while ((pb = gdk_pixbuf_new_from_file(buf, NULL)))
131                         {
132                         sp->list = g_list_append(sp->list, pb);
133
134                         n++;
135                         g_free(buf);
136                         buf = g_strdup_printf("%s%02d.png", pathl, n);
137                         }
138                 g_free(buf);
139
140                 g_free(pathl);
141                 }
142
143         if (!sp->list)
144                 {
145                 GdkPixbuf *pb;
146                 gint n;
147                 gint w, h;
148
149                 pb = gdk_pixbuf_new_from_inline(-1, icon_spinner, FALSE, NULL);
150                 w = gdk_pixbuf_get_width(pb);
151                 h = gdk_pixbuf_get_height(pb) / SPINNER_FRAMES;
152                 for (n = 0; n < SPINNER_FRAMES; n++)
153                         {
154                         sp->list = g_list_append(sp->list,
155                                                  gdk_pixbuf_new_subpixbuf(pb, 0, n * h, w, h));
156                         }
157                 /* pb pixels is inline static, so the subpixbufs in sp->list will be ok */
158                 g_object_unref(pb);
159                 }
160
161         if (sp->list)
162                 {
163                 GdkPixbuf *pb;
164
165                 pb = static_cast<GdkPixbuf *>(sp->list->data);
166                 sp->image = gtk_image_new_from_pixbuf(pb);
167                 }
168         else
169                 {
170                 sp->image = gtk_image_new_from_stock(GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_DIALOG);
171                 }
172
173         g_object_set_data(G_OBJECT(sp->image), "spinner", sp);
174
175         g_signal_connect(G_OBJECT(sp->image), "destroy",
176                          G_CALLBACK(spinner_destroy_cb), sp);
177
178         spinner_set_timeout(sp, interval);
179
180         return sp->image;
181 }
182
183 void spinner_set_interval(GtkWidget *spinner, gint interval)
184 {
185         SpinnerData *sp;
186
187         sp = static_cast<SpinnerData *>(g_object_get_data(G_OBJECT(spinner), "spinner"));
188
189         spinner_set_timeout(sp, interval);
190 }
191
192 //void spinner_step(GtkWidget *spinner, gboolean reset)
193 //{
194         //SpinnerData *sp;
195
196         //sp = g_object_get_data(G_OBJECT(spinner), "spinner");
197         //if (sp->timer_id)
198                 //{
199                 //log_printf("spinner warning: attempt to step with timer set\n");
200                 //return;
201                 //}
202
203         //if (reset)
204                 //{
205                 //spinner_set_frame(sp, 0);
206                 //}
207         //else
208                 //{
209                 //spinner_increment_frame(sp);
210                 //}
211 //}
212 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */