summaryrefslogtreecommitdiff
path: root/gtk/gtkcssrepeatvalue.c
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2012-04-04 11:44:57 +0200
committerBenjamin Otte <otte@redhat.com>2012-04-17 08:59:18 +0200
commitf785f7177c455369f1482ff6582cebf69ddddb7a (patch)
tree67d4d3131bd8e69d7ba7c9e7c225beb0ce970ba6 /gtk/gtkcssrepeatvalue.c
parent5377169ef33d7b17d953ccd464e64dbd32335c47 (diff)
downloadgtk+-f785f7177c455369f1482ff6582cebf69ddddb7a.tar.gz
cssvalue: Add a custom value for repeats
In particular, that's background-repeat and border-image-repeat. Also, fix up the border-image shorthand to allow any order.
Diffstat (limited to 'gtk/gtkcssrepeatvalue.c')
-rw-r--r--gtk/gtkcssrepeatvalue.c299
1 files changed, 299 insertions, 0 deletions
diff --git a/gtk/gtkcssrepeatvalue.c b/gtk/gtkcssrepeatvalue.c
new file mode 100644
index 0000000000..0ec1ef7aed
--- /dev/null
+++ b/gtk/gtkcssrepeatvalue.c
@@ -0,0 +1,299 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gtkcssrepeatvalueprivate.h"
+
+#include "gtkcssnumbervalueprivate.h"
+
+struct _GtkCssValue {
+ GTK_CSS_VALUE_BASE
+ GtkCssRepeatStyle x;
+ GtkCssRepeatStyle y;
+};
+
+static void
+gtk_css_value_repeat_free (GtkCssValue *value)
+{
+ g_slice_free (GtkCssValue, value);
+}
+
+static gboolean
+gtk_css_value_repeat_equal (const GtkCssValue *repeat1,
+ const GtkCssValue *repeat2)
+{
+ return repeat1->x == repeat2->x
+ && repeat1->y == repeat2->y;
+}
+
+static GtkCssValue *
+gtk_css_value_repeat_transition (GtkCssValue *start,
+ GtkCssValue *end,
+ double progress)
+{
+ return NULL;
+}
+
+static void
+gtk_css_value_background_repeat_print (const GtkCssValue *repeat,
+ GString *string)
+{
+ static const char *names[] = {
+ "no-repeat",
+ "repeat",
+ "round",
+ "space"
+ };
+
+ if (repeat->x == repeat->y)
+ {
+ g_string_append (string, names[repeat->x]);
+ }
+ else if (repeat->x == GTK_CSS_REPEAT_STYLE_REPEAT &&
+ repeat->y == GTK_CSS_REPEAT_STYLE_NO_REPEAT)
+ {
+ g_string_append (string, "repeat-x");
+ }
+ else if (repeat->x == GTK_CSS_REPEAT_STYLE_NO_REPEAT &&
+ repeat->y == GTK_CSS_REPEAT_STYLE_REPEAT)
+ {
+ g_string_append (string, "repeat-y");
+ }
+ else
+ {
+ g_string_append (string, names[repeat->x]);
+ g_string_append_c (string, ' ');
+ g_string_append (string, names[repeat->y]);
+ }
+}
+
+static void
+gtk_css_value_border_repeat_print (const GtkCssValue *repeat,
+ GString *string)
+{
+ static const char *names[] = {
+ "stretch",
+ "repeat",
+ "round",
+ "space"
+ };
+
+ g_string_append (string, names[repeat->x]);
+ if (repeat->x != repeat->y)
+ {
+ g_string_append_c (string, ' ');
+ g_string_append (string, names[repeat->y]);
+ }
+}
+
+static const GtkCssValueClass GTK_CSS_VALUE_BACKGROUND_REPEAT = {
+ gtk_css_value_repeat_free,
+ gtk_css_value_repeat_equal,
+ gtk_css_value_repeat_transition,
+ gtk_css_value_background_repeat_print
+};
+
+static const GtkCssValueClass GTK_CSS_VALUE_BORDER_REPEAT = {
+ gtk_css_value_repeat_free,
+ gtk_css_value_repeat_equal,
+ gtk_css_value_repeat_transition,
+ gtk_css_value_border_repeat_print
+};
+/* BACKGROUND REPEAT */
+
+static struct {
+ const char *name;
+ GtkCssValue values[4];
+} background_repeat_values[4] = {
+ { "no-repeat",
+ { { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_NO_REPEAT },
+ { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_REPEAT },
+ { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_ROUND },
+ { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_SPACE }
+ } },
+ { "repeat",
+ { { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_NO_REPEAT },
+ { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_REPEAT },
+ { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_ROUND },
+ { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_SPACE }
+ } },
+ { "round",
+ { { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_NO_REPEAT },
+ { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_REPEAT },
+ { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_ROUND },
+ { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_SPACE }
+ } },
+ { "space",
+ { { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_NO_REPEAT },
+ { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_REPEAT },
+ { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_ROUND },
+ { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_SPACE }
+ } }
+};
+
+GtkCssValue *
+_gtk_css_background_repeat_value_new (GtkCssRepeatStyle x,
+ GtkCssRepeatStyle y)
+{
+ return _gtk_css_value_ref (&background_repeat_values[x].values[y]);
+}
+
+static gboolean
+_gtk_css_background_repeat_style_try (GtkCssParser *parser,
+ GtkCssRepeatStyle *result)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (background_repeat_values); i++)
+ {
+ if (_gtk_css_parser_try (parser, background_repeat_values[i].name, TRUE))
+ {
+ *result = i;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+GtkCssValue *
+_gtk_css_background_repeat_value_try_parse (GtkCssParser *parser)
+{
+ GtkCssRepeatStyle x, y;
+
+ g_return_val_if_fail (parser != NULL, NULL);
+
+ if (_gtk_css_parser_try (parser, "repeat-x", TRUE))
+ return _gtk_css_background_repeat_value_new (GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_NO_REPEAT);
+ if (_gtk_css_parser_try (parser, "repeat-y", TRUE))
+ return _gtk_css_background_repeat_value_new (GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_REPEAT);
+
+ if (!_gtk_css_background_repeat_style_try (parser, &x))
+ return NULL;
+
+ if (!_gtk_css_background_repeat_style_try (parser, &y))
+ y = x;
+
+ return _gtk_css_background_repeat_value_new (x, y);
+}
+
+GtkCssRepeatStyle
+_gtk_css_background_repeat_value_get_x (const GtkCssValue *repeat)
+{
+ g_return_val_if_fail (repeat->class == &GTK_CSS_VALUE_BACKGROUND_REPEAT, GTK_CSS_REPEAT_STYLE_NO_REPEAT);
+
+ return repeat->x;
+}
+
+GtkCssRepeatStyle
+_gtk_css_background_repeat_value_get_y (const GtkCssValue *repeat)
+{
+ g_return_val_if_fail (repeat->class == &GTK_CSS_VALUE_BACKGROUND_REPEAT, GTK_CSS_REPEAT_STYLE_NO_REPEAT);
+
+ return repeat->y;
+}
+
+/* BORDER IMAGE REPEAT */
+
+static struct {
+ const char *name;
+ GtkCssValue values[4];
+} border_repeat_values[4] = {
+ { "stretch",
+ { { &GTK_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_STRETCH },
+ { &GTK_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_REPEAT },
+ { &GTK_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_ROUND },
+ { &GTK_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_SPACE }
+ } },
+ { "repeat",
+ { { &GTK_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_STRETCH },
+ { &GTK_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_REPEAT },
+ { &GTK_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_ROUND },
+ { &GTK_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_SPACE }
+ } },
+ { "round",
+ { { &GTK_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_STRETCH },
+ { &GTK_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_REPEAT },
+ { &GTK_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_ROUND },
+ { &GTK_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_SPACE }
+ } },
+ { "space",
+ { { &GTK_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_STRETCH },
+ { &GTK_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_REPEAT },
+ { &GTK_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_ROUND },
+ { &GTK_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_SPACE }
+ } }
+};
+
+GtkCssValue *
+_gtk_css_border_repeat_value_new (GtkCssRepeatStyle x,
+ GtkCssRepeatStyle y)
+{
+ return _gtk_css_value_ref (&border_repeat_values[x].values[y]);
+}
+
+static gboolean
+_gtk_css_border_repeat_style_try (GtkCssParser *parser,
+ GtkCssRepeatStyle *result)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (border_repeat_values); i++)
+ {
+ if (_gtk_css_parser_try (parser, border_repeat_values[i].name, TRUE))
+ {
+ *result = i;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+GtkCssValue *
+_gtk_css_border_repeat_value_try_parse (GtkCssParser *parser)
+{
+ GtkCssRepeatStyle x, y;
+
+ g_return_val_if_fail (parser != NULL, NULL);
+
+ if (!_gtk_css_border_repeat_style_try (parser, &x))
+ return NULL;
+
+ if (!_gtk_css_border_repeat_style_try (parser, &y))
+ y = x;
+
+ return _gtk_css_border_repeat_value_new (x, y);
+}
+
+GtkCssRepeatStyle
+_gtk_css_border_repeat_value_get_x (const GtkCssValue *repeat)
+{
+ g_return_val_if_fail (repeat->class == &GTK_CSS_VALUE_BORDER_REPEAT, GTK_CSS_REPEAT_STYLE_STRETCH);
+
+ return repeat->x;
+}
+
+GtkCssRepeatStyle
+_gtk_css_border_repeat_value_get_y (const GtkCssValue *repeat)
+{
+ g_return_val_if_fail (repeat->class == &GTK_CSS_VALUE_BORDER_REPEAT, GTK_CSS_REPEAT_STYLE_STRETCH);
+
+ return repeat->y;
+}
+