*
* Copyright (C) 2007 Nokia Corporation, all rights reserved.
*
- * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
+ * Contact: Rodrigo Novo <rodrigo.novo@nokia.com>
* Author: Xan Lopez <xan.lopez@nokia.com>
*
* This library is free software; you can redistribute it and/or
* implemented if needed. See #HildonBreadCrumb for more details.
*/
+#undef HILDON_DISABLE_DEPRECATED
+
+#include <gdk/gdkkeysyms.h>
+
#include "hildon-marshalers.h"
#include "hildon-bread-crumb-trail.h"
#include "hildon-bread-crumb-widget.h"
enum {
CRUMB_CLICKED,
+ MOVE_PARENT,
LAST_SIGNAL
};
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 void hildon_bread_crumb_trail_move_parent (HildonBreadCrumbTrail *bct);
+
+static gpointer get_bread_crumb_id (HildonBreadCrumb *item);
static guint bread_crumb_trail_signals[LAST_SIGNAL] = { 0 };
GtkObjectClass *object_class = (GtkObjectClass*)klass;
GtkWidgetClass *widget_class = (GtkWidgetClass*)klass;
GtkContainerClass *container_class = (GtkContainerClass*)klass;
+ GtkBindingSet *binding_set;
/* GObject signals */
gobject_class->finalize = hildon_bread_crumb_trail_finalize;
container_class->forall = hildon_bread_crumb_trail_forall;
container_class->remove = hildon_bread_crumb_trail_remove;
+ /* HildonBreadCrumbTrail signals */
+ klass->move_parent = hildon_bread_crumb_trail_move_parent;
+
/* Style properties */
#define _BREAD_CRUMB_TRAIL_MINIMUM_WIDTH 10
_hildon_marshal_BOOLEAN__POINTER,
G_TYPE_BOOLEAN, 1,
G_TYPE_POINTER);
+
+ bread_crumb_trail_signals[MOVE_PARENT] =
+ g_signal_new ("move-parent",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (HildonBreadCrumbTrailClass, move_parent),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ /* Binding set */
+ binding_set = gtk_binding_set_by_class (widget_class);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
+ "move-parent", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0,
+ "move-parent", 0);
+
/* Private data */
g_type_class_add_private (gobject_class, sizeof (HildonBreadCrumbTrailPrivate));
}
}
static void
+hildon_bread_crumb_trail_move_parent (HildonBreadCrumbTrail *bct)
+{
+ if (g_list_length (bct->priv->item_list) > 1)
+ {
+ g_signal_emit_by_name (HILDON_BREAD_CRUMB (bct->priv->item_list->next->data),
+ "crumb-activated");
+ }
+}
+
+static void
hildon_bread_crumb_trail_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
GList *p, *first_show, *first_hide;
gint back_button_size;
HildonBreadCrumbTrailPrivate *priv = HILDON_BREAD_CRUMB_TRAIL (widget)->priv;
+ gboolean rtl;
+
+ /* Get the rtl status */
+ rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
widget->allocation = *allocation;
allocation_width = allocation->width - 2 * border_width;
/* Allocate the back button */
- child_allocation.x = allocation->x + border_width;
+ if (rtl)
+ child_allocation.x = allocation->width - border_width;
+ else
+ child_allocation.x = allocation->x + border_width;
+
child_allocation.y = allocation->y + border_width;
gtk_widget_get_child_requisition (priv->back_button, &child_requisition);
/* We want the back button to be a square */
back_button_size = MAX (child_requisition.width, child_requisition.height);
child_allocation.width = child_allocation.height = back_button_size;
+
+ if (rtl)
+ child_allocation.x -= back_button_size;
+
gtk_widget_size_allocate (priv->back_button, &child_allocation);
- child_allocation.x += back_button_size;
+
+ if (!rtl)
+ child_allocation.x += back_button_size;
/* If there are no buttons there's nothing else to do */
if (priv->item_list == NULL)
if (child_allocation.width > req.width)
{
first_hide = p->next;
- gtk_widget_size_allocate (child, &child_allocation);
gtk_widget_set_child_visible (child, TRUE);
- child_allocation.x += child_allocation.width;
+
+ if (rtl)
+ child_allocation.x -= child_allocation.width;
+
+ gtk_widget_size_allocate (child, &child_allocation);
+
+ if (!rtl)
+ child_allocation.x += child_allocation.width;
}
else
{
}
child_allocation.width = natural_width;
- gtk_widget_size_allocate (child, &child_allocation);
gtk_widget_set_child_visible (child, TRUE);
- child_allocation.x += child_allocation.width;
+
+ if (rtl)
+ child_allocation.x -= child_allocation.width;
+
+ gtk_widget_size_allocate (child, &child_allocation);
+
+ if (!rtl)
+ child_allocation.x += child_allocation.width;
}
for (p = first_hide; p; p = p->next)
{
item = HILDON_BREAD_CRUMB (p->data);
- child = GTK_WIDGET (item);
-
gtk_widget_set_child_visible (GTK_WIDGET (item), FALSE);
}
}
if (signal_handled == FALSE)
{
GtkWidget *child;
+ gboolean focus_last_item = FALSE;
HildonBreadCrumbTrailPrivate *priv;
priv = bct->priv;
/* We remove the tip of the list until we hit the clicked button */
while (child && child != button)
{
+ if (GTK_WIDGET_HAS_FOCUS (child))
+ focus_last_item = TRUE;
+
gtk_container_remove (GTK_CONTAINER (bct), child);
if (priv->item_list == NULL)
child = GTK_WIDGET (priv->item_list->data);
}
+
+ if (focus_last_item)
+ gtk_widget_grab_focus (GTK_WIDGET (bct->priv->item_list->data));
}
}
hildon_bread_crumb_trail_remove (GtkContainer *container,
GtkWidget *widget)
{
- GList *p;
+ GList *p, *next;
HildonBreadCrumbTrailPrivate *priv;
gboolean was_visible = GTK_WIDGET_VISIBLE (widget);
while (p)
{
+ next = p->next;
+
if (widget == GTK_WIDGET (p->data))
{
g_signal_handlers_disconnect_by_func (widget, G_CALLBACK (crumb_activated_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);
+ priv->item_list = g_list_delete_link (priv->item_list, p);
hildon_bread_crumb_trail_update_back_button_sensitivity (HILDON_BREAD_CRUMB_TRAIL (container));
}
}
- p = p->next;
+ p = next;
}
}
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));
+ hildon_bread_crumb_trail_move_parent (bct);
}
static void
g_return_if_fail (text != NULL);
widget = _hildon_bread_crumb_widget_new_with_text (text);
+ if (bct->priv->item_list == NULL)
+ {
+ g_object_set (G_OBJECT (widget), "show-separator", FALSE, NULL);
+ }
attach_bread_crumb (bct, widget, id, destroy);
}
/**
- * hildon_bread_crumb_trail_push_text:
+ * hildon_bread_crumb_trail_push_icon:
* @bct: pointer to #HildonBreadCrumbTrail
* @text: content of the new bread crumb
* @icon: a widget to set as the icon in the bread crumb
g_return_if_fail (GTK_IS_WIDGET (icon));
widget = _hildon_bread_crumb_widget_new_with_icon (icon, text);
+ if (bct->priv->item_list == NULL)
+ {
+ g_object_set (G_OBJECT (widget), "show-separator", FALSE, NULL);
+ }
attach_bread_crumb (bct, widget, id, destroy);
}
{
hildon_bread_crumb_trail_pop (bct);
}
+
+ /*
+ Sensitivity hack from hell. We need to do this while
+ http://bugzilla.gnome.org/show_bug.cgi?id=56070 is not
+ fixed to allow repeated clicking on the back button if
+ someone clears and rebuilds the trail when it's clicked
+ */
+ gtk_widget_hide (priv->back_button);
+ gtk_widget_show (priv->back_button);
}