/// <summary>Removes this selector from its parent documents caches.</summary> public void RemoveFromDocument(StyleRule rule, ReflowDocument document, Css.StyleSheet sheet) { // Get the cached root name: string text = LastRoot.StyleText; List <StyleRule> list = null; if (text == "*") { list = document.AnySelectors; } else { // Add the rule: document.SelectorStubs.TryGetValue(text, out list); } // Remove from the set: if (list != null) { for (int i = 0; i < list.Count; i++) { if (list[i] == rule) { list.RemoveAt(i); break; } } } // For each root, remove their locals: for (int r = 0; r < RootCount; r++) { // Get locals set: LocalMatcher[] locals = Roots[r].LocalMatchers; if (locals != null) { // For each one.. for (int i = 0; i < locals.Length; i++) { // Remove it: locals[i].RemoveFromDocument(document, sheet); } } } }
internal void BuildString(Css.StyleSheet sheet) { string result = ""; foreach (Css.Rule rule in sheet.rules) { Css.StyleRule style = rule as Css.StyleRule; if (style == null) { result += rule.GetType() + "\r\n"; } else { result += style.Selector.ToString() + "\r\n"; } } ComputedNodeData = result; }
/// <summary>Adds this selector to its parent documents caches. /// This is used by the default style sheet when the document gets cleared.</summary> public void AddToDocument(StyleRule rule, ReflowDocument document, Css.StyleSheet sheet) { // Get the cached root (always the 'last' one): string text = LastRoot.StyleText; List <StyleRule> list = null; if (text == "*") { list = document.AnySelectors; } else { // Add the rule: if (!document.SelectorStubs.TryGetValue(text, out list)) { list = new List <StyleRule>(); document.SelectorStubs[text] = list; } } // Add the rule to the set: list.Add(rule); // For each root, add their locals: for (int r = 0; r < RootCount; r++) { // Get locals set: LocalMatcher[] locals = Roots[r].LocalMatchers; if (locals != null) { // For each one.. for (int i = 0; i < locals.Length; i++) { // Add it: locals[i].AddToDocument(document, sheet); } } } }
public KeyframesRule(StyleSheet sheet, Css.Value rawValue, string name, List <Rule> frames) { Name = name; ParentSheet = sheet; RawValue = rawValue; SortedDictionary <float, KeyframesKeyframe> sortedSet = new SortedDictionary <float, KeyframesKeyframe>(); // Sort the set by % order. Exceptions for from and to. foreach (Rule rule in frames) { StyleRule styleRule = rule as StyleRule; if (styleRule == null) { continue; } // Create the frame: KeyframesKeyframe frame = new KeyframesKeyframe(styleRule.Style); if (frame.Style == null) { // Empty keyframe - ignore it. continue; } // What is its percentage position? Css.Value cssValue = styleRule.Selector.Value[0]; float percF = 0f; if (cssValue.Type == ValueType.Text) { // Get as text: string text = cssValue.Text.ToLower(); if (text == "from") { percF = 0f; } else if (text == "to") { percF = 1f; } else { continue; } } else { percF = cssValue.GetRawDecimal() / 100f; } // Apply the time: frame.Time = percF; // Add to Frames set in order of percF. sortedSet[percF] = frame; } // Create the frames set: FrameCount = sortedSet.Count; Frames = new KeyframesKeyframe[FrameCount]; int index = 0; foreach (KeyValuePair <float, KeyframesKeyframe> kvp in sortedSet) { if (index != 0) { // Get the frame before: KeyframesKeyframe before = Frames[index - 1]; // Figure out the gap between them: float delay = kvp.Value.Time - before.Time; // Update the delay that occurs after it: before.AfterDelay = delay; // And update the delay that occurs before this: kvp.Value.BeforeDelay = delay; } else { // Apply before: kvp.Value.BeforeDelay = kvp.Value.Time; } Frames[index] = kvp.Value; index++; } }
/// <summary>Converts a value to a rule. Note that it can be a set of rules (RuleSet).</summary> public static Rule ConvertToRule(Rule parentRule, Css.Value value, StyleSheet sheet, out Rule[] ruleSet) { ruleSet = null; if (value == null) { // Nothing else. return(null); } // Is it an @ rule? Note that they can actually be 'nested' inside an,array,of,selectors (happens with @media) AtRuleUnit atRule = value[0] as AtRuleUnit; if (atRule != null) { // Let the @ rule handle the value: return(atRule.AtRule.LoadRule(parentRule, sheet, value)); } // One or more selectors followed by a block unit. // Get the block: int max = value.Count - 1; SelectorBlockUnit block = value[max] as SelectorBlockUnit; if (block == null) { // Try as a set instead: ValueSet set = value[max] as ValueSet; if (set == null) { // Invalid/ unrecognised selector block. Ignore it. return(null); } // Get last one in the set: block = set[set.Count - 1] as SelectorBlockUnit; // still null? if (block == null) { // Invalid/ unrecognised selector block. Ignore it. return(null); } // Check again for an @rule: Css.Value v0 = value[0]; if (v0 != null && v0[0] is AtRuleUnit) { // Got an at rule! atRule = v0[0] as AtRuleUnit; return(atRule.AtRule.LoadRule(parentRule, sheet, value)); } // Clear last one: set[set.Count - 1] = null; } else { // Clear the block from the value: value[max] = null; } // Get the style object: Style style = block.Style; // Read the selector(s): List <Selector> into = new List <Selector>(); ReadSelectors(sheet, value, into); if (into.Count == 0) { return(null); } if (into.Count != 1) { ruleSet = new Rule[into.Count]; } // Got a specifity override? -spark-specifity:x Css.Value specifityOverride = null; int specOverride = -1; if (style.Properties.TryGetValue(Css.Properties.SparkSpecifity.GlobalProperty, out specifityOverride)) { // Yep! Pull the integer value: specOverride = specifityOverride.GetInteger(null, null); } for (int i = 0; i < into.Count; i++) { // Get it: Selector s = into[i]; // Create the rule: StyleRule rule = new StyleRule(style); rule.ParentStyleSheet = sheet; rule.Selector = s; s.Rule = rule; // Must use a copy of the style if its a secondary selector. // This is because the 'specifity' of CSS properties is defined by how specific // a selector is. So, when there's multiple selectors, we have to clone the style. Style currentStyle = i == 0?style:style.Clone(); // Apply the selectors specifity to the style: int specifity = s.Specifity; if (specOverride != -1) { specifity = specOverride; } foreach (KeyValuePair <CssProperty, Css.Value> kvp in currentStyle.Properties) { // Apply: kvp.Value.SetSpecifity(specifity); } if (ruleSet == null) { return(rule); } ruleSet[i] = rule; } return(null); }