* examples/Makefile.am * examples/hildon-bread-crumb-trail-example.c * src/Makefile...
authorXan Lopez <xan.lopez@nokia.com>
Thu, 12 Apr 2007 13:38:35 +0000 (13:38 +0000)
committerXan Lopez <xan.lopez@nokia.com>
Thu, 12 Apr 2007 13:38:35 +0000 (13:38 +0000)
New HildonBreadCrumbTrail widget.

ChangeLog
examples/Makefile.am
examples/hildon-bread-crumb-trail-example.c [new file with mode: 0644]
src/Makefile.am
src/hildon-bread-crumb-trail.c [new file with mode: 0644]
src/hildon-bread-crumb-trail.h [new file with mode: 0644]
src/hildon-bread-crumb.c [new file with mode: 0644]
src/hildon-bread-crumb.h [new file with mode: 0644]

index f085e76..477d933 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2007-04-12  Xan Lopez  <xan.lopez@nokia.com>
+
+       * examples/Makefile.am
+       * examples/hildon-bread-crumb-trail-example.c
+       * src/Makefile.am
+       * src/hildon-bread-crumb-trail.c
+       * src/hildon-bread-crumb-trail.h
+       * src/hildon-bread-crumb.c
+       * src/hildon-bread-crumb.h
+
+       New HildonBreadCrumbTrail widget.
+
 2007-04-02  Lucas Rocha  <lucas.rocha@nokia.com>
 
        * src/hildon-range-editor.c (hildon_range_editor_init),
index ccf4c06..dc0c578 100644 (file)
@@ -28,7 +28,8 @@ noinst_PROGRAMS                               = hildon-window-example                 \
                                          hildon-scrolled-window-example        \
                                          hildon-color-pop-example              \
                                          hildon-thumb-scrollbar-example        \
-                                         hildon-date-editor-example
+                                         hildon-date-editor-example            \
+                                         hildon-bread-crumb-trail-example
 
 # HIldon window
 hildon_window_example_LDADD            = $(HILDON_OBJ_LIBS)
@@ -170,4 +171,9 @@ hildon_date_editor_example_LDADD    = $(HILDON_OBJ_LIBS)
 hildon_date_editor_example_CFLAGS      = $(HILDON_OBJ_CFLAGS)
 hildon_date_editor_example_SOURCES     = hildon-date-editor-example.c
 
+# Hildon bread crumb trail example
+hildon_bread_crumb_trail_example_LDADD = $(HILDON_OBJ_LIBS)
+hildon_bread_crumb_trail_example_CFLAGS        = $(HILDON_OBJ_CFLAGS)
+hildon_bread_crumb_trail_example_SOURCES       = hildon-bread-crumb-trail-example.c
+
 endif
