2 * This file is a part of hildon
4 * Copyright (C) 2008 Nokia Corporation, all rights reserved.
6 * Contact: Karl Lattimer <karl.lattimer@nokia.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser Public License as published by
10 * the Free Software Foundation; version 2 of the license.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser Public License for more details.
20 * SECTION:hildon-button
21 * @short_description: Widget representing a button in the Hildon framework.
23 * The #HildonButton is a GTK widget which represents a clickable
24 * button. It is derived from the GtkButton widget and provides
25 * additional commodities specific to the Hildon framework.
27 * The height of a #HildonButton can be set to either "finger" height
28 * or "thumb" height. It can also be configured to use halfscreen or
29 * fullscreen width. Alternatively, either dimension can be set to
30 * "auto" so it behaves like a standard GtkButton.
32 * The #HildonButton can hold any valid child widget, but it usually
33 * contains two labels, named title and value, and it can also contain
34 * an image. To change the alignment of the button contents, use
35 * gtk_button_set_alignment()
37 * If only one label is needed, #GtkButton can be used as well, see
38 * also hildon_gtk_button_new().
41 * <title>Creating a HildonButton</title>
44 * button_clicked (HildonButton *button, gpointer user_data)
46 * const gchar *title, *value;
48 * title = hildon_button_get_title (button);
49 * value = hildon_button_get_value (button);
50 * g_debug ("Button clicked with title '%s' and value '%s'", title, value);
54 * create_button (void)
59 * button = hildon_button_new (HILDON_SIZE_AUTO, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
60 * hildon_button_set_text (HILDON_BUTTON (button), "Some title", "Some value");
62 * image = gtk_image_new_from_stock (GTK_STOCK_INFO, GTK_ICON_SIZE_BUTTON);
63 * hildon_button_set_image (HILDON_BUTTON (button), image);
64 * hildon_button_set_image_position (HILDON_BUTTON (button), GTK_POS_RIGHT);
66 * gtk_button_set_alignment (GTK_BUTTON (button), 0.0, 0.5);
68 * g_signal_connect (button, "clicked", G_CALLBACK (button_clicked), NULL);
76 #include "hildon-button.h"
77 #include "hildon-enum-types.h"
78 #include "hildon-gtk.h"
80 G_DEFINE_TYPE (HildonButton, hildon_button, GTK_TYPE_BUTTON);
82 #define HILDON_BUTTON_GET_PRIVATE(obj) \
83 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
84 HILDON_TYPE_BUTTON, HildonButtonPrivate));
86 typedef struct _HildonButtonPrivate HildonButtonPrivate;
88 struct _HildonButtonPrivate
96 GtkPositionType image_position;
109 hildon_button_set_arrangement (HildonButton *button,
110 HildonButtonArrangement arrangement);
113 hildon_button_construct_child (HildonButton *button);
116 hildon_button_set_property (GObject *object,
121 HildonButton *button = HILDON_BUTTON (object);
126 hildon_button_set_title (button, g_value_get_string (value));
129 hildon_button_set_value (button, g_value_get_string (value));
132 hildon_gtk_widget_set_theme_size (GTK_WIDGET (button), g_value_get_flags (value));
134 case PROP_ARRANGEMENT:
135 hildon_button_set_arrangement (button, g_value_get_enum (value));
138 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
144 hildon_button_get_property (GObject *object,
149 HildonButton *button = HILDON_BUTTON (object);
150 HildonButtonPrivate *priv = HILDON_BUTTON_GET_PRIVATE (button);
155 g_value_set_string (value, gtk_label_get_text (priv->title));
158 g_value_set_string (value, gtk_label_get_text (priv->value));
161 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
167 hildon_button_style_set (GtkWidget *widget,
168 GtkStyle *previous_style)
170 guint horizontal_spacing, vertical_spacing, image_spacing;
171 HildonButtonPrivate *priv = HILDON_BUTTON_GET_PRIVATE (widget);
173 if (GTK_WIDGET_CLASS (hildon_button_parent_class)->style_set)
174 GTK_WIDGET_CLASS (hildon_button_parent_class)->style_set (widget, previous_style);
176 gtk_widget_style_get (widget,
177 "horizontal-spacing", &horizontal_spacing,
178 "vertical-spacing", &vertical_spacing,
179 "image-spacing", &image_spacing,
182 if (GTK_IS_HBOX (priv->label_box)) {
183 gtk_box_set_spacing (GTK_BOX (priv->label_box), horizontal_spacing);
185 gtk_box_set_spacing (GTK_BOX (priv->label_box), vertical_spacing);
188 if (GTK_IS_BOX (priv->hbox)) {
189 gtk_box_set_spacing (priv->hbox, image_spacing);
194 hildon_button_class_init (HildonButtonClass *klass)
196 GObjectClass *gobject_class = (GObjectClass *)klass;
197 GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
199 gobject_class->set_property = hildon_button_set_property;
200 gobject_class->get_property = hildon_button_get_property;
201 widget_class->style_set = hildon_button_style_set;
203 g_object_class_install_property (
206 g_param_spec_string (
209 "Text of the title label inside the button",
211 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
213 g_object_class_install_property (
216 g_param_spec_string (
219 "Text of the value label inside the button",
221 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
223 g_object_class_install_property (
229 "Size request for the button",
230 HILDON_TYPE_SIZE_TYPE,
232 G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
234 g_object_class_install_property (
240 "How the button contents must be arranged",
241 HILDON_TYPE_BUTTON_ARRANGEMENT,
242 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
243 G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
245 gtk_widget_class_install_style_property (
248 "horizontal-spacing",
249 "Horizontal spacing between labels",
250 "Horizontal spacing between the title and value labels, when in horizontal mode",
254 gtk_widget_class_install_style_property (
258 "Vertical spacing between labels",
259 "Vertical spacing between the title and value labels, when in vertical mode",
263 g_type_class_add_private (klass, sizeof (HildonButtonPrivate));
267 hildon_button_init (HildonButton *self)
269 HildonButtonPrivate *priv = HILDON_BUTTON_GET_PRIVATE (self);
271 priv->title = GTK_LABEL (gtk_label_new (NULL));
272 priv->value = GTK_LABEL (gtk_label_new (NULL));
273 priv->alignment = gtk_alignment_new (0.5, 0.5, 0, 0);
275 priv->image_position = GTK_POS_LEFT;
276 priv->image_xalign = 0.0;
277 priv->image_yalign = 0.0;
279 priv->label_box = NULL;
281 gtk_widget_set_name (GTK_WIDGET (priv->title), "hildon-button-title");
282 gtk_widget_set_name (GTK_WIDGET (priv->value), "hildon-button-value");
284 gtk_misc_set_alignment (GTK_MISC (priv->title), 0, 0.5);
285 gtk_misc_set_alignment (GTK_MISC (priv->value), 0, 0.5);
287 /* The labels are not shown automatically, see hildon_button_set_(title|value) */
288 gtk_widget_set_no_show_all (GTK_WIDGET (priv->title), TRUE);
289 gtk_widget_set_no_show_all (GTK_WIDGET (priv->value), TRUE);
293 * hildon_button_add_title_size_group:
294 * @button: a #HildonButton
295 * @size_group: A #GtkSizeGroup for the button title (main label)
297 * Adds the title label of @button to @size_group.
300 hildon_button_add_title_size_group (HildonButton *button,
301 GtkSizeGroup *size_group)
303 HildonButtonPrivate *priv;
305 g_return_if_fail (HILDON_IS_BUTTON (button));
306 g_return_if_fail (GTK_IS_SIZE_GROUP (size_group));
308 priv = HILDON_BUTTON_GET_PRIVATE (button);
310 gtk_size_group_add_widget (size_group, GTK_WIDGET (priv->title));
314 * hildon_button_add_value_size_group:
315 * @button: a #HildonButton
316 * @size_group: A #GtkSizeGroup for the button value (secondary label)
318 * Adds the value label of @button to @size_group.
321 hildon_button_add_value_size_group (HildonButton *button,
322 GtkSizeGroup *size_group)
324 HildonButtonPrivate *priv;
326 g_return_if_fail (HILDON_IS_BUTTON (button));
327 g_return_if_fail (GTK_IS_SIZE_GROUP (size_group));
329 priv = HILDON_BUTTON_GET_PRIVATE (button);
331 gtk_size_group_add_widget (size_group, GTK_WIDGET (priv->value));
335 * hildon_button_add_image_size_group:
336 * @button: a #HildonButton
337 * @size_group: A #GtkSizeGroup for the button image
339 * Adds the image of @button to @size_group. You must add an image
340 * using hildon_button_set_image() before calling this function.
343 hildon_button_add_image_size_group (HildonButton *button,
344 GtkSizeGroup *size_group)
346 HildonButtonPrivate *priv;
348 g_return_if_fail (HILDON_IS_BUTTON (button));
349 g_return_if_fail (GTK_IS_SIZE_GROUP (size_group));
351 priv = HILDON_BUTTON_GET_PRIVATE (button);
353 g_return_if_fail (GTK_IS_WIDGET (priv->image));
355 gtk_size_group_add_widget (size_group, GTK_WIDGET (priv->image));
359 * hildon_button_add_size_groups:
360 * @button: a #HildonButton
361 * @title_size_group: A #GtkSizeGroup for the button title (main label), or %NULL
362 * @value_size_group: A #GtkSizeGroup group for the button value (secondary label), or %NULL
363 * @image_size_group: A #GtkSizeGroup group for the button image, or %NULL
365 * Convenience function to add title, value and image to size
366 * groups. %NULL size groups will be ignored.
369 hildon_button_add_size_groups (HildonButton *button,
370 GtkSizeGroup *title_size_group,
371 GtkSizeGroup *value_size_group,
372 GtkSizeGroup *image_size_group)
374 if (title_size_group)
375 hildon_button_add_title_size_group (button, title_size_group);
377 if (value_size_group)
378 hildon_button_add_value_size_group (button, value_size_group);
380 if (image_size_group)
381 hildon_button_add_image_size_group (button, image_size_group);
386 * @size: Flags to set the size of the button.
387 * @arrangement: How the labels must be arranged.
389 * Creates a new #HildonButton. To set text in the labels, use
390 * hildon_button_set_title() and
391 * hildon_button_set_value(). Alternatively, you can add a custom
392 * child widget using gtk_container_add().
394 * Returns: a new #HildonButton
397 hildon_button_new (HildonSizeType size,
398 HildonButtonArrangement arrangement)
400 return hildon_button_new_with_text (size, arrangement, NULL, NULL);
404 * hildon_button_new_with_text:
405 * @size: Flags to set the size of the button.
406 * @arrangement: How the labels must be arranged.
407 * @title: Title of the button (main label), or %NULL
408 * @value: Value of the button (secondary label), or %NULL
410 * Creates a new #HildonButton with two labels, @title and @value.
412 * If you just don't want to use one of the labels, set it to
413 * %NULL. You can set it to a non-%NULL value at any time later.
415 * Returns: a new #HildonButton
418 hildon_button_new_with_text (HildonSizeType size,
419 HildonButtonArrangement arrangement,
426 button = g_object_new (HILDON_TYPE_BUTTON,
430 "arrangement", arrangement,
437 hildon_button_set_arrangement (HildonButton *button,
438 HildonButtonArrangement arrangement)
440 HildonButtonPrivate *priv;
442 priv = HILDON_BUTTON_GET_PRIVATE (button);
444 /* Pack everything */
445 if (arrangement == HILDON_BUTTON_ARRANGEMENT_VERTICAL) {
446 priv->label_box = gtk_vbox_new (FALSE, 0);
448 priv->label_box = gtk_hbox_new (FALSE, 0);
451 gtk_box_pack_start (GTK_BOX (priv->label_box), GTK_WIDGET (priv->title), TRUE, TRUE, 0);
452 gtk_box_pack_start (GTK_BOX (priv->label_box), GTK_WIDGET (priv->value), TRUE, TRUE, 0);
454 hildon_button_construct_child (button);
458 * hildon_button_set_title:
459 * @button: a #HildonButton
460 * @title: a new title (main label) for the button, or %NULL
462 * Sets the title (main label) of @button to @title.
464 * This will clear any previously set title.
466 * If @title is set to %NULL, the title label will be hidden and the
467 * value label will be realigned.
470 hildon_button_set_title (HildonButton *button,
473 HildonButtonPrivate *priv;
475 g_return_if_fail (HILDON_IS_BUTTON (button));
477 priv = HILDON_BUTTON_GET_PRIVATE (button);
478 gtk_label_set_text (priv->title, title);
480 /* If the button has no title, hide the label so the value is
481 * properly aligned */
483 hildon_button_construct_child (button);
484 gtk_widget_show (GTK_WIDGET (priv->title));
486 gtk_widget_hide (GTK_WIDGET (priv->title));
489 g_object_notify (G_OBJECT (button), "title");
493 * hildon_button_set_value:
494 * @button: a #HildonButton
495 * @value: a new value (secondary label) for the button, or %NULL
497 * Sets the value (secondary label) of @button to @value.
499 * This will clear any previously set value.
501 * If @value is set to %NULL, the value label will be hidden and the
502 * title label will be realigned.
506 hildon_button_set_value (HildonButton *button,
509 HildonButtonPrivate *priv;
511 g_return_if_fail (HILDON_IS_BUTTON (button));
513 priv = HILDON_BUTTON_GET_PRIVATE (button);
514 gtk_label_set_text (priv->value, value);
516 /* If the button has no value, hide the label so the title is
517 * properly aligned */
519 hildon_button_construct_child (button);
520 gtk_widget_show (GTK_WIDGET (priv->value));
522 gtk_widget_hide (GTK_WIDGET (priv->value));
525 g_object_notify (G_OBJECT (button), "value");
529 * hildon_button_get_title:
530 * @button: a #HildonButton
532 * Gets the text from the main label (title) of @button, or %NULL if
535 * Returns: The text of the title label. This string is owned by the
536 * widget and must not be modified or freed.
539 hildon_button_get_title (HildonButton *button)
541 HildonButtonPrivate *priv;
543 g_return_val_if_fail (HILDON_IS_BUTTON (button), NULL);
545 priv = HILDON_BUTTON_GET_PRIVATE (button);
547 return gtk_label_get_text (priv->title);
551 * hildon_button_get_value:
552 * @button: a #HildonButton
554 * Gets the text from the secondary label (value) of @button, or %NULL
555 * if none has been set.
557 * Returns: The text of the value label. This string is owned by the
558 * widget and must not be modified or freed.
561 hildon_button_get_value (HildonButton *button)
563 HildonButtonPrivate *priv;
565 g_return_val_if_fail (HILDON_IS_BUTTON (button), NULL);
567 priv = HILDON_BUTTON_GET_PRIVATE (button);
569 return gtk_label_get_text (priv->value);
573 * hildon_button_set_text:
574 * @button: a #HildonButton
575 * @title: new text for the button title (main label)
576 * @value: new text for the button value (secondary label)
578 * Convenience function to change both labels of a #HildonButton
581 hildon_button_set_text (HildonButton *button,
585 hildon_button_set_title (button, title);
586 hildon_button_set_value (button, value);
590 * hildon_button_set_image:
591 * @button: a #HildonButton
592 * @image: a widget to set as the button image
594 * Sets the image of @button to the given widget. The previous image
595 * (if any) will be removed.
598 hildon_button_set_image (HildonButton *button,
601 HildonButtonPrivate *priv;
603 g_return_if_fail (HILDON_IS_BUTTON (button));
604 g_return_if_fail (!image || GTK_IS_WIDGET (image));
606 priv = HILDON_BUTTON_GET_PRIVATE (button);
608 /* Return if there's nothing to do */
609 if (image == priv->image)
612 if (priv->image && priv->image->parent)
613 gtk_container_remove (GTK_CONTAINER (priv->image->parent), priv->image);
617 hildon_button_construct_child (button);
621 * hildon_button_get_image:
622 * @button: a #HildonButton
624 * Gets the widget that is currenty set as the image of @button,
625 * previously set with hildon_button_set_image()
627 * Returns: a #GtkWidget or %NULL in case there is no image
630 hildon_button_get_image (HildonButton *button)
632 HildonButtonPrivate *priv;
634 g_return_val_if_fail (HILDON_IS_BUTTON (button), NULL);
636 priv = HILDON_BUTTON_GET_PRIVATE (button);
642 * hildon_button_set_image_position:
643 * @button: a #HildonButton
644 * @position: the position of the image (%GTK_POS_LEFT or %GTK_POS_RIGHT)
646 * Sets the position of the image inside @button. Only %GTK_POS_LEFT
647 * and %GTK_POS_RIGHT are currently supported.
650 hildon_button_set_image_position (HildonButton *button,
651 GtkPositionType position)
653 HildonButtonPrivate *priv;
655 g_return_if_fail (HILDON_IS_BUTTON (button));
656 g_return_if_fail (position == GTK_POS_LEFT || position == GTK_POS_RIGHT);
658 priv = HILDON_BUTTON_GET_PRIVATE (button);
660 /* Return if there's nothing to do */
661 if (priv->image_position == position)
664 priv->image_position = position;
666 hildon_button_construct_child (button);
670 * hildon_button_set_alignment:
671 * @button: a #HildonButton
672 * @xalign: the horizontal alignment of the contents, from 0 (left) to 1 (right).
673 * @yalign: the vertical alignment of the contents, from 0 (top) to 1 (bottom).
674 * @xscale: the amount that the child widget expands horizontally to fill up unused space, from 0 to 1
675 * @yscale: the amount that the child widget expands vertically to fill up unused space, from 0 to 1
677 * Sets the alignment of the contents of the widget. If you don't need
678 * to change @xscale or @yscale you can just use
679 * gtk_button_set_alignment() instead.
682 hildon_button_set_alignment (HildonButton *button,
688 HildonButtonPrivate *priv;
691 g_return_if_fail (HILDON_IS_BUTTON (button));
693 priv = HILDON_BUTTON_GET_PRIVATE (button);
695 child = gtk_bin_get_child (GTK_BIN (button));
697 if (GTK_IS_ALIGNMENT (child)) {
698 gtk_button_set_alignment (GTK_BUTTON (button), xalign, yalign);
699 g_object_set (child, "xscale", xscale, "yscale", yscale, NULL);
704 * hildon_button_set_title_alignment:
705 * @button: a #HildonButton
706 * @xalign: the horizontal alignment of the title label, from 0 (left) to 1 (right).
707 * @yalign: the vertical alignment of the title label, from 0 (top) to 1 (bottom).
709 * Sets the alignment of the title label. See also
710 * hildon_button_set_alignment() to set the alignment of the whole
711 * contents of the button.
714 hildon_button_set_title_alignment (HildonButton *button,
718 HildonButtonPrivate *priv;
720 g_return_if_fail (HILDON_IS_BUTTON (button));
722 priv = HILDON_BUTTON_GET_PRIVATE (button);
724 gtk_misc_set_alignment (GTK_MISC (priv->title), xalign, yalign);
728 * hildon_button_set_value_alignment:
729 * @button: a #HildonButton
730 * @xalign: the horizontal alignment of the value label, from 0 (left) to 1 (right).
731 * @yalign: the vertical alignment of the value label, from 0 (top) to 1 (bottom).
733 * Sets the alignment of the value label. See also
734 * hildon_button_set_alignment() to set the alignment of the whole
735 * contents of the button.
738 hildon_button_set_value_alignment (HildonButton *button,
742 HildonButtonPrivate *priv;
744 g_return_if_fail (HILDON_IS_BUTTON (button));
746 priv = HILDON_BUTTON_GET_PRIVATE (button);
748 gtk_misc_set_alignment (GTK_MISC (priv->value), xalign, yalign);
752 * hildon_button_set_image_alignment:
753 * @button: a #HildonButton
754 * @xalign: the horizontal alignment of the image, from 0 (left) to 1 (right).
755 * @yalign: the vertical alignment of the image, from 0 (top) to 1 (bottom).
757 * Sets the alignment of the image. See also
758 * hildon_button_set_alignment() to set the alignment of the whole
759 * contents of the button.
762 hildon_button_set_image_alignment (HildonButton *button,
766 HildonButtonPrivate *priv;
768 g_return_if_fail (HILDON_IS_BUTTON (button));
770 priv = HILDON_BUTTON_GET_PRIVATE (button);
772 /* Return if there's nothing to do */
773 if (priv->image_xalign == xalign && priv->image_yalign == yalign)
776 priv->image_xalign = xalign;
777 priv->image_yalign = yalign;
779 hildon_button_construct_child (button);
783 hildon_button_construct_child (HildonButton *button)
785 HildonButtonPrivate *priv = HILDON_BUTTON_GET_PRIVATE (button);
789 /* Don't do anything if the button is not constructed yet */
790 if (priv->label_box == NULL)
793 /* Save a ref to the image if necessary */
794 if (priv->image && priv->image->parent != NULL) {
795 g_object_ref (priv->image);
796 gtk_container_remove (GTK_CONTAINER (priv->image->parent), priv->image);
799 /* Save a ref to the label box if necessary */
800 if (priv->label_box->parent != NULL) {
801 g_object_ref (priv->label_box);
802 gtk_container_remove (GTK_CONTAINER (priv->label_box->parent), priv->label_box);
805 /* Remove the child from the container and add priv->alignment */
806 child = gtk_bin_get_child (GTK_BIN (button));
807 if (child != NULL && child != priv->alignment) {
808 gtk_container_remove (GTK_CONTAINER (button), child);
813 gtk_container_add (GTK_CONTAINER (button), GTK_WIDGET (priv->alignment));
816 /* Create a new hbox */
818 gtk_container_remove (GTK_CONTAINER (priv->alignment), GTK_WIDGET (priv->hbox));
820 gtk_widget_style_get (GTK_WIDGET (button), "image-spacing", &image_spacing, NULL);
821 priv->hbox = GTK_BOX (gtk_hbox_new (FALSE, image_spacing));
822 gtk_container_add (GTK_CONTAINER (priv->alignment), GTK_WIDGET (priv->hbox));
824 /* Pack the image and the alignment in the new hbox */
825 if (priv->image && priv->image_position == GTK_POS_LEFT)
826 gtk_box_pack_start (priv->hbox, priv->image, TRUE, TRUE, 0);
828 gtk_box_pack_start (priv->hbox, priv->label_box, TRUE, TRUE, 0);
830 if (priv->image && priv->image_position == GTK_POS_RIGHT)
831 gtk_box_pack_start (priv->hbox, priv->image, TRUE, TRUE, 0);
833 /* Set image alignment */
835 gtk_misc_set_alignment (GTK_MISC (priv->image), priv->image_xalign, priv->image_yalign);
837 /* Show everything */
838 gtk_widget_show_all (GTK_WIDGET (priv->alignment));