public void BakeToModifiers() { // Does it have any modified selectors? If so, add these properties in there too // (as the modified form 'derives' from this) but weakly - don't override them. // This occurs if :aModified is defined before the unmodified selector. List <Css.SelectorStyle> modifiedForms = Sheet.GetModifiers(Selector); if (modifiedForms != null) { // Great, it's got some! Copy this style over now: for (int i = modifiedForms.Count - 1; i >= 0; i--) { SelectorStyle modifiedForm = modifiedForms[i]; CopyTo(modifiedForm, false); } } if (Document != null && Document.html != null && Unmodified) { // Is this selector already in use? Css.SelectorType type = SelectorType; // Next, recurse through the DOM looking for it: Document.html.RefreshSelector(type, BaseSelector); } }
public Selector(StyleSheet sheet,string selectorText,string modifier){ SelectorText=selectorText; Modifier=modifier; // Start it off immediately: Style=sheet.StartSelector(selectorText,modifier); }
public Selector(StyleSheet sheet, string selectorText, string modifier) { SelectorText = selectorText; Modifier = modifier; // Start it off immediately: Style = sheet.StartSelector(selectorText, modifier); }
/// <summary>Gets the CSS property value defined by the ID selector for the given property.</summary> /// <param name="property">The CSS property to get the value for.</param> public Css.Value GetIDStyle(string property) { if (!string.IsNullOrEmpty(IDSelector)) { SelectorStyle idStyle = Element.Document.getStyleBySelector(IDSelector); if (idStyle != null) { return(idStyle[property]); } } return(null); }
/// <summary>Gets a style definition by css selector from the StyleSheet. /// If it's not found in the style sheet, the default stylesheet is checked.</summary> /// <param name="selector">The css selector to search for.</param> /// <returns>If found, a selector style definition; null otherwise.</returns> public Css.SelectorStyle getStyleBySelector(string selector) { if (Style == null || AotDocument) { return(null); } Css.SelectorStyle result = Style.GetStyleBySelector(selector); if (result == null) { result = DefaultStyleSheet.GetStyleBySelector(selector); } return(result); }
/// <summary>Copies this objects properties to the other given style, overwriting existing properties if told to do so.</summary> /// <param name="otherStyle">The style to copy this objects properties into.</param> /// <param name="overwrite">True if existing properties should be overwriten.</param> public void CopyTo(SelectorStyle otherStyle, bool overwrite) { if (otherStyle == null) { return; } foreach (KeyValuePair <CssProperty, Value> kvp in Properties) { if (!overwrite && otherStyle.Properties.ContainsKey(kvp.Key)) { continue; } otherStyle[kvp.Key] = kvp.Value.Copy(); } }
/// <summary>Gets the CSS property value defined by the class selector for the given property.</summary> /// <param name="property">The CSS property to get the value for.</param> public Css.Value GetClassStyle(CssProperty property) { if (!string.IsNullOrEmpty(ClassSelector)) { // Grab the main class style: SelectorStyle classStyle = Element.Document.getStyleBySelector(ClassSelector); Css.Value result; if (classStyle != null) { result = classStyle[property]; if (result != null) { return(result); } } if (ExtraClassSelectors != null) { for (int i = ExtraClassSelectors.Length - 1; i >= 0; i--) { // Grab the style: classStyle = Element.Document.getStyleBySelector(ExtraClassSelectors[i]); if (classStyle == null) { continue; } // Get the property: result = classStyle[property]; if (result != null) { // Got it! return(result); } } } } return(null); }
/// <summary>Keeps reading selectors and their properties until a > or the end of the css is reached.</summary> /// <param name="css">The css text to parse.</param> public void ParseCss(string css) { MLLexer lexer = new MLLexer(css); char currentCharacter = lexer.Peek(); while (currentCharacter != '<' && currentCharacter != StringReader.NULL) { if (TryReadBlockComment(lexer, currentCharacter)) { currentCharacter = lexer.Peek(); continue; } // Read a selector: string selector = ""; string modifier = ""; bool inModifier = false; List <Selector> additionalSelectors = null; while (currentCharacter != '{' && currentCharacter != '<' && currentCharacter != StringReader.NULL) { // Read it off: lexer.Read(); if (currentCharacter == ' ') { // Skip spaces here. } else if (currentCharacter == ',') { // We have a series of selectors. if (selector != "") { // Store the current one in the additional list: if (additionalSelectors == null) { additionalSelectors = new List <Selector>(1); } additionalSelectors.Add(new Selector(this, selector, modifier)); // Clear the current one: selector = ""; modifier = ""; inModifier = false; } } else if (currentCharacter == ':') { if (inModifier) { // Already in the modifier - they've been daisy chained. // So, the modifier we've read so far is actually part of the selector: selector += ":" + modifier.ToLower(); modifier = ""; } inModifier = true; } else if (inModifier) { // Add it to the modifier: modifier += currentCharacter; } else { // Add it to the selector: selector += currentCharacter; } // Peek the next one: currentCharacter = lexer.Peek(); } if (currentCharacter == '{') { // Read it off: lexer.Read(); } else { // It must have been a < or null. Halt. break; } // Start the style block: SelectorStyle style = StartSelector(selector, modifier); // Read the properties inside a selectors block. Literal reading after : until ; bool readPropertyName = true; string propertyName = ""; string propertyValue = ""; currentCharacter = lexer.Peek(); while (currentCharacter != '}' && currentCharacter != '<' && currentCharacter != StringReader.NULL) { if (readPropertyName) { if (TryReadBlockComment(lexer, currentCharacter)) { currentCharacter = lexer.Peek(); continue; } if (currentCharacter == ':') { // Bump into literal mode. lexer.Literal = true; readPropertyName = false; } else { propertyName += currentCharacter; } } else { if (currentCharacter == ';') { // Pop out of literal mode, and go back to property names. readPropertyName = true; lexer.Literal = false; // And push our new propertyName/propertyValue set: style.SetDirect(propertyName, propertyValue); if (additionalSelectors != null) { // We have more,than,one selector. // Set to them too: for (int i = additionalSelectors.Count - 1; i >= 0; i--) { additionalSelectors[i].Style.SetDirect(propertyName, propertyValue); } } propertyName = ""; propertyValue = ""; } else { propertyValue += currentCharacter; } } // Read it off: lexer.Read(); // And take a look at what's next: currentCharacter = lexer.Peek(); } // Let the style know it's done loading: style.OnLoaded(); // 'Bake' the new styles into their modified forms, if any have been loaded yet. style.BakeToModifiers(); if (additionalSelectors != null) { // We have more,than,one selector. // Start their blocks too: for (int i = additionalSelectors.Count - 1; i >= 0; i--) { additionalSelectors[i].Style.BakeToModifiers(); } } if (currentCharacter == '}') { // Read it off: lexer.Read(); // And setup the next character: currentCharacter = lexer.Peek(); } else { // Halt - it was a null or <. break; } // Ensure we're out of literal mode: lexer.Literal = false; } }
/// <summary>Creates a new selector block for the given selector/modifier combo.</summary> public SelectorStyle StartSelector(string selector, string modifier) { string fullSelector = selector; bool modified = false; if (!string.IsNullOrEmpty(modifier)) { // Make it lowercase: modifier = modifier.ToLower(); // Append it to the selector: fullSelector += ":" + modifier; modified = true; } // Generate a style object for this selector if it doesn't already have one: SelectorStyle style = null; if (fullSelector == "@font-face") { // Special case for the font-face selector style. // - Load the font and add it to the document's renderer, style = new SelectorStyle(this, selector, modifier); return(style); } if (!Selectors.TryGetValue(fullSelector, out style)) { Selectors[fullSelector] = style = new SelectorStyle(this, selector, modifier); if (modified) { // Add it as a modified form: AddModified(selector, style); } // Does a default selector exist? if (Document.DefaultStyleSheet != null && Document.DefaultStyleSheet != this) { SelectorStyle defaultStyle = Document.DefaultStyleSheet.GetStyleBySelector(fullSelector); if (defaultStyle != null) { // This tag has a default style - we must copy the content from it into the new overriding tag. defaultStyle.CopyTo(style, false); } } // Does a * selector exist? Only apply if selector is not html and a tag. Note that this must be applied last. // Also note that it's not applied to modified styles as they are applied additively. if (!modified && Document.DefaultStyleSheet != null && selector != "html" && selector != "*" && style.SelectorType == Css.SelectorType.Tag) { SelectorStyle defaultStyle = Document.DefaultStyleSheet.GetStyleBySelector("*"); if (defaultStyle != null) { // Got a * style - Copy the content from it into the new overriding tag. defaultStyle.CopyTo(style, false); } } } return(style); }
//--------------------------------------
/// <summary>Creates a new UIAnimation for animating CSS and immediately animates it. /// See <see cref="PowerUI.Element.animate"/>.</summary> /// <param name="animating">The element being animated.</param> /// <param name="properties">The CSS property string. Each property should define the value it will be when the animation is done.</param> /// <param name="constantSpeedTime">How long this animation lasts for at a constant speed.</param> /// <param name="timeToAccelerateFor">How long this animation accelerates for. Creates smooth animations when used.</param> /// <param name="timeToDecelerateFor">How long this animation decelerates for. Creates smooth animations when used.</param> public UIAnimation(Element animating, string properties, float constantSpeedTime, float timeToAccelerateFor, float timeToDecelerateFor) { Animating = animating; ElementStyle = Animating.Style; if (string.IsNullOrEmpty(properties)) { Wrench.Log.Add("No properties given to animate!"); return; } if (constantSpeedTime < 0f) { constantSpeedTime = 0f; } if (timeToAccelerateFor < 0f) { timeToAccelerateFor = 0f; } if (timeToDecelerateFor < 0f) { timeToDecelerateFor = 0f; } TotalTime = (timeToDecelerateFor + timeToAccelerateFor + constantSpeedTime); ConstantSpeedTime = constantSpeedTime; TimeToAccelerateFor = timeToAccelerateFor; TimeToDecelerateFor = timeToDecelerateFor; if (TotalTime == 0f) { // Instant - probably a fault somewhere in the users request, so we won't do anything. Wrench.Log.Add("Instant css animation request ignored. Told to take no time to transition."); return; } if (timeToDecelerateFor == 0f) { Decelerate = false; } else { Decelerate = true; DecelerateAt = timeToAccelerateFor + constantSpeedTime; } if (properties.StartsWith(".") || properties.StartsWith("#")) { // Targeting a selector, e.g. #fadedBox // First, get the selector style: Css.SelectorStyle selector = animating.Document.getStyleBySelector(properties); if (selector == null) { return; } // Animate each property: foreach (KeyValuePair <CssProperty, Css.Value> kvp in selector.Properties) { // Is it a composite property? Css.Value value = kvp.Value; // Grab the type: Css.ValueType type = value.Type; if (type == Css.ValueType.Null || type == Css.ValueType.Text) { // Can't deal with either of these. continue; } if (type == Css.ValueType.Rectangle || type == Css.ValueType.Point || type == Css.ValueType.Color) { // Animate it (note that we don't need to copy it): AnimateComposite(kvp.Key, value); } else { // Animate it (note that we don't need to copy it): Animate(kvp.Key, -1, value, true); } } return; } string[] propertySet = properties.Split(';'); foreach (string currentProperty in propertySet) { if (currentProperty == "") { continue; } string[] keyValue = currentProperty.Split(Css.Style.Delimiter, 2); if (keyValue.Length != 2) { continue; } string key = keyValue[0].Trim(); if (key == "opacity") { key = "color-overlay-a"; } // Grab the inner index: int innerIndex = Css.Value.GetInnerIndex(ref key); // Get the property: CssProperty property = CssProperties.Get(key); if (property == null) { Wrench.Log.Add("Warning: CSS property '" + keyValue[0] + "' not found during animate."); continue; } // Trim shouldn't be applied to inner-text's value, but we can't animate that anyway! This is all we need to do: string value = keyValue[1].Trim(); // Key could be a composite property - for example padding, which needs to be broken down into it's individual inner elements (e.g. padding-left) Css.ValueType type; if (innerIndex == -1) { type = Css.Value.TypeOf(property, ref value); } else { type = Css.Value.TypeOf(value); } if (type == Css.ValueType.Null || type == Css.ValueType.Text) { // Can't deal with either of these. continue; } else if (type == Css.ValueType.Rectangle || type == Css.ValueType.Point || type == Css.ValueType.Color) { // We have a composite property (and we're animating the whole thing). Css.Value tempValue = new Css.Value(); tempValue.Set(value, type); // Animate it: AnimateComposite(property, tempValue); } else { Animate(property, innerIndex, new Css.Value(value, type), true); } } }