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 <libanjuta/anjuta-status.h>
33 #include <libanjuta/anjuta-utils.h>
34 #include <libanjuta/resources.h>
35 #include <libanjuta/e-splash.h>
37 struct _AnjutaStatusPriv
39 GHashTable
*default_status_items
;
49 gboolean disable_splash
;
51 gint splash_progress_position
;
62 static gpointer parent_class
= NULL
;
63 static guint status_signals
[LAST_SIGNAL
] = { 0 };
65 static void on_widget_destroy (AnjutaStatus
*status
, GObject
*widget
);
68 anjuta_status_finalize (GObject
*widget
)
70 g_free(ANJUTA_STATUS(widget
)->priv
);
71 GNOME_CALL_PARENT(G_OBJECT_CLASS
, finalize
, (widget
));
75 foreach_widget_unref (gpointer key
, gpointer value
, gpointer data
)
77 g_object_weak_unref (G_OBJECT (key
), (GWeakNotify
) on_widget_destroy
, data
);
81 anjuta_status_dispose (GObject
*widget
)
85 status
= ANJUTA_STATUS (widget
);
87 if (status
->priv
->default_status_items
)
89 g_hash_table_destroy (status
->priv
->default_status_items
);
90 status
->priv
->default_status_items
= NULL
;
92 if (status
->priv
->splash
!= NULL
) {
93 gtk_widget_destroy (status
->priv
->splash
);
94 status
->priv
->splash
= NULL
;
96 if (status
->priv
->splash_file
)
98 g_free (status
->priv
->splash_file
);
99 status
->priv
->splash_file
= NULL
;
101 if (status
->priv
->widgets
)
103 g_hash_table_foreach (status
->priv
->widgets
,
104 foreach_widget_unref
, widget
);
105 g_hash_table_destroy (status
->priv
->widgets
);
106 status
->priv
->widgets
= NULL
;
108 if (status
->priv
->window
)
110 g_object_remove_weak_pointer (G_OBJECT (status
->priv
->window
),
111 (gpointer
*)(gpointer
)&status
->priv
->window
);
112 status
->priv
->window
= NULL
;
114 GNOME_CALL_PARENT(G_OBJECT_CLASS
, dispose
, (widget
));
118 anjuta_status_instance_init (AnjutaStatus
*status
)
120 status
->priv
= g_new0 (AnjutaStatusPriv
, 1);
121 status
->priv
->splash_file
= NULL
;
122 status
->priv
->splash_progress_position
= 0;
123 status
->priv
->disable_splash
= FALSE
;
124 status
->priv
->total_ticks
= 0;
125 status
->priv
->current_ticks
= 0;
126 status
->priv
->splash
= NULL
;
127 status
->priv
->default_status_items
=
128 g_hash_table_new_full (g_str_hash
, g_str_equal
,
133 anjuta_status_class_init (AnjutaStatusClass
*class)
135 GObjectClass
*object_class
;
137 parent_class
= g_type_class_peek_parent (class);
138 object_class
= (GObjectClass
*) class;
139 object_class
->finalize
= anjuta_status_finalize
;
140 object_class
->dispose
= anjuta_status_dispose
;
142 status_signals
[BUSY
] =
143 g_signal_new ("busy",
146 G_STRUCT_OFFSET (AnjutaStatusClass
, busy
),
148 g_cclosure_marshal_VOID__BOOLEAN
,
154 anjuta_status_new (void)
158 status
= GTK_WIDGET (g_object_new (ANJUTA_TYPE_STATUS
,
159 "has-progress", TRUE
, "has-status", TRUE
,
160 "interactivity", GNOME_PREFERENCES_NEVER
, NULL
));
165 anjuta_status_set (AnjutaStatus
*status
, const gchar
* mesg
, ...)
170 g_return_if_fail (ANJUTA_IS_STATUS (status
));
171 g_return_if_fail (mesg
!= NULL
);
173 va_start (args
, mesg
);
174 message
= g_strdup_vprintf (mesg
, args
);
176 gnome_appbar_set_status (GNOME_APPBAR (status
), message
);
181 anjuta_status_push (AnjutaStatus
*status
, const gchar
* mesg
, ...)
186 g_return_if_fail (ANJUTA_IS_STATUS (status
));
187 g_return_if_fail (mesg
!= NULL
);
189 va_start (args
, mesg
);
190 message
= g_strdup_vprintf (mesg
, args
);
192 gnome_appbar_push (GNOME_APPBAR (status
), message
);
197 foreach_widget_set_cursor (gpointer widget
, gpointer value
, gpointer cursor
)
199 if (GTK_WIDGET (widget
)->window
)
200 gdk_window_set_cursor (GTK_WIDGET (widget
)->window
, (GdkCursor
*)cursor
);
204 anjuta_status_busy_push (AnjutaStatus
*status
)
209 g_return_if_fail (ANJUTA_IS_STATUS (status
));
211 top
= gtk_widget_get_toplevel (GTK_WIDGET (status
));
215 status
->priv
->busy_count
++;
216 if (status
->priv
->busy_count
> 1)
218 cursor
= gdk_cursor_new (GDK_WATCH
);
219 if (GTK_WIDGET (top
)->window
)
220 gdk_window_set_cursor (GTK_WIDGET (top
)->window
, cursor
);
221 if (status
->priv
->widgets
)
222 g_hash_table_foreach (status
->priv
->widgets
,
223 foreach_widget_set_cursor
, cursor
);
224 gdk_cursor_unref (cursor
);
226 g_signal_emit_by_name (G_OBJECT (status
), "busy", TRUE
);
230 anjuta_status_busy_pop (AnjutaStatus
*status
)
234 g_return_if_fail (ANJUTA_IS_STATUS (status
));
236 top
= gtk_widget_get_toplevel (GTK_WIDGET (status
));
240 status
->priv
->busy_count
--;
241 if (status
->priv
->busy_count
> 0)
244 status
->priv
->busy_count
= 0;
245 if (GTK_WIDGET (top
)->window
)
246 gdk_window_set_cursor (GTK_WIDGET (top
)->window
, NULL
);
247 if (status
->priv
->widgets
)
248 g_hash_table_foreach (status
->priv
->widgets
,
249 foreach_widget_set_cursor
, NULL
);
250 g_signal_emit_by_name (G_OBJECT (status
), "busy", FALSE
);
254 foreach_hash (gpointer key
, gpointer value
, gpointer userdata
)
256 GString
*str
= (GString
*)(userdata
);
257 const gchar
*divider
= ": ";
258 const gchar
*separator
= " ";
260 g_string_append (str
, separator
);
261 g_string_append (str
, (const gchar
*)key
);
262 g_string_append (str
, divider
);
263 g_string_append (str
, (const gchar
*)value
);
267 anjuta_status_set_default (AnjutaStatus
*status
, const gchar
*label
,
268 const gchar
*value_format
, ...)
273 g_return_if_fail (ANJUTA_IS_STATUS (status
));
274 g_return_if_fail (label
!= NULL
);
281 va_start (args
, value_format
);
282 value
= g_strdup_vprintf (value_format
, args
);
284 g_hash_table_replace (status
->priv
->default_status_items
,
285 g_strdup (label
), value
);
289 if (g_hash_table_lookup (status
->priv
->default_status_items
, label
))
291 g_hash_table_remove (status
->priv
->default_status_items
, label
);
295 /* Update default status */
296 str
= g_string_new (NULL
);
297 g_hash_table_foreach (status
->priv
->default_status_items
, foreach_hash
, str
);
298 status_str
= g_string_free (str
, FALSE
);
299 gnome_appbar_set_default (GNOME_APPBAR (status
), status_str
);
304 on_widget_destroy (AnjutaStatus
*status
, GObject
*widget
)
306 if (g_hash_table_lookup (status
->priv
->widgets
, widget
))
307 g_hash_table_remove (status
->priv
->widgets
, widget
);
311 anjuta_status_add_widget (AnjutaStatus
*status
, GtkWidget
*widget
)
313 g_return_if_fail (ANJUTA_IS_STATUS (status
));
314 g_return_if_fail (GTK_IS_WIDGET (widget
));
316 if (status
->priv
->widgets
== NULL
)
317 status
->priv
->widgets
=
318 g_hash_table_new (g_direct_hash
, g_direct_equal
);
320 g_hash_table_insert (status
->priv
->widgets
, widget
, widget
);
321 g_object_weak_ref (G_OBJECT (widget
),
322 (GWeakNotify
) (on_widget_destroy
), status
);
326 anjuta_status_set_splash (AnjutaStatus
*status
, const gchar
*splash_file
,
327 gint splash_progress_position
)
329 g_return_if_fail (ANJUTA_IS_STATUS (status
));
330 g_return_if_fail (splash_file
!= NULL
);
331 g_return_if_fail (splash_progress_position
>= 0);
332 if (status
->priv
->splash_file
)
333 g_free (status
->priv
->splash_file
);
334 status
->priv
->splash_file
= g_strdup (splash_file
);
335 status
->priv
->splash_progress_position
= splash_progress_position
;
339 anjuta_status_disable_splash (AnjutaStatus
*status
,
340 gboolean disable_splash
)
342 g_return_if_fail (ANJUTA_IS_STATUS (status
));
344 status
->priv
->disable_splash
= disable_splash
;
345 if (status
->priv
->splash
)
347 gtk_widget_destroy (status
->priv
->splash
);
348 status
->priv
->splash
= NULL
;
349 anjuta_status_progress_add_ticks (status
, 0);
354 anjuta_status_progress_add_ticks (AnjutaStatus
*status
, gint ticks
)
358 g_return_if_fail (ANJUTA_IS_STATUS (status
));
359 g_return_if_fail (ticks
>= 0);
361 status
->priv
->total_ticks
+= ticks
;
362 if (!GTK_WIDGET_REALIZED (status
))
364 if (status
->priv
->splash
== NULL
&&
365 status
->priv
->splash_file
&&
366 !status
->priv
->disable_splash
)
368 status
->priv
->splash
= e_splash_new (status
->priv
->splash_file
, 100);
369 if (status
->priv
->splash
)
370 gtk_widget_show (status
->priv
->splash
);
373 percentage
= ((gfloat
)status
->priv
->current_ticks
)/status
->priv
->total_ticks
;
374 if (status
->priv
->splash
)
376 e_splash_set (E_SPLASH(status
->priv
->splash
), NULL
, NULL
, NULL
,
378 while (g_main_context_iteration(NULL
, FALSE
));
382 GtkProgressBar
*progressbar
;
383 GtkWidget
*statusbar
;
385 gnome_appbar_set_progress_percentage (GNOME_APPBAR (status
),
387 progressbar
= gnome_appbar_get_progress (GNOME_APPBAR (status
));
388 statusbar
= gnome_appbar_get_status (GNOME_APPBAR (status
));
389 gtk_widget_queue_draw (GTK_WIDGET (statusbar
));
390 gtk_widget_queue_draw (GTK_WIDGET (progressbar
));
391 if (GTK_WIDGET(progressbar
)->window
!= NULL
&&
392 GDK_IS_WINDOW(GTK_WIDGET(progressbar
)->window
))
393 gdk_window_process_updates (GTK_WIDGET(progressbar
)->window
, TRUE
);
394 if (GTK_WIDGET(statusbar
)->window
!= NULL
&&
395 GDK_IS_WINDOW(GTK_WIDGET(statusbar
)->window
))
396 gdk_window_process_updates (GTK_WIDGET(statusbar
)->window
, TRUE
);
401 anjuta_status_progress_pulse (AnjutaStatus
*status
, const gchar
*text
)
403 GtkProgressBar
*progressbar
;
404 GtkWidget
*statusbar
;
406 progressbar
= gnome_appbar_get_progress (GNOME_APPBAR (status
));
407 statusbar
= gnome_appbar_get_status (GNOME_APPBAR (status
));
410 anjuta_status_set (status
, "%s", text
);
412 gtk_progress_bar_pulse (progressbar
);
414 gtk_widget_queue_draw (GTK_WIDGET (statusbar
));
415 gtk_widget_queue_draw (GTK_WIDGET (progressbar
));
416 if (GTK_WIDGET(progressbar
)->window
!= NULL
&&
417 GDK_IS_WINDOW(GTK_WIDGET(progressbar
)->window
))
418 gdk_window_process_updates (GTK_WIDGET(progressbar
)->window
, TRUE
);
419 if (GTK_WIDGET(statusbar
)->window
!= NULL
&&
420 GDK_IS_WINDOW(GTK_WIDGET(statusbar
)->window
))
421 gdk_window_process_updates (GTK_WIDGET(statusbar
)->window
, TRUE
);
425 anjuta_status_progress_tick (AnjutaStatus
*status
,
426 GdkPixbuf
*icon
, const gchar
*text
)
430 g_return_if_fail (ANJUTA_IS_STATUS (status
));
431 g_return_if_fail (status
->priv
->total_ticks
!= 0);
433 status
->priv
->current_ticks
++;
434 percentage
= ((gfloat
)status
->priv
->current_ticks
)/status
->priv
->total_ticks
;
436 if (status
->priv
->splash
)
438 e_splash_set (E_SPLASH(status
->priv
->splash
), icon
, text
, NULL
, percentage
);
439 while (g_main_context_iteration(NULL
, FALSE
));
443 GtkProgressBar
*progressbar
;
444 GtkWidget
*statusbar
;
447 anjuta_status_set (status
, "%s", text
);
448 gnome_appbar_set_progress_percentage (GNOME_APPBAR (status
),
450 progressbar
= gnome_appbar_get_progress (GNOME_APPBAR (status
));
451 statusbar
= gnome_appbar_get_status (GNOME_APPBAR (status
));
452 gtk_widget_queue_draw (GTK_WIDGET (statusbar
));
453 gtk_widget_queue_draw (GTK_WIDGET (progressbar
));
454 if (GTK_WIDGET(progressbar
)->window
!= NULL
&&
455 GDK_IS_WINDOW(GTK_WIDGET(progressbar
)->window
))
456 gdk_window_process_updates (GTK_WIDGET(progressbar
)->window
, TRUE
);
457 if (GTK_WIDGET(statusbar
)->window
!= NULL
&&
458 GDK_IS_WINDOW(GTK_WIDGET(statusbar
)->window
))
459 gdk_window_process_updates (GTK_WIDGET(statusbar
)->window
, TRUE
);
461 if (status
->priv
->current_ticks
>= status
->priv
->total_ticks
)
462 anjuta_status_progress_reset (status
);
466 anjuta_status_progress_reset (AnjutaStatus
*status
)
468 g_return_if_fail (ANJUTA_IS_STATUS (status
));
469 if (status
->priv
->splash
)
471 gtk_widget_destroy (status
->priv
->splash
);
472 status
->priv
->splash
= NULL
;
474 status
->priv
->current_ticks
= 0;
475 status
->priv
->total_ticks
= 0;
476 gnome_appbar_set_progress_percentage (GNOME_APPBAR (status
), 0);
477 gnome_appbar_refresh (GNOME_APPBAR(status
));
481 anjuta_status_timeout (AnjutaStatus
*status
)
483 anjuta_status_pop (status
);
487 /* Display message in status until timeout (secondes) */
489 anjuta_status (AnjutaStatus
*status
, const gchar
*mesg
, gint timeout
)
491 g_return_if_fail (ANJUTA_IS_STATUS (status
));
492 g_return_if_fail (mesg
!= NULL
);
493 anjuta_status_push (status
, "%s", mesg
);
494 g_timeout_add (timeout
* 1000, (void*) anjuta_status_timeout
, status
);
498 anjuta_status_set_title_window (AnjutaStatus
*status
, GtkWidget
*window
)
500 g_return_if_fail (ANJUTA_IS_STATUS (status
));
501 g_return_if_fail (GTK_IS_WINDOW (window
));
502 status
->priv
->window
= GTK_WINDOW (window
);
503 g_object_add_weak_pointer (G_OBJECT (window
),
504 (gpointer
*)(gpointer
)&status
->priv
->window
);
508 anjuta_status_set_title (AnjutaStatus
*status
, const gchar
*title
)
510 g_return_if_fail (ANJUTA_IS_STATUS (status
));
512 if (!status
->priv
->window
)
515 const gchar
*app_name
= g_get_application_name();
518 gchar
* str
= g_strconcat (title
, " - ", app_name
, NULL
);
519 gtk_window_set_title (status
->priv
->window
, str
);
524 gtk_window_set_title (status
->priv
->window
, app_name
);
528 ANJUTA_TYPE_BEGIN(AnjutaStatus
, anjuta_status
, GNOME_TYPE_APPBAR
);