diff --git a/examples/hildon-bread-crumb-trail-example.c b/examples/hildon-bread-crumb-trail-example.c
new file mode 100644 (file)
index 0000000..e4f4b40
--- /dev/null
@@ -0,0 +1,205 @@
+#include <gtk/gtk.h>
+#include "hildon-bread-crumb-trail.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#if 1
+#include <hildon/hildon.h>
+#endif
+
+GtkWidget *treeview;
+gchar *current_root;
+
+enum {
+  ICON_COL,
+  STRING_COL,
+  IS_DIR_COL,
+  N_COLS
+};
+
+static void
+populate_store (GtkListStore *store,
+               const gchar *path)
+{
+  GDir *dir;
+  GError *error = NULL;
+  gchar *item;
+  GtkTreeIter iter;
+  struct stat stat_info;
+  GdkPixbuf *pixbuf = NULL;
+
+  dir = g_dir_open (path, 0, &error);
+  if (error)
+    {
+      g_debug ("Error populating store: %s", error->message);
+      g_error_free (error);
+      return;
+    }
+
+  while ((item = (gchar*)g_dir_read_name (dir)) != NULL)
+    {
+      gchar *file_path = g_strconcat (path, "/", item, NULL);
+
+      if (stat (file_path, &stat_info) == -1)
+       {
+         g_debug ("error retrieving stat info for %s", item);
+         continue;
+       }
+      g_free (file_path);
+
+      gtk_list_store_append (store, &iter);
+
+      if (S_ISDIR (stat_info.st_mode))
+       pixbuf = gdk_pixbuf_new_from_file ("./gnome-fs-directory.png", NULL);
+      else
+       pixbuf = gdk_pixbuf_new_from_file ("./gnome-mime-text.png", NULL);
+
+      gtk_list_store_set (store, &iter,
+                         ICON_COL, pixbuf,
+                         STRING_COL, item,
+                         IS_DIR_COL, S_ISDIR (stat_info.st_mode) ? TRUE : FALSE,
+                         -1);
+      if (pixbuf)
+       g_object_unref (pixbuf);
+    }
+
+  g_dir_close (dir);
+
+  return;
+}
+
+static void
+free_id (gpointer data)
+{
+  g_debug ("Freeing ID data");
+  g_free (data);
+}
+
+static void
+row_activated_cb (GtkTreeView *treeview,
+                 GtkTreePath *path,
+                 GtkTreeViewColumn *column,
+                 HildonBreadCrumbTrail *bct)
+{
+  gchar *text = NULL, *new_root;
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  gboolean is_dir;
+
+  model = gtk_tree_view_get_model (treeview);
+  gtk_tree_model_get_iter (model, &iter, path);
+  gtk_tree_model_get (model, &iter,
+                     STRING_COL, &text,
+                     IS_DIR_COL, &is_dir,
+                     -1);
+
+  if (is_dir == FALSE) goto out;
+
+  g_debug ("Clicked %s", text);
+
+  new_root = g_strconcat (g_str_equal (current_root, "/")? "" : current_root, "/", text, NULL);
+  gtk_list_store_clear (GTK_LIST_STORE (model));
+  populate_store (GTK_LIST_STORE (model), new_root);
+
+  hildon_bread_crumb_trail_push_text (bct, text, new_root, (GDestroyNotify)free_id);
+  
+  if (current_root)
+    {
+      g_free (current_root);
+    }
+
+  current_root = g_strdup (new_root);
+
+ out:
+  g_free (text);
+}
+
+static void
+crumb_clicked_cb (HildonBreadCrumbTrail *bct, gpointer id)
+{
+  GtkTreeModel *model;
+  gchar *text = (gchar*)id;
+
+  g_debug ("item %s clicked", text);
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
+  gtk_list_store_clear (GTK_LIST_STORE (model));
+  populate_store (GTK_LIST_STORE (model), text);
+  if (current_root)
+    g_free (current_root);
+  current_root = g_strdup (text);
+}
+
+int main (int argc, char **argv)
+{
+#if 1
+  HildonProgram *program;
+#endif
+  GtkListStore *store;
+  GtkWidget *window, *scrolled_window, *vbox, *bct;
+  GtkCellRenderer *renderer;
+  GtkTreeViewColumn *column;
+
+  gtk_init (&argc, &argv);
+
+  /* Main window */
+#if 1
+  program = hildon_program_get_instance ();
+  window = hildon_window_new ();
+  hildon_program_add_window (program, HILDON_WINDOW (window));
+#else
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+#endif
+  gtk_container_set_border_width (GTK_CONTAINER (window), 2);
+  gtk_window_set_default_size (GTK_WINDOW (window), 400, 600);
+  g_signal_connect (window, "delete-event", gtk_main_quit, NULL);
+
+  vbox = gtk_vbox_new (FALSE, 3);
+  gtk_container_add (GTK_CONTAINER (window), vbox);
+  gtk_widget_show (vbox);
+
+  current_root = g_strdup ("/");
+
+  bct = hildon_bread_crumb_trail_new ();
+  g_signal_connect (bct, "crumb-clicked", G_CALLBACK (crumb_clicked_cb), NULL);
+  gtk_box_pack_start (GTK_BOX (vbox), bct, FALSE, FALSE, 0);
+  gtk_widget_show (bct);
+
+  hildon_bread_crumb_trail_push_text (HILDON_BREAD_CRUMB_TRAIL (bct), "/",
+                                     g_strdup ("/"), (GDestroyNotify)free_id);
+
+  /* Treeview */
+  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                 GTK_POLICY_AUTOMATIC,
+                                 GTK_POLICY_AUTOMATIC);
+  store = gtk_list_store_new (N_COLS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_BOOLEAN);
+  populate_store (store, "/");
+  treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
+  g_signal_connect (treeview, "row-activated", G_CALLBACK (row_activated_cb), bct);
+
+  renderer = gtk_cell_renderer_pixbuf_new ();
+  column = gtk_tree_view_column_new_with_attributes ("Icon",
+                                                    renderer,
+                                                    "pixbuf", ICON_COL,
+                                                    NULL);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+  renderer = gtk_cell_renderer_text_new ();
+  column = gtk_tree_view_column_new_with_attributes ("Name",
+                                                    renderer,
+                                                    "text", STRING_COL,
+                                                    NULL);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+  gtk_container_add (GTK_CONTAINER (scrolled_window), treeview);
+  gtk_widget_show (treeview);
+  gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 0);
+  gtk_widget_show (scrolled_window);
+
+  gtk_widget_show (window);
+
+  gtk_main ();
+
+  return 0;
+}
index ab9adf3..433f70d 100644 (file)
@@ -58,7 +58,9 @@ libhildon_@PACKAGE_VERSION_MAJOR@_la_SOURCES          = hildon-private.c                              \
                                                          hildon-code-dialog.c                          \
                                                          hildon-enum-types.c                           \
                                                          hildon-marshalers.c                           \
-                                                         hildon-calendar.c
+                                                         hildon-calendar.c                             \
+                                                         hildon-bread-crumb-trail.c                    \
+                                                         hildon-bread-crumb.c
 
 libhildon_@PACKAGE_VERSION_MAJOR@_includedir           = $(includedir)/$(PACKAGE)-$(PACKAGE_VERSION_MAJOR)/$(PACKAGE)
 
@@ -97,7 +99,9 @@ libhildon_@PACKAGE_VERSION_MAJOR@_include_HEADERS     = hildon-banner.h                               \
                                                          hildon.h                                      \
                                                          hildon-window.h                               \
                                                          hildon-wizard-dialog.h                        \
-                                                         hildon-calendar.h
+                                                         hildon-calendar.h                             \
+                                                         hildon-bread-crumb-trail.h                    \
+                                                         hildon-bread-crumb.h
 
 noinst_HEADERS                                         = hildon-banner-private.h                       \
                                                          hildon-calendar-popup-private.h               \
