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