2008-08-28 Alejandro Pinheiro <apinheiro@igalia.com> * src/hildon-touch-selector...
[hildon] / src / 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: Michael Dominic Kostrzewa <michael.kostrzewa@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  * Notes are used to for confirmation (OK/Cancel/etc.) from the user.
30  * A simple note contains an information text. Additional features
31  * such as progress bars or animation can also be included.
32  * 
33  * <example>
34  * <title>HildonNote example</title>
35  * <programlisting>
36  * <!-- -->
37  * gboolean
38  * show_confirmation_note (GtkWindow *parent)
39  * {
40  *   gint retcode;
41  *   GtkWidget *note;
42  *   note = hildon_note_new_confirmation (parent, "Confirmation message...");
43  * <!-- -->
44  *   retcode = gtk_dialog_run (GTK_DIALOG (note));
45  *   gtk_widget_destroy (note);
46  * <!-- -->
47  *   if (retcode == GTK_RESPONSE_OK) {
48  *        g_debug ("User pressed 'OK' button'");
49  *        return TRUE;
50  *   } else {
51  *        g_debug ("User pressed 'Cancel' button");
52  *        return FALSE;
53  *   }
54  * }
55  * </programlisting>
56  * </example>
57  */
58
59 #ifdef                                          HAVE_CONFIG_H
60 #include                                        <config.h>
61 #endif
62
63 #include                                        <stdio.h>
64 #include                                        <string.h>
65 #include                                        <libintl.h>
66 #include                                        <X11/X.h>
67 #include                                        <X11/Xatom.h>
68 #include                                        <gdk/gdkx.h>
69
70 #include                                        "hildon-note.h"
71 #include                                        "hildon-defines.h"
72 #include                                        "hildon-sound.h"
73 #include                                        "hildon-banner.h" 
74 #include                                        "hildon-enum-types.h"
75 #include                                        "hildon-note-private.h"
76
77
78 #define                                         CONFIRMATION_SOUND_PATH \
79                                                 "/usr/share/sounds/ui-confirmation_note.wav"
80
81 #define                                         INFORMATION_SOUND_PATH \
82                                                 "/usr/share/sounds/ui-information_note.wav"
83
84 #define                                         HILDON_NOTE_CONFIRMATION_ICON \
85                                                 "qgn_note_confirm"
86
87 #define                                         HILDON_NOTE_INFORMATION_ICON \
88                                                 "qgn_note_info"
89
90 #define                                         _(String) dgettext("hildon-libs", String)
91
92 static void 
93 hildon_note_class_init                          (HildonNoteClass *class);
94
95 static void
96 hildon_note_init                                (HildonNote *dialog);
97
98 static void 
99 hildon_note_rebuild                             (HildonNote *note);
100
101 static void
102 hildon_note_finalize                            (GObject *obj_self);
103
104 static gboolean
105 hildon_note_button_release                      (GtkWidget *widget,
106                                                  GdkEventButton *event);
107
108 static void
109 hildon_note_map                                 (GtkWidget *widget);
110
111 static void
112 hildon_note_unmap                               (GtkWidget *widget);
113
114 static void
115 hildon_note_realize                             (GtkWidget *widget);
116
117 static void 
118 hildon_note_set_property                        (GObject *object,
119                                                  guint prop_id,
120                                                  const GValue *value,
121                                                  GParamSpec *pspec);
122
123 static void
124 hildon_note_get_property                        (GObject *object,
125                                                  guint prop_id,
126                                                  GValue *value, 
127                                                  GParamSpec *pspec);
128
129 static gboolean
130 sound_handling                                  (GtkWidget *widget, 
131                                                  GdkEventExpose *event, 
132                                                  gpointer data);
133
134 enum 
135 {
136     PROP_0,
137     PROP_HILDON_NOTE_TYPE,
138     PROP_HILDON_NOTE_DESCRIPTION,
139     PROP_HILDON_NOTE_ICON,
140     PROP_HILDON_NOTE_PROGRESSBAR,
141     PROP_HILDON_NOTE_STOCK_ICON
142 };
143
144 static GtkDialogClass*                          parent_class;
145
146 static GdkWindow *
147 grab_transfer_window_get                        (GtkWidget *widget)
148 {
149     GdkWindow *window;
150     GdkWindowAttr attributes;
151     gint attributes_mask;
152
153     attributes.x = 0;
154     attributes.y = 0;
155     attributes.width = 10;
156     attributes.height = 10;
157     attributes.window_type = GDK_WINDOW_TEMP;
158     attributes.wclass = GDK_INPUT_ONLY;
159     attributes.override_redirect = TRUE;
160     attributes.event_mask = 0;
161
162     attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
163
164     window = gdk_window_new (gtk_widget_get_root_window (widget),
165                              &attributes, attributes_mask);
166     gdk_window_set_user_data (window, widget);
167
168     gdk_window_show (window);
169
170     return window;
171 }
172
173 static void
174 hildon_note_set_property                        (GObject *object,
175                                                  guint prop_id,
176                                                  const GValue *value, 
177                                                  GParamSpec * pspec)
178 {
179     HildonNote *note = HILDON_NOTE (object);
180     HildonNotePrivate *priv;
181     GtkWidget *widget;
182
183     priv = HILDON_NOTE_GET_PRIVATE (note);
184     g_assert (priv);
185
186     switch (prop_id) {
187
188         case PROP_HILDON_NOTE_TYPE:
189             priv->note_n = g_value_get_enum (value);
190             hildon_note_rebuild (note);
191             break;
192
193         case PROP_HILDON_NOTE_DESCRIPTION:
194             if (priv->original_description) 
195                     g_free (priv->original_description);
196             priv->original_description = g_value_dup_string (value);
197
198             gtk_label_set_text (GTK_LABEL (priv->label), priv->original_description);
199             /* FIXME Is the "original_description" used anywhere? */
200             
201             break;
202
203         case PROP_HILDON_NOTE_ICON:
204             gtk_image_set_from_icon_name (GTK_IMAGE (priv->icon), 
205                     g_value_get_string(value), HILDON_ICON_SIZE_BIG_NOTE);
206             break;
207
208         case PROP_HILDON_NOTE_STOCK_ICON:
209             gtk_image_set_from_stock (GTK_IMAGE (priv->icon), 
210                     g_value_get_string (value), HILDON_ICON_SIZE_BIG_NOTE);
211             break;
212
213         case PROP_HILDON_NOTE_PROGRESSBAR:
214             widget = g_value_get_object (value);
215             if (widget != priv->progressbar)
216             {
217                 if (priv->progressbar)
218                     g_object_unref (priv->progressbar);
219
220                 priv->progressbar = widget;
221
222                 if (widget)
223                 {
224                     g_object_ref (widget);
225                     gtk_object_sink (GTK_OBJECT (widget));
226                 }
227
228                 hildon_note_rebuild (note);
229             }
230             break;
231
232         default:
233             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
234             break;
235     }
236 }
237
238 static void
239 hildon_note_get_property                        (GObject *object,
240                                                  guint prop_id, 
241                                                  GValue *value, 
242                                                  GParamSpec *pspec)
243 {
244     HildonNote *note = HILDON_NOTE (object);
245     HildonNotePrivate *priv;
246
247     priv = HILDON_NOTE_GET_PRIVATE (note);
248
249     switch (prop_id) {
250
251         case PROP_HILDON_NOTE_TYPE:
252             g_value_set_enum (value, priv->note_n);
253             break;
254
255         case PROP_HILDON_NOTE_DESCRIPTION:
256             g_value_set_string (value, priv->original_description);
257             break;
258
259         case PROP_HILDON_NOTE_ICON:
260             g_object_get_property (G_OBJECT (priv->icon), "icon-name", value);
261             break;
262
263         case PROP_HILDON_NOTE_STOCK_ICON:
264             g_object_get_property (G_OBJECT (priv->icon), "stock", value);
265             break;
266
267         case PROP_HILDON_NOTE_PROGRESSBAR:
268             g_value_set_object (value, priv->progressbar);
269             break;
270
271         default:
272             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
273             break;
274     }
275 }
276
277 /**
278  * hildon_note_get_type:
279  *
280  * Returns GType for HildonNote.
281  *
282  * Returns: HildonNote type
283  */
284 GType G_GNUC_CONST
285 hildon_note_get_type                            (void)
286 {
287     static GType dialog_type = 0;
288
289     if (! dialog_type) {
290         static const GTypeInfo dialog_info = {
291             sizeof(HildonNoteClass),
292             NULL,       /* base_init */
293             NULL,       /* base_finalize */
294             (GClassInitFunc) hildon_note_class_init,
295             NULL,       /* class_finalize */
296             NULL,       /* class_data */
297             sizeof(HildonNote),
298             0,  /* n_preallocs */
299             (GInstanceInitFunc) hildon_note_init
300         };
301         dialog_type = g_type_register_static (GTK_TYPE_DIALOG,
302                 "HildonNote",
303                 &dialog_info, 0);
304     }
305     return dialog_type;
306 }
307
308 static void 
309 hildon_note_class_init                          (HildonNoteClass *class)
310 {
311     GObjectClass *object_class = G_OBJECT_CLASS (class);
312     GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
313
314     /* set the global parent_class */
315     parent_class = g_type_class_peek_parent (class);
316
317     g_type_class_add_private (class, sizeof (HildonNotePrivate));
318
319     object_class->finalize      = hildon_note_finalize;
320     object_class->set_property  = hildon_note_set_property;
321     object_class->get_property  = hildon_note_get_property;
322     widget_class->button_release_event = hildon_note_button_release;
323     widget_class->map           = hildon_note_map;
324     widget_class->unmap         = hildon_note_unmap;
325     widget_class->realize       = hildon_note_realize;
326
327     g_object_class_install_property (object_class,
328             PROP_HILDON_NOTE_TYPE,
329             g_param_spec_enum ("note-type",
330                 "note type",
331                 "The type of the note dialog",
332                 hildon_note_type_get_type (),
333                 HILDON_NOTE_TYPE_CONFIRMATION,
334                 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
335
336     /**
337      * HildonNote:description:
338      *
339      * Description for the note.
340      */
341     g_object_class_install_property (object_class,
342             PROP_HILDON_NOTE_DESCRIPTION,
343             g_param_spec_string ("description",
344                 "note description",
345                 "The text that appears in the note dialog",
346                 "",
347                 G_PARAM_READWRITE));
348
349     /**
350      * HildonNote:icon:
351      *
352      * Icon for the note.
353      */
354     g_object_class_install_property (object_class,
355             PROP_HILDON_NOTE_ICON,
356             g_param_spec_string ("icon",
357                 "note icon",
358                 "The name of the icon that appears in the note dialog",
359                 "",
360                 G_PARAM_READWRITE));
361
362     /**
363      * HildonNote:stock-icon:
364      *
365      * Stock icon name for the note.
366      */
367     g_object_class_install_property (object_class,
368             PROP_HILDON_NOTE_STOCK_ICON,
369             g_param_spec_string ("stock-icon",
370                 "Stock note icon",
371                 "The stock name of the icon that appears in the note dialog",
372                 "",
373                 G_PARAM_READWRITE));
374
375     /**
376      * HildonNote:progressbar:
377      *
378      * Progressbar for the note (if any).
379      */
380     g_object_class_install_property (object_class,
381             PROP_HILDON_NOTE_PROGRESSBAR,
382             g_param_spec_object ("progressbar",
383                 "Progressbar widget",
384                 "The progressbar that appears in the note dialog",
385                 GTK_TYPE_PROGRESS_BAR,
386                 G_PARAM_READWRITE));
387 }
388
389 static void 
390 hildon_note_init                                (HildonNote *dialog)
391 {
392     HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (dialog);
393     g_assert (priv);
394
395     priv->label = gtk_label_new (NULL);
396     gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE);
397     
398     priv->icon  = gtk_image_new ();
399     priv->close_if_pressed_outside = FALSE;
400     priv->transfer_window = NULL;
401
402     /* Acquire real references to our internal children, since
403        they are not nessecarily packed into container in each
404        layout */
405     g_object_ref_sink (priv->label);
406     g_object_ref_sink (priv->icon);
407
408     gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
409     gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
410 }
411
412
413 static void 
414 hildon_note_finalize                            (GObject *obj_self)
415 {
416     HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (obj_self);
417     g_assert (priv);
418
419     /* FIXME Some of this stuff should be moved to dispose */
420
421     /* Free internal data */
422     if (priv->label)
423         g_object_unref (priv->label);
424
425     if (priv->icon)
426         g_object_unref (priv->icon);
427
428     if (priv->progressbar)
429         g_object_unref (priv->progressbar);
430
431     if (priv->original_description)
432         g_free (priv->original_description);
433
434     G_OBJECT_CLASS (parent_class)->finalize (obj_self);
435 }
436
437
438 static gboolean
439 hildon_note_button_release                      (GtkWidget *widget,
440                                                  GdkEventButton *event)
441 {
442     int x, y;
443     gboolean info_note, released_outside;
444     HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget);
445
446     gdk_window_get_position (widget->window, &x, &y);
447
448     /* Whether the button has been released outside the widget */
449     released_outside = (event->x_root < x || event->x_root > x + widget->allocation.width ||
450                         event->y_root < y || event->y_root > y + widget->allocation.height);
451
452     /* Information notes are also closed by tapping on them */
453     info_note = (priv->note_n == HILDON_NOTE_TYPE_INFORMATION ||
454                  priv->note_n == HILDON_NOTE_TYPE_INFORMATION_THEME);
455
456     if (info_note || (released_outside && priv->close_if_pressed_outside)) {
457         gtk_dialog_response (GTK_DIALOG (widget), GTK_RESPONSE_CANCEL);
458     }
459
460     if (GTK_WIDGET_CLASS (parent_class)->button_release_event) {
461         return GTK_WIDGET_CLASS (parent_class)->button_release_event (widget, event);
462     } else {
463         return FALSE;
464     }
465 }
466
467 static void
468 hildon_note_map                                 (GtkWidget *widget)
469 {
470     HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget);
471     g_assert (priv);
472
473     /* Map the window */
474     GTK_WIDGET_CLASS (parent_class)->map (widget);
475
476     if (priv->transfer_window == NULL && priv->close_if_pressed_outside) {
477         gboolean has_grab = FALSE;
478
479         priv->transfer_window = grab_transfer_window_get (widget);
480
481         if (gdk_pointer_grab (priv->transfer_window, TRUE,
482                               GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
483                               GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
484                               GDK_POINTER_MOTION_MASK, NULL, NULL,
485                               GDK_CURRENT_TIME) == GDK_GRAB_SUCCESS) {
486             if (gdk_keyboard_grab (priv->transfer_window, TRUE,
487                                    GDK_CURRENT_TIME) == GDK_GRAB_SUCCESS) {
488                 has_grab = TRUE;
489             } else {
490                 gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
491                                             GDK_CURRENT_TIME);
492             }
493         }
494
495         if (has_grab) {
496             gtk_grab_add (widget);
497         } else {
498             gdk_window_destroy (priv->transfer_window);
499             priv->transfer_window = NULL;
500         }
501     }
502 }
503
504 static void
505 hildon_note_unmap                               (GtkWidget *widget)
506 {
507     HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget);
508     g_assert (priv);
509
510     if (priv->transfer_window != NULL) {
511         /* Remove the grab */
512         gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
513                                     GDK_CURRENT_TIME);
514         gtk_grab_remove (widget);
515
516         /* Destroy the transfer window */
517         gdk_window_destroy (priv->transfer_window);
518         priv->transfer_window = NULL;
519     }
520 }
521
522 static void
523 hildon_note_realize                             (GtkWidget *widget)
524 {
525     GdkDisplay *display;
526     Atom atom;
527     const gchar *notification_type;
528     HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget);
529     g_assert (priv);
530
531     /* Make widget->window accessible */
532     GTK_WIDGET_CLASS (parent_class)->realize (widget);
533
534     /* Border only, no titlebar */
535     gdk_window_set_decorations (widget->window, GDK_DECOR_BORDER);
536
537     /* Because ESD is synchronous, we wish to play sound after the
538        note is already on screen to avoid blocking its appearance */
539     if (priv->sound_signal_handler == 0)
540         priv->sound_signal_handler = g_signal_connect_after(widget, 
541                 "expose-event", G_CALLBACK (sound_handling), NULL);
542
543     /* We use special hint to turn the note into information notification. */
544     gdk_window_set_type_hint (widget->window, GDK_WINDOW_TYPE_HINT_NOTIFICATION);
545
546     /* Set the _HILDON_NOTIFICATION_TYPE property so Matchbox places the window correctly */
547     display = gdk_drawable_get_display (widget->window);
548     atom = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_NOTIFICATION_TYPE");
549
550     if (priv->note_n == HILDON_NOTE_TYPE_INFORMATION ||
551         priv->note_n == HILDON_NOTE_TYPE_INFORMATION_THEME) {
552         notification_type = "_HILDON_NOTIFICATION_TYPE_INFO";
553     } else {
554         notification_type = "_HILDON_NOTIFICATION_TYPE_CONFIRMATION";
555     }
556
557     XChangeProperty (GDK_WINDOW_XDISPLAY (widget->window), GDK_WINDOW_XID (widget->window),
558                      atom, XA_STRING, 8, PropModeReplace, (guchar *) notification_type,
559                      strlen (notification_type));
560 }
561
562 /* Helper function for removing a widget from it's container.
563    we own a separate reference to each object we try to unpack,
564    so extra referencing is not needed. */
565 static void 
566 unpack_widget                                   (GtkWidget *widget)
567 {
568     g_assert (widget == NULL || GTK_IS_WIDGET (widget));
569
570     if (widget && widget->parent)
571         gtk_container_remove (GTK_CONTAINER (widget->parent), widget);
572 }
573
574 static void
575 hildon_note_rebuild                             (HildonNote *note)
576 {
577     GtkDialog *dialog;
578     HildonNotePrivate *priv;
579     gboolean IsHorizontal = TRUE;
580
581     g_assert (HILDON_IS_NOTE (note));
582
583     priv = HILDON_NOTE_GET_PRIVATE (note);
584     g_assert (priv);
585
586     dialog = GTK_DIALOG (note);
587
588     /* Reuse exiting content widgets for new layout */
589     unpack_widget (priv->label);
590     unpack_widget (priv->icon);
591     unpack_widget (priv->progressbar);
592
593     /* Destroy old layout and buttons */
594     if (priv->box) {
595         gtk_widget_destroy (priv->box);
596         priv->box = NULL;
597     }
598     if (priv->okButton) {
599         gtk_widget_destroy (priv->okButton);
600         priv->okButton = NULL;
601     }
602     if (priv->cancelButton) {
603         gtk_widget_destroy (priv->cancelButton);
604         priv->cancelButton = NULL;
605     }
606
607     /* By default the note won't be closed when pressing outside */
608     priv->close_if_pressed_outside = FALSE;
609
610     /* Add needed buttons and images for each note type */
611     switch (priv->note_n)
612     {
613         case HILDON_NOTE_TYPE_CONFIRMATION:
614             priv->okButton = gtk_dialog_add_button (dialog,
615                     _("ecdg_bd_confirmation_note_ok"), GTK_RESPONSE_OK);
616             priv->cancelButton = gtk_dialog_add_button (dialog,
617                     _("ecdg_bd_confirmation_note_cancel"), GTK_RESPONSE_CANCEL);
618
619             /* Fall through */
620         case HILDON_NOTE_TYPE_CONFIRMATION_BUTTON:
621             gtk_image_set_from_icon_name (GTK_IMAGE (priv->icon),
622                     HILDON_NOTE_CONFIRMATION_ICON, 
623                     HILDON_ICON_SIZE_BIG_NOTE);
624             break;
625
626         case HILDON_NOTE_TYPE_INFORMATION_THEME:
627         case HILDON_NOTE_TYPE_INFORMATION:
628             priv->close_if_pressed_outside = TRUE;
629             gtk_image_set_from_icon_name (GTK_IMAGE (priv->icon),
630                     HILDON_NOTE_INFORMATION_ICON,
631                     HILDON_ICON_SIZE_BIG_NOTE);
632             break;
633
634         case HILDON_NOTE_TYPE_PROGRESSBAR:
635             priv->cancelButton = gtk_dialog_add_button (dialog,
636                     _("ecdg_bd_cancel_note_cancel"), GTK_RESPONSE_CANCEL);
637             IsHorizontal = FALSE;
638             break;
639
640         default:
641             break;
642     }
643
644     if (IsHorizontal) {
645         /* Pack item with label horizontally */
646         priv->box = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
647         gtk_container_add (GTK_CONTAINER (dialog->vbox), priv->box);
648
649         if (priv->icon) {
650             GtkWidget *alignment = gtk_alignment_new (0, 0, 0, 0);
651
652             gtk_box_pack_start (GTK_BOX (priv->box), alignment, FALSE, FALSE, 0);
653             gtk_container_add (GTK_CONTAINER (alignment), priv->icon);
654         }
655         gtk_box_pack_start (GTK_BOX (priv->box), priv->label, TRUE, TRUE, 0);
656
657     } else {
658         /* Pack item with label vertically */
659         priv->box = gtk_vbox_new (FALSE, HILDON_MARGIN_DOUBLE);
660         gtk_container_add (GTK_CONTAINER (dialog->vbox), priv->box);
661         gtk_box_pack_start (GTK_BOX (priv->box), priv->label, TRUE, TRUE, 0);
662
663         if (priv->progressbar)
664             gtk_box_pack_start (GTK_BOX (priv->box), priv->progressbar, FALSE, FALSE, 0);
665     }
666
667     gtk_widget_show_all (priv->box);
668 }
669
670 /**
671  * hildon_note_new_confirmation_add_buttons:
672  * @parent: the parent window. The X window ID of the parent window
673  *   has to be the same as the X window ID of the application. This is
674  *   important so that the window manager could handle the windows
675  *   correctly.
676  *   In GTK the X window ID can be checked using
677  *   GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
678  * @description: the message to confirm
679  * @Varargs: arguments pairs for new buttons(label and return value). 
680  *   Terminate the list with %NULL value.
681  * 
682  * Create a new confirmation note with custom buttons. Confirmation
683  * note has a text and any number of buttons. It's important to note
684  * that even though the name of the function might suggest, the
685  * default ok/cancel buttons are not appended but you have to provide
686  * all of the buttons.
687  *
688  * FIXME: This doc seems to be wrong, the two buttons aren't added so
689  * it would only contain the "additional" buttons? However, changing
690  * this would break those applications that rely on current behaviour.
691  *
692  * Returns: A #GtkWidget pointer of the note
693  */
694 GtkWidget*
695 hildon_note_new_confirmation_add_buttons        (GtkWindow *parent,
696                                                  const gchar *description,
697                                                  ...)
698 {
699     va_list args;
700     char *message;
701     int value;
702
703     g_return_val_if_fail (description != NULL, NULL);
704
705     GtkWidget *conf_note =
706         g_object_new (HILDON_TYPE_NOTE,
707                 "note-type", HILDON_NOTE_TYPE_CONFIRMATION_BUTTON,
708                 "description", description,
709                 "icon", HILDON_NOTE_CONFIRMATION_ICON, 
710                 NULL);
711
712     if (parent != NULL)
713         gtk_window_set_transient_for (GTK_WINDOW (conf_note), parent);
714
715     /* Add the buttons from varargs */
716     va_start(args, description);
717
718     while (TRUE) {
719         message = va_arg (args, char *);
720
721         if (! message) {
722             break;
723         }
724         value = va_arg (args, int);
725
726         gtk_dialog_add_button (GTK_DIALOG (conf_note), message, value);
727     }
728
729     va_end (args);
730
731     return conf_note;
732 }
733
734
735 /**
736  * hildon_note_new_confirmation:
737  * @parent: the parent window. The X window ID of the parent window
738  *   has to be the same as the X window ID of the application. This is
739  *   important so that the window manager could handle the windows
740  *   correctly. In GTK the X window ID can be checked using
741  *   GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
742  * @description: the message to confirm
743  * 
744  * Create a new confirmation note. Confirmation note has text (description)
745  * that you specify, two buttons and a default confirmation stock icon.
746  *
747  * Returns: a #GtkWidget pointer of the note
748  */
749 GtkWidget*
750 hildon_note_new_confirmation                    (GtkWindow *parent,
751                                                  const gchar *description)
752 {
753     return hildon_note_new_confirmation_with_icon_name
754         (parent, description, HILDON_NOTE_CONFIRMATION_ICON);
755 }
756
757 /**
758  * hildon_note_new_confirmation_with_icon_name:
759  * @parent: the parent window. The X window ID of the parent window
760  *   has to be the same as the X window ID of the application. This is
761  *   important so that the window manager could handle the windows
762  *   correctly. In GTK the X window ID can be checked using
763  *   GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
764  * @description: the message to confirm
765  * @icon_name: icon to be displayed. If NULL, default icon is used.
766  * 
767  * Create a new confirmation note. Confirmation note has text(description) 
768  * that you specify, two buttons and an icon.
769  *
770  * Returns: a #GtkWidget pointer of the note
771  */
772 GtkWidget*
773 hildon_note_new_confirmation_with_icon_name     (GtkWindow *parent,
774                                                  const gchar *description,
775                                                  const gchar *icon_name)
776 {
777     GtkWidget *dialog = NULL;
778
779     g_return_val_if_fail (description != NULL, NULL);
780
781     dialog = g_object_new (HILDON_TYPE_NOTE,
782             "note-type",
783             HILDON_NOTE_TYPE_CONFIRMATION,
784             "description", description, "icon",
785             icon_name, NULL);
786
787     if (parent != NULL)
788         gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
789
790     return dialog;
791 }
792
793 /**
794  * hildon_note_new_information:
795  * @parent: the parent window. The X window ID of the parent window
796  *   has to be the same as the X window ID of the application. This is
797  *   important so that the window manager could handle the windows
798  *   correctly. In GTK the X window ID can be checked using
799  *   GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
800  * @description: the message to confirm
801  * 
802  * Create a new information note. Information note has a text(description) 
803  * that you specify, an OK button and an icon.
804  * 
805  * Returns: a #GtkWidget pointer of the note
806  */
807 GtkWidget*
808 hildon_note_new_information                     (GtkWindow *parent,
809                                                  const gchar *description)
810 {
811     return hildon_note_new_information_with_icon_name
812         (parent, description, HILDON_NOTE_INFORMATION_ICON);
813 }
814
815 /**
816  * hildon_note_new_information_with_icon_name:
817  * @parent: the parent window. The X window ID of the parent window
818  *   has to be the same as the X window ID of the application. This is
819  *   important so that the window manager could handle the windows
820  *   correctly. In GTK the X window ID can be checked using
821  *   GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
822  * @description: the message to confirm
823  * @icon_name: icon to be displayed. If NULL, default icon is used.
824  * 
825  * Create a new information note. Information note has text(description) 
826  * that you specify, an OK button and an icon.
827  * 
828  * Returns: a #GtkWidget pointer of the note
829  */
830 GtkWidget*
831 hildon_note_new_information_with_icon_name      (GtkWindow * parent,
832                                                  const gchar *description,
833                                                  const gchar *icon_name)
834 {
835     GtkWidget *dialog = NULL;
836
837     g_return_val_if_fail (description != NULL, NULL);
838     g_return_val_if_fail (icon_name != NULL, NULL);
839
840     dialog = g_object_new (HILDON_TYPE_NOTE,
841             "note-type",
842             HILDON_NOTE_TYPE_INFORMATION_THEME,
843             "description", description,
844             "icon", icon_name, NULL);
845
846     if (parent != NULL)
847         gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
848
849     return dialog;
850 }
851
852 /* FIXME This documentation string LIES! */
853
854 /**
855  * hildon_note_new_cancel_with_progress_bar:
856  * @parent: the parent window. The X window ID of the parent window
857  *   has to be the same as the X window ID of the application. This is
858  *   important so that the window manager could handle the windows
859  *   correctly. In GTK the X window ID can be checked using
860  *   GDK_WINDOW_XID(GTK_WIDGET(parent)->window).
861  * @description: the action to cancel
862  * @progressbar: a pointer to #GtkProgressBar to be filled with the
863  *   progressbar assigned to this note. Use this to set the fraction of
864  *   progressbar done. This parameter can be %NULL as well, in which
865  *   case plain text cancel note appears.
866  *
867  * Create a new cancel note with a progress bar. Cancel note has 
868  * text(description) that you specify, a Cancel button and a progress bar.
869  *
870  * Returns: a #GtkDialog. Use this to get rid of this note when you
871  *   no longer need it.
872  */
873 GtkWidget*
874 hildon_note_new_cancel_with_progress_bar        (GtkWindow *parent,
875                                                  const gchar *description,
876                                                  GtkProgressBar *progressbar)
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_PROGRESSBAR,
885             "description", description,
886             "progressbar",
887             progressbar, NULL);
888
889     if (parent != NULL)
890         gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
891
892     return dialog;
893 }
894
895
896 /**
897  * hildon_note_set_button_text:
898  * @note: a #HildonNote
899  * @text: sets the button text and if there is two buttons in dialog, 
900  *   the button texts will be &lt;text&gt;, "Cancel".  
901  *
902  * Sets the button text to be used by the hildon_note widget.
903  */
904 void 
905 hildon_note_set_button_text                     (HildonNote *note, 
906                                                  const gchar *text)
907 {
908     HildonNotePrivate *priv;
909
910     g_return_if_fail (HILDON_IS_NOTE (note));
911
912     priv = HILDON_NOTE_GET_PRIVATE (HILDON_NOTE (note));
913     g_assert (priv);
914
915     if (priv->okButton) {
916         gtk_button_set_label (GTK_BUTTON (priv->okButton), text);
917         gtk_button_set_label (GTK_BUTTON (priv->cancelButton),
918                 _("ecdg_bd_confirmation_note_cancel"));
919     } else {
920         gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text);
921     }
922 }
923
924 /**
925  * hildon_note_set_button_texts:
926  * @note: a #HildonNote
927  * @text_ok: the new text of the default OK button
928  * @text_cancel: the new text of the default cancel button 
929  *
930  * Sets the button texts to be used by this hildon_note widget.
931  */
932 void 
933 hildon_note_set_button_texts                    (HildonNote *note,
934                                                  const gchar *text_ok,
935                                                  const gchar *text_cancel)
936 {
937     HildonNotePrivate *priv;
938
939     g_return_if_fail (HILDON_IS_NOTE (note));
940
941     priv = HILDON_NOTE_GET_PRIVATE (HILDON_NOTE (note));
942     g_assert (priv);
943
944     if (priv->okButton) {
945         gtk_button_set_label (GTK_BUTTON (priv->okButton), text_ok);
946         gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text_cancel);
947     } else {
948         gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text_cancel);
949     }
950 }
951
952 /* We play a system sound when the note comes visible */
953 static gboolean
954 sound_handling                                  (GtkWidget *widget, 
955                                                  GdkEventExpose *event, 
956                                                  gpointer data)
957 {
958     HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget);
959     g_assert (priv);
960
961     g_signal_handler_disconnect (widget, priv->sound_signal_handler);
962
963     priv->sound_signal_handler = 0;
964
965     switch (priv->note_n)
966     {
967         case HILDON_NOTE_TYPE_INFORMATION:
968         case HILDON_NOTE_TYPE_INFORMATION_THEME:
969             hildon_play_system_sound (INFORMATION_SOUND_PATH);
970             break;
971
972         case HILDON_NOTE_TYPE_CONFIRMATION:
973         case HILDON_NOTE_TYPE_CONFIRMATION_BUTTON:
974             hildon_play_system_sound (CONFIRMATION_SOUND_PATH);
975             break;
976
977         default:
978             break;
979     };
980
981     return FALSE;
982 }