Documentation improvements for HildonNote
[hildon] / hildon / hildon-note.c
1 /*
2  * This file is a part of hildon
3  *
4  * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved.
5  *
6  * Contact: Rodrigo Novo <rodrigo.novo@nokia.com>
7  *
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.
12  *
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.
17  *
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
21  * 02110-1301 USA
22  *
23  */
24
25 /**
26  * SECTION:hildon-note
27  * @short_description: A widget to ask confirmation from the user.
28  *
29  * #HildonNote is a convenient way to prompt users for a small amount of
30  * input. A simple note contains an information text and, in case of
31  * confirmation notes, it shows buttons to confirm or cancel. It can also
32  * include a #GtkProgressBar.
33  *
34  * This widget provides convenient functions to create either
35  * information notes, confirmation notes or cancel notes, which are
36  * useful to show the progress of a requested task allowing the user
37  * to cancel it.
38  *
39  * To create information notes you can use
40  * hildon_note_new_information(). hildon_note_new_confirmation()
41  * creates a note with a text and two buttons to confirm or
42  * cancel. Note that it is possible to create a confirmation note with
43  * customized buttons by using
44  * hildon_note_new_confirmation_add_buttons().
45  *
46  * To create a note with a text, a progress bar and cancel button,
47  * hildon_note_new_cancel_with_progress_bar() can be used.
48  *
49  * <example>
50  * <title>HildonNote example</title>
51  * <programlisting>
52  * <!-- -->
53  * gboolean
54  * show_confirmation_note (GtkWindow *parent)
55  * {
56  *   gint retcode;
57  *   GtkWidget *note;
58  *   note = hildon_note_new_confirmation (parent, "Confirmation message...");
59  * <!-- -->
60  *   retcode = gtk_dialog_run (GTK_DIALOG (note));
61  *   gtk_widget_destroy (note);
62  * <!-- -->
63  *   if (retcode == GTK_RESPONSE_OK) {
64  *        g_debug ("User pressed 'OK' button'");
65  *        return TRUE;
66  *   } else {
67  *        g_debug ("User pressed 'Cancel' button");
68  *        return FALSE;
69  *   }
70  * }
71  * </programlisting>
72  * </example>
73  */
74
75 #ifdef                                          HAVE_CONFIG_H
76 #include                                        <config.h>
77 #endif
78
79 #include                                        <stdio.h>
80 #include                                        <string.h>
81 #include                                        <libintl.h>
82 #include                                        <X11/X.h>
83 #include                                        <X11/Xatom.h>
84 #include                                        <gdk/gdkx.h>
85
86 #undef HILDON_DISABLE_DEPRECATED
87
88 #include                                        "hildon-note.h"
89 #include                                        "hildon-defines.h"
90 #include                                        "hildon-sound.h"
91 #include                                        "hildon-banner.h" 
92 #include                                        "hildon-enum-types.h"
93 #include                                        "hildon-note-private.h"
94
95 #define                                         HILDON_INFORMATION_NOTE_MIN_HEIGHT 140
96
97 #define                                         HILDON_INFORMATION_NOTE_MARGIN 100
98
99 #define                                         CONFIRMATION_SOUND_PATH \
100                                                 "/usr/share/sounds/ui-confirmation_note.wav"
101
102 #define                                         INFORMATION_SOUND_PATH \
103                                                 "/usr/share/sounds/ui-information_note.wav"
104
105 #define                                         _(String) dgettext("hildon-libs", String)
106
107 static void 
108 hildon_note_class_init                          (HildonNoteClass *class);
109
110 static void
111 hildon_note_init                                (HildonNote *dialog);
112
113 static void 
114 hildon_note_rebuild                             (HildonNote *note);
115
116 static void
117 hildon_note_rename                              (HildonNote *note);
118
119 static void
120 hildon_note_finalize                            (GObject *obj_self);
121
122 static void
123 hildon_note_realize                             (GtkWidget *widget);
124
125 static void
126 hildon_note_unrealize                           (GtkWidget *widget);
127
128 static void
129 label_size_request                              (GtkWidget      *label,
130                                                  GtkRequisition *req,
131                                                  GtkWidget      *note);
132
133 static void 
134 hildon_note_set_property                        (GObject *object,
135                                                  guint prop_id,
136                                                  const GValue *value,
137                                                  GParamSpec *pspec);
138
139 static void
140 hildon_note_get_property                        (GObject *object,
141                                                  guint prop_id,
142                                                  GValue *value, 
143                                                  GParamSpec *pspec);
144
145 static void
146 on_show_cb                                      (GtkWidget *widget,
147                                                  gpointer data);
148 static gboolean
149 sound_handling                                  (gpointer data);
150
151 static void
152 unpack_widget                                   (GtkWidget *widget);
153
154 enum 
155 {
156     PROP_0,
157     PROP_HILDON_NOTE_TYPE,
158     PROP_HILDON_NOTE_DESCRIPTION,
159     PROP_HILDON_NOTE_ICON,
160     PROP_HILDON_NOTE_PROGRESSBAR,
161     PROP_HILDON_NOTE_STOCK_ICON
162 };
163
164 static GtkDialogClass*                          parent_class;
165
166 static gboolean
167 event_box_press_event                           (GtkEventBox    *event_box,
168                                                  GdkEventButton *event,
169                                                  GtkDialog      *note)
170 {
171     HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (note);
172
173     if (priv->note_n == HILDON_NOTE_TYPE_INFORMATION ||
174         priv->note_n == HILDON_NOTE_TYPE_INFORMATION_THEME) {
175             gtk_dialog_response (note, GTK_RESPONSE_DELETE_EVENT);
176             return TRUE;
177     } else {
178             return FALSE;
179     }
180 }
181
182 static void
183 hildon_note_set_property                        (GObject *object,
184                                                  guint prop_id,
185                                                  const GValue *value, 
186                                                  GParamSpec * pspec)
187 {
188     HildonNote *note = HILDON_NOTE (object);
189     HildonNotePrivate *priv;
190     GtkWidget *widget;
191
192     priv = HILDON_NOTE_GET_PRIVATE (note);
193     g_assert (priv);
194
195     switch (prop_id) {
196
197         case PROP_HILDON_NOTE_TYPE:
198             priv->note_n = g_value_get_enum (value);
199             hildon_note_rename (note);
200             hildon_note_rebuild (note);
201             break;
202
203         case PROP_HILDON_NOTE_DESCRIPTION:
204             if (priv->original_description) 
205                     g_free (priv->original_description);
206             priv->original_description = g_value_dup_string (value);
207
208             gtk_label_set_text (GTK_LABEL (priv->label), priv->original_description);
209             /* FIXME Is the "original_description" used anywhere? */
210             
211             break;
212
213         case PROP_HILDON_NOTE_ICON:
214             if (priv->icon) {
215               g_free (priv->icon);
216             }
217             priv->icon = g_value_dup_string (value);
218             break;
219
220         case PROP_HILDON_NOTE_STOCK_ICON:
221             if (priv->stock_icon) {
222               g_free (priv->stock_icon);
223             }
224             priv->stock_icon = g_value_dup_string (value);
225             break;
226
227         case PROP_HILDON_NOTE_PROGRESSBAR:
228             widget = g_value_get_object (value);
229             if (widget != priv->progressbar)
230             {
231                 if (priv->progressbar)
232                     g_object_unref (priv->progressbar);
233
234                 priv->progressbar = widget;
235
236                 if (widget)
237                 {
238                     g_object_ref (widget);
239                     gtk_object_sink (GTK_OBJECT (widget));
240                 }
241
242                 hildon_note_rebuild (note);
243             }
244             break;
245
246         default:
247             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
248             break;
249     }
250 }
251
252 static void
253 hildon_note_get_property                        (GObject *object,
254                                                  guint prop_id, 
255                                                  GValue *value, 
256                                                  GParamSpec *pspec)
257 {
258     HildonNote *note = HILDON_NOTE (object);
259     HildonNotePrivate *priv;
260
261     priv = HILDON_NOTE_GET_PRIVATE (note);
262
263     switch (prop_id) {
264
265         case PROP_HILDON_NOTE_TYPE:
266             g_value_set_enum (value, priv->note_n);
267             break;
268
269         case PROP_HILDON_NOTE_DESCRIPTION:
270             g_value_set_string (value, priv->original_description);
271             break;
272
273         case PROP_HILDON_NOTE_ICON:
274             g_value_set_string (value, priv->icon);
275             break;
276
277         case PROP_HILDON_NOTE_STOCK_ICON:
278             g_value_set_string (value, priv->stock_icon);
279             break;
280
281         case PROP_HILDON_NOTE_PROGRESSBAR:
282             g_value_set_object (value, priv->progressbar);
283             break;
284
285         default:
286             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
287             break;
288     }
289 }
290
291 /**
292  * hildon_note_get_type:
293  *
294  * Returns GType for HildonNote.
295  *
296  * Returns: HildonNote type
297  */
298 GType G_GNUC_CONST
299 hildon_note_get_type                            (void)
300 {
301     static GType dialog_type = 0;
302
303     if (! dialog_type) {
304         static const GTypeInfo dialog_info = {
305             sizeof(HildonNoteClass),
306             NULL,       /* base_init */
307             NULL,       /* base_finalize */
308             (GClassInitFunc) hildon_note_class_init,
309             NULL,       /* class_finalize */
310             NULL,       /* class_data */
311             sizeof(HildonNote),
312             0,  /* n_preallocs */
313             (GInstanceInitFunc) hildon_note_init
314         };
315         dialog_type = g_type_register_static (GTK_TYPE_DIALOG,
316                 "HildonNote",
317                 &dialog_info, 0);
318     }
319     return dialog_type;
320 }
321
322 static void 
323 hildon_note_class_init                          (HildonNoteClass *class)
324 {
325     GObjectClass *object_class = G_OBJECT_CLASS (class);
326     GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
327
328     /* set the global parent_class */
329     parent_class = g_type_class_peek_parent (class);
330
331     g_type_class_add_private (class, sizeof (HildonNotePrivate));
332
333     object_class->finalize      = hildon_note_finalize;
334     object_class->set_property  = hildon_note_set_property;
335     object_class->get_property  = hildon_note_get_property;
336     widget_class->realize       = hildon_note_realize;
337     widget_class->unrealize     = hildon_note_unrealize;
338
339     /**
340      * HildonNote:type:
341      *
342      * The type of the #HildonNote, defining its contents, behavior, and
343      * theming.
344      */
345     g_object_class_install_property (object_class,
346             PROP_HILDON_NOTE_TYPE,
347             g_param_spec_enum ("note-type",
348                 "note type",
349                 "The type of the note dialog",
350                 hildon_note_type_get_type (),
351                 HILDON_NOTE_TYPE_CONFIRMATION,
352                 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
353
354     /**
355      * HildonNote:description:
356      *
357      * The text that appears in the #HildonNote.
358      */
359     g_object_class_install_property (object_class,
360             PROP_HILDON_NOTE_DESCRIPTION,
361             g_param_spec_string ("description",
362                 "note description",
363                 "The text that appears in the note dialog",
364                 "",
365                 G_PARAM_READWRITE));
366
367     /**
368      * HildonNote:icon:
369      *
370      * Icon for the note.
371      *
372      * Deprecated: Since 2.2
373      */
374     g_object_class_install_property (object_class,
375             PROP_HILDON_NOTE_ICON,
376             g_param_spec_string ("icon",
377                 "note icon",
378                 "The name of the icon that appears in the note dialog",
379                 "",
380                 G_PARAM_READWRITE));
381
382     /**
383      * HildonNote:stock-icon:
384      *
385      * Stock icon name for the note.
386      *
387      * Deprecated: Since 2.2
388      */
389     g_object_class_install_property (object_class,
390             PROP_HILDON_NOTE_STOCK_ICON,
391             g_param_spec_string ("stock-icon",
392                 "Stock note icon",
393                 "The stock name of the icon that appears in the note dialog",
394                 "",
395                 G_PARAM_READWRITE));
396
397     /**
398      * HildonNote:progressbar:
399      *
400      * If set, a #GtkProgressBar visible in the note.
401      */
402     g_object_class_install_property (object_class,
403             PROP_HILDON_NOTE_PROGRESSBAR,
404             g_param_spec_object ("progressbar",
405                 "Progressbar widget",
406                 "The progressbar that appears in the note dialog",
407                 GTK_TYPE_PROGRESS_BAR,
408                 G_PARAM_READWRITE));
409 }
410
411 static void 
412 hildon_note_init                                (HildonNote *dialog)
413 {
414     HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (dialog);
415     g_assert (priv);
416
417     priv->label = gtk_label_new (NULL);
418     gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
419     gtk_label_set_justify (GTK_LABEL (priv->label), GTK_JUSTIFY_LEFT);
420
421     priv->event_box = gtk_event_box_new ();
422     priv->icon = NULL;
423     priv->stock_icon = NULL;
424     priv->idle_handler = 0;
425
426     gtk_event_box_set_visible_window (GTK_EVENT_BOX (priv->event_box), FALSE);
427     gtk_event_box_set_above_child (GTK_EVENT_BOX (priv->event_box), TRUE);
428     g_signal_connect (priv->event_box, "button-press-event",
429                       G_CALLBACK (event_box_press_event), dialog);
430
431     /* Because ESD is synchronous, we wish to play sound after the
432        note is already on screen to avoid blocking its appearance */
433     g_signal_connect (GTK_WIDGET (dialog), "show",
434                       G_CALLBACK (on_show_cb), NULL);
435
436     /* Acquire real references to our internal children, since
437        they are not nessecarily packed into container in each
438        layout */
439     g_object_ref_sink (priv->event_box);
440     g_object_ref_sink (priv->label);
441
442     gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
443     gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
444
445     /* We use special hint to turn the note into information notification. */
446     gtk_window_set_type_hint (GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_NOTIFICATION);
447 }
448
449
450 static void 
451 hildon_note_finalize                            (GObject *obj_self)
452 {
453     HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (obj_self);
454     g_assert (priv);
455
456     /* FIXME Some of this stuff should be moved to dispose */
457
458     /* Free internal data */
459     if (priv->event_box)
460         g_object_unref (priv->event_box);
461
462     if (priv->label)
463         g_object_unref (priv->label);
464
465     if (priv->icon) {
466         g_free (priv->icon);
467         priv->icon = NULL;
468     }
469     if (priv->stock_icon) {
470         g_free (priv->stock_icon);
471         priv->stock_icon = NULL;
472     }
473     if (priv->idle_handler) {
474         g_source_remove (priv->idle_handler);
475         priv->idle_handler = 0;
476     }
477
478     if (priv->progressbar)
479         g_object_unref (priv->progressbar);
480
481     if (priv->original_description)
482         g_free (priv->original_description);
483
484     G_OBJECT_CLASS (parent_class)->finalize (obj_self);
485 }
486
487 static void
488 label_size_request                              (GtkWidget      *label,
489                                                  GtkRequisition *req,
490                                                  GtkWidget      *note)
491 {
492     gint note_height = MAX (HILDON_INFORMATION_NOTE_MIN_HEIGHT, req->height);
493     g_object_set (note, "height-request", note_height, NULL);
494 }
495
496 static void
497 resize_button (GtkWidget *button, gpointer *data)
498 {
499     gint width = GPOINTER_TO_INT (data);
500     g_object_set (button, "width-request", width, NULL);
501 }
502
503 static void
504 hildon_note_orientation_update (HildonNote *note, GdkScreen *screen)
505 {
506     GtkDialog *dialog = GTK_DIALOG (note);
507     HildonNotePrivate* priv = HILDON_NOTE_GET_PRIVATE (note);
508     GtkWidget *parent;
509     gint button_width, padding;
510     gboolean portrait = gdk_screen_get_width (screen) < gdk_screen_get_height (screen);
511
512     g_object_ref (dialog->action_area);
513     unpack_widget (dialog->action_area);
514
515     if (portrait) {
516         parent = dialog->vbox;
517         button_width = gdk_screen_get_width (screen) - HILDON_MARGIN_DOUBLE * 2;
518         padding = HILDON_MARGIN_DOUBLE;
519     } else {
520         parent = gtk_widget_get_parent (dialog->vbox);
521         button_width = priv->button_width;
522         padding = 0;
523     }
524
525     gtk_box_pack_end (GTK_BOX (parent), dialog->action_area,
526                       portrait, TRUE, 0);
527     gtk_box_reorder_child (GTK_BOX (parent), dialog->action_area, 0);
528     gtk_container_foreach (GTK_CONTAINER (dialog->action_area),
529                            (GtkCallback) resize_button,
530                            GINT_TO_POINTER (button_width));
531     g_object_unref (dialog->action_area);
532     gtk_container_child_set (GTK_CONTAINER (priv->box), priv->label,
533                              "padding", padding, NULL);
534 }
535
536 static void
537 screen_size_changed                            (GdkScreen *screen,
538                                                 GtkWidget *note)
539 {
540     HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (note);
541     gint screen_width = gdk_screen_get_width (screen);
542     gint text_width = screen_width - HILDON_INFORMATION_NOTE_MARGIN * 2;
543
544     if (priv->note_n == HILDON_NOTE_TYPE_INFORMATION ||
545         priv->note_n == HILDON_NOTE_TYPE_INFORMATION_THEME) {
546         g_object_set (note, "width-request", screen_width, NULL);
547         g_object_set (priv->label, "width-request", text_width, NULL);
548
549         return;
550     } else if (priv->note_n == HILDON_NOTE_TYPE_CONFIRMATION) {
551         hildon_note_orientation_update (HILDON_NOTE (note), screen);
552     }
553 }
554
555 static void
556 hildon_note_realize                             (GtkWidget *widget)
557 {
558     GdkDisplay *display;
559     gboolean is_info_note = FALSE;
560     Atom atom;
561     const gchar *notification_type;
562     HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget);
563     g_assert (priv);
564
565     /* Make widget->window accessible */
566     GTK_WIDGET_CLASS (parent_class)->realize (widget);
567
568     /* Border only, no titlebar */
569     gdk_window_set_decorations (widget->window, GDK_DECOR_BORDER);
570
571     /* Set the _HILDON_NOTIFICATION_TYPE property so Matchbox places the window correctly */
572     display = gdk_drawable_get_display (widget->window);
573     atom = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_NOTIFICATION_TYPE");
574
575     if (priv->note_n == HILDON_NOTE_TYPE_INFORMATION ||
576         priv->note_n == HILDON_NOTE_TYPE_INFORMATION_THEME) {
577         notification_type = "_HILDON_NOTIFICATION_TYPE_INFO";
578         is_info_note = TRUE;
579     } else {
580         notification_type = "_HILDON_NOTIFICATION_TYPE_CONFIRMATION";
581     }
582
583     XChangeProperty (GDK_WINDOW_XDISPLAY (widget->window), GDK_WINDOW_XID (widget->window),
584                      atom, XA_STRING, 8, PropModeReplace, (guchar *) notification_type,
585                      strlen (notification_type));
586
587     if (is_info_note) {
588         g_signal_connect (priv->label, "size-request", G_CALLBACK (label_size_request), widget);
589     }
590
591     GdkScreen *screen = gtk_widget_get_screen (widget);
592     g_signal_connect (screen, "size-changed", G_CALLBACK (screen_size_changed), widget);
593     screen_size_changed (screen, widget);
594 }
595
596 static void
597 hildon_note_unrealize                           (GtkWidget *widget)
598 {
599     HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget);
600     GdkScreen *screen = gtk_widget_get_screen (widget);
601
602     g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (screen_size_changed), widget);
603     g_signal_handlers_disconnect_by_func (priv->label, G_CALLBACK (label_size_request), widget);
604
605     GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
606 }
607
608
609 /* Helper function for removing a widget from it's container.
610    we own a separate reference to each object we try to unpack,
611    so extra referencing is not needed. */
612 static void 
613 unpack_widget                                   (GtkWidget *widget)
614 {
615     g_assert (widget == NULL || GTK_IS_WIDGET (widget));
616
617     if (widget && widget->parent)
618         gtk_container_remove (GTK_CONTAINER (widget->parent), widget);
619 }
620
621 /*
622   Name the widget and text label based on the note type. This is used
623   by the theme to give proper backgrounds depending on the note type.
624 */
625 static void
626 hildon_note_rename                              (HildonNote *note)
627 {
628   GEnumValue *value;
629   GEnumClass *enum_class;
630   gchar *name;
631
632   HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (note);
633
634   enum_class = g_type_class_ref (HILDON_TYPE_NOTE_TYPE);
635   value = g_enum_get_value (enum_class, priv->note_n);
636
637   name = g_strconcat ("HildonNote-", value->value_nick, NULL);
638   gtk_widget_set_name (GTK_WIDGET (note), name);
639   g_free (name);
640
641   name = g_strconcat ("HildonNoteLabel-", value->value_nick, NULL);
642   gtk_widget_set_name (priv->label, name);
643   g_free (name);
644
645   g_type_class_unref (enum_class);
646 }
647
648 static void
649 hildon_note_rebuild                             (HildonNote *note)
650 {
651     GtkDialog *dialog;
652     HildonNotePrivate *priv;
653     gboolean is_info_note = FALSE;
654
655     g_assert (HILDON_IS_NOTE (note));
656
657     priv = HILDON_NOTE_GET_PRIVATE (note);
658     g_assert (priv);
659
660     dialog = GTK_DIALOG (note);
661
662     /* Reuse exiting content widgets for new layout */
663     unpack_widget (priv->label);
664     unpack_widget (priv->progressbar);
665     unpack_widget (priv->event_box);
666
667     /* Destroy old layout and buttons */
668     if (priv->box) {
669         gtk_widget_destroy (priv->box);
670         priv->box = NULL;
671     }
672     if (priv->okButton) {
673         gtk_widget_destroy (priv->okButton);
674         priv->okButton = NULL;
675     }
676     if (priv->cancelButton) {
677         gtk_widget_destroy (priv->cancelButton);
678         priv->cancelButton = NULL;
679     }
680
681     /* Add needed buttons and images for each note type */
682     switch (priv->note_n)
683     {
684         case HILDON_NOTE_TYPE_CONFIRMATION:
685             priv->okButton = gtk_dialog_add_button (dialog,
686                     _("wdgt_bd_yes"), GTK_RESPONSE_OK);
687             priv->cancelButton = gtk_dialog_add_button (dialog,
688                     _("wdgt_bd_no"), GTK_RESPONSE_CANCEL);
689             gtk_widget_show (priv->cancelButton);
690             g_object_get (priv->okButton, "width-request",
691                           &priv->button_width, NULL);
692             gtk_widget_set_no_show_all (priv->cancelButton, FALSE);
693             break;
694
695         case HILDON_NOTE_TYPE_PROGRESSBAR:
696             priv->cancelButton = gtk_dialog_add_button (dialog,
697                     _("wdgt_bd_stop"), GTK_RESPONSE_CANCEL);
698             gtk_widget_show (priv->cancelButton);
699             gtk_widget_set_no_show_all (priv->cancelButton, FALSE);
700             break;
701
702         case HILDON_NOTE_TYPE_INFORMATION_THEME:
703         case HILDON_NOTE_TYPE_INFORMATION:
704             is_info_note = TRUE;
705             break;
706
707         case HILDON_NOTE_TYPE_CONFIRMATION_BUTTON:
708         default:
709             break;
710     }
711
712     /* Don't display the action area if this is just an information
713      * note. This prevents text from being slightly aligned to the
714      * left
715      */
716     if (is_info_note) {
717         gtk_widget_hide (dialog->action_area);
718     } else {
719         gtk_widget_show (dialog->action_area);
720     }
721     gtk_widget_set_no_show_all (dialog->action_area, is_info_note);
722
723     /* Pack label vertically. Spacing is only necessary for the progressbar note. */
724     priv->box = gtk_vbox_new (FALSE, priv->progressbar ? HILDON_MARGIN_DOUBLE : 0);
725     gtk_container_add (GTK_CONTAINER (priv->event_box), priv->box);
726     gtk_box_pack_start (GTK_BOX (priv->box), priv->label, TRUE, TRUE, 0);
727
728     if (priv->progressbar)
729         gtk_box_pack_start (GTK_BOX (priv->box), priv->progressbar, FALSE, FALSE, 0);
730
731     gtk_container_add (GTK_CONTAINER (dialog->vbox), priv->event_box);
732
733     gtk_widget_show_all (priv->event_box);
734 }
735
736 /**
737  * hildon_note_new_confirmation_add_buttons:
738  * @parent: the parent window. The X window ID of the parent window
739  *   has to be the same as the X window ID of the application. This is
740  *   important so that the window manager could handle the windows
741  *   correctly.
742  *   In GTK the X window ID can be checked using
743  *   GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
744  * @description: the message to confirm
745  * @Varargs: arguments pairs for new buttons(label and return value). 
746  *   Terminate the list with %NULL value.
747  * 
748  * Create a new confirmation note with custom buttons. Confirmation
749  * note has a text and any number of buttons. It's important to note
750  * that even though the name of the function might suggest, the
751  * default ok/cancel buttons are not appended but you have to provide
752  * all of the buttons.
753  *
754  * FIXME: This doc seems to be wrong, the two buttons aren't added so
755  * it would only contain the "additional" buttons? However, changing
756  * this would break those applications that rely on current behaviour.
757  *
758  * Returns: A #GtkWidget pointer of the note
759  */
760 GtkWidget*
761 hildon_note_new_confirmation_add_buttons        (GtkWindow *parent,
762                                                  const gchar *description,
763                                                  ...)
764 {
765     va_list args;
766     char *message;
767     int value;
768     GtkWidget *button;
769
770     g_return_val_if_fail (description != NULL, NULL);
771
772     GtkWidget *conf_note =
773         g_object_new (HILDON_TYPE_NOTE,
774                 "note-type", HILDON_NOTE_TYPE_CONFIRMATION_BUTTON,
775                 "description", description,
776                 NULL);
777
778     if (parent != NULL)
779         gtk_window_set_transient_for (GTK_WINDOW (conf_note), parent);
780
781     /* Add the buttons from varargs */
782     va_start(args, description);
783
784     while (TRUE) {
785         message = va_arg (args, char *);
786
787         if (! message) {
788             break;
789         }
790         value = va_arg (args, int);
791
792         button = gtk_dialog_add_button (GTK_DIALOG (conf_note), message, value);
793         /* maemo-gtk is going to set the "no-show-all" property all
794            cancel/close-like buttons to TRUE, so that they are not shown. On
795            the other hand, this confirmation note with custom buttons should
796            not obey this rule, so we need to make sure they are shown. */
797         gtk_widget_show (button);
798         gtk_widget_set_no_show_all (button, FALSE);
799     }
800
801     va_end (args);
802
803     return conf_note;
804 }
805
806
807 /**
808  * hildon_note_new_confirmation:
809  * @parent: the parent window. The X window ID of the parent window
810  *   has to be the same as the X window ID of the application. This is
811  *   important so that the window manager could handle the windows
812  *   correctly. In GTK the X window ID can be checked using
813  *   GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
814  * @description: the message to confirm
815  *
816  * Create a new confirmation note. Confirmation note has a text (description)
817  * that you specify and two buttons.
818  *
819  * Returns: a #GtkWidget pointer of the note
820  */
821 GtkWidget*
822 hildon_note_new_confirmation                    (GtkWindow *parent,
823                                                  const gchar *description)
824 {
825     GtkWidget *dialog = NULL;
826
827     g_return_val_if_fail (description != NULL, NULL);
828
829     dialog = g_object_new (HILDON_TYPE_NOTE,
830             "note-type",
831             HILDON_NOTE_TYPE_CONFIRMATION,
832             "description", description, NULL);
833
834     if (parent != NULL)
835         gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
836
837     return dialog;
838 }
839
840 /**
841  * hildon_note_new_confirmation_with_icon_name:
842  * @parent: the parent window. The X window ID of the parent window
843  *   has to be the same as the X window ID of the application. This is
844  *   important so that the window manager could handle the windows
845  *   correctly. In GTK the X window ID can be checked using
846  *   GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
847  * @description: the message to confirm
848  * @icon_name: icon to be displayed. If NULL, default icon is used.
849  * 
850  * Create a new confirmation note. Confirmation note has a text (description) 
851  * that you specify and two buttons.
852  *
853  * Deprecated: Since 2.2, icons are not shown in confirmation notes. Icons set
854  * with this function will be ignored. Use hildon_note_new_confirmation() instead.
855  *
856  * Returns: a #GtkWidget pointer of the note
857  */
858 GtkWidget*
859 hildon_note_new_confirmation_with_icon_name     (GtkWindow *parent,
860                                                  const gchar *description,
861                                                  const gchar *icon_name)
862 {
863     GtkWidget *dialog;
864
865     dialog = hildon_note_new_confirmation (parent, description);
866     g_object_set (dialog, "icon", icon_name, NULL);
867
868     return dialog;
869 }
870
871 /**
872  * hildon_note_new_information:
873  * @parent: the parent window. The X window ID of the parent window
874  *   has to be the same as the X window ID of the application. This is
875  *   important so that the window manager could handle the windows
876  *   correctly. In GTK the X window ID can be checked using
877  *   GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
878  * @description: the message to confirm
879  * 
880  * Create a new information note. Information note has a text (description)
881  * that you specify and an OK button.
882  * 
883  * Returns: a #GtkWidget pointer of the note
884  */
885 GtkWidget*
886 hildon_note_new_information                     (GtkWindow *parent,
887                                                  const gchar *description)
888 {
889     GtkWidget *dialog = NULL;
890
891     g_return_val_if_fail (description != NULL, NULL);
892
893     dialog = g_object_new (HILDON_TYPE_NOTE,
894             "note-type",
895             HILDON_NOTE_TYPE_INFORMATION_THEME,
896             "description", description, NULL);
897
898     if (parent != NULL)
899         gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
900
901     return dialog;
902 }
903
904 /**
905  * hildon_note_new_information_with_icon_name:
906  * @parent: the parent window. The X window ID of the parent window
907  *   has to be the same as the X window ID of the application. This is
908  *   important so that the window manager could handle the windows
909  *   correctly. In GTK the X window ID can be checked using
910  *   GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
911  * @description: the message to confirm
912  * @icon_name: icon to be displayed. If NULL, default icon is used.
913  * 
914  * Create a new information note. Information note has text(description) 
915  * that you specify, an OK button and an icon.
916  * 
917  * Deprecated: Since 2.2, icons are not shown in confirmation notes. Icons set
918  * with this function will be ignored. Use hildon_note_new_information() instead.
919  *
920  * Returns: a #GtkWidget pointer of the note
921  */
922 GtkWidget*
923 hildon_note_new_information_with_icon_name      (GtkWindow * parent,
924                                                  const gchar *description,
925                                                  const gchar *icon_name)
926 {
927     GtkWidget *dialog;
928
929     dialog = hildon_note_new_information (parent, description);
930     g_object_set (dialog, "icon", icon_name, NULL);
931
932     return dialog;
933 }
934
935 /* FIXME This documentation string LIES! */
936
937 /**
938  * hildon_note_new_cancel_with_progress_bar:
939  * @parent: the parent window. The X window ID of the parent window
940  *   has to be the same as the X window ID of the application. This is
941  *   important so that the window manager could handle the windows
942  *   correctly. In GTK the X window ID can be checked using
943  *   GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
944  * @description: the action to cancel
945  * @progressbar: a pointer to #GtkProgressBar to be filled with the
946  *   progressbar assigned to this note. Use this to set the fraction of
947  *   progressbar done. This parameter can be %NULL as well, in which
948  *   case plain text cancel note appears.
949  *
950  * Create a new cancel note with a progress bar. Cancel note has 
951  * text(description) that you specify, a Cancel button and a progress bar.
952  *
953  * Returns: a #GtkDialog. Use this to get rid of this note when you
954  *   no longer need it.
955  */
956 GtkWidget*
957 hildon_note_new_cancel_with_progress_bar        (GtkWindow *parent,
958                                                  const gchar *description,
959                                                  GtkProgressBar *progressbar)
960 {
961     GtkWidget *dialog = NULL;
962
963     g_return_val_if_fail (description != NULL, NULL);
964
965     dialog = g_object_new (HILDON_TYPE_NOTE,
966             "note-type",
967             HILDON_NOTE_TYPE_PROGRESSBAR,
968             "description", description,
969             "progressbar",
970             progressbar, NULL);
971
972     if (parent != NULL)
973         gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
974
975     return dialog;
976 }
977
978
979 /**
980  * hildon_note_set_button_text:
981  * @note: a #HildonNote
982  * @text: sets the button text and if there is two buttons in dialog, 
983  *   the button texts will be &lt;text&gt;, "Cancel".  
984  *
985  * Sets the text of the button in @note.
986  */
987 void 
988 hildon_note_set_button_text                     (HildonNote *note, 
989                                                  const gchar *text)
990 {
991     HildonNotePrivate *priv;
992
993     g_return_if_fail (HILDON_IS_NOTE (note));
994
995     priv = HILDON_NOTE_GET_PRIVATE (HILDON_NOTE (note));
996     g_assert (priv);
997
998     if (priv->okButton) {
999         gtk_button_set_label (GTK_BUTTON (priv->okButton), text);
1000         gtk_button_set_label (GTK_BUTTON (priv->cancelButton),
1001                 _("wdgt_bd_no"));
1002     } else {
1003         gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text);
1004     }
1005 }
1006
1007 /**
1008  * hildon_note_set_button_texts:
1009  * @note: a #HildonNote
1010  * @text_ok: the new text of the default OK button
1011  * @text_cancel: the new text of the default cancel button 
1012  *
1013  * Sets the text for the buttons in @note.
1014  */
1015 void 
1016 hildon_note_set_button_texts                    (HildonNote *note,
1017                                                  const gchar *text_ok,
1018                                                  const gchar *text_cancel)
1019 {
1020     HildonNotePrivate *priv;
1021
1022     g_return_if_fail (HILDON_IS_NOTE (note));
1023
1024     priv = HILDON_NOTE_GET_PRIVATE (HILDON_NOTE (note));
1025     g_assert (priv);
1026
1027     if (priv->okButton) {
1028         gtk_button_set_label (GTK_BUTTON (priv->okButton), text_ok);
1029         gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text_cancel);
1030     } else {
1031         gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text_cancel);
1032     }
1033 }
1034
1035 static void
1036 on_show_cb                                      (GtkWidget *widget,
1037                                                  gpointer data)
1038 {
1039     HildonNotePrivate *priv;
1040
1041     priv = HILDON_NOTE_GET_PRIVATE (widget);
1042     priv->idle_handler = g_idle_add (sound_handling, widget);
1043 }
1044
1045 /* We play a system sound when the note comes visible */
1046 static gboolean
1047 sound_handling                                  (gpointer data)
1048 {
1049     HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (data);
1050     g_assert (priv);
1051
1052     switch (priv->note_n)
1053     {
1054         case HILDON_NOTE_TYPE_INFORMATION:
1055         case HILDON_NOTE_TYPE_INFORMATION_THEME:
1056             hildon_play_system_sound (INFORMATION_SOUND_PATH);
1057             break;
1058
1059         case HILDON_NOTE_TYPE_CONFIRMATION:
1060         case HILDON_NOTE_TYPE_CONFIRMATION_BUTTON:
1061             hildon_play_system_sound (CONFIRMATION_SOUND_PATH);
1062             break;
1063
1064         default:
1065             break;
1066     };
1067
1068     priv->idle_handler = 0;
1069
1070     return FALSE;
1071 }