[gtk+/wip/cssnode3: 4/88] cssnode: Split into 3 objects



commit 4c0a76a8b6a6ae225752ea61507b112658b35a62
Author: Benjamin Otte <otte redhat com>
Date:   Mon Jan 12 03:58:21 2015 +0100

    cssnode: Split into 3 objects
    
    - GtkCssWidgetNode
      for style contexts owned by a widget
    - GtkCssPathNode
      for style contexts using a GtkWidgetPath
    - GtkCssTransientNode
      for nodes created with gtk_style_context_save()/restore()

 gtk/Makefile.am                  |    8 ++-
 gtk/gtkcssnode.c                 |   46 +++++----
 gtk/gtkcssnodeprivate.h          |    9 +-
 gtk/gtkcsspathnode.c             |   89 +++++++++++++++++
 gtk/gtkcsspathnodeprivate.h      |   58 +++++++++++
 gtk/gtkcsstransientnode.c        |   82 +++++++++++++++
 gtk/gtkcsstransientnodeprivate.h |   51 ++++++++++
 gtk/gtkcsswidgetnode.c           |   93 +++++++++++++++++
 gtk/gtkcsswidgetnodeprivate.h    |   58 +++++++++++
 gtk/gtkstylecontext.c            |  204 +++++++++++++++++++++++---------------
 10 files changed, 597 insertions(+), 101 deletions(-)
---
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index d20364b..5fdb68d 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -401,6 +401,7 @@ gtk_private_h_sources =             \
        gtkcssnodedeclarationprivate.h  \
        gtkcssnumbervalueprivate.h      \
        gtkcssparserprivate.h   \
+       gtkcsspathnodeprivate.h \
        gtkcsspositionvalueprivate.h    \
        gtkcssproviderprivate.h \
        gtkcssrepeatvalueprivate.h      \
@@ -416,10 +417,12 @@ gtk_private_h_sources =           \
        gtkcssstyleprivate.h    \
        gtkcssstylepropertyprivate.h \
        gtkcsstransformvalueprivate.h   \
+       gtkcsstransientnodeprivate.h    \
        gtkcsstransitionprivate.h       \
        gtkcsstypedvalueprivate.h       \
        gtkcssunsetvalueprivate.h       \
        gtkcssvalueprivate.h    \
+       gtkcsswidgetnodeprivate.h       \
        gtkcustompaperunixdialog.h \
        gtkdialogprivate.h      \
        gtkentryprivate.h       \
@@ -631,6 +634,7 @@ gtk_base_c_sources =                \
        gtkcssnodedeclaration.c \
        gtkcssnumbervalue.c     \
        gtkcssparser.c          \
+       gtkcsspathnode.c        \
        gtkcsspositionvalue.c   \
        gtkcssprovider.c        \
        gtkcssrepeatvalue.c     \
@@ -648,11 +652,13 @@ gtk_base_c_sources =              \
        gtkcssstyleproperty.c   \
        gtkcssstylepropertyimpl.c \
        gtkcsstransformvalue.c  \
+       gtkcsstransientnode.c   \
        gtkcsstransition.c      \
        gtkcsstypedvalue.c      \
        gtkcssunsetvalue.c      \
-       gtkcssvalue.c           \
        gtkcsstypes.c           \
+       gtkcssvalue.c           \
+       gtkcsswidgetnode.c      \
        gtkdialog.c             \
        gtkdrawingarea.c        \
        gtkeditable.c           \
diff --git a/gtk/gtkcssnode.c b/gtk/gtkcssnode.c
index a4b5a63..86c0a07 100644
--- a/gtk/gtkcssnode.c
+++ b/gtk/gtkcssnode.c
@@ -33,12 +33,27 @@ gtk_css_node_finalize (GObject *object)
   G_OBJECT_CLASS (gtk_css_node_parent_class)->finalize (object);
 }
 
+static GtkWidgetPath *
+gtk_css_node_real_create_widget_path (GtkCssNode *cssnode)
+{
+  return gtk_widget_path_new ();
+}
+
+static const GtkWidgetPath *
+gtk_css_node_real_get_widget_path (GtkCssNode *cssnode)
+{
+  return NULL;
+}
+
 static void
 gtk_css_node_class_init (GtkCssNodeClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
   object_class->finalize = gtk_css_node_finalize;
+
+  klass->create_widget_path = gtk_css_node_real_create_widget_path;
+  klass->get_widget_path = gtk_css_node_real_get_widget_path;
 }
 
 static void
@@ -47,24 +62,6 @@ gtk_css_node_init (GtkCssNode *cssnode)
   cssnode->decl = gtk_css_node_declaration_new ();
 }
 
-GtkCssNode *
-gtk_css_node_new (void)
-{
-  return g_object_new (GTK_TYPE_CSS_NODE, NULL);
-}
-
-GtkCssNode *
-gtk_css_node_copy (GtkCssNode *cssnode)
-{
-  GtkCssNode *copy;
-
-  copy = gtk_css_node_new ();
-  gtk_css_node_declaration_unref (copy->decl);
-  copy->decl = gtk_css_node_declaration_ref (cssnode->decl);
-
-  return copy;
-}
-
 void
 gtk_css_node_set_parent (GtkCssNode *cssnode,
                          GtkCssNode *parent)
