spinner: Use a gadget
This gives us min-width/height support. Currently, the spinner still has a hardcoded minimum size of 16 and doesn't grow beyond 32. We may want to revisit that at some point.
This commit is contained in:
321
gtk/gtkspinner.c
321
gtk/gtkspinner.c
@ -38,6 +38,7 @@
|
|||||||
#include "gtkstylecontextprivate.h"
|
#include "gtkstylecontextprivate.h"
|
||||||
#include "gtkwidgetprivate.h"
|
#include "gtkwidgetprivate.h"
|
||||||
#include "a11y/gtkspinneraccessible.h"
|
#include "a11y/gtkspinneraccessible.h"
|
||||||
|
#include "gtkcsscustomgadgetprivate.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,8 +60,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#define SPINNER_SIZE 16
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_ACTIVE
|
PROP_ACTIVE
|
||||||
@ -68,65 +67,157 @@ enum {
|
|||||||
|
|
||||||
struct _GtkSpinnerPrivate
|
struct _GtkSpinnerPrivate
|
||||||
{
|
{
|
||||||
|
GtkCssGadget *gadget;
|
||||||
gboolean active;
|
gboolean active;
|
||||||
};
|
};
|
||||||
|
|
||||||
static gboolean gtk_spinner_draw (GtkWidget *widget,
|
|
||||||
cairo_t *cr);
|
|
||||||
static void gtk_spinner_size_allocate (GtkWidget *widget,
|
|
||||||
GtkAllocation *allocation);
|
|
||||||
static void gtk_spinner_get_property (GObject *object,
|
|
||||||
guint param_id,
|
|
||||||
GValue *value,
|
|
||||||
GParamSpec *pspec);
|
|
||||||
static void gtk_spinner_set_property (GObject *object,
|
|
||||||
guint param_id,
|
|
||||||
const GValue *value,
|
|
||||||
GParamSpec *pspec);
|
|
||||||
static void gtk_spinner_set_active (GtkSpinner *spinner,
|
|
||||||
gboolean active);
|
|
||||||
static void gtk_spinner_get_preferred_width (GtkWidget *widget,
|
|
||||||
gint *minimum_size,
|
|
||||||
gint *natural_size);
|
|
||||||
static void gtk_spinner_get_preferred_height (GtkWidget *widget,
|
|
||||||
gint *minimum_size,
|
|
||||||
gint *natural_size);
|
|
||||||
|
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkSpinner, gtk_spinner, GTK_TYPE_WIDGET)
|
G_DEFINE_TYPE_WITH_PRIVATE (GtkSpinner, gtk_spinner, GTK_TYPE_WIDGET)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_spinner_class_init (GtkSpinnerClass *klass)
|
gtk_spinner_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class;
|
GtkSpinner *spinner = GTK_SPINNER (object);
|
||||||
GtkWidgetClass *widget_class;
|
|
||||||
|
|
||||||
gobject_class = G_OBJECT_CLASS(klass);
|
g_clear_object (&spinner->priv->gadget);
|
||||||
gobject_class->get_property = gtk_spinner_get_property;
|
|
||||||
gobject_class->set_property = gtk_spinner_set_property;
|
|
||||||
|
|
||||||
widget_class = GTK_WIDGET_CLASS(klass);
|
G_OBJECT_CLASS (gtk_spinner_parent_class)->finalize (object);
|
||||||
widget_class->size_allocate = gtk_spinner_size_allocate;
|
}
|
||||||
widget_class->draw = gtk_spinner_draw;
|
|
||||||
widget_class->get_preferred_width = gtk_spinner_get_preferred_width;
|
|
||||||
widget_class->get_preferred_height = gtk_spinner_get_preferred_height;
|
|
||||||
|
|
||||||
/* GtkSpinner:active:
|
static void
|
||||||
*
|
gtk_spinner_measure (GtkCssGadget *gadget,
|
||||||
* Whether the spinner is active
|
GtkOrientation orientation,
|
||||||
*
|
gint for_size,
|
||||||
* Since: 2.20
|
gint *minimum,
|
||||||
*/
|
gint *natural,
|
||||||
g_object_class_install_property (gobject_class,
|
gint *minimum_baseline,
|
||||||
PROP_ACTIVE,
|
gint *natural_baseline,
|
||||||
g_param_spec_boolean ("active",
|
gpointer data)
|
||||||
P_("Active"),
|
{
|
||||||
P_("Whether the spinner is active"),
|
*minimum = *natural = 16;
|
||||||
FALSE,
|
}
|
||||||
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
|
|
||||||
|
|
||||||
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_SPINNER_ACCESSIBLE);
|
static void
|
||||||
gtk_widget_class_set_css_name (widget_class, "spinner");
|
gtk_spinner_get_preferred_width (GtkWidget *widget,
|
||||||
|
gint *minimum,
|
||||||
|
gint *natural)
|
||||||
|
{
|
||||||
|
gtk_css_gadget_get_preferred_size (GTK_SPINNER (widget)->priv->gadget,
|
||||||
|
GTK_ORIENTATION_HORIZONTAL,
|
||||||
|
-1,
|
||||||
|
minimum, natural,
|
||||||
|
NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_spinner_get_preferred_height (GtkWidget *widget,
|
||||||
|
gint *minimum,
|
||||||
|
gint *natural)
|
||||||
|
{
|
||||||
|
gtk_css_gadget_get_preferred_size (GTK_SPINNER (widget)->priv->gadget,
|
||||||
|
GTK_ORIENTATION_VERTICAL,
|
||||||
|
-1,
|
||||||
|
minimum, natural,
|
||||||
|
NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_spinner_allocate (GtkCssGadget *gadget,
|
||||||
|
const GtkAllocation *allocation,
|
||||||
|
gint baseline,
|
||||||
|
GtkAllocation *out_clip,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
GtkWidget *widget;
|
||||||
|
GtkStyleContext *context;
|
||||||
|
gint size;
|
||||||
|
|
||||||
|
widget = gtk_css_gadget_get_owner (gadget);
|
||||||
|
context = gtk_widget_get_style_context (widget);
|
||||||
|
size = MIN (allocation->width, allocation->height);
|
||||||
|
|
||||||
|
gtk_widget_set_allocation (widget, allocation);
|
||||||
|
|
||||||
|
_gtk_style_context_get_icon_extents (context,
|
||||||
|
out_clip,
|
||||||
|
allocation->x + (allocation->width - size) / 2,
|
||||||
|
allocation->y + (allocation->height - size) / 2,
|
||||||
|
size, size);
|
||||||
|
|
||||||
|
gdk_rectangle_union (out_clip, allocation, out_clip);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_spinner_size_allocate (GtkWidget *widget,
|
||||||
|
GtkAllocation *allocation)
|
||||||
|
{
|
||||||
|
GtkAllocation clip;
|
||||||
|
|
||||||
|
gtk_widget_set_allocation (widget, allocation);
|
||||||
|
|
||||||
|
gtk_css_gadget_allocate (GTK_SPINNER (widget)->priv->gadget,
|
||||||
|
allocation,
|
||||||
|
gtk_widget_get_allocated_baseline (widget),
|
||||||
|
&clip);
|
||||||
|
|
||||||
|
gtk_widget_set_clip (widget, &clip);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gtk_spinner_draw (GtkWidget *widget,
|
||||||
|
cairo_t *cr)
|
||||||
|
{
|
||||||
|
gtk_css_gadget_draw (GTK_SPINNER (widget)->priv->gadget, cr);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gtk_spinner_render (GtkCssGadget *gadget,
|
||||||
|
cairo_t *cr,
|
||||||
|
gint x,
|
||||||
|
gint y,
|
||||||
|
gint width,
|
||||||
|
gint height,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
GtkWidget *widget;
|
||||||
|
GtkStyleContext *context;
|
||||||
|
gint size;
|
||||||
|
|
||||||
|
widget = gtk_css_gadget_get_owner (gadget);
|
||||||
|
context = gtk_widget_get_style_context (widget);
|
||||||
|
|
||||||
|
size = MIN (width, height);
|
||||||
|
|
||||||
|
gtk_render_activity (context, cr,
|
||||||
|
(width - size) / 2,
|
||||||
|
(height - size) / 2,
|
||||||
|
size, size);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_spinner_set_active (GtkSpinner *spinner,
|
||||||
|
gboolean active)
|
||||||
|
{
|
||||||
|
GtkSpinnerPrivate *priv = spinner->priv;
|
||||||
|
|
||||||
|
active = !!active;
|
||||||
|
|
||||||
|
if (priv->active != active)
|
||||||
|
{
|
||||||
|
priv->active = active;
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (spinner), "active");
|
||||||
|
|
||||||
|
if (active)
|
||||||
|
gtk_widget_set_state_flags (GTK_WIDGET (spinner),
|
||||||
|
GTK_STATE_FLAG_CHECKED, FALSE);
|
||||||
|
else
|
||||||
|
gtk_widget_unset_state_flags (GTK_WIDGET (spinner),
|
||||||
|
GTK_STATE_FLAG_CHECKED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -165,98 +256,58 @@ gtk_spinner_set_property (GObject *object,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_spinner_class_init (GtkSpinnerClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class;
|
||||||
|
GtkWidgetClass *widget_class;
|
||||||
|
|
||||||
|
gobject_class = G_OBJECT_CLASS(klass);
|
||||||
|
gobject_class->finalize = gtk_spinner_finalize;
|
||||||
|
gobject_class->get_property = gtk_spinner_get_property;
|
||||||
|
gobject_class->set_property = gtk_spinner_set_property;
|
||||||
|
|
||||||
|
widget_class = GTK_WIDGET_CLASS(klass);
|
||||||
|
widget_class->size_allocate = gtk_spinner_size_allocate;
|
||||||
|
widget_class->draw = gtk_spinner_draw;
|
||||||
|
widget_class->get_preferred_width = gtk_spinner_get_preferred_width;
|
||||||
|
widget_class->get_preferred_height = gtk_spinner_get_preferred_height;
|
||||||
|
|
||||||
|
/* GtkSpinner:active:
|
||||||
|
*
|
||||||
|
* Whether the spinner is active
|
||||||
|
*
|
||||||
|
* Since: 2.20
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_ACTIVE,
|
||||||
|
g_param_spec_boolean ("active",
|
||||||
|
P_("Active"),
|
||||||
|
P_("Whether the spinner is active"),
|
||||||
|
FALSE,
|
||||||
|
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
|
||||||
|
|
||||||
|
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_SPINNER_ACCESSIBLE);
|
||||||
|
gtk_widget_class_set_css_name (widget_class, "spinner");
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_spinner_init (GtkSpinner *spinner)
|
gtk_spinner_init (GtkSpinner *spinner)
|
||||||
{
|
{
|
||||||
|
GtkCssNode *widget_node;
|
||||||
|
|
||||||
spinner->priv = gtk_spinner_get_instance_private (spinner);
|
spinner->priv = gtk_spinner_get_instance_private (spinner);
|
||||||
|
|
||||||
gtk_widget_set_has_window (GTK_WIDGET (spinner), FALSE);
|
gtk_widget_set_has_window (GTK_WIDGET (spinner), FALSE);
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
widget_node = gtk_widget_get_css_node (GTK_WIDGET (spinner));
|
||||||
gtk_spinner_get_preferred_width (GtkWidget *widget,
|
spinner->priv->gadget = gtk_css_custom_gadget_new_for_node (widget_node,
|
||||||
gint *minimum_size,
|
GTK_WIDGET (spinner),
|
||||||
gint *natural_size)
|
gtk_spinner_measure,
|
||||||
{
|
gtk_spinner_allocate,
|
||||||
*minimum_size = SPINNER_SIZE;
|
gtk_spinner_render,
|
||||||
*natural_size = SPINNER_SIZE;
|
NULL,
|
||||||
}
|
NULL);
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_spinner_get_preferred_height (GtkWidget *widget,
|
|
||||||
gint *minimum_size,
|
|
||||||
gint *natural_size)
|
|
||||||
{
|
|
||||||
*minimum_size = SPINNER_SIZE;
|
|
||||||
*natural_size = SPINNER_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_spinner_size_allocate (GtkWidget *widget,
|
|
||||||
GtkAllocation *allocation)
|
|
||||||
{
|
|
||||||
GtkStyleContext *context;
|
|
||||||
GtkAllocation clip;
|
|
||||||
gint size;
|
|
||||||
|
|
||||||
context = gtk_widget_get_style_context (widget);
|
|
||||||
size = MIN (allocation->width, allocation->height);
|
|
||||||
|
|
||||||
_gtk_style_context_get_icon_extents (context,
|
|
||||||
&clip,
|
|
||||||
allocation->x + (allocation->width - size) / 2,
|
|
||||||
allocation->y + (allocation->height - size) / 2,
|
|
||||||
size, size);
|
|
||||||
|
|
||||||
gdk_rectangle_union (&clip, allocation, &clip);
|
|
||||||
|
|
||||||
gtk_widget_set_allocation (widget, allocation);
|
|
||||||
gtk_widget_set_clip (widget, &clip);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gtk_spinner_draw (GtkWidget *widget,
|
|
||||||
cairo_t *cr)
|
|
||||||
{
|
|
||||||
GtkStyleContext *context;
|
|
||||||
gint width, height;
|
|
||||||
gint size;
|
|
||||||
|
|
||||||
context = gtk_widget_get_style_context (widget);
|
|
||||||
|
|
||||||
width = gtk_widget_get_allocated_width (widget);
|
|
||||||
height = gtk_widget_get_allocated_height (widget);
|
|
||||||
size = MIN (width, height);
|
|
||||||
|
|
||||||
gtk_render_activity (context, cr,
|
|
||||||
(width - size) / 2,
|
|
||||||
(height - size) / 2,
|
|
||||||
size, size);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_spinner_set_active (GtkSpinner *spinner,
|
|
||||||
gboolean active)
|
|
||||||
{
|
|
||||||
GtkSpinnerPrivate *priv = spinner->priv;
|
|
||||||
|
|
||||||
active = !!active;
|
|
||||||
|
|
||||||
if (priv->active != active)
|
|
||||||
{
|
|
||||||
priv->active = active;
|
|
||||||
|
|
||||||
g_object_notify (G_OBJECT (spinner), "active");
|
|
||||||
|
|
||||||
if (active)
|
|
||||||
gtk_widget_set_state_flags (GTK_WIDGET (spinner),
|
|
||||||
GTK_STATE_FLAG_CHECKED, FALSE);
|
|
||||||
else
|
|
||||||
gtk_widget_unset_state_flags (GTK_WIDGET (spinner),
|
|
||||||
GTK_STATE_FLAG_CHECKED);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user