Add powerbox hook
[gtk-with-powerbox.git] / demos / testanimation.c
blobfa29585079220351c797927528215f72999e6167
2 /* testpixbuf -- test program for gdk-pixbuf code
3 * Copyright (C) 1999 Mark Crichton, Larry Ewing
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
21 #include "config.h"
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <gtk/gtk.h>
29 typedef struct _LoadContext LoadContext;
31 struct _LoadContext
33 gchar *filename;
34 GtkWidget *window;
35 GdkPixbufLoader *pixbuf_loader;
36 guint load_timeout;
37 FILE* image_stream;
40 static void
41 destroy_context (gpointer data)
43 LoadContext *lc = data;
45 g_free (lc->filename);
47 if (lc->load_timeout)
48 g_source_remove (lc->load_timeout);
50 if (lc->image_stream)
51 fclose (lc->image_stream);
53 if (lc->pixbuf_loader)
55 gdk_pixbuf_loader_close (lc->pixbuf_loader, NULL);
56 g_object_unref (lc->pixbuf_loader);
59 g_free (lc);
62 static LoadContext*
63 get_load_context (GtkWidget *image)
65 LoadContext *lc;
67 lc = g_object_get_data (G_OBJECT (image), "lc");
69 if (lc == NULL)
71 lc = g_new0 (LoadContext, 1);
73 g_object_set_data_full (G_OBJECT (image),
74 "lc",
75 lc,
76 destroy_context);
79 return lc;
82 static void
83 progressive_prepared_callback (GdkPixbufLoader* loader,
84 gpointer data)
86 GdkPixbuf* pixbuf;
87 GtkWidget* image;
89 image = GTK_WIDGET (data);
91 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
93 /* Avoid displaying random memory contents, since the pixbuf
94 * isn't filled in yet.
96 gdk_pixbuf_fill (pixbuf, 0xaaaaaaff);
98 /* Could set the pixbuf instead, if we only wanted to display
99 * static images.
101 gtk_image_set_from_animation (GTK_IMAGE (image),
102 gdk_pixbuf_loader_get_animation (loader));
105 static void
106 progressive_updated_callback (GdkPixbufLoader* loader,
107 gint x, gint y, gint width, gint height,
108 gpointer data)
110 GtkWidget* image;
112 image = GTK_WIDGET (data);
114 /* We know the pixbuf inside the GtkImage has changed, but the image
115 * itself doesn't know this; so queue a redraw. If we wanted to be
116 * really efficient, we could use a drawing area or something
117 * instead of a GtkImage, so we could control the exact position of
118 * the pixbuf on the display, then we could queue a draw for only
119 * the updated area of the image.
122 /* We only really need to redraw if the image's animation iterator
123 * is gdk_pixbuf_animation_iter_on_currently_loading_frame(), but
124 * who cares.
127 gtk_widget_queue_draw (image);
130 static gint
131 progressive_timeout (gpointer data)
133 GtkWidget *image;
134 LoadContext *lc;
136 image = GTK_WIDGET (data);
137 lc = get_load_context (image);
139 /* This shows off fully-paranoid error handling, so looks scary.
140 * You could factor out the error handling code into a nice separate
141 * function to make things nicer.
144 if (lc->image_stream)
146 size_t bytes_read;
147 guchar buf[256];
148 GError *error = NULL;
150 bytes_read = fread (buf, 1, 256, lc->image_stream);
152 if (ferror (lc->image_stream))
154 GtkWidget *dialog;
156 dialog = gtk_message_dialog_new (GTK_WINDOW (lc->window),
157 GTK_DIALOG_DESTROY_WITH_PARENT,
158 GTK_MESSAGE_ERROR,
159 GTK_BUTTONS_CLOSE,
160 "Failure reading image file 'alphatest.png': %s",
161 g_strerror (errno));
163 g_signal_connect (dialog, "response",
164 G_CALLBACK (gtk_widget_destroy), NULL);
166 fclose (lc->image_stream);
167 lc->image_stream = NULL;
169 gtk_widget_show (dialog);
171 lc->load_timeout = 0;
173 return FALSE; /* uninstall the timeout */
176 if (!gdk_pixbuf_loader_write (lc->pixbuf_loader,
177 buf, bytes_read,
178 &error))
180 GtkWidget *dialog;
182 dialog = gtk_message_dialog_new (GTK_WINDOW (lc->window),
183 GTK_DIALOG_DESTROY_WITH_PARENT,
184 GTK_MESSAGE_ERROR,
185 GTK_BUTTONS_CLOSE,
186 "Failed to load image: %s",
187 error->message);
189 g_error_free (error);
191 g_signal_connect (dialog, "response",
192 G_CALLBACK (gtk_widget_destroy), NULL);
194 fclose (lc->image_stream);
195 lc->image_stream = NULL;
197 gtk_widget_show (dialog);
199 lc->load_timeout = 0;
201 return FALSE; /* uninstall the timeout */
204 if (feof (lc->image_stream))
206 fclose (lc->image_stream);
207 lc->image_stream = NULL;
209 /* Errors can happen on close, e.g. if the image
210 * file was truncated we'll know on close that
211 * it was incomplete.
213 error = NULL;
214 if (!gdk_pixbuf_loader_close (lc->pixbuf_loader,
215 &error))
217 GtkWidget *dialog;
219 dialog = gtk_message_dialog_new (GTK_WINDOW (lc->window),
220 GTK_DIALOG_DESTROY_WITH_PARENT,
221 GTK_MESSAGE_ERROR,
222 GTK_BUTTONS_CLOSE,
223 "Failed to load image: %s",
224 error->message);
226 g_error_free (error);
228 g_signal_connect (dialog, "response",
229 G_CALLBACK (gtk_widget_destroy), NULL);
231 gtk_widget_show (dialog);
233 g_object_unref (lc->pixbuf_loader);
234 lc->pixbuf_loader = NULL;
236 lc->load_timeout = 0;
238 return FALSE; /* uninstall the timeout */
241 g_object_unref (lc->pixbuf_loader);
242 lc->pixbuf_loader = NULL;
245 else
247 lc->image_stream = fopen (lc->filename, "r");
249 if (lc->image_stream == NULL)
251 GtkWidget *dialog;
253 dialog = gtk_message_dialog_new (GTK_WINDOW (lc->window),
254 GTK_DIALOG_DESTROY_WITH_PARENT,
255 GTK_MESSAGE_ERROR,
256 GTK_BUTTONS_CLOSE,
257 "Unable to open image file '%s': %s",
258 lc->filename,
259 g_strerror (errno));
261 g_signal_connect (dialog, "response",
262 G_CALLBACK (gtk_widget_destroy), NULL);
264 gtk_widget_show (dialog);
266 lc->load_timeout = 0;
268 return FALSE; /* uninstall the timeout */
271 if (lc->pixbuf_loader)
273 gdk_pixbuf_loader_close (lc->pixbuf_loader, NULL);
274 g_object_unref (lc->pixbuf_loader);
275 lc->pixbuf_loader = NULL;
278 lc->pixbuf_loader = gdk_pixbuf_loader_new ();
280 g_signal_connect (lc->pixbuf_loader, "area_prepared",
281 G_CALLBACK (progressive_prepared_callback), image);
282 g_signal_connect (lc->pixbuf_loader, "area_updated",
283 G_CALLBACK (progressive_updated_callback), image);
286 /* leave timeout installed */
287 return TRUE;
290 static void
291 start_progressive_loading (GtkWidget *image)
293 LoadContext *lc;
295 lc = get_load_context (image);
297 /* This is obviously totally contrived (we slow down loading
298 * on purpose to show how incremental loading works).
299 * The real purpose of incremental loading is the case where
300 * you are reading data from a slow source such as the network.
301 * The timeout simply simulates a slow data source by inserting
302 * pauses in the reading process.
304 lc->load_timeout = gdk_threads_add_timeout (100,
305 progressive_timeout,
306 image);
309 static GtkWidget *
310 do_image (const char *filename)
312 GtkWidget *frame;
313 GtkWidget *vbox;
314 GtkWidget *image;
315 GtkWidget *label;
316 GtkWidget *align;
317 GtkWidget *window;
318 gchar *str, *escaped;
319 LoadContext *lc;
321 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
322 gtk_window_set_title (GTK_WINDOW (window), "Image Loading");
324 gtk_container_set_border_width (GTK_CONTAINER (window), 8);
326 vbox = gtk_vbox_new (FALSE, 8);
327 gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
328 gtk_container_add (GTK_CONTAINER (window), vbox);
330 label = gtk_label_new (NULL);
331 gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
332 escaped = g_markup_escape_text (filename, -1);
333 str = g_strdup_printf ("Progressively loading: <b>%s</b>", escaped);
334 gtk_label_set_markup (GTK_LABEL (label),
335 str);
336 g_free (escaped);
337 g_free (str);
339 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
341 frame = gtk_frame_new (NULL);
342 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
343 /* The alignment keeps the frame from growing when users resize
344 * the window
346 align = gtk_alignment_new (0.5, 0.5, 0, 0);
347 gtk_container_add (GTK_CONTAINER (align), frame);
348 gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 0);
350 image = gtk_image_new_from_pixbuf (NULL);
351 gtk_container_add (GTK_CONTAINER (frame), image);
353 lc = get_load_context (image);
355 lc->window = window;
356 lc->filename = g_strdup (filename);
358 start_progressive_loading (image);
360 g_signal_connect (window, "destroy",
361 G_CALLBACK (gtk_main_quit), NULL);
363 g_signal_connect (window, "delete_event",
364 G_CALLBACK (gtk_main_quit), NULL);
366 gtk_widget_show_all (window);
368 return window;
371 static void
372 do_nonprogressive (const gchar *filename)
374 GtkWidget *frame;
375 GtkWidget *vbox;
376 GtkWidget *image;
377 GtkWidget *label;
378 GtkWidget *align;
379 GtkWidget *window;
380 gchar *str, *escaped;
382 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
383 gtk_window_set_title (GTK_WINDOW (window), "Animation");
385 gtk_container_set_border_width (GTK_CONTAINER (window), 8);
387 vbox = gtk_vbox_new (FALSE, 8);
388 gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
389 gtk_container_add (GTK_CONTAINER (window), vbox);
391 label = gtk_label_new (NULL);
392 gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
393 escaped = g_markup_escape_text (filename, -1);
394 str = g_strdup_printf ("Loaded from file: <b>%s</b>", escaped);
395 gtk_label_set_markup (GTK_LABEL (label),
396 str);
397 g_free (escaped);
398 g_free (str);
400 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
402 frame = gtk_frame_new (NULL);
403 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
404 /* The alignment keeps the frame from growing when users resize
405 * the window
407 align = gtk_alignment_new (0.5, 0.5, 0, 0);
408 gtk_container_add (GTK_CONTAINER (align), frame);
409 gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 0);
411 image = gtk_image_new_from_file (filename);
412 gtk_container_add (GTK_CONTAINER (frame), image);
414 g_signal_connect (window, "destroy",
415 G_CALLBACK (gtk_main_quit), NULL);
417 g_signal_connect (window, "delete_event",
418 G_CALLBACK (gtk_main_quit), NULL);
420 gtk_widget_show_all (window);
424 main (int argc,
425 char **argv)
427 gint i;
429 gtk_init (&argc, &argv);
431 i = 1;
432 while (i < argc)
434 do_image (argv[i]);
435 do_nonprogressive (argv[i]);
437 ++i;
440 gtk_main ();
442 return 0;