[gtk+/nth-child: 21/22] css: Add all border-radius properties
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/nth-child: 21/22] css: Add all border-radius properties
- Date: Thu, 26 May 2011 03:32:20 +0000 (UTC)
commit 55ce514dafb2ca0f4f39e7bba62e1bf57142ed61
Author: Benjamin Otte <otte redhat com>
Date: Thu May 26 03:50:53 2011 +0200
css: Add all border-radius properties
Implement all border-radisu properties as specified by
http://www.w3.org/TR/css3-background/#the-border-radius
The end goal here is to get joined buttons to really look joined.
gtk/Makefile.am | 2 +
gtk/gtkcsstypes.c | 35 ++++++
gtk/gtkcsstypesprivate.h | 50 ++++++++
gtk/gtkstyleproperties.c | 6 +
gtk/gtkstyleproperty.c | 283 +++++++++++++++++++++++++++++++++++++++++++++-
5 files changed, 373 insertions(+), 3 deletions(-)
---
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index a9e623e..19b187a 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -389,6 +389,7 @@ gtk_private_h_sources = \
gtkcssparserprivate.h \
gtkcssproviderprivate.h \
gtkcssselectorprivate.h \
+ gtkcsstypesprivate.h \
gtkcustompaperunixdialog.h \
gtkdndcursors.h \
gtkentryprivate.h \
@@ -518,6 +519,7 @@ gtk_base_c_sources = \
gtkcssparser.c \
gtkcssprovider.c \
gtkcssselector.c \
+ gtkcsstypes.c \
gtkdialog.c \
gtkdrawingarea.c \
gtkeditable.c \
diff --git a/gtk/gtkcsstypes.c b/gtk/gtkcsstypes.c
new file mode 100644
index 0000000..44b0d28
--- /dev/null
+++ b/gtk/gtkcsstypes.c
@@ -0,0 +1,35 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2011 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "gtkcsstypesprivate.h"
+
+#define DEFINE_BOXED_TYPE_WITH_COPY_FUNC(TypeName, type_name) \
+\
+static TypeName * \
+type_name ## _copy (const TypeName *foo) \
+{ \
+ return g_memdup (foo, sizeof (TypeName)); \
+} \
+\
+G_DEFINE_BOXED_TYPE (TypeName, type_name, type_name ## _copy, g_free)
+
+DEFINE_BOXED_TYPE_WITH_COPY_FUNC (GtkCssBorderCornerRadius, _gtk_css_border_corner_radius)
+DEFINE_BOXED_TYPE_WITH_COPY_FUNC (GtkCssBorderRadius, _gtk_css_border_radius)
diff --git a/gtk/gtkcsstypesprivate.h b/gtk/gtkcsstypesprivate.h
new file mode 100644
index 0000000..db3e274
--- /dev/null
+++ b/gtk/gtkcsstypesprivate.h
@@ -0,0 +1,50 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2011 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_CSS_TYPES_PRIVATE_H__
+#define __GTK_CSS_TYPES_PRIVATE_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GtkCssBorderCornerRadius GtkCssBorderCornerRadius;
+typedef struct _GtkCssBorderRadius GtkCssBorderRadius;
+
+struct _GtkCssBorderCornerRadius {
+ double horizontal;
+ double vertical;
+};
+
+struct _GtkCssBorderRadius {
+ GtkCssBorderCornerRadius top_left;
+ GtkCssBorderCornerRadius top_right;
+ GtkCssBorderCornerRadius bottom_right;
+ GtkCssBorderCornerRadius bottom_left;
+};
+
+#define GTK_TYPE_CSS_BORDER_CORNER_RADIUS _gtk_css_border_corner_radius_get_type ()
+#define GTK_TYPE_CSS_BORDER_RADIUS _gtk_css_border_radius_get_type ()
+
+GType _gtk_css_border_corner_radius_get_type (void);
+GType _gtk_css_border_radius_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GTK_CSS_TYPES_PRIVATE_H__ */
diff --git a/gtk/gtkstyleproperties.c b/gtk/gtkstyleproperties.c
index 97ecfd2..97fe316 100644
--- a/gtk/gtkstyleproperties.c
+++ b/gtk/gtkstyleproperties.c
@@ -31,6 +31,7 @@
#include "gtkanimationdescription.h"
#include "gtkgradient.h"
#include "gtkshadowprivate.h"
+#include "gtkcsstypesprivate.h"
#include "gtkstylepropertyprivate.h"
#include "gtkintl.h"
@@ -512,6 +513,11 @@ _gtk_style_properties_set_property_by_property (GtkStyleProperties *props,
g_return_if_fail (value_type == CAIRO_GOBJECT_TYPE_PATTERN ||
value_type == GTK_TYPE_GRADIENT);
}
+ else if (style_prop->pspec->value_type == G_TYPE_INT)
+ {
+ g_return_if_fail (value_type == G_TYPE_INT ||
+ value_type == GTK_TYPE_CSS_BORDER_RADIUS);
+ }
else
g_return_if_fail (style_prop->pspec->value_type == value_type);
diff --git a/gtk/gtkstyleproperty.c b/gtk/gtkstyleproperty.c
index bcd7e32..333f470 100644
--- a/gtk/gtkstyleproperty.c
+++ b/gtk/gtkstyleproperty.c
@@ -30,6 +30,7 @@
#include "gtkcssprovider.h"
#include "gtkcssparserprivate.h"
+#include "gtkcsstypesprivate.h"
/* the actual parsers we have */
#include "gtkanimationdescription.h"
@@ -1183,6 +1184,192 @@ bindings_value_print (const GValue *value,
}
}
+static gboolean
+border_corner_radius_value_parse (GtkCssParser *parser,
+ GFile *base,
+ GValue *value)
+{
+ GtkCssBorderCornerRadius corner;
+
+ if (!_gtk_css_parser_try_double (parser, &corner.horizontal))
+ {
+ _gtk_css_parser_error (parser, "Expected a number");
+ return FALSE;
+ }
+
+ if (!_gtk_css_parser_try_double (parser, &corner.vertical))
+ corner.vertical = corner.horizontal;
+
+ g_value_set_boxed (value, &corner);
+ return TRUE;
+}
+
+static void
+border_corner_radius_value_print (const GValue *value,
+ GString *string)
+{
+ GtkCssBorderCornerRadius *corner;
+
+ corner = g_value_get_boxed (value);
+
+ if (corner == NULL)
+ {
+ g_string_append (string, "none");
+ return;
+ }
+
+ string_append_double (string, corner->horizontal);
+ if (corner->horizontal != corner->vertical)
+ {
+ g_string_append_c (string, ' ');
+ string_append_double (string, corner->horizontal);
+ }
+
+ g_free (corner);
+}
+
+static gboolean
+border_radius_value_parse (GtkCssParser *parser,
+ GFile *base,
+ GValue *value)
+{
+ GtkCssBorderRadius border;
+
+ if (!_gtk_css_parser_try_double (parser, &border.top_left.horizontal))
+ {
+ _gtk_css_parser_error (parser, "Expected a number");
+ return FALSE;
+ }
+
+ if (_gtk_css_parser_try_double (parser, &border.top_right.horizontal))
+ {
+ if (_gtk_css_parser_try_double (parser, &border.bottom_right.horizontal))
+ {
+ if (!_gtk_css_parser_try_double (parser, &border.bottom_left.horizontal))
+ border.bottom_left.horizontal = border.top_right.horizontal;
+ }
+ else
+ {
+ border.bottom_right.horizontal = border.top_left.horizontal;
+ border.bottom_left.horizontal = border.top_right.horizontal;
+ }
+ }
+ else
+ {
+ border.top_right.horizontal = border.top_left.horizontal;
+ border.bottom_right.horizontal = border.top_left.horizontal;
+ border.bottom_left.horizontal = border.top_left.horizontal;
+ }
+
+ if (_gtk_css_parser_try (parser, "/", TRUE))
+ {
+ if (!_gtk_css_parser_try_double (parser, &border.top_left.vertical))
+ {
+ _gtk_css_parser_error (parser, "Expected a number");
+ return FALSE;
+ }
+
+ if (_gtk_css_parser_try_double (parser, &border.top_right.vertical))
+ {
+ if (_gtk_css_parser_try_double (parser, &border.bottom_right.vertical))
+ {
+ if (!_gtk_css_parser_try_double (parser, &border.bottom_left.vertical))
+ border.bottom_left.vertical = border.top_right.vertical;
+ }
+ else
+ {
+ border.bottom_right.vertical = border.top_left.vertical;
+ border.bottom_left.vertical = border.top_right.vertical;
+ }
+ }
+ else
+ {
+ border.top_right.vertical = border.top_left.vertical;
+ border.bottom_right.vertical = border.top_left.vertical;
+ border.bottom_left.vertical = border.top_left.vertical;
+ }
+ }
+ else
+ {
+ border.top_left.vertical = border.top_left.horizontal;
+ border.top_right.vertical = border.top_right.horizontal;
+ border.bottom_right.vertical = border.bottom_right.horizontal;
+ border.bottom_left.vertical = border.bottom_left.horizontal;
+ }
+
+ /* border-radius is an int property for backwards-compat reasons */
+ g_value_unset (value);
+ g_value_init (value, GTK_TYPE_CSS_BORDER_RADIUS);
+ g_value_set_boxed (value, &border);
+
+ return TRUE;
+}
+
+static void
+border_radius_value_print (const GValue *value,
+ GString *string)
+{
+ GtkCssBorderRadius *border;
+
+ border = g_value_get_boxed (value);
+
+ if (border == NULL)
+ {
+ g_string_append (string, "none");
+ return;
+ }
+
+ string_append_double (string, border->top_left.horizontal);
+ if (border->top_left.horizontal != border->top_right.horizontal ||
+ border->top_left.horizontal != border->bottom_right.horizontal ||
+ border->top_left.horizontal != border->bottom_left.horizontal)
+ {
+ g_string_append_c (string, ' ');
+ string_append_double (string, border->top_right.horizontal);
+ if (border->top_left.horizontal != border->bottom_right.horizontal ||
+ border->top_right.horizontal != border->bottom_left.horizontal)
+ {
+ g_string_append_c (string, ' ');
+ string_append_double (string, border->bottom_right.horizontal);
+ if (border->top_right.horizontal != border->bottom_left.horizontal)
+ {
+ g_string_append_c (string, ' ');
+ string_append_double (string, border->bottom_left.horizontal);
+ }
+ }
+ }
+
+ if (border->top_left.horizontal != border->top_left.vertical ||
+ border->top_right.horizontal != border->top_right.vertical ||
+ border->bottom_right.horizontal != border->bottom_right.vertical ||
+ border->bottom_left.horizontal != border->bottom_left.vertical)
+ {
+ g_string_append (string, " / ");
+ string_append_double (string, border->top_left.vertical);
+ if (border->top_left.vertical != border->top_right.vertical ||
+ border->top_left.vertical != border->bottom_right.vertical ||
+ border->top_left.vertical != border->bottom_left.vertical)
+ {
+ g_string_append_c (string, ' ');
+ string_append_double (string, border->top_right.vertical);
+ if (border->top_left.vertical != border->bottom_right.vertical ||
+ border->top_right.vertical != border->bottom_left.vertical)
+ {
+ g_string_append_c (string, ' ');
+ string_append_double (string, border->bottom_right.vertical);
+ if (border->top_right.vertical != border->bottom_left.vertical)
+ {
+ g_string_append_c (string, ' ');
+ string_append_double (string, border->bottom_left.vertical);
+ }
+ }
+ }
+
+ }
+
+ g_free (border);
+}
+
/*** PACKING ***/
static GParameter *
@@ -1300,6 +1487,54 @@ pack_margin (GValue *value,
"margin-bottom", "margin-right");
}
+static GParameter *
+unpack_border_radius (const GValue *value,
+ guint *n_params)
+{
+ GParameter *parameter = g_new0 (GParameter, 4);
+ GtkCssBorderRadius *border = g_value_get_boxed (value);
+
+ parameter[0].name = "border-top-left-radius";
+ g_value_init (¶meter[0].value, GTK_TYPE_CSS_BORDER_CORNER_RADIUS);
+ g_value_set_boxed (¶meter[0].value, &border->top_left);
+ parameter[1].name = "border-top-right-radius";
+ g_value_init (¶meter[1].value, GTK_TYPE_CSS_BORDER_CORNER_RADIUS);
+ g_value_set_boxed (¶meter[1].value, &border->top_right);
+ parameter[2].name = "border-bottom-right-radius";
+ g_value_init (¶meter[2].value, GTK_TYPE_CSS_BORDER_CORNER_RADIUS);
+ g_value_set_boxed (¶meter[2].value, &border->bottom_right);
+ parameter[3].name = "border-bottom-left-radius";
+ g_value_init (¶meter[3].value, GTK_TYPE_CSS_BORDER_CORNER_RADIUS);
+ g_value_set_boxed (¶meter[3].value, &border->bottom_left);
+
+ g_free (border);
+
+ *n_params = 4;
+ return parameter;
+}
+
+static void
+pack_border_radius (GValue *value,
+ GtkStyleProperties *props,
+ GtkStateFlags state)
+{
+ GtkCssBorderCornerRadius *top_left;
+
+ /* NB: We are an int property, so we have to resolve to an int here.
+ * So we just resolve to an int. We pick one and stick to it.
+ * Lesson learned: Don't query border-radius shorthand, query the
+ * real properties instead. */
+ gtk_style_properties_get (props,
+ state,
+ "border-top-left-radius", &top_left,
+ NULL);
+
+ if (top_left)
+ g_value_set_int (value, top_left->horizontal);
+
+ g_free (top_left);
+}
+
/*** API ***/
static void
@@ -1628,11 +1863,53 @@ gtk_style_property_init (void)
pack_border_width,
NULL,
NULL);
- gtk_style_properties_register_property (NULL,
- g_param_spec_int ("border-radius",
+
+ _gtk_style_property_register (g_param_spec_boxed ("border-top-left-radius",
+ "Border top left radius",
+ "Border radius of top left corner, in pixels",
+ GTK_TYPE_CSS_BORDER_CORNER_RADIUS, 0),
+ NULL,
+ NULL,
+ NULL,
+ border_corner_radius_value_parse,
+ border_corner_radius_value_print);
+ _gtk_style_property_register (g_param_spec_boxed ("border-top-right-radius",
+ "Border top right radius",
+ "Border radius of top right corner, in pixels",
+ GTK_TYPE_CSS_BORDER_CORNER_RADIUS, 0),
+ NULL,
+ NULL,
+ NULL,
+ border_corner_radius_value_parse,
+ border_corner_radius_value_print);
+ _gtk_style_property_register (g_param_spec_boxed ("border-bottom-right-radius",
+ "Border bottom right radius",
+ "Border radius of bottom right corner, in pixels",
+ GTK_TYPE_CSS_BORDER_CORNER_RADIUS, 0),
+ NULL,
+ NULL,
+ NULL,
+ border_corner_radius_value_parse,
+ border_corner_radius_value_print);
+ _gtk_style_property_register (g_param_spec_boxed ("border-bottom-left-radius",
+ "Border bottom left radius",
+ "Border radius of bottom left corner, in pixels",
+ GTK_TYPE_CSS_BORDER_CORNER_RADIUS, 0),
+ NULL,
+ NULL,
+ NULL,
+ border_corner_radius_value_parse,
+ border_corner_radius_value_print);
+ _gtk_style_property_register (g_param_spec_int ("border-radius",
"Border radius",
"Border radius, in pixels",
- 0, G_MAXINT, 0, 0));
+ 0, G_MAXINT, 0, 0),
+ NULL,
+ unpack_border_radius,
+ pack_border_radius,
+ border_radius_value_parse,
+ border_radius_value_print);
+
gtk_style_properties_register_property (NULL,
g_param_spec_enum ("border-style",
"Border style",
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]