[gtk+/gtk-style-context: 68/276] GtkCssProvider: Add support for child/descendant combinators.



commit 580180d85e04785b56e4b8fd457e603e0c789de6
Author: Carlos Garnacho <carlosg gnome org>
Date:   Fri Apr 16 03:02:42 2010 +0200

    GtkCssProvider: Add support for child/descendant combinators.
    
    Now, selectors like:
    
      GtkWindow > GtkButton {}
      GtkNotebook > GtkLabel {}
    
    will represent a direct parent/child relation between both elements, while
    
      GtkWindow GtkButton {}
      GtkNotebook GtkLabel {}
    
    will allow intermediate children between these.

 gtk/gtkcssprovider.c |   40 ++++++++++++++++++++++++++++++++++++++--
 1 files changed, 38 insertions(+), 2 deletions(-)
---
diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c
index 5fdc882..8fbddc2 100644
--- a/gtk/gtkcssprovider.c
+++ b/gtk/gtkcssprovider.c
@@ -33,6 +33,7 @@ typedef struct SelectorElement SelectorElement;
 typedef struct SelectorPath SelectorPath;
 typedef struct SelectorStyleInfo SelectorStyleInfo;
 typedef enum SelectorElementType SelectorElementType;
+typedef enum CombinatorType CombinatorType;
 typedef enum ParserScope ParserScope;
 
 enum SelectorElementType {
@@ -42,9 +43,15 @@ enum SelectorElementType {
   SELECTOR_GLOB
 };
 
+enum CombinatorType {
+  COMBINATOR_DESCENDANT, /* No direct relation needed */
+  COMBINATOR_CHILD       /* Direct child */
+};
+
 struct SelectorElement
 {
   SelectorElementType elem_type;
+  CombinatorType combinator;
 
   union
   {
@@ -150,6 +157,7 @@ selector_path_prepend_type (SelectorPath *path,
   GType type;
 
   elem = g_slice_new (SelectorElement);
+  elem->combinator = COMBINATOR_DESCENDANT;
   type = g_type_from_name (type_name);
 
   if (type == G_TYPE_INVALID)
@@ -173,10 +181,24 @@ selector_path_prepend_glob (SelectorPath *path)
 
   elem = g_slice_new (SelectorElement);
   elem->elem_type = SELECTOR_GLOB;
+  elem->combinator = COMBINATOR_DESCENDANT;
 
   path->elements = g_slist_prepend (path->elements, elem);
 }
 
+static void
+selector_path_prepend_combinator (SelectorPath   *path,
+                                  CombinatorType  combinator)
+{
+  SelectorElement *elem;
+
+  g_assert (path->elements != NULL);
+
+  /* It is actually stored in the last element */
+  elem = path->elements->data;
+  elem->combinator = combinator;
+}
+
 static gint
 selector_path_depth (SelectorPath *path)
 {
@@ -286,8 +308,16 @@ compare_path_foreach (GType        type,
       if (!g_type_is_a (type, elem->type))
         {
           /* Selector definitely doesn't match */
-          data->score = 0;
-          return TRUE;
+          if (elem->combinator == COMBINATOR_CHILD)
+            {
+              data->score = 0;
+              return TRUE;
+            }
+          else
+            {
+              /* Keep checking descendants for a match */
+              return FALSE;
+            }
         }
       else if (type == elem->type)
         data->score |= 0xF;
@@ -614,6 +644,12 @@ parse_selector (GtkCssProvider  *css_provider,
         }
 
       g_scanner_get_next_token (scanner);
+
+      if (scanner->token == '>')
+        {
+          selector_path_prepend_combinator (path, COMBINATOR_CHILD);
+          g_scanner_get_next_token (scanner);
+        }
     }
 
   if (scanner->token == ':')



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