9b8d9107d87844ca5bba70f219c37ffeba075115
[hildon] / hildon / hildon-edit-toolbar.c
1 /*
2  * This file is a part of hildon
3  *
4  * Copyright (C) 2008 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  * <example>
37  * <title>HildonEditToolbar example</title>
38  * <programlisting>
39  * GtkWidget *window;
40  * GtkWidget *toolbar;
41  * // Declare more widgets here ...
42  * <!-- -->
43  * window = hildon_stackable_window_new ();
44  * toolbar = hildon_edit_toolbar_new_with_text ("Choose items to delete", "Delete");
45  * // Create more widgets here ...
46  * <!-- -->
47  * // Add toolbar to window
48  * hildon_window_set_edit_toolbar (HILDON_WINDOW (window), HILDON_EDIT_TOOLBAR (toolbar));
49  * <!-- -->
50  * // Add other widgets ...
51  * <!-- -->
52  * g_signal_connect (toolbar, "button-clicked", G_CALLBACK (delete_button_clicked), someparameter);
53  * g_signal_connect_swapped (toolbar, "arrow-clicked", G_CALLBACK (gtk_widget_destroy), window);
54  * <!-- -->
55  * gtk_widget_show_all (window);
56  * gtk_window_fullscreen (GTK_WINDOW (window));
57  * </programlisting>
58  * </example>
59  */
60
61 #include                                        "hildon-edit-toolbar.h"
62 #include                                        "hildon-edit-toolbar-private.h"
63 #include                                        "hildon-private.h"
64 #include                                        "hildon-gtk.h"
65
66 G_DEFINE_TYPE                                   (HildonEditToolbar, hildon_edit_toolbar, GTK_TYPE_HBOX);
67
68 #define                                         TOOLBAR_LEFT_PADDING 24
69 #define                                         TOOLBAR_RIGHT_PADDING 8
70
71 #define                                         HILDON_EDIT_TOOLBAR_ANIMATION_FRAMERATE ((float)1000/150)
72 #define                                         HILDON_EDIT_TOOLBAR_ANIMATION_TMPL "indicator_update%d"
73 #define                                         HILDON_EDIT_TOOLBAR_ANIMATION_NFRAMES 8
74
75 #define                                         HILDON_EDIT_TOOLBAR_GET_PRIVATE(obj) \
76                                                 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
77                                                 HILDON_TYPE_EDIT_TOOLBAR, HildonEditToolbarPrivate));
78
79 typedef struct                                  _HildonEditToolbarPrivate HildonEditToolbarPrivate;
80
81 struct                                          _HildonEditToolbarPrivate
82 {
83     GtkBox *hbox;
84     GtkLabel *label;
85     GtkWidget *animation;
86     GtkButton *button;
87     GtkButton *arrow;
88 };
89
90 enum {
91     BUTTON_CLICKED,
92     ARROW_CLICKED,
93     N_SIGNALS
94 };
95
96 static guint                                    toolbar_signals [N_SIGNALS] = { 0 };
97
98 static void
99 hildon_edit_toolbar_style_set                   (GtkWidget *widget,
100                                                  GtkStyle  *previous_style)
101 {
102     guint width, height;
103     HildonEditToolbarPrivate *priv = HILDON_EDIT_TOOLBAR_GET_PRIVATE (widget);
104
105     if (GTK_WIDGET_CLASS (hildon_edit_toolbar_parent_class)->style_set)
106         GTK_WIDGET_CLASS (hildon_edit_toolbar_parent_class)->style_set (widget, previous_style);
107
108     gtk_widget_style_get (widget,
109                           "arrow-width", &width,
110                           "arrow-height", &height,
111                           NULL);
112
113     gtk_widget_set_size_request (GTK_WIDGET (priv->arrow), width, height);
114 }
115
116 static gboolean
117 hildon_edit_toolbar_expose                      (GtkWidget      *widget,
118                                                  GdkEventExpose *event)
119 {
120     if (GTK_WIDGET_DRAWABLE (widget)) {
121         gtk_paint_flat_box (widget->style,
122                             widget->window,
123                             GTK_STATE_NORMAL,
124                             GTK_SHADOW_NONE,
125                             &event->area, widget, "edit-toolbar",
126                             widget->allocation.x, widget->allocation.y,
127                             widget->allocation.width, widget->allocation.height);
128     }
129
130     if (GTK_WIDGET_CLASS (hildon_edit_toolbar_parent_class)->expose_event)
131         return GTK_WIDGET_CLASS (hildon_edit_toolbar_parent_class)->expose_event (widget, event);
132
133     return FALSE;
134 }
135
136 static void
137 hildon_edit_toolbar_class_init                  (HildonEditToolbarClass *klass)
138 {
139     GObjectClass *gobject_class = (GObjectClass *) klass;
140     GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
141
142     widget_class->style_set = hildon_edit_toolbar_style_set;
143     widget_class->expose_event = hildon_edit_toolbar_expose;
144
145     g_type_class_add_private (klass, sizeof (HildonEditToolbarPrivate));
146
147     gtk_widget_class_install_style_property (
148         widget_class,
149         g_param_spec_uint (
150             "arrow-width",
151             "Width of the arrow button",
152             "Width of the arrow button",
153             0, G_MAXUINT, 112,
154             G_PARAM_READABLE));
155
156     gtk_widget_class_install_style_property (
157         widget_class,
158         g_param_spec_uint (
159             "arrow-height",
160             "Height of the arrow button",
161             "Height of the arrow button",
162             0, G_MAXUINT, 56,
163             G_PARAM_READABLE));
164
165     /**
166      * HildonEditToolbar::button-clicked:
167      * @widget: the object which received the signal.
168      *
169      * Emitted when the toolbar button has been activated (pressed and released).
170      *
171      * Since: 2.2
172      */
173     toolbar_signals[BUTTON_CLICKED] =
174         g_signal_new ("button_clicked",
175                       G_OBJECT_CLASS_TYPE (gobject_class),
176                       G_SIGNAL_RUN_FIRST,
177                       0, NULL, NULL,
178                       g_cclosure_marshal_VOID__VOID,
179                       G_TYPE_NONE, 0);
180
181     /**
182      * HildonEditToolbar::arrow-clicked:
183      * @widget: the object which received the signal.
184      *
185      * Emitted when the toolbar back button (arrow) has been activated
186      * (pressed and released).
187      *
188      * Since: 2.2
189      */
190     toolbar_signals[ARROW_CLICKED] =
191         g_signal_new ("arrow_clicked",
192                       G_OBJECT_CLASS_TYPE (gobject_class),
193                       G_SIGNAL_RUN_FIRST,
194                       0, NULL, NULL,
195                       g_cclosure_marshal_VOID__VOID,
196                       G_TYPE_NONE, 0);
197 }
198
199 static void
200 button_clicked_cb                               (GtkButton *self,
201                                                  HildonEditToolbar *toolbar)
202 {
203     g_signal_emit (toolbar, toolbar_signals[BUTTON_CLICKED], 0);
204 }
205
206 static void
207 arrow_clicked_cb                                (GtkButton *self,
208                                                  HildonEditToolbar *toolbar)
209 {
210     g_signal_emit (toolbar, toolbar_signals[ARROW_CLICKED], 0);
211 }
212
213 static void
214 hildon_edit_toolbar_init                        (HildonEditToolbar *self)
215 {
216     HildonEditToolbarPrivate *priv = HILDON_EDIT_TOOLBAR_GET_PRIVATE (self);
217     GtkWidget *separator;
218     GtkAlignment *align;
219     GtkBox *hbox = GTK_BOX (self);
220
221     priv->hbox = GTK_BOX (gtk_hbox_new (FALSE, 0));
222     align = GTK_ALIGNMENT (gtk_alignment_new (0, 0.5, 1, 1));
223     priv->label = GTK_LABEL (gtk_label_new (NULL));
224     priv->animation = hildon_private_create_animation (
225         HILDON_EDIT_TOOLBAR_ANIMATION_FRAMERATE,
226         HILDON_EDIT_TOOLBAR_ANIMATION_TMPL,
227         HILDON_EDIT_TOOLBAR_ANIMATION_NFRAMES);
228     priv->button = GTK_BUTTON (hildon_gtk_button_new (HILDON_SIZE_AUTO));
229     separator = gtk_vseparator_new ();
230     priv->arrow = GTK_BUTTON (gtk_button_new ());
231
232     g_object_set (priv->button, "can-focus", FALSE, NULL);
233     g_object_set (priv->arrow, "can-focus", FALSE, NULL);
234
235     g_signal_connect (priv->button, "clicked", G_CALLBACK (button_clicked_cb), self);
236     g_signal_connect (priv->arrow, "clicked", G_CALLBACK (arrow_clicked_cb), self);
237
238     gtk_box_set_spacing (hbox, 0);
239     gtk_alignment_set_padding (align, 0, 0, TOOLBAR_LEFT_PADDING, TOOLBAR_RIGHT_PADDING);
240
241     gtk_widget_set_name (GTK_WIDGET (self), "toolbar-edit-mode");
242     gtk_widget_set_name (GTK_WIDGET (priv->arrow), "hildon-edit-toolbar-arrow");
243
244     gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET (priv->hbox));
245     gtk_box_pack_start (priv->hbox, GTK_WIDGET (priv->label), TRUE, TRUE, 0);
246     gtk_box_pack_start (priv->hbox, priv->animation, TRUE, TRUE, 10);
247     gtk_box_pack_start (priv->hbox, GTK_WIDGET (priv->button), FALSE, FALSE, 0);
248
249     gtk_widget_set_no_show_all (priv->animation, TRUE);
250
251     gtk_box_pack_start (hbox, GTK_WIDGET (align), TRUE, TRUE, 0);
252     gtk_box_pack_start (hbox, separator, FALSE, FALSE, 0);
253     gtk_box_pack_start (hbox, GTK_WIDGET (priv->arrow), FALSE, FALSE, 0);
254
255     gtk_misc_set_alignment (GTK_MISC (priv->label), 0, 0.5);
256     gtk_misc_set_alignment (GTK_MISC (priv->animation), 0, 0.5);
257
258     gtk_widget_show_all (GTK_WIDGET (align));
259     gtk_widget_show_all (separator);
260     gtk_widget_show_all (GTK_WIDGET (priv->arrow));
261 }
262
263 /**
264  * hildon_edit_toolbar_set_label:
265  * @toolbar: a #HildonEditToolbar
266  * @label: a new text for the toolbar label
267  *
268  * Sets the label of @toolbar to @label. This will clear any
269  * previously set value.
270  *
271  * Since: 2.2
272  */
273 void
274 hildon_edit_toolbar_set_label                   (HildonEditToolbar *toolbar,
275                                                  const gchar       *label)
276 {
277     HildonEditToolbarPrivate *priv;
278     g_return_if_fail (HILDON_IS_EDIT_TOOLBAR (toolbar));
279     priv = HILDON_EDIT_TOOLBAR_GET_PRIVATE (toolbar);
280     gtk_label_set_text (priv->label, label);
281 }
282
283 /**
284  * hildon_edit_toolbar_set_button_label:
285  * @toolbar: a #HildonEditToolbar
286  * @label: a new text for the label of the toolbar button
287  *
288  * Sets the label of the toolbar button to @label. This will clear any
289  * previously set value.
290  *
291  * Since: 2.2
292  */
293 void
294 hildon_edit_toolbar_set_button_label            (HildonEditToolbar *toolbar,
295                                                  const gchar       *label)
296 {
297     HildonEditToolbarPrivate *priv;
298     g_return_if_fail (HILDON_IS_EDIT_TOOLBAR (toolbar));
299     priv = HILDON_EDIT_TOOLBAR_GET_PRIVATE (toolbar);
300     gtk_button_set_label (priv->button, label);
301 }
302
303 /**
304  * hildon_edit_toolbar_new:
305  *
306  * Creates a new #HildonEditToolbar.
307  *
308  * Returns: a new #HildonEditToolbar
309  *
310  * Since: 2.2
311  */
312 GtkWidget *
313 hildon_edit_toolbar_new                         (void)
314 {
315     return g_object_new (HILDON_TYPE_EDIT_TOOLBAR, NULL);
316 }
317
318 /**
319  * hildon_edit_toolbar_new_with_text:
320  * @label: Text for the toolbar label.
321  * @button: Text for the toolbar button.
322  *
323  * Creates a new #HildonEditToolbar, with the toolbar label set to
324  * @label and the button label set to @button.
325  *
326  * Returns: a new #HildonEditToolbar
327  *
328  * Since: 2.2
329  */
330 GtkWidget *
331 hildon_edit_toolbar_new_with_text               (const gchar *label,
332                                                  const gchar *button)
333 {
334     GtkWidget *toolbar = g_object_new (HILDON_TYPE_EDIT_TOOLBAR, NULL);
335
336     hildon_edit_toolbar_set_label (HILDON_EDIT_TOOLBAR (toolbar), label);
337     hildon_edit_toolbar_set_button_label (HILDON_EDIT_TOOLBAR (toolbar), button);
338
339     return toolbar;
340 }
341
342 void G_GNUC_INTERNAL
343 hildon_edit_toolbar_set_progress_indicator      (HildonEditToolbar *toolbar,
344                                                  gboolean           show)
345 {
346     HildonEditToolbarPrivate *priv;
347     g_return_if_fail (HILDON_IS_EDIT_TOOLBAR (toolbar));
348     priv = HILDON_EDIT_TOOLBAR_GET_PRIVATE (toolbar);
349     if (show) {
350         gtk_widget_show (priv->animation);
351         gtk_box_set_child_packing (priv->hbox, GTK_WIDGET (priv->label),
352                                    FALSE, FALSE, 0, GTK_PACK_START);
353     } else {
354         gtk_box_set_child_packing (priv->hbox, GTK_WIDGET (priv->label),
355                                    TRUE, TRUE, 0, GTK_PACK_START);
356         gtk_widget_hide (priv->animation);
357     }
358 }