diff options
author | Benjamin Otte <otte@redhat.com> | 2016-03-26 06:17:51 +0100 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2016-04-08 16:18:31 +0200 |
commit | 9d07be0238bab6d40ed453bf303b5e3959b875c8 (patch) | |
tree | 585b265cd23790e803f5c647cb6403ff5bfa5abd | |
parent | f36217dda6b8ed83be6571565a7d30f89a4ae985 (diff) | |
download | gtk+-9d07be0238bab6d40ed453bf303b5e3959b875c8.tar.gz |
css: Parse widget styles with token parser
-rw-r--r-- | gtk/Makefile.am | 2 | ||||
-rw-r--r-- | gtk/gtkcssdeclaration.c | 7 | ||||
-rw-r--r-- | gtk/gtkcsswidgetstyledeclaration.c | 197 | ||||
-rw-r--r-- | gtk/gtkcsswidgetstyledeclarationprivate.h | 57 |
4 files changed, 262 insertions, 1 deletions
diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 699037e5f2..18fed3a1d0 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -467,6 +467,7 @@ gtk_private_h_sources = \ gtkcssvalueprivate.h \ gtkcsswin32sizevalueprivate.h \ gtkcsswidgetnodeprivate.h \ + gtkcsswidgetstyledeclarationprivate.h \ gtkcustompaperunixdialog.h \ gtkdialogprivate.h \ gtkdndprivate.h \ @@ -752,6 +753,7 @@ gtk_base_c_sources = \ gtkcsstypes.c \ gtkcssvalue.c \ gtkcsswidgetnode.c \ + gtkcsswidgetstyledeclaration.c \ gtkcsswin32sizevalue.c \ gtkdialog.c \ gtkdragsource.c \ diff --git a/gtk/gtkcssdeclaration.c b/gtk/gtkcssdeclaration.c index 1d1d09f4a3..aed4a306bb 100644 --- a/gtk/gtkcssdeclaration.c +++ b/gtk/gtkcssdeclaration.c @@ -23,6 +23,7 @@ #include "gtkcsslonghanddeclarationprivate.h" #include "gtkcssshorthanddeclarationprivate.h" +#include "gtkcsswidgetstyledeclarationprivate.h" #include "gtkstylepropertyprivate.h" #include "gtkintl.h" #include "gtkprivate.h" @@ -139,9 +140,13 @@ gtk_css_declaration_new_parse (GtkCssStyleDeclaration *style, return gtk_css_longhand_declaration_new_parse (style, source); else if (GTK_IS_CSS_SHORTHAND_PROPERTY (prop)) return gtk_css_shorthand_declaration_new_parse (style, source); + else if (gtk_css_widget_style_declaration_accepts_name (token->string.string)) + return gtk_css_widget_style_declaration_new_parse (style, source); else { - gtk_css_token_source_error (source, "Property name does not define a valid property"); + gtk_css_token_source_unknown (source, + "Property name \"%s\" does not define a valid property", + token->string.string); gtk_css_token_source_consume_all (source); return NULL; } diff --git a/gtk/gtkcsswidgetstyledeclaration.c b/gtk/gtkcsswidgetstyledeclaration.c new file mode 100644 index 0000000000..7b5e458555 --- /dev/null +++ b/gtk/gtkcsswidgetstyledeclaration.c @@ -0,0 +1,197 @@ +/* + * Copyright © 2016 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.1 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/>. + * + * Authors: Benjamin Otte <otte@gnome.org> + */ + +#include "config.h" + +#include "gtkcsswidgetstyledeclarationprivate.h" + +#include "gtkwidget.h" + +#include <string.h> + +typedef struct _GtkCssWidgetStyleDeclarationPrivate GtkCssWidgetStyleDeclarationPrivate; +struct _GtkCssWidgetStyleDeclarationPrivate { + char *name; + char *value; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (GtkCssWidgetStyleDeclaration, gtk_css_widget_style_declaration, GTK_TYPE_CSS_DECLARATION) + +static void +gtk_css_widget_style_declaration_finalize (GObject *object) +{ + GtkCssWidgetStyleDeclaration *widget_style = GTK_CSS_WIDGET_STYLE_DECLARATION (object); + GtkCssWidgetStyleDeclarationPrivate *priv = gtk_css_widget_style_declaration_get_instance_private (widget_style); + + g_free (priv->name); + g_free (priv->value); + + G_OBJECT_CLASS (gtk_css_widget_style_declaration_parent_class)->finalize (object); +} + +static const char * +gtk_css_widget_style_declaration_get_name (GtkCssDeclaration *decl) +{ + GtkCssWidgetStyleDeclaration *widget_style_declaration = GTK_CSS_WIDGET_STYLE_DECLARATION (decl); + GtkCssWidgetStyleDeclarationPrivate *priv = gtk_css_widget_style_declaration_get_instance_private (widget_style_declaration); + + return priv->name; +} + +static void +gtk_css_widget_style_declaration_print_value (GtkCssDeclaration *decl, + GString *string) +{ + GtkCssWidgetStyleDeclaration *widget_style = GTK_CSS_WIDGET_STYLE_DECLARATION (decl); + GtkCssWidgetStyleDeclarationPrivate *priv = gtk_css_widget_style_declaration_get_instance_private (widget_style); + + g_string_append (string, priv->value); +} + +static void +gtk_css_widget_style_declaration_class_init (GtkCssWidgetStyleDeclarationClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkCssDeclarationClass *decl_class = GTK_CSS_DECLARATION_CLASS (klass); + + object_class->finalize = gtk_css_widget_style_declaration_finalize; + + decl_class->get_name = gtk_css_widget_style_declaration_get_name; + decl_class->print_value = gtk_css_widget_style_declaration_print_value; +} + +static void +gtk_css_widget_style_declaration_init (GtkCssWidgetStyleDeclaration *widget_style_declaration) +{ +} + +gboolean +gtk_css_widget_style_declaration_accepts_name (const char *name) +{ + g_return_val_if_fail (name != NULL, FALSE); + + if (name[0] != '-') + return FALSE; + + if (g_str_has_prefix (name, "-gtk-")) + return FALSE; + + return TRUE; +} + +static void +warn_if_deprecated (GtkCssTokenSource *source, + const gchar *name) +{ + gchar *n = NULL; + gchar *p; + const gchar *type_name; + const gchar *property_name; + GType type; + GTypeClass *class = NULL; + GParamSpec *pspec; + + n = g_strdup (name); + + /* skip initial - */ + type_name = n + 1; + + p = strchr (type_name, '-'); + if (!p) + goto out; + + p[0] = '\0'; + property_name = p + 1; + + type = g_type_from_name (type_name); + if (type == G_TYPE_INVALID || + !g_type_is_a (type, GTK_TYPE_WIDGET)) + goto out; + + class = g_type_class_ref (type); + pspec = gtk_widget_class_find_style_property (GTK_WIDGET_CLASS (class), property_name); + if (!pspec) + goto out; + + if (!(pspec->flags & G_PARAM_DEPRECATED)) + goto out; + + gtk_css_token_source_deprecated (source, + "The style property %s:%s is deprecated and shouldn't be " + "used anymore. It will be removed in a future version", + g_type_name (pspec->owner_type), pspec->name); + +out: + g_free (n); + if (class) + g_type_class_unref (class); +} + +GtkCssDeclaration * +gtk_css_widget_style_declaration_new_parse (GtkCssStyleDeclaration *style, + GtkCssTokenSource *source) +{ + GtkCssWidgetStyleDeclarationPrivate *priv; + const GtkCssToken *token; + GtkCssWidgetStyleDeclaration *decl; + + decl = g_object_new (GTK_TYPE_CSS_WIDGET_STYLE_DECLARATION, + "parent-style", style, + NULL); + priv = gtk_css_widget_style_declaration_get_instance_private (decl); + + gtk_css_token_source_set_consumer (source, G_OBJECT (decl)); + + token = gtk_css_token_source_get_token (source); + if (!gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT)) + { + gtk_css_token_source_error (source, "Expected a property name"); + gtk_css_token_source_consume_all (source); + g_object_unref (decl); + return NULL; + } + if (!gtk_css_widget_style_declaration_accepts_name (token->string.string)) + { + gtk_css_token_source_unknown (source, "Property name '%s' is not valid for a widget style property", token->string.string); + gtk_css_token_source_consume_all (source); + g_object_unref (decl); + return NULL; + } + + priv->name = g_strdup (token->string.string); + warn_if_deprecated (source, priv->name); + gtk_css_token_source_consume_token (source); + + token = gtk_css_token_source_get_token (source); + if (!gtk_css_token_is (token, GTK_CSS_TOKEN_COLON)) + { + gtk_css_token_source_error (source, "No colon following property name"); + gtk_css_token_source_consume_all (source); + g_object_unref (decl); + return NULL; + } + gtk_css_token_source_consume_token (source); + + /* skip whitespace */ + gtk_css_token_source_get_token (source); + priv->value = gtk_css_token_source_consume_to_string (source); + + return GTK_CSS_DECLARATION (decl); +} + diff --git a/gtk/gtkcsswidgetstyledeclarationprivate.h b/gtk/gtkcsswidgetstyledeclarationprivate.h new file mode 100644 index 0000000000..555232f866 --- /dev/null +++ b/gtk/gtkcsswidgetstyledeclarationprivate.h @@ -0,0 +1,57 @@ +/* + * Copyright © 2016 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.1 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/>. + * + * Authors: Benjamin Otte <otte@gnome.org> + */ + +#ifndef __GTK_CSS_WIDGET_STYLE_DECLARATION_PRIVATE_H__ +#define __GTK_CSS_WIDGET_STYLE_DECLARATION_PRIVATE_H__ + +#include "gtk/gtkcssdeclarationprivate.h" + +G_BEGIN_DECLS + +#define GTK_TYPE_CSS_WIDGET_STYLE_DECLARATION (gtk_css_widget_style_declaration_get_type ()) +#define GTK_CSS_WIDGET_STYLE_DECLARATION(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_WIDGET_STYLE_DECLARATION, GtkCssWidgetStyleDeclaration)) +#define GTK_CSS_WIDGET_STYLE_DECLARATION_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_WIDGET_STYLE_DECLARATION, GtkCssWidgetStyleDeclarationClass)) +#define GTK_IS_CSS_WIDGET_STYLE_DECLARATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_WIDGET_STYLE_DECLARATION)) +#define GTK_IS_CSS_WIDGET_STYLE_DECLARATION_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_WIDGET_STYLE_DECLARATION)) +#define GTK_CSS_WIDGET_STYLE_DECLARATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_WIDGET_STYLE_DECLARATION, GtkCssWidgetStyleDeclarationClass)) + +typedef struct _GtkCssWidgetStyleDeclaration GtkCssWidgetStyleDeclaration; +typedef struct _GtkCssWidgetStyleDeclarationClass GtkCssWidgetStyleDeclarationClass; + +struct _GtkCssWidgetStyleDeclaration +{ + GtkCssDeclaration parent; +}; + +struct _GtkCssWidgetStyleDeclarationClass +{ + GtkCssDeclarationClass parent_class; +}; + +GType gtk_css_widget_style_declaration_get_type (void) G_GNUC_CONST; + +gboolean gtk_css_widget_style_declaration_accepts_name (const char *name); + +GtkCssDeclaration * gtk_css_widget_style_declaration_new_parse (GtkCssStyleDeclaration *style, + GtkCssTokenSource *source); + + +G_END_DECLS + +#endif /* __GTK_CSS_WIDGET_STYLE_DECLARATION_PRIVATE_H__ */ |