]> Pileus Git - ~andy/gtk/commitdiff
selector: Add sibling seletors
authorBenjamin Otte <otte@redhat.com>
Fri, 2 Mar 2012 01:04:15 +0000 (02:04 +0100)
committerBenjamin Otte <otte@redhat.com>
Fri, 2 Mar 2012 01:17:10 +0000 (02:17 +0100)
"a + b" and "a ~ b" selectors now work, provided the widget supports
siblings.

gtk/gtkcssselector.c

index b25ad3e7171f81cca18dc80a4f4b47bda080e73b..b15bb771990f35ee95f50e0e443e49489e9c68e6 100644 (file)
@@ -166,6 +166,75 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_CHILD = {
   FALSE, FALSE, FALSE
 };
 
+/* SIBLING */
+
+static void
+gtk_css_selector_sibling_print (const GtkCssSelector *selector,
+                                GString              *string)
+{
+  g_string_append (string, " ~ ");
+}
+
+static gboolean
+gtk_css_selector_sibling_match (const GtkCssSelector *selector,
+                                GtkStateFlags         state,
+                                const GtkWidgetPath  *path,
+                                guint                 id,
+                                guint                 sibling)
+{
+  while (sibling-- > 0)
+    {
+      if (gtk_css_selector_match (gtk_css_selector_previous (selector),
+                                  0,
+                                  path,
+                                  id,
+                                  sibling))
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
+static const GtkCssSelectorClass GTK_CSS_SELECTOR_SIBLING = {
+  "sibling",
+  gtk_css_selector_sibling_print,
+  gtk_css_selector_sibling_match,
+  FALSE, FALSE, FALSE
+};
+
+/* ADJACENT */
+
+static void
+gtk_css_selector_adjacent_print (const GtkCssSelector *selector,
+                                 GString              *string)
+{
+  g_string_append (string, " + ");
+}
+
+static gboolean
+gtk_css_selector_adjacent_match (const GtkCssSelector *selector,
+                                 GtkStateFlags         state,
+                                 const GtkWidgetPath  *path,
+                                 guint                 id,
+                                 guint                 sibling)
+{
+  if (sibling == 0)
+    return FALSE;
+
+  return gtk_css_selector_match (gtk_css_selector_previous (selector),
+                                 0,
+                                 path,
+                                 id,
+                                 sibling - 1);
+}
+
+static const GtkCssSelectorClass GTK_CSS_SELECTOR_ADJACENT = {
+  "adjacent",
+  gtk_css_selector_adjacent_print,
+  gtk_css_selector_adjacent_match,
+  FALSE, FALSE, FALSE
+};
+
 /* NAME */
 
 static void
@@ -736,7 +805,11 @@ _gtk_css_selector_parse (GtkCssParser *parser)
          !_gtk_css_parser_begins_with (parser, ',') &&
          !_gtk_css_parser_begins_with (parser, '{'))
     {
-      if (_gtk_css_parser_try (parser, ">", TRUE))
+      if (_gtk_css_parser_try (parser, "+", TRUE))
+        selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_ADJACENT, selector, NULL);
+      else if (_gtk_css_parser_try (parser, "~", TRUE))
+        selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_SIBLING, selector, NULL);
+      else if (_gtk_css_parser_try (parser, ">", TRUE))
         selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_CHILD, selector, NULL);
       else
         selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_DESCENDANT, selector, NULL);