/// <summary>Gets or sets the parsed value of this style by property name.</summary> /// <param name="property">The property to get the value for.</param> public Value this[string cssProperty] { get{ // Get the property: CssProperty property = CssProperties.Get(cssProperty); if (property == null) { return(null); } return(this[property]); } set{ // Get the CSS property: CssProperty property = CssProperties.Get(cssProperty); if (property == null) { return; } this[property] = value; } }
/// <summary> /// Adds all the type checkers to the given scanner. /// They basically automatically find CSS properties, units etc in assemblies. /// </summary> public static void AddToScanner(Modular.AssemblyScanner scanner) { // CSS functions: scanner.FindAllSubTypes(typeof(CssFunction), delegate(Type type){ // Add it: CssFunctions.Add(type); }); // CSS at rules: scanner.FindAllSubTypes(typeof(CssAtRule), delegate(Type type){ // Add it: CssAtRules.Add(type); }); // CSS units: scanner.FindAllSubTypes(typeof(CssUnit), delegate(Type type){ // Add it: CssUnits.Add(type); }); // CSS keywords: scanner.FindAllSubTypes(typeof(CssKeyword), delegate(Type type){ // Add it: CssKeywords.Add(type); }); // CSS properties (secondary pass; requires default values which can be any of the above): scanner.FindAllSubTypes(1, typeof(CssProperty), delegate(Type type){ // Add it: CssProperties.Add(type); }); }
/// <summary>Sets the named property on this style to the given value.</summary> /// <param name="cssProperty">The property to set or overwrite. e.g. "display".</param> /// <param name="value">The value to set the property to, e.g. "none".</param> public Css.Value Set(string cssProperty, string valueText) { cssProperty = cssProperty.Trim().ToLower(); // Get the property: CssProperty property = CssProperties.Get(cssProperty); if (property == null) { // Property not found: return(null); } // The underlying value: Css.Value value; if (string.IsNullOrEmpty(valueText)) { // No value - actually a clear: value = null; } else { // Create a lexer for the value: CssLexer lexer = new CssLexer(valueText, Element); // Read the underlying value: value = lexer.ReadValue(); } // Apply, taking aliases into account: this[property] = value; return(value); }
/// <summary>This is called to change a CSS property from an element. /// For example, font color=".." uses this. It sets a specifity of 0 as required by /// https://www.w3.org/TR/CSS2/cascade.html 6.4.4</summary> /// <param name="cssProperty">The css property being changed.</param> /// <param name="newValue">The new property value.</param> public void ChangeTagProperty(string cssProperty, Css.Value newValue) { // Resolve the property: CssProperty property = CssProperties.Get(cssProperty); if (property == null) { return; } // Apply now: ChangeProperty(property, newValue); }
/// <summary>This is called to change a CSS property from an element. /// For example, font color=".." uses this. It sets a specifity of 0 as required by /// https://www.w3.org/TR/CSS2/cascade.html 6.4.4</summary> /// <param name="cssProperty">The css property being changed.</param> /// <param name="newValue">The new property value.</param> public Css.Value ChangeTagProperty(string cssProperty, string newValue) { // Resolve the property: CssProperty property = CssProperties.Get(cssProperty); if (property == null) { return(null); } Css.Value val = Css.Value.Load(newValue); // Apply now: ChangeProperty(property, val); return(val); }
/// <summary>Sets a property from a composite set. Any new values that are null are set to the initial value /// and inherit the specifity from the composite value.</summary> public void SetComposite(string cssProperty, Css.Value newValue, Css.Value composite) { // Get the property: CssProperty property = CssProperties.Get(cssProperty); if (property == null) { return; } if (newValue == null && composite != null) { // Use the specifity in the comps value: newValue = new Css.Keywords.Initial(property, composite.Specifity); } // Write it now: this[property] = newValue; }
/// <summary>Causes the named property to apply its value.</summary> public void Reapply(ComputedStyle computed, string propertyName) { // Get the property: CssProperty property = CssProperties.Get(propertyName); if (property == null) { return; } // Got a value? Value value = computed[property]; if (value == null) { return; } // Apply: property.Apply(computed, value); }
/// <summary>This is called to change a CSS property from an element. /// For example, font color=".." uses this. It sets a specifity of 0 as required by /// https://www.w3.org/TR/CSS2/cascade.html 6.4.4</summary> /// <param name="cssProperty">The css property being changed.</param> /// <param name="newValue">The new property value.</param> public void ChangeTagProperty(string cssProperty, Css.Value newValue, bool requestLayout) { // Resolve the property: CssProperty property = CssProperties.Get(cssProperty); if (property == null) { return; } Renderman rm = (Element.document as Css.ReflowDocument).Renderer; bool layoutState = rm.DoLayout; // Apply now: ChangeProperty(property, newValue); // Restore layout state: if (!requestLayout) { rm.DoLayout = layoutState; } }
/// <summary>Reads the properties for this style block from the lexer. /// Essentially treats it like a set of properties only. Terminated by }, null or >.</summary> public void LoadProperties(CssLexer lexer, OnReadProperty onPropertyRead) { // Read the properties inside a selectors block. lexer.SkipJunk(); char current = lexer.Peek(); bool readPropertyName = true; bool isVariable = false; int dashCount = 0; StringBuilder propertyName = new StringBuilder(); while (current != '\0' && current != '<' && current != '}') { // Read the property name: if (readPropertyName) { // Hash, open quote or {? If so, the value does not start with a colon. CssUnitHandlers set; if (CssUnits.AllStart.TryGetValue(current, out set)) { // Match on the pretext: Value value = set.Handle(lexer, false); if (value != null) { // Read the value (using the global instance): value = value.ReadStartValue(lexer); // Call ready: value.OnValueReady(lexer); // Get the property name: string pName = propertyName.ToString().ToLower().Trim(); propertyName.Length = 0; // Trigger OPR (note that it's triggered all the time): int status = 0; if (onPropertyRead != null) { status = onPropertyRead(this, pName, value); } if (status == 0) { // Map property to a function: CssProperty property = CssProperties.Get(pName); if (property != null) { // Apply, taking aliases into account: property.OnReadValue(this, value); } } // Read off any junk: lexer.SkipJunk(); // Update current: current = lexer.Peek(); continue; } } if (current == ':') { // Done reading the property: readPropertyName = false; dashCount = 0; // Note that we don't need to skip junk as ReadValue will internally anyway. } else if (current == '-' && propertyName.Length == 0) { dashCount++; if (dashCount == 2) { isVariable = true; propertyName.Length = 0; } else { propertyName.Append(current); } } else { propertyName.Append(current); } // Read it off: lexer.Read(); // And take a look at what's next: current = lexer.Peek(); } else { // Read the value: Value value = lexer.ReadValue(); string pName = propertyName.ToString().ToLower().Trim(); propertyName.Length = 0; if (isVariable) { // CSS variable. isVariable = false; // Add to lexer set: lexer.AddVariable(pName, value); } else { // Trigger OPR (note that it's triggered all the time): int status = 0; if (onPropertyRead != null) { status = onPropertyRead(this, pName, value); } if (status == 0) { // Map property to a function: CssProperty property = CssProperties.Get(pName); if (property != null) { // Apply, taking aliases into account: property.OnReadValue(this, value); } } } // ReadValue might actually read off the } in malformed CSS. // Make sure it didn't just do that: if (lexer.Input[lexer.Position - 1] == '}') { lexer.Position--; } // Read off any junk: lexer.SkipJunk(); // Update current: current = lexer.Peek(); // Go into property reading mode: readPropertyName = true; } } }