Commit 79a171de authored by Benjamin Otte's avatar Benjamin Otte

styleproperty: Make query() and assign() vfuncs

... and implement them in the 2 known subclasses.
parent b904679a
......@@ -59,10 +59,43 @@ gtk_css_shorthand_property_set_property (GObject *object,
}
}
static void
_gtk_css_shorthand_property_assign (GtkStyleProperty *property,
GtkStyleProperties *props,
GtkStateFlags state,
const GValue *value)
{
GParameter *parameters;
guint i, n_parameters;
parameters = _gtk_style_property_unpack (property, value, &n_parameters);
for (i = 0; i < n_parameters; i++)
{
_gtk_style_property_assign (_gtk_style_property_lookup (parameters[i].name),
props,
state,
&parameters[i].value);
g_value_unset (&parameters[i].value);
}
g_free (parameters);
}
static void
_gtk_css_shorthand_property_query (GtkStyleProperty *property,
GtkStyleProperties *props,
GtkStateFlags state,
GtkStylePropertyContext *context,
GValue *value)
{
property->pack_func (value, props, state, context);
}
static void
_gtk_css_shorthand_property_class_init (GtkCssShorthandPropertyClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkStylePropertyClass *property_class = GTK_STYLE_PROPERTY_CLASS (klass);
object_class->set_property = gtk_css_shorthand_property_set_property;
......@@ -73,6 +106,9 @@ _gtk_css_shorthand_property_class_init (GtkCssShorthandPropertyClass *klass)
P_("The list of subproperties"),
G_TYPE_STRV,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
property_class->assign = _gtk_css_shorthand_property_assign;
property_class->query = _gtk_css_shorthand_property_query;
}
static void
......
......@@ -26,6 +26,14 @@
#include "gtkcsstypesprivate.h"
#include "gtkintl.h"
#include "gtkprivatetypebuiltins.h"
#include "gtkstylepropertiesprivate.h"
/* for resolvage */
#include <cairo-gobject.h>
#include "gtkgradient.h"
#include "gtkshadowprivate.h"
#include "gtkwin32themeprivate.h"
enum {
PROP_0,
......@@ -99,10 +107,222 @@ gtk_css_style_property_get_property (GObject *object,
}
}
static void
_gtk_css_style_property_assign (GtkStyleProperty *property,
GtkStyleProperties *props,
GtkStateFlags state,
const GValue *value)
{
_gtk_style_properties_set_property_by_property (props,
GTK_CSS_STYLE_PROPERTY (property),
state,
value);
}
static void
_gtk_style_property_default_value (GtkStyleProperty *property,
GtkStyleProperties *properties,
GtkStateFlags state,
GValue *value)
{
g_value_copy (_gtk_css_style_property_get_initial_value (GTK_CSS_STYLE_PROPERTY (property)), value);
}
static gboolean
resolve_color (GtkStyleProperties *props,
GValue *value)
{
GdkRGBA color;
/* Resolve symbolic color to GdkRGBA */
if (!gtk_symbolic_color_resolve (g_value_get_boxed (value), props, &color))
return FALSE;
/* Store it back, this is where GdkRGBA caching happens */
g_value_unset (value);
g_value_init (value, GDK_TYPE_RGBA);
g_value_set_boxed (value, &color);
return TRUE;
}
static gboolean
resolve_color_rgb (GtkStyleProperties *props,
GValue *value)
{
GdkColor color = { 0 };
GdkRGBA rgba;
if (!gtk_symbolic_color_resolve (g_value_get_boxed (value), props, &rgba))
return FALSE;
color.red = rgba.red * 65535. + 0.5;
color.green = rgba.green * 65535. + 0.5;
color.blue = rgba.blue * 65535. + 0.5;
g_value_unset (value);
g_value_init (value, GDK_TYPE_COLOR);
g_value_set_boxed (value, &color);
return TRUE;
}
static gboolean
resolve_win32_theme_part (GtkStyleProperties *props,
GValue *value,
GValue *value_out,
GtkStylePropertyContext *context)
{
GtkWin32ThemePart *part;
cairo_pattern_t *pattern;
part = g_value_get_boxed (value);
if (part == NULL)
return FALSE;
pattern = _gtk_win32_theme_part_render (part, context->width, context->height);
g_value_take_boxed (value_out, pattern);
return TRUE;
}
static gboolean
resolve_gradient (GtkStyleProperties *props,
GValue *value)
{
cairo_pattern_t *gradient;
if (!gtk_gradient_resolve (g_value_get_boxed (value), props, &gradient))
return FALSE;
/* Store it back, this is where cairo_pattern_t caching happens */
g_value_unset (value);
g_value_init (value, CAIRO_GOBJECT_TYPE_PATTERN);
g_value_take_boxed (value, gradient);
return TRUE;
}
static gboolean
resolve_shadow (GtkStyleProperties *props,
GValue *value)
{
GtkShadow *resolved, *base;
base = g_value_get_boxed (value);
if (base == NULL)
return TRUE;
if (_gtk_shadow_get_resolved (base))
return TRUE;
resolved = _gtk_shadow_resolve (base, props);
if (resolved == NULL)
return FALSE;
g_value_take_boxed (value, resolved);
return TRUE;
}
static void
_gtk_style_property_resolve (GtkStyleProperty *property,
GtkStyleProperties *props,
GtkStateFlags state,
GtkStylePropertyContext *context,
GValue *val,
GValue *val_out)
{
if (G_VALUE_TYPE (val) == GTK_TYPE_CSS_SPECIAL_VALUE)
{
GtkCssSpecialValue special = g_value_get_enum (val);
g_value_unset (val);
switch (special)
{
case GTK_CSS_CURRENT_COLOR:
g_assert (property->pspec->value_type == GDK_TYPE_RGBA);
gtk_style_properties_get_property (props, "color", state, val);
break;
case GTK_CSS_INHERIT:
case GTK_CSS_INITIAL:
default:
g_assert_not_reached ();
}
}
else if (G_VALUE_TYPE (val) == GTK_TYPE_SYMBOLIC_COLOR)
{
if (property->pspec->value_type == GDK_TYPE_RGBA)
{
if (resolve_color (props, val))
goto out;
}
else if (property->pspec->value_type == GDK_TYPE_COLOR)
{
if (resolve_color_rgb (props, val))
goto out;
}
g_value_unset (val);
g_value_init (val, property->pspec->value_type);
_gtk_style_property_default_value (property, props, state, val);
}
else if (G_VALUE_TYPE (val) == GDK_TYPE_RGBA)
{
if (g_value_get_boxed (val) == NULL)
_gtk_style_property_default_value (property, props, state, val);
}
else if (G_VALUE_TYPE (val) == GTK_TYPE_GRADIENT)
{
g_return_if_fail (property->pspec->value_type == CAIRO_GOBJECT_TYPE_PATTERN);
if (!resolve_gradient (props, val))
{
g_value_unset (val);
g_value_init (val, CAIRO_GOBJECT_TYPE_PATTERN);
_gtk_style_property_default_value (property, props, state, val);
}
}
else if (G_VALUE_TYPE (val) == GTK_TYPE_SHADOW)
{
if (!resolve_shadow (props, val))
_gtk_style_property_default_value (property, props, state, val);
}
else if (G_VALUE_TYPE (val) == GTK_TYPE_WIN32_THEME_PART)
{
if (resolve_win32_theme_part (props, val, val_out, context))
return; /* Don't copy val, this sets val_out */
_gtk_style_property_default_value (property, props, state, val);
}
out:
g_value_copy (val, val_out);
}
static void
_gtk_css_style_property_query (GtkStyleProperty *property,
GtkStyleProperties *props,
GtkStateFlags state,
GtkStylePropertyContext *context,
GValue *value)
{
const GValue *val;
val = _gtk_style_properties_peek_property (props, GTK_CSS_STYLE_PROPERTY (property), state);
if (val)
_gtk_style_property_resolve (property, props, state, context, (GValue *) val, value);
else
_gtk_style_property_default_value (property, props, state, value);
}
static void
_gtk_css_style_property_class_init (GtkCssStylePropertyClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkStylePropertyClass *property_class = GTK_STYLE_PROPERTY_CLASS (klass);
object_class->constructed = gtk_css_style_property_constructed;
object_class->set_property = gtk_css_style_property_set_property;
......@@ -130,6 +350,9 @@ _gtk_css_style_property_class_init (GtkCssStylePropertyClass *klass)
G_TYPE_VALUE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
property_class->assign = _gtk_css_style_property_assign;
property_class->query = _gtk_css_style_property_query;
klass->style_properties = g_ptr_array_new ();
}
......
......@@ -437,189 +437,6 @@ _gtk_style_property_parse_value (GtkStyleProperty *property,
return _gtk_css_style_parse_value (value, parser, base);
}
static void
_gtk_style_property_default_value (GtkStyleProperty *property,
GtkStyleProperties *properties,
GtkStateFlags state,
GValue *value)
{
g_value_copy (_gtk_css_style_property_get_initial_value (GTK_CSS_STYLE_PROPERTY (property)), value);
}
static gboolean
resolve_color (GtkStyleProperties *props,
GValue *value)
{
GdkRGBA color;
/* Resolve symbolic color to GdkRGBA */
if (!gtk_symbolic_color_resolve (g_value_get_boxed (value), props, &color))
return FALSE;
/* Store it back, this is where GdkRGBA caching happens */
g_value_unset (value);
g_value_init (value, GDK_TYPE_RGBA);
g_value_set_boxed (value, &color);
return TRUE;
}
static gboolean
resolve_color_rgb (GtkStyleProperties *props,
GValue *value)
{
GdkColor color = { 0 };
GdkRGBA rgba;
if (!gtk_symbolic_color_resolve (g_value_get_boxed (value), props, &rgba))
return FALSE;
color.red = rgba.red * 65535. + 0.5;
color.green = rgba.green * 65535. + 0.5;
color.blue = rgba.blue * 65535. + 0.5;
g_value_unset (value);
g_value_init (value, GDK_TYPE_COLOR);
g_value_set_boxed (value, &color);
return TRUE;
}
static gboolean
resolve_win32_theme_part (GtkStyleProperties *props,
GValue *value,
GValue *value_out,
GtkStylePropertyContext *context)
{
GtkWin32ThemePart *part;
cairo_pattern_t *pattern;
part = g_value_get_boxed (value);
if (part == NULL)
return FALSE;
pattern = _gtk_win32_theme_part_render (part, context->width, context->height);
g_value_take_boxed (value_out, pattern);
return TRUE;
}
static gboolean
resolve_gradient (GtkStyleProperties *props,
GValue *value)
{
cairo_pattern_t *gradient;
if (!gtk_gradient_resolve (g_value_get_boxed (value), props, &gradient))
return FALSE;
/* Store it back, this is where cairo_pattern_t caching happens */
g_value_unset (value);
g_value_init (value, CAIRO_GOBJECT_TYPE_PATTERN);
g_value_take_boxed (value, gradient);
return TRUE;
}
static gboolean
resolve_shadow (GtkStyleProperties *props,
GValue *value)
{
GtkShadow *resolved, *base;
base = g_value_get_boxed (value);
if (base == NULL)
return TRUE;
if (_gtk_shadow_get_resolved (base))
return TRUE;
resolved = _gtk_shadow_resolve (base, props);
if (resolved == NULL)
return FALSE;
g_value_take_boxed (value, resolved);
return TRUE;
}
static void
_gtk_style_property_resolve (GtkStyleProperty *property,
GtkStyleProperties *props,
GtkStateFlags state,
GtkStylePropertyContext *context,
GValue *val,
GValue *val_out)
{
if (G_VALUE_TYPE (val) == GTK_TYPE_CSS_SPECIAL_VALUE)
{
GtkCssSpecialValue special = g_value_get_enum (val);
g_value_unset (val);
switch (special)
{
case GTK_CSS_CURRENT_COLOR:
g_assert (property->pspec->value_type == GDK_TYPE_RGBA);
gtk_style_properties_get_property (props, "color", state, val);
break;
case GTK_CSS_INHERIT:
case GTK_CSS_INITIAL:
default:
g_assert_not_reached ();
}
}
else if (G_VALUE_TYPE (val) == GTK_TYPE_SYMBOLIC_COLOR)
{
if (property->pspec->value_type == GDK_TYPE_RGBA)
{
if (resolve_color (props, val))
goto out;
}
else if (property->pspec->value_type == GDK_TYPE_COLOR)
{
if (resolve_color_rgb (props, val))
goto out;
}
g_value_unset (val);
g_value_init (val, property->pspec->value_type);
_gtk_style_property_default_value (property, props, state, val);
}
else if (G_VALUE_TYPE (val) == GDK_TYPE_RGBA)
{
if (g_value_get_boxed (val) == NULL)
_gtk_style_property_default_value (property, props, state, val);
}
else if (G_VALUE_TYPE (val) == GTK_TYPE_GRADIENT)
{
g_return_if_fail (property->pspec->value_type == CAIRO_GOBJECT_TYPE_PATTERN);
if (!resolve_gradient (props, val))
{
g_value_unset (val);
g_value_init (val, CAIRO_GOBJECT_TYPE_PATTERN);
_gtk_style_property_default_value (property, props, state, val);
}
}
else if (G_VALUE_TYPE (val) == GTK_TYPE_SHADOW)
{
if (!resolve_shadow (props, val))
_gtk_style_property_default_value (property, props, state, val);
}
else if (G_VALUE_TYPE (val) == GTK_TYPE_WIN32_THEME_PART)
{
if (resolve_win32_theme_part (props, val, val_out, context))
return; /* Don't copy val, this sets val_out */
_gtk_style_property_default_value (property, props, state, val);
}
out:
g_value_copy (val, val_out);
}
GParameter *
_gtk_style_property_unpack (GtkStyleProperty *property,
const GValue *value,
......@@ -633,62 +450,47 @@ _gtk_style_property_unpack (GtkStyleProperty *property,
return property->unpack_func (value, n_params);
}
static void
_gtk_style_property_pack (GtkStyleProperty *property,
GtkStyleProperties *props,
GtkStateFlags state,
GtkStylePropertyContext *context,
GValue *value)
{
g_return_if_fail (property != NULL);
g_return_if_fail (property->pack_func != NULL);
g_return_if_fail (GTK_IS_STYLE_PROPERTIES (props));
g_return_if_fail (G_IS_VALUE (value));
property->pack_func (value, props, state, context);
}
/**
* _gtk_style_property_assign:
* @property: the property
* @props: The properties to assign to
* @state: The state to assign
* @value: (out): the #GValue with the value to be
* assigned
*
* This function is called by gtk_style_properties_set() and in
* turn gtk_style_context_set() and similar functions to set the
* value from code using old APIs.
**/
void
_gtk_style_property_assign (GtkStyleProperty *property,
GtkStyleProperties *props,
GtkStateFlags state,
const GValue *value)
{
GtkStylePropertyClass *klass;
g_return_if_fail (GTK_IS_STYLE_PROPERTY (property));
g_return_if_fail (GTK_IS_STYLE_PROPERTIES (props));
g_return_if_fail (value != NULL);
if (GTK_IS_CSS_SHORTHAND_PROPERTY (property))
{
GParameter *parameters;
guint i, n_parameters;
parameters = _gtk_style_property_unpack (property, value, &n_parameters);
klass = GTK_STYLE_PROPERTY_GET_CLASS (property);
for (i = 0; i < n_parameters; i++)
{
_gtk_style_property_assign (_gtk_style_property_lookup (parameters[i].name),
props,
state,
&parameters[i].value);
g_value_unset (&parameters[i].value);
}
g_free (parameters);
return;
}
else if (GTK_IS_CSS_STYLE_PROPERTY (property))
{
_gtk_style_properties_set_property_by_property (props,
GTK_CSS_STYLE_PROPERTY (property),
state,
value);
}
else
{
g_assert_not_reached ();
}
klass->assign (property, props, state, value);
}
/**
* _gtk_style_property_query:
* @property: the property
* @props: The properties to query
* @state: The state to query
* @value: (out): an uninitialized #GValue to be filled with the
* contents of the lookup
*
* This function is called by gtk_style_properties_get() and in
* turn gtk_style_context_get() and similar functions to get the
* value to return to code using old APIs.
**/
void
_gtk_style_property_query (GtkStyleProperty *property,
GtkStyleProperties *props,
......@@ -696,32 +498,18 @@ _gtk_style_property_query (GtkStyleProperty *property,
GtkStylePropertyContext *context,
GValue *value)
{
GtkStylePropertyClass *klass;
g_return_if_fail (property != NULL);
g_return_if_fail (GTK_IS_STYLE_PROPERTIES (props));
g_return_if_fail (context != NULL);
g_return_if_fail (value != NULL);
g_value_init (value, property->pspec->value_type);
klass = GTK_STYLE_PROPERTY_GET_CLASS (property);
if (GTK_IS_CSS_STYLE_PROPERTY (property))
{
const GValue *val;
val = _gtk_style_properties_peek_property (props, GTK_CSS_STYLE_PROPERTY (property), state);
if (val)
_gtk_style_property_resolve (property, props, state, context, (GValue *) val, value);
else
_gtk_style_property_default_value (property, props, state, value);
}
else if (GTK_IS_CSS_SHORTHAND_PROPERTY (property))
{
_gtk_style_property_pack (property, props, state, context, value);
}
else
{
g_assert_not_reached ();
}
g_value_init (value, property->value_type);
klass->query (property, props, state, context, value);
}
#define rgba_init(rgba, r, g, b, a) G_STMT_START{ \
......@@ -1168,6 +956,7 @@ _gtk_style_property_register (GParamSpec *pspec,
"name", pspec->name,
"value-type", pspec->value_type,
NULL);
g_assert (node->value_type == pspec->value_type);
node->pspec = pspec;
node->property_parse_func = property_parse_func;
node->parse_func = parse_func;
......
......@@ -71,6 +71,16 @@ struct _GtkStylePropertyClass
{
GObjectClass parent_class;
void (* assign) (GtkStyleProperty *property,
GtkStyleProperties *props,
GtkStateFlags state,
const GValue *value);
void (* query) (GtkStyleProperty *property,
GtkStyleProperties *props,
GtkStateFlags state,
GtkStylePropertyContext *context,
GValue *value);
GHashTable *properties;
};
......
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