1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) 2004 Naba Kumar <naba@gnome.org>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc., 59
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 * SECTION:anjuta-status
23 * @short_description: Program status such as status message, progress etc.
25 * @stability: Unstable
26 * @include: libanjuta/anjuta-status.h
31 #include <gtk/gtkwindow.h>
32 #include <gtk/gtkprogressbar.h>
33 #include <gtk/gtkstatusbar.h>
34 #include <libanjuta/anjuta-status.h>
35 #include <libanjuta/anjuta-utils.h>
36 #include <libanjuta/resources.h>
37 #include <libanjuta/e-splash.h>
39 struct _AnjutaStatusPriv
41 GHashTable
*default_status_items
;
46 GtkWidget
*status_bar
;
52 GtkWidget
*progress_bar
;
58 gboolean disable_splash
;
60 gint splash_progress_position
;
71 static gpointer parent_class
= NULL
;
72 static guint status_signals
[LAST_SIGNAL
] = { 0 };
74 static void on_widget_destroy (AnjutaStatus
*status
, GObject
*widget
);
77 anjuta_status_finalize (GObject
*widget
)
79 g_free(ANJUTA_STATUS(widget
)->priv
);
80 G_OBJECT_CLASS (parent_class
)->finalize (widget
);
84 foreach_widget_unref (gpointer key
, gpointer value
, gpointer data
)
86 g_object_weak_unref (G_OBJECT (key
), (GWeakNotify
) on_widget_destroy
, data
);
90 anjuta_status_dispose (GObject
*widget
)
94 status
= ANJUTA_STATUS (widget
);
96 if (status
->priv
->default_status_items
)
98 g_hash_table_destroy (status
->priv
->default_status_items
);
99 status
->priv
->default_status_items
= NULL
;
101 if (status
->priv
->splash
!= NULL
) {
102 gtk_widget_destroy (status
->priv
->splash
);
103 status
->priv
->splash
= NULL
;
105 if (status
->priv
->splash_file
)
107 g_free (status
->priv
->splash_file
);
108 status
->priv
->splash_file
= NULL
;
110 if (status
->priv
->push_values
)
112 g_list_free (status
->priv
->push_values
);
113 status
->priv
->push_values
= NULL
;
115 if (status
->priv
->widgets
)
117 g_hash_table_foreach (status
->priv
->widgets
,
118 foreach_widget_unref
, widget
);
119 g_hash_table_destroy (status
->priv
->widgets
);
120 status
->priv
->widgets
= NULL
;
122 if (status
->priv
->window
)
124 g_object_remove_weak_pointer (G_OBJECT (status
->priv
->window
),
125 (gpointer
*)(gpointer
)&status
->priv
->window
);
126 status
->priv
->window
= NULL
;
128 G_OBJECT_CLASS (parent_class
)->dispose (widget
);
132 anjuta_status_instance_init (AnjutaStatus
*status
)
134 status
->priv
= g_new0 (AnjutaStatusPriv
, 1);
135 status
->priv
->progress_bar
= gtk_progress_bar_new ();
136 gtk_box_pack_start (GTK_BOX (status
), status
->priv
->progress_bar
, FALSE
, TRUE
, 0);
137 gtk_widget_show (status
->priv
->progress_bar
);
138 status
->priv
->status_bar
= gtk_statusbar_new ();
139 gtk_box_pack_start (GTK_BOX (status
), status
->priv
->status_bar
, TRUE
, TRUE
, 0);
140 gtk_widget_show (status
->priv
->status_bar
);
141 status
->priv
->status_message
= gtk_statusbar_get_context_id (GTK_STATUSBAR (status
->priv
->status_bar
),
143 status
->priv
->push_message
= gtk_statusbar_get_context_id (GTK_STATUSBAR (status
->priv
->status_bar
),
145 status
->priv
->push_values
= NULL
;
146 status
->priv
->splash_file
= NULL
;
147 status
->priv
->splash_progress_position
= 0;
148 status
->priv
->disable_splash
= FALSE
;
149 status
->priv
->total_ticks
= 0;
150 status
->priv
->current_ticks
= 0;
151 status
->priv
->splash
= NULL
;
152 status
->priv
->default_status_items
=
153 g_hash_table_new_full (g_str_hash
, g_str_equal
,
158 anjuta_status_class_init (AnjutaStatusClass
*class)
160 GObjectClass
*object_class
;
162 parent_class
= g_type_class_peek_parent (class);
163 object_class
= (GObjectClass
*) class;
164 object_class
->finalize
= anjuta_status_finalize
;
165 object_class
->dispose
= anjuta_status_dispose
;
167 status_signals
[BUSY
] =
168 g_signal_new ("busy",
171 G_STRUCT_OFFSET (AnjutaStatusClass
, busy
),
173 g_cclosure_marshal_VOID__BOOLEAN
,
179 anjuta_status_new (void)
183 status
= GTK_WIDGET (g_object_new (ANJUTA_TYPE_STATUS
, NULL
));
188 anjuta_status_set (AnjutaStatus
*status
, const gchar
* mesg
, ...)
193 g_return_if_fail (ANJUTA_IS_STATUS (status
));
194 g_return_if_fail (mesg
!= NULL
);
196 va_start (args
, mesg
);
197 message
= g_strdup_vprintf (mesg
, args
);
199 gtk_statusbar_pop (GTK_STATUSBAR (status
->priv
->status_bar
),
200 status
->priv
->status_message
);
201 gtk_statusbar_push (GTK_STATUSBAR (status
->priv
->status_bar
),
202 status
->priv
->status_message
, message
);
207 anjuta_status_push (AnjutaStatus
*status
, const gchar
* mesg
, ...)
213 g_return_if_fail (ANJUTA_IS_STATUS (status
));
214 g_return_if_fail (mesg
!= NULL
);
216 va_start (args
, mesg
);
217 message
= g_strdup_vprintf (mesg
, args
);
220 value
= gtk_statusbar_push (GTK_STATUSBAR (status
->priv
->status_bar
),
221 status
->priv
->push_message
, message
);
222 status
->priv
->push_values
= g_list_prepend (status
->priv
->push_values
,
223 GUINT_TO_POINTER (value
));
228 anjuta_status_pop (AnjutaStatus
*status
)
230 g_return_if_fail (ANJUTA_IS_STATUS (status
));
232 gtk_statusbar_pop (GTK_STATUSBAR (status
->priv
->status_bar
),
233 status
->priv
->push_message
);
235 status
->priv
->push_values
= g_list_remove_link (status
->priv
->push_values
,
236 status
->priv
->push_values
);
240 anjuta_status_clear_stack (AnjutaStatus
*status
)
243 g_return_if_fail (ANJUTA_IS_STATUS (status
));
245 for (l
= status
->priv
->push_values
; l
!= NULL
; l
= g_list_next (l
))
247 guint value
= GPOINTER_TO_UINT (l
->data
);
248 gtk_statusbar_remove (GTK_STATUSBAR (status
->priv
->status_bar
),
249 status
->priv
->push_message
, value
);
251 g_list_free (status
->priv
->push_values
);
252 status
->priv
->push_values
= NULL
;
256 foreach_widget_set_cursor (gpointer widget
, gpointer value
, gpointer cursor
)
258 if (GTK_WIDGET (widget
)->window
)
259 gdk_window_set_cursor (GTK_WIDGET (widget
)->window
, (GdkCursor
*)cursor
);
263 anjuta_status_busy_push (AnjutaStatus
*status
)
268 g_return_if_fail (ANJUTA_IS_STATUS (status
));
270 top
= gtk_widget_get_toplevel (GTK_WIDGET (status
));
274 status
->priv
->busy_count
++;
275 if (status
->priv
->busy_count
> 1)
277 cursor
= gdk_cursor_new (GDK_WATCH
);
278 if (GTK_WIDGET (top
)->window
)
279 gdk_window_set_cursor (GTK_WIDGET (top
)->window
, cursor
);
280 if (status
->priv
->widgets
)
281 g_hash_table_foreach (status
->priv
->widgets
,
282 foreach_widget_set_cursor
, cursor
);
283 gdk_cursor_unref (cursor
);
285 g_signal_emit_by_name (G_OBJECT (status
), "busy", TRUE
);
289 anjuta_status_busy_pop (AnjutaStatus
*status
)
293 g_return_if_fail (ANJUTA_IS_STATUS (status
));
295 top
= gtk_widget_get_toplevel (GTK_WIDGET (status
));
299 status
->priv
->busy_count
--;
300 if (status
->priv
->busy_count
> 0)
303 status
->priv
->busy_count
= 0;
304 if (GTK_WIDGET (top
)->window
)
305 gdk_window_set_cursor (GTK_WIDGET (top
)->window
, NULL
);
306 if (status
->priv
->widgets
)
307 g_hash_table_foreach (status
->priv
->widgets
,
308 foreach_widget_set_cursor
, NULL
);
309 g_signal_emit_by_name (G_OBJECT (status
), "busy", FALSE
);
313 foreach_hash (gpointer key
, gpointer value
, gpointer userdata
)
315 GString
*str
= (GString
*)(userdata
);
316 const gchar
*divider
= ": ";
317 const gchar
*separator
= " ";
319 g_string_append (str
, separator
);
320 g_string_append (str
, (const gchar
*)key
);
321 g_string_append (str
, divider
);
322 g_string_append (str
, (const gchar
*)value
);
326 anjuta_status_set_default (AnjutaStatus
*status
, const gchar
*label
,
327 const gchar
*value_format
, ...)
332 g_return_if_fail (ANJUTA_IS_STATUS (status
));
333 g_return_if_fail (label
!= NULL
);
340 va_start (args
, value_format
);
341 value
= g_strdup_vprintf (value_format
, args
);
343 g_hash_table_replace (status
->priv
->default_status_items
,
344 g_strdup (label
), value
);
348 if (g_hash_table_lookup (status
->priv
->default_status_items
, label
))
350 g_hash_table_remove (status
->priv
->default_status_items
, label
);
354 /* Update default status */
355 str
= g_string_new (NULL
);
356 g_hash_table_foreach (status
->priv
->default_status_items
, foreach_hash
, str
);
357 status_str
= g_string_free (str
, FALSE
);
358 anjuta_status_set (status
, status_str
, NULL
);
363 on_widget_destroy (AnjutaStatus
*status
, GObject
*widget
)
365 if (g_hash_table_lookup (status
->priv
->widgets
, widget
))
366 g_hash_table_remove (status
->priv
->widgets
, widget
);
370 anjuta_status_add_widget (AnjutaStatus
*status
, GtkWidget
*widget
)
372 g_return_if_fail (ANJUTA_IS_STATUS (status
));
373 g_return_if_fail (GTK_IS_WIDGET (widget
));
375 if (status
->priv
->widgets
== NULL
)
376 status
->priv
->widgets
=
377 g_hash_table_new (g_direct_hash
, g_direct_equal
);
379 g_hash_table_insert (status
->priv
->widgets
, widget
, widget
);
380 g_object_weak_ref (G_OBJECT (widget
),
381 (GWeakNotify
) (on_widget_destroy
), status
);
385 anjuta_status_set_splash (AnjutaStatus
*status
, const gchar
*splash_file
,
386 gint splash_progress_position
)
388 g_return_if_fail (ANJUTA_IS_STATUS (status
));
389 g_return_if_fail (splash_file
!= NULL
);
390 g_return_if_fail (splash_progress_position
>= 0);
391 if (status
->priv
->splash_file
)
392 g_free (status
->priv
->splash_file
);
393 status
->priv
->splash_file
= g_strdup (splash_file
);
394 status
->priv
->splash_progress_position
= splash_progress_position
;
398 anjuta_status_disable_splash (AnjutaStatus
*status
,
399 gboolean disable_splash
)
401 g_return_if_fail (ANJUTA_IS_STATUS (status
));
403 status
->priv
->disable_splash
= disable_splash
;
404 if (status
->priv
->splash
)
406 gtk_widget_destroy (status
->priv
->splash
);
407 status
->priv
->splash
= NULL
;
408 anjuta_status_progress_add_ticks (status
, 0);
413 anjuta_status_progress_add_ticks (AnjutaStatus
*status
, gint ticks
)
417 g_return_if_fail (ANJUTA_IS_STATUS (status
));
418 g_return_if_fail (ticks
>= 0);
420 status
->priv
->total_ticks
+= ticks
;
421 if (!GTK_WIDGET_REALIZED (status
))
423 if (status
->priv
->splash
== NULL
&&
424 status
->priv
->splash_file
&&
425 !status
->priv
->disable_splash
)
427 status
->priv
->splash
= e_splash_new (status
->priv
->splash_file
, 100);
428 if (status
->priv
->splash
)
429 gtk_widget_show (status
->priv
->splash
);
432 percentage
= ((gfloat
)status
->priv
->current_ticks
)/status
->priv
->total_ticks
;
433 if (status
->priv
->splash
)
435 e_splash_set (E_SPLASH(status
->priv
->splash
), NULL
, NULL
, NULL
,
437 while (g_main_context_iteration(NULL
, FALSE
));
441 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (status
->priv
->progress_bar
),
443 gtk_widget_queue_draw (GTK_WIDGET (status
->priv
->status_bar
));
444 gtk_widget_queue_draw (GTK_WIDGET (status
->priv
->progress_bar
));
445 if (GTK_WIDGET(status
->priv
->progress_bar
)->window
!= NULL
&&
446 GDK_IS_WINDOW(GTK_WIDGET(status
->priv
->progress_bar
)->window
))
447 gdk_window_process_updates (GTK_WIDGET(status
->priv
->progress_bar
)->window
, TRUE
);
448 if (GTK_WIDGET(status
->priv
->status_bar
)->window
!= NULL
&&
449 GDK_IS_WINDOW(GTK_WIDGET(status
->priv
->status_bar
)->window
))
450 gdk_window_process_updates (GTK_WIDGET(status
->priv
->status_bar
)->window
, TRUE
);
455 anjuta_status_progress_pulse (AnjutaStatus
*status
, const gchar
*text
)
457 GtkProgressBar
*progressbar
;
458 GtkWidget
*statusbar
;
460 progressbar
= GTK_PROGRESS_BAR (status
->priv
->progress_bar
);
461 statusbar
= status
->priv
->status_bar
;
464 anjuta_status_set (status
, "%s", text
);
466 gtk_progress_bar_pulse (progressbar
);
468 gtk_widget_queue_draw (GTK_WIDGET (statusbar
));
469 gtk_widget_queue_draw (GTK_WIDGET (progressbar
));
470 if (GTK_WIDGET(progressbar
)->window
!= NULL
&&
471 GDK_IS_WINDOW(GTK_WIDGET(progressbar
)->window
))
472 gdk_window_process_updates (GTK_WIDGET(progressbar
)->window
, TRUE
);
473 if (GTK_WIDGET(statusbar
)->window
!= NULL
&&
474 GDK_IS_WINDOW(GTK_WIDGET(statusbar
)->window
))
475 gdk_window_process_updates (GTK_WIDGET(statusbar
)->window
, TRUE
);
479 anjuta_status_progress_tick (AnjutaStatus
*status
,
480 GdkPixbuf
*icon
, const gchar
*text
)
484 g_return_if_fail (ANJUTA_IS_STATUS (status
));
485 g_return_if_fail (status
->priv
->total_ticks
!= 0);
487 status
->priv
->current_ticks
++;
488 percentage
= ((gfloat
)status
->priv
->current_ticks
)/status
->priv
->total_ticks
;
490 if (status
->priv
->splash
)
492 e_splash_set (E_SPLASH(status
->priv
->splash
), icon
, text
, NULL
, percentage
);
493 while (g_main_context_iteration(NULL
, FALSE
));
497 GtkProgressBar
*progressbar
;
498 GtkWidget
*statusbar
;
501 anjuta_status_set (status
, "%s", text
);
502 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (status
->priv
->progress_bar
),
504 progressbar
= GTK_PROGRESS_BAR (status
->priv
->progress_bar
);
505 statusbar
= status
->priv
->status_bar
;
506 gtk_widget_queue_draw (GTK_WIDGET (statusbar
));
507 gtk_widget_queue_draw (GTK_WIDGET (progressbar
));
508 if (GTK_WIDGET(progressbar
)->window
!= NULL
&&
509 GDK_IS_WINDOW(GTK_WIDGET(progressbar
)->window
))
510 gdk_window_process_updates (GTK_WIDGET(progressbar
)->window
, TRUE
);
511 if (GTK_WIDGET(statusbar
)->window
!= NULL
&&
512 GDK_IS_WINDOW(GTK_WIDGET(statusbar
)->window
))
513 gdk_window_process_updates (GTK_WIDGET(statusbar
)->window
, TRUE
);
515 if (status
->priv
->current_ticks
>= status
->priv
->total_ticks
)
516 anjuta_status_progress_reset (status
);
520 anjuta_status_progress_increment_ticks (AnjutaStatus
*status
, gint ticks
,
525 g_return_if_fail (ANJUTA_IS_STATUS (status
));
526 g_return_if_fail (status
->priv
->total_ticks
!= 0);
528 status
->priv
->current_ticks
+= ticks
;
529 percentage
= ((gfloat
)status
->priv
->current_ticks
)/status
->priv
->total_ticks
;
531 GtkProgressBar
*progressbar
;
532 GtkWidget
*statusbar
;
535 anjuta_status_set (status
, "%s", text
);
536 gnome_appbar_set_progress_percentage (GNOME_APPBAR (status
),
538 progressbar
= gnome_appbar_get_progress (GNOME_APPBAR (status
));
539 statusbar
= gnome_appbar_get_status (GNOME_APPBAR (status
));
540 gtk_widget_queue_draw (GTK_WIDGET (statusbar
));
541 gtk_widget_queue_draw (GTK_WIDGET (progressbar
));
542 if (GTK_WIDGET(progressbar
)->window
!= NULL
&&
543 GDK_IS_WINDOW(GTK_WIDGET(progressbar
)->window
))
544 gdk_window_process_updates (GTK_WIDGET(progressbar
)->window
, TRUE
);
545 if (GTK_WIDGET(statusbar
)->window
!= NULL
&&
546 GDK_IS_WINDOW(GTK_WIDGET(statusbar
)->window
))
547 gdk_window_process_updates (GTK_WIDGET(statusbar
)->window
, TRUE
);
549 if (status
->priv
->current_ticks
>= status
->priv
->total_ticks
)
550 anjuta_status_progress_reset (status
);
554 anjuta_status_progress_reset (AnjutaStatus
*status
)
556 g_return_if_fail (ANJUTA_IS_STATUS (status
));
558 if (status
->priv
->splash
)
560 gtk_widget_destroy (status
->priv
->splash
);
561 status
->priv
->splash
= NULL
;
563 status
->priv
->current_ticks
= 0;
564 status
->priv
->total_ticks
= 0;
565 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (status
->priv
->progress_bar
), 0);
566 anjuta_status_clear_stack (status
);
570 anjuta_status_timeout (AnjutaStatus
*status
)
572 anjuta_status_pop (status
);
576 /* Display message in status until timeout (secondes) */
578 anjuta_status (AnjutaStatus
*status
, const gchar
*mesg
, gint timeout
)
580 g_return_if_fail (ANJUTA_IS_STATUS (status
));
581 g_return_if_fail (mesg
!= NULL
);
582 anjuta_status_push (status
, "%s", mesg
);
583 g_timeout_add (timeout
* 1000, (void*) anjuta_status_timeout
, status
);
587 anjuta_status_set_title_window (AnjutaStatus
*status
, GtkWidget
*window
)
589 g_return_if_fail (ANJUTA_IS_STATUS (status
));
590 g_return_if_fail (GTK_IS_WINDOW (window
));
591 status
->priv
->window
= GTK_WINDOW (window
);
592 g_object_add_weak_pointer (G_OBJECT (window
),
593 (gpointer
*)(gpointer
)&status
->priv
->window
);
597 anjuta_status_set_title (AnjutaStatus
*status
, const gchar
*title
)
599 g_return_if_fail (ANJUTA_IS_STATUS (status
));
601 if (!status
->priv
->window
)
604 const gchar
*app_name
= g_get_application_name();
607 gchar
* str
= g_strconcat (title
, " - ", app_name
, NULL
);
608 gtk_window_set_title (status
->priv
->window
, str
);
613 gtk_window_set_title (status
->priv
->window
, app_name
);
617 ANJUTA_TYPE_BEGIN(AnjutaStatus
, anjuta_status
, GTK_TYPE_HBOX
);