[gtk+/wip/otte/tokenizer: 15/42] css: Allow the css editor to take a CSS node



commit d0461871ca5b105e6f7566dcea1131d1c1aabc52
Author: Benjamin Otte <otte redhat com>
Date:   Tue Mar 15 09:23:25 2016 +0100

    css: Allow the css editor to take a CSS node
    
    Use that to hilight the selectors that match that node.

 gtk/gtkcssstylerule.c        |   25 ++++++++++
 gtk/gtkcssstyleruleprivate.h |    5 ++
 gtk/inspector/css-editor.c   |  100 ++++++++++++++++++++++++++++++++++++++++++
 gtk/inspector/css-editor.h   |    7 ++-
 gtk/inspector/css-editor.ui  |   14 +++++-
 5 files changed, 148 insertions(+), 3 deletions(-)
---
diff --git a/gtk/gtkcssstylerule.c b/gtk/gtkcssstylerule.c
index c40c9b6..c7d3645 100644
--- a/gtk/gtkcssstylerule.c
+++ b/gtk/gtkcssstylerule.c
@@ -139,6 +139,31 @@ gtk_css_style_rule_new_parse (GtkCssTokenSource *source,
   return GTK_CSS_RULE (rule);
 }
 
+gsize
+gtk_css_style_rule_get_n_selectors (GtkCssStyleRule *rule)
+{
+  GtkCssStyleRulePrivate *priv;
+  
+  g_return_val_if_fail (GTK_IS_CSS_STYLE_RULE (rule), 0);
+
+  priv = gtk_css_style_rule_get_instance_private (rule);
+
+  return priv->selectors->len;
+}
+
+GtkCssSelector *
+gtk_css_style_rule_get_selector (GtkCssStyleRule *rule,
+                                 gsize            id)
+{
+  GtkCssStyleRulePrivate *priv;
+  
+  g_return_val_if_fail (GTK_IS_CSS_STYLE_RULE (rule), 0);
+
+  priv = gtk_css_style_rule_get_instance_private (rule);
+
+  return g_ptr_array_index (priv->selectors, id);
+}
+
 GtkCssStyleDeclaration *
 gtk_css_style_rule_get_style (GtkCssStyleRule *rule)
 {
diff --git a/gtk/gtkcssstyleruleprivate.h b/gtk/gtkcssstyleruleprivate.h
index 1b60ec0..023ccb6 100644
--- a/gtk/gtkcssstyleruleprivate.h
+++ b/gtk/gtkcssstyleruleprivate.h
@@ -21,6 +21,7 @@
 #define __GTK_CSS_STYLE_RULE_PRIVATE_H__
 
 #include "gtk/gtkcssruleprivate.h"
+#include "gtk/gtkcssselectorprivate.h"
 #include "gtk/gtkcssstyledeclarationprivate.h"
 
 G_BEGIN_DECLS
@@ -51,6 +52,10 @@ GtkCssRule *            gtk_css_style_rule_new_parse            (GtkCssTokenSour
                                                                  GtkCssRule             *parent_rule,
                                                                  GtkCssStyleSheet       *parent_style_sheet);
 
+gsize                   gtk_css_style_rule_get_n_selectors      (GtkCssStyleRule        *rule);
+GtkCssSelector *        gtk_css_style_rule_get_selector         (GtkCssStyleRule        *rule,
+                                                                 gsize                   id);
+
 GtkCssStyleDeclaration *gtk_css_style_rule_get_style            (GtkCssStyleRule        *rule);
 
 
diff --git a/gtk/inspector/css-editor.c b/gtk/inspector/css-editor.c
index 36e9ddf..a8ca34f 100644
--- a/gtk/inspector/css-editor.c
+++ b/gtk/inspector/css-editor.c
@@ -28,6 +28,7 @@
 #include "gtkcssdeclarationprivate.h"
 #include "gtkcssprovider.h"
 #include "gtkcssrbtreeprivate.h"
+#include "gtkcssstyleruleprivate.h"
 #include "gtkcssstylesheetprivate.h"
 #include "gtkcsstokenizerprivate.h"
 #include "gtkcsstokensourceprivate.h"
@@ -79,6 +80,7 @@ struct _GtkInspectorCssEditorPrivate
   GtkCssRbTree *tokens;
   GtkCssProvider *provider;
   GtkCssStyleSheet *style_sheet;
+  GtkCssNode *node;
   GtkToggleButton *disable_button;
   guint timeout;
 };
@@ -498,6 +500,54 @@ apply_declaration (GtkInspectorCssEditor *ce,
 }
 
 static gboolean
