checkbutton: Use a box gadget

Now that builtin icons have a baseline, we can just use
a box gadget with baseline alignment for the indicator
and the label.
This commit is contained in:
Matthias Clasen 2016-01-17 21:16:33 -05:00
parent da30858ee4
commit 7859f8ee91

View File

@ -35,7 +35,7 @@
#include "gtkwidgetprivate.h" #include "gtkwidgetprivate.h"
#include "gtkbuiltiniconprivate.h" #include "gtkbuiltiniconprivate.h"
#include "gtkcssnodeprivate.h" #include "gtkcssnodeprivate.h"
#include "gtkcsscustomgadgetprivate.h" #include "gtkboxgadgetprivate.h"
#include "gtkcontainerprivate.h" #include "gtkcontainerprivate.h"
#include "gtkstylecontextprivate.h" #include "gtkstylecontextprivate.h"
#include "gtkcssnumbervalueprivate.h" #include "gtkcssnumbervalueprivate.h"
@ -106,29 +106,6 @@ static void gtk_check_button_size_allocate (GtkWidget *widget,
GtkAllocation *allocation); GtkAllocation *allocation);
static gboolean gtk_check_button_draw (GtkWidget *widget, static gboolean gtk_check_button_draw (GtkWidget *widget,
cairo_t *cr); cairo_t *cr);
static void gtk_check_button_draw_indicator (GtkCheckButton *check_button,
cairo_t *cr);
static void gtk_check_button_measure (GtkCssGadget *gadget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline,
gpointer unused);
static void gtk_check_button_allocate (GtkCssGadget *gadget,
const GtkAllocation *allocation,
int baseline,
GtkAllocation *out_clip,
gpointer unused);
static gboolean gtk_check_button_render (GtkCssGadget *gadget,
cairo_t *cr,
int x,
int y,
int width,
int height,
gpointer data);
typedef struct { typedef struct {
GtkCssGadget *gadget; GtkCssGadget *gadget;
@ -206,11 +183,34 @@ gtk_check_button_finalize (GObject *object)
G_OBJECT_CLASS (gtk_check_button_parent_class)->finalize (object); G_OBJECT_CLASS (gtk_check_button_parent_class)->finalize (object);
} }
static void
gtk_check_button_add (GtkContainer *container,
GtkWidget *widget)
{
GtkCheckButtonPrivate *priv = gtk_check_button_get_instance_private (GTK_CHECK_BUTTON (container));
GTK_CONTAINER_CLASS (gtk_check_button_parent_class)->add (container, widget);
gtk_box_gadget_insert_widget (GTK_BOX_GADGET (priv->gadget), 1, widget);
}
static void
gtk_check_button_remove (GtkContainer *container,
GtkWidget *widget)
{
GtkCheckButtonPrivate *priv = gtk_check_button_get_instance_private (GTK_CHECK_BUTTON (container));
gtk_box_gadget_remove_widget (GTK_BOX_GADGET (priv->gadget), widget);
GTK_CONTAINER_CLASS (gtk_check_button_parent_class)->remove (container, widget);
}
static void static void
gtk_check_button_class_init (GtkCheckButtonClass *class) gtk_check_button_class_init (GtkCheckButtonClass *class)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (class); GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
object_class->finalize = gtk_check_button_finalize; object_class->finalize = gtk_check_button_finalize;
@ -224,6 +224,9 @@ gtk_check_button_class_init (GtkCheckButtonClass *class)
widget_class->state_flags_changed = gtk_check_button_state_flags_changed; widget_class->state_flags_changed = gtk_check_button_state_flags_changed;
widget_class->direction_changed = gtk_check_button_direction_changed; widget_class->direction_changed = gtk_check_button_direction_changed;
container_class->add = gtk_check_button_add;
container_class->remove = gtk_check_button_remove;
/** /**
* GtkCheckButton:indicator-size: * GtkCheckButton:indicator-size:
* *
@ -321,19 +324,14 @@ gtk_check_button_init (GtkCheckButton *check_button)
gtk_style_context_remove_class (gtk_widget_get_style_context (GTK_WIDGET (check_button)), "toggle"); gtk_style_context_remove_class (gtk_widget_get_style_context (GTK_WIDGET (check_button)), "toggle");
widget_node = gtk_widget_get_css_node (GTK_WIDGET (check_button)); widget_node = gtk_widget_get_css_node (GTK_WIDGET (check_button));
priv->gadget = gtk_css_custom_gadget_new_for_node (widget_node, priv->gadget = gtk_box_gadget_new_for_node (widget_node, GTK_WIDGET (check_button));
GTK_WIDGET (check_button), gtk_box_gadget_set_orientation (GTK_BOX_GADGET (priv->gadget), GTK_ORIENTATION_HORIZONTAL);
gtk_check_button_measure,
gtk_check_button_allocate,
gtk_check_button_render,
NULL,
NULL);
priv->indicator_gadget = gtk_builtin_icon_new ("check", priv->indicator_gadget = gtk_builtin_icon_new ("check",
GTK_WIDGET (check_button), GTK_WIDGET (check_button),
priv->gadget, priv->gadget,
NULL); NULL);
gtk_builtin_icon_set_default_size_property (GTK_BUILTIN_ICON (priv->indicator_gadget), "indicator-size"); gtk_builtin_icon_set_default_size_property (GTK_BUILTIN_ICON (priv->indicator_gadget), "indicator-size");
gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), 0, priv->indicator_gadget, FALSE, FALSE, GTK_ALIGN_BASELINE);
gtk_check_button_update_node_state (GTK_WIDGET (check_button)); gtk_check_button_update_node_state (GTK_WIDGET (check_button));
} }
@ -386,145 +384,6 @@ gtk_check_button_new_with_mnemonic (const gchar *label)
NULL); NULL);
} }
static gboolean
gtk_check_button_render (GtkCssGadget *gadget,
cairo_t *cr,
int x,
int y,
int width,
int height,
gpointer data)
{
GtkWidget *widget;
GtkWidget *child;
widget = gtk_css_gadget_get_owner (gadget);
gtk_check_button_draw_indicator (GTK_CHECK_BUTTON (widget), cr);
child = gtk_bin_get_child (GTK_BIN (widget));
if (child)
gtk_container_propagate_draw (GTK_CONTAINER (widget), child, cr);
if (gtk_widget_has_visible_focus (widget))
{
GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
GtkStyleContext *context;
GtkAllocation allocation;
gtk_widget_get_allocation (widget, &allocation);
context = gtk_widget_get_style_context (widget);
if (child && gtk_widget_get_visible (child))
{
GtkAllocation child_allocation;
gtk_widget_get_allocation (child, &child_allocation);
gtk_render_focus (context, cr,
child_allocation.x - allocation.x,
child_allocation.y - allocation.y,
child_allocation.width,
child_allocation.height);
}
else
gtk_render_focus (context, cr, x, y, width, height);
}
return FALSE;
}
static void
gtk_check_button_measure (GtkCssGadget *gadget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline,
gpointer unused)
{
GtkWidget *widget;
GtkCheckButtonPrivate *priv;
widget = gtk_css_gadget_get_owner (gadget);
priv = gtk_check_button_get_instance_private (GTK_CHECK_BUTTON (widget));
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
GtkWidget *child;
gint check_min, check_nat;
gtk_css_gadget_get_preferred_size (priv->indicator_gadget,
GTK_ORIENTATION_HORIZONTAL,
for_size,
&check_min, &check_nat,
NULL, NULL);
child = gtk_bin_get_child (GTK_BIN (widget));
if (child && gtk_widget_get_visible (child))
{
gint child_min, child_nat;
_gtk_widget_get_preferred_size_for_size (child,
GTK_ORIENTATION_HORIZONTAL,
for_size,
&child_min, &child_nat,
NULL, NULL);
*minimum = check_min + child_min;
*natural = check_nat + child_nat;
}
else
{
*minimum = check_min;
*natural = check_nat;
}
}
else
{
GtkWidget *child;
gint check_min, check_nat;
gint check_min_width, check_nat_width;
gtk_css_gadget_get_preferred_size (priv->indicator_gadget,
GTK_ORIENTATION_HORIZONTAL,
-1,
&check_min_width, &check_nat_width,
NULL, NULL);
gtk_css_gadget_get_preferred_size (priv->indicator_gadget,
GTK_ORIENTATION_VERTICAL,
-1,
&check_min, &check_nat,
NULL, NULL);
child = gtk_bin_get_child (GTK_BIN (widget));
if (child && gtk_widget_get_visible (child))
{
gint child_min, child_nat;
gint child_min_baseline = -1, child_nat_baseline = -1;
if (for_size > -1)
for_size -= check_nat_width;
gtk_widget_get_preferred_height_and_baseline_for_width (child, for_size,
&child_min, &child_nat,
&child_min_baseline, &child_nat_baseline);
*minimum = MAX (check_min, child_min);
*natural = MAX (check_nat, child_nat);
if (minimum_baseline && child_min_baseline >= 0)
*minimum_baseline = child_min_baseline + (*minimum - child_min) / 2;
if (natural_baseline && child_nat_baseline >= 0)
*natural_baseline = child_nat_baseline + (*natural - child_nat) / 2;
}
else
{
*minimum = check_min;
*natural = check_nat;
}
}
}
static void static void
gtk_check_button_get_preferred_width_for_height (GtkWidget *widget, gtk_check_button_get_preferred_width_for_height (GtkWidget *widget,
gint height, gint height,
@ -635,13 +494,16 @@ gtk_check_button_size_allocate (GtkWidget *widget,
GtkAllocation *allocation) GtkAllocation *allocation)
{ {
GtkCheckButtonPrivate *priv = gtk_check_button_get_instance_private (GTK_CHECK_BUTTON (widget)); GtkCheckButtonPrivate *priv = gtk_check_button_get_instance_private (GTK_CHECK_BUTTON (widget));
GtkButton *button = GTK_BUTTON (widget);
GtkCssGadget *gadget; GtkCssGadget *gadget;
GdkRectangle clip; GdkRectangle clip;
PangoContext *pango_context;
PangoFontMetrics *metrics;
if (gtk_toggle_button_get_mode (GTK_TOGGLE_BUTTON (widget))) if (gtk_toggle_button_get_mode (GTK_TOGGLE_BUTTON (widget)))
gadget = priv->gadget; gadget = priv->gadget;
else else
gadget = GTK_BUTTON (widget)->priv->gadget; gadget = button->priv->gadget;
gtk_widget_set_allocation (widget, allocation); gtk_widget_set_allocation (widget, allocation);
gtk_css_gadget_allocate (gadget, gtk_css_gadget_allocate (gadget,
@ -650,71 +512,6 @@ gtk_check_button_size_allocate (GtkWidget *widget,
&clip); &clip);
gtk_widget_set_clip (widget, &clip); gtk_widget_set_clip (widget, &clip);
}
static void
gtk_check_button_allocate (GtkCssGadget *gadget,
const GtkAllocation *allocation,
int baseline,
GtkAllocation *out_clip,
gpointer unused)
{
GtkCheckButtonPrivate *priv;
GtkWidget *widget;
PangoContext *pango_context;
PangoFontMetrics *metrics;
GtkCheckButton *check_button;
GtkButton *button;
GtkAllocation child_allocation;
GtkWidget *child;
gint check_width, check_height;
GdkRectangle check_clip;
widget = gtk_css_gadget_get_owner (gadget);
button = GTK_BUTTON (widget);
check_button = GTK_CHECK_BUTTON (widget);
priv = gtk_check_button_get_instance_private (check_button);
g_assert (gtk_toggle_button_get_mode (GTK_TOGGLE_BUTTON (widget)));
gtk_css_gadget_get_preferred_size (priv->indicator_gadget,
GTK_ORIENTATION_HORIZONTAL,
-1,
NULL, &check_width,
NULL, NULL);
gtk_css_gadget_get_preferred_size (priv->indicator_gadget,
GTK_ORIENTATION_VERTICAL,
-1,
NULL, &check_height,
NULL, NULL);
child = gtk_bin_get_child (GTK_BIN (button));
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
child_allocation.x = allocation->x;
else
child_allocation.x = allocation->x + allocation->width - check_width;
child_allocation.y = allocation->y + (allocation->height - check_height) / 2;
child_allocation.width = check_width;
child_allocation.height = check_height;
gtk_css_gadget_allocate (priv->indicator_gadget,
&child_allocation,
baseline,
&check_clip);
if (child && gtk_widget_get_visible (child))
{
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
child_allocation.x = allocation->x + check_width;
else
child_allocation.x = allocation->x;
child_allocation.y = allocation->y;
child_allocation.width = allocation->width - check_width;
child_allocation.height = allocation->height;
gtk_widget_size_allocate_with_baseline (child, &child_allocation, baseline);
}
pango_context = gtk_widget_get_pango_context (widget); pango_context = gtk_widget_get_pango_context (widget);
metrics = pango_context_get_metrics (pango_context, metrics = pango_context_get_metrics (pango_context,
@ -735,9 +532,6 @@ gtk_check_button_allocate (GtkCssGadget *gadget,
border_allocation.width, border_allocation.width,
border_allocation.height); border_allocation.height);
} }
gtk_container_get_children_clip (GTK_CONTAINER (widget), out_clip);
gdk_rectangle_union (out_clip, &check_clip, out_clip);
} }
static gint static gint
@ -757,19 +551,6 @@ gtk_check_button_draw (GtkWidget *widget,
return FALSE; return FALSE;
} }
static void
gtk_check_button_draw_indicator (GtkCheckButton *check_button,
cairo_t *cr)
{
GtkCheckButtonClass *class = GTK_CHECK_BUTTON_GET_CLASS (check_button);
GtkCheckButtonPrivate *priv = gtk_check_button_get_instance_private (check_button);
if (class->draw_indicator)
class->draw_indicator (check_button, cr);
else
gtk_css_gadget_draw (priv->indicator_gadget, cr);
}
GtkCssNode * GtkCssNode *
gtk_check_button_get_indicator_node (GtkCheckButton *check_button) gtk_check_button_get_indicator_node (GtkCheckButton *check_button)
{ {