diff options
author | Benjamin Otte <otte@redhat.com> | 2012-04-04 11:44:57 +0200 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2012-04-17 08:59:18 +0200 |
commit | f785f7177c455369f1482ff6582cebf69ddddb7a (patch) | |
tree | 67d4d3131bd8e69d7ba7c9e7c225beb0ce970ba6 /gtk/gtkcssrepeatvalue.c | |
parent | 5377169ef33d7b17d953ccd464e64dbd32335c47 (diff) | |
download | gtk+-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.c | 299 |
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", + { { >K_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_NO_REPEAT }, + { >K_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_REPEAT }, + { >K_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_ROUND }, + { >K_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_SPACE } + } }, + { "repeat", + { { >K_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_NO_REPEAT }, + { >K_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_REPEAT }, + { >K_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_ROUND }, + { >K_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_SPACE } + } }, + { "round", + { { >K_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_NO_REPEAT }, + { >K_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_REPEAT }, + { >K_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_ROUND }, + { >K_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_SPACE } + } }, + { "space", + { { >K_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_NO_REPEAT }, + { >K_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_REPEAT }, + { >K_CSS_VALUE_BACKGROUND_REPEAT, 1, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_ROUND }, + { >K_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 == >K_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 == >K_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", + { { >K_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_STRETCH }, + { >K_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_REPEAT }, + { >K_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_ROUND }, + { >K_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_SPACE } + } }, + { "repeat", + { { >K_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_STRETCH }, + { >K_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_REPEAT }, + { >K_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_ROUND }, + { >K_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_SPACE } + } }, + { "round", + { { >K_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_STRETCH }, + { >K_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_REPEAT }, + { >K_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_ROUND }, + { >K_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_SPACE } + } }, + { "space", + { { >K_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_STRETCH }, + { >K_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_REPEAT }, + { >K_CSS_VALUE_BORDER_REPEAT, 1, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_ROUND }, + { >K_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 == >K_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 == >K_CSS_VALUE_BORDER_REPEAT, GTK_CSS_REPEAT_STYLE_STRETCH); + + return repeat->y; +} + |