Play the sound on hildon-note using "show" event and a idle
[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 also can
32  * include a progress bar.
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     g_object_class_install_property (object_class,
340             PROP_HILDON_NOTE_TYPE,
341             g_param_spec_enum ("note-type",
342                 "note type",
343                 "The type of the note dialog",
344                 hildon_note_type_get_type (),
345                 HILDON_NOTE_TYPE_CONFIRMATION,
346                 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
347
348     /**
349      * HildonNote:description:
350      *
351      * Description for the note.
352      */
353     g_object_class_install_property (object_class,
354             PROP_HILDON_NOTE_DESCRIPTION,
355             g_param_spec_string ("description",
356                 "note description",
357                 "The text that appears in the note dialog",
358                 "",
359                 G_PARAM_READWRITE));
360
361     /**
362      * HildonNote:icon:
363      *
364      * Icon for the note.
365      *
366      * Deprecated: Since 2.2
367      */
368     g_object_class_install_property (object_class,
369             PROP_HILDON_NOTE_ICON,
370             g_param_spec_string ("icon",
371                 "note icon",
372                 "The name of the icon that appears in the note dialog",
373                 "",
374                 G_PARAM_READWRITE));
375
376     /**
377      * HildonNote:stock-icon:
378      *
379      * Stock icon name for the note.
380      *
381      * Deprecated: Since 2.2
382      */
383     g_object_class_install_property (object_class,
384             PROP_HILDON_NOTE_STOCK_ICON,
385             g_param_spec_string ("stock-icon",
386                 "Stock note icon",
387                 "The stock name of the icon that appears in the note dialog",
388                 "",
389                 G_PARAM_READWRITE));
390
391     /**
392      * HildonNote:progressbar:
393      *
394      * Progressbar for the note (if any).
395      */
396     g_object_class_install_property (object_class,
397             PROP_HILDON_NOTE_PROGRESSBAR,
398             g_param_spec_object ("progressbar",
399                 "Progressbar widget",
400                 "The progressbar that appears in the note dialog",
401                 GTK_TYPE_PROGRESS_BAR,
402                 G_PARAM_READWRITE));
403 }
404
405 static void 
406 hildon_note_init                                (HildonNote *dialog)
407 {
408     HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (dialog);
409     g_assert (priv);
410
411     priv->label = gtk_label_new (NULL);
412     gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
413     gtk_label_set_justify (GTK_LABEL (priv->label), GTK_JUSTIFY_LEFT);
414
415     priv->event_box = gtk_event_box_new ();
416     priv->icon = NULL;
417     priv->stock_icon = NULL;
418
419     gtk_event_box_set_visible_window (GTK_EVENT_BOX (priv->event_box), FALSE);
420     gtk_event_box_set_above_child (GTK_EVENT_BOX (priv->event_box), TRUE);
421     g_signal_connect (priv->event_box, "button-press-event",
422                       G_CALLBACK (event_box_press_event), dialog);
423
424     /* Because ESD is synchronous, we wish to play sound after the
425        note is already on screen to avoid blocking its appearance */
426     g_signal_connect (GTK_WIDGET (dialog), "show",
427                       G_CALLBACK (on_show_cb), NULL);
428
429     /* Acquire real references to our internal children, since
430        they are not nessecarily packed into container in each
431        layout */
432     g_object_ref_sink (priv->event_box);
433     g_object_ref_sink (priv->label);
434
435     gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
436     gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
437
438     /* We use special hint to turn the note into information notification. */
439     gtk_window_set_type_hint (GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_NOTIFICATION);
440 }
441
442
443 static void 
444 hildon_note_finalize                            (GObject *obj_self)
445 {
446     HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (obj_self);
447     g_assert (priv);
448
449     /* FIXME Some of this stuff should be moved to dispose */
450
451     /* Free internal data */
452     if (priv->event_box)
453         g_object_unref (priv->event_box);
454
455     if (priv->label)
456         g_object_unref (priv->label);
457
458     if (priv->icon) {
459         g_free (priv->icon);
460         priv->icon = NULL;
461     }
462     if (priv->stock_icon) {
463         g_free (priv->stock_icon);
464         priv->stock_icon = NULL;
465     }
466
467     if (priv->progressbar)
468         g_object_unref (priv->progressbar);
469
470     if (priv->original_description)
471         g_free (priv->original_description);
472
473     G_OBJECT_CLASS (parent_class)->finalize (obj_self);
474 }
475
476 static void
477 label_size_request                              (GtkWidget      *label,
478                                                  GtkRequisition *req,
479                                                  GtkWidget      *note)
480 {
481     gint note_height = MAX (HILDON_INFORMATION_NOTE_MIN_HEIGHT, req->height);
482     g_object_set (note, "height-request", note_height, NULL);
483 }
484
485 static void
486 resize_button (GtkWidget *button, gpointer *data)
487 {
488     gint width = GPOINTER_TO_INT (data);
489     g_object_set (button, "width-request", width, NULL);
490 }
491
492 static void
493 hildon_note_orientation_update (HildonNote *note, GdkScreen *screen)
494 {
495     GtkDialog *dialog = GTK_DIALOG (note);
496     HildonNotePrivate* priv = HILDON_NOTE_GET_PRIVATE (note);
497     GtkWidget *parent;
498     gint button_width, padding;
499     gboolean portrait = gdk_screen_get_width (screen) < gdk_screen_get_height (screen);
500
501     g_object_ref (dialog->action_area);
502     unpack_widget (dialog->action_area);
503
504     if (portrait) {
505         parent = dialog->vbox;
506         button_width = gdk_screen_get_width (screen) - HILDON_MARGIN_DOUBLE * 2;
507         padding = HILDON_MARGIN_DOUBLE;
508     } else {
509         parent = gtk_widget_get_parent (dialog->vbox);
510         button_width = priv->button_width;
511         padding = 0;
512     }
513
514     gtk_box_pack_end (GTK_BOX (parent), dialog->action_area,
515                       portrait, TRUE, 0);
516     gtk_box_reorder_child (GTK_BOX (parent), dialog->action_area, 0);
517     gtk_container_foreach (GTK_CONTAINER (dialog->action_area),
518                            (GtkCallback) resize_button,
519                            GINT_TO_POINTER (button_width));
520     g_object_unref (dialog->action_area);
521     gtk_container_child_set (GTK_CONTAINER (priv->box), priv->label,
522                              "padding", padding, NULL);
523 }
524
525 static void
526 screen_size_changed                            (GdkScreen *screen,
527                                                 GtkWidget *note)
528 {
529     HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (note);
530     gint screen_width = gdk_screen_get_width (screen);
531     gint text_width = screen_width - HILDON_INFORMATION_NOTE_MARGIN * 2;
532
533     if (priv->note_n == HILDON_NOTE_TYPE_INFORMATION ||
534         priv->note_n == HILDON_NOTE_TYPE_INFORMATION_THEME) {
535         g_object_set (note, "width-request", screen_width, NULL);
536         g_object_set (priv->label, "width-request", text_width, NULL);
537
538         return;
539     } else if (priv->note_n == HILDON_NOTE_TYPE_CONFIRMATION) {
540         hildon_note_orientation_update (HILDON_NOTE (note), screen);
541     }
542 }
543
544 static void
545 hildon_note_realize                             (GtkWidget *widget)
546 {
547     GdkDisplay *display;
548     gboolean is_info_note = FALSE;
549     Atom atom;
550     const gchar *notification_type;
551     HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget);
552     g_assert (priv);
553
554     /* Make widget->window accessible */
555     GTK_WIDGET_CLASS (parent_class)->realize (widget);
556
557     /* Border only, no titlebar */
558     gdk_window_set_decorations (widget->window, GDK_DECOR_BORDER);
559
560     /* Set the _HILDON_NOTIFICATION_TYPE property so Matchbox places the window correctly */
561     display = gdk_drawable_get_display (widget->window);
562     atom = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_NOTIFICATION_TYPE");
563
564     if (priv->note_n == HILDON_NOTE_TYPE_INFORMATION ||
565         priv->note_n == HILDON_NOTE_TYPE_INFORMATION_THEME) {
566         notification_type = "_HILDON_NOTIFICATION_TYPE_INFO";
567         is_info_note = TRUE;
568     } else {
569         notification_type = "_HILDON_NOTIFICATION_TYPE_CONFIRMATION";
570     }
571
572     XChangeProperty (GDK_WINDOW_XDISPLAY (widget->window), GDK_WINDOW_XID (widget->window),
573                      atom, XA_STRING, 8, PropModeReplace, (guchar *) notification_type,
574                      strlen (notification_type));
575
576     if (is_info_note) {
577         g_signal_connect (priv->label, "size-request", G_CALLBACK (label_size_request), widget);
578     }
579
580     GdkScreen *screen = gtk_widget_get_screen (widget);
581     g_signal_connect (screen, "size-changed", G_CALLBACK (screen_size_changed), widget);
582     screen_size_changed (screen, widget);
583 }
584
585 static void
586 hildon_note_unrealize                           (GtkWidget *widget)
587 {
588     HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget);
589     GdkScreen *screen = gtk_widget_get_screen (widget);
590
591     g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (screen_size_changed), widget);
592     g_signal_handlers_disconnect_by_func (priv->label, G_CALLBACK (label_size_request), widget);
593
594     GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
595 }
596
597
598 /* Helper function for removing a widget from it's container.
599    we own a separate reference to each object we try to unpack,
600    so extra referencing is not needed. */
601 static void 
602 unpack_widget                                   (GtkWidget *widget)
603 {
604     g_assert (widget == NULL || GTK_IS_WIDGET (widget));
605
606     if (widget && widget->parent)
607         gtk_container_remove (GTK_CONTAINER (widget->parent), widget);
608 }
609
610 /*
611   Name the widget and text label based on the note type. This is used
612   by the theme to give proper backgrounds depending on the note type.
613 */
614 static void
615 hildon_note_rename                              (HildonNote *note)
616 {
617   GEnumValue *value;
618   GEnumClass *enum_class;
619   gchar *name;
620
621   HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (note);
622
623   enum_class = g_type_class_ref (HILDON_TYPE_NOTE_TYPE);
624   value = g_enum_get_value (enum_class, priv->note_n);
625
626   name = g_strconcat ("HildonNote-", value->value_nick, NULL);
627   gtk_widget_set_name (GTK_WIDGET (note), name);
628   g_free (name);
629
630   name = g_strconcat ("HildonNoteLabel-", value->value_nick, NULL);
631   gtk_widget_set_name (priv->label, name);
632   g_free (name);
633
634   g_type_class_unref (enum_class);
635 }
636
637 static void
638 hildon_note_rebuild                             (HildonNote *note)
639 {
640     GtkDialog *dialog;
641     HildonNotePrivate *priv;
642     gboolean is_info_note = FALSE;
643
644     g_assert (HILDON_IS_NOTE (note));
645
646     priv = HILDON_NOTE_GET_PRIVATE (note);
647     g_assert (priv);
648
649     dialog = GTK_DIALOG (note);
650
651     /* Reuse exiting content widgets for new layout */
652     unpack_widget (priv->label);
653     unpack_widget (priv->progressbar);
654     unpack_widget (priv->event_box);
655
656     /* Destroy old layout and buttons */
657     if (priv->box) {
658         gtk_widget_destroy (priv->box);
659         priv->box = NULL;
660     }
661     if (priv->okButton) {
662         gtk_widget_destroy (priv->okButton);
663         priv->okButton = NULL;
664     }
665     if (priv->cancelButton) {
666         gtk_widget_destroy (priv->cancelButton);
667         priv->cancelButton = NULL;
668     }
669
670     /* Add needed buttons and images for each note type */
671     switch (priv->note_n)
672     {
673         case HILDON_NOTE_TYPE_CONFIRMATION:
674             priv->okButton = gtk_dialog_add_button (dialog,
675                     _("wdgt_bd_yes"), GTK_RESPONSE_OK);
676             priv->cancelButton = gtk_dialog_add_button (dialog,
677                     _("wdgt_bd_no"), GTK_RESPONSE_CANCEL);
678             gtk_widget_show (priv->cancelButton);
679             g_object_get (priv->okButton, "width-request",
680                           &priv->button_width, NULL);
681             gtk_widget_set_no_show_all (priv->cancelButton, FALSE);
682             break;
683
684         case HILDON_NOTE_TYPE_PROGRESSBAR:
685             priv->cancelButton = gtk_dialog_add_button (dialog,
686                     _("wdgt_bd_stop"), GTK_RESPONSE_CANCEL);
687             gtk_widget_show (priv->cancelButton);
688             gtk_widget_set_no_show_all (priv->cancelButton, FALSE);
689             break;
690
691         case HILDON_NOTE_TYPE_INFORMATION_THEME:
692         case HILDON_NOTE_TYPE_INFORMATION:
693             is_info_note = TRUE;
694             break;
695
696         case HILDON_NOTE_TYPE_CONFIRMATION_BUTTON:
697         default:
698             break;
699     }
700
701     /* Don't display the action area if this is just an information
702      * note. This prevents text from being slightly aligned to the
703      * left
704      */
705     if (is_info_note) {
706         gtk_widget_hide (dialog->action_area);
707     } else {
708         gtk_widget_show (dialog->action_area);
709     }
710     gtk_widget_set_no_show_all (dialog->action_area, is_info_note);
711
712     /* Pack label vertically. Spacing is only necessary for the progressbar note. */
713     priv->box = gtk_vbox_new (FALSE, priv->progressbar ? HILDON_MARGIN_DOUBLE : 0);
714     gtk_container_add (GTK_CONTAINER (priv->event_box), priv->box);
715     gtk_box_pack_start (GTK_BOX (priv->box), priv->label, TRUE, TRUE, 0);
716
717     if (priv->progressbar)
718         gtk_box_pack_start (GTK_BOX (priv->box), priv->progressbar, FALSE, FALSE, 0);
719
720     gtk_container_add (GTK_CONTAINER (dialog->vbox), priv->event_box);
721
722     gtk_widget_show_all (priv->event_box);
723 }
724
725 /**
726  * hildon_note_new_confirmation_add_buttons:
727  * @parent: the parent window. The X window ID of the parent window
728  *   has to be the same as the X window ID of the application. This is
729  *   important so that the window manager could handle the windows
730  *   correctly.
731  *   In GTK the X window ID can be checked using
732  *   GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
733  * @description: the message to confirm
734  * @Varargs: arguments pairs for new buttons(label and return value). 
735  *   Terminate the list with %NULL value.
736  * 
737  * Create a new confirmation note with custom buttons. Confirmation
738  * note has a text and any number of buttons. It's important to note
739  * that even though the name of the function might suggest, the
740  * default ok/cancel buttons are not appended but you have to provide
741  * all of the buttons.
742  *
743  * FIXME: This doc seems to be wrong, the two buttons aren't added so
744  * it would only contain the "additional" buttons? However, changing
745  * this would break those applications that rely on current behaviour.
746  *
747  * Returns: A #GtkWidget pointer of the note
748  */
749 GtkWidget*
750 hildon_note_new_confirmation_add_buttons        (GtkWindow *parent,
751                                                  const gchar *description,
752                                                  ...)
753 {
754     va_list args;
755     char *message;
756     int value;
757     GtkWidget *button;
758
759     g_return_val_if_fail (description != NULL, NULL);
760
761     GtkWidget *conf_note =
762         g_object_new (HILDON_TYPE_NOTE,
763                 "note-type", HILDON_NOTE_TYPE_CONFIRMATION_BUTTON,
764                 "description", description,
765                 NULL);
766
767     if (parent != NULL)
768         gtk_window_set_transient_for (GTK_WINDOW (conf_note), parent);
769
770     /* Add the buttons from varargs */
771     va_start(args, description);
772
773     while (TRUE) {
774         message = va_arg (args, char *);
775
776         if (! message) {
777             break;
778         }
779         value = va_arg (args, int);
780
781         button = gtk_dialog_add_button (GTK_DIALOG (conf_note), message, value);
782         /* maemo-gtk is going to set the "no-show-all" property all
783            cancel/close-like buttons to TRUE, so that they are not shown. On
784            the other hand, this confirmation note with custom buttons should
785            not obey this rule, so we need to make sure they are shown. */
786         gtk_widget_show (button);
787         gtk_widget_set_no_show_all (button, FALSE);
788     }
789
790     va_end (args);
791
792     return conf_note;
793 }
794
795
796 /**
797  * hildon_note_new_confirmation:
798  * @parent: the parent window. The X window ID of the parent window
799  *   has to be the same as the X window ID of the application. This is
800  *   important so that the window manager could handle the windows
801  *   correctly. In GTK the X window ID can be checked using
802  *   GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
803  * @description: the message to confirm
804  *
805  * Create a new confirmation note. Confirmation note has a text (description)
806  * that you specify and two buttons.
807  *
808  * Returns: a #GtkWidget pointer of the note
809  */
810 GtkWidget*
811 hildon_note_new_confirmation                    (GtkWindow *parent,
812                                                  const gchar *description)
813 {
814     GtkWidget *dialog = NULL;
815
816     g_return_val_if_fail (description != NULL, NULL);
817
818     dialog = g_object_new (HILDON_TYPE_NOTE,
819             "note-type",
820             HILDON_NOTE_TYPE_CONFIRMATION,
821             "description", description, NULL);
822
823     if (parent != NULL)
824         gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
825
826     return dialog;
827 }
828
829 /**
830  * hildon_note_new_confirmation_with_icon_name:
831  * @parent: the parent window. The X window ID of the parent window
832  *   has to be the same as the X window ID of the application. This is
833  *   important so that the window manager could handle the windows
834  *   correctly. In GTK the X window ID can be checked using
835  *   GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
836  * @description: the message to confirm
837  * @icon_name: icon to be displayed. If NULL, default icon is used.
838  * 
839  * Create a new confirmation note. Confirmation note has a text (description) 
840  * that you specify and two buttons.
841  *
842  * Deprecated: Since 2.2, icons are not shown in confirmation notes. Icons set
843  * with this function will be ignored. Use hildon_note_new_confirmation() instead.
844  *
845  * Returns: a #GtkWidget pointer of the note
846  */
847 GtkWidget*
848 hildon_note_new_confirmation_with_icon_name     (GtkWindow *parent,
849                                                  const gchar *description,
850                                                  const gchar *icon_name)
851 {
852     GtkWidget *dialog;
853
854     dialog = hildon_note_new_confirmation (parent, description);
855     g_object_set (dialog, "icon", icon_name, NULL);
856
857     return dialog;
858 }
859
860 /**
861  * hildon_note_new_information:
862  * @parent: the parent window. The X window ID of the parent window
863  *   has to be the same as the X window ID of the application. This is
864  *   important so that the window manager could handle the windows
865  *   correctly. In GTK the X window ID can be checked using
866  *   GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
867  * @description: the message to confirm
868  * 
869  * Create a new information note. Information note has a text (description)
870  * that you specify and an OK button.
871  * 
872  * Returns: a #GtkWidget pointer of the note
873  */
874 GtkWidget*
875 hildon_note_new_information                     (GtkWindow *parent,
876                                                  const gchar *description)
877 {
878     GtkWidget *dialog = NULL;
879
880     g_return_val_if_fail (description != NULL, NULL);
881
882     dialog = g_object_new (HILDON_TYPE_NOTE,
883             "note-type",
884             HILDON_NOTE_TYPE_INFORMATION_THEME,
885             "description", description, NULL);
886
887     if (parent != NULL)
888         gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
889
890     return dialog;
891 }
892
893 /**
894  * hildon_note_new_information_with_icon_name:
895  * @parent: the parent window. The X window ID of the parent window
896  *   has to be the same as the X window ID of the application. This is
897  *   important so that the window manager could handle the windows
898  *   correctly. In GTK the X window ID can be checked using
899  *   GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
900  * @description: the message to confirm
901  * @icon_name: icon to be displayed. If NULL, default icon is used.
902  * 
903  * Create a new information note. Information note has text(description) 
904  * that you specify, an OK button and an icon.
905  * 
906  * Deprecated: Since 2.2, icons are not shown in confirmation notes. Icons set
907  * with this function will be ignored. Use hildon_note_new_information() instead.
908  *
909  * Returns: a #GtkWidget pointer of the note
910  */
911 GtkWidget*
912 hildon_note_new_information_with_icon_name      (GtkWindow * parent,
913                                                  const gchar *description,
914                                                  const gchar *icon_name)
915 {
916     GtkWidget *dialog;
917
918     dialog = hildon_note_new_information (parent, description);
919     g_object_set (dialog, "icon", icon_name, NULL);
920
921     return dialog;
922 }
923
924 /* FIXME This documentation string LIES! */
925
926 /**
927  * hildon_note_new_cancel_with_progress_bar:
928  * @parent: the parent window. The X window ID of the parent window
929  *   has to be the same as the X window ID of the application. This is
930  *   important so that the window manager could handle the windows
931  *   correctly. In GTK the X window ID can be checked using
932  *   GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
933  * @description: the action to cancel
934  * @progressbar: a pointer to #GtkProgressBar to be filled with the
935  *   progressbar assigned to this note. Use this to set the fraction of
936  *   progressbar done. This parameter can be %NULL as well, in which
937  *   case plain text cancel note appears.
938  *
939  * Create a new cancel note with a progress bar. Cancel note has 
940  * text(description) that you specify, a Cancel button and a progress bar.
941  *
942  * Returns: a #GtkDialog. Use this to get rid of this note when you
943  *   no longer need it.
944  */
945 GtkWidget*
946 hildon_note_new_cancel_with_progress_bar        (GtkWindow *parent,
947                                                  const gchar *description,
948                                                  GtkProgressBar *progressbar)
949 {
950     GtkWidget *dialog = NULL;
951
952     g_return_val_if_fail (description != NULL, NULL);
953
954     dialog = g_object_new (HILDON_TYPE_NOTE,
955             "note-type",
956             HILDON_NOTE_TYPE_PROGRESSBAR,
957             "description", description,
958             "progressbar",
959             progressbar, NULL);
960
961     if (parent != NULL)
962         gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
963
964     return dialog;
965 }
966
967
968 /**
969  * hildon_note_set_button_text:
970  * @note: a #HildonNote
971  * @text: sets the button text and if there is two buttons in dialog, 
972  *   the button texts will be &lt;text&gt;, "Cancel".  
973  *
974  * Sets the button text to be used by the hildon_note widget.
975  */
976 void 
977 hildon_note_set_button_text                     (HildonNote *note, 
978                                                  const gchar *text)
979 {
980     HildonNotePrivate *priv;
981
982     g_return_if_fail (HILDON_IS_NOTE (note));
983
984     priv = HILDON_NOTE_GET_PRIVATE (HILDON_NOTE (note));
985     g_assert (priv);
986
987     if (priv->okButton) {
988         gtk_button_set_label (GTK_BUTTON (priv->okButton), text);
989         gtk_button_set_label (GTK_BUTTON (priv->cancelButton),
990                 _("wdgt_bd_no"));
991     } else {
992         gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text);
993     }
994 }
995
996 /**
997  * hildon_note_set_button_texts:
998  * @note: a #HildonNote
999  * @text_ok: the new text of the default OK button
1000  * @text_cancel: the new text of the default cancel button 
1001  *
1002  * Sets the button texts to be used by this hildon_note widget.
1003  */
1004 void 
1005 hildon_note_set_button_texts                    (HildonNote *note,
1006                                                  const gchar *text_ok,
1007                                                  const gchar *text_cancel)
1008 {
1009     HildonNotePrivate *priv;
1010
1011     g_return_if_fail (HILDON_IS_NOTE (note));
1012
1013     priv = HILDON_NOTE_GET_PRIVATE (HILDON_NOTE (note));
1014     g_assert (priv);
1015
1016     if (priv->okButton) {
1017         gtk_button_set_label (GTK_BUTTON (priv->okButton), text_ok);
1018         gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text_cancel);
1019     } else {
1020         gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text_cancel);
1021     }
1022 }
1023
1024 static void
1025 on_show_cb                                      (GtkWidget *widget,
1026                                                  gpointer data)
1027 {
1028     g_idle_add (sound_handling, widget);
1029 }
1030
1031 /* We play a system sound when the note comes visible */
1032 static gboolean
1033 sound_handling                                  (gpointer data)
1034 {
1035     HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (data);
1036     g_assert (priv);
1037
1038     switch (priv->note_n)
1039     {
1040         case HILDON_NOTE_TYPE_INFORMATION:
1041         case HILDON_NOTE_TYPE_INFORMATION_THEME:
1042             hildon_play_system_sound (INFORMATION_SOUND_PATH);
1043             break;
1044
1045         case HILDON_NOTE_TYPE_CONFIRMATION:
1046         case HILDON_NOTE_TYPE_CONFIRMATION_BUTTON:
1047             hildon_play_system_sound (CONFIRMATION_SOUND_PATH);
1048             break;
1049
1050         default:
1051             break;
1052     };
1053
1054     return FALSE;
1055 }