]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/tray-monitor/eggstatusicon.c
Updates for debugging disk seek
[bacula/bacula] / bacula / src / tray-monitor / eggstatusicon.c
1 /* eggstatusicon.c:
2  *
3  * Copyright (C) 2003 Sun Microsystems, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library 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.
9  *
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  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library 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.
19  *
20  * Authors:
21  *      Mark McLoughlin <mark@skynet.ie>
22  *  Nicolas Boichat <nicolas@boichat.ch> (add access to the underlying EggTrayIcon)
23  */
24 /*
25    Bacula® - The Network Backup Solution
26
27    Copyright (C) 2004-2006 Free Software Foundation Europe e.V.
28
29    The main author of Bacula is Kern Sibbald, with contributions from
30    many others, a complete list can be found in the file AUTHORS.
31    This program is Free Software; you can redistribute it and/or
32    modify it under the terms of version two of the GNU General Public
33    License as published by the Free Software Foundation plus additions
34    that are listed in the file LICENSE.
35
36    This program is distributed in the hope that it will be useful, but
37    WITHOUT ANY WARRANTY; without even the implied warranty of
38    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39    General Public License for more details.
40
41    You should have received a copy of the GNU General Public License
42    along with this program; if not, write to the Free Software
43    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
44    02110-1301, USA.
45
46    Bacula® is a registered trademark of John Walker.
47    The licensor of Bacula is the Free Software Foundation Europe
48    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
49    Switzerland, email:ftf@fsfeurope.org.
50 */
51
52 extern "C" {
53
54 #include <string.h>
55 #include <libintl.h>
56
57 #include "eggstatusicon.h"
58
59 #include <gtk/gtk.h>
60 #include "eggmarshalers.h"
61
62 #ifndef EGG_COMPILATION
63 #ifndef _
64 #define _(x) dgettext (GETTEXT_PACKAGE, x)
65 #define N_(x) x
66 #endif
67 #else
68 #define _(x) x
69 #define N_(x) x
70 #endif
71
72 enum{
73   PROP_0,
74   PROP_PIXBUF,
75   PROP_FILE,
76   PROP_STOCK,
77   PROP_PIXBUF_ANIMATION,
78   PROP_STORAGE_TYPE,
79   PROP_SIZE,
80   PROP_BLINKING
81 };
82
83 enum {
84   ACTIVATE_SIGNAL,
85   POPUP_MENU_SIGNAL,
86   SIZE_CHANGED_SIGNAL,
87   LAST_SIGNAL
88 };
89
90 struct _EggStatusIconPrivate
91 {
92   GtkWidget    *tray_icon;
93   GtkWidget    *image;
94   gint          size;
95
96   GtkTooltips  *tooltips;
97
98   GtkImageType  image_type;
99
100   union
101     {
102       GdkPixbuf          *pixbuf;
103       const gchar        *stock_id;
104       GdkPixbufAnimation *animimation;
105     } image_data;
106
107   GdkPixbuf    *blank_icon;
108   guint         blinking_timeout;
109
110   guint         blinking : 1;
111   guint         blink_off : 1;
112 };
113
114 static void egg_status_icon_class_init (EggStatusIconClass *klass);
115 static void egg_status_icon_init       (EggStatusIcon      *status_icon);
116
117 static void egg_status_icon_finalize     (GObject      *object);
118 static void egg_status_icon_set_property (GObject      *object,
119                                           guint         prop_id,
120                                           const GValue *value,
121                                           GParamSpec   *pspec);
122 static void egg_status_icon_get_property (GObject      *object,
123                                           guint         prop_id,
124                                           GValue       *value,
125                                           GParamSpec   *pspec);
126
127 static void     egg_status_icon_size_allocate    (EggStatusIcon  *status_icon,
128                                                   GtkAllocation  *allocation);
129 static gboolean egg_status_icon_button_release   (EggStatusIcon  *status_icon,
130                                                   GdkEventButton *event);
131 static void     egg_status_icon_disable_blinking (EggStatusIcon  *status_icon);
132 static void     egg_status_icon_reset_image_data (EggStatusIcon  *status_icon);
133
134
135 static GObjectClass *parent_class = NULL;
136 static guint status_icon_signals [LAST_SIGNAL] = { 0 };
137
138 GType
139 egg_status_icon_get_type (void)
140 {
141   static GType status_icon_type = 0;
142
143   if (!status_icon_type)
144     {
145       static const GTypeInfo status_icon_info =
146       {
147         sizeof (EggStatusIconClass),
148         NULL,           /* base_init */
149         NULL,           /* base_finalize */
150         (GClassInitFunc) egg_status_icon_class_init,
151         NULL,           /* class_finalize */
152         NULL,           /* class_data */
153         sizeof (EggStatusIcon),
154         0,              /* n_preallocs */
155         (GInstanceInitFunc) egg_status_icon_init,
156       };
157
158       status_icon_type = g_type_register_static (G_TYPE_OBJECT,
159                                                  "EggStatusIcon",
160                                                  &status_icon_info, (GTypeFlags)0);
161     }
162
163   return status_icon_type;
164 }
165
166 static void
167 egg_status_icon_class_init (EggStatusIconClass *klass)
168 {
169   GObjectClass *gobject_class = (GObjectClass *) klass;
170
171   parent_class = (GObjectClass*)g_type_class_peek_parent (klass);
172
173   gobject_class->finalize     = egg_status_icon_finalize;
174   gobject_class->set_property = egg_status_icon_set_property;
175   gobject_class->get_property = egg_status_icon_get_property;
176
177   g_object_class_install_property (gobject_class,
178                                    PROP_PIXBUF,
179                                    g_param_spec_object ("pixbuf",
180                                                         "Pixbuf",
181                                                         "A GdkPixbuf to display",
182                                                         GDK_TYPE_PIXBUF,
183                                                         (GParamFlags)G_PARAM_READWRITE));
184
185   g_object_class_install_property (gobject_class,
186                                    PROP_FILE,
187                                    g_param_spec_string ("file",
188                                                         "Filename",
189                                                         "Filename to load and display",
190                                                         NULL,
191                                                         G_PARAM_WRITABLE));
192
193   g_object_class_install_property (gobject_class,
194                                    PROP_STOCK,
195                                    g_param_spec_string ("stock",
196                                                         "Stock ID",
197                                                         "Stock ID for a stock image to display",
198                                                         NULL,
199                                                         (GParamFlags)G_PARAM_READWRITE));
200
201   g_object_class_install_property (gobject_class,
202                                    PROP_PIXBUF_ANIMATION,
203                                    g_param_spec_object ("pixbuf-animation",
204                                                         "Animation",
205                                                         "GdkPixbufAnimation to display",
206                                                         GDK_TYPE_PIXBUF_ANIMATION,
207                                                         (GParamFlags)G_PARAM_READWRITE));
208
209   g_object_class_install_property (gobject_class,
210                                    PROP_STORAGE_TYPE,
211                                    g_param_spec_enum ("image-type",
212                                                       "Image type",
213                                                       "The representation being used for image data",
214                                                       GTK_TYPE_IMAGE_TYPE,
215                                                       GTK_IMAGE_EMPTY,
216                                                       G_PARAM_READABLE));
217
218   g_object_class_install_property (gobject_class,
219                                    PROP_SIZE,
220                                    g_param_spec_int ("size",
221                                                      "Size",
222                                                      "The size of the icon",
223                                                      G_MININT,
224                                                      G_MAXINT,
225                                                      0,
226                                                      G_PARAM_READABLE));
227
228   g_object_class_install_property (gobject_class,
229                                    PROP_BLINKING,
230                                    g_param_spec_boolean ("blinking",
231                                                          "Blinking",
232                                                          "Whether or not the status icon is blinking",
233                                                          FALSE,
234                                                          (GParamFlags)G_PARAM_READWRITE));
235
236   status_icon_signals [ACTIVATE_SIGNAL] =
237     g_signal_new ("activate",
238                   G_TYPE_FROM_CLASS (gobject_class),
239                   (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
240                   G_STRUCT_OFFSET (EggStatusIconClass, activate),
241                   NULL,
242                   NULL,
243                   g_cclosure_marshal_VOID__VOID,
244                   G_TYPE_NONE,
245                   0);
246
247   status_icon_signals [POPUP_MENU_SIGNAL] =
248     g_signal_new ("popup-menu",
249                   G_TYPE_FROM_CLASS (gobject_class),
250                   (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
251                   G_STRUCT_OFFSET (EggStatusIconClass, popup_menu),
252                   NULL,
253                   NULL,
254                   _egg_marshal_VOID__UINT_UINT,
255                   G_TYPE_NONE,
256                   2,
257                   G_TYPE_UINT,
258                   G_TYPE_UINT);
259
260   status_icon_signals [SIZE_CHANGED_SIGNAL] =
261     g_signal_new ("size-changed",
262                   G_TYPE_FROM_CLASS (gobject_class),
263                   G_SIGNAL_RUN_FIRST,
264                   G_STRUCT_OFFSET (EggStatusIconClass, size_changed),
265                   NULL,
266                   NULL,
267                   g_cclosure_marshal_VOID__INT,
268                   G_TYPE_NONE,
269                   1,
270                   G_TYPE_INT);
271 }
272
273 static void
274 egg_status_icon_init (EggStatusIcon *status_icon)
275 {
276   status_icon->priv = g_new0 (EggStatusIconPrivate, 1);
277
278   status_icon->priv->image_type = GTK_IMAGE_EMPTY;
279   status_icon->priv->size       = G_MAXINT;
280
281   status_icon->priv->tray_icon = GTK_WIDGET (egg_tray_icon_new (NULL));
282
283   gtk_widget_add_events (GTK_WIDGET (status_icon->priv->tray_icon),
284                          GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
285
286   g_signal_connect_swapped (status_icon->priv->tray_icon, "button-release-event",
287                             G_CALLBACK (egg_status_icon_button_release), status_icon);
288
289   status_icon->priv->image = gtk_image_new ();
290   gtk_container_add (GTK_CONTAINER (status_icon->priv->tray_icon),
291                      status_icon->priv->image);
292
293   g_signal_connect_swapped (status_icon->priv->image, "size-allocate",
294                             G_CALLBACK (egg_status_icon_size_allocate), status_icon);
295
296   gtk_widget_show (status_icon->priv->image);
297   gtk_widget_show (status_icon->priv->tray_icon);
298
299   status_icon->priv->tooltips = gtk_tooltips_new ();
300   g_object_ref (status_icon->priv->tooltips);
301   gtk_object_sink (GTK_OBJECT (status_icon->priv->tooltips));
302 }
303
304 static void
305 egg_status_icon_finalize (GObject *object)
306 {
307   EggStatusIcon *status_icon = EGG_STATUS_ICON (object);
308
309   egg_status_icon_disable_blinking (status_icon);
310
311   egg_status_icon_reset_image_data (status_icon);
312
313   if (status_icon->priv->blank_icon)
314     g_object_unref (status_icon->priv->blank_icon);
315   status_icon->priv->blank_icon = NULL;
316
317   if (status_icon->priv->tooltips)
318     g_object_unref (status_icon->priv->tooltips);
319   status_icon->priv->tooltips = NULL;
320
321   gtk_widget_destroy (status_icon->priv->tray_icon);
322
323   g_free (status_icon->priv);
324
325   G_OBJECT_CLASS (parent_class)->finalize (object);
326 }
327
328 static void
329 egg_status_icon_set_property (GObject      *object,
330                               guint         prop_id,
331                               const GValue *value,
332                               GParamSpec   *pspec)
333 {
334   EggStatusIcon *status_icon = EGG_STATUS_ICON (object);
335
336   switch (prop_id)
337     {
338     case PROP_PIXBUF:
339       egg_status_icon_set_from_pixbuf (status_icon, (GdkPixbuf*)g_value_get_object (value));
340       break;
341     case PROP_FILE:
342       egg_status_icon_set_from_file (status_icon, g_value_get_string (value));
343       break;
344     case PROP_STOCK:
345       egg_status_icon_set_from_stock (status_icon, g_value_get_string (value));
346       break;
347     case PROP_PIXBUF_ANIMATION:
348       egg_status_icon_set_from_animation (status_icon, (GdkPixbufAnimation*)g_value_get_object (value));
349       break;
350     case PROP_BLINKING:
351       egg_status_icon_set_is_blinking (status_icon, g_value_get_boolean (value));
352       break;
353     default:
354       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
355       break;
356     }
357 }
358
359 static void
360 egg_status_icon_get_property (GObject    *object,
361                               guint       prop_id,
362                               GValue     *value,
363                               GParamSpec *pspec)
364 {
365   EggStatusIcon *status_icon = EGG_STATUS_ICON (object);
366
367   switch (prop_id)
368     {
369     case PROP_PIXBUF:
370       g_value_set_object (value, egg_status_icon_get_pixbuf (status_icon));
371       break;
372     case PROP_STOCK:
373       g_value_set_string (value, egg_status_icon_get_stock (status_icon));
374       break;
375     case PROP_PIXBUF_ANIMATION:
376       g_value_set_object (value, egg_status_icon_get_animation (status_icon));
377       break;
378     case PROP_STORAGE_TYPE:
379       g_value_set_enum (value, egg_status_icon_get_image_type (status_icon));
380       break;
381     case PROP_SIZE:
382       g_value_set_int (value, status_icon->priv->size);
383       break;
384     case PROP_BLINKING:
385       g_value_set_boolean (value, status_icon->priv->blinking);
386       break;
387     default:
388       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
389       break;
390     }
391 }
392
393 EggStatusIcon *
394 egg_status_icon_new (void)
395 {
396   return (EggStatusIcon*)g_object_new (EGG_TYPE_STATUS_ICON, NULL);
397 }
398
399 EggStatusIcon *
400 egg_status_icon_new_from_pixbuf (GdkPixbuf *pixbuf)
401 {
402   return (EggStatusIcon*)g_object_new (EGG_TYPE_STATUS_ICON,
403                        "pixbuf", pixbuf,
404                        NULL);
405 }
406
407 EggStatusIcon *
408 egg_status_icon_new_from_file (const gchar *filename)
409 {
410   return (EggStatusIcon*)g_object_new (EGG_TYPE_STATUS_ICON,
411                        "file", filename,
412                        NULL);
413 }
414
415 EggStatusIcon *
416 egg_status_icon_new_from_stock (const gchar *stock_id)
417 {
418   return (EggStatusIcon*)g_object_new (EGG_TYPE_STATUS_ICON,
419                        "stock", stock_id,
420                        NULL);
421 }
422
423 EggStatusIcon *
424 egg_status_icon_new_from_animation (GdkPixbufAnimation *animation)
425 {
426   return (EggStatusIcon*)g_object_new (EGG_TYPE_STATUS_ICON,
427                        "pixbuf_animation", animation,
428                        NULL);
429 }
430
431 static void
432 emit_activate_signal (EggStatusIcon *status_icon)
433 {
434   g_signal_emit (status_icon,
435                  status_icon_signals [ACTIVATE_SIGNAL], 0);
436 }
437
438 static void
439 emit_popup_menu_signal (EggStatusIcon *status_icon,
440                         guint          button,
441                         guint32        activate_time)
442 {
443   g_signal_emit (status_icon,
444                  status_icon_signals [POPUP_MENU_SIGNAL], 0,
445                  button,
446                  activate_time);
447 }
448
449 static gboolean
450 emit_size_changed_signal (EggStatusIcon *status_icon,
451                           gint           size)
452 {
453   gboolean handled = FALSE;
454
455   g_signal_emit (status_icon,
456                  status_icon_signals [SIZE_CHANGED_SIGNAL], 0,
457                  size,
458                  &handled);
459
460   return handled;
461 }
462
463 static GdkPixbuf *
464 egg_status_icon_blank_icon (EggStatusIcon *status_icon)
465 {
466   if (status_icon->priv->blank_icon)
467     {
468       gint width, height;
469
470       width  = gdk_pixbuf_get_width (status_icon->priv->blank_icon);
471       height = gdk_pixbuf_get_width (status_icon->priv->blank_icon);
472
473       if (width  == status_icon->priv->size &&
474           height == status_icon->priv->size)
475         {
476           return status_icon->priv->blank_icon;
477         }
478       else
479         {
480           g_object_unref (status_icon->priv->blank_icon);
481           status_icon->priv->blank_icon = NULL;
482         }
483     }
484
485   status_icon->priv->blank_icon = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
486                                                   status_icon->priv->size,
487                                                   status_icon->priv->size);
488   if (status_icon->priv->blank_icon)
489     gdk_pixbuf_fill (status_icon->priv->blank_icon, 0);
490
491   return status_icon->priv->blank_icon;
492 }
493
494 static void
495 egg_status_icon_update_image (EggStatusIcon *status_icon)
496 {
497   if (status_icon->priv->blink_off)
498     {
499       gtk_image_set_from_pixbuf (GTK_IMAGE (status_icon->priv->image),
500                                  egg_status_icon_blank_icon (status_icon));
501       return;
502     }
503
504   switch (status_icon->priv->image_type)
505     {
506     case GTK_IMAGE_PIXBUF:
507       {
508         GdkPixbuf *pixbuf;
509
510         pixbuf = status_icon->priv->image_data.pixbuf;
511
512         if (pixbuf)
513           {
514             GdkPixbuf *scaled;
515             gint size;
516             gint width;
517             gint height;
518
519             size = status_icon->priv->size;
520
521             width  = gdk_pixbuf_get_width  (pixbuf);
522             height = gdk_pixbuf_get_height (pixbuf);
523
524             if (width > size || height > size)
525               {
526                 scaled = gdk_pixbuf_scale_simple (pixbuf,
527                                                   MIN (size, width),
528                                                   MIN (size, height),
529                                                   GDK_INTERP_BILINEAR);
530               }
531             else
532               {
533                 scaled = (GdkPixbuf*)g_object_ref (pixbuf);
534               }
535
536             gtk_image_set_from_pixbuf (GTK_IMAGE (status_icon->priv->image), scaled);
537
538             g_object_unref (scaled);
539           }
540         else
541           {
542             gtk_image_set_from_pixbuf (GTK_IMAGE (status_icon->priv->image), NULL);
543           }
544       }
545       break;
546     case GTK_IMAGE_STOCK:
547     case GTK_IMAGE_ANIMATION:
548     case GTK_IMAGE_EMPTY:
549       gtk_image_set_from_pixbuf (GTK_IMAGE (status_icon->priv->image), NULL);
550       break;
551     default:
552       g_assert_not_reached ();
553       break;
554     }
555 }
556
557 static void
558 egg_status_icon_size_allocate (EggStatusIcon *status_icon,
559                                GtkAllocation *allocation)
560 {
561   GtkOrientation orientation;
562   gint size;
563
564   orientation = egg_tray_icon_get_orientation (EGG_TRAY_ICON (status_icon->priv->tray_icon));
565
566   if (orientation == GTK_ORIENTATION_HORIZONTAL)
567     size = allocation->height;
568   else
569     size = allocation->width;
570
571   if (status_icon->priv->size != size)
572     {
573       status_icon->priv->size = size;
574
575       g_object_notify (G_OBJECT (status_icon), "size");
576
577       if (!emit_size_changed_signal (status_icon, size))
578         {
579           egg_status_icon_update_image (status_icon);
580         }
581     }
582 }
583
584 static gboolean
585 egg_status_icon_button_release (EggStatusIcon  *status_icon,
586                                 GdkEventButton *event)
587 {
588   if (event->button == 1)
589     {
590       emit_activate_signal (status_icon);
591       return TRUE;
592     }
593   if (event->button == 3)
594     {
595       emit_popup_menu_signal (status_icon, event->button, event->time);
596       return TRUE;
597     }
598
599   return FALSE;
600 }
601
602 static void
603 egg_status_icon_reset_image_data (EggStatusIcon *status_icon)
604 {
605   switch (status_icon->priv->image_type)
606   {
607     case GTK_IMAGE_PIXBUF:
608       status_icon->priv->image_type = GTK_IMAGE_EMPTY;
609
610       if (status_icon->priv->image_data.pixbuf)
611         g_object_unref (status_icon->priv->image_data.pixbuf);
612       status_icon->priv->image_data.pixbuf = NULL;
613
614       g_object_notify (G_OBJECT (status_icon), "image-type");
615       g_object_notify (G_OBJECT (status_icon), "pixbuf");
616       break;
617     case GTK_IMAGE_STOCK:
618     case GTK_IMAGE_ANIMATION:
619     case GTK_IMAGE_EMPTY:
620       break;
621     default:
622       g_assert_not_reached ();
623       break;
624   }
625 }
626
627 void
628 egg_status_icon_set_from_pixbuf (EggStatusIcon *status_icon,
629                                  GdkPixbuf     *pixbuf)
630 {
631   g_return_if_fail (EGG_IS_STATUS_ICON (status_icon));
632   g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
633
634   if (pixbuf)
635     g_object_ref (pixbuf);
636
637   g_object_freeze_notify (G_OBJECT (status_icon));
638
639   egg_status_icon_reset_image_data (status_icon);
640
641   status_icon->priv->image_type = GTK_IMAGE_PIXBUF;
642   status_icon->priv->image_data.pixbuf = pixbuf;
643
644   g_object_notify (G_OBJECT (status_icon), "image-type");
645   g_object_notify (G_OBJECT (status_icon), "pixbuf");
646
647   g_object_thaw_notify (G_OBJECT (status_icon));
648
649   egg_status_icon_update_image (status_icon);
650 }
651
652 void
653 egg_status_icon_set_from_file (EggStatusIcon *status_icon,
654                                const gchar   *filename)
655 {
656   g_return_if_fail (EGG_IS_STATUS_ICON (status_icon));
657 }
658
659 void
660 egg_status_icon_set_from_stock (EggStatusIcon *status_icon,
661                                 const gchar   *stock_id)
662 {
663   g_return_if_fail (EGG_IS_STATUS_ICON (status_icon));
664 }
665
666 void
667 egg_status_icon_set_from_animation (EggStatusIcon      *status_icon,
668                                     GdkPixbufAnimation *animation)
669 {
670   g_return_if_fail (EGG_IS_STATUS_ICON (status_icon));
671   g_return_if_fail (animation == NULL || GDK_IS_PIXBUF_ANIMATION (animation));
672 }
673
674 GtkImageType
675 egg_status_icon_get_image_type (EggStatusIcon *status_icon)
676 {
677   g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), GTK_IMAGE_EMPTY);
678
679   return status_icon->priv->image_type;
680 }
681
682 GdkPixbuf *
683 egg_status_icon_get_pixbuf (EggStatusIcon *status_icon)
684 {
685   g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), NULL);
686   g_return_val_if_fail (status_icon->priv->image_type == GTK_IMAGE_PIXBUF ||
687                         status_icon->priv->image_type == GTK_IMAGE_EMPTY, NULL);
688
689   if (status_icon->priv->image_type == GTK_IMAGE_EMPTY)
690     status_icon->priv->image_data.pixbuf = NULL;
691
692   return status_icon->priv->image_data.pixbuf;
693 }
694
695 G_CONST_RETURN gchar *
696 egg_status_icon_get_stock (EggStatusIcon *status_icon)
697 {
698   g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), NULL);
699
700   return NULL;
701 }
702
703 GdkPixbufAnimation *
704 egg_status_icon_get_animation (EggStatusIcon *status_icon)
705 {
706   g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), NULL);
707
708   return NULL;
709 }
710
711 gint
712 egg_status_icon_get_size (EggStatusIcon *status_icon)
713 {
714   g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), -1);
715
716   return status_icon->priv->size;
717 }
718
719 void
720 egg_status_icon_set_tooltip (EggStatusIcon *status_icon,
721                              const gchar   *tooltip_text,
722                              const gchar   *tooltip_private)
723 {
724   g_return_if_fail (EGG_IS_STATUS_ICON (status_icon));
725
726   gtk_tooltips_set_tip (status_icon->priv->tooltips,
727                         status_icon->priv->tray_icon,
728                         tooltip_text,
729                         tooltip_private);
730 }
731
732 void
733 egg_status_icon_set_balloon_text (EggStatusIcon *status_icon,
734                                   const gchar   *text)
735 {
736   g_return_if_fail (EGG_IS_STATUS_ICON (status_icon));
737 }
738
739 G_CONST_RETURN gchar *
740 egg_status_icon_get_balloon_text (EggStatusIcon *status_icon)
741 {
742   g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), NULL);
743
744   return NULL;
745 }
746
747 static gboolean
748 egg_status_icon_blinker (EggStatusIcon *status_icon)
749 {
750   status_icon->priv->blink_off = !status_icon->priv->blink_off;
751
752   egg_status_icon_update_image (status_icon);
753
754   return TRUE;
755 }
756
757 static void
758 egg_status_icon_enable_blinking (EggStatusIcon *status_icon)
759 {
760   if (!status_icon->priv->blinking_timeout)
761     {
762       egg_status_icon_blinker (status_icon);
763
764       status_icon->priv->blinking_timeout =
765         g_timeout_add (500, (GSourceFunc) egg_status_icon_blinker, status_icon);
766     }
767 }
768
769 static void
770 egg_status_icon_disable_blinking (EggStatusIcon *status_icon)
771 {
772   if (status_icon->priv->blinking_timeout)
773     {
774       g_source_remove (status_icon->priv->blinking_timeout);
775       status_icon->priv->blinking_timeout = 0;
776       status_icon->priv->blink_off = FALSE;
777
778       egg_status_icon_update_image (status_icon);
779     }
780 }
781
782 void
783 egg_status_icon_set_is_blinking (EggStatusIcon *status_icon,
784                                  guint       is_blinking)
785 {
786   g_return_if_fail (EGG_IS_STATUS_ICON (status_icon));
787
788   is_blinking = is_blinking != FALSE;
789
790   if (status_icon->priv->blinking != is_blinking)
791     {
792       status_icon->priv->blinking = is_blinking;
793
794       if (is_blinking)
795         egg_status_icon_enable_blinking (status_icon);
796       else
797         egg_status_icon_disable_blinking (status_icon);
798
799       g_object_notify (G_OBJECT (status_icon), "blinking");
800     }
801 }
802
803 gboolean
804 egg_status_icon_get_is_blinking (EggStatusIcon *status_icon)
805 {
806   g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), FALSE);
807
808   return status_icon->priv->blinking;
809 }
810
811 EggTrayIcon*
812 egg_status_icon_get_tray_icon (EggStatusIcon      *status_icon)
813 {
814    g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), NULL);
815
816    return EGG_TRAY_ICON(status_icon->priv->tray_icon);
817 }
818
819 } //extern "C"