4953add453c903ce3e5a43b5c391ca68778aa0da
[hildon] / src / hildon-gtk.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-gtk
19  * @short_description: Additional functions for Gtk widgets
20  * @see_also: #HildonButton, #HildonCheckButton
21  *
22  * Hildon provides some functions to extend the functionality of
23  * existing Gtk widgets. This also includes convenience functions to
24  * easily perform frequent tasks.
25  */
26
27 #include <X11/Xatom.h>
28 #include <gdk/gdkx.h>
29
30 #include "hildon-gtk.h"
31
32 static void
33 image_visible_changed_cb                        (GtkWidget  *image,
34                                                  GParamSpec *arg1,
35                                                  gpointer   oldparent)
36 {
37     if (!GTK_WIDGET_VISIBLE (image))
38         gtk_widget_show (image);
39 }
40
41 static void
42 parent_changed_cb                               (GtkWidget  *image,
43                                                  GParamSpec *arg1,
44                                                  gpointer   oldparent)
45 {
46     /* If the parent has really changed, remove the old signal handlers */
47     if (image->parent != oldparent) {
48         g_signal_handlers_disconnect_by_func (image, parent_changed_cb, oldparent);
49         g_signal_handlers_disconnect_by_func (image, image_visible_changed_cb, NULL);
50     }
51 }
52
53 static void
54 image_changed_cb                                (GtkButton  *button,
55                                                  GParamSpec *arg1,
56                                                  gpointer    user_data)
57 {
58     GtkWidget *image = gtk_button_get_image (button);
59
60     g_return_if_fail (image == NULL || GTK_IS_WIDGET (image));
61
62     if (image != NULL) {
63         /* If the button has a new image, show it */
64         gtk_widget_show (image);
65         /* Show the image no matter the value of gtk-button-images */
66         g_signal_connect (image, "notify::visible", G_CALLBACK (image_visible_changed_cb), NULL);
67         /* If the image is removed from the button, disconnect these handlers */
68         g_signal_connect (image, "notify::parent", G_CALLBACK (parent_changed_cb), image->parent);
69     }
70 }
71
72 static void
73 button_common_init                              (GtkWidget      *button,
74                                                  HildonSizeType  size)
75 {
76     /* Set requested size */
77     hildon_gtk_widget_set_theme_size (button, size);
78
79     /* Set focus-on-click to FALSE by default */
80     gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
81
82     /* Make sure that all images in this button are always shown */
83     g_signal_connect (button, "notify::image", G_CALLBACK (image_changed_cb), NULL);
84 }
85
86 /**
87  * hildon_gtk_menu_new:
88  *
89  * This is a convenience function to create a #GtkMenu setting its
90  * widget name to allow Hildon specific styling.
91  *
92  * Return value: A newly created #GtkMenu widget.
93  *
94  * Since: 2.2
95  **/
96 GtkWidget *
97 hildon_gtk_menu_new                             (void)
98 {
99     GtkWidget *menu = gtk_menu_new ();
100     gtk_widget_set_name (menu, "hildon-context-sensitive-menu");
101     return menu;
102 }
103
104 /**
105  * hildon_gtk_button_new:
106  * @size: Flags indicating the size of the new button
107  *
108  * This is a convenience function to create a #GtkButton setting its
109  * size to one of the pre-defined Hildon sizes.
110  *
111  * Buttons created with this function also override the
112  * "gtk-button-images" setting. Images set using
113  * gtk_button_set_image() are always shown.
114  *
115  * Buttons created using this function have #GtkButton:focus-on-click
116  * set to %FALSE by default.
117  *
118  * Return value: A newly created #GtkButton widget.
119  *
120  * Since: 2.2
121  **/
122 GtkWidget *
123 hildon_gtk_button_new                           (HildonSizeType size)
124 {
125     GtkWidget *button = gtk_button_new ();
126     button_common_init (button, size);
127     return button;
128 }
129
130 /**
131  * hildon_gtk_toggle_button_new:
132  * @size: Flags indicating the size of the new button
133  *
134  * This is a convenience function to create a #GtkToggleButton setting
135  * its size to one of the pre-defined Hildon sizes.
136  *
137  * Buttons created with this function also override the
138  * "gtk-button-images" setting. Images set using
139  * gtk_button_set_image() are always shown.
140  *
141  * Buttons created using this function have #GtkButton:focus-on-click
142  * set to %FALSE by default.
143  *
144  * Return value: A newly created #GtkToggleButton widget.
145  *
146  * Since: 2.2
147  **/
148 GtkWidget *
149 hildon_gtk_toggle_button_new                    (HildonSizeType size)
150 {
151     GtkWidget *button = gtk_toggle_button_new ();
152     button_common_init (button, size);
153     return button;
154 }
155
156 /**
157  * hildon_gtk_radio_button_new:
158  * @size: Flags indicating the size of the new button
159  * @group: An existing radio button group, or %NULL if you are
160  * creating a new group
161  *
162  * This is a convenience function to create a #GtkRadioButton setting
163  * its size to one of the pre-defined Hildon sizes.
164  *
165  * Buttons created with this function also override the
166  * "gtk-button-images" setting. Images set using
167  * gtk_button_set_image() are always shown.
168  *
169  * Buttons created using this function have #GtkButton:focus-on-click
170  * set to %FALSE by default.
171  *
172  * Return value: A newly created #GtkRadioButton widget.
173  *
174  * Since: 2.2
175  **/
176 GtkWidget *
177 hildon_gtk_radio_button_new                     (HildonSizeType  size,
178                                                  GSList         *group)
179 {
180     GtkWidget *button = gtk_radio_button_new (group);
181     button_common_init (button, size);
182     return button;
183 }
184
185 /**
186  * hildon_gtk_radio_button_new_from_widget:
187  * @size: Flags indicating the size of the new button
188  * @radio_group_member: widget to get radio group from or %NULL
189  *
190  * This is a convenience function to create a #GtkRadioButton setting
191  * its size to one of the pre-defined Hildon sizes.
192  *
193  * Buttons created with this function also override the
194  * "gtk-button-images" setting. Images set using
195  * gtk_button_set_image() are always shown.
196  *
197  * Buttons created using this function have #GtkButton:focus-on-click
198  * set to %FALSE by default.
199  *
200  * Return value: A newly created #GtkRadioButton widget.
201  *
202  * Since: 2.2
203  **/
204 GtkWidget *
205 hildon_gtk_radio_button_new_from_widget         (HildonSizeType  size,
206                                                  GtkRadioButton *radio_group_member)
207 {
208     GtkWidget *button = gtk_radio_button_new_from_widget (radio_group_member);
209     button_common_init (button, size);
210     return button;
211 }
212
213 #ifdef MAEMO_GTK
214 /**
215  * hildon_gtk_tree_view_new:
216  * @mode: the Hildon UI mode
217  *
218  * Creates a new #GtkTreeView widget with the Hildon UI mode set to
219  * @mode
220  *
221  * Return value: A newly created #GtkTreeView widget.
222  *
223  * Since: 2.2
224  **/
225 GtkWidget *
226 hildon_gtk_tree_view_new                        (HildonUIMode mode)
227 {
228     return g_object_new (GTK_TYPE_TREE_VIEW, "hildon-ui-mode", mode,
229                          "enable-search", FALSE, NULL);
230 }
231
232 /**
233  * hildon_gtk_tree_view_new_with_model:
234  * @mode: the Hildon UI mode
235  * @model: the model.
236  *
237  * Creates a new #GtkTreeView widget with the Hildon UI mode set to
238  * @mode and the model initialized to @model.
239  *
240  * Return value: A newly created #GtkTreeView widget.
241  *
242  * Since: 2.2
243  **/
244 GtkWidget *
245 hildon_gtk_tree_view_new_with_model             (HildonUIMode  mode,
246                                                  GtkTreeModel *model)
247 {
248     return g_object_new (GTK_TYPE_TREE_VIEW, "hildon-ui-mode", mode, "model", model, NULL);
249 }
250
251 /**
252  * hildon_gtk_tree_view_set_ui_mode:
253  * @treeview: A #GtkTreeView
254  * @mode: The new #HildonUIMode
255  *
256  * Sets the UI mode of @treeview to @mode.
257  *
258  * Since: 2.2
259  **/
260 void
261 hildon_gtk_tree_view_set_ui_mode                (GtkTreeView  *treeview,
262                                                  HildonUIMode  mode)
263 {
264     g_return_if_fail (GTK_IS_TREE_VIEW (treeview));
265     g_object_set (treeview, "hildon-ui-mode", mode, NULL);
266 }
267
268 /**
269  * hildon_gtk_icon_view_new:
270  * @mode: the Hildon UI mode
271  *
272  * Creates a new #GtkIconView widget with the Hildon UI mode set to
273  * @mode
274  *
275  * Return value: A newly created #GtkIconView widget
276  *
277  * Since: 2.2
278  **/
279 GtkWidget *
280 hildon_gtk_icon_view_new                        (HildonUIMode mode)
281 {
282     return g_object_new (GTK_TYPE_ICON_VIEW, "hildon-ui-mode", mode, NULL);
283 }
284
285 /**
286  * hildon_gtk_icon_view_new_with_model:
287  * @mode: the Hildon UI mode
288  * @model: The model.
289  *
290  * Creates a new #GtkIconView widget with the Hildon UI mode set to
291  * @mode and the model intitialized to @model.
292  *
293  * Return value: A newly created #GtkIconView widget.
294  *
295  * Since: 2.2
296  **/
297 GtkWidget *
298 hildon_gtk_icon_view_new_with_model             (HildonUIMode  mode,
299                                                  GtkTreeModel *model)
300 {
301     return g_object_new (GTK_TYPE_ICON_VIEW, "hildon-ui-mode", mode, "model", model, NULL);
302 }
303
304 /**
305  * hildon_gtk_icon_view_set_ui_mode:
306  * @iconview: A #GtkIconView
307  * @mode: The new #HildonUIMode
308  *
309  * Sets the UI mode of @iconview to @mode.
310  *
311  * Since: 2.2
312  **/
313 void
314 hildon_gtk_icon_view_set_ui_mode                (GtkIconView  *iconview,
315                                                  HildonUIMode  mode)
316 {
317     g_return_if_fail (GTK_IS_ICON_VIEW (iconview));
318     g_object_set (iconview, "hildon-ui-mode", mode, NULL);
319 }
320 #endif /* MAEMO_GTK */
321
322 static void
323 set_clear_window_flag                           (GtkWindow   *window,
324                                                  const gchar *atomname,
325                                                  gboolean     flag)
326 {
327     GdkWindow *gdkwin;
328     GdkAtom atom;
329
330     g_return_if_fail (GTK_IS_WINDOW (window));
331     g_return_if_fail (GTK_WIDGET_REALIZED (window));
332
333     gdkwin = GTK_WIDGET (window)->window;
334     atom = gdk_atom_intern (atomname, FALSE);
335
336     if (flag) {
337         guint32 set = 1;
338         gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (XA_INTEGER),
339                              32, GDK_PROP_MODE_REPLACE, (const guchar *) &set, 1);
340     } else {
341         gdk_property_delete (gdkwin, atom);
342     }
343 }
344
345 /**
346  * hildon_gtk_window_set_progress_indicator:
347  * @window: a #GtkWindow.
348  * @state: The state we want to set: 1 -> show progress indicator, 0
349  *          -> hide progress indicator.
350  *
351  * This functions tells the window manager to show/hide a progress
352  * indicator in the window title. It applies to #HildonDialog and
353  * #HildonWindow (including subclasses).
354  *
355  * Note that @window must be realized for this to work.
356  *
357  * Since: 2.2
358  **/
359 void
360 hildon_gtk_window_set_progress_indicator        (GtkWindow    *window,
361                                                  guint        state)
362 {
363     set_clear_window_flag (window, "_HILDON_WM_WINDOW_PROGRESS_INDICATOR", state);
364 }
365
366 /**
367  * hildon_gtk_hscale_new:
368  *
369  * Creates a new horizontal scale widget that lets the user select
370  * a value. The value is technically a double between 0.0 and 1.0.
371  * See gtk_adjustment_configure() for reconfiguring the adjustment.
372  *
373  * The scale is hildonized, which means that a click or tap immediately
374  * jumps to the desired position, see gtk_range_set_jump_to_position().
375  * Further more the value is not displayed, see gtk_scale_set_draw_value().
376  *
377  * Returns: a new hildonized #GtkHScale
378  *
379  * Since: 2.2
380  **/
381 GtkWidget*
382 hildon_gtk_hscale_new                           (void)
383 {
384   GtkWidget *scale = gtk_hscale_new_with_range (0.0, 1.0, 0.1);
385   g_object_set (scale,
386                 "draw-value", FALSE,
387 #ifdef MAEMO_GTK
388                 "jump-to-position", TRUE,
389 #endif
390                 NULL);
391
392   return scale;
393 }
394
395 /**
396  * hildon_gtk_vscale_new:
397  *
398  * Creates a new vertical scale widget that lets the user select
399  * a value. The value is technically a double between 0.0 and 1.0.
400  * See gtk_adjustment_configure() for reconfiguring the adjustment.
401  *
402  * The scale is hildonized, which means that a click or tap immediately
403  * jumps to the desired position, see gtk_range_set_jump_to_position().
404  * Further more the value is not displayed, see gtk_scale_set_draw_value().
405  *
406  * Returns: a new hildonized #GtkVScale
407  *
408  * Since: 2.2
409  **/
410 GtkWidget*
411 hildon_gtk_vscale_new                           (void)
412 {
413   GtkWidget *scale = gtk_vscale_new_with_range (0.0, 1.0, 0.1);
414   g_object_set (scale,
415                 "draw-value", FALSE,
416 #ifdef MAEMO_GTK
417                 "jump-to-position", TRUE,
418 #endif
419                 NULL);
420
421   return scale;
422 }