2 * This file is a part of hildon
4 * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved.
6 * Contact: Rodrigo Novo <rodrigo.novo@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 #undef HILDON_DISABLE_DEPRECATED
72 #include "hildon-note.h"
73 #include "hildon-defines.h"
74 #include "hildon-sound.h"
75 #include "hildon-banner.h"
76 #include "hildon-enum-types.h"
77 #include "hildon-note-private.h"
80 #define CONFIRMATION_SOUND_PATH \
81 "/usr/share/sounds/ui-confirmation_note.wav"
83 #define INFORMATION_SOUND_PATH \
84 "/usr/share/sounds/ui-information_note.wav"
86 #define _(String) dgettext("hildon-libs", String)
89 hildon_note_class_init (HildonNoteClass *class);
92 hildon_note_init (HildonNote *dialog);
95 hildon_note_rebuild (HildonNote *note);
98 hildon_note_finalize (GObject *obj_self);
101 hildon_note_realize (GtkWidget *widget);
104 hildon_note_set_property (GObject *object,
110 hildon_note_get_property (GObject *object,
116 sound_handling (GtkWidget *widget,
117 GdkEventExpose *event,
123 PROP_HILDON_NOTE_TYPE,
124 PROP_HILDON_NOTE_DESCRIPTION,
125 PROP_HILDON_NOTE_ICON,
126 PROP_HILDON_NOTE_PROGRESSBAR,
127 PROP_HILDON_NOTE_STOCK_ICON
130 static GtkDialogClass* parent_class;
134 hildon_note_set_property (GObject *object,
139 HildonNote *note = HILDON_NOTE (object);
140 HildonNotePrivate *priv;
143 priv = HILDON_NOTE_GET_PRIVATE (note);
148 case PROP_HILDON_NOTE_TYPE:
149 priv->note_n = g_value_get_enum (value);
150 hildon_note_rebuild (note);
153 case PROP_HILDON_NOTE_DESCRIPTION:
154 if (priv->original_description)
155 g_free (priv->original_description);
156 priv->original_description = g_value_dup_string (value);
158 gtk_label_set_text (GTK_LABEL (priv->label), priv->original_description);
159 /* FIXME Is the "original_description" used anywhere? */
163 case PROP_HILDON_NOTE_ICON:
167 priv->icon = g_value_dup_string (value);
170 case PROP_HILDON_NOTE_STOCK_ICON:
171 if (priv->stock_icon) {
172 g_free (priv->stock_icon);
174 priv->stock_icon = g_value_dup_string (value);
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_value_set_string (value, priv->icon);
227 case PROP_HILDON_NOTE_STOCK_ICON:
228 g_value_set_string (value, priv->stock_icon);
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 * Deprecated: Since 2.2
317 g_object_class_install_property (object_class,
318 PROP_HILDON_NOTE_ICON,
319 g_param_spec_string ("icon",
321 "The name of the icon that appears in the note dialog",
326 * HildonNote:stock-icon:
328 * Stock icon name for the note.
330 * Deprecated: Since 2.2
332 g_object_class_install_property (object_class,
333 PROP_HILDON_NOTE_STOCK_ICON,
334 g_param_spec_string ("stock-icon",
336 "The stock name of the icon that appears in the note dialog",
341 * HildonNote:progressbar:
343 * Progressbar for the note (if any).
345 g_object_class_install_property (object_class,
346 PROP_HILDON_NOTE_PROGRESSBAR,
347 g_param_spec_object ("progressbar",
348 "Progressbar widget",
349 "The progressbar that appears in the note dialog",
350 GTK_TYPE_PROGRESS_BAR,
355 hildon_note_init (HildonNote *dialog)
357 HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (dialog);
360 priv->label = gtk_label_new (NULL);
361 gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
364 priv->stock_icon = NULL;
366 /* Acquire real references to our internal children, since
367 they are not nessecarily packed into container in each
369 g_object_ref_sink (priv->label);
371 gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
372 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
374 /* We use special hint to turn the note into information notification. */
375 gtk_window_set_type_hint (GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_NOTIFICATION);
380 hildon_note_finalize (GObject *obj_self)
382 HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (obj_self);
385 /* FIXME Some of this stuff should be moved to dispose */
387 /* Free internal data */
389 g_object_unref (priv->label);
395 if (priv->stock_icon) {
396 g_free (priv->stock_icon);
397 priv->stock_icon = NULL;
400 if (priv->progressbar)
401 g_object_unref (priv->progressbar);
403 if (priv->original_description)
404 g_free (priv->original_description);
406 G_OBJECT_CLASS (parent_class)->finalize (obj_self);
411 hildon_note_realize (GtkWidget *widget)
415 const gchar *notification_type;
416 HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget);
419 /* Make widget->window accessible */
420 GTK_WIDGET_CLASS (parent_class)->realize (widget);
422 /* Border only, no titlebar */
423 gdk_window_set_decorations (widget->window, GDK_DECOR_BORDER);
425 /* Because ESD is synchronous, we wish to play sound after the
426 note is already on screen to avoid blocking its appearance */
427 if (priv->sound_signal_handler == 0)
428 priv->sound_signal_handler = g_signal_connect_after(widget,
429 "expose-event", G_CALLBACK (sound_handling), NULL);
431 /* Set the _HILDON_NOTIFICATION_TYPE property so Matchbox places the window correctly */
432 display = gdk_drawable_get_display (widget->window);
433 atom = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_NOTIFICATION_TYPE");
435 if (priv->note_n == HILDON_NOTE_TYPE_INFORMATION ||
436 priv->note_n == HILDON_NOTE_TYPE_INFORMATION_THEME) {
437 notification_type = "_HILDON_NOTIFICATION_TYPE_INFO";
439 notification_type = "_HILDON_NOTIFICATION_TYPE_CONFIRMATION";
442 XChangeProperty (GDK_WINDOW_XDISPLAY (widget->window), GDK_WINDOW_XID (widget->window),
443 atom, XA_STRING, 8, PropModeReplace, (guchar *) notification_type,
444 strlen (notification_type));
447 /* Helper function for removing a widget from it's container.
448 we own a separate reference to each object we try to unpack,
449 so extra referencing is not needed. */
451 unpack_widget (GtkWidget *widget)
453 g_assert (widget == NULL || GTK_IS_WIDGET (widget));
455 if (widget && widget->parent)
456 gtk_container_remove (GTK_CONTAINER (widget->parent), widget);
460 hildon_note_rebuild (HildonNote *note)
463 HildonNotePrivate *priv;
464 gboolean IsHorizontal = TRUE;
466 g_assert (HILDON_IS_NOTE (note));
468 priv = HILDON_NOTE_GET_PRIVATE (note);
471 dialog = GTK_DIALOG (note);
473 /* Reuse exiting content widgets for new layout */
474 unpack_widget (priv->label);
475 unpack_widget (priv->progressbar);
477 /* Destroy old layout and buttons */
479 gtk_widget_destroy (priv->box);
482 if (priv->okButton) {
483 gtk_widget_destroy (priv->okButton);
484 priv->okButton = NULL;
486 if (priv->cancelButton) {
487 gtk_widget_destroy (priv->cancelButton);
488 priv->cancelButton = NULL;
491 /* Add needed buttons and images for each note type */
492 switch (priv->note_n)
494 case HILDON_NOTE_TYPE_CONFIRMATION:
495 priv->okButton = gtk_dialog_add_button (dialog,
496 _("wdgt_bd_yes"), GTK_RESPONSE_OK);
497 priv->cancelButton = gtk_dialog_add_button (dialog,
498 _("wdgt_bd_no"), GTK_RESPONSE_CANCEL);
499 gtk_widget_show (priv->cancelButton);
500 gtk_widget_set_no_show_all (priv->cancelButton, FALSE);
503 case HILDON_NOTE_TYPE_PROGRESSBAR:
504 priv->cancelButton = gtk_dialog_add_button (dialog,
505 _("wdgt_bd_stop"), GTK_RESPONSE_CANCEL);
506 gtk_widget_show (priv->cancelButton);
507 gtk_widget_set_no_show_all (priv->cancelButton, FALSE);
508 IsHorizontal = FALSE;
511 case HILDON_NOTE_TYPE_CONFIRMATION_BUTTON:
512 case HILDON_NOTE_TYPE_INFORMATION_THEME:
513 case HILDON_NOTE_TYPE_INFORMATION:
519 /* Pack item with label horizontally */
520 priv->box = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
521 gtk_container_add (GTK_CONTAINER (dialog->vbox), priv->box);
523 gtk_box_pack_start (GTK_BOX (priv->box), priv->label, TRUE, TRUE, 0);
526 /* Pack item with label vertically */
527 priv->box = gtk_vbox_new (FALSE, HILDON_MARGIN_DOUBLE);
528 gtk_container_add (GTK_CONTAINER (dialog->vbox), priv->box);
529 gtk_box_pack_start (GTK_BOX (priv->box), priv->label, TRUE, TRUE, 0);
531 if (priv->progressbar)
532 gtk_box_pack_start (GTK_BOX (priv->box), priv->progressbar, FALSE, FALSE, 0);
535 gtk_widget_show_all (priv->box);
539 * hildon_note_new_confirmation_add_buttons:
540 * @parent: the parent window. The X window ID of the parent window
541 * has to be the same as the X window ID of the application. This is
542 * important so that the window manager could handle the windows
544 * In GTK the X window ID can be checked using
545 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
546 * @description: the message to confirm
547 * @Varargs: arguments pairs for new buttons(label and return value).
548 * Terminate the list with %NULL value.
550 * Create a new confirmation note with custom buttons. Confirmation
551 * note has a text and any number of buttons. It's important to note
552 * that even though the name of the function might suggest, the
553 * default ok/cancel buttons are not appended but you have to provide
554 * all of the buttons.
556 * FIXME: This doc seems to be wrong, the two buttons aren't added so
557 * it would only contain the "additional" buttons? However, changing
558 * this would break those applications that rely on current behaviour.
560 * Returns: A #GtkWidget pointer of the note
563 hildon_note_new_confirmation_add_buttons (GtkWindow *parent,
564 const gchar *description,
572 g_return_val_if_fail (description != NULL, NULL);
574 GtkWidget *conf_note =
575 g_object_new (HILDON_TYPE_NOTE,
576 "note-type", HILDON_NOTE_TYPE_CONFIRMATION_BUTTON,
577 "description", description,
581 gtk_window_set_transient_for (GTK_WINDOW (conf_note), parent);
583 /* Add the buttons from varargs */
584 va_start(args, description);
587 message = va_arg (args, char *);
592 value = va_arg (args, int);
594 button = gtk_dialog_add_button (GTK_DIALOG (conf_note), message, value);
595 /* maemo-gtk is going to set the "no-show-all" property all
596 cancel/close-like buttons to TRUE, so that they are not shown. On
597 the other hand, this confirmation note with custom buttons should
598 not obey this rule, so we need to make sure they are shown. */
599 gtk_widget_show (button);
600 gtk_widget_set_no_show_all (button, FALSE);
610 * hildon_note_new_confirmation:
611 * @parent: the parent window. The X window ID of the parent window
612 * has to be the same as the X window ID of the application. This is
613 * important so that the window manager could handle the windows
614 * correctly. In GTK the X window ID can be checked using
615 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
616 * @description: the message to confirm
618 * Create a new confirmation note. Confirmation note has a text (description)
619 * that you specify and two buttons.
621 * Returns: a #GtkWidget pointer of the note
624 hildon_note_new_confirmation (GtkWindow *parent,
625 const gchar *description)
627 GtkWidget *dialog = NULL;
629 g_return_val_if_fail (description != NULL, NULL);
631 dialog = g_object_new (HILDON_TYPE_NOTE,
633 HILDON_NOTE_TYPE_CONFIRMATION,
634 "description", description, NULL);
637 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
643 * hildon_note_new_confirmation_with_icon_name:
644 * @parent: the parent window. The X window ID of the parent window
645 * has to be the same as the X window ID of the application. This is
646 * important so that the window manager could handle the windows
647 * correctly. In GTK the X window ID can be checked using
648 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
649 * @description: the message to confirm
650 * @icon_name: icon to be displayed. If NULL, default icon is used.
652 * Create a new confirmation note. Confirmation note has a text (description)
653 * that you specify and two buttons.
655 * Deprecated: Since 2.2, icons are not shown in confirmation notes. Icons set
656 * with this function will be ignored. Use hildon_note_new_confirmation() instead.
658 * Returns: a #GtkWidget pointer of the note
661 hildon_note_new_confirmation_with_icon_name (GtkWindow *parent,
662 const gchar *description,
663 const gchar *icon_name)
665 return hildon_note_new_confirmation (parent, description);
669 * hildon_note_new_information:
670 * @parent: the parent window. The X window ID of the parent window
671 * has to be the same as the X window ID of the application. This is
672 * important so that the window manager could handle the windows
673 * correctly. In GTK the X window ID can be checked using
674 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
675 * @description: the message to confirm
677 * Create a new information note. Information note has a text (description)
678 * that you specify and an OK button.
680 * Returns: a #GtkWidget pointer of the note
683 hildon_note_new_information (GtkWindow *parent,
684 const gchar *description)
686 GtkWidget *dialog = NULL;
688 g_return_val_if_fail (description != NULL, NULL);
690 dialog = g_object_new (HILDON_TYPE_NOTE,
692 HILDON_NOTE_TYPE_INFORMATION_THEME,
693 "description", description, NULL);
696 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
702 * hildon_note_new_information_with_icon_name:
703 * @parent: the parent window. The X window ID of the parent window
704 * has to be the same as the X window ID of the application. This is
705 * important so that the window manager could handle the windows
706 * correctly. In GTK the X window ID can be checked using
707 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
708 * @description: the message to confirm
709 * @icon_name: icon to be displayed. If NULL, default icon is used.
711 * Create a new information note. Information note has text(description)
712 * that you specify, an OK button and an icon.
714 * Deprecated: Since 2.2, icons are not shown in confirmation notes. Icons set
715 * with this function will be ignored. Use hildon_note_new_information() instead.
717 * Returns: a #GtkWidget pointer of the note
720 hildon_note_new_information_with_icon_name (GtkWindow * parent,
721 const gchar *description,
722 const gchar *icon_name)
724 return hildon_note_new_information (parent, description);
727 /* FIXME This documentation string LIES! */
730 * hildon_note_new_cancel_with_progress_bar:
731 * @parent: the parent window. The X window ID of the parent window
732 * has to be the same as the X window ID of the application. This is
733 * important so that the window manager could handle the windows
734 * correctly. In GTK the X window ID can be checked using
735 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
736 * @description: the action to cancel
737 * @progressbar: a pointer to #GtkProgressBar to be filled with the
738 * progressbar assigned to this note. Use this to set the fraction of
739 * progressbar done. This parameter can be %NULL as well, in which
740 * case plain text cancel note appears.
742 * Create a new cancel note with a progress bar. Cancel note has
743 * text(description) that you specify, a Cancel button and a progress bar.
745 * Returns: a #GtkDialog. Use this to get rid of this note when you
749 hildon_note_new_cancel_with_progress_bar (GtkWindow *parent,
750 const gchar *description,
751 GtkProgressBar *progressbar)
753 GtkWidget *dialog = NULL;
755 g_return_val_if_fail (description != NULL, NULL);
757 dialog = g_object_new (HILDON_TYPE_NOTE,
759 HILDON_NOTE_TYPE_PROGRESSBAR,
760 "description", description,
765 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
772 * hildon_note_set_button_text:
773 * @note: a #HildonNote
774 * @text: sets the button text and if there is two buttons in dialog,
775 * the button texts will be <text>, "Cancel".
777 * Sets the button text to be used by the hildon_note widget.
780 hildon_note_set_button_text (HildonNote *note,
783 HildonNotePrivate *priv;
785 g_return_if_fail (HILDON_IS_NOTE (note));
787 priv = HILDON_NOTE_GET_PRIVATE (HILDON_NOTE (note));
790 if (priv->okButton) {
791 gtk_button_set_label (GTK_BUTTON (priv->okButton), text);
792 gtk_button_set_label (GTK_BUTTON (priv->cancelButton),
795 gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text);
800 * hildon_note_set_button_texts:
801 * @note: a #HildonNote
802 * @text_ok: the new text of the default OK button
803 * @text_cancel: the new text of the default cancel button
805 * Sets the button texts to be used by this hildon_note widget.
808 hildon_note_set_button_texts (HildonNote *note,
809 const gchar *text_ok,
810 const gchar *text_cancel)
812 HildonNotePrivate *priv;
814 g_return_if_fail (HILDON_IS_NOTE (note));
816 priv = HILDON_NOTE_GET_PRIVATE (HILDON_NOTE (note));
819 if (priv->okButton) {
820 gtk_button_set_label (GTK_BUTTON (priv->okButton), text_ok);
821 gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text_cancel);
823 gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text_cancel);
827 /* We play a system sound when the note comes visible */
829 sound_handling (GtkWidget *widget,
830 GdkEventExpose *event,
833 HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget);
836 g_signal_handler_disconnect (widget, priv->sound_signal_handler);
838 priv->sound_signal_handler = 0;
840 switch (priv->note_n)
842 case HILDON_NOTE_TYPE_INFORMATION:
843 case HILDON_NOTE_TYPE_INFORMATION_THEME:
844 hildon_play_system_sound (INFORMATION_SOUND_PATH);
847 case HILDON_NOTE_TYPE_CONFIRMATION:
848 case HILDON_NOTE_TYPE_CONFIRMATION_BUTTON:
849 hildon_play_system_sound (CONFIRMATION_SOUND_PATH);