2 * This file is a part of hildon
4 * Copyright (C) 2007 Nokia Corporation, all rights reserved.
6 * Contact: Rodrigo Novo <rodrigo.novo@nokia.com>
7 * Author: Xan Lopez <xan.lopez@nokia.com>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
26 #undef HILDON_DISABLE_DEPRECATED
28 #include "hildon-bread-crumb-widget.h"
29 #include "hildon-defines.h"
31 #define HILDON_BREAD_CRUMB_WIDGET_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_BREAD_CRUMB_WIDGET, HildonBreadCrumbWidgetPrivate))
33 struct _HildonBreadCrumbWidgetPrivate
41 GtkPositionType icon_position;
43 gboolean show_separator;
63 static guint bread_crumb_item_signals[LAST_SIGNAL] = { 0 };
68 static void hildon_bread_crumb_widget_finalize (GObject *object);
69 static void hildon_bread_crumb_widget_set_property (GObject *object, guint prop_id,
70 const GValue *value, GParamSpec *pspec);
71 static void hildon_bread_crumb_widget_get_property (GObject *object, guint prop_id,
72 GValue *value, GParamSpec *pspec);
73 static GObject* hildon_bread_crumb_widget_constructor (GType type,
74 guint n_construct_properties,
75 GObjectConstructParam *construct_params);
76 static void hildon_bread_crumb_widget_set_contents (HildonBreadCrumbWidget *bread_crumb);
78 static void hildon_bread_crumb_widget_clicked (GtkButton *button);
80 static void hildon_bread_crumb_widget_bread_crumb_init (HildonBreadCrumbIface *iface);
82 static void hildon_bread_crumb_widget_get_natural_size (HildonBreadCrumb *bread_crumb,
86 G_DEFINE_TYPE_WITH_CODE (HildonBreadCrumbWidget, hildon_bread_crumb_widget, GTK_TYPE_BUTTON,
87 G_IMPLEMENT_INTERFACE (HILDON_TYPE_BREAD_CRUMB,
88 hildon_bread_crumb_widget_bread_crumb_init))
91 hildon_bread_crumb_widget_class_init (HildonBreadCrumbWidgetClass *klass)
93 GObjectClass *gobject_class = (GObjectClass*)klass;
94 GtkButtonClass *button_class = (GtkButtonClass*)klass;
97 gobject_class->constructor = hildon_bread_crumb_widget_constructor;
98 gobject_class->finalize = hildon_bread_crumb_widget_finalize;
99 gobject_class->set_property = hildon_bread_crumb_widget_set_property;
100 gobject_class->get_property = hildon_bread_crumb_widget_get_property;
102 /* GtkButton signals */
103 button_class->clicked = hildon_bread_crumb_widget_clicked;
106 g_object_class_install_property (gobject_class,
108 g_param_spec_string ("text",
110 "Text of the label widget inside the bread crumb",
112 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
114 g_object_class_install_property (gobject_class,
116 g_param_spec_object ("icon",
118 "Image that will appear next to the bread crumb text",
120 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
122 g_object_class_install_property (gobject_class,
124 g_param_spec_enum ("icon-position",
126 "The position of the image relative to the text",
127 GTK_TYPE_POSITION_TYPE,
129 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
131 g_object_class_install_property (gobject_class,
133 g_param_spec_boolean ("show-separator",
135 "Show the separator attached to the item",
137 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
140 g_type_class_add_private (gobject_class, sizeof (HildonBreadCrumbWidgetPrivate));
144 hildon_bread_crumb_widget_bread_crumb_init (HildonBreadCrumbIface *iface)
146 iface->get_natural_size = hildon_bread_crumb_widget_get_natural_size;
150 hildon_bread_crumb_widget_constructor (GType type,
151 guint n_construct_properties,
152 GObjectConstructParam *construct_params)
155 HildonBreadCrumbWidget *bread_crumb;
156 HildonBreadCrumbWidgetPrivate *priv;
158 object = (* G_OBJECT_CLASS (hildon_bread_crumb_widget_parent_class)->constructor) (type,
159 n_construct_properties,
162 bread_crumb = HILDON_BREAD_CRUMB_WIDGET (object);
163 priv = bread_crumb->priv;
164 priv->constructed = TRUE;
166 priv->hbox = gtk_hbox_new (FALSE, 6);
167 gtk_container_add (GTK_CONTAINER (bread_crumb), priv->hbox);
170 priv->arrow = gtk_arrow_new (GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
171 gtk_widget_set_name (priv->arrow, "hildon-bread-crumb-separator-arrow");
172 gtk_box_pack_start (GTK_BOX (priv->hbox), priv->arrow, FALSE, FALSE, 0);
174 if (priv->show_separator)
175 gtk_widget_show (priv->arrow);
177 gtk_widget_set_no_show_all (priv->arrow, TRUE);
179 /* Contents base container */
180 bread_crumb->contents = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
181 gtk_container_add (GTK_CONTAINER (priv->hbox), bread_crumb->contents);
182 gtk_widget_show (bread_crumb->contents);
184 if (priv->text || priv->icon)
185 hildon_bread_crumb_widget_set_contents (bread_crumb);
187 /* Show everything */
188 gtk_widget_show (priv->hbox);
194 hildon_bread_crumb_widget_init (HildonBreadCrumbWidget *item)
196 HildonBreadCrumbWidgetPrivate *priv = HILDON_BREAD_CRUMB_WIDGET_GET_PRIVATE (item);
200 item->contents = NULL;
202 priv->constructed = FALSE;
205 priv->icon_position = GTK_POS_LEFT;
206 priv->show_separator = TRUE;
210 hildon_bread_crumb_widget_finalize (GObject *object)
212 HildonBreadCrumbWidgetPrivate *priv = HILDON_BREAD_CRUMB_WIDGET (object)->priv;
216 G_OBJECT_CLASS (hildon_bread_crumb_widget_parent_class)->finalize (object);
220 hildon_bread_crumb_widget_clicked (GtkButton *button)
222 hildon_bread_crumb_activated (HILDON_BREAD_CRUMB (button));
226 hildon_bread_crumb_widget_set_contents (HildonBreadCrumbWidget *bread_crumb)
228 GtkWidget *icon = NULL;
229 HildonBreadCrumbWidgetPrivate *priv = bread_crumb->priv;
231 if (!priv->constructed)
234 if (!priv->text && !priv->icon)
237 /* If the icon exists, keep it */
240 icon = g_object_ref (priv->icon);
242 gtk_container_remove (GTK_CONTAINER (icon->parent), icon);
247 if (bread_crumb->contents)
248 gtk_container_remove (GTK_CONTAINER (priv->hbox),
249 bread_crumb->contents);
254 if (priv->icon_position == GTK_POS_LEFT ||
255 priv->icon_position == GTK_POS_RIGHT)
256 bread_crumb->contents = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT);
258 bread_crumb->contents = gtk_vbox_new (FALSE, HILDON_MARGIN_DEFAULT);
260 if (priv->icon_position == GTK_POS_LEFT ||
261 priv->icon_position == GTK_POS_TOP)
262 gtk_box_pack_start (GTK_BOX (bread_crumb->contents), priv->icon,
265 gtk_box_pack_end (GTK_BOX (bread_crumb->contents), priv->icon,
270 priv->label = gtk_label_new (priv->text);
271 g_object_set (G_OBJECT (priv->label), "xalign", 0.0, NULL);
272 gtk_label_set_ellipsize (GTK_LABEL (priv->label),
273 PANGO_ELLIPSIZE_END);
275 if (priv->icon_position == GTK_POS_RIGHT ||
276 priv->icon_position == GTK_POS_BOTTOM)
277 gtk_box_pack_start (GTK_BOX (bread_crumb->contents), priv->label,
280 gtk_box_pack_end (GTK_BOX (bread_crumb->contents), priv->label,
285 gtk_box_pack_start (GTK_BOX (priv->hbox), bread_crumb->contents,
287 gtk_widget_show_all (bread_crumb->contents);
289 g_object_unref (icon);
294 bread_crumb->contents = gtk_hbox_new (FALSE, 0);
295 gtk_box_pack_start (GTK_BOX (priv->hbox), bread_crumb->contents,
298 priv->label = gtk_label_new (priv->text);
299 g_object_set (G_OBJECT (priv->label), "xalign", 0.0, NULL);
300 gtk_label_set_ellipsize (GTK_LABEL (priv->label),
301 PANGO_ELLIPSIZE_END);
302 gtk_box_pack_start (GTK_BOX (bread_crumb->contents), priv->label, TRUE, TRUE, 0);
304 gtk_widget_show_all (bread_crumb->contents);
309 hildon_bread_crumb_widget_set_property (GObject *object, guint prop_id,
310 const GValue *value, GParamSpec *pspec)
312 HildonBreadCrumbWidget *item = HILDON_BREAD_CRUMB_WIDGET (object);
317 _hildon_bread_crumb_widget_set_text (item, g_value_get_string (value));
320 _hildon_bread_crumb_widget_set_icon (item, (GtkWidget*)g_value_get_object (value));
322 case PROP_ICON_POSITION:
323 _hildon_bread_crumb_widget_set_icon_position (item, g_value_get_enum (value));
325 case PROP_SHOW_SEPARATOR:
326 _hildon_bread_crumb_widget_set_show_separator (item, g_value_get_boolean (value));
329 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
335 hildon_bread_crumb_widget_get_property (GObject *object, guint prop_id,
336 GValue *value, GParamSpec *pspec)
338 HildonBreadCrumbWidget *item = HILDON_BREAD_CRUMB_WIDGET (object);
343 g_value_set_string (value, item->priv->text);
346 g_value_set_object (value, (GObject *)item->priv->icon);
348 case PROP_ICON_POSITION:
349 g_value_set_enum (value, item->priv->icon_position);
351 case PROP_SHOW_SEPARATOR:
352 g_value_set_boolean (value, item->priv->show_separator);
355 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
361 _hildon_bread_crumb_widget_set_text (HildonBreadCrumbWidget *item,
364 HildonBreadCrumbWidgetPrivate *priv;
366 g_return_if_fail (HILDON_IS_BREAD_CRUMB_WIDGET (item));
373 priv->text = g_strdup (text);
375 hildon_bread_crumb_widget_set_contents (item);
377 g_object_notify (G_OBJECT (item), "text");
381 _hildon_bread_crumb_widget_get_text (HildonBreadCrumbWidget *item)
383 HildonBreadCrumbWidgetPrivate *priv;
385 g_return_val_if_fail (HILDON_IS_BREAD_CRUMB_WIDGET (item), NULL);
393 _hildon_bread_crumb_widget_set_show_separator (HildonBreadCrumbWidget *item,
394 gboolean show_separator)
396 HildonBreadCrumbWidgetPrivate *priv;
398 g_return_if_fail (HILDON_IS_BREAD_CRUMB_WIDGET (item));
402 if (priv->show_separator == show_separator)
405 priv->show_separator = show_separator;
407 if (!priv->constructed)
411 gtk_widget_show (priv->arrow);
413 gtk_widget_hide (priv->arrow);
415 g_object_notify (G_OBJECT (item), "show-separator");
419 hildon_bread_crumb_widget_get_natural_size (HildonBreadCrumb *bread_crumb,
421 gint *natural_height)
423 GtkRequisition widget_req, label_req;
426 HildonBreadCrumbWidget *item;
427 HildonBreadCrumbWidgetPrivate *priv;
429 g_return_if_fail (HILDON_IS_BREAD_CRUMB_WIDGET (bread_crumb));
431 item = HILDON_BREAD_CRUMB_WIDGET (bread_crumb);
434 gtk_widget_size_request (GTK_WIDGET (item), &widget_req);
436 layout = gtk_widget_create_pango_layout (priv->label, priv->text);
437 pango_layout_get_pixel_size (layout, &width, &height);
438 g_object_unref (layout);
442 *natural_width = widget_req.width;
443 /* Substract the size request of the label */
444 gtk_widget_size_request (priv->label, &label_req);
445 *natural_width -= label_req.width;
447 /* Add the "natural" width for the label */
448 *natural_width += width;
449 *natural_width += GTK_CONTAINER (item)->border_width * 2;
454 *natural_height = widget_req.height;
455 *natural_height += GTK_CONTAINER (item)->border_width * 2;
460 _hildon_bread_crumb_widget_new ()
462 return GTK_WIDGET (g_object_new (HILDON_TYPE_BREAD_CRUMB_WIDGET, NULL));
466 _hildon_bread_crumb_widget_new_with_text (const gchar *text)
468 return GTK_WIDGET (g_object_new (HILDON_TYPE_BREAD_CRUMB_WIDGET,
474 _hildon_bread_crumb_widget_new_with_icon (GtkWidget *icon, const gchar *text)
476 return GTK_WIDGET (g_object_new (HILDON_TYPE_BREAD_CRUMB_WIDGET,
483 _hildon_bread_crumb_widget_set_icon (HildonBreadCrumbWidget *bread_crumb,
486 HildonBreadCrumbWidgetPrivate *priv;
488 g_return_if_fail (HILDON_IS_BREAD_CRUMB_WIDGET (bread_crumb));
490 priv = bread_crumb->priv;
494 hildon_bread_crumb_widget_set_contents (bread_crumb);
496 g_object_notify (G_OBJECT (bread_crumb), "icon");
500 _hildon_bread_crumb_widget_set_icon_position (HildonBreadCrumbWidget *bread_crumb,
501 GtkPositionType icon_position)
503 HildonBreadCrumbWidgetPrivate *priv;
505 g_return_if_fail (HILDON_IS_BREAD_CRUMB_WIDGET (bread_crumb));
507 priv = bread_crumb->priv;
509 if (priv->icon_position == icon_position)
512 priv->icon_position = icon_position;
514 hildon_bread_crumb_widget_set_contents (bread_crumb);
516 g_object_notify (G_OBJECT (bread_crumb), "icon-position");