00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00036 #ifdef HAVE_CONFIG_H
00037 #include <config.h>
00038 #endif
00039
00040 #include "gedit-spinner.h"
00041
00042 #include <gdk-pixbuf/gdk-pixbuf.h>
00043 #include <gtk/gtk.h>
00044
00045
00046
00047 #define GEDIT_TYPE_SPINNER_CACHE (gedit_spinner_cache_get_type())
00048 #define GEDIT_SPINNER_CACHE(object) (G_TYPE_CHECK_INSTANCE_CAST((object), GEDIT_TYPE_SPINNER_CACHE, GeditSpinnerCache))
00049 #define GEDIT_SPINNER_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_SPINNER_CACHE, GeditSpinnerCacheClass))
00050 #define GEDIT_IS_SPINNER_CACHE(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), GEDIT_TYPE_SPINNER_CACHE))
00051 #define GEDIT_IS_SPINNER_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GEDIT_TYPE_SPINNER_CACHE))
00052 #define GEDIT_SPINNER_CACHE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_SPINNER_CACHE, GeditSpinnerCacheClass))
00053
00054 typedef struct _GeditSpinnerCache GeditSpinnerCache;
00055 typedef struct _GeditSpinnerCacheClass GeditSpinnerCacheClass;
00056 typedef struct _GeditSpinnerCachePrivate GeditSpinnerCachePrivate;
00057
00058 struct _GeditSpinnerCacheClass
00059 {
00060 GObjectClass parent_class;
00061 };
00062
00063 struct _GeditSpinnerCache
00064 {
00065 GObject parent_object;
00066
00067
00068 GeditSpinnerCachePrivate *priv;
00069 };
00070
00071 #define GEDIT_SPINNER_CACHE_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_SPINNER_CACHE, GeditSpinnerCachePrivate))
00072
00073 struct _GeditSpinnerCachePrivate
00074 {
00075
00076 GHashTable *hash;
00077 };
00078
00079 typedef struct
00080 {
00081 guint ref_count;
00082 GtkIconSize size;
00083 gint width;
00084 gint height;
00085 GdkPixbuf **animation_pixbufs;
00086 guint n_animation_pixbufs;
00087 } GeditSpinnerImages;
00088
00089 #define LAST_ICON_SIZE GTK_ICON_SIZE_DIALOG + 1
00090 #define SPINNER_ICON_NAME "process-working"
00091 #define SPINNER_FALLBACK_ICON_NAME "gnome-spinner"
00092 #define GEDIT_SPINNER_IMAGES_INVALID ((GeditSpinnerImages *) 0x1)
00093
00094 typedef struct
00095 {
00096 GdkScreen *screen;
00097 GtkIconTheme *icon_theme;
00098 GeditSpinnerImages *images[LAST_ICON_SIZE];
00099 } GeditSpinnerCacheData;
00100
00101 static void gedit_spinner_cache_class_init (GeditSpinnerCacheClass *klass);
00102 static void gedit_spinner_cache_init (GeditSpinnerCache *cache);
00103
00104 static GObjectClass *gedit_spinner_cache_parent_class;
00105
00106 static GType
00107 gedit_spinner_cache_get_type (void)
00108 {
00109 static GType type = 0;
00110
00111 if (G_UNLIKELY (type == 0))
00112 {
00113 const GTypeInfo our_info =
00114 {
00115 sizeof (GeditSpinnerCacheClass),
00116 NULL,
00117 NULL,
00118 (GClassInitFunc) gedit_spinner_cache_class_init,
00119 NULL,
00120 NULL,
00121 sizeof (GeditSpinnerCache),
00122 0,
00123 (GInstanceInitFunc) gedit_spinner_cache_init
00124 };
00125
00126 type = g_type_register_static (G_TYPE_OBJECT,
00127 "GeditSpinnerCache",
00128 &our_info, 0);
00129 }
00130
00131 return type;
00132 }
00133
00134 static GeditSpinnerImages *
00135 gedit_spinner_images_ref (GeditSpinnerImages *images)
00136 {
00137 g_return_val_if_fail (images != NULL, NULL);
00138
00139 images->ref_count++;
00140
00141 return images;
00142 }
00143
00144 static void
00145 gedit_spinner_images_unref (GeditSpinnerImages *images)
00146 {
00147 g_return_if_fail (images != NULL);
00148
00149 images->ref_count--;
00150 if (images->ref_count == 0)
00151 {
00152 guint i;
00153
00154
00155
00156 for (i = 0; i < images->n_animation_pixbufs; ++i)
00157 {
00158 g_object_unref (images->animation_pixbufs[i]);
00159 }
00160 g_free (images->animation_pixbufs);
00161
00162 g_free (images);
00163 }
00164 }
00165
00166 static void
00167 gedit_spinner_cache_data_unload (GeditSpinnerCacheData *data)
00168 {
00169 GtkIconSize size;
00170 GeditSpinnerImages *images;
00171
00172 g_return_if_fail (data != NULL);
00173
00174
00175
00176 for (size = GTK_ICON_SIZE_INVALID; size < LAST_ICON_SIZE; ++size)
00177 {
00178 images = data->images[size];
00179 data->images[size] = NULL;
00180
00181 if (images != NULL && images != GEDIT_SPINNER_IMAGES_INVALID)
00182 {
00183 gedit_spinner_images_unref (images);
00184 }
00185 }
00186 }
00187
00188 static GdkPixbuf *
00189 extract_frame (GdkPixbuf *grid_pixbuf,
00190 int x,
00191 int y,
00192 int size)
00193 {
00194 GdkPixbuf *pixbuf;
00195
00196 if (x + size > gdk_pixbuf_get_width (grid_pixbuf) ||
00197 y + size > gdk_pixbuf_get_height (grid_pixbuf))
00198 {
00199 return NULL;
00200 }
00201
00202 pixbuf = gdk_pixbuf_new_subpixbuf (grid_pixbuf,
00203 x, y,
00204 size, size);
00205 g_return_val_if_fail (pixbuf != NULL, NULL);
00206
00207 return pixbuf;
00208 }
00209
00210 static GdkPixbuf *
00211 scale_to_size (GdkPixbuf *pixbuf,
00212 int dw,
00213 int dh)
00214 {
00215 GdkPixbuf *result;
00216 int pw, ph;
00217
00218 g_return_val_if_fail (pixbuf != NULL, NULL);
00219
00220 pw = gdk_pixbuf_get_width (pixbuf);
00221 ph = gdk_pixbuf_get_height (pixbuf);
00222
00223 if (pw != dw || ph != dh)
00224 {
00225 result = gdk_pixbuf_scale_simple (pixbuf, dw, dh,
00226 GDK_INTERP_BILINEAR);
00227 g_object_unref (pixbuf);
00228 return result;
00229 }
00230
00231 return pixbuf;
00232 }
00233
00234 static GeditSpinnerImages *
00235 gedit_spinner_images_load (GdkScreen *screen,
00236 GtkIconTheme *icon_theme,
00237 GtkIconSize icon_size)
00238 {
00239 GeditSpinnerImages *images;
00240 GdkPixbuf *icon_pixbuf, *pixbuf;
00241 GtkIconInfo *icon_info = NULL;
00242 int grid_width, grid_height, x, y, requested_size, size, isw, ish, n;
00243 const char *icon;
00244 GSList *list = NULL, *l;
00245
00246
00247
00248
00249
00250 if (!gtk_icon_size_lookup_for_settings (gtk_settings_get_for_screen (screen),
00251 icon_size, &isw, &ish))
00252 goto loser;
00253
00254 requested_size = MAX (ish, isw);
00255
00256
00257 icon_info = gtk_icon_theme_lookup_icon (icon_theme,
00258 SPINNER_ICON_NAME,
00259 requested_size, 0);
00260 if (icon_info == NULL)
00261 {
00262 g_warning ("Throbber animation not found");
00263
00264
00265 icon_info = gtk_icon_theme_lookup_icon (icon_theme,
00266 SPINNER_FALLBACK_ICON_NAME,
00267 requested_size, 0);
00268 if (icon_info == NULL)
00269 {
00270 g_warning ("Throbber fallback animation not found either");
00271 goto loser;
00272 }
00273 }
00274
00275 g_assert (icon_info != NULL);
00276
00277 size = gtk_icon_info_get_base_size (icon_info);
00278 icon = gtk_icon_info_get_filename (icon_info);
00279
00280 if (icon == NULL)
00281 goto loser;
00282
00283 icon_pixbuf = gdk_pixbuf_new_from_file (icon, NULL);
00284 gtk_icon_info_free (icon_info);
00285 icon_info = NULL;
00286
00287 if (icon_pixbuf == NULL)
00288 {
00289 g_warning ("Could not load the spinner file");
00290 goto loser;
00291 }
00292
00293 grid_width = gdk_pixbuf_get_width (icon_pixbuf);
00294 grid_height = gdk_pixbuf_get_height (icon_pixbuf);
00295
00296 n = 0;
00297 for (y = 0; y < grid_height; y += size)
00298 {
00299 for (x = 0; x < grid_width ; x += size)
00300 {
00301 pixbuf = extract_frame (icon_pixbuf, x, y, size);
00302
00303 if (pixbuf)
00304 {
00305 list = g_slist_prepend (list, pixbuf);
00306 ++n;
00307 }
00308 else
00309 {
00310 g_warning ("Cannot extract frame (%d, %d) from the grid\n", x, y);
00311 }
00312 }
00313 }
00314
00315 g_object_unref (icon_pixbuf);
00316
00317 if (list == NULL)
00318 goto loser;
00319
00320
00321
00322 if (size > requested_size)
00323 {
00324 for (l = list; l != NULL; l = l->next)
00325 {
00326 l->data = scale_to_size (l->data, isw, ish);
00327 }
00328 }
00329
00330
00331 images = g_new (GeditSpinnerImages, 1);
00332 images->ref_count = 1;
00333
00334 images->size = icon_size;
00335 images->width = images->height = requested_size;
00336
00337 images->n_animation_pixbufs = n;
00338 images->animation_pixbufs = g_new (GdkPixbuf *, n);
00339
00340 for (l = list; l != NULL; l = l->next)
00341 {
00342 g_assert (l->data != NULL);
00343 images->animation_pixbufs[--n] = l->data;
00344 }
00345 g_assert (n == 0);
00346
00347 g_slist_free (list);
00348
00349
00350 return images;
00351
00352 loser:
00353 if (icon_info)
00354 {
00355 gtk_icon_info_free (icon_info);
00356 }
00357
00358 g_slist_foreach (list, (GFunc) g_object_unref, NULL);
00359
00360
00361
00362 return NULL;
00363 }
00364
00365 static GeditSpinnerCacheData *
00366 gedit_spinner_cache_data_new (GdkScreen *screen)
00367 {
00368 GeditSpinnerCacheData *data;
00369
00370 data = g_new0 (GeditSpinnerCacheData, 1);
00371
00372 data->screen = screen;
00373 data->icon_theme = gtk_icon_theme_get_for_screen (screen);
00374 g_signal_connect_swapped (data->icon_theme,
00375 "changed",
00376 G_CALLBACK (gedit_spinner_cache_data_unload),
00377 data);
00378
00379 return data;
00380 }
00381
00382 static void
00383 gedit_spinner_cache_data_free (GeditSpinnerCacheData *data)
00384 {
00385 g_return_if_fail (data != NULL);
00386 g_return_if_fail (data->icon_theme != NULL);
00387
00388 g_signal_handlers_disconnect_by_func (data->icon_theme,
00389 G_CALLBACK (gedit_spinner_cache_data_unload),
00390 data);
00391
00392 gedit_spinner_cache_data_unload (data);
00393
00394 g_free (data);
00395 }
00396
00397 static GeditSpinnerImages *
00398 gedit_spinner_cache_get_images (GeditSpinnerCache *cache,
00399 GdkScreen *screen,
00400 GtkIconSize icon_size)
00401 {
00402 GeditSpinnerCachePrivate *priv = cache->priv;
00403 GeditSpinnerCacheData *data;
00404 GeditSpinnerImages *images;
00405
00406
00407
00408 g_return_val_if_fail (icon_size >= 0 && icon_size < LAST_ICON_SIZE, NULL);
00409
00410
00411 if (icon_size == GTK_ICON_SIZE_INVALID)
00412 {
00413 icon_size = GTK_ICON_SIZE_DIALOG;
00414 }
00415
00416 data = g_hash_table_lookup (priv->hash, screen);
00417 if (data == NULL)
00418 {
00419 data = gedit_spinner_cache_data_new (screen);
00420
00421 g_hash_table_insert (priv->hash, screen, data);
00422 }
00423
00424 images = data->images[icon_size];
00425 if (images == GEDIT_SPINNER_IMAGES_INVALID)
00426 {
00427
00428 return NULL;
00429 }
00430
00431 if (images != NULL)
00432 {
00433
00434 return gedit_spinner_images_ref (images);
00435 }
00436
00437 images = gedit_spinner_images_load (screen, data->icon_theme, icon_size);
00438
00439 if (images == NULL)
00440 {
00441
00442 data->images[icon_size] = GEDIT_SPINNER_IMAGES_INVALID;
00443
00444 return NULL;
00445 }
00446
00447 data->images[icon_size] = images;
00448
00449 return gedit_spinner_images_ref (images);
00450 }
00451
00452 static void
00453 gedit_spinner_cache_init (GeditSpinnerCache *cache)
00454 {
00455 GeditSpinnerCachePrivate *priv;
00456
00457 priv = cache->priv = GEDIT_SPINNER_CACHE_GET_PRIVATE (cache);
00458
00459
00460
00461 priv->hash = g_hash_table_new_full (g_direct_hash,
00462 g_direct_equal,
00463 NULL,
00464 (GDestroyNotify) gedit_spinner_cache_data_free);
00465 }
00466
00467 static void
00468 gedit_spinner_cache_finalize (GObject *object)
00469 {
00470 GeditSpinnerCache *cache = GEDIT_SPINNER_CACHE (object);
00471 GeditSpinnerCachePrivate *priv = cache->priv;
00472
00473 g_hash_table_destroy (priv->hash);
00474
00475
00476
00477 G_OBJECT_CLASS (gedit_spinner_cache_parent_class)->finalize (object);
00478 }
00479
00480 static void
00481 gedit_spinner_cache_class_init (GeditSpinnerCacheClass *klass)
00482 {
00483 GObjectClass *object_class = G_OBJECT_CLASS (klass);
00484
00485 gedit_spinner_cache_parent_class = g_type_class_peek_parent (klass);
00486
00487 object_class->finalize = gedit_spinner_cache_finalize;
00488
00489 g_type_class_add_private (object_class, sizeof (GeditSpinnerCachePrivate));
00490 }
00491
00492 static GeditSpinnerCache *spinner_cache = NULL;
00493
00494 static GeditSpinnerCache *
00495 gedit_spinner_cache_ref (void)
00496 {
00497 if (spinner_cache == NULL)
00498 {
00499 GeditSpinnerCache **cache_ptr;
00500
00501 spinner_cache = g_object_new (GEDIT_TYPE_SPINNER_CACHE, NULL);
00502 cache_ptr = &spinner_cache;
00503 g_object_add_weak_pointer (G_OBJECT (spinner_cache),
00504 (gpointer *) cache_ptr);
00505
00506 return spinner_cache;
00507 }
00508
00509 return g_object_ref (spinner_cache);
00510 }
00511
00512
00513
00514 #define SPINNER_TIMEOUT 125
00515
00516 #define GEDIT_SPINNER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_SPINNER, GeditSpinnerPrivate))
00517
00518 struct _GeditSpinnerPrivate
00519 {
00520 GtkIconTheme *icon_theme;
00521 GeditSpinnerCache *cache;
00522 GtkIconSize size;
00523 GeditSpinnerImages *images;
00524 guint current_image;
00525 guint timeout;
00526 guint timer_task;
00527 guint spinning : 1;
00528 guint need_load : 1;
00529 };
00530
00531 static void gedit_spinner_class_init (GeditSpinnerClass *class);
00532 static void gedit_spinner_init (GeditSpinner *spinner);
00533
00534 static GObjectClass *parent_class;
00535
00536 GType
00537 gedit_spinner_get_type (void)
00538 {
00539 static GType type = 0;
00540
00541 if (G_UNLIKELY (type == 0))
00542 {
00543 const GTypeInfo our_info =
00544 {
00545 sizeof (GeditSpinnerClass),
00546 NULL,
00547 NULL,
00548 (GClassInitFunc) gedit_spinner_class_init,
00549 NULL,
00550 NULL,
00551 sizeof (GeditSpinner),
00552 0,
00553 (GInstanceInitFunc) gedit_spinner_init
00554 };
00555
00556 type = g_type_register_static (GTK_TYPE_WIDGET,
00557 "GeditSpinner",
00558 &our_info, 0);
00559 }
00560
00561 return type;
00562 }
00563
00564 static gboolean
00565 gedit_spinner_load_images (GeditSpinner *spinner)
00566 {
00567 GeditSpinnerPrivate *priv = spinner->priv;
00568
00569 if (priv->need_load)
00570 {
00571
00572
00573 priv->images =
00574 gedit_spinner_cache_get_images (priv->cache,
00575 gtk_widget_get_screen (GTK_WIDGET (spinner)),
00576 priv->size);
00577
00578
00579
00580 priv->current_image = 0;
00581 priv->need_load = FALSE;
00582 }
00583
00584 return priv->images != NULL;
00585 }
00586
00587 static void
00588 gedit_spinner_unload_images (GeditSpinner *spinner)
00589 {
00590 GeditSpinnerPrivate *priv = spinner->priv;
00591
00592 if (priv->images != NULL)
00593 {
00594 gedit_spinner_images_unref (priv->images);
00595 priv->images = NULL;
00596 }
00597
00598 priv->current_image = 0;
00599 priv->need_load = TRUE;
00600 }
00601
00602 static void
00603 icon_theme_changed_cb (GtkIconTheme *icon_theme,
00604 GeditSpinner *spinner)
00605 {
00606 gedit_spinner_unload_images (spinner);
00607 gtk_widget_queue_resize (GTK_WIDGET (spinner));
00608 }
00609
00610 static void
00611 gedit_spinner_init (GeditSpinner *spinner)
00612 {
00613 GeditSpinnerPrivate *priv;
00614
00615 priv = spinner->priv = GEDIT_SPINNER_GET_PRIVATE (spinner);
00616
00617 GTK_WIDGET_SET_FLAGS (GTK_WIDGET (spinner), GTK_NO_WINDOW);
00618
00619 priv->cache = gedit_spinner_cache_ref ();
00620 priv->size = GTK_ICON_SIZE_DIALOG;
00621 priv->spinning = FALSE;
00622 priv->timeout = SPINNER_TIMEOUT;
00623 priv->need_load = TRUE;
00624 }
00625
00626 static int
00627 gedit_spinner_expose (GtkWidget *widget,
00628 GdkEventExpose *event)
00629 {
00630 GeditSpinner *spinner = GEDIT_SPINNER (widget);
00631 GeditSpinnerPrivate *priv = spinner->priv;
00632 GeditSpinnerImages *images;
00633 GdkPixbuf *pixbuf;
00634 GdkGC *gc;
00635 int x_offset, y_offset, width, height;
00636 GdkRectangle pix_area, dest;
00637
00638 if (!GTK_WIDGET_DRAWABLE (spinner))
00639 {
00640 return FALSE;
00641 }
00642
00643 if (priv->need_load &&
00644 !gedit_spinner_load_images (spinner))
00645 {
00646 return FALSE;
00647 }
00648
00649 images = priv->images;
00650 if (images == NULL)
00651 {
00652 return FALSE;
00653 }
00654
00655
00656 g_assert (images->n_animation_pixbufs > 0);
00657
00658 g_assert (priv->current_image >= 0 &&
00659 priv->current_image < images->n_animation_pixbufs);
00660
00661 pixbuf = images->animation_pixbufs[priv->current_image];
00662
00663 g_assert (pixbuf != NULL);
00664
00665 width = gdk_pixbuf_get_width (pixbuf);
00666 height = gdk_pixbuf_get_height (pixbuf);
00667
00668
00669 x_offset = (widget->allocation.width - width) / 2;
00670 y_offset = (widget->allocation.height - height) / 2;
00671
00672 pix_area.x = x_offset + widget->allocation.x;
00673 pix_area.y = y_offset + widget->allocation.y;
00674 pix_area.width = width;
00675 pix_area.height = height;
00676
00677 if (!gdk_rectangle_intersect (&event->area, &pix_area, &dest))
00678 {
00679 return FALSE;
00680 }
00681
00682 gc = gdk_gc_new (widget->window);
00683 gdk_draw_pixbuf (widget->window, gc, pixbuf,
00684 dest.x - x_offset - widget->allocation.x,
00685 dest.y - y_offset - widget->allocation.y,
00686 dest.x, dest.y,
00687 dest.width, dest.height,
00688 GDK_RGB_DITHER_MAX, 0, 0);
00689 g_object_unref (gc);
00690
00691 return FALSE;
00692 }
00693
00694 static gboolean
00695 bump_spinner_frame_cb (GeditSpinner *spinner)
00696 {
00697 GeditSpinnerPrivate *priv = spinner->priv;
00698
00699
00700
00701
00702
00703 if (priv->images == NULL)
00704 return TRUE;
00705
00706 priv->current_image++;
00707 if (priv->current_image >= priv->images->n_animation_pixbufs)
00708 {
00709
00710 priv->current_image = MIN (1, priv->images->n_animation_pixbufs);
00711 }
00712
00713 gtk_widget_queue_draw (GTK_WIDGET (spinner));
00714
00715
00716 return TRUE;
00717 }
00718
00725 void
00726 gedit_spinner_start (GeditSpinner *spinner)
00727 {
00728 GeditSpinnerPrivate *priv = spinner->priv;
00729
00730 priv->spinning = TRUE;
00731
00732 if (GTK_WIDGET_MAPPED (GTK_WIDGET (spinner)) &&
00733 priv->timer_task == 0 &&
00734 gedit_spinner_load_images (spinner))
00735 {
00736
00737 priv->current_image = MIN (1, priv->images->n_animation_pixbufs);
00738
00739 priv->timer_task = g_timeout_add_full (G_PRIORITY_LOW,
00740 priv->timeout,
00741 (GSourceFunc) bump_spinner_frame_cb,
00742 spinner,
00743 NULL);
00744 }
00745 }
00746
00747 static void
00748 gedit_spinner_remove_update_callback (GeditSpinner *spinner)
00749 {
00750 GeditSpinnerPrivate *priv = spinner->priv;
00751
00752 if (priv->timer_task != 0)
00753 {
00754 g_source_remove (priv->timer_task);
00755 priv->timer_task = 0;
00756 }
00757 }
00758
00765 void
00766 gedit_spinner_stop (GeditSpinner *spinner)
00767 {
00768 GeditSpinnerPrivate *priv = spinner->priv;
00769
00770 priv->spinning = FALSE;
00771 priv->current_image = 0;
00772
00773 if (priv->timer_task != 0)
00774 {
00775 gedit_spinner_remove_update_callback (spinner);
00776
00777 if (GTK_WIDGET_MAPPED (GTK_WIDGET (spinner)))
00778 gtk_widget_queue_draw (GTK_WIDGET (spinner));
00779 }
00780 }
00781
00782
00783
00784
00785
00786
00787
00788
00789 void
00790 gedit_spinner_set_size (GeditSpinner *spinner,
00791 GtkIconSize size)
00792 {
00793 if (size == GTK_ICON_SIZE_INVALID)
00794 {
00795 size = GTK_ICON_SIZE_DIALOG;
00796 }
00797
00798 if (size != spinner->priv->size)
00799 {
00800 gedit_spinner_unload_images (spinner);
00801
00802 spinner->priv->size = size;
00803
00804 gtk_widget_queue_resize (GTK_WIDGET (spinner));
00805 }
00806 }
00807
00808 #if 0
00809
00810
00811
00812
00813
00814
00815
00816 void
00817 gedit_spinner_set_timeout (GeditSpinner *spinner,
00818 guint timeout)
00819 {
00820 GeditSpinnerPrivate *priv = spinner->priv;
00821
00822 if (timeout != priv->timeout)
00823 {
00824 gedit_spinner_stop (spinner);
00825
00826 priv->timeout = timeout;
00827
00828 if (priv->spinning)
00829 {
00830 gedit_spinner_start (spinner);
00831 }
00832 }
00833 }
00834 #endif
00835
00836 static void
00837 gedit_spinner_size_request (GtkWidget *widget,
00838 GtkRequisition *requisition)
00839 {
00840 GeditSpinner *spinner = GEDIT_SPINNER (widget);
00841 GeditSpinnerPrivate *priv = spinner->priv;
00842
00843 if ((priv->need_load &&
00844 !gedit_spinner_load_images (spinner)) ||
00845 priv->images == NULL)
00846 {
00847 requisition->width = requisition->height = 0;
00848 gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (widget),
00849 priv->size,
00850 &requisition->width,
00851 &requisition->height);
00852 return;
00853 }
00854
00855 requisition->width = priv->images->width;
00856 requisition->height = priv->images->height;
00857
00858
00859
00860 if (priv->size != GTK_ICON_SIZE_MENU)
00861 {
00862 requisition->width += 2;
00863 requisition->height += 2;
00864 }
00865 }
00866
00867 static void
00868 gedit_spinner_map (GtkWidget *widget)
00869 {
00870 GeditSpinner *spinner = GEDIT_SPINNER (widget);
00871 GeditSpinnerPrivate *priv = spinner->priv;
00872
00873 GTK_WIDGET_CLASS (parent_class)->map (widget);
00874
00875 if (priv->spinning)
00876 {
00877 gedit_spinner_start (spinner);
00878 }
00879 }
00880
00881 static void
00882 gedit_spinner_unmap (GtkWidget *widget)
00883 {
00884 GeditSpinner *spinner = GEDIT_SPINNER (widget);
00885
00886 gedit_spinner_remove_update_callback (spinner);
00887
00888 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
00889 }
00890
00891 static void
00892 gedit_spinner_dispose (GObject *object)
00893 {
00894 GeditSpinner *spinner = GEDIT_SPINNER (object);
00895
00896 g_signal_handlers_disconnect_by_func
00897 (spinner->priv->icon_theme,
00898 G_CALLBACK (icon_theme_changed_cb), spinner);
00899
00900 G_OBJECT_CLASS (parent_class)->dispose (object);
00901 }
00902
00903 static void
00904 gedit_spinner_finalize (GObject *object)
00905 {
00906 GeditSpinner *spinner = GEDIT_SPINNER (object);
00907
00908 gedit_spinner_remove_update_callback (spinner);
00909 gedit_spinner_unload_images (spinner);
00910
00911 g_object_unref (spinner->priv->cache);
00912
00913 G_OBJECT_CLASS (parent_class)->finalize (object);
00914 }
00915
00916 static void
00917 gedit_spinner_screen_changed (GtkWidget *widget,
00918 GdkScreen *old_screen)
00919 {
00920 GeditSpinner *spinner = GEDIT_SPINNER (widget);
00921 GeditSpinnerPrivate *priv = spinner->priv;
00922 GdkScreen *screen;
00923
00924 if (GTK_WIDGET_CLASS (parent_class)->screen_changed)
00925 {
00926 GTK_WIDGET_CLASS (parent_class)->screen_changed (widget, old_screen);
00927 }
00928
00929 screen = gtk_widget_get_screen (widget);
00930
00931
00932 if (old_screen == screen)
00933 return;
00934
00935
00936
00937
00938 gedit_spinner_remove_update_callback (spinner);
00939
00940 gedit_spinner_unload_images (spinner);
00941
00942 if (old_screen != NULL)
00943 {
00944 g_signal_handlers_disconnect_by_func
00945 (gtk_icon_theme_get_for_screen (old_screen),
00946 G_CALLBACK (icon_theme_changed_cb), spinner);
00947 }
00948
00949 priv->icon_theme = gtk_icon_theme_get_for_screen (screen);
00950 g_signal_connect (priv->icon_theme, "changed",
00951 G_CALLBACK (icon_theme_changed_cb), spinner);
00952 }
00953
00954 static void
00955 gedit_spinner_class_init (GeditSpinnerClass *class)
00956 {
00957 GObjectClass *object_class = G_OBJECT_CLASS (class);
00958 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
00959
00960 parent_class = g_type_class_peek_parent (class);
00961
00962 object_class->dispose = gedit_spinner_dispose;
00963 object_class->finalize = gedit_spinner_finalize;
00964
00965 widget_class->expose_event = gedit_spinner_expose;
00966 widget_class->size_request = gedit_spinner_size_request;
00967 widget_class->map = gedit_spinner_map;
00968 widget_class->unmap = gedit_spinner_unmap;
00969 widget_class->screen_changed = gedit_spinner_screen_changed;
00970
00971 g_type_class_add_private (object_class, sizeof (GeditSpinnerPrivate));
00972 }
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983 GtkWidget *
00984 gedit_spinner_new (void)
00985 {
00986 return GTK_WIDGET (g_object_new (GEDIT_TYPE_SPINNER, NULL));
00987 }