2007-07-20 Johannes Schmid <jhs@gnome.org>
[anjuta-git-plugin.git] / libanjuta / anjuta-status.c
blob8983cf2cd2221efc7677333f689678ddfb3a5b23
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * anjuta-status.c
4 * Copyright (C) 2004 Naba Kumar <naba@gnome.org>
5 *
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)
9 * any later version.
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
14 * for more details.
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 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 /**
22 * SECTION:anjuta-status
23 * @short_description: Program status such as status message, progress etc.
24 * @see_also:
25 * @stability: Unstable
26 * @include: libanjuta/anjuta-status.h
30 #include <config.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;
40 gint busy_count;
41 GHashTable *widgets;
43 /* Progress bar */
44 gint total_ticks;
45 gint current_ticks;
46 GtkWidget *splash;
48 /* Splash */
49 gboolean disable_splash;
50 gchar *splash_file;
51 gint splash_progress_position;
53 /* Title window */
54 GtkWindow *window;
57 enum {
58 BUSY,
59 LAST_SIGNAL
62 static gpointer parent_class = NULL;
63 static guint status_signals[LAST_SIGNAL] = { 0 };
65 static void on_widget_destroy (AnjutaStatus *status, GObject *widget);
67 static void
68 anjuta_status_finalize (GObject *widget)
70 GNOME_CALL_PARENT(G_OBJECT_CLASS, finalize, (widget));
73 static void
74 foreach_widget_unref (gpointer key, gpointer value, gpointer data)
76 g_object_weak_unref (G_OBJECT (key), (GWeakNotify) on_widget_destroy, data);
79 static void
80 anjuta_status_dispose (GObject *widget)
82 AnjutaStatus *status;
84 status = ANJUTA_STATUS (widget);
86 if (status->priv->default_status_items)
88 g_hash_table_destroy (status->priv->default_status_items);
89 status->priv->default_status_items = NULL;
91 if (status->priv->splash != NULL) {
92 gtk_widget_destroy (status->priv->splash);
93 status->priv->splash = NULL;
95 if (status->priv->splash_file)
97 g_free (status->priv->splash_file);
98 status->priv->splash_file = NULL;
100 if (status->priv->widgets)
102 g_hash_table_foreach (status->priv->widgets,
103 foreach_widget_unref, widget);
104 g_hash_table_destroy (status->priv->widgets);
105 status->priv->widgets = NULL;
108 g_free(status->priv);
110 GNOME_CALL_PARENT(G_OBJECT_CLASS, dispose, (widget));
113 static void
114 anjuta_status_instance_init (AnjutaStatus *status)
116 status->priv = g_new0 (AnjutaStatusPriv, 1);
117 status->priv->splash_file = NULL;
118 status->priv->splash_progress_position = 0;
119 status->priv->disable_splash = FALSE;
120 status->priv->total_ticks = 0;
121 status->priv->current_ticks = 0;
122 status->priv->splash = NULL;
123 status->priv->default_status_items =
124 g_hash_table_new_full (g_str_hash, g_str_equal,
125 g_free, g_free);
128 static void
129 anjuta_status_class_init (AnjutaStatusClass *class)
131 GObjectClass *object_class;
133 parent_class = g_type_class_peek_parent (class);
134 object_class = (GObjectClass*) class;
135 object_class->finalize = anjuta_status_finalize;
136 object_class->dispose = anjuta_status_dispose;
138 status_signals[BUSY] =
139 g_signal_new ("busy",
140 ANJUTA_TYPE_STATUS,
141 G_SIGNAL_RUN_LAST,
142 G_STRUCT_OFFSET (AnjutaStatusClass, busy),
143 NULL, NULL,
144 g_cclosure_marshal_VOID__BOOLEAN,
145 G_TYPE_NONE, 1,
146 G_TYPE_BOOLEAN);
149 GtkWidget *
150 anjuta_status_new (void)
152 GtkWidget *status;
154 status = GTK_WIDGET (g_object_new (ANJUTA_TYPE_STATUS,
155 "has-progress", TRUE, "has-status", TRUE,
156 "interactivity", GNOME_PREFERENCES_NEVER, NULL));
157 return status;
160 void
161 anjuta_status_set (AnjutaStatus *status, const gchar * mesg, ...)
163 gchar* message;
164 va_list args;
166 g_return_if_fail (ANJUTA_IS_STATUS (status));
167 g_return_if_fail (mesg != NULL);
169 va_start (args, mesg);
170 message = g_strdup_vprintf (mesg, args);
171 va_end (args);
172 gnome_appbar_set_status (GNOME_APPBAR (status), message);
173 g_free(message);
176 void
177 anjuta_status_push (AnjutaStatus *status, const gchar * mesg, ...)
179 gchar* message;
180 va_list args;
182 g_return_if_fail (ANJUTA_IS_STATUS (status));
183 g_return_if_fail (mesg != NULL);
185 va_start (args, mesg);
186 message = g_strdup_vprintf (mesg, args);
187 va_end (args);
188 gnome_appbar_push (GNOME_APPBAR (status), message);
189 g_free(message);
192 static void
193 foreach_widget_set_cursor (gpointer widget, gpointer value, gpointer cursor)
195 if (GTK_WIDGET (widget)->window)
196 gdk_window_set_cursor (GTK_WIDGET (widget)->window, (GdkCursor*)cursor);
199 void
200 anjuta_status_busy_push (AnjutaStatus *status)
202 GtkWidget *top;
203 GdkCursor *cursor;
205 g_return_if_fail (ANJUTA_IS_STATUS (status));
207 top = gtk_widget_get_toplevel (GTK_WIDGET (status));
208 if (top == NULL)
209 return;
211 status->priv->busy_count++;
212 if (status->priv->busy_count > 1)
213 return;
214 cursor = gdk_cursor_new (GDK_WATCH);
215 if (GTK_WIDGET (top)->window)
216 gdk_window_set_cursor (GTK_WIDGET (top)->window, cursor);
217 if (status->priv->widgets)
218 g_hash_table_foreach (status->priv->widgets,
219 foreach_widget_set_cursor, cursor);
220 gdk_cursor_unref (cursor);
221 gdk_flush ();
222 g_signal_emit_by_name (G_OBJECT (status), "busy", TRUE);
225 void
226 anjuta_status_busy_pop (AnjutaStatus *status)
228 GtkWidget *top;
230 g_return_if_fail (ANJUTA_IS_STATUS (status));
232 top = gtk_widget_get_toplevel (GTK_WIDGET (status));
233 if (top == NULL)
234 return;
236 status->priv->busy_count--;
237 if (status->priv->busy_count > 0)
238 return;
240 status->priv->busy_count = 0;
241 if (GTK_WIDGET (top)->window)
242 gdk_window_set_cursor (GTK_WIDGET (top)->window, NULL);
243 if (status->priv->widgets)
244 g_hash_table_foreach (status->priv->widgets,
245 foreach_widget_set_cursor, NULL);
246 g_signal_emit_by_name (G_OBJECT (status), "busy", FALSE);
249 static void
250 foreach_hash (gpointer key, gpointer value, gpointer userdata)
252 GString *str = (GString*)(userdata);
253 const gchar *divider = ": ";
254 const gchar *separator = " ";
256 g_string_append (str, separator);
257 g_string_append (str, (const gchar*)key);
258 g_string_append (str, divider);
259 g_string_append (str, (const gchar*)value);
262 void
263 anjuta_status_set_default (AnjutaStatus *status, const gchar *label,
264 const gchar *value_format, ...)
266 GString *str;
267 gchar *status_str;
269 g_return_if_fail (ANJUTA_IS_STATUS (status));
270 g_return_if_fail (label != NULL);
272 if (value_format)
274 gchar* value;
275 va_list args;
277 va_start (args, value_format);
278 value = g_strdup_vprintf (value_format, args);
279 va_end (args);
280 g_hash_table_replace (status->priv->default_status_items,
281 g_strdup (label), value);
283 else
285 if (g_hash_table_lookup (status->priv->default_status_items, label))
287 g_hash_table_remove (status->priv->default_status_items, label);
291 /* Update default status */
292 str = g_string_new (NULL);
293 g_hash_table_foreach (status->priv->default_status_items, foreach_hash, str);
294 status_str = g_string_free (str, FALSE);
295 gnome_appbar_set_default (GNOME_APPBAR (status), status_str);
296 g_free (status_str);
299 static void
300 on_widget_destroy (AnjutaStatus *status, GObject *widget)
302 if (g_hash_table_lookup (status->priv->widgets, widget))
303 g_hash_table_remove (status->priv->widgets, widget);
306 void
307 anjuta_status_add_widget (AnjutaStatus *status, GtkWidget *widget)
309 g_return_if_fail (ANJUTA_IS_STATUS (status));
310 g_return_if_fail (GTK_IS_WIDGET (widget));
312 if (status->priv->widgets == NULL)
313 status->priv->widgets =
314 g_hash_table_new (g_direct_hash, g_direct_equal);
316 g_hash_table_insert (status->priv->widgets, widget, widget);
317 g_object_weak_ref (G_OBJECT (widget),
318 (GWeakNotify) (on_widget_destroy), status);
321 void
322 anjuta_status_set_splash (AnjutaStatus *status, const gchar *splash_file,
323 gint splash_progress_position)
325 g_return_if_fail (ANJUTA_IS_STATUS (status));
326 g_return_if_fail (splash_file != NULL);
327 g_return_if_fail (splash_progress_position >= 0);
328 if (status->priv->splash_file)
329 g_free (status->priv->splash_file);
330 status->priv->splash_file = g_strdup (splash_file);
331 status->priv->splash_progress_position = splash_progress_position;
334 void
335 anjuta_status_disable_splash (AnjutaStatus *status,
336 gboolean disable_splash)
338 g_return_if_fail (ANJUTA_IS_STATUS (status));
340 status->priv->disable_splash = disable_splash;
341 if (status->priv->splash)
343 gtk_widget_destroy (status->priv->splash);
344 status->priv->splash = NULL;
345 anjuta_status_progress_add_ticks (status, 0);
349 void
350 anjuta_status_progress_add_ticks (AnjutaStatus *status, gint ticks)
352 gfloat percentage;
354 g_return_if_fail (ANJUTA_IS_STATUS (status));
355 g_return_if_fail (ticks >= 0);
357 status->priv->total_ticks += ticks;
358 if (!GTK_WIDGET_REALIZED (status))
360 if (status->priv->splash == NULL &&
361 status->priv->splash_file &&
362 !status->priv->disable_splash)
364 status->priv->splash = e_splash_new (status->priv->splash_file, 100);
365 if (status->priv->splash)
366 gtk_widget_show (status->priv->splash);
369 percentage = ((gfloat)status->priv->current_ticks)/status->priv->total_ticks;
370 if (status->priv->splash)
372 e_splash_set (E_SPLASH(status->priv->splash), NULL, NULL, NULL,
373 percentage);
374 while (g_main_context_iteration(NULL, FALSE));
376 else
378 GtkProgressBar *progressbar;
379 GtkWidget *statusbar;
381 gnome_appbar_set_progress_percentage (GNOME_APPBAR (status),
382 percentage);
383 progressbar = gnome_appbar_get_progress (GNOME_APPBAR (status));
384 statusbar = gnome_appbar_get_status (GNOME_APPBAR (status));
385 gtk_widget_queue_draw (GTK_WIDGET (statusbar));
386 gtk_widget_queue_draw (GTK_WIDGET (progressbar));
387 if (GTK_WIDGET(progressbar)->window != NULL &&
388 GDK_IS_WINDOW(GTK_WIDGET(progressbar)->window))
389 gdk_window_process_updates (GTK_WIDGET(progressbar)->window, TRUE);
390 if (GTK_WIDGET(statusbar)->window != NULL &&
391 GDK_IS_WINDOW(GTK_WIDGET(statusbar)->window))
392 gdk_window_process_updates (GTK_WIDGET(statusbar)->window, TRUE);
396 void
397 anjuta_status_progress_tick (AnjutaStatus *status,
398 GdkPixbuf *icon, const gchar *text)
400 gfloat percentage;
402 g_return_if_fail (ANJUTA_IS_STATUS (status));
403 g_return_if_fail (status->priv->total_ticks != 0);
405 status->priv->current_ticks++;
406 percentage = ((gfloat)status->priv->current_ticks)/status->priv->total_ticks;
408 if (status->priv->splash)
410 e_splash_set (E_SPLASH(status->priv->splash), icon, text, NULL, percentage);
411 while (g_main_context_iteration(NULL, FALSE));
413 else
415 GtkProgressBar *progressbar;
416 GtkWidget *statusbar;
418 if (text)
419 anjuta_status_set (status, "%s", text);
420 gnome_appbar_set_progress_percentage (GNOME_APPBAR (status),
421 percentage);
422 progressbar = gnome_appbar_get_progress (GNOME_APPBAR (status));
423 statusbar = gnome_appbar_get_status (GNOME_APPBAR (status));
424 gtk_widget_queue_draw (GTK_WIDGET (statusbar));
425 gtk_widget_queue_draw (GTK_WIDGET (progressbar));
426 if (GTK_WIDGET(progressbar)->window != NULL &&
427 GDK_IS_WINDOW(GTK_WIDGET(progressbar)->window))
428 gdk_window_process_updates (GTK_WIDGET(progressbar)->window, TRUE);
429 if (GTK_WIDGET(statusbar)->window != NULL &&
430 GDK_IS_WINDOW(GTK_WIDGET(statusbar)->window))
431 gdk_window_process_updates (GTK_WIDGET(statusbar)->window, TRUE);
433 if (status->priv->current_ticks >= status->priv->total_ticks)
434 anjuta_status_progress_reset (status);
437 void
438 anjuta_status_progress_reset (AnjutaStatus *status)
440 g_return_if_fail (ANJUTA_IS_STATUS (status));
441 if (status->priv->splash)
443 gtk_widget_destroy (status->priv->splash);
444 status->priv->splash = NULL;
446 status->priv->current_ticks = 0;
447 status->priv->total_ticks = 0;
448 gnome_appbar_set_progress_percentage (GNOME_APPBAR (status), 0);
449 gnome_appbar_refresh (GNOME_APPBAR(status));
452 static gboolean
453 anjuta_status_timeout (AnjutaStatus *status)
455 anjuta_status_pop (status);
456 return FALSE;
459 /* Display message in status until timeout (secondes) */
460 void
461 anjuta_status (AnjutaStatus *status, const gchar *mesg, gint timeout)
463 g_return_if_fail (ANJUTA_IS_STATUS (status));
464 g_return_if_fail (mesg != NULL);
465 anjuta_status_push (status, "%s", mesg);
466 g_timeout_add (timeout * 1000, (void*) anjuta_status_timeout, status);
469 void
470 anjuta_status_set_title_window (AnjutaStatus *status, GtkWidget *window)
472 g_return_if_fail (ANJUTA_IS_STATUS (status));
473 g_return_if_fail (GTK_IS_WINDOW (window));
474 status->priv->window = GTK_WINDOW (window);
475 g_object_add_weak_pointer (G_OBJECT (window),
476 (gpointer*)&status->priv->window);
479 void
480 anjuta_status_set_title (AnjutaStatus *status, const gchar *title)
482 g_return_if_fail (ANJUTA_IS_STATUS (status));
484 if (!status->priv->window)
485 return;
487 if (title)
489 gchar *str;
490 str = g_strconcat (title, " - ",
491 g_get_application_name(), NULL);
492 gtk_window_set_title (status->priv->window, str);
493 g_free (str);
495 else
497 gtk_window_set_title (status->priv->window,
498 g_get_application_name ());
502 ANJUTA_TYPE_BEGIN(AnjutaStatus, anjuta_status, GNOME_TYPE_APPBAR);
503 ANJUTA_TYPE_END;