3 namespace Tizen.NUI.StyleSheets
5 internal abstract class Selector
11 public static Selector Parse(CssReader reader, char stopChar = '\0')
13 Selector root = All, workingRoot = All;
14 Operator workingRootParent = null;
15 Action<Operator, Selector> setCurrentSelector = (op, sel) => SetCurrentSelector(ref root, ref workingRoot, ref workingRootParent, op, sel);
18 reader.SkipWhiteSpaces();
19 while ((p = reader.Peek()) > 0)
21 switch (unchecked((char)p))
24 setCurrentSelector(new And(), All);
29 var className = reader.ReadIdent();
30 if (className == null)
32 setCurrentSelector(new And(), new Class(className));
36 var id = reader.ReadName();
39 setCurrentSelector(new And(), new Id(id));
42 throw new NotImplementedException("Attributes not implemented");
45 setCurrentSelector(new Or(), All);
46 reader.SkipWhiteSpaces();
50 setCurrentSelector(new Adjacent(), All);
51 reader.SkipWhiteSpaces();
55 setCurrentSelector(new Sibling(), All);
56 reader.SkipWhiteSpaces();
60 setCurrentSelector(new Child(), All);
61 reader.SkipWhiteSpaces();
63 case '^': //not in CSS spec
65 var element = reader.ReadIdent();
66 if (element == null) return Invalid;
67 setCurrentSelector(new And(), new Base(element));
75 bool processWs = false;
76 while ((p = reader.Peek()) > 0)
78 var c = unchecked((char)p);
79 if (char.IsWhiteSpace(c))
94 setCurrentSelector(new Descendent(), All);
95 reader.SkipWhiteSpaces();
98 if (unchecked((char)p) == stopChar)
101 var elementName = reader.ReadIdent();
102 if (elementName == null)
104 setCurrentSelector(new And(), new Element(elementName));
111 static void SetCurrentSelector(ref Selector root, ref Selector workingRoot, ref Operator workingRootParent, Operator op, Selector sel)
113 var updateRoot = root == workingRoot;
115 op.Left = workingRoot;
118 if (workingRootParent != null)
119 workingRootParent.Right = workingRoot;
124 if (workingRoot is Or)
126 workingRootParent = (Operator)workingRoot;
131 public abstract bool Matches(IStyleSelectable styleable);
133 internal static Selector Invalid = new Generic(s => false);
134 internal static Selector All = new Generic(s => true);
136 abstract class UnarySelector : Selector
140 abstract class Operator : Selector
142 public Selector Left { get; set; } = Invalid;
143 public Selector Right { get; set; } = Invalid;
146 sealed class Generic : UnarySelector
148 readonly Func<IStyleSelectable, bool> func;
149 public Generic(Func<IStyleSelectable, bool> func)
154 public override bool Matches(IStyleSelectable styleable) => func(styleable);
157 sealed class Class : UnarySelector
159 public Class(string className)
161 ClassName = className;
164 public string ClassName { get; }
165 public override bool Matches(IStyleSelectable styleable)
166 => styleable.Classes != null && styleable.Classes.Contains(ClassName);
169 sealed class Id : UnarySelector
176 public string IdName { get; }
177 public override bool Matches(IStyleSelectable styleable) => styleable.Id == IdName;
180 sealed class Or : Operator
182 public override bool Matches(IStyleSelectable styleable) => Right.Matches(styleable) || Left.Matches(styleable);
185 sealed class And : Operator
187 public override bool Matches(IStyleSelectable styleable) => Right.Matches(styleable) && Left.Matches(styleable);
190 sealed class Element : UnarySelector
192 public Element(string elementName)
194 ElementName = elementName;
197 public string ElementName { get; }
198 public override bool Matches(IStyleSelectable styleable) =>
199 string.Equals(styleable.NameAndBases[0], ElementName, StringComparison.OrdinalIgnoreCase);
202 sealed class Base : UnarySelector
204 public Base(string elementName)
206 ElementName = elementName;
209 public string ElementName { get; }
210 public override bool Matches(IStyleSelectable styleable)
212 for (var i = 0; i < styleable.NameAndBases.Length; i++)
213 if (string.Equals(styleable.NameAndBases[i], ElementName, StringComparison.OrdinalIgnoreCase))
219 sealed class Child : Operator
221 public override bool Matches(IStyleSelectable styleable) =>
222 Right.Matches(styleable) && styleable.Parent != null && Left.Matches(styleable.Parent);
225 sealed class Descendent : Operator
227 public override bool Matches(IStyleSelectable styleable)
229 if (!Right.Matches(styleable))
231 var parent = styleable.Parent;
232 while (parent != null)
234 if (Left.Matches(parent))
236 parent = parent.Parent;
242 sealed class Adjacent : Operator
244 public override bool Matches(IStyleSelectable styleable)
246 if (!Right.Matches(styleable))
248 if (styleable.Parent == null)
251 IStyleSelectable prev = null;
252 foreach (var elem in styleable.Parent.Children)
254 if (elem == styleable && prev != null)
255 return Left.Matches(prev);
259 //var index = styleable.Parent.Children.IndexOf(styleable);
262 //var adjacent = styleable.Parent.Children[index - 1];
263 //return Left.Matches(adjacent);
267 sealed class Sibling : Operator
269 public override bool Matches(IStyleSelectable styleable)
271 if (!Right.Matches(styleable))
273 if (styleable.Parent == null)
277 bool foundSelfInParent = false;
278 foreach (var elem in styleable.Parent.Children)
280 if (elem == styleable)
282 foundSelfInParent = true;
288 if (!foundSelfInParent)
292 foreach (var elem in styleable.Parent.Children)
294 if (index >= selfIndex)
296 if (Left.Matches(elem))
303 //var index = styleable.Parent.Children.IndexOf(styleable);
306 //int siblingIndex = -1;
307 //for (var i = 0; i < index; i++)
308 // if (Left.Matches(styleable.Parent.Children[i])) {
312 //return siblingIndex != -1;