@@ -220,3 +217,16 @@ gtk_css_node_dup_declaration (GtkCssNode *cssnode)
 {
   return gtk_css_node_declaration_ref (cssnode->decl);
 }
+
+GtkWidgetPath *
+gtk_css_node_create_widget_path (GtkCssNode *cssnode)
+{
+  return GTK_CSS_NODE_GET_CLASS (cssnode)->create_widget_path (cssnode);
+}
+
+const GtkWidgetPath *
+gtk_css_node_get_widget_path (GtkCssNode *cssnode)
+{
+  return GTK_CSS_NODE_GET_CLASS (cssnode)->get_widget_path (cssnode);
+}
+
diff --git a/gtk/gtkcssnodeprivate.h b/gtk/gtkcssnodeprivate.h
index 7d217d9..fb8bb4d 100644
--- a/gtk/gtkcssnodeprivate.h
+++ b/gtk/gtkcssnodeprivate.h
@@ -45,13 +45,13 @@ struct _GtkCssNode
 struct _GtkCssNodeClass
 {
   GObjectClass object_class;
+
+  GtkWidgetPath *       (* create_widget_path)          (GtkCssNode            *cssnode);
+  const GtkWidgetPath * (* get_widget_path)             (GtkCssNode            *cssnode);
 };
 
 GType                   gtk_css_node_get_type           (void) G_GNUC_CONST;
 
-GtkCssNode *            gtk_css_node_new                (void);
-GtkCssNode *            gtk_css_node_copy               (GtkCssNode            *cssnode);
-
 void                    gtk_css_node_set_parent         (GtkCssNode            *cssnode,
                                                          GtkCssNode            *parent);
 GtkCssNode *            gtk_css_node_get_parent         (GtkCssNode            *cssnode);
