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