Emit HildonAppMenu::changed when menu items change visibility
[hildon] / hildon / hildon-edit-toolbar.c
1 /*
2  * This file is a part of hildon
3  *
4  * Copyright (C) 2008, 2009 Nokia Corporation, all rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser Public License as published by
8  * the Free Software Foundation; version 2 of the license.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser Public License for more details.
14  *
15  */
16
17 /**
18  * SECTION:hildon-edit-toolbar
19  * @short_description: Toolbar for edition of user data.
20  *
21  * The #HildonEditToolbar is a toolbar which contains a label and two
22  * buttons, one of them being an arrow pointing backwards.
23  *
24  * The label is a description of the action that the user is supposed
25  * to do. The button is to be pressed when the user completes the
26  * action. The arrow is used to go back to the previous view
27  * discarding any changes.
28  *
29  * Note that those widgets don't do anything themselves by default. To
30  * actually peform actions the developer must provide callbacks for
31  * them.
32  *
33  * To add a #HildonEditToolbar to a window use
34  * hildon_window_set_edit_toolbar().
35  *
36  * This toolbar is meant to replace the window title bar by emulating
37  * its appearance, so you should put the window in full screen mode
38  * with gtk_window_fullscreen().
39  *
40  * <example>
41  * <title>HildonEditToolbar example</title>
42  * <programlisting>
43  * GtkWidget *window;
44  * GtkWidget *toolbar;
45  * // Declare more widgets here ...
46  * <!-- -->
47  * window = hildon_stackable_window_new ();
48  * toolbar = hildon_edit_toolbar_new_with_text ("Choose items to delete", "Delete");
49  * // Create more widgets here ...
50  * <!-- -->
51  * // Add toolbar to window
52  * hildon_window_set_edit_toolbar (HILDON_WINDOW (window), HILDON_EDIT_TOOLBAR (toolbar));
53  * <!-- -->
54  * // Add other widgets ...
55  * <!-- -->
56  * g_signal_connect (toolbar, "button-clicked", G_CALLBACK (delete_button_clicked), someparameter);
57  * g_signal_connect_swapped (toolbar, "arrow-clicked", G_CALLBACK (gtk_widget_destroy), window);
58  * <!-- -->
59  * gtk_widget_show_all (window);
60  * gtk_window_fullscreen (GTK_WINDOW (window));
61  * </programlisting>
62  * </example>
63  */
64
65 #include                                        "hildon-edit-toolbar.h"
66 #include                                        "hildon-edit-toolbar-private.h"
67 #include                                        "hildon-private.h"
68 #include                                        "hildon-gtk.h"
69
70 G_DEFINE_TYPE                                   (HildonEditToolbar, hildon_edit_toolbar, GTK_TYPE_HBOX);
71
72 #define                                         TOOLBAR_LEFT_PADDING 24
73 #define                                         TOOLBAR_RIGHT_PADDING 8
74
75 #define                                         HILDON_EDIT_TOOLBAR_ANIMATION_FRAMERATE ((float)1000/150)
76 #define                                         HILDON_EDIT_TOOLBAR_ANIMATION_TMPL "indicator_update%d"
77 #define                                         HILDON_EDIT_TOOLBAR_ANIMATION_NFRAMES 8
78
79 #define                                         HILDON_EDIT_TOOLBAR_GET_PRIVATE(obj) \
80                                                 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
81                                                 HILDON_TYPE_EDIT_TOOLBAR, HildonEditToolbarPrivate));
82
83 typedef struct                                  _HildonEditToolbarPrivate HildonEditToolbarPrivate;
84
85 struct                                          _HildonEditToolbarPrivate
86 {
87     GtkBox *hbox;
88     GtkLabel *label;
89     GtkWidget *animation;
90     GtkButton *button;
91     GtkButton *arrow;
92 };
93
94 enum {
95     BUTTON_CLICKED,
96     ARROW_CLICKED,
97     N_SIGNALS
98 };
99
100 static guint                                    toolbar_signals [N_SIGNALS] = { 0 };
101
102 static void
103 hildon_edit_toolbar_style_set                   (GtkWidget *widget,
104                                                  GtkStyle  *previous_style)
105 {
106     guint width, height;
107     HildonEditToolbarPrivate *priv = HILDON_EDIT_TOOLBAR_GET_PRIVATE (widget);
108
109     if (GTK_WIDGET_CLASS (hildon_edit_toolbar_parent_class)->style_set)
110         GTK_WIDGET_CLASS (hildon_edit_toolbar_parent_class)->style_set (widget, previous_style);
111
112     gtk_widget_style_get (widget,
113                           "arrow-width", &width,
114                           "arrow-height", &height,
115                           NULL);
116
117     gtk_widget_set_size_request (GTK_WIDGET (priv->arrow), width, height);
118 }
119
120 static gboolean
121 hildon_edit_toolbar_expose                      (GtkWidget      *widget,
122                                                  GdkEventExpose *event)
123 {
124     if (GTK_WIDGET_DRAWABLE (widget)) {
125         gtk_paint_flat_box (widget->style,
126                             widget->window,
127                             GTK_STATE_NORMAL,
128                             GTK_SHADOW_NONE,
129                             &event->area, widget, "edit-toolbar",
130                             widget->allocation.x, widget->allocation.y,
131                             widget->allocation.width, widget->allocation.height);
132     }
133
134     if (GTK_WIDGET_CLASS (hildon_edit_toolbar_parent_class)->expose_event)
135         return GTK_WIDGET_CLASS (hildon_edit_toolbar_parent_class)->expose_event (widget, event);
136
137     return FALSE;
138 }
139
140 static void
141 hildon_edit_toolbar_class_init                  (HildonEditToolbarClass *klass)
142 {
143     GObjectClass *gobject_class = (GObjectClass *) klass;
144     GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
145
146     widget_class->style_set = hildon_edit_toolbar_style_set;
147     widget_class->expose_event = hildon_edit_toolbar_expose;
148
149     g_type_class_add_private (klass, sizeof (HildonEditToolbarPrivate));
150
151     gtk_widget_class_install_style_property (
152         widget_class,
153         g_param_spec_uint (
154             "arrow-width",
155             "Width of the arrow button",
156             "Width of the arrow button",
157             0, G_MAXUINT, 112,
158             G_PARAM_READABLE));
159
160     gtk_widget_class_install_style_property (
161         widget_class,
162         g_param_spec_uint (
163             "arrow-height",
164             "Height of the arrow button",
165             "Height of the arrow button",
166             0, G_MAXUINT, 56,
167             G_PARAM_READABLE));
168
169     /**
170      * HildonEditToolbar::button-clicked:
171      * @widget: the object which received the signal.
172      *
173      * Emitted when the toolbar button has been activated (pressed and released).
174      *
175      * Since: 2.2
176      */
177     toolbar_signals[BUTTON_CLICKED] =
178         g_signal_new ("button_clicked",
179                       G_OBJECT_CLASS_TYPE (gobject_class),
180                       G_SIGNAL_RUN_FIRST,
181                       0, NULL, NULL,
182                       g_cclosure_marshal_VOID__VOID,
183                       G_TYPE_NONE, 0);
184
185     /**
186      * HildonEditToolbar::arrow-clicked:
187      * @widget: the object which received the signal.
188      *
189      * Emitted when the toolbar back button (arrow) has been activated
190      * (pressed and released).
191      *
192      * Since: 2.2
193      */
194     toolbar_signals[ARROW_CLICKED] =
195         g_signal_new ("arrow_clicked",
196                       G_OBJECT_CLASS_TYPE (gobject_class),
197                       G_SIGNAL_RUN_FIRST,
198                       0, NULL, NULL,
199                       g_cclosure_marshal_VOID__VOID,
200                       G_TYPE_NONE, 0);
201 }
202
203 static void
204 button_clicked_cb                               (GtkButton *self,
205                                                  HildonEditToolbar *toolbar)
206 {
207     g_signal_emit (toolbar, toolbar_signals[BUTTON_CLICKED], 0);
208 }
209
210 static void
211 arrow_clicked_cb                                (GtkButton *self,
212                                                  HildonEditToolbar *toolbar)
213 {
214     g_signal_emit (toolbar, toolbar_signals[ARROW_CLICKED], 0);
215 }
216
217 static void
218 hildon_edit_toolbar_init                        (HildonEditToolbar *self)
219 {
220     HildonEditToolbarPrivate *priv = HILDON_EDIT_TOOLBAR_GET_PRIVATE (self);
221     GtkWidget *separator;
222     GtkAlignment *align;
223     GtkBox *hbox = GTK_BOX (self);
224
225     priv->hbox = GTK_BOX (gtk_hbox_new (FALSE, 0));
226     align = GTK_ALIGNMENT (gtk_alignment_new (0, 0.5, 1, 1));
227     priv->label = GTK_LABEL (gtk_label_new (NULL));
228     priv->animation = hildon_private_create_animation (
229         HILDON_EDIT_TOOLBAR_ANIMATION_FRAMERATE,
230         HILDON_EDIT_TOOLBAR_ANIMATION_TMPL,
231         HILDON_EDIT_TOOLBAR_ANIMATION_NFRAMES);
232     priv->button = GTK_BUTTON (hildon_gtk_button_new (HILDON_SIZE_AUTO));
233     separator = gtk_vseparator_new ();
234     priv->arrow = GTK_BUTTON (gtk_button_new ());
235
236     g_object_set (priv->button, "can-focus", FALSE, NULL);
237     g_object_set (priv->arrow, "can-focus", FALSE, NULL);
238
239     g_signal_connect (priv->button, "clicked", G_CALLBACK (button_clicked_cb), self);
240     g_signal_connect (priv->arrow, "clicked", G_CALLBACK (arrow_clicked_cb), self);
241
242     gtk_box_set_spacing (hbox, 0);
243     gtk_alignment_set_padding (align, 0, 0, TOOLBAR_LEFT_PADDING, TOOLBAR_RIGHT_PADDING);
244
245     gtk_widget_set_name (GTK_WIDGET (self), "toolbar-edit-mode");
246     gtk_widget_set_name (GTK_WIDGET (priv->arrow), "hildon-edit-toolbar-arrow");
247
248     gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET (priv->hbox));
249     gtk_box_pack_start (priv->hbox, GTK_WIDGET (priv->label), TRUE, TRUE, 0);
250     gtk_box_pack_start (priv->hbox, priv->animation, TRUE, TRUE, 10);
251     gtk_box_pack_start (priv->hbox, GTK_WIDGET (priv->button), FALSE, FALSE, 0);
252
253     gtk_widget_set_no_show_all (priv->animation, TRUE);
254
255     gtk_box_pack_start (hbox, GTK_WIDGET (align), TRUE, TRUE, 0);
256     gtk_box_pack_start (hbox, separator, FALSE, FALSE, 0);
257     gtk_box_pack_start (hbox, GTK_WIDGET (priv->arrow), FALSE, FALSE, 0);
258
259     gtk_misc_set_alignment (GTK_MISC (priv->label), 0, 0.5);
260     gtk_misc_set_alignment (GTK_MISC (priv->animation), 0, 0.5);
261
262     gtk_widget_show_all (GTK_WIDGET (align));
263     gtk_widget_show_all (separator);
264     gtk_widget_show_all (GTK_WIDGET (priv->arrow));
265 }
266
267 /**
268  * hildon_edit_toolbar_set_label:
269  * @toolbar: a #HildonEditToolbar
270  * @label: a new text for the toolbar label
271  *
272  * Sets the label of @toolbar to @label. This will clear any
273  * previously set value.
274  *
275  * Since: 2.2
276  */
277 void
278 hildon_edit_toolbar_set_label                   (HildonEditToolbar *toolbar,
279                                                  const gchar       *label)
280 {
281     HildonEditToolbarPrivate *priv;
282     g_return_if_fail (HILDON_IS_EDIT_TOOLBAR (toolbar));
283     priv = HILDON_EDIT_TOOLBAR_GET_PRIVATE (toolbar);
284     gtk_label_set_text (priv->label, label);
285 }
286
287 /**
288  * hildon_edit_toolbar_set_button_label:
289  * @toolbar: a #HildonEditToolbar
290  * @label: a new text for the label of the toolbar button
291  *
292  * Sets the label of the toolbar button to @label. This will clear any
293  * previously set value.
294  *
295  * Since: 2.2
296  */
297 void
298 hildon_edit_toolbar_set_button_label            (HildonEditToolbar *toolbar,
299                                                  const gchar       *label)
300 {
301     HildonEditToolbarPrivate *priv;
302     g_return_if_fail (HILDON_IS_EDIT_TOOLBAR (toolbar));
303     priv = HILDON_EDIT_TOOLBAR_GET_PRIVATE (toolbar);
304     gtk_button_set_label (priv->button, label);
305 }
306
307 /**
308  * hildon_edit_toolbar_new:
309  *
310  * Creates a new #HildonEditToolbar.
311  *
312  * Returns: a new #HildonEditToolbar
313  *
314  * Since: 2.2
315  */
316 GtkWidget *
317 hildon_edit_toolbar_new                         (void)
318 {
319     return g_object_new (HILDON_TYPE_EDIT_TOOLBAR, NULL);
320 }
321
322 /**
323  * hildon_edit_toolbar_new_with_text:
324  * @label: Text for the toolbar label.
325  * @button: Text for the toolbar button.
326  *
327  * Creates a new #HildonEditToolbar, with the toolbar label set to
328  * @label and the button label set to @button.
329  *
330  * Returns: a new #HildonEditToolbar
331  *
332  * Since: 2.2
333  */
334 GtkWidget *
335 hildon_edit_toolbar_new_with_text               (const gchar *label,
336                                                  const gchar *button)
337 {
338     GtkWidget *toolbar = g_object_new (HILDON_TYPE_EDIT_TOOLBAR, NULL);
339
340     hildon_edit_toolbar_set_label (HILDON_EDIT_TOOLBAR (toolbar), label);
341     hildon_edit_toolbar_set_button_label (HILDON_EDIT_TOOLBAR (toolbar), button);
342
343     return toolbar;
344 }
345
346 void G_GNUC_INTERNAL
347 hildon_edit_toolbar_set_progress_indicator      (HildonEditToolbar *toolbar,
348                                                  gboolean           show)
349 {
350     HildonEditToolbarPrivate *priv;
351     g_return_if_fail (HILDON_IS_EDIT_TOOLBAR (toolbar));
352     priv = HILDON_EDIT_TOOLBAR_GET_PRIVATE (toolbar);
353     if (show) {
354         gtk_widget_show (priv->animation);
355         gtk_box_set_child_packing (priv->hbox, GTK_WIDGET (priv->label),
356                                    FALSE, FALSE, 0, GTK_PACK_START);
357     } else {
358         gtk_box_set_child_packing (priv->hbox, GTK_WIDGET (priv->label),
359                                    TRUE, TRUE, 0, GTK_PACK_START);
360         gtk_widget_hide (priv->animation);
361     }
362 }