@@ -94,6 +94,9 @@ GtkCssStyle *           gtk_css_node_get_style          (GtkCssNode            *
 void                    gtk_css_node_set_style          (GtkCssNode            *cssnode,
                                                          GtkCssStyle           *style);
 
+GtkWidgetPath *         gtk_css_node_create_widget_path (GtkCssNode            *cssnode);
+const GtkWidgetPath *   gtk_css_node_get_widget_path    (GtkCssNode            *cssnode);
+
 G_END_DECLS
 
 #endif /* __GTK_CSS_NODE_PRIVATE_H__ */
diff --git a/gtk/gtkcsspathnode.c b/gtk/gtkcsspathnode.c
new file mode 100644
index 0000000..85358b4
--- /dev/null
+++ b/gtk/gtkcsspathnode.c
@@ -0,0 +1,89 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2014 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gtkcsspathnodeprivate.h"
+#include "gtkprivate.h"
+
+G_DEFINE_TYPE (GtkCssPathNode, gtk_css_path_node, GTK_TYPE_CSS_NODE)
+
+static GtkWidgetPath *
+gtk_css_path_node_real_create_widget_path (GtkCssNode *node)
+{
+  GtkCssPathNode *path_node = GTK_CSS_PATH_NODE (node);
+
+  if (path_node->path == NULL)
+    return gtk_widget_path_new ();
+
+  return gtk_widget_path_copy (path_node->path);
+}
+
+static const GtkWidgetPath *
+gtk_css_path_node_real_get_widget_path (GtkCssNode *node)
+{
+  GtkCssPathNode *path_node = GTK_CSS_PATH_NODE (node);
+
+  return path_node->path;
+}
+
+static void
+gtk_css_path_node_class_init (GtkCssPathNodeClass *klass)
+{
+  GtkCssNodeClass *node_class = GTK_CSS_NODE_CLASS (klass);
+
+  node_class->create_widget_path = gtk_css_path_node_real_create_widget_path;
+  node_class->get_widget_path = gtk_css_path_node_real_get_widget_path;
+}
+
+static void
+gtk_css_path_node_init (GtkCssPathNode *cssnode)
+{
+}
+
+GtkCssNode *
+gtk_css_path_node_new (void)
+{
+  return g_object_new (GTK_TYPE_CSS_PATH_NODE, NULL);
+}
+
+void
+gtk_css_path_node_set_widget_path (GtkCssPathNode *node,
+                                   GtkWidgetPath  *path)
+{
+  gtk_internal_return_if_fail (GTK_IS_CSS_PATH_NODE (node));
+
+  if (node->path == path)
+    return;
+
+  if (node->path)
+    gtk_widget_path_unref (node->path);
+
+  if (path)
+    gtk_widget_path_ref (path);
+
+  node->path = path;
+}
+
+GtkWidgetPath *
+gtk_css_path_node_get_widget_path (GtkCssPathNode *node)
+{
+  gtk_internal_return_val_if_fail (GTK_IS_CSS_PATH_NODE (node), NULL);
+
+  return node->path;
+}
+
diff --git a/gtk/gtkcsspathnodeprivate.h b/gtk/gtkcsspathnodeprivate.h
new file mode 100644
index 0000000..0ff89e7
--- /dev/null
+++ b/gtk/gtkcsspathnodeprivate.h
@@ -0,0 +1,58 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2014 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_CSS_PATH_NODE_PRIVATE_H__
+#define __GTK_CSS_PATH_NODE_PRIVATE_H__
+
+#include "gtkcssnodeprivate.h"
+#include "gtkwidgetpath.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_CSS_PATH_NODE           (gtk_css_path_node_get_type ())
+#define GTK_CSS_PATH_NODE(obj)           (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_PATH_NODE, 
GtkCssPathNode))
+#define GTK_CSS_PATH_NODE_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_PATH_NODE, 
GtkCssPathNodeClass))
+#define GTK_IS_CSS_PATH_NODE(obj)        (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_PATH_NODE))
+#define GTK_IS_CSS_PATH_NODE_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_PATH_NODE))
+#define GTK_CSS_PATH_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_PATH_NODE, 
GtkCssPathNodeClass))
+
+typedef struct _GtkCssPathNode           GtkCssPathNode;
+typedef struct _GtkCssPathNodeClass      GtkCssPathNodeClass;
+
+struct _GtkCssPathNode
+{
+  GtkCssNode node;
+
+  GtkWidgetPath *path;
+};
+
+struct _GtkCssPathNodeClass
+{
+  GtkCssNodeClass node_class;
+};
+
+GType                   gtk_css_path_node_get_type         (void) G_GNUC_CONST;
+
+GtkCssNode *            gtk_css_path_node_new              (void);
+
+void                    gtk_css_path_node_set_widget_path  (GtkCssPathNode *node,
+                                                            GtkWidgetPath  *path);
+GtkWidgetPath *         gtk_css_path_node_get_widget_path  (GtkCssPathNode *node);
+
+G_END_DECLS
+
+#endif /* __GTK_CSS_PATH_NODE_PRIVATE_H__ */
diff --git a/gtk/gtkcsstransientnode.c b/gtk/gtkcsstransientnode.c
new file mode 100644
index 0000000..723c97a
--- /dev/null
+++ b/gtk/gtkcsstransientnode.c
@@ -0,0 +1,82 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2014 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gtkcsstransientnodeprivate.h"
+#include "gtkprivate.h"
+
+G_DEFINE_TYPE (GtkCssTransientNode, gtk_css_transient_node, GTK_TYPE_CSS_NODE)
+
+static GtkWidgetPath *
+gtk_css_transient_node_create_widget_path (GtkCssNode *node)
+{
+  GtkWidgetPath *result;
+  GtkCssNode *parent;
+
+  parent = gtk_css_node_get_parent (node);
+  if (parent == NULL)
+    result = gtk_widget_path_new ();
+  else
+    result = gtk_css_node_create_widget_path (parent);
+
+  gtk_widget_path_append_type (result, gtk_css_node_get_widget_type (node));
+  gtk_css_node_declaration_add_to_widget_path (gtk_css_node_get_declaration (node), result, -1);
+  
+  return result;
+}
+
+static const GtkWidgetPath *
+gtk_css_transient_node_get_widget_path (GtkCssNode *node)
+{
+  GtkCssNode *parent;
+
+  parent = gtk_css_node_get_parent (node);
+  if (parent == NULL)
+    return NULL;
+
+  return gtk_css_node_get_widget_path (parent);
+}
+
+static void
+gtk_css_transient_node_class_init (GtkCssTransientNodeClass *klass)
+{
+  GtkCssNodeClass *node_class = GTK_CSS_NODE_CLASS (klass);
+
+  node_class->create_widget_path = gtk_css_transient_node_create_widget_path;
+  node_class->get_widget_path = gtk_css_transient_node_get_widget_path;
+}
+
+static void
+gtk_css_transient_node_init (GtkCssTransientNode *cssnode)
+{
+}
+
+GtkCssNode *
+gtk_css_transient_node_new (GtkCssNode *parent)
+{
+  GtkCssNode *result;
+
+  gtk_internal_return_val_if_fail (GTK_IS_CSS_NODE (parent), NULL);
+
+  result = g_object_new (GTK_TYPE_CSS_TRANSIENT_NODE, NULL);
+  gtk_css_node_declaration_unref (result->decl);
+  result->decl = gtk_css_node_declaration_ref (parent->decl);
+
+  return result;
+}
+
diff --git a/gtk/gtkcsstransientnodeprivate.h b/gtk/gtkcsstransientnodeprivate.h
new file mode 100644
index 0000000..2fb438a
--- /dev/null
+++ b/gtk/gtkcsstransientnodeprivate.h
@@ -0,0 +1,51 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2014 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_CSS_TRANSIENT_NODE_PRIVATE_H__
+#define __GTK_CSS_TRANSIENT_NODE_PRIVATE_H__
+
+#include "gtkcssnodeprivate.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_CSS_TRANSIENT_NODE           (gtk_css_transient_node_get_type ())
+#define GTK_CSS_TRANSIENT_NODE(obj)           (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_TRANSIENT_NODE, 
GtkCssTransientNode))
+#define GTK_CSS_TRANSIENT_NODE_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_TRANSIENT_NODE, 
GtkCssTransientNodeClass))
+#define GTK_IS_CSS_TRANSIENT_NODE(obj)        (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_TRANSIENT_NODE))
+#define GTK_IS_CSS_TRANSIENT_NODE_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_TRANSIENT_NODE))
+#define GTK_CSS_TRANSIENT_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), 
GTK_TYPE_CSS_TRANSIENT_NODE, GtkCssTransientNodeClass))
+
+typedef struct _GtkCssTransientNode           GtkCssTransientNode;
+typedef struct _GtkCssTransientNodeClass      GtkCssTransientNodeClass;
+
+struct _GtkCssTransientNode
+{
+  GtkCssNode node;
+};
+
+struct _GtkCssTransientNodeClass
+{
+  GtkCssNodeClass node_class;
+};
+
+GType                   gtk_css_transient_node_get_type         (void) G_GNUC_CONST;
+
+GtkCssNode *            gtk_css_transient_node_new              (GtkCssNode     *parent);
+
+G_END_DECLS
+
+#endif /* __GTK_CSS_TRANSIENT_NODE_PRIVATE_H__ */
diff --git a/gtk/gtkcsswidgetnode.c b/gtk/gtkcsswidgetnode.c
new file mode 100644
index 0000000..b7932ce
--- /dev/null
+++ b/gtk/gtkcsswidgetnode.c
@@ -0,0 +1,93 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2014 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gtkcsswidgetnodeprivate.h"
+#include "gtkprivate.h"
+#include "gtkwidgetprivate.h"
+
+G_DEFINE_TYPE (GtkCssWidgetNode, gtk_css_widget_node, GTK_TYPE_CSS_NODE)
+
+static GtkWidgetPath *
+gtk_css_widget_node_create_widget_path (GtkCssNode *node)
+{
+  GtkCssWidgetNode *widget_node = GTK_CSS_WIDGET_NODE (node);
+
+  if (widget_node->widget == NULL)
+    return gtk_widget_path_new ();
+
+  return _gtk_widget_create_path (widget_node->widget);
+}
+
+static const GtkWidgetPath *
+gtk_css_widget_node_get_widget_path (GtkCssNode *node)
+{
+  GtkCssWidgetNode *widget_node = GTK_CSS_WIDGET_NODE (node);
+
+  if (widget_node->widget == NULL)
+    return NULL;
+
+  return gtk_widget_get_path (widget_node->widget);
+}
+
+static void
+gtk_css_widget_node_class_init (GtkCssWidgetNodeClass *klass)
+{
+  GtkCssNodeClass *node_class = GTK_CSS_NODE_CLASS (klass);
+
+  node_class->create_widget_path = gtk_css_widget_node_create_widget_path;
+  node_class->get_widget_path = gtk_css_widget_node_get_widget_path;
+}
+
+static void
+gtk_css_widget_node_init (GtkCssWidgetNode *cssnode)
+{
+}
+
+GtkCssNode *
+gtk_css_widget_node_new (GtkWidget *widget)
+{
+  GtkCssWidgetNode *result;
+
+  gtk_internal_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+
+  result = g_object_new (GTK_TYPE_CSS_WIDGET_NODE, NULL);
+  result->widget = widget;
+
+  return GTK_CSS_NODE (result);
+}
+
+void
+gtk_css_widget_node_widget_destroyed (GtkCssWidgetNode *node)
+{
+  gtk_internal_return_if_fail (GTK_IS_CSS_WIDGET_NODE (node));
+  gtk_internal_return_if_fail (node->widget != NULL);
+
+  node->widget = NULL;
+  /* Contents of this node are now undefined.
+   * So we don't clear the style or anything.
+   */
+}
+
+GtkWidget *
+gtk_css_widget_node_get_widget (GtkCssWidgetNode *node)
+{
+  gtk_internal_return_val_if_fail (GTK_IS_CSS_WIDGET_NODE (node), NULL);
+
+  return node->widget;
+}
diff --git a/gtk/gtkcsswidgetnodeprivate.h b/gtk/gtkcsswidgetnodeprivate.h
new file mode 100644
index 0000000..78c4337
--- /dev/null
+++ b/gtk/gtkcsswidgetnodeprivate.h
@@ -0,0 +1,58 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2014 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_CSS_WIDGET_NODE_PRIVATE_H__
+#define __GTK_CSS_WIDGET_NODE_PRIVATE_H__
+
+#include "gtkcssnodeprivate.h"
+#include "gtkwidget.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_CSS_WIDGET_NODE           (gtk_css_widget_node_get_type ())
+#define GTK_CSS_WIDGET_NODE(obj)           (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_WIDGET_NODE, 
GtkCssWidgetNode))
+#define GTK_CSS_WIDGET_NODE_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_WIDGET_NODE, 
GtkCssWidgetNodeClass))
+#define GTK_IS_CSS_WIDGET_NODE(obj)        (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_WIDGET_NODE))
+#define GTK_IS_CSS_WIDGET_NODE_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_WIDGET_NODE))
+#define GTK_CSS_WIDGET_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_WIDGET_NODE, 
GtkCssWidgetNodeClass))
+
+typedef struct _GtkCssWidgetNode           GtkCssWidgetNode;
+typedef struct _GtkCssWidgetNodeClass      GtkCssWidgetNodeClass;
+
+struct _GtkCssWidgetNode
+{
+  GtkCssNode node;
+
+  GtkWidget *widget;
+};
+
+struct _GtkCssWidgetNodeClass
+{
+  GtkCssNodeClass node_class;
+};
+
+GType                   gtk_css_widget_node_get_type         (void) G_GNUC_CONST;
+
+GtkCssNode *            gtk_css_widget_node_new              (GtkWidget         *widget);
+
+void                    gtk_css_widget_node_widget_destroyed (GtkCssWidgetNode  *node);
+
+GtkWidget *             gtk_css_widget_node_get_widget       (GtkCssWidgetNode  *node);
+
+G_END_DECLS
+
+#endif /* __GTK_CSS_WIDGET_NODE_PRIVATE_H__ */
diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c
index c5ec2d4..24b50a0 100644
--- a/gtk/gtkstylecontext.c
+++ b/gtk/gtkstylecontext.c
@@ -33,15 +33,17 @@
 #include "gtkcssnodedeclarationprivate.h"
 #include "gtkcssnodeprivate.h"
 #include "gtkcssnumbervalueprivate.h"