+apply_selector (GtkInspectorCssEditor *ce,
+                GtkCssChunk           *chunk)
+{
+  GtkCssChunk *prev;
+
+  if (!GTK_IS_CSS_STYLE_RULE (chunk->consumer))
+    return FALSE;
+
+  for (prev = chunk;
+       prev->consumer == chunk->consumer;
+       prev = gtk_css_rb_tree_get_previous (ce->priv->tokens, prev))
+    {
+      if (gtk_css_token_is (&chunk->token, GTK_CSS_TOKEN_OPEN_CURLY))
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
+static gboolean
+apply_selector_matching (GtkInspectorCssEditor *ce,
+                         GtkCssChunk           *chunk)
+{
+  GtkCssMatcher matcher;
+  GtkCssStyleRule *rule;
+  gsize i;
+
+  if (ce->priv->node == NULL)
+    return FALSE;
+
+  if (!apply_selector (ce, chunk))
+    return FALSE;
+
+  rule = GTK_CSS_STYLE_RULE (chunk->consumer);
+  gtk_css_node_init_matcher (ce->priv->node, &matcher);
+
+  for (i = 0; i < gtk_css_style_rule_get_n_selectors (rule); i++)
+    {
+      GtkCssSelector *selector = gtk_css_style_rule_get_selector (rule, i);
+
+      if (_gtk_css_selector_matches (selector, &matcher))
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
+static gboolean
 apply_error (GtkInspectorCssEditor *ce,
              GtkCssChunk           *chunk)
 {
@@ -521,6 +571,9 @@ static struct {
   { "comment", apply_comment },
   { "string", apply_string },
   { "declaration", apply_declaration },
+  { "selector", apply_selector },
+  { "selector-matching", apply_selector_matching },
+  { "declaration", apply_declaration },
   { "error", apply_error },
   { "warning", apply_warning },
 };
@@ -713,9 +766,13 @@ finalize (GObject *object)
   if (ce->priv->timeout != 0)
     g_source_remove (ce->priv->timeout);
 
+  gtk_inspector_css_editor_set_node (ce, NULL);
+
   if (ce->priv->tokens)
     gtk_css_rb_tree_unref (ce->priv->tokens);
 
+  gtk_inspector_css_editor_set_node (ce, NULL);
+
   g_object_unref (ce->priv->style_sheet);
 
   destroy_provider (ce);
@@ -742,4 +799,47 @@ gtk_inspector_css_editor_class_init (GtkInspectorCssEditorClass *klass)
   gtk_widget_class_bind_template_callback (widget_class, query_tooltip_cb);
 }
 
+static void
+gtk_inspector_css_editor_node_changed_cb (GtkCssNode            *node,
+                                          GtkCssStyleChange     *change,
+                                          GtkInspectorCssEditor *ce)
+{
+  clear_all_tags (ce);
+  update_token_tags (ce, gtk_css_rb_tree_get_first (ce->priv->tokens), NULL);
+}
+
+void
+gtk_inspector_css_editor_set_node (GtkInspectorCssEditor *ce,
+                                   GtkCssNode            *node)
+{
+  GtkInspectorCssEditorPrivate *priv;
+
+  g_return_if_fail (GTK_INSPECTOR_IS_CSS_EDITOR (ce));
+  g_return_if_fail (node == NULL || GTK_IS_CSS_NODE (node));
+
+  priv = ce->priv;
+
+  if (priv->node == node)
+    return;
+
+  if (priv->node)
+    {
+      g_signal_handlers_disconnect_by_func (priv->node, gtk_inspector_css_editor_node_changed_cb, ce);
+    }
+
+  priv->node = node;
+
+  if (node)
+    {
+      g_object_ref (node);
+      g_signal_connect (priv->node,
+                        "style-changed",
+                        G_CALLBACK (gtk_inspector_css_editor_node_changed_cb),
+                        ce);
+    }
+
+  clear_all_tags (ce);
+  update_token_tags (ce, gtk_css_rb_tree_get_first (ce->priv->tokens), NULL);
+}
+
 // vim: set et sw=2 ts=2:
diff --git a/gtk/inspector/css-editor.h b/gtk/inspector/css-editor.h
index ad95d65..9a2057a 100644
--- a/gtk/inspector/css-editor.h
+++ b/gtk/inspector/css-editor.h
@@ -25,6 +25,8 @@
 
 #include <gtk/gtkbox.h>
 
+#include "gtkcssnodeprivate.h"
+
 #define GTK_TYPE_INSPECTOR_CSS_EDITOR            (gtk_inspector_css_editor_get_type())
 #define GTK_INSPECTOR_CSS_EDITOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), 
GTK_TYPE_INSPECTOR_CSS_EDITOR, GtkInspectorCssEditor))
 #define GTK_INSPECTOR_CSS_EDITOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), 
GTK_TYPE_INSPECTOR_CSS_EDITOR, GtkInspectorCssEditorClass))
@@ -49,8 +51,9 @@ typedef struct _GtkInspectorCssEditorClass
 G_BEGIN_DECLS
 
 GType      gtk_inspector_css_editor_get_type   (void);
-void       gtk_inspector_css_editor_set_object (GtkInspectorCssEditor *ce,
-                                                GObject               *object);
+
+void       gtk_inspector_css_editor_set_node   (GtkInspectorCssEditor *ce,
+                                                GtkCssNode            *node);
 
 G_END_DECLS
 
diff --git a/gtk/inspector/css-editor.ui b/gtk/inspector/css-editor.ui
index 7bb3ee2..4880b3b 100644
--- a/gtk/inspector/css-editor.ui
+++ b/gtk/inspector/css-editor.ui
@@ -10,7 +10,19 @@
     <child type="tag">
       <object class="GtkTextTag">
         <property name="name">string</property>
-        <property name="foreground">red</property>
+        <property name="foreground">darkred</property>
+      </object>
+    </child>
+    <child type="tag">
+      <object class="GtkTextTag">
+        <property name="name">selector</property>
+        <property name="foreground">darkgreen</property>
+      </object>
+    </child>
+    <child type="tag">
+      <object class="GtkTextTag">
+        <property name="name">selector-matching</property>
+        <property name="background">yellow</property>
       </object>
     </child>
     <child type="tag">


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