2 * This file is part of hildon-libs
4 * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved.
6 * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; version 2.1 of
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 * @short_description: A widget to ask confirmation from the user
29 * Notes are used to for confirmation (OK/Cancel/etc.) from the user.
30 * A simple note contains an information text and an OK button to be
31 * pressed. Additional features such as progress bars or animation can
39 #include "hildon-note.h"
40 #include <gtk/gtklabel.h>
41 #include <gtk/gtkimage.h>
42 #include <gtk/gtkhbox.h>
43 #include <gtk/gtkalignment.h>
44 #include <gtk/gtkvbox.h>
45 #include <gtk/gtkbutton.h>
47 #include "hildon-defines.h"
48 #include "hildon-sound.h"
49 #include "hildon-banner.h"
50 #include "hildon-enum-types.h"
53 #include "hildon-note-private.h"
55 #define CONFIRMATION_SOUND_PATH \
56 "/usr/share/sounds/ui-confirmation_note.wav"
58 #define INFORMATION_SOUND_PATH \
59 "/usr/share/sounds/ui-information_note.wav"
61 #define HILDON_NOTE_CONFIRMATION_ICON \
64 #define HILDON_NOTE_INFORMATION_ICON \
67 #define _(String) dgettext(PACKAGE, String)
70 hildon_note_class_init (HildonNoteClass *class);
73 hildon_note_init (HildonNote *dialog);
76 hildon_note_rebuild (HildonNote *note);
79 hildon_note_finalize (GObject *obj_self);
82 hildon_note_realize (GtkWidget *widget);
85 hildon_note_set_property (GObject *object,
91 hildon_note_get_property (GObject *object,
97 sound_handling (GtkWidget *widget,
98 GdkEventExpose *event,
104 PROP_HILDON_NOTE_TYPE,
105 PROP_HILDON_NOTE_DESCRIPTION,
106 PROP_HILDON_NOTE_ICON,
107 PROP_HILDON_NOTE_PROGRESSBAR,
108 PROP_HILDON_NOTE_STOCK_ICON
111 static GtkDialogClass* parent_class;
114 hildon_note_set_property (GObject *object,
119 HildonNote *note = HILDON_NOTE (object);
120 HildonNotePrivate *priv;
123 priv = HILDON_NOTE_GET_PRIVATE (note);
128 case PROP_HILDON_NOTE_TYPE:
129 priv->note_n = g_value_get_enum (value);
130 hildon_note_rebuild (note);
133 case PROP_HILDON_NOTE_DESCRIPTION:
134 g_free (priv->original_description);
135 priv->original_description = g_value_dup_string (value);
137 hildon_gtk_label_set_text_n_lines (GTK_LABEL (priv->label),
138 priv->original_description,
139 priv->note_n == HILDON_NOTE_PROGRESSBAR_TYPE ? 1 : 5);
143 case PROP_HILDON_NOTE_ICON:
144 gtk_image_set_from_icon_name (GTK_IMAGE (priv->icon),
145 g_value_get_string(value), HILDON_ICON_SIZE_BIG_NOTE);
148 case PROP_HILDON_NOTE_STOCK_ICON:
149 gtk_image_set_from_stock (GTK_IMAGE (priv->icon),
150 g_value_get_string (value), HILDON_ICON_SIZE_BIG_NOTE);
153 case PROP_HILDON_NOTE_PROGRESSBAR:
154 widget = g_value_get_object (value);
155 if (widget != priv->progressbar)
157 if (priv->progressbar)
158 g_object_unref (priv->progressbar);
160 priv->progressbar = widget;
164 g_object_ref (widget);
165 gtk_object_sink (GTK_OBJECT (widget));
168 hildon_note_rebuild (note);
173 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
179 hildon_note_get_property (GObject *object,
184 HildonNote *note = HILDON_NOTE (object);
185 HildonNotePrivate *priv;
187 priv = HILDON_NOTE_GET_PRIVATE (note);
191 case PROP_HILDON_NOTE_TYPE:
192 g_value_set_enum (value, priv->note_n);
195 case PROP_HILDON_NOTE_DESCRIPTION:
196 g_value_set_string (value, priv->original_description);
199 case PROP_HILDON_NOTE_ICON:
200 g_object_get_property (G_OBJECT (priv->icon), "icon-name", value);
203 case PROP_HILDON_NOTE_STOCK_ICON:
204 g_object_get_property (G_OBJECT (priv->icon), "stock", value);
207 case PROP_HILDON_NOTE_PROGRESSBAR:
208 g_value_set_object (value, priv->progressbar);
212 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
218 hildon_note_get_type (void)
220 static GType dialog_type = 0;
223 static const GTypeInfo dialog_info = {
224 sizeof(HildonNoteClass),
225 NULL, /* base_init */
226 NULL, /* base_finalize */
227 (GClassInitFunc) hildon_note_class_init,
228 NULL, /* class_finalize */
229 NULL, /* class_data */
232 (GInstanceInitFunc) hildon_note_init
234 dialog_type = g_type_register_static (GTK_TYPE_DIALOG,
242 hildon_note_class_init (HildonNoteClass *class)
244 GObjectClass *object_class = G_OBJECT_CLASS (class);
245 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
247 /* set the global parent_class */
248 parent_class = g_type_class_peek_parent (class);
250 g_type_class_add_private (class, sizeof (HildonNotePrivate));
252 object_class->finalize = hildon_note_finalize;
253 object_class->set_property = hildon_note_set_property;
254 object_class->get_property = hildon_note_get_property;
255 widget_class->realize = hildon_note_realize;
257 g_object_class_install_property (object_class,
258 PROP_HILDON_NOTE_TYPE,
259 g_param_spec_enum ("note_type",
261 "The type of the note dialog",
262 hildon_note_type_get_type(),
263 HILDON_NOTE_CONFIRMATION_TYPE,
264 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
267 * HildonNote:description:
269 * Description for note.
271 g_object_class_install_property (object_class,
272 PROP_HILDON_NOTE_DESCRIPTION,
273 g_param_spec_string ("description",
275 "The text that appears in the note dialog",
284 g_object_class_install_property (object_class,
285 PROP_HILDON_NOTE_ICON,
286 g_param_spec_string ("icon",
288 "The name of the icon that appears in the note dialog",
293 * HildonNote:stock-icon:
295 * Stock icon for note.
297 g_object_class_install_property (object_class,
298 PROP_HILDON_NOTE_STOCK_ICON,
299 g_param_spec_string ("stock-icon",
301 "The stock name of the icon that appears in the note dialog",
306 * HildonNote:progressbar:
308 * Progressbar for note.
310 g_object_class_install_property (object_class,
311 PROP_HILDON_NOTE_PROGRESSBAR,
312 g_param_spec_object ("progressbar",
313 "Progressbar widget",
314 "The progressbar that appears in the note dialog",
315 GTK_TYPE_PROGRESS_BAR,
320 hildon_note_init (HildonNote *dialog)
322 HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (dialog);
325 priv->label = gtk_label_new (NULL);
326 priv->icon = gtk_image_new ();
328 /* Acquire real references to our internal children, since
329 they are not nessecarily packed into container in each
331 g_object_ref (priv->label);
332 g_object_ref (priv->icon);
334 gtk_object_sink (GTK_OBJECT (priv->label));
335 gtk_object_sink (GTK_OBJECT (priv->icon));
337 gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
338 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
343 hildon_note_finalize (GObject *obj_self)
345 HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (obj_self);
348 /* FIXME Some of this stuff should be moved to dispose */
350 /* Free internal data */
352 g_object_unref (priv->label);
355 g_object_unref (priv->icon);
357 if (priv->progressbar)
358 g_object_unref (priv->progressbar);
360 if (priv->original_description)
361 g_free (priv->original_description);
363 G_OBJECT_CLASS (parent_class)->finalize (obj_self);
367 hildon_note_realize (GtkWidget *widget)
369 HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget);
372 /* Make widget->window accessible */
373 GTK_WIDGET_CLASS (parent_class)->realize (widget);
375 /* Border only, no titlebar */
376 gdk_window_set_decorations (widget->window, GDK_DECOR_BORDER);
378 /* Because ESD is synchronous, we wish to play sound after the
379 note is already on screen to avoid blocking its appearance */
380 if (priv->sound_signal_handler == 0)
381 priv->sound_signal_handler = g_signal_connect_after(widget,
382 "expose-event", G_CALLBACK (sound_handling), NULL);
385 /* Helper function for removing a widget from it's container.
386 we own a separate reference to each object we try to unpack,
387 so extra referencing is not needed. */
389 unpack_widget (GtkWidget *widget)
391 g_assert (widget == NULL || GTK_IS_WIDGET (widget));
393 if (widget && widget->parent)
394 gtk_container_remove (GTK_CONTAINER (widget->parent), widget);
398 hildon_note_rebuild (HildonNote *note)
401 HildonNotePrivate *priv;
402 gboolean IsHorizontal = TRUE;
404 g_assert (HILDON_IS_NOTE (note));
406 priv = HILDON_NOTE_GET_PRIVATE (note);
409 dialog = GTK_DIALOG (note);
411 /* Reuse exiting content widgets for new layout */
412 unpack_widget (priv->label);
413 unpack_widget (priv->icon);
414 unpack_widget (priv->progressbar);
416 /* Destroy old layout and buttons */
418 gtk_widget_destroy (priv->box);
421 if (priv->okButton) {
422 gtk_widget_destroy (priv->okButton);
423 priv->okButton = NULL;
425 if (priv->cancelButton) {
426 gtk_widget_destroy (priv->cancelButton);
427 priv->cancelButton = NULL;
430 /* Add needed buttons and images for each note type */
431 switch (priv->note_n)
433 case HILDON_NOTE_CONFIRMATION_TYPE:
434 priv->okButton = gtk_dialog_add_button (dialog,
435 _("ecdg_bd_confirmation_note_ok"), GTK_RESPONSE_OK);
436 priv->cancelButton = gtk_dialog_add_button (dialog,
437 _("ecdg_bd_confirmation_note_cancel"), GTK_RESPONSE_CANCEL);
440 case HILDON_NOTE_CONFIRMATION_BUTTON_TYPE:
441 gtk_image_set_from_icon_name (GTK_IMAGE (priv->icon),
442 HILDON_NOTE_CONFIRMATION_ICON,
443 HILDON_ICON_SIZE_BIG_NOTE);
446 case HILDON_NOTE_INFORMATION_THEME_TYPE:
447 case HILDON_NOTE_INFORMATION_TYPE:
448 /* Add clickable OK button (cancel really,
449 but doesn't matter since this is info) */
450 priv->cancelButton = gtk_dialog_add_button (dialog,
451 _("ecdg_bd_information_note_ok"), GTK_RESPONSE_CANCEL);
452 gtk_image_set_from_icon_name (GTK_IMAGE (priv->icon),
453 HILDON_NOTE_INFORMATION_ICON,
454 HILDON_ICON_SIZE_BIG_NOTE);
457 case HILDON_NOTE_PROGRESSBAR_TYPE:
458 priv->cancelButton = gtk_dialog_add_button (dialog,
459 _("ecdg_bd_cancel_note_cancel"), GTK_RESPONSE_CANCEL);
460 IsHorizontal = FALSE;
468 /* Pack item with label horizontally */
469 priv->box = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
470 gtk_container_add (GTK_CONTAINER (dialog->vbox), priv->box);
473 GtkWidget *alignment = gtk_alignment_new (0, 0, 0, 0);
475 gtk_box_pack_start (GTK_BOX (priv->box), alignment, FALSE, FALSE, 0);
476 gtk_container_add (GTK_CONTAINER (alignment), priv->icon);
478 gtk_box_pack_start (GTK_BOX (priv->box), priv->label, TRUE, TRUE, 0);
481 /* Pack item with label vertically */
482 priv->box = gtk_vbox_new (FALSE, HILDON_MARGIN_DOUBLE);
483 gtk_container_add (GTK_CONTAINER (dialog->vbox), priv->box);
484 gtk_box_pack_start (GTK_BOX (priv->box), priv->label, TRUE, TRUE, 0);
486 if (priv->progressbar)
487 gtk_box_pack_start (GTK_BOX (priv->box), priv->progressbar, FALSE, FALSE, 0);
490 gtk_widget_show_all (priv->box);
494 * hildon_note_new_confirmation_add_buttons:
495 * @parent: the parent window. The X window ID of the parent window
496 * has to be the same as the X window ID of the application. This is
497 * important so that the window manager could handle the windows
499 * In GTK the X window ID can be checked using
500 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
501 * @description: the message to confirm
502 * @Varargs: arguments pairs for new buttons(label and return value).
503 * Terminate the list with %NULL value.
505 * Create a new confirmation note with custom buttons. Confirmation
506 * note has a text and any number of buttons. It's important to note
507 * that even though the name of the function might suggest, the
508 * default ok/cancel buttons are not appended but you have to provide
509 * all of the buttons.
511 * FIXME: This doc seems to be wrong, the two buttons aren't added so
512 * it would only contain the "additional" buttons? However, changing
513 * this would break those applications that rely on current behaviour.
515 * Returns: A #GtkWidget pointer of the note
518 hildon_note_new_confirmation_add_buttons (GtkWindow *parent,
519 const gchar *description,
526 g_return_val_if_fail (GTK_IS_WINDOW (parent), NULL);
528 GtkWidget *conf_note =
529 g_object_new (HILDON_TYPE_NOTE,
530 "note_type", HILDON_NOTE_CONFIRMATION_BUTTON_TYPE,
531 "description", description,
532 "icon", HILDON_NOTE_CONFIRMATION_ICON,
536 gtk_window_set_transient_for (GTK_WINDOW (conf_note), parent);
538 /* Add the buttons from varargs */
539 va_start(args, description);
542 message = va_arg (args, char *);
547 value = va_arg (args, int);
549 gtk_dialog_add_button (GTK_DIALOG (conf_note), message, value);
559 * hildon_note_new_confirmation:
560 * @parent: the parent window. The X window ID of the parent window
561 * has to be the same as the X window ID of the application. This is
562 * important so that the window manager could handle the windows
563 * correctly. In GTK the X window ID can be checked using
564 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
565 * @description: the message to confirm
567 * Create a new confirmation note. Confirmation note has text (description)
568 * that you specify, two buttons and a default confirmation stock icon.
570 * Returns: a #GtkWidget pointer of the note
573 hildon_note_new_confirmation (GtkWindow *parent,
574 const gchar *description)
576 return hildon_note_new_confirmation_with_icon_name
577 (parent, description, HILDON_NOTE_CONFIRMATION_ICON);
581 * hildon_note_new_confirmation_with_icon_name:
582 * @parent: the parent window. The X window ID of the parent window
583 * has to be the same as the X window ID of the application. This is
584 * important so that the window manager could handle the windows
585 * correctly. In GTK the X window ID can be checked using
586 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
587 * @description: the message to confirm
588 * @icon_name: icon to be displayed. If NULL, default icon is used.
590 * Create a new confirmation note. Confirmation note has text(description)
591 * that you specify, two buttons and an icon.
593 * Returns: a #GtkWidget pointer of the note
596 hildon_note_new_confirmation_with_icon_name (GtkWindow *parent,
597 const gchar *description,
598 const gchar *icon_name)
600 GtkWidget *dialog = NULL;
602 g_return_val_if_fail (GTK_IS_WINDOW (parent), NULL);
604 dialog = g_object_new (HILDON_TYPE_NOTE,
606 HILDON_NOTE_CONFIRMATION_TYPE,
607 "description", description, "icon",
611 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
617 * hildon_note_new_information:
618 * @parent: the parent window. The X window ID of the parent window
619 * has to be the same as the X window ID of the application. This is
620 * important so that the window manager could handle the windows
621 * correctly. In GTK the X window ID can be checked using
622 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
623 * @description: the message to confirm
625 * Create a new information note. Information note has a text(description)
626 * that you specify, an OK button and an icon.
628 * Returns: a #GtkWidget pointer of the note
631 hildon_note_new_information (GtkWindow *parent,
632 const gchar *description)
634 return hildon_note_new_information_with_icon_name
635 (parent, description, HILDON_NOTE_INFORMATION_ICON);
639 * hildon_note_new_information_with_icon_name:
640 * @parent: the parent window. The X window ID of the parent window
641 * has to be the same as the X window ID of the application. This is
642 * important so that the window manager could handle the windows
643 * correctly. In GTK the X window ID can be checked using
644 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
645 * @description: the message to confirm
646 * @icon_name: icon to be displayed. If NULL, default icon is used.
648 * Create a new information note. Information note has text(description)
649 * that you specify, an OK button and an icon.
651 * Returns: a #GtkWidget pointer of the note
654 hildon_note_new_information_with_icon_name (GtkWindow * parent,
655 const gchar *description,
656 const gchar *icon_name)
658 GtkWidget *dialog = NULL;
660 g_return_val_if_fail (GTK_IS_WINDOW (parent), NULL);
662 dialog = g_object_new (HILDON_TYPE_NOTE,
664 HILDON_NOTE_INFORMATION_THEME_TYPE,
665 "description", description,
666 "icon", icon_name, NULL);
669 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
675 * hildon_note_new_cancel_with_progress_bar:
676 * @parent: the parent window. The X window ID of the parent window
677 * has to be the same as the X window ID of the application. This is
678 * important so that the window manager could handle the windows
679 * correctly. In GTK the X window ID can be checked using
680 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
681 * @description: the action to cancel
682 * @progressbar: a pointer to #GtkProgressBar to be filled with the
683 * progressbar assigned to this note. Use this to set the fraction of
684 * progressbar done. This parameter can be %NULL as well, in which
685 * case plain text cancel note appears.
687 * Create a new cancel note with a progress bar. Cancel note has
688 * text(description) that you specify, a Cancel button and a progress bar.
690 * Returns: a #GtkDialog. Use this to get rid of this note when you
694 hildon_note_new_cancel_with_progress_bar (GtkWindow *parent,
695 const gchar *description,
696 GtkProgressBar *progressbar)
698 GtkWidget *dialog = NULL;
700 g_return_val_if_fail (GTK_IS_WINDOW (parent), NULL);
702 dialog = g_object_new (HILDON_TYPE_NOTE,
704 HILDON_NOTE_PROGRESSBAR_TYPE,
705 "description", description,
710 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
717 * hildon_note_set_button_text:
718 * @note: a #HildonNote
719 * @text: sets the button text and if there is two buttons in dialog,
720 * the button texts will be <text>, "Cancel".
722 * Sets the button text to be used by the hildon_note widget.
725 hildon_note_set_button_text (HildonNote *note,
728 HildonNotePrivate *priv;
730 g_return_if_fail (HILDON_IS_NOTE (note));
732 priv = HILDON_NOTE_GET_PRIVATE (HILDON_NOTE (note));
735 if (priv->okButton) {
736 gtk_button_set_label (GTK_BUTTON (priv->okButton), text);
737 gtk_button_set_label (GTK_BUTTON (priv->cancelButton),
738 _("ecdg_bd_confirmation_note_cancel"));
740 gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text);
745 * hildon_note_set_button_texts:
746 * @note: a #HildonNote
747 * @textOk: the new text of the default OK button
748 * @textCancel: the new text of the default cancel button
750 * Sets the button texts to be used by this hildon_note widget.
753 hildon_note_set_button_texts (HildonNote *note,
754 const gchar *text_ok,
755 const gchar *text_cancel)
757 HildonNotePrivate *priv;
759 g_return_if_fail (HILDON_IS_NOTE (note));
761 priv = HILDON_NOTE_GET_PRIVATE (HILDON_NOTE (note));
764 if (priv->okButton) {
765 gtk_button_set_label (GTK_BUTTON (priv->okButton), text_ok);
766 gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text_cancel);
768 gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text_cancel);
772 /* We play a system sound when the note comes visible */
774 sound_handling (GtkWidget *widget,
775 GdkEventExpose *event,
778 HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget);
781 g_signal_handler_disconnect (widget, priv->sound_signal_handler);
783 priv->sound_signal_handler = 0;
785 switch (priv->note_n)
787 case HILDON_NOTE_INFORMATION_TYPE:
788 case HILDON_NOTE_INFORMATION_THEME_TYPE:
789 hildon_play_system_sound (INFORMATION_SOUND_PATH);
792 case HILDON_NOTE_CONFIRMATION_TYPE:
793 case HILDON_NOTE_CONFIRMATION_BUTTON_TYPE:
794 hildon_play_system_sound (CONFIRMATION_SOUND_PATH);