+#include "gtkcsspathnodeprivate.h"
 #include "gtkcssrgbavalueprivate.h"
 #include "gtkcssshadowsvalueprivate.h"
 #include "gtkcssstaticstyleprivate.h"
 #include "gtkcssstylepropertyprivate.h"
 #include "gtkcsstransformvalueprivate.h"
+#include "gtkcsstransientnodeprivate.h"
+#include "gtkcsswidgetnodeprivate.h"
 #include "gtkdebug.h"
 #include "gtktypebuiltins.h"
 #include "gtkintl.h"
-#include "gtkwidget.h"
 #include "gtkwindow.h"
 #include "gtkprivate.h"
 #include "gtkwidgetpath.h"
@@ -152,8 +154,6 @@ struct _GtkStyleContextPrivate
   GtkStyleCascade *cascade;
   GtkStyleContext *parent;
   GSList *children;
-  GtkWidget *widget;
-  GtkWidgetPath *widget_path;
   GHashTable *style_values;
   GtkCssNode *cssnode;
   GSList *saved_nodes;
@@ -206,8 +206,8 @@ gtk_style_context_real_changed (GtkStyleContext *context)
 {
   GtkStyleContextPrivate *priv = context->priv;
 
-  if (priv->widget)
-    _gtk_widget_style_context_invalidated (priv->widget);
+  if (GTK_IS_CSS_WIDGET_NODE (priv->cssnode))
+    _gtk_widget_style_context_invalidated (gtk_css_widget_node_get_widget (GTK_CSS_WIDGET_NODE 
(priv->cssnode)));
 }
 
 static void
@@ -377,7 +377,7 @@ gtk_style_context_init (GtkStyleContext *style_context)
   priv->screen = gdk_screen_get_default ();
 
   /* Create default info store */
-  priv->cssnode = gtk_css_node_new ();
+  priv->cssnode = gtk_css_path_node_new ();
   gtk_css_node_set_state (priv->cssnode, GTK_STATE_FLAG_DIR_LTR);
 
   priv->property_cache = g_array_new (FALSE, FALSE, sizeof (PropertyValue));
@@ -460,15 +460,20 @@ static gboolean
 gtk_style_context_should_animate (GtkStyleContext *context)
 {
   GtkStyleContextPrivate *priv;
+  GtkWidget *widget;
   GtkCssStyle *values;
   gboolean animate;
 
   priv = context->priv;
 
-  if (priv->widget == NULL)
+  if (!GTK_IS_CSS_WIDGET_NODE (priv->cssnode))
     return FALSE;
 
-  if (!gtk_widget_get_mapped (priv->widget))
+  widget = gtk_css_widget_node_get_widget (GTK_CSS_WIDGET_NODE (priv->cssnode));
+  if (widget == NULL)
+    return FALSE;
+
+  if (!gtk_widget_get_mapped (widget))
     return FALSE;
 
   values = gtk_style_context_lookup_style (context);
@@ -476,7 +481,7 @@ gtk_style_context_should_animate (GtkStyleContext *context)
       gtk_css_animated_style_is_static (GTK_CSS_ANIMATED_STYLE (values)))
     return FALSE;
 
-  g_object_get (gtk_widget_get_settings (context->priv->widget),
+  g_object_get (gtk_widget_get_settings (widget),
                 "gtk-enable-animations", &animate,
                 NULL);
 
@@ -522,9 +527,6 @@ gtk_style_context_finalize (GObject *object)
 
   gtk_style_context_set_cascade (style_context, NULL);
 
-  if (priv->widget_path)
-    gtk_widget_path_free (priv->widget_path);
-
   g_hash_table_destroy (priv->style_values);
 
   while (priv->saved_nodes)
@@ -636,16 +638,16 @@ create_query_path (GtkStyleContext              *context,
                    const GtkCssNodeDeclaration  *decl,
                    gboolean                      is_root)
 {
-  GtkStyleContextPrivate *priv;
+  GtkCssNode *root;
   GtkWidgetPath *path;
   guint length;
 
-  priv = context->priv;
-  path = priv->widget ? _gtk_widget_create_path (priv->widget) : gtk_widget_path_copy (priv->widget_path);
+  root = gtk_style_context_get_root (context);
+
+  path = gtk_css_node_create_widget_path (root);
   length = gtk_widget_path_length (path);
   if (!is_root)
     {
-      GtkCssNode *root = gtk_style_context_get_root (context);
 
       if (length > 0)
         gtk_css_node_declaration_add_to_widget_path (gtk_css_node_get_declaration (root), path, length - 1);
@@ -911,9 +913,12 @@ gtk_style_context_set_invalid (GtkStyleContext *context,
 
   if (invalid)
     {
+      GtkWidget *widget;
+
       G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
-      if (GTK_IS_RESIZE_CONTAINER (priv->widget))
-        _gtk_container_queue_restyle (GTK_CONTAINER (priv->widget));
+      if (GTK_IS_CSS_WIDGET_NODE (priv->cssnode) &&
+          GTK_IS_RESIZE_CONTAINER (widget = gtk_css_widget_node_get_widget (GTK_CSS_WIDGET_NODE 
(priv->cssnode))))
+        _gtk_container_queue_restyle (GTK_CONTAINER (widget));
       else if (priv->parent)
         gtk_style_context_set_invalid (priv->parent, TRUE);
       G_GNUC_END_IGNORE_DEPRECATIONS;
@@ -962,15 +967,31 @@ void
 _gtk_style_context_set_widget (GtkStyleContext *context,
                                GtkWidget       *widget)
 {
+  GtkStyleContextPrivate *priv;
+
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
   g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
+  g_return_if_fail (!gtk_style_context_is_saved (context));
 
-  context->priv->widget = widget;
+  priv = context->priv;
+
+  if (!GTK_IS_CSS_WIDGET_NODE (priv->cssnode))
+    {
+      g_object_unref (priv->cssnode);
+      priv->cssnode = gtk_css_widget_node_new (widget);
+      gtk_css_node_set_state (priv->cssnode, GTK_STATE_FLAG_DIR_LTR);
+      gtk_css_node_set_style (priv->cssnode, gtk_css_static_style_get_default (priv->screen));
+    }
 
   if (widget)
-    gtk_css_node_set_widget_type (context->priv->cssnode, G_OBJECT_TYPE (widget));
+    {
+      gtk_css_node_set_widget_type (priv->cssnode, G_OBJECT_TYPE (widget));
+    }
   else
-    gtk_css_node_set_widget_type (context->priv->cssnode, G_TYPE_NONE);
+    {
+      gtk_css_node_set_widget_type (priv->cssnode, G_TYPE_NONE);
+      gtk_css_widget_node_widget_destroyed (GTK_CSS_WIDGET_NODE (priv->cssnode));
+    }
 
   _gtk_style_context_update_animating (context);
 
@@ -1214,7 +1235,6 @@ gtk_style_context_get_property (GtkStyleContext *context,
                                 GtkStateFlags    state,
                                 GValue          *value)
 {
-  GtkStyleContextPrivate *priv;
   GtkCssStyle *values;
   GtkStyleProperty *prop;
 
@@ -1222,9 +1242,6 @@ gtk_style_context_get_property (GtkStyleContext *context,
   g_return_if_fail (property != NULL);
   g_return_if_fail (value != NULL);
 
-  priv = context->priv;
-  g_return_if_fail (priv->widget != NULL || priv->widget_path != NULL);
-
   prop = _gtk_style_property_lookup (property);
   if (prop == NULL)
     {
@@ -1499,30 +1516,29 @@ void
 gtk_style_context_set_path (GtkStyleContext *context,
                             GtkWidgetPath   *path)
 {
-  GtkStyleContextPrivate *priv;
+  GtkCssNode *root;
 
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
   g_return_if_fail (path != NULL);
 
-  priv = context->priv;
-  g_return_if_fail (priv->widget == NULL);
+  root = gtk_style_context_get_root (context);
+  g_return_if_fail (GTK_IS_CSS_PATH_NODE (root));
 
-  if (priv->widget_path)
+  if (path)
     {
-      gtk_widget_path_free (priv->widget_path);
-      priv->widget_path = NULL;
-      gtk_css_node_set_widget_type (context->priv->cssnode, G_TYPE_NONE);
+      GtkWidgetPath *copy = gtk_widget_path_copy (path);
+      gtk_css_path_node_set_widget_path (GTK_CSS_PATH_NODE (root), copy);
+      if (gtk_widget_path_length (copy))
+        gtk_css_node_set_widget_type (root,
+                                      gtk_widget_path_iter_get_object_type (copy, -1));
+      gtk_widget_path_unref (copy);
     }
-
-  if (path)
+  else
     {
-      priv->widget_path = gtk_widget_path_copy (path);
-      if (gtk_widget_path_length (path))
-        gtk_css_node_set_widget_type (context->priv->cssnode,
-                                      gtk_widget_path_iter_get_object_type (path, -1));
+      gtk_css_path_node_set_widget_path (GTK_CSS_PATH_NODE (root), NULL);
+      gtk_css_node_set_widget_type (root, G_TYPE_NONE);
     }
 
-
   _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANY);
 }
 
@@ -1539,13 +1555,7 @@ gtk_style_context_set_path (GtkStyleContext *context,
 const GtkWidgetPath *
 gtk_style_context_get_path (GtkStyleContext *context)
 {
-  GtkStyleContextPrivate *priv;
-
-  priv = context->priv;
-  if (priv->widget)
-    return gtk_widget_get_path (priv->widget);
-  else
-    return priv->widget_path;
+  return gtk_css_node_get_widget_path (gtk_style_context_get_root (context));
 }
 
 /**
@@ -1641,7 +1651,7 @@ gtk_style_context_save (GtkStyleContext *context)
   if (!gtk_style_context_is_saved (context))
     gtk_style_context_lookup_style (context);
 
-  cssnode = gtk_css_node_copy (priv->cssnode);
+  cssnode = gtk_css_transient_node_new (priv->cssnode);
   gtk_css_node_set_parent (cssnode, gtk_style_context_get_root (context));
 
   priv->saved_nodes = g_slist_prepend (priv->saved_nodes, priv->cssnode);
@@ -2021,6 +2031,7 @@ _gtk_style_context_peek_style_property (GtkStyleContext *context,
                                         GParamSpec      *pspec)
 {
   GtkStyleContextPrivate *priv;
+  GtkWidgetPath *path;
   PropertyValue *pcache, key = { 0 };
   guint i;
 
@@ -2048,13 +2059,12 @@ _gtk_style_context_peek_style_property (GtkStyleContext *context,
   g_param_spec_ref (pcache->pspec);
   g_value_init (&pcache->value, G_PARAM_SPEC_VALUE_TYPE (pspec));
 
-  if (priv->widget || priv->widget_path)
+  path = gtk_css_node_create_widget_path (gtk_style_context_get_root (context));
+  if (path && gtk_widget_path_length (path) > 0)
     {
-      GtkWidgetPath *widget_path = priv->widget ? _gtk_widget_create_path (priv->widget) : priv->widget_path;
-
       if (gtk_style_provider_get_style_property (GTK_STYLE_PROVIDER (priv->cascade),
-                                                 widget_path,
-                                                 gtk_widget_path_iter_get_state (widget_path, -1),
+                                                 path,
+                                                 gtk_widget_path_iter_get_state (path, -1),
                                                  pspec, &pcache->value))
         {
           G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
@@ -2097,16 +2107,14 @@ _gtk_style_context_peek_style_property (GtkStyleContext *context,
 
           G_GNUC_END_IGNORE_DEPRECATIONS;
 
-          if (priv->widget)
-            gtk_widget_path_free (widget_path);
+          gtk_widget_path_unref (path);
 
           return &pcache->value;
         }
-
-      if (priv->widget)
-        gtk_widget_path_free (widget_path);
     }
 
+  gtk_widget_path_unref (path);
+
   /* not supplied by any provider, revert to default */
   g_param_value_set_default (pspec, &pcache->value);
 
@@ -2129,7 +2137,7 @@ gtk_style_context_get_style_property (GtkStyleContext *context,
                                       const gchar     *property_name,
                                       GValue          *value)
 {
-  GtkStyleContextPrivate *priv;
+  GtkCssNode *root;
   GtkWidgetClass *widget_class;
   GParamSpec *pspec;
   const GValue *peek_value;
@@ -2139,18 +2147,27 @@ gtk_style_context_get_style_property (GtkStyleContext *context,
   g_return_if_fail (property_name != NULL);
   g_return_if_fail (value != NULL);
 
-  priv = context->priv;
+  root = gtk_style_context_get_root (context);
 
-  if (priv->widget)
+  if (GTK_IS_CSS_WIDGET_NODE (root))
     {
-      widget_type = G_OBJECT_TYPE (priv->widget);
+      GtkWidget *widget;
+      
+      widget = gtk_css_widget_node_get_widget (GTK_CSS_WIDGET_NODE (root));
+      if (widget == NULL)
+        return;
+
+      widget_type = G_OBJECT_TYPE (widget);
     }
-  else
+  else if (GTK_IS_CSS_PATH_NODE (root))
     {
-      if (!priv->widget_path)
+      GtkWidgetPath *path;
+      
+      path = gtk_css_path_node_get_widget_path (GTK_CSS_PATH_NODE (root));
+      if (path == NULL)
         return;
 
-      widget_type = gtk_widget_path_get_object_type (priv->widget_path);
+      widget_type = gtk_widget_path_get_object_type (path);
 
       if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET))
         {
@@ -2160,6 +2177,10 @@ gtk_style_context_get_style_property (GtkStyleContext *context,
           return;
         }
     }
+  else
+    {
+      return;
+    }
 
   widget_class = g_type_class_ref (widget_type);
   pspec = gtk_widget_class_find_style_property (widget_class, property_name);
@@ -2201,25 +2222,34 @@ void
 gtk_style_context_get_style_valist (GtkStyleContext *context,
                                     va_list          args)
 {
-  GtkStyleContextPrivate *priv;
+  GtkCssNode *root;
   const gchar *prop_name;
   GType widget_type;
 
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
 
   prop_name = va_arg (args, const gchar *);
-  priv = context->priv;
+  root = gtk_style_context_get_root (context);
 
-  if (priv->widget)
+  if (GTK_IS_CSS_WIDGET_NODE (root))
     {
-      widget_type = G_OBJECT_TYPE (priv->widget);
+      GtkWidget *widget;
+      
+      widget = gtk_css_widget_node_get_widget (GTK_CSS_WIDGET_NODE (root));
+      if (widget == NULL)
+        return;
+
+      widget_type = G_OBJECT_TYPE (widget);
     }
-  else
+  else if (GTK_IS_CSS_PATH_NODE (root))
     {
-      if (!priv->widget_path)
+      GtkWidgetPath *path;
+      
+      path = gtk_css_path_node_get_widget_path (GTK_CSS_PATH_NODE (root));
+      if (path == NULL)
         return;
 
-      widget_type = gtk_widget_path_get_object_type (priv->widget_path);
+      widget_type = gtk_widget_path_get_object_type (path);
 
       if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET))
         {
@@ -2229,6 +2259,10 @@ gtk_style_context_get_style_valist (GtkStyleContext *context,
           return;
         }
     }
+  else
+    {
+      return;
+    }
 
   while (prop_name)
     {
@@ -2894,20 +2928,25 @@ gtk_style_context_should_create_transitions (GtkStyleContext *context,
                                              GtkCssStyle     *previous_style)
 {
   GtkStyleContextPrivate *priv;
+  GtkWidget *widget;
   gboolean animate;
 
   priv = context->priv;
 
-  if (priv->widget == NULL)
+  if (GTK_IS_CSS_WIDGET_NODE (priv->cssnode))
     return FALSE;
 
-  if (!gtk_widget_get_mapped (priv->widget))
+  widget = gtk_css_widget_node_get_widget (GTK_CSS_WIDGET_NODE (priv->cssnode));
+  if (widget == NULL)
+    return FALSE;
+
+  if (!gtk_widget_get_mapped (widget))
     return FALSE;
 
   if (previous_style == gtk_css_static_style_get_default ())
     return FALSE;
 
-  g_object_get (gtk_widget_get_settings (context->priv->widget),
+  g_object_get (gtk_widget_get_settings (widget),
                 "gtk-enable-animations", &animate,
                 NULL);
 
@@ -2952,10 +2991,17 @@ _gtk_style_context_validate (GtkStyleContext  *context,
 
   if (G_UNLIKELY (gtk_style_context_is_saved (context)))
     {
-      g_warning ("unmatched gtk_style_context_save/restore() detected while validating context for %s %p",
-                 priv->widget ? gtk_widget_get_name (priv->widget) : "widget path",
-                 priv->widget ? (gpointer) priv->widget : (gpointer) priv->widget_path);
       cssnode = gtk_style_context_get_root (context);
+      if (GTK_IS_CSS_WIDGET_NODE (cssnode))
+        {
+          GtkWidget *widget = gtk_css_widget_node_get_widget (GTK_CSS_WIDGET_NODE (cssnode));
+          g_warning ("unmatched gtk_style_context_save/restore() detected while validating context for %s 
%p",
+                     gtk_widget_get_name (widget), widget);
+        }
+      else
+        {
+          g_warning ("unmatched gtk_style_context_save/restore() detected while validating context");
+        }
     }
   else
     cssnode = priv->cssnode;
@@ -3065,12 +3111,12 @@ _gtk_style_context_queue_invalidate (GtkStyleContext *context,
 
   priv = context->priv;
 
-  if (priv->widget != NULL)
+  if (GTK_IS_CSS_WIDGET_NODE (priv->cssnode))
     {
       priv->pending_changes |= change;
       gtk_style_context_set_invalid (context, TRUE);
     }
-  else if (priv->widget_path != NULL)
+  else if (GTK_IS_CSS_PATH_NODE (priv->cssnode))
     {
       G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
       gtk_style_context_invalidate (context);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]