forked from AuroraMiddleware/gtk
expander: Convert to use box gadgets
Use a vertical box gadget for the overall expander, and a horizontal one for the title row. This lets us get rid of all the custom allocation code here.
This commit is contained in:
parent
5f5dc10820
commit
2e27c0af25
@ -120,6 +120,7 @@
|
||||
#include "a11y/gtkexpanderaccessible.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtkcsscustomgadgetprivate.h"
|
||||
#include "gtkboxgadgetprivate.h"
|
||||
#include "gtkbuiltiniconprivate.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
#include "gtkcontainerprivate.h"
|
||||
@ -245,48 +246,6 @@ static void gesture_multipress_released_cb (GtkGestureMultiPress *gesture,
|
||||
gdouble y,
|
||||
GtkExpander *expander);
|
||||
|
||||
/* Gadgets */
|
||||
static void gtk_expander_measure (GtkCssGadget *gadget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum_size,
|
||||
int *natural_size,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline,
|
||||
gpointer data);
|
||||
static void gtk_expander_allocate (GtkCssGadget *gadget,
|
||||
const GtkAllocation *allocation,
|
||||
int baseline,
|
||||
GtkAllocation *out_clip,
|
||||
gpointer data);
|
||||
static gboolean gtk_expander_render (GtkCssGadget *gadget,
|
||||
cairo_t *cr,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
gpointer data);
|
||||
static void gtk_expander_measure_title (GtkCssGadget *gadget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum_size,
|
||||
int *natural_size,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline,
|
||||
gpointer data);
|
||||
static void gtk_expander_allocate_title (GtkCssGadget *gadget,
|
||||
const GtkAllocation *allocation,
|
||||
int baseline,
|
||||
GtkAllocation *out_clip,
|
||||
gpointer data);
|
||||
static gboolean gtk_expander_render_title (GtkCssGadget *gadget,
|
||||
cairo_t *cr,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
gpointer data);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkExpander, gtk_expander, GTK_TYPE_BIN,
|
||||
G_ADD_PRIVATE (GtkExpander)
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
|
||||
@ -484,22 +443,15 @@ gtk_expander_init (GtkExpander *expander)
|
||||
priv->resize_toplevel = 0;
|
||||
|
||||
widget_node = gtk_widget_get_css_node (GTK_WIDGET (expander));
|
||||
priv->gadget = gtk_css_custom_gadget_new_for_node (widget_node,
|
||||
GTK_WIDGET (expander),
|
||||
gtk_expander_measure,
|
||||
gtk_expander_allocate,
|
||||
gtk_expander_render,
|
||||
NULL,
|
||||
NULL);
|
||||
priv->title_gadget = gtk_css_custom_gadget_new ("title",
|
||||
GTK_WIDGET (expander),
|
||||
priv->gadget,
|
||||
NULL,
|
||||
gtk_expander_measure_title,
|
||||
gtk_expander_allocate_title,
|
||||
gtk_expander_render_title,
|
||||
NULL,
|
||||
NULL);
|
||||
priv->gadget = gtk_box_gadget_new_for_node (widget_node, GTK_WIDGET (expander));
|
||||
gtk_box_gadget_set_orientation (GTK_BOX_GADGET (priv->gadget), GTK_ORIENTATION_VERTICAL);
|
||||
priv->title_gadget = gtk_box_gadget_new ("title",
|
||||
GTK_WIDGET (expander),
|
||||
priv->gadget,
|
||||
NULL);
|
||||
gtk_box_gadget_set_orientation (GTK_BOX_GADGET (priv->title_gadget), GTK_ORIENTATION_HORIZONTAL);
|
||||
gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), -1, priv->title_gadget, FALSE, FALSE, GTK_ALIGN_FILL);
|
||||
|
||||
priv->arrow_gadget = gtk_builtin_icon_new ("arrow",
|
||||
GTK_WIDGET (expander),
|
||||
priv->title_gadget,
|
||||
@ -507,6 +459,8 @@ gtk_expander_init (GtkExpander *expander)
|
||||
gtk_css_gadget_add_class (priv->arrow_gadget, GTK_STYLE_CLASS_HORIZONTAL);
|
||||
gtk_builtin_icon_set_default_size_property (GTK_BUILTIN_ICON (priv->arrow_gadget), "expander-size");
|
||||
|
||||
gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->title_gadget), -1, priv->arrow_gadget, FALSE, FALSE, GTK_ALIGN_CENTER);
|
||||
|
||||
gtk_drag_dest_set (GTK_WIDGET (expander), 0, NULL, 0, 0);
|
||||
gtk_drag_dest_set_track_motion (GTK_WIDGET (expander), TRUE);
|
||||
|
||||
@ -703,156 +657,27 @@ static void
|
||||
gtk_expander_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *allocation)
|
||||
{
|
||||
GtkExpanderPrivate *priv = GTK_EXPANDER (widget)->priv;
|
||||
GtkAllocation clip;
|
||||
|
||||
gtk_widget_set_allocation (widget, allocation);
|
||||
|
||||
gtk_css_gadget_allocate (GTK_EXPANDER (widget)->priv->gadget,
|
||||
gtk_css_gadget_allocate (priv->gadget,
|
||||
allocation,
|
||||
gtk_widget_get_allocated_baseline (widget),
|
||||
&clip);
|
||||
|
||||
gtk_widget_set_clip (widget, &clip);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_expander_allocate (GtkCssGadget *gadget,
|
||||
const GtkAllocation *allocation,
|
||||
gint baseline,
|
||||
GtkAllocation *out_clip,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GtkExpander *expander;
|
||||
GtkWidget *child;
|
||||
GtkExpanderPrivate *priv;
|
||||
GtkAllocation title_allocation;
|
||||
GtkAllocation title_clip;
|
||||
gint title_height_min, title_height_nat;
|
||||
|
||||
widget = gtk_css_gadget_get_owner (gadget);
|
||||
expander = GTK_EXPANDER (widget);
|
||||
priv = expander->priv;
|
||||
child = gtk_bin_get_child (GTK_BIN (widget));
|
||||
|
||||
gtk_css_gadget_get_preferred_size (priv->title_gadget,
|
||||
GTK_ORIENTATION_VERTICAL,
|
||||
allocation->width,
|
||||
&title_height_min, &title_height_nat,
|
||||
NULL, NULL);
|
||||
|
||||
title_allocation.x = allocation->x;
|
||||
title_allocation.y = allocation->y;
|
||||
title_allocation.width = allocation->width;
|
||||
title_allocation.height = CLAMP (title_height_nat, title_height_min, allocation->height);
|
||||
|
||||
gtk_css_gadget_allocate (priv->title_gadget, &title_allocation, baseline, &title_clip);
|
||||
|
||||
if (gtk_widget_get_realized (widget))
|
||||
gdk_window_move_resize (priv->event_window,
|
||||
title_allocation.x, title_allocation.y,
|
||||
title_allocation.width, title_allocation.height);
|
||||
|
||||
if (child && gtk_widget_get_child_visible (child))
|
||||
{
|
||||
GtkAllocation child_allocation;
|
||||
GtkAllocation title_allocation;
|
||||
|
||||
child_allocation.x = allocation->x;
|
||||
child_allocation.y = allocation->y + title_allocation.height;
|
||||
child_allocation.width = allocation->width;
|
||||
child_allocation.height = allocation->height - title_allocation.height;
|
||||
|
||||
gtk_widget_size_allocate (child, &child_allocation);
|
||||
gtk_css_gadget_get_border_allocation (priv->title_gadget, &title_allocation, NULL);
|
||||
gdk_window_move_resize (priv->event_window,
|
||||
title_allocation.x, title_allocation.y,
|
||||
title_allocation.width, title_allocation.height);
|
||||
}
|
||||
|
||||
gtk_container_get_children_clip (GTK_CONTAINER (expander), out_clip);
|
||||
gdk_rectangle_union (out_clip, &title_clip, out_clip);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_expander_allocate_title (GtkCssGadget *gadget,
|
||||
const GtkAllocation *allocation,
|
||||
gint baseline,
|
||||
GtkAllocation *out_clip,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GtkExpander *expander;
|
||||
GtkExpanderPrivate *priv;
|
||||
gint arrow_width, arrow_height;
|
||||
gint label_height;
|
||||
gint label_xoffset;
|
||||
GtkAllocation arrow_allocation;
|
||||
GtkAllocation clip;
|
||||
|
||||
widget = gtk_css_gadget_get_owner (gadget);
|
||||
expander = GTK_EXPANDER (widget);
|
||||
priv = expander->priv;
|
||||
|
||||
gtk_css_gadget_get_preferred_size (priv->arrow_gadget,
|
||||
GTK_ORIENTATION_HORIZONTAL,
|
||||
-1,
|
||||
NULL, &arrow_width,
|
||||
NULL, NULL);
|
||||
gtk_css_gadget_get_preferred_size (priv->arrow_gadget,
|
||||
GTK_ORIENTATION_VERTICAL,
|
||||
-1,
|
||||
NULL, &arrow_height,
|
||||
NULL, NULL);
|
||||
|
||||
label_xoffset = arrow_width;
|
||||
if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
|
||||
{
|
||||
GtkAllocation label_allocation;
|
||||
gint label_width;
|
||||
|
||||
gtk_widget_get_preferred_width (priv->label_widget, NULL, &label_width);
|
||||
|
||||
if (priv->label_fill)
|
||||
label_allocation.width = allocation->width - label_xoffset;
|
||||
else
|
||||
label_allocation.width = MIN (label_width, allocation->width - label_xoffset);
|
||||
|
||||
label_allocation.width = MAX (label_allocation.width, 1);
|
||||
|
||||
/* We distribute the minimum height to the label widget and prioritize
|
||||
* the child widget giving it the remaining height
|
||||
*/
|
||||
gtk_widget_get_preferred_height_for_width (priv->label_widget,
|
||||
label_allocation.width, &label_height, NULL);
|
||||
|
||||
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
|
||||
label_allocation.x = allocation->x + allocation->width - label_xoffset - label_width;
|
||||
else
|
||||
label_allocation.x = allocation->x + label_xoffset;
|
||||
|
||||
label_allocation.y = allocation->y + MAX (0, (arrow_height - label_height) / 2);
|
||||
label_allocation.height = label_height;
|
||||
|
||||
gtk_widget_size_allocate (priv->label_widget, &label_allocation);
|
||||
|
||||
label_height = label_allocation.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
label_height = 0;
|
||||
}
|
||||
|
||||
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
|
||||
arrow_allocation.x = allocation->x + allocation->width - arrow_width;
|
||||
else
|
||||
arrow_allocation.x = allocation->x;
|
||||
arrow_allocation.y = allocation->y + MAX (0, (label_height - arrow_height) / 2);
|
||||
arrow_allocation.width = arrow_width;
|
||||
arrow_allocation.height = arrow_height;
|
||||
|
||||
gtk_css_gadget_allocate (priv->arrow_gadget,
|
||||
&arrow_allocation,
|
||||
gtk_widget_get_allocated_baseline (widget),
|
||||
&clip);
|
||||
|
||||
gtk_container_get_children_clip (GTK_CONTAINER (expander), out_clip);
|
||||
gdk_rectangle_union (out_clip, &clip, out_clip);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -883,24 +708,6 @@ gtk_expander_unmap (GtkWidget *widget)
|
||||
gtk_widget_unmap (priv->label_widget);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_expander_render_title (GtkCssGadget *gadget,
|
||||
cairo_t *cr,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
|
||||
GtkExpander *expander = GTK_EXPANDER (widget);
|
||||
GtkExpanderPrivate *priv = expander->priv;
|
||||
|
||||
gtk_css_gadget_draw (priv->arrow_gadget, cr);
|
||||
|
||||
return gtk_widget_has_visible_focus (widget);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_expander_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
@ -910,25 +717,6 @@ gtk_expander_draw (GtkWidget *widget,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_expander_render (GtkCssGadget *gadget,
|
||||
cairo_t *cr,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
|
||||
GtkExpander *expander = GTK_EXPANDER (widget);
|
||||
|
||||
gtk_css_gadget_draw (expander->priv->title_gadget, cr);
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_expander_parent_class)->draw (widget, cr);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gesture_multipress_released_cb (GtkGestureMultiPress *gesture,
|
||||
gint n_press,
|
||||
@ -1310,10 +1098,14 @@ static void
|
||||
gtk_expander_add (GtkContainer *container,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkExpander *expander = GTK_EXPANDER (container);
|
||||
|
||||
GTK_CONTAINER_CLASS (gtk_expander_parent_class)->add (container, widget);
|
||||
|
||||
gtk_widget_set_child_visible (widget, GTK_EXPANDER (container)->priv->expanded);
|
||||
gtk_widget_queue_resize (GTK_WIDGET (container));
|
||||
|
||||
if (expander->priv->expanded)
|
||||
gtk_box_gadget_insert_widget (GTK_BOX_GADGET (expander->priv->gadget), -1, widget);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1325,7 +1117,10 @@ gtk_expander_remove (GtkContainer *container,
|
||||
if (GTK_EXPANDER (expander)->priv->label_widget == widget)
|
||||
gtk_expander_set_label_widget (expander, NULL);
|
||||
else
|
||||
GTK_CONTAINER_CLASS (gtk_expander_parent_class)->remove (container, widget);
|
||||
{
|
||||
gtk_box_gadget_remove_widget (GTK_BOX_GADGET (expander->priv->gadget), widget);
|
||||
GTK_CONTAINER_CLASS (gtk_expander_parent_class)->remove (container, widget);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1402,140 +1197,6 @@ gtk_expander_get_preferred_height_for_width (GtkWidget *widget,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_expander_measure (GtkCssGadget *gadget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GtkExpander *expander;
|
||||
GtkExpanderPrivate *priv;
|
||||
GtkWidget *child;
|
||||
|
||||
widget = gtk_css_gadget_get_owner (gadget);
|
||||
expander = GTK_EXPANDER (widget);
|
||||
priv = expander->priv;
|
||||
child = gtk_bin_get_child (GTK_BIN (widget));
|
||||
|
||||
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
gint title_height;
|
||||
gtk_css_gadget_get_preferred_size (priv->title_gadget,
|
||||
GTK_ORIENTATION_VERTICAL,
|
||||
-1,
|
||||
&title_height, NULL,
|
||||
NULL, NULL);
|
||||
gtk_css_gadget_get_preferred_size (priv->title_gadget,
|
||||
GTK_ORIENTATION_HORIZONTAL,
|
||||
title_height,
|
||||
minimum, natural,
|
||||
NULL, NULL);
|
||||
|
||||
if (child && gtk_widget_get_child_visible (child))
|
||||
{
|
||||
gint child_min, child_nat;
|
||||
|
||||
if (for_size > -1)
|
||||
gtk_widget_get_preferred_width_for_height (child, MAX (for_size - priv->spacing - title_height, 0), &child_min, &child_nat);
|
||||
else
|
||||
gtk_widget_get_preferred_width (child, &child_min, &child_nat);
|
||||
|
||||
*minimum = MAX (*minimum, child_min);
|
||||
*natural = MAX (*natural, child_nat);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_gadget_get_preferred_size (priv->title_gadget,
|
||||
GTK_ORIENTATION_VERTICAL,
|
||||
for_size,
|
||||
minimum, natural,
|
||||
NULL, NULL);
|
||||
|
||||
if (child && gtk_widget_get_child_visible (child))
|
||||
{
|
||||
gint child_min, child_nat;
|
||||
|
||||
if (for_size > 0)
|
||||
gtk_widget_get_preferred_height_for_width (child,
|
||||
for_size,
|
||||
&child_min, &child_nat);
|
||||
else
|
||||
gtk_widget_get_preferred_height (child, &child_min, &child_nat);
|
||||
|
||||
*minimum += child_min + priv->spacing;
|
||||
*natural += child_nat + priv->spacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gtk_expander_measure_title (GtkCssGadget *gadget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GtkExpander *expander;
|
||||
GtkExpanderPrivate *priv;
|
||||
gint arrow_width, arrow_height;
|
||||
gint label_min, label_nat;
|
||||
|
||||
widget = gtk_css_gadget_get_owner (gadget);
|
||||
expander = GTK_EXPANDER (widget);
|
||||
priv = expander->priv;
|
||||
|
||||
gtk_css_gadget_get_preferred_size (priv->arrow_gadget,
|
||||
GTK_ORIENTATION_HORIZONTAL,
|
||||
-1,
|
||||
NULL, &arrow_width,
|
||||
NULL, NULL);
|
||||
gtk_css_gadget_get_preferred_size (priv->arrow_gadget,
|
||||
GTK_ORIENTATION_VERTICAL,
|
||||
-1,
|
||||
NULL, &arrow_height,
|
||||
NULL, NULL);
|
||||
|
||||
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
|
||||
gtk_widget_get_preferred_width (priv->label_widget, &label_min, &label_nat);
|
||||
else
|
||||
label_min = label_nat = 0;
|
||||
|
||||
*minimum = arrow_width + label_min;
|
||||
*natural = arrow_width + label_nat;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
|
||||
{
|
||||
if (for_size > 0)
|
||||
gtk_widget_get_preferred_height_for_width (priv->label_widget,
|
||||
MAX (for_size - arrow_width, 1),
|
||||
&label_min, &label_nat);
|
||||
else
|
||||
gtk_widget_get_preferred_height (priv->label_widget,
|
||||
&label_min, &label_nat);
|
||||
}
|
||||
else
|
||||
label_min = label_nat = 0;
|
||||
|
||||
*minimum = MAX (arrow_height, label_min);
|
||||
*natural = MAX (arrow_height, label_nat);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_expander_new:
|
||||
* @label: the text of the label
|
||||
@ -1612,7 +1273,11 @@ gtk_expander_set_expanded (GtkExpander *expander,
|
||||
|
||||
if (child)
|
||||
{
|
||||
gtk_widget_set_child_visible (child, priv->expanded);
|
||||
if (priv->expanded)
|
||||
gtk_box_gadget_insert_widget (GTK_BOX_GADGET (priv->gadget), 1, child);
|
||||
else
|
||||
gtk_box_gadget_remove_widget (GTK_BOX_GADGET (priv->gadget), child);
|
||||
|
||||
gtk_widget_queue_resize (GTK_WIDGET (expander));
|
||||
gtk_expander_resize_toplevel (expander);
|
||||
}
|
||||
@ -1897,6 +1562,7 @@ gtk_expander_set_label_widget (GtkExpander *expander,
|
||||
|
||||
if (priv->label_widget)
|
||||
{
|
||||
gtk_box_gadget_remove_widget (GTK_BOX_GADGET (priv->title_gadget), priv->label_widget);
|
||||
gtk_widget_set_state_flags (priv->label_widget, 0, TRUE);
|
||||
gtk_widget_unparent (priv->label_widget);
|
||||
}
|
||||
@ -1916,6 +1582,8 @@ gtk_expander_set_label_widget (GtkExpander *expander,
|
||||
gtk_widget_set_state_flags (label_widget,
|
||||
GTK_STATE_FLAG_PRELIGHT,
|
||||
FALSE);
|
||||
|
||||
gtk_box_gadget_insert_widget (GTK_BOX_GADGET (priv->title_gadget), 1, label_widget);
|
||||
}
|
||||
|
||||
if (gtk_widget_get_visible (widget))
|
||||
|
Loading…
Reference in New Issue
Block a user