diff --git a/src/hildon-bread-crumb-trail.c b/src/hildon-bread-crumb-trail.c
new file mode 100644 (file)
index 0000000..655141e
--- /dev/null
@@ -0,0 +1,688 @@
+/*
+ * This file is a part of hildon
+ *
+ * Copyright (C) 2007 Nokia Corporation, all rights reserved.
+ *
+ * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
+ * Author: Xan Lopez <xan.lopez@nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "hildon-bread-crumb-trail.h"
+
+#define HILDON_BREAD_CRUMB_TRAIL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_BREAD_CRUMB_TRAIL, HildonBreadCrumbTrailPrivate))
+
+struct _HildonBreadCrumbTrailPrivate
+{
+  GtkWidget *back_button;
+  GList *item_list;
+  gchar *path_separator;
+};
+
+/* Signals */
+
+enum {
+  CRUMB_CLICKED,
+  LAST_SIGNAL
+};
+
+/* Properties */
+
+enum {
+  PROP_0
+};
+
+static void hildon_bread_crumb_trail_size_request (GtkWidget *widget,
+                                                  GtkRequisition *requisition);
+static void hildon_bread_crumb_trail_size_allocate (GtkWidget *widget,
+                                                   GtkAllocation *allocation);
+static void hildon_bread_crumb_trail_add (GtkContainer *container,
+                                         GtkWidget *widget);
+static void hildon_bread_crumb_trail_forall (GtkContainer *container,
+                                            gboolean include_internals,
+                                            GtkCallback callback,
+                                            gpointer callback_data);
+static void hildon_bread_crumb_trail_remove (GtkContainer *container,
+                                            GtkWidget *widget);
+static void hildon_bread_crumb_trail_finalize (GObject *object);
+static void hildon_bread_crumb_trail_scroll_back (GtkWidget *button,
+                                                 HildonBreadCrumbTrail *bct);
+static void hildon_bread_crumb_trail_update_back_button_sensitivity (HildonBreadCrumbTrail *bct);
+
+static guint bread_crumb_trail_signals[LAST_SIGNAL] = { 0 };
+
+/* GType methods */
+
+G_DEFINE_TYPE (HildonBreadCrumbTrail, hildon_bread_crumb_trail, GTK_TYPE_CONTAINER)
+
+static void
+hildon_bread_crumb_trail_class_init (HildonBreadCrumbTrailClass *klass)
+{
+  GObjectClass *gobject_class = (GObjectClass*)klass;
+  GtkObjectClass *object_class = (GtkObjectClass*)klass;
+  GtkWidgetClass *widget_class = (GtkWidgetClass*)klass;
+  GtkContainerClass *container_class = (GtkContainerClass*)klass;
+
+  /* GObject signals */
+  gobject_class->finalize = hildon_bread_crumb_trail_finalize;
+
+  /* GtkWidget signals */
+  widget_class->size_request = hildon_bread_crumb_trail_size_request;
+  widget_class->size_allocate = hildon_bread_crumb_trail_size_allocate;
+
+  /* GtkContainer signals */
+  container_class->add = hildon_bread_crumb_trail_add;
+  container_class->forall = hildon_bread_crumb_trail_forall;
+  container_class->remove = hildon_bread_crumb_trail_remove;
+
+  /* Style properties */
+
+#define _BREAD_CRUMB_TRAIL_MINIMUM_WIDTH 10
+
+  /* FIXME: is this the best way to do it? */
+  gtk_widget_class_install_style_property (widget_class,
+                                          g_param_spec_int ("minimum-width",
+                                                            "Minimum width",
+                                                            "The minimum width in characters the children widgets will request",
+                                                            0,
+                                                            G_MAXINT,
+                                                            _BREAD_CRUMB_TRAIL_MINIMUM_WIDTH,
+                                                            G_PARAM_READABLE));
+
+#define _BREAD_CRUMB_TRAIL_MAXIMUM_WIDTH 250
+
+  gtk_widget_class_install_style_property (widget_class,
+                                          g_param_spec_int ("maximum-width",
+                                                            "Maximum width",
+                                                            "The maximum width in characters the children widgets will be allocated",
+                                                            0,
+                                                            G_MAXINT,
+                                                            _BREAD_CRUMB_TRAIL_MAXIMUM_WIDTH,
+                                                            G_PARAM_READABLE));
+                                                            
+#define _BREAD_CRUMB_TRAIL_ARROW_SIZE 34
+
+  gtk_widget_class_install_style_property (widget_class,
+                                          g_param_spec_int ("arrow-size",
+                                                            "Arrow size",
+                                                            "Size of the back button arrow",
+                                                            0,
+                                                            G_MAXINT,
+                                                            _BREAD_CRUMB_TRAIL_ARROW_SIZE,
+                                                            G_PARAM_READABLE));
+  /* Signals */
+  bread_crumb_trail_signals[CRUMB_CLICKED] =
+    g_signal_new ("crumb-clicked",
+                 G_OBJECT_CLASS_TYPE (object_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (HildonBreadCrumbTrailClass, crumb_clicked),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__POINTER,
+                 G_TYPE_NONE, 1,
+                 G_TYPE_POINTER);
+                 
+  /* Private data */
+  g_type_class_add_private (gobject_class, sizeof (HildonBreadCrumbTrailPrivate));
+}
+
+static void
+hildon_bread_crumb_trail_finalize (GObject *object)
+{
+  HildonBreadCrumbTrailPrivate *priv = HILDON_BREAD_CRUMB_TRAIL (object)->priv;
+
+  g_free (priv->path_separator);
+  g_list_free (priv->item_list);
+
+  G_OBJECT_CLASS (hildon_bread_crumb_trail_parent_class)->finalize (object);
+}
+
+static void
+hildon_bread_crumb_trail_size_request (GtkWidget *widget,
+                                      GtkRequisition *requisition)
+{
+  GList *p;
+  GtkRequisition child_requisition;
+  HildonBreadCrumbTrail *bct;
+  HildonBreadCrumbTrailPrivate *priv;
+  gint minimum_width, width = 0;
+  PangoLayout *layout;
+  gchar *tmp = NULL;
+
+  bct= HILDON_BREAD_CRUMB_TRAIL (widget);
+  priv = bct->priv;
+
+  requisition->height = 0;
+  requisition->width = 0;
+
+  gtk_widget_size_request (priv->back_button, &child_requisition);
+  g_debug ("BACK BUTTON REQUEST %d %d", child_requisition.width, child_requisition.width);
+  requisition->width = child_requisition.width;
+  requisition->height = child_requisition.height;
+
+  if (priv->item_list)
+    {
+      /* Add minimum width for one item */
+      /* TODO: this can be probably cached */
+      gtk_widget_style_get (widget,
+                           "minimum-width", &minimum_width,
+                           NULL);
+
+      tmp = g_strnfill ((gsize)minimum_width, 'm');
+      layout = gtk_widget_create_pango_layout (widget, tmp);
+      g_free (tmp);
+      pango_layout_get_size (layout, &width, NULL);
+      requisition->width += PANGO_PIXELS (width);
+      g_object_unref (layout);
+    }
+
+  /* Button requisitions */
+  for (p = priv->item_list; p; p = p->next)
+    {
+      gtk_widget_size_request (GTK_WIDGET (p->data), &child_requisition);
+    }
+
+  /* Border width */
+  requisition->width += GTK_CONTAINER (widget)->border_width * 2;
+  requisition->height += GTK_CONTAINER (widget)->border_width * 2;
+
+  widget->requisition = *requisition;
+}
+
+/* Document me please */
+
+static void
+hildon_bread_crumb_trail_size_allocate (GtkWidget *widget,
+                                       GtkAllocation *allocation)
+{
+  GtkRequisition req;
+  gint natural_width, natural_height;
+  HildonBreadCrumb *item;
+  GtkAllocation child_allocation;
+  GtkRequisition child_requisition;
+  GtkWidget *child;
+  gint allocation_width;
+  gint border_width, width;
+  gint extra_space;
+  gint maximum_width;
+  gint desired_width;
+  GList *p, *first_show, *first_hide;
+  HildonBreadCrumbTrailPrivate *priv = HILDON_BREAD_CRUMB_TRAIL (widget)->priv;
+
+  widget->allocation = *allocation;
+
+  border_width = (gint) GTK_CONTAINER (widget)->border_width;
+  allocation_width = allocation->width - 2 * border_width;
+
+  /* Allocate the back button */
+  child_allocation.x = allocation->x;
+  child_allocation.y = allocation->y;
+  gtk_widget_get_child_requisition (priv->back_button, &child_requisition);
+  child_allocation.width = child_requisition.width;
+  child_allocation.height = child_requisition.height;
+  gtk_widget_size_allocate (priv->back_button, &child_allocation);
+  child_allocation.x += child_allocation.width;
+
+  /* If there are no buttons there's nothing else to do */
+  if (priv->item_list == NULL)
+    return;
+
+  /* We find out how many buttons can we show, starting from the
+     the last one in the logical path (the first item in the list) */
+
+  width = child_allocation.width;
+  p = priv->item_list;
+  first_show = NULL;
+  first_hide = NULL; 
+  extra_space = 0;
+
+  for (p = priv->item_list; p; p = p->next)
+    {
+      item = HILDON_BREAD_CRUMB (p->data);
+      child = GTK_WIDGET (item);
+
+      /* Does the widget fit with its natural size? */
+      hildon_bread_crumb_get_natural_size (item,
+                                          &natural_width,
+                                          &natural_height);
+
+      gtk_widget_style_get (widget,
+                           "maximum-width", &maximum_width,
+                           NULL);
+
+      desired_width = MIN (natural_width, maximum_width);
+
+      if (width + desired_width <= allocation_width)
+       {
+         /* Yes, it does */
+         first_show = p;
+         first_hide = p->next;
+         width += desired_width;
+         g_debug ("It fits %s at x %d, width %d", hildon_bread_crumb_get_text (item),
+                  child_allocation.x, desired_width);
+       }
+      else
+       {
+         /* No, it doesn't. Allocate as much as possible
+            and stop */
+         child_allocation.width = allocation_width - width;
+
+         gtk_widget_size_request (child, &req);
+
+         if (child_allocation.width > req.width)
+           {
+             first_hide = p->next;
+             gtk_widget_size_allocate (child, &child_allocation);
+             gtk_widget_show (child);
+             gtk_widget_set_child_visible (child, TRUE);
+             g_debug ("It doesn't. Allocated %s at x: %d, width %d, size_req width is %d",
+                      hildon_bread_crumb_get_text (item), 
+                      child_allocation.x, child_allocation.width,
+                      req.width);
+             child_allocation.x += child_allocation.width;
+           }
+         else
+           {
+             extra_space = child_allocation.width;
+           }
+
+         break;
+       }
+    }
+
+  /* Not enough items to fill the breadcrumb? */
+  if (p == NULL && width < allocation_width)
+    {
+      extra_space = allocation_width - width;
+    }
+
+  /* Allocate the other buttons */
+  for (p = first_show; p; p = p->prev)
+    {
+      item = HILDON_BREAD_CRUMB (p->data);
+      child = GTK_WIDGET (item);
+
+      /* Does the widget fit with its natural size? */
+      hildon_bread_crumb_get_natural_size (item,
+                                          &natural_width,
+                                          &natural_height);
+
+      gtk_widget_style_get (widget,
+                           "maximum-width", &maximum_width,
+                           NULL);
+
+      desired_width = MIN (natural_width, maximum_width);
+
+      /* If I'm the last and there's extra space, use it */
+      if (p->prev == NULL && extra_space != 0)
+       {
+         desired_width += extra_space;
+       }
+
+      child_allocation.width = desired_width;
+      gtk_widget_size_allocate (child, &child_allocation);
+      gtk_widget_show (child);
+      gtk_widget_set_child_visible (child, TRUE);
+      g_debug ("Natural Size. Allocated %s at x: %d, width %d",
+              hildon_bread_crumb_get_text (item), 
+              child_allocation.x, child_allocation.width);
+      child_allocation.x += child_allocation.width;
+    }
+
+  for (p = first_hide; p; p = p->next)
+    {
+      item = HILDON_BREAD_CRUMB (p->data);
+      child = GTK_WIDGET (item);
+
+      g_debug ("Hiding %s", hildon_bread_crumb_get_text (item));
+      gtk_widget_hide (GTK_WIDGET (item));
+      gtk_widget_set_child_visible (GTK_WIDGET (item), FALSE);
+    }
+}
+
+static gpointer
+get_bread_crumb_id (HildonBreadCrumb *item)
+{
+  return g_object_get_data (G_OBJECT (item), "bread-crumb-id");
+}
+
+static void
+crumb_clicked_cb (GtkWidget *button,
+                 HildonBreadCrumbTrail *bct)
+{
+  GtkWidget *child;
+  HildonBreadCrumbTrailPrivate *priv;
+
+  priv = bct->priv;
+
+  child = GTK_WIDGET (priv->item_list->data);
+
+  /* We remove the tip of the list until we hit the clicked button */
+  while (child != button)
+    {
+      gtk_container_remove (GTK_CONTAINER (bct), child);
+
+      child = GTK_WIDGET (priv->item_list->data);
+    }
+
+  /* We need the item for the ID */
+  g_signal_emit (bct, bread_crumb_trail_signals[CRUMB_CLICKED], 0,
+                get_bread_crumb_id (HILDON_BREAD_CRUMB (child)));
+}
+
+static void
+hildon_bread_crumb_trail_add (GtkContainer *container,
+                             GtkWidget *widget)
+{
+  gtk_widget_set_parent (widget, GTK_WIDGET (container));
+}
+
+static void
+hildon_bread_crumb_trail_forall (GtkContainer *container,
+                                gboolean include_internals,
+                                GtkCallback callback,
+                                gpointer callback_data)
+{
+  g_return_if_fail (callback != NULL);
+  g_return_if_fail (HILDON_IS_BREAD_CRUMB_TRAIL (container));
+
+  GList *children;
+  HildonBreadCrumbTrailPrivate *priv = HILDON_BREAD_CRUMB_TRAIL (container)->priv;
+
+  children = priv->item_list;
+
+  while (children)
+    {
+      GtkWidget *child;
+      child = GTK_WIDGET (children->data);
+      children = children->next;
+
+      (*callback) (child, callback_data);
+    }
+
+  if (include_internals && priv->back_button)
+    {
+      (*callback) (priv->back_button, callback_data);
+    }
+}
+
+static void
+hildon_bread_crumb_trail_remove (GtkContainer *container,
+                                GtkWidget *widget)
+{
+  GList *p;
+  HildonBreadCrumbTrailPrivate *priv;
+  gboolean was_visible = GTK_WIDGET_VISIBLE (widget);
+
+  priv = HILDON_BREAD_CRUMB_TRAIL (container)->priv;
+
+  p = priv->item_list;
+
+  while (p)
+    {
+      if (widget == GTK_WIDGET (p->data))
+       {
+         g_signal_handlers_disconnect_by_func (widget, G_CALLBACK (crumb_clicked_cb),
+                                               HILDON_BREAD_CRUMB_TRAIL (container));
+         gtk_widget_unparent (widget);
+
+         priv->item_list = g_list_remove_link (priv->item_list, p);
+         g_list_free (p);
+
+         hildon_bread_crumb_trail_update_back_button_sensitivity (HILDON_BREAD_CRUMB_TRAIL (container));
+
+         if (was_visible)
+           {
+             gtk_widget_queue_resize (GTK_WIDGET (container));
+           }
+       }
+
+      p = p->next;
+    }
+}
+
+static void
+hildon_bread_crumb_trail_update_back_button_sensitivity (HildonBreadCrumbTrail *bct)
+{
+  guint list_length;
+  HildonBreadCrumbTrailPrivate *priv = bct->priv;
+
+  list_length = g_list_length (priv->item_list);
+
+  if (list_length == 0 || list_length == 1)
+    {
+      gtk_widget_set_sensitive (priv->back_button, FALSE);
+    }
+  else
+    {
+      gtk_widget_set_sensitive (priv->back_button, TRUE);
+    }
+}
+
+static GtkWidget*
+create_back_button (HildonBreadCrumbTrail *bct)
+{
+  GtkWidget *button;
+  GtkWidget *arrow;
+  gint arrow_size;
+
+  gtk_widget_push_composite_child ();
+
+  button = gtk_button_new ();
+  gtk_widget_set_name (button, "hildon-bread-crumb-back-button");
+  gtk_widget_set_sensitive (button, FALSE);
+
+  arrow = gtk_arrow_new (GTK_ARROW_LEFT, GTK_SHADOW_NONE);
+  gtk_widget_style_get (GTK_WIDGET (bct),
+                       "arrow-size", &arrow_size,
+                       NULL);
+  gtk_widget_set_size_request (arrow, arrow_size, arrow_size);
+
+  gtk_container_add (GTK_CONTAINER (button), arrow);
+  gtk_container_add (GTK_CONTAINER (bct), button);
+  gtk_widget_show_all (button);
+
+  gtk_widget_pop_composite_child ();
+
+  return button;
+}
+
+static void
+hildon_bread_crumb_trail_init (HildonBreadCrumbTrail *bct)
+{
+  HildonBreadCrumbTrailPrivate *priv = HILDON_BREAD_CRUMB_TRAIL_GET_PRIVATE (bct);
+
+  GTK_WIDGET_SET_FLAGS (bct, GTK_NO_WINDOW);
+  gtk_widget_set_redraw_on_allocate (GTK_WIDGET (bct), FALSE);
+
+  bct->priv = priv;
+  priv->item_list = NULL;
+
+  priv->back_button = create_back_button (bct);
+  g_signal_connect (priv->back_button, "clicked",
+                   G_CALLBACK (hildon_bread_crumb_trail_scroll_back),
+                   bct);
+}
+
+static void
+hildon_bread_crumb_trail_scroll_back (GtkWidget *button,
+                                     HildonBreadCrumbTrail *bct)
+{
+  HildonBreadCrumb *item;
+
+  hildon_bread_crumb_trail_pop (bct);
+
+  item = HILDON_BREAD_CRUMB (bct->priv->item_list->data);
+
+  g_signal_emit (bct, bread_crumb_trail_signals[CRUMB_CLICKED], 0,
+                get_bread_crumb_id (item));
+}
+
+static GtkWidget*
+create_crumb_button (HildonBreadCrumbTrail *bct,
+                    const gchar *text,
+                    gpointer id,
+                    GDestroyNotify destroy)
+{
+  GtkWidget *item;
+
+  item = hildon_bread_crumb_new (text);
+
+  if (id)
+    g_object_set_data_full (G_OBJECT (item), "bread-crumb-id", id, destroy);
+
+  g_signal_connect (G_OBJECT (item), "clicked",
+                   G_CALLBACK (crumb_clicked_cb), bct);
+
+  return item;
+}
+
+
+/* PUBLIC API */
+
+/**
+ * hildon_bread_crumb_trail_new:
+ * 
+ * Creates a new #HildonBreadCrumbTrail widget.
+ *
+ * Returns: a #GtkWidget pointer of newly created bread crumb trail
+ * widget
+ */
+
+GtkWidget*
+hildon_bread_crumb_trail_new (void)
+{
+  return GTK_WIDGET (g_object_new (HILDON_TYPE_BREAD_CRUMB_TRAIL, NULL));
+}
+
+/* This is stupidly duplicated from the simple API, consolidate */
+
+/**
+ * hildon_bread_crumb_trail_push:
+ * @bct: pointer to #HildonBreadCrumbTrail
+ * @item: the #HildonBreadCrumb to be added to the trail
+ * @id: optional id for the bread crumb
+ * @destroy: GDestroyNotify callback to be called when the bread crumb is destroyed
+ *
+ * Adds a new bread crumb to the end of the trail.
+ */
+
+void
+hildon_bread_crumb_trail_push (HildonBreadCrumbTrail *bct,
+                              HildonBreadCrumb *item,
+                              gpointer id,
+                              GDestroyNotify destroy)
+{
+  GtkWidget *widget;
+  HildonBreadCrumbTrailPrivate *priv = bct->priv;
+
+  g_return_if_fail (HILDON_IS_BREAD_CRUMB_TRAIL (bct));
+  g_return_if_fail (HILDON_IS_BREAD_CRUMB (item));
+
+  widget = GTK_WIDGET (item);
+
+  gtk_container_add (GTK_CONTAINER (bct), widget);
+  gtk_widget_show (widget);
+
+  if (id)
+    g_object_set_data_full (G_OBJECT (item), "bread-crumb-id", id, destroy);
+
+  g_signal_connect (G_OBJECT (item), "clicked",
+                   G_CALLBACK (crumb_clicked_cb), bct);
+
+  priv->item_list = g_list_prepend (priv->item_list, widget);
+
+  hildon_bread_crumb_trail_update_back_button_sensitivity (bct);
+}
+
+/**
+ * hildon_bread_crumb_trail_push_text:
+ * @bct: pointer to #HildonBreadCrumbTrail
+ * @text: content of the new bread crumb
+ * @id: optional id for the bread crumb
+ * @destroy: GDestroyNotify callback to be called when the bread crumb is destroyed
+ *
+ * Adds a new bread crumb to the end of the trail containing the specified text.
+ */
+
+void
+hildon_bread_crumb_trail_push_text (HildonBreadCrumbTrail *bct,
+                                   const gchar *text,
+                                   gpointer id,
+                                   GDestroyNotify destroy)
+{
+  GtkWidget *widget;
+  HildonBreadCrumbTrailPrivate *priv = bct->priv;
+
+  g_return_if_fail (HILDON_IS_BREAD_CRUMB_TRAIL (bct));
+  g_return_if_fail (text != NULL);
+
+  widget = create_crumb_button (bct, text, id, destroy);
+  gtk_container_add (GTK_CONTAINER (bct), widget);
+  gtk_widget_show (widget);
+
+  priv->item_list = g_list_prepend (priv->item_list, widget);
+
+  hildon_bread_crumb_trail_update_back_button_sensitivity (bct);
+}
+
+/**
+ * hildon_bread_crumb_trail_pop:
+ * @bct: pointer to #HildonBreadCrumbTrail
+ *
+ * Removes the last bread crumb from the trail.
+ */
+
+void
+hildon_bread_crumb_trail_pop (HildonBreadCrumbTrail *bct)
+{
+  GtkWidget *child;
+  HildonBreadCrumbTrailPrivate *priv;
+
+  g_return_if_fail (HILDON_IS_BREAD_CRUMB_TRAIL (bct));
+
+  priv = bct->priv;
+
+  if (priv->item_list == NULL)
+    return;
+
+  if (priv->item_list)
+    {
+      child = GTK_WIDGET (priv->item_list->data);
+      gtk_container_remove (GTK_CONTAINER (bct), child);
+    }
+
+  hildon_bread_crumb_trail_update_back_button_sensitivity (bct);
+}
+
+/**
+ * hildon_bread_crumb_trail_clear:
+ * @bct: pointer to #HildonBreadCrumbTrail
+ *
+ * Removes all the bread crumbs from the bread crumb trail.
+ */
+
+void
+hildon_bread_crumb_trail_clear (HildonBreadCrumbTrail *bct)
+{
+  HildonBreadCrumbTrailPrivate *priv = bct->priv;
+
+  while (priv->item_list)
+    {
+      hildon_bread_crumb_trail_pop (bct);
+    }
+}
diff --git a/src/hildon-bread-crumb-trail.h b/src/hildon-bread-crumb-trail.h
new file mode 100644 (file)
index 0000000..016c549
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * This file is a part of hildon
+ *
+ * Copyright (C) 2007 Nokia Corporation, all rights reserved.
+ *
+ * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
+ * Author: Xan Lopez <xan.lopez@nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __HILDON_BREAD_CRUMB_TRAIL_H__
+#define __HILDON_BREAD_CRUMB_TRAIL_H__
+
+#include <gtk/gtk.h>
+#include "hildon-bread-crumb.h"
+
+G_BEGIN_DECLS
+
+typedef struct _HildonBreadCrumbTrail  HildonBreadCrumbTrail;
+typedef struct _HildonBreadCrumbTrailClass     HildonBreadCrumbTrailClass;
+typedef struct _HildonBreadCrumbTrailPrivate HildonBreadCrumbTrailPrivate;
+
+#define HILDON_TYPE_BREAD_CRUMB_TRAIL                 (hildon_bread_crumb_trail_get_type ())
+#define HILDON_BREAD_CRUMB_TRAIL(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), HILDON_TYPE_BREAD_CRUMB_TRAIL, HildonBreadCrumbTrail))
+#define HILDON_BREAD_CRUMB_TRAIL_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), HILDON_TYPE_BREAD_CRUMB_TRAIL, HildonBreadCrumbTrailClass))
+#define HILDON_IS_BREAD_CRUMB_TRAIL(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_BREAD_CRUMB_TRAIL))
+#define HILDON_IS_BREAD_CRUMB_TRAIL_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_BREAD_CRUMB_TRAIL))
+#define HILDON_BREAD_CRUMB_TRAIL_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), HILDON_TYPE_BREAD_CRUMB_TRAIL, HildonBreadCrumbTrailClass))
+
+struct _HildonBreadCrumbTrail
+{
+  GtkContainer parent;
+
+  HildonBreadCrumbTrailPrivate *priv;
+};
+
+struct _HildonBreadCrumbTrailClass
+{
+  GtkContainerClass parent_class;
+
+  void (*crumb_clicked) (HildonBreadCrumbTrail *bct,
+                        gpointer id);
+};
+
+GType hildon_bread_crumb_trail_get_type (void) G_GNUC_CONST;
+GtkWidget *hildon_bread_crumb_trail_new (void);
+void hildon_bread_crumb_trail_push (HildonBreadCrumbTrail *bct, HildonBreadCrumb *item,
+                             gpointer id, GDestroyNotify  notify);
+void hildon_bread_crumb_trail_push_text (HildonBreadCrumbTrail *bct, const gchar *text,
+                                  gpointer id, GDestroyNotify notify);
+void hildon_bread_crumb_trail_pop (HildonBreadCrumbTrail *bct);
+void hildon_bread_crumb_trail_clear (HildonBreadCrumbTrail *bct);
+
+G_END_DECLS
+
+#endif
diff --git a/src/hildon-bread-crumb.c b/src/hildon-bread-crumb.c
new file mode 100644 (file)
index 0000000..2da2dce
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ * This file is a part of hildon
+ *
+ * Copyright (C) 2007 Nokia Corporation, all rights reserved.
+ *
+ * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
+ * Author: Xan Lopez <xan.lopez@nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "hildon-bread-crumb.h"
+
+#define HILDON_BREAD_CRUMB_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_BREAD_CRUMB, HildonBreadCrumbPrivate))
+
+struct _HildonBreadCrumbPrivate
+{
+  GtkWidget *icon;
+  GtkWidget *label;
+  GtkWidget *arrow;
+  gchar *text;
+
+  gboolean show_separator;
+};
+
+/* Signals */
+
+enum {
+  LAST_SIGNAL
+};
+
+/* Properties */
+
+enum {
+  PROP_0,
+  PROP_TEXT,
+  PROP_SHOW_SEPARATOR
+};
+
+/*
+static guint bread_crumb_item_signals[LAST_SIGNAL] = { 0 };
+*/
+
+/* GType methods */
+
+static void hildon_bread_crumb_finalize (GObject *object);
+static void hildon_bread_crumb_set_property (GObject *object, guint prop_id,
+                                                 const GValue *value, GParamSpec *pspec);
+static void hildon_bread_crumb_get_property (GObject *object, guint prop_id,
+                                                 GValue *value, GParamSpec *pspec);
+
+G_DEFINE_TYPE (HildonBreadCrumb, hildon_bread_crumb, GTK_TYPE_BUTTON)
+
+static void
+hildon_bread_crumb_class_init (HildonBreadCrumbClass *klass)
+{
+  GObjectClass *gobject_class = (GObjectClass*)klass;
+
+  /* GObject signals */
+  gobject_class->finalize = hildon_bread_crumb_finalize;
+  gobject_class->set_property = hildon_bread_crumb_set_property;
+  gobject_class->get_property = hildon_bread_crumb_get_property;
+
+  /* Properties */
+  g_object_class_install_property (gobject_class,
+                                  PROP_TEXT,
+                                  g_param_spec_string ("text",
+                                                       "Text",
+                                                       "Text displayed as the name of the item",
+                                                       NULL,
+                                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+  g_object_class_install_property (gobject_class,
+                                  PROP_SHOW_SEPARATOR,
+                                  g_param_spec_boolean ("show-separator",
+                                                        "Show separator",
+                                                        "Show the separator attached to the item",
+                                                        TRUE,
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+  /* Private data */
+  g_type_class_add_private (gobject_class, sizeof (HildonBreadCrumbPrivate));
+}
+
+static void
+hildon_bread_crumb_init (HildonBreadCrumb *item)
+{
+  GtkWidget *hbox;
+  HildonBreadCrumbPrivate *priv = HILDON_BREAD_CRUMB_GET_PRIVATE (item);
+
+  item->priv = priv;
+
+  hbox = gtk_hbox_new (FALSE, 6);
+  gtk_container_add (GTK_CONTAINER (item), hbox);
+
+  priv->arrow = gtk_arrow_new (GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
+  gtk_widget_set_name (priv->arrow, "hildon-bread-crumb-separator-arrow");
+  gtk_box_pack_start (GTK_BOX (hbox), priv->arrow, FALSE, FALSE, 0);
+
+  if (priv->show_separator)
+    gtk_widget_show (priv->arrow);
+
+  priv->label = gtk_label_new ("");
+  gtk_box_pack_start (GTK_BOX (hbox), priv->label, TRUE, TRUE, 0);
+  gtk_widget_show (priv->label);
+
+  gtk_widget_show (hbox);
+}
+
+static void
+hildon_bread_crumb_finalize (GObject *object)
+{
+  HildonBreadCrumbPrivate *priv = HILDON_BREAD_CRUMB (object)->priv;
+
+  g_free (priv->text);
+
+  G_OBJECT_CLASS (hildon_bread_crumb_parent_class)->finalize (object);
+}
+
+static void
+hildon_bread_crumb_set_property (GObject *object, guint prop_id,
+                                     const GValue *value, GParamSpec *pspec)
+{
+  HildonBreadCrumb *item = HILDON_BREAD_CRUMB (object);
+
+  switch (prop_id)
+    {
+    case PROP_TEXT:
+      hildon_bread_crumb_set_text (item, g_value_get_string (value));
+      break;
+    case PROP_SHOW_SEPARATOR:
+      hildon_bread_crumb_set_show_separator (item, g_value_get_boolean (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+hildon_bread_crumb_get_property (GObject *object, guint prop_id,
+                                     GValue *value, GParamSpec *pspec)
+{
+  HildonBreadCrumb *item = HILDON_BREAD_CRUMB (object);
+
+  switch (prop_id)
+    {
+    case PROP_TEXT:
+      g_value_set_string (value, item->priv->text);
+      break;
+    case PROP_SHOW_SEPARATOR:
+      g_value_set_boolean (value, item->priv->show_separator);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+void
+hildon_bread_crumb_set_text (HildonBreadCrumb *item,
+                                 const gchar *text)
+{
+  HildonBreadCrumbPrivate *priv;
+
+  g_return_if_fail (HILDON_IS_BREAD_CRUMB (item));
+
+  priv = item->priv;
+
+  if (priv->text)
+    g_free (priv->text);
+
+  priv->text = g_strdup (text);
+
+  gtk_label_set_label (GTK_LABEL (priv->label), text);
+  gtk_label_set_ellipsize (GTK_LABEL (item->priv->label),
+                          PANGO_ELLIPSIZE_START);
+  gtk_widget_show (priv->label);
+
+  g_object_notify (G_OBJECT (item), "text");
+}
+
+const gchar*
+hildon_bread_crumb_get_text (HildonBreadCrumb *item)
+{
+  HildonBreadCrumbPrivate *priv;
+
+  g_return_val_if_fail (HILDON_IS_BREAD_CRUMB (item), NULL);
+
+  priv = item->priv;
+
+  return priv->text;
+}
+
+void
+hildon_bread_crumb_set_show_separator (HildonBreadCrumb *item,
+                                           gboolean show_separator)
+{
+  HildonBreadCrumbPrivate *priv;
+
+  g_return_if_fail (HILDON_IS_BREAD_CRUMB (item));
+
+  priv = item->priv;
+
+  if (priv->show_separator == show_separator)
+    return;
+  
+  priv->show_separator = show_separator;
+
+  if (show_separator)
+    gtk_widget_show (priv->arrow);
+  else
+    gtk_widget_hide (priv->arrow);
+
+  g_object_notify (G_OBJECT (item), "show-separator");
+}
+
+void
+hildon_bread_crumb_get_natural_size (HildonBreadCrumb *item,
+                                         gint *natural_width,
+                                         gint *natural_height)
+{
+  GtkRequisition req;
+  gint width, height;
+  PangoLayout *layout;
+  HildonBreadCrumbPrivate *priv;
+
+  g_return_if_fail (HILDON_IS_BREAD_CRUMB (item));
+
+  priv = item->priv;
+
+  gtk_widget_size_request (GTK_WIDGET (item), &req);
+  if (natural_width)
+    *natural_width = req.width;
+
+  if (natural_height)
+    *natural_height = req.height;
+  /* Substract the size request of the label */
+  gtk_widget_size_request (priv->label, &req);
+  if (natural_width)
+    *natural_width -= req.width;
+  layout = gtk_widget_create_pango_layout (priv->label, priv->text);
+  pango_layout_get_size (layout, &width, &height);
+
+  if (natural_width)
+    *natural_width += PANGO_PIXELS (width);
+  /* Border width */
+  if (natural_width)
+    *natural_width += GTK_CONTAINER (item)->border_width * 2;
+
+  if (natural_height)
+    *natural_height += GTK_CONTAINER (item)->border_width * 2;
+}
+
+GtkWidget*
+hildon_bread_crumb_new (const gchar* text)
+{
+  return GTK_WIDGET (g_object_new (HILDON_TYPE_BREAD_CRUMB,
+                                  "text", text,
+                                  NULL));
+}
+
diff --git a/src/hildon-bread-crumb.h b/src/hildon-bread-crumb.h
new file mode 100644 (file)
index 0000000..257b3e2
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * This file is a part of hildon
+ *
+ * Copyright (C) 2007 Nokia Corporation, all rights reserved.
+ *
+ * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
+ * Author: Xan Lopez <xan.lopez@nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __HILDON_BREAD_CRUMB_H__
+#define __HILDON_BREAD_CRUMB_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _HildonBreadCrumb       HildonBreadCrumb;
+typedef struct _HildonBreadCrumbClass  HildonBreadCrumbClass;
+typedef struct _HildonBreadCrumbPrivate HildonBreadCrumbPrivate;
+
+#define HILDON_TYPE_BREAD_CRUMB                 (hildon_bread_crumb_get_type ())
+#define HILDON_BREAD_CRUMB(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), HILDON_TYPE_BREAD_CRUMB, HildonBreadCrumb))
+#define HILDON_BREAD_CRUMB_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), HILDON_TYPE_BREAD_CRUMB, HildonBreadCrumbClass))
+#define HILDON_IS_BREAD_CRUMB(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_BREAD_CRUMB))
+#define HILDON_IS_BREAD_CRUMB_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_BREAD_CRUMB))
+#define HILDON_BREAD_CRUMB_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), HILDON_TYPE_BREAD_CRUMB, HildonBreadCrumbClass))
+
+struct _HildonBreadCrumb
+{
+  GtkButton parent;
+
+  HildonBreadCrumbPrivate *priv;
+};
+
+struct _HildonBreadCrumbClass
+{
+  GtkButtonClass parent_class;
+};
+
+GType hildon_bread_crumb_get_type (void) G_GNUC_CONST;
+GtkWidget *hildon_bread_crumb_new (const gchar* text);
+void hildon_bread_crumb_set_text (HildonBreadCrumb *item, const gchar *text);
+const gchar* hildon_bread_crumb_get_text (HildonBreadCrumb *item);
+void hildon_bread_crumb_get_natural_size (HildonBreadCrumb *item,
+                                         gint *width, gint *height);
+void hildon_bread_crumb_set_show_separator (HildonBreadCrumb *item,
+                                           gboolean show_separator);
+
+G_END_DECLS
+
+#endif