2 * This file is a part of hildon
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
11 * the License, or (at your option) any later version.
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. Additional features
31 * such as progress bars or animation can also be included.
34 * <title>HildonNote example</title>
38 * show_confirmation_note (GtkWindow *parent)
42 * note = hildon_note_new_confirmation (parent, "Confirmation message...");
44 * retcode = gtk_dialog_run (GTK_DIALOG (note));
45 * gtk_widget_destroy (note);
47 * if (retcode == GTK_RESPONSE_OK) {
48 * g_debug ("User pressed 'OK' button'");
51 * g_debug ("User pressed 'Cancel' button");
67 #include <X11/Xatom.h>
70 #include "hildon-note.h"
71 #include "hildon-defines.h"
72 #include "hildon-sound.h"
73 #include "hildon-banner.h"
74 #include "hildon-enum-types.h"
75 #include "hildon-note-private.h"
78 #define CONFIRMATION_SOUND_PATH \
79 "/usr/share/sounds/ui-confirmation_note.wav"
81 #define INFORMATION_SOUND_PATH \
82 "/usr/share/sounds/ui-information_note.wav"
84 #define HILDON_NOTE_CONFIRMATION_ICON \
87 #define HILDON_NOTE_INFORMATION_ICON \
90 #define _(String) dgettext("hildon-libs", String)
93 hildon_note_class_init (HildonNoteClass *class);
96 hildon_note_init (HildonNote *dialog);
99 hildon_note_rebuild (HildonNote *note);
102 hildon_note_finalize (GObject *obj_self);
105 hildon_note_realize (GtkWidget *widget);
108 hildon_note_set_property (GObject *object,
114 hildon_note_get_property (GObject *object,
120 sound_handling (GtkWidget *widget,
121 GdkEventExpose *event,
127 PROP_HILDON_NOTE_TYPE,
128 PROP_HILDON_NOTE_DESCRIPTION,
129 PROP_HILDON_NOTE_ICON,
130 PROP_HILDON_NOTE_PROGRESSBAR,
131 PROP_HILDON_NOTE_STOCK_ICON
134 static GtkDialogClass* parent_class;
138 hildon_note_set_property (GObject *object,
143 HildonNote *note = HILDON_NOTE (object);
144 HildonNotePrivate *priv;
147 priv = HILDON_NOTE_GET_PRIVATE (note);
152 case PROP_HILDON_NOTE_TYPE:
153 priv->note_n = g_value_get_enum (value);
154 hildon_note_rebuild (note);
157 case PROP_HILDON_NOTE_DESCRIPTION:
158 if (priv->original_description)
159 g_free (priv->original_description);
160 priv->original_description = g_value_dup_string (value);
162 gtk_label_set_text (GTK_LABEL (priv->label), priv->original_description);
163 /* FIXME Is the "original_description" used anywhere? */
167 case PROP_HILDON_NOTE_ICON:
168 gtk_image_set_from_icon_name (GTK_IMAGE (priv->icon),
169 g_value_get_string(value), HILDON_ICON_SIZE_BIG_NOTE);
172 case PROP_HILDON_NOTE_STOCK_ICON:
173 gtk_image_set_from_stock (GTK_IMAGE (priv->icon),
174 g_value_get_string (value), HILDON_ICON_SIZE_BIG_NOTE);
177 case PROP_HILDON_NOTE_PROGRESSBAR:
178 widget = g_value_get_object (value);
179 if (widget != priv->progressbar)
181 if (priv->progressbar)
182 g_object_unref (priv->progressbar);
184 priv->progressbar = widget;
188 g_object_ref (widget);
189 gtk_object_sink (GTK_OBJECT (widget));
192 hildon_note_rebuild (note);
197 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
203 hildon_note_get_property (GObject *object,
208 HildonNote *note = HILDON_NOTE (object);
209 HildonNotePrivate *priv;
211 priv = HILDON_NOTE_GET_PRIVATE (note);
215 case PROP_HILDON_NOTE_TYPE:
216 g_value_set_enum (value, priv->note_n);
219 case PROP_HILDON_NOTE_DESCRIPTION:
220 g_value_set_string (value, priv->original_description);
223 case PROP_HILDON_NOTE_ICON:
224 g_object_get_property (G_OBJECT (priv->icon), "icon-name", value);
227 case PROP_HILDON_NOTE_STOCK_ICON:
228 g_object_get_property (G_OBJECT (priv->icon), "stock", value);
231 case PROP_HILDON_NOTE_PROGRESSBAR:
232 g_value_set_object (value, priv->progressbar);
236 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
242 * hildon_note_get_type:
244 * Returns GType for HildonNote.
246 * Returns: HildonNote type
249 hildon_note_get_type (void)
251 static GType dialog_type = 0;
254 static const GTypeInfo dialog_info = {
255 sizeof(HildonNoteClass),
256 NULL, /* base_init */
257 NULL, /* base_finalize */
258 (GClassInitFunc) hildon_note_class_init,
259 NULL, /* class_finalize */
260 NULL, /* class_data */
263 (GInstanceInitFunc) hildon_note_init
265 dialog_type = g_type_register_static (GTK_TYPE_DIALOG,
273 hildon_note_class_init (HildonNoteClass *class)
275 GObjectClass *object_class = G_OBJECT_CLASS (class);
276 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
278 /* set the global parent_class */
279 parent_class = g_type_class_peek_parent (class);
281 g_type_class_add_private (class, sizeof (HildonNotePrivate));
283 object_class->finalize = hildon_note_finalize;
284 object_class->set_property = hildon_note_set_property;
285 object_class->get_property = hildon_note_get_property;
286 widget_class->realize = hildon_note_realize;
288 g_object_class_install_property (object_class,
289 PROP_HILDON_NOTE_TYPE,
290 g_param_spec_enum ("note-type",
292 "The type of the note dialog",
293 hildon_note_type_get_type (),
294 HILDON_NOTE_TYPE_CONFIRMATION,
295 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
298 * HildonNote:description:
300 * Description for the note.
302 g_object_class_install_property (object_class,
303 PROP_HILDON_NOTE_DESCRIPTION,
304 g_param_spec_string ("description",
306 "The text that appears in the note dialog",
315 g_object_class_install_property (object_class,
316 PROP_HILDON_NOTE_ICON,
317 g_param_spec_string ("icon",
319 "The name of the icon that appears in the note dialog",
324 * HildonNote:stock-icon:
326 * Stock icon name for the note.
328 g_object_class_install_property (object_class,
329 PROP_HILDON_NOTE_STOCK_ICON,
330 g_param_spec_string ("stock-icon",
332 "The stock name of the icon that appears in the note dialog",
337 * HildonNote:progressbar:
339 * Progressbar for the note (if any).
341 g_object_class_install_property (object_class,
342 PROP_HILDON_NOTE_PROGRESSBAR,
343 g_param_spec_object ("progressbar",
344 "Progressbar widget",
345 "The progressbar that appears in the note dialog",
346 GTK_TYPE_PROGRESS_BAR,
351 hildon_note_init (HildonNote *dialog)
353 HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (dialog);
356 priv->label = gtk_label_new (NULL);
357 gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
359 priv->icon = gtk_image_new ();
361 /* Acquire real references to our internal children, since
362 they are not nessecarily packed into container in each
364 g_object_ref_sink (priv->label);
365 g_object_ref_sink (priv->icon);
367 gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
368 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
373 hildon_note_finalize (GObject *obj_self)
375 HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (obj_self);
378 /* FIXME Some of this stuff should be moved to dispose */
380 /* Free internal data */
382 g_object_unref (priv->label);
385 g_object_unref (priv->icon);
387 if (priv->progressbar)
388 g_object_unref (priv->progressbar);
390 if (priv->original_description)
391 g_free (priv->original_description);
393 G_OBJECT_CLASS (parent_class)->finalize (obj_self);
398 hildon_note_realize (GtkWidget *widget)
402 const gchar *notification_type;
403 HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget);
406 /* Make widget->window accessible */
407 GTK_WIDGET_CLASS (parent_class)->realize (widget);
409 /* Border only, no titlebar */
410 gdk_window_set_decorations (widget->window, GDK_DECOR_BORDER);
412 /* Because ESD is synchronous, we wish to play sound after the
413 note is already on screen to avoid blocking its appearance */
414 if (priv->sound_signal_handler == 0)
415 priv->sound_signal_handler = g_signal_connect_after(widget,
416 "expose-event", G_CALLBACK (sound_handling), NULL);
418 /* We use special hint to turn the note into information notification. */
419 gdk_window_set_type_hint (widget->window, GDK_WINDOW_TYPE_HINT_NOTIFICATION);
421 /* Set the _HILDON_NOTIFICATION_TYPE property so Matchbox places the window correctly */
422 display = gdk_drawable_get_display (widget->window);
423 atom = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_NOTIFICATION_TYPE");
425 if (priv->note_n == HILDON_NOTE_TYPE_INFORMATION ||
426 priv->note_n == HILDON_NOTE_TYPE_INFORMATION_THEME) {
427 notification_type = "_HILDON_NOTIFICATION_TYPE_INFO";
429 notification_type = "_HILDON_NOTIFICATION_TYPE_CONFIRMATION";
432 XChangeProperty (GDK_WINDOW_XDISPLAY (widget->window), GDK_WINDOW_XID (widget->window),
433 atom, XA_STRING, 8, PropModeReplace, (guchar *) notification_type,
434 strlen (notification_type));
437 /* Helper function for removing a widget from it's container.
438 we own a separate reference to each object we try to unpack,
439 so extra referencing is not needed. */
441 unpack_widget (GtkWidget *widget)
443 g_assert (widget == NULL || GTK_IS_WIDGET (widget));
445 if (widget && widget->parent)
446 gtk_container_remove (GTK_CONTAINER (widget->parent), widget);
450 hildon_note_rebuild (HildonNote *note)
453 HildonNotePrivate *priv;
454 gboolean IsHorizontal = TRUE;
456 g_assert (HILDON_IS_NOTE (note));
458 priv = HILDON_NOTE_GET_PRIVATE (note);
461 dialog = GTK_DIALOG (note);
463 /* Reuse exiting content widgets for new layout */
464 unpack_widget (priv->label);
465 unpack_widget (priv->icon);
466 unpack_widget (priv->progressbar);
468 /* Destroy old layout and buttons */
470 gtk_widget_destroy (priv->box);
473 if (priv->okButton) {
474 gtk_widget_destroy (priv->okButton);
475 priv->okButton = NULL;
477 if (priv->cancelButton) {
478 gtk_widget_destroy (priv->cancelButton);
479 priv->cancelButton = NULL;
482 /* Add needed buttons and images for each note type */
483 switch (priv->note_n)
485 case HILDON_NOTE_TYPE_CONFIRMATION:
486 priv->okButton = gtk_dialog_add_button (dialog,
487 _("ecdg_bd_confirmation_note_ok"), GTK_RESPONSE_OK);
488 priv->cancelButton = gtk_dialog_add_button (dialog,
489 _("ecdg_bd_confirmation_note_cancel"), GTK_RESPONSE_CANCEL);
492 case HILDON_NOTE_TYPE_CONFIRMATION_BUTTON:
493 gtk_image_set_from_icon_name (GTK_IMAGE (priv->icon),
494 HILDON_NOTE_CONFIRMATION_ICON,
495 HILDON_ICON_SIZE_BIG_NOTE);
498 case HILDON_NOTE_TYPE_INFORMATION_THEME:
499 case HILDON_NOTE_TYPE_INFORMATION:
500 gtk_image_set_from_icon_name (GTK_IMAGE (priv->icon),
501 HILDON_NOTE_INFORMATION_ICON,
502 HILDON_ICON_SIZE_BIG_NOTE);
505 case HILDON_NOTE_TYPE_PROGRESSBAR:
506 priv->cancelButton = gtk_dialog_add_button (dialog,
507 _("ecdg_bd_cancel_note_cancel"), GTK_RESPONSE_CANCEL);
508 IsHorizontal = FALSE;
516 /* Pack item with label horizontally */
517 priv->box = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
518 gtk_container_add (GTK_CONTAINER (dialog->vbox), priv->box);
521 GtkWidget *alignment = gtk_alignment_new (0, 0, 0, 0);
523 gtk_box_pack_start (GTK_BOX (priv->box), alignment, FALSE, FALSE, 0);
524 gtk_container_add (GTK_CONTAINER (alignment), priv->icon);
526 gtk_box_pack_start (GTK_BOX (priv->box), priv->label, TRUE, TRUE, 0);
529 /* Pack item with label vertically */
530 priv->box = gtk_vbox_new (FALSE, HILDON_MARGIN_DOUBLE);
531 gtk_container_add (GTK_CONTAINER (dialog->vbox), priv->box);
532 gtk_box_pack_start (GTK_BOX (priv->box), priv->label, TRUE, TRUE, 0);
534 if (priv->progressbar)
535 gtk_box_pack_start (GTK_BOX (priv->box), priv->progressbar, FALSE, FALSE, 0);
538 gtk_widget_show_all (priv->box);
542 * hildon_note_new_confirmation_add_buttons:
543 * @parent: the parent window. The X window ID of the parent window
544 * has to be the same as the X window ID of the application. This is
545 * important so that the window manager could handle the windows
547 * In GTK the X window ID can be checked using
548 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
549 * @description: the message to confirm
550 * @Varargs: arguments pairs for new buttons(label and return value).
551 * Terminate the list with %NULL value.
553 * Create a new confirmation note with custom buttons. Confirmation
554 * note has a text and any number of buttons. It's important to note
555 * that even though the name of the function might suggest, the
556 * default ok/cancel buttons are not appended but you have to provide
557 * all of the buttons.
559 * FIXME: This doc seems to be wrong, the two buttons aren't added so
560 * it would only contain the "additional" buttons? However, changing
561 * this would break those applications that rely on current behaviour.
563 * Returns: A #GtkWidget pointer of the note
566 hildon_note_new_confirmation_add_buttons (GtkWindow *parent,
567 const gchar *description,
574 g_return_val_if_fail (description != NULL, NULL);
576 GtkWidget *conf_note =
577 g_object_new (HILDON_TYPE_NOTE,
578 "note-type", HILDON_NOTE_TYPE_CONFIRMATION_BUTTON,
579 "description", description,
580 "icon", HILDON_NOTE_CONFIRMATION_ICON,
584 gtk_window_set_transient_for (GTK_WINDOW (conf_note), parent);
586 /* Add the buttons from varargs */
587 va_start(args, description);
590 message = va_arg (args, char *);
595 value = va_arg (args, int);
597 gtk_dialog_add_button (GTK_DIALOG (conf_note), message, value);
607 * hildon_note_new_confirmation:
608 * @parent: the parent window. The X window ID of the parent window
609 * has to be the same as the X window ID of the application. This is
610 * important so that the window manager could handle the windows
611 * correctly. In GTK the X window ID can be checked using
612 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
613 * @description: the message to confirm
615 * Create a new confirmation note. Confirmation note has text (description)
616 * that you specify, two buttons and a default confirmation stock icon.
618 * Returns: a #GtkWidget pointer of the note
621 hildon_note_new_confirmation (GtkWindow *parent,
622 const gchar *description)
624 return hildon_note_new_confirmation_with_icon_name
625 (parent, description, HILDON_NOTE_CONFIRMATION_ICON);
629 * hildon_note_new_confirmation_with_icon_name:
630 * @parent: the parent window. The X window ID of the parent window
631 * has to be the same as the X window ID of the application. This is
632 * important so that the window manager could handle the windows
633 * correctly. In GTK the X window ID can be checked using
634 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
635 * @description: the message to confirm
636 * @icon_name: icon to be displayed. If NULL, default icon is used.
638 * Create a new confirmation note. Confirmation note has text(description)
639 * that you specify, two buttons and an icon.
641 * Returns: a #GtkWidget pointer of the note
644 hildon_note_new_confirmation_with_icon_name (GtkWindow *parent,
645 const gchar *description,
646 const gchar *icon_name)
648 GtkWidget *dialog = NULL;
650 g_return_val_if_fail (description != NULL, NULL);
652 dialog = g_object_new (HILDON_TYPE_NOTE,
654 HILDON_NOTE_TYPE_CONFIRMATION,
655 "description", description, "icon",
659 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
665 * hildon_note_new_information:
666 * @parent: the parent window. The X window ID of the parent window
667 * has to be the same as the X window ID of the application. This is
668 * important so that the window manager could handle the windows
669 * correctly. In GTK the X window ID can be checked using
670 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
671 * @description: the message to confirm
673 * Create a new information note. Information note has a text(description)
674 * that you specify, an OK button and an icon.
676 * Returns: a #GtkWidget pointer of the note
679 hildon_note_new_information (GtkWindow *parent,
680 const gchar *description)
682 return hildon_note_new_information_with_icon_name
683 (parent, description, HILDON_NOTE_INFORMATION_ICON);
687 * hildon_note_new_information_with_icon_name:
688 * @parent: the parent window. The X window ID of the parent window
689 * has to be the same as the X window ID of the application. This is
690 * important so that the window manager could handle the windows
691 * correctly. In GTK the X window ID can be checked using
692 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
693 * @description: the message to confirm
694 * @icon_name: icon to be displayed. If NULL, default icon is used.
696 * Create a new information note. Information note has text(description)
697 * that you specify, an OK button and an icon.
699 * Returns: a #GtkWidget pointer of the note
702 hildon_note_new_information_with_icon_name (GtkWindow * parent,
703 const gchar *description,
704 const gchar *icon_name)
706 GtkWidget *dialog = NULL;
708 g_return_val_if_fail (description != NULL, NULL);
709 g_return_val_if_fail (icon_name != NULL, NULL);
711 dialog = g_object_new (HILDON_TYPE_NOTE,
713 HILDON_NOTE_TYPE_INFORMATION_THEME,
714 "description", description,
715 "icon", icon_name, NULL);
718 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
723 /* FIXME This documentation string LIES! */
726 * hildon_note_new_cancel_with_progress_bar:
727 * @parent: the parent window. The X window ID of the parent window
728 * has to be the same as the X window ID of the application. This is
729 * important so that the window manager could handle the windows
730 * correctly. In GTK the X window ID can be checked using
731 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
732 * @description: the action to cancel
733 * @progressbar: a pointer to #GtkProgressBar to be filled with the
734 * progressbar assigned to this note. Use this to set the fraction of
735 * progressbar done. This parameter can be %NULL as well, in which
736 * case plain text cancel note appears.
738 * Create a new cancel note with a progress bar. Cancel note has
739 * text(description) that you specify, a Cancel button and a progress bar.
741 * Returns: a #GtkDialog. Use this to get rid of this note when you
745 hildon_note_new_cancel_with_progress_bar (GtkWindow *parent,
746 const gchar *description,
747 GtkProgressBar *progressbar)
749 GtkWidget *dialog = NULL;
751 g_return_val_if_fail (description != NULL, NULL);
753 dialog = g_object_new (HILDON_TYPE_NOTE,
755 HILDON_NOTE_TYPE_PROGRESSBAR,
756 "description", description,
761 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
768 * hildon_note_set_button_text:
769 * @note: a #HildonNote
770 * @text: sets the button text and if there is two buttons in dialog,
771 * the button texts will be <text>, "Cancel".
773 * Sets the button text to be used by the hildon_note widget.
776 hildon_note_set_button_text (HildonNote *note,
779 HildonNotePrivate *priv;
781 g_return_if_fail (HILDON_IS_NOTE (note));
783 priv = HILDON_NOTE_GET_PRIVATE (HILDON_NOTE (note));
786 if (priv->okButton) {
787 gtk_button_set_label (GTK_BUTTON (priv->okButton), text);
788 gtk_button_set_label (GTK_BUTTON (priv->cancelButton),
789 _("ecdg_bd_confirmation_note_cancel"));
791 gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text);
796 * hildon_note_set_button_texts:
797 * @note: a #HildonNote
798 * @text_ok: the new text of the default OK button
799 * @text_cancel: the new text of the default cancel button
801 * Sets the button texts to be used by this hildon_note widget.
804 hildon_note_set_button_texts (HildonNote *note,
805 const gchar *text_ok,
806 const gchar *text_cancel)
808 HildonNotePrivate *priv;
810 g_return_if_fail (HILDON_IS_NOTE (note));
812 priv = HILDON_NOTE_GET_PRIVATE (HILDON_NOTE (note));
815 if (priv->okButton) {
816 gtk_button_set_label (GTK_BUTTON (priv->okButton), text_ok);
817 gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text_cancel);
819 gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text_cancel);
823 /* We play a system sound when the note comes visible */
825 sound_handling (GtkWidget *widget,
826 GdkEventExpose *event,
829 HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget);
832 g_signal_handler_disconnect (widget, priv->sound_signal_handler);
834 priv->sound_signal_handler = 0;
836 switch (priv->note_n)
838 case HILDON_NOTE_TYPE_INFORMATION:
839 case HILDON_NOTE_TYPE_INFORMATION_THEME:
840 hildon_play_system_sound (INFORMATION_SOUND_PATH);
843 case HILDON_NOTE_TYPE_CONFIRMATION:
844 case HILDON_NOTE_TYPE_CONFIRMATION_BUTTON:
845 hildon_play_system_sound (CONFIRMATION_SOUND_PATH);