gtkhidingbox: add property to choose side to handle overflow

i.e. The case of Nautilus and FileChooser GtkPathBar is that we always
want to show the end part of the path. However that might not be the
case for other uses, like gnome-software and its titles.
parent ab639497
......@@ -29,6 +29,7 @@ struct _GtkHidingBoxPrivate
{
GList *children;
gint16 spacing;
gint inverted :1;
};
static void
......@@ -56,6 +57,7 @@ G_DEFINE_TYPE_WITH_CODE (GtkHidingBox, gtk_hiding_box, GTK_TYPE_CONTAINER,
enum {
PROP_0,
PROP_SPACING,
PROP_INVERTED,
LAST_PROP
};
......@@ -74,6 +76,9 @@ gtk_hiding_box_set_property (GObject *object,
case PROP_SPACING:
gtk_hiding_box_set_spacing (box, g_value_get_int (value));
break;
case PROP_INVERTED:
gtk_hiding_box_set_inverted (box, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
......@@ -94,6 +99,9 @@ gtk_hiding_box_get_property (GObject *object,
case PROP_SPACING:
g_value_set_int (value, priv->spacing);
break;
case PROP_INVERTED:
g_value_set_boolean (value, priv->inverted);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
......@@ -167,15 +175,21 @@ update_children_visibility (GtkHidingBox *box,
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
GtkWidget *child_widget;
GList *child;
GtkRequestedSize *sizes_temp;
gint i;
gint children_size = -priv->spacing;
GList *children;
gboolean allocate_more_children = TRUE;
*n_visible_children = 0;
*n_visible_children_expanding = 0;
children = g_list_copy (priv->children);
sizes_temp = g_newa (GtkRequestedSize, g_list_length (priv->children));
if (priv->inverted)
children = g_list_reverse (children);
/* Retrieve desired size for visible children. */
for (i = 0, child = priv->children; child != NULL; i++, child = child->next)
for (i = 0, child = children; child != NULL; i++, child = child->next)
{
child_widget = GTK_WIDGET (child->data);
if (!gtk_widget_get_visible (child_widget) || !allocate_more_children)
......@@ -186,22 +200,22 @@ update_children_visibility (GtkHidingBox *box,
gtk_widget_get_preferred_width_for_height (child_widget,
allocation->height,
&sizes[i].minimum_size,
&sizes[i].natural_size);
&sizes_temp[i].minimum_size,
&sizes_temp[i].natural_size);
/* Assert the api is working properly */
if (sizes[i].minimum_size < 0)
if (sizes_temp[i].minimum_size < 0)
g_error ("GtkHidingBox child %s minimum width: %d < 0 for height %d",
gtk_widget_get_name (child_widget),
sizes[i].minimum_size, allocation->height);
sizes_temp[i].minimum_size, allocation->height);
if (sizes[i].natural_size < sizes[i].minimum_size)
if (sizes_temp[i].natural_size < sizes_temp[i].minimum_size)
g_error ("GtkHidingBox child %s natural width: %d < minimum %d for height %d",
gtk_widget_get_name (child_widget),
sizes[i].natural_size, sizes[i].minimum_size,
sizes_temp[i].natural_size, sizes_temp[i].minimum_size,
allocation->height);
children_size += sizes[i].minimum_size + priv->spacing;
sizes[i].data = child_widget;
children_size += sizes_temp[i].minimum_size + priv->spacing;
sizes_temp[i].data = child_widget;
if (children_size > allocation->width)
{
......@@ -215,6 +229,22 @@ update_children_visibility (GtkHidingBox *box,
(*n_visible_children)++;
gtk_widget_set_child_visible (child_widget, TRUE);
}
for (i = 0; i < *n_visible_children; i++)
{
if (priv->inverted)
{
sizes[*n_visible_children - i - 1].minimum_size = sizes_temp[i].minimum_size;
sizes[*n_visible_children - i - 1].natural_size = sizes_temp[i].natural_size;
}
else
{
sizes[i].minimum_size = sizes_temp[i].minimum_size;
sizes[i].natural_size = sizes_temp[i].natural_size;
}
}
g_list_free (children);
}
static void
......@@ -329,12 +359,17 @@ gtk_hiding_box_get_preferred_width (GtkWidget *widget,
GList *child;
gint n_visible_children;
gboolean have_min = FALSE;
GList *children;
*minimum_width = 0;
*natural_width = 0;
children = g_list_copy (priv->children);
if (priv->inverted)
children = g_list_reverse (children);
n_visible_children = 0;
for (child = priv->children; child != NULL; child = child->next)
for (child = children; child != NULL; child = child->next)
{
if (!gtk_widget_is_visible (child->data))
continue;
......@@ -354,6 +389,8 @@ gtk_hiding_box_get_preferred_width (GtkWidget *widget,
/* Natural must also include the spacing */
if (priv->spacing && n_visible_children > 1)
*natural_width += priv->spacing * (n_visible_children - 1);
g_list_free (children);
}
static void
......@@ -386,9 +423,8 @@ gtk_hiding_box_init (GtkHidingBox *box)
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
gtk_widget_set_has_window (GTK_WIDGET (box), FALSE);
gtk_widget_set_redraw_on_allocate (GTK_WIDGET (box), FALSE);
priv->spacing = 0;
priv->inverted = FALSE;
}
static void
......@@ -416,6 +452,13 @@ gtk_hiding_box_class_init (GtkHidingBoxClass *class)
0, G_MAXINT, 0,
G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
hiding_box_properties[PROP_INVERTED] =
g_param_spec_int ("inverted",
_("Direction of hiding children inverted"),
P_("If false the container will start hiding widgets from the end when there is not enough space, and the oposite in case inverted is true."),
0, G_MAXINT, 0,
G_PARAM_READWRITE);
g_object_class_install_properties (object_class, LAST_PROP, hiding_box_properties);
}
......@@ -480,3 +523,35 @@ gtk_hiding_box_get_spacing (GtkHidingBox *box)
return priv->spacing;
}
void
gtk_hiding_box_set_inverted (GtkHidingBox *box,
gboolean inverted)
{
GtkHidingBoxPrivate *priv ;
g_return_if_fail (GTK_IS_HIDING_BOX (box));
priv = gtk_hiding_box_get_instance_private (box);
if (priv->inverted != inverted)
{
priv->inverted = inverted != FALSE;
g_object_notify (G_OBJECT (box), "inverted");
gtk_widget_queue_resize (GTK_WIDGET (box));
}
}
gboolean
gtk_hiding_box_get_inverted (GtkHidingBox *box)
{
GtkHidingBoxPrivate *priv ;
g_return_val_if_fail (GTK_IS_HIDING_BOX (box), 0);
priv = gtk_hiding_box_get_instance_private (box);
return priv->inverted;
}
......@@ -54,15 +54,21 @@ struct _GtkHidingBox
};
GDK_AVAILABLE_IN_3_20
GType gtk_hiding_box_get_type (void) G_GNUC_CONST;
GType gtk_hiding_box_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_3_20
GtkWidget *gtk_hiding_box_new (void);
GtkWidget *gtk_hiding_box_new (void);
GDK_AVAILABLE_IN_3_20
void gtk_hiding_box_set_spacing (GtkHidingBox *box,
gint spacing);
void gtk_hiding_box_set_spacing (GtkHidingBox *box,
gint spacing);
GDK_AVAILABLE_IN_3_20
gint gtk_hiding_box_get_spacing (GtkHidingBox *box);
gint gtk_hiding_box_get_spacing (GtkHidingBox *box);
GDK_AVAILABLE_IN_3_20
void gtk_hiding_box_set_inverted (GtkHidingBox *box,
gboolean inverted);
GDK_AVAILABLE_IN_3_20
gboolean gtk_hiding_box_get_inverted (GtkHidingBox *box);
G_END_DECLS
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment