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 and an OK button to be
31 * pressed. Additional features such as progress bars or animation can
35 * <title>HildonNote example</title>
38 * hildon_note_new_confirmation (window, "Confirmation message...");
40 * i = gtk_dialog_run (GTK_DIALOG (note));
41 * gtk_widget_destroy (GTK_WIDGET (note));
43 * if (i == GTK_RESPONSE_OK)
44 * gtk_infoprint (window, "User pressed 'OK' button'");
46 * gtk_infoprint (window, "User pressed 'Cancel' button" );
55 #include "hildon-note.h"
56 #include <gtk/gtklabel.h>
57 #include <gtk/gtkimage.h>
58 #include <gtk/gtkhbox.h>
59 #include <gtk/gtkalignment.h>
60 #include <gtk/gtkvbox.h>
61 #include <gtk/gtkbutton.h>
63 #include "hildon-defines.h"
64 #include "hildon-sound.h"
65 #include "hildon-banner.h"
66 #include "hildon-enum-types.h"
69 #include "hildon-note-private.h"
71 #define CONFIRMATION_SOUND_PATH \
72 "/usr/share/sounds/ui-confirmation_note.wav"
74 #define INFORMATION_SOUND_PATH \
75 "/usr/share/sounds/ui-information_note.wav"
77 #define HILDON_NOTE_CONFIRMATION_ICON \
80 #define HILDON_NOTE_INFORMATION_ICON \
83 #define _(String) dgettext("hildon-libs", String)
86 hildon_note_class_init (HildonNoteClass *class);
89 hildon_note_init (HildonNote *dialog);
92 hildon_note_rebuild (HildonNote *note);
95 hildon_note_finalize (GObject *obj_self);
98 hildon_note_realize (GtkWidget *widget);
101 hildon_note_set_property (GObject *object,
107 hildon_note_get_property (GObject *object,
113 sound_handling (GtkWidget *widget,
114 GdkEventExpose *event,
120 PROP_HILDON_NOTE_TYPE,
121 PROP_HILDON_NOTE_DESCRIPTION,
122 PROP_HILDON_NOTE_ICON,
123 PROP_HILDON_NOTE_PROGRESSBAR,
124 PROP_HILDON_NOTE_STOCK_ICON
127 static GtkDialogClass* parent_class;
130 hildon_note_set_property (GObject *object,
135 HildonNote *note = HILDON_NOTE (object);
136 HildonNotePrivate *priv;
139 priv = HILDON_NOTE_GET_PRIVATE (note);
144 case PROP_HILDON_NOTE_TYPE:
145 priv->note_n = g_value_get_enum (value);
146 hildon_note_rebuild (note);
149 case PROP_HILDON_NOTE_DESCRIPTION:
150 if (priv->original_description)
151 g_free (priv->original_description);
152 priv->original_description = g_value_dup_string (value);
154 gtk_label_set_text (GTK_LABEL (priv->label), priv->original_description);
155 /* FIXME Is the "original_description" used anywhere? */
159 case PROP_HILDON_NOTE_ICON:
160 gtk_image_set_from_icon_name (GTK_IMAGE (priv->icon),
161 g_value_get_string(value), HILDON_ICON_SIZE_BIG_NOTE);
164 case PROP_HILDON_NOTE_STOCK_ICON:
165 gtk_image_set_from_stock (GTK_IMAGE (priv->icon),
166 g_value_get_string (value), HILDON_ICON_SIZE_BIG_NOTE);
169 case PROP_HILDON_NOTE_PROGRESSBAR:
170 widget = g_value_get_object (value);
171 if (widget != priv->progressbar)
173 if (priv->progressbar)
174 g_object_unref (priv->progressbar);
176 priv->progressbar = widget;
180 g_object_ref (widget);
181 gtk_object_sink (GTK_OBJECT (widget));
184 hildon_note_rebuild (note);
189 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
195 hildon_note_get_property (GObject *object,
200 HildonNote *note = HILDON_NOTE (object);
201 HildonNotePrivate *priv;
203 priv = HILDON_NOTE_GET_PRIVATE (note);
207 case PROP_HILDON_NOTE_TYPE:
208 g_value_set_enum (value, priv->note_n);
211 case PROP_HILDON_NOTE_DESCRIPTION:
212 g_value_set_string (value, priv->original_description);
215 case PROP_HILDON_NOTE_ICON:
216 g_object_get_property (G_OBJECT (priv->icon), "icon-name", value);
219 case PROP_HILDON_NOTE_STOCK_ICON:
220 g_object_get_property (G_OBJECT (priv->icon), "stock", value);
223 case PROP_HILDON_NOTE_PROGRESSBAR:
224 g_value_set_object (value, priv->progressbar);
228 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
234 * hildon_note_get_type:
236 * Returns GType for HildonNote.
238 * Returns: HildonNote type
241 hildon_note_get_type (void)
243 static GType dialog_type = 0;
246 static const GTypeInfo dialog_info = {
247 sizeof(HildonNoteClass),
248 NULL, /* base_init */
249 NULL, /* base_finalize */
250 (GClassInitFunc) hildon_note_class_init,
251 NULL, /* class_finalize */
252 NULL, /* class_data */
255 (GInstanceInitFunc) hildon_note_init
257 dialog_type = g_type_register_static (GTK_TYPE_DIALOG,
265 hildon_note_class_init (HildonNoteClass *class)
267 GObjectClass *object_class = G_OBJECT_CLASS (class);
268 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
270 /* set the global parent_class */
271 parent_class = g_type_class_peek_parent (class);
273 g_type_class_add_private (class, sizeof (HildonNotePrivate));
275 object_class->finalize = hildon_note_finalize;
276 object_class->set_property = hildon_note_set_property;
277 object_class->get_property = hildon_note_get_property;
278 widget_class->realize = hildon_note_realize;
280 g_object_class_install_property (object_class,
281 PROP_HILDON_NOTE_TYPE,
282 g_param_spec_enum ("note-type",
284 "The type of the note dialog",
285 hildon_note_type_get_type (),
286 HILDON_NOTE_TYPE_CONFIRMATION,
287 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
290 * HildonNote:description:
292 * Description for the note.
294 g_object_class_install_property (object_class,
295 PROP_HILDON_NOTE_DESCRIPTION,
296 g_param_spec_string ("description",
298 "The text that appears in the note dialog",
307 g_object_class_install_property (object_class,
308 PROP_HILDON_NOTE_ICON,
309 g_param_spec_string ("icon",
311 "The name of the icon that appears in the note dialog",
316 * HildonNote:stock-icon:
318 * Stock icon name for the note.
320 g_object_class_install_property (object_class,
321 PROP_HILDON_NOTE_STOCK_ICON,
322 g_param_spec_string ("stock-icon",
324 "The stock name of the icon that appears in the note dialog",
329 * HildonNote:progressbar:
331 * Progressbar for the note (if any).
333 g_object_class_install_property (object_class,
334 PROP_HILDON_NOTE_PROGRESSBAR,
335 g_param_spec_object ("progressbar",
336 "Progressbar widget",
337 "The progressbar that appears in the note dialog",
338 GTK_TYPE_PROGRESS_BAR,
343 hildon_note_init (HildonNote *dialog)
345 HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (dialog);
348 priv->label = gtk_label_new (NULL);
349 gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
351 priv->icon = gtk_image_new ();
353 /* Acquire real references to our internal children, since
354 they are not nessecarily packed into container in each
356 g_object_ref_sink (priv->label);
357 g_object_ref_sink (priv->icon);
359 gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
360 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
365 hildon_note_finalize (GObject *obj_self)
367 HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (obj_self);
370 /* FIXME Some of this stuff should be moved to dispose */
372 /* Free internal data */
374 g_object_unref (priv->label);
377 g_object_unref (priv->icon);
379 if (priv->progressbar)
380 g_object_unref (priv->progressbar);
382 if (priv->original_description)
383 g_free (priv->original_description);
385 G_OBJECT_CLASS (parent_class)->finalize (obj_self);
389 hildon_note_realize (GtkWidget *widget)
391 HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget);
394 /* Make widget->window accessible */
395 GTK_WIDGET_CLASS (parent_class)->realize (widget);
397 /* Border only, no titlebar */
398 gdk_window_set_decorations (widget->window, GDK_DECOR_BORDER);
400 /* Because ESD is synchronous, we wish to play sound after the
401 note is already on screen to avoid blocking its appearance */
402 if (priv->sound_signal_handler == 0)
403 priv->sound_signal_handler = g_signal_connect_after(widget,
404 "expose-event", G_CALLBACK (sound_handling), NULL);
407 /* Helper function for removing a widget from it's container.
408 we own a separate reference to each object we try to unpack,
409 so extra referencing is not needed. */
411 unpack_widget (GtkWidget *widget)
413 g_assert (widget == NULL || GTK_IS_WIDGET (widget));
415 if (widget && widget->parent)
416 gtk_container_remove (GTK_CONTAINER (widget->parent), widget);
420 hildon_note_rebuild (HildonNote *note)
423 HildonNotePrivate *priv;
424 gboolean IsHorizontal = TRUE;
426 g_assert (HILDON_IS_NOTE (note));
428 priv = HILDON_NOTE_GET_PRIVATE (note);
431 dialog = GTK_DIALOG (note);
433 /* Reuse exiting content widgets for new layout */
434 unpack_widget (priv->label);
435 unpack_widget (priv->icon);
436 unpack_widget (priv->progressbar);
438 /* Destroy old layout and buttons */
440 gtk_widget_destroy (priv->box);
443 if (priv->okButton) {
444 gtk_widget_destroy (priv->okButton);
445 priv->okButton = NULL;
447 if (priv->cancelButton) {
448 gtk_widget_destroy (priv->cancelButton);
449 priv->cancelButton = NULL;
452 /* Add needed buttons and images for each note type */
453 switch (priv->note_n)
455 case HILDON_NOTE_TYPE_CONFIRMATION:
456 priv->okButton = gtk_dialog_add_button (dialog,
457 _("ecdg_bd_confirmation_note_ok"), GTK_RESPONSE_OK);
458 priv->cancelButton = gtk_dialog_add_button (dialog,
459 _("ecdg_bd_confirmation_note_cancel"), GTK_RESPONSE_CANCEL);
462 case HILDON_NOTE_TYPE_CONFIRMATION_BUTTON:
463 gtk_image_set_from_icon_name (GTK_IMAGE (priv->icon),
464 HILDON_NOTE_CONFIRMATION_ICON,
465 HILDON_ICON_SIZE_BIG_NOTE);
468 case HILDON_NOTE_TYPE_INFORMATION_THEME:
469 case HILDON_NOTE_TYPE_INFORMATION:
470 /* Add clickable OK button (cancel really,
471 but doesn't matter since this is info) */
472 priv->cancelButton = gtk_dialog_add_button (dialog,
473 _("ecdg_bd_information_note_ok"), GTK_RESPONSE_CANCEL);
474 gtk_image_set_from_icon_name (GTK_IMAGE (priv->icon),
475 HILDON_NOTE_INFORMATION_ICON,
476 HILDON_ICON_SIZE_BIG_NOTE);
479 case HILDON_NOTE_TYPE_PROGRESSBAR:
480 priv->cancelButton = gtk_dialog_add_button (dialog,
481 _("ecdg_bd_cancel_note_cancel"), GTK_RESPONSE_CANCEL);
482 IsHorizontal = FALSE;
490 /* Pack item with label horizontally */
491 priv->box = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
492 gtk_container_add (GTK_CONTAINER (dialog->vbox), priv->box);
495 GtkWidget *alignment = gtk_alignment_new (0, 0, 0, 0);
497 gtk_box_pack_start (GTK_BOX (priv->box), alignment, FALSE, FALSE, 0);
498 gtk_container_add (GTK_CONTAINER (alignment), priv->icon);
500 gtk_box_pack_start (GTK_BOX (priv->box), priv->label, TRUE, TRUE, 0);
503 /* Pack item with label vertically */
504 priv->box = gtk_vbox_new (FALSE, HILDON_MARGIN_DOUBLE);
505 gtk_container_add (GTK_CONTAINER (dialog->vbox), priv->box);
506 gtk_box_pack_start (GTK_BOX (priv->box), priv->label, TRUE, TRUE, 0);
508 if (priv->progressbar)
509 gtk_box_pack_start (GTK_BOX (priv->box), priv->progressbar, FALSE, FALSE, 0);
512 gtk_widget_show_all (priv->box);
516 * hildon_note_new_confirmation_add_buttons:
517 * @parent: the parent window. The X window ID of the parent window
518 * has to be the same as the X window ID of the application. This is
519 * important so that the window manager could handle the windows
521 * In GTK the X window ID can be checked using
522 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
523 * @description: the message to confirm
524 * @Varargs: arguments pairs for new buttons(label and return value).
525 * Terminate the list with %NULL value.
527 * Create a new confirmation note with custom buttons. Confirmation
528 * note has a text and any number of buttons. It's important to note
529 * that even though the name of the function might suggest, the
530 * default ok/cancel buttons are not appended but you have to provide
531 * all of the buttons.
533 * FIXME: This doc seems to be wrong, the two buttons aren't added so
534 * it would only contain the "additional" buttons? However, changing
535 * this would break those applications that rely on current behaviour.
537 * Returns: A #GtkWidget pointer of the note
540 hildon_note_new_confirmation_add_buttons (GtkWindow *parent,
541 const gchar *description,
548 g_return_val_if_fail (description != NULL, NULL);
550 GtkWidget *conf_note =
551 g_object_new (HILDON_TYPE_NOTE,
552 "note-type", HILDON_NOTE_TYPE_CONFIRMATION_BUTTON,
553 "description", description,
554 "icon", HILDON_NOTE_CONFIRMATION_ICON,
558 gtk_window_set_transient_for (GTK_WINDOW (conf_note), parent);
560 /* Add the buttons from varargs */
561 va_start(args, description);
564 message = va_arg (args, char *);
569 value = va_arg (args, int);
571 gtk_dialog_add_button (GTK_DIALOG (conf_note), message, value);
581 * hildon_note_new_confirmation:
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
589 * Create a new confirmation note. Confirmation note has text (description)
590 * that you specify, two buttons and a default confirmation stock icon.
592 * Returns: a #GtkWidget pointer of the note
595 hildon_note_new_confirmation (GtkWindow *parent,
596 const gchar *description)
598 return hildon_note_new_confirmation_with_icon_name
599 (parent, description, HILDON_NOTE_CONFIRMATION_ICON);
603 * hildon_note_new_confirmation_with_icon_name:
604 * @parent: the parent window. The X window ID of the parent window
605 * has to be the same as the X window ID of the application. This is
606 * important so that the window manager could handle the windows
607 * correctly. In GTK the X window ID can be checked using
608 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
609 * @description: the message to confirm
610 * @icon_name: icon to be displayed. If NULL, default icon is used.
612 * Create a new confirmation note. Confirmation note has text(description)
613 * that you specify, two buttons and an icon.
615 * Returns: a #GtkWidget pointer of the note
618 hildon_note_new_confirmation_with_icon_name (GtkWindow *parent,
619 const gchar *description,
620 const gchar *icon_name)
622 GtkWidget *dialog = NULL;
624 g_return_val_if_fail (description != NULL, NULL);
626 dialog = g_object_new (HILDON_TYPE_NOTE,
628 HILDON_NOTE_TYPE_CONFIRMATION,
629 "description", description, "icon",
633 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
639 * hildon_note_new_information:
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
647 * Create a new information note. Information note has a text(description)
648 * that you specify, an OK button and an icon.
650 * Returns: a #GtkWidget pointer of the note
653 hildon_note_new_information (GtkWindow *parent,
654 const gchar *description)
656 return hildon_note_new_information_with_icon_name
657 (parent, description, HILDON_NOTE_INFORMATION_ICON);
661 * hildon_note_new_information_with_icon_name:
662 * @parent: the parent window. The X window ID of the parent window
663 * has to be the same as the X window ID of the application. This is
664 * important so that the window manager could handle the windows
665 * correctly. In GTK the X window ID can be checked using
666 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
667 * @description: the message to confirm
668 * @icon_name: icon to be displayed. If NULL, default icon is used.
670 * Create a new information note. Information note has text(description)
671 * that you specify, an OK button and an icon.
673 * Returns: a #GtkWidget pointer of the note
676 hildon_note_new_information_with_icon_name (GtkWindow * parent,
677 const gchar *description,
678 const gchar *icon_name)
680 GtkWidget *dialog = NULL;
682 g_return_val_if_fail (description != NULL, NULL);
683 g_return_val_if_fail (icon_name != NULL, NULL);
685 dialog = g_object_new (HILDON_TYPE_NOTE,
687 HILDON_NOTE_TYPE_INFORMATION_THEME,
688 "description", description,
689 "icon", icon_name, NULL);
692 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
697 /* FIXME This documentation string LIES! */
700 * hildon_note_new_cancel_with_progress_bar:
701 * @parent: the parent window. The X window ID of the parent window
702 * has to be the same as the X window ID of the application. This is
703 * important so that the window manager could handle the windows
704 * correctly. In GTK the X window ID can be checked using
705 * GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
706 * @description: the action to cancel
707 * @progressbar: a pointer to #GtkProgressBar to be filled with the
708 * progressbar assigned to this note. Use this to set the fraction of
709 * progressbar done. This parameter can be %NULL as well, in which
710 * case plain text cancel note appears.
712 * Create a new cancel note with a progress bar. Cancel note has
713 * text(description) that you specify, a Cancel button and a progress bar.
715 * Returns: a #GtkDialog. Use this to get rid of this note when you
719 hildon_note_new_cancel_with_progress_bar (GtkWindow *parent,
720 const gchar *description,
721 GtkProgressBar *progressbar)
723 GtkWidget *dialog = NULL;
725 g_return_val_if_fail (description != NULL, NULL);
727 dialog = g_object_new (HILDON_TYPE_NOTE,
729 HILDON_NOTE_TYPE_PROGRESSBAR,
730 "description", description,
735 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
742 * hildon_note_set_button_text:
743 * @note: a #HildonNote
744 * @text: sets the button text and if there is two buttons in dialog,
745 * the button texts will be <text>, "Cancel".
747 * Sets the button text to be used by the hildon_note widget.
750 hildon_note_set_button_text (HildonNote *note,
753 HildonNotePrivate *priv;
755 g_return_if_fail (HILDON_IS_NOTE (note));
757 priv = HILDON_NOTE_GET_PRIVATE (HILDON_NOTE (note));
760 if (priv->okButton) {
761 gtk_button_set_label (GTK_BUTTON (priv->okButton), text);
762 gtk_button_set_label (GTK_BUTTON (priv->cancelButton),
763 _("ecdg_bd_confirmation_note_cancel"));
765 gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text);
770 * hildon_note_set_button_texts:
771 * @note: a #HildonNote
772 * @text_ok: the new text of the default OK button
773 * @text_cancel: the new text of the default cancel button
775 * Sets the button texts to be used by this hildon_note widget.
778 hildon_note_set_button_texts (HildonNote *note,
779 const gchar *text_ok,
780 const gchar *text_cancel)
782 HildonNotePrivate *priv;
784 g_return_if_fail (HILDON_IS_NOTE (note));
786 priv = HILDON_NOTE_GET_PRIVATE (HILDON_NOTE (note));
789 if (priv->okButton) {
790 gtk_button_set_label (GTK_BUTTON (priv->okButton), text_ok);
791 gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text_cancel);
793 gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text_cancel);
797 /* We play a system sound when the note comes visible */
799 sound_handling (GtkWidget *widget,
800 GdkEventExpose *event,
803 HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget);
806 g_signal_handler_disconnect (widget, priv->sound_signal_handler);
808 priv->sound_signal_handler = 0;
810 switch (priv->note_n)
812 case HILDON_NOTE_TYPE_INFORMATION:
813 case HILDON_NOTE_TYPE_INFORMATION_THEME:
814 hildon_play_system_sound (INFORMATION_SOUND_PATH);
817 case HILDON_NOTE_TYPE_CONFIRMATION:
818 case HILDON_NOTE_TYPE_CONFIRMATION_BUTTON:
819 hildon_play_system_sound (CONFIRMATION_SOUND_PATH);