/// <summary>Adds a CSS property to the global set. /// This is generally done automatically, but you can also add one manually if you wish.</summary> /// <param name="property">The property to add.</param> /// <returns>True if adding it was successful.</returns> public static bool Add(CssProperty property) { string[] tags = property.GetProperties(); if (tags == null || tags.Length == 0) { return(false); } for (int i = 0; i < tags.Length; i++) { // Grab the property: string propertyName = tags[i].ToLower(); // Is it the first? If so, set the name: if (i == 0) { property.Name = propertyName; } // Add it to properties: Properties[propertyName] = property; if (property.IsTextual) { // Add it to text properties too: TextProperties[propertyName] = property; } } return(true); }
/// <summary>Attempts to find the named property, returning the global property if it's found.</summary> /// <param name="property">The property to look for.</param> /// <returns>The global CssProperty if the property was found; Null otherwise.</returns> public static CssProperty Get(string property) { CssProperty globalProperty = null; Properties.TryGetValue(property, out globalProperty); return(globalProperty); }
/// <summary>Gets the given property as a css string. May optionally read the given inner index of it as a css string.</summary> /// <param name="property">The property to get as a string.</param> /// <param name="innerIndex">The inner value to get from the property. -1 for the whole property.</param> /// <returns>The property as a css string, e.g. color-overlay may return "#ffffff".</returns> public virtual string GetString(string cssProperty, int innerIndex) { // Get the property: CssProperty property = CssProperties.Get(cssProperty); if (property == null) { // Doesn't exist - can't have been set. return(""); } // Get the value: Value propertyValue = this[property]; if (propertyValue == null) { return(""); } if (innerIndex != -1) { propertyValue = propertyValue[innerIndex]; if (propertyValue == null) { return(""); } } return(propertyValue.ToString()); }
/// <summary>Gets the value of the given property, if any.</summary> /// <param name="cssProperty">The property to get the value of, e.g. "display".</param> /// <returns>The value of the property if found. Null otherwise.</returns> public Value Get(string cssProperty) { // Get the inner index: int innerIndex = Css.Value.GetInnerIndex(ref cssProperty); // Get the property: CssProperty property = CssProperties.Get(cssProperty); if (property == null) { // Property not found. Stop there. return(null); } Value result = this[property]; if (result == null) { return(null); } if (innerIndex != -1) { return(result[innerIndex]); } return(result); }
/// <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[CssProperty property] { get{ Value result; Properties.TryGetValue(property, out result); return(result); } set{ Properties[property] = value; } }
/// <summary>Attempts to find the property with the given name. /// If it's not found, a default property which is known to exist can be returned instead. /// For example, property "color".</summary> /// <param name="property">The property to look for.</param> /// <param name="defaultProperty">If the given property is not found, this is used instead.</param> /// <returns>The global property object.</returns> public static CssProperty Get(string property, string defaultProperty) { CssProperty globalProperty = Get(property); if (globalProperty == null) { globalProperty = Get(defaultProperty); } return(globalProperty); }
/// <summary>Attempts to find the named property, returning the global property if it's found. This works with all properties as it resolve the index too.</summary> /// <param name="property">The property to look for.</param> /// <param name="innerIndex">Some properties are sets of properties, such as color and color-r. color-r is an "inner" property of color.</param> /// <returns>The global CssProperty if the property was found; Null otherwise.</returns> public static CssProperty Get(string property, out int innerIndex) { // Resolve the inner index: innerIndex = Css.Value.GetInnerIndex(ref property); // Resolve the property: CssProperty globalProperty = null; Properties.TryGetValue(property, out globalProperty); return(globalProperty); }
/// <summary>This is called to change a property defined by a css selector that matches the ID of this element. /// This change may be rejected if a style attribute on the element overrides this change.</summary> /// <param name="cssProperty">The css property being changed.</param> /// <param name="newValue">The new property value.</param> public void ChangeIDProperty(string cssProperty, Css.Value newValue) { // Resolve the property: CssProperty property = CssProperties.Get(cssProperty); if (property == null) { return; } // Apply now: ChangeIDProperty(property, newValue); }
/// <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(CssProperty property) { if (!string.IsNullOrEmpty(IDSelector)) { SelectorStyle idStyle = Element.Document.getStyleBySelector(IDSelector); if (idStyle != null) { return(idStyle[property]); } } return(null); }
/// <summary>Creates a new animated property.</summary> /// <param name="animation">The animation that this property is a part of.</param> /// <param name="property">The property being animated.</param> /// <param name="targetValue">The value that this property will be when the animation is over.</param> /// <param name="constantSpeedTime">How long the animation will change the value at a constant speed for.</param> /// <param name="timeToAccelerateFor">How long the animation will accelerate for. This produces a smoother animation.</param> /// <param name="timeToDecelerateFor">How long the animation will decelerate for. This produces a smoother animation.</param> /// <param name="updateCss">True if this particular property should flush its changes to css/the screen.</param> public AnimatedProperty(UIAnimation animation,CssProperty property,int innerIndex,Css.Value targetValue,float constantSpeedTime,float timeToAccelerateFor,float timeToDecelerateFor,bool updateCss){ Animation=animation; PropertyInfo=property; InnerIndex=innerIndex; Css.ValueType type=targetValue.Type; if(!Animation.ElementStyle.Properties.TryGetValue(property,out ValueObject)){ ComputedStyle computed=Animation.ElementStyle.Computed; if(computed!=null && computed.Properties.TryGetValue(property,out ValueObject)){ // Let's derive from the computed form. ValueObject=ValueObject.Copy(); }else{ ValueObject=new Css.Value(); if(innerIndex!=-1 || type==Css.ValueType.Null){ type=Css.ValueType.Rectangle; } property.SetDefault(ValueObject,type); } Animation.ElementStyle.Properties[property]=ValueObject; } if(ValueObject.Type==Css.ValueType.Inherit){ // Special case - we need to duplicate it. Animation.ElementStyle.Properties[property]=ValueObject=ValueObject.Copy(); ValueObject.Type=type; } PropertyValueObject=ValueObject; if(innerIndex!=-1){ Css.Value innerValue=ValueObject[innerIndex]; if(innerValue==null){ ValueObject[innerIndex]=innerValue=new Css.Value(); } ValueObject=innerValue; } // Set our starting value: ActiveValue=ValueObject.ToFloat(); Animate(Animation,targetValue,constantSpeedTime,timeToAccelerateFor,timeToDecelerateFor,updateCss); }
/// <summary>Gets or creates the base value for the given property. /// The base value is essentially the value held directly in this style sheet. /// E.g. if the value you're setting is the R channel of color-overlay, this sets up the color-overlay value for you.</summary> /// <returns>The raw value (which may have just been created).</returns> public Css.Value GetRawValue(CssProperty property, ValueType type) { Css.Value propertyValue; // Does it exist already? if (!Properties.TryGetValue(property, out propertyValue)) { // Nope! Create it now. Does the computed style hold a value instead? ComputedStyle computed = GetComputed(); if (computed != null && computed.Properties.TryGetValue(property, out propertyValue) && propertyValue != null) { // Let's derive from the computed form. propertyValue = propertyValue.Copy(); Properties[property] = propertyValue; } else { // Needs to be created. Properties[property] = propertyValue = new Value(); if (type == ValueType.Null) { type = ValueType.Rectangle; } // Set the default value: property.SetDefault(propertyValue, type); if (type == ValueType.Inherit) { // Set inherit: propertyValue.Type = ValueType.Inherit; } } } if (propertyValue.Type == ValueType.Inherit && type != ValueType.Inherit) { // Special case - we need to duplicate it. Properties[property] = propertyValue = propertyValue.Copy(); propertyValue.Type = type; } return(propertyValue); }
/// <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>Searches the current animated properties for the named property on the given element.</summary> /// <param name="animating">The element being animated.</param> /// <param name="property">The CSS property to look for. Note: Must not be a composite property such as color-overlay. /// Must be a full property such as color-overlay-r.</param> /// <returns>An AnimatedProperty if it was found; Null otherwise.</returns> public static AnimatedProperty GetAnimatedProperty(Element animating,CssProperty property,int innerIndex){ if(FirstProperty==null){ return null; } AnimatedProperty current=FirstProperty; while(current!=null){ if(current.Animating==animating && current.PropertyInfo==property && current.InnerIndex==innerIndex){ return current; } current=current.PropertyAfter; } return null; }
/// <summary>This is called to change a property defined by a css selector that matches the class of this element. /// The request may be rejected if an ID selector or a style attribute on the element overrides this change.</summary> /// <param name="property">The css property being changed.</param> /// <param name="newValue">The new property value.</param> public void ChangeClassProperty(CssProperty property, Css.Value newValue) { // Is it overriden by any ID properties? // If so, stop. // Grab the ID style: Css.Value idStyle = GetIDStyle(property); if (idStyle != null) { if (newValue == null || !newValue.Important || idStyle.Important) { return; } } // Not overriden by the ID; act like we changed a property of the ID. ChangeIDProperty(property, newValue); }
/// <summary>This is called to change a property defined by a css selector that matches the tag of this element. /// The request may be rejected if a class selector, ID selector or a style attribute /// on the element overrides this change.</summary> /// <param name="property">The css property being changed.</param> /// <param name="newValue">The new property value.</param> public void ChangeTagProperty(CssProperty property, Css.Value newValue) { // Is it overriden by any class properties? // If so, stop. // Grab the class style: Css.Value classStyle = GetClassStyle(property); if (classStyle != null) { if (newValue == null || !newValue.Important || classStyle.Important) { return; } } // Not overriden by the class; Act like we changed a class property. ChangeClassProperty(property, newValue); }
public static ValueType TypeOf(CssProperty property, ref string value) { if (value == "inherit") { return(ValueType.Inherit); } if (property.Name == "background-image") { value = value.Replace("url(", "").Replace(")", "").Replace("'", "").Replace("\"", ""); } if (property.Type != ValueType.Null) { return(property.Type); } return(TypeOf(value)); }
/// <summary>This is called to change a property defined by a css selector that matches the ID of this element. /// This change may be rejected if a style attribute on the element overrides this change.</summary> /// <param name="property">The css property being changed.</param> /// <param name="newValue">The new property value.</param> public void ChangeIDProperty(CssProperty property, Css.Value newValue) { // Is it overriden by any local style properties? // If so, stop. // Grab the local style: Css.Value localStyle = Element.style[property]; if (localStyle != null) { if (newValue == null || !newValue.Important || localStyle.Important) { return; } } // Not overriden by the style="" attribute. Act like we set it directly. ChangeProperty(property, newValue); }
/// <summary>Converts this relative value (such as a percentage or em) into a fixed one.</summary> /// <param name="property">The property that this value represents and is being made absolute.</param> /// <param name="element">The element holding all the values that represent 100%.</param> public void MakeAbsolute(CssProperty property,Element element){ if(element.ParentNode==null){ PX=0; return; } ComputedStyle parentStyle=element.ParentNode.Style.Computed; switch(Type){ case ValueType.Em: BakePX(ParentFontSize(parentStyle)); break; case ValueType.Percentage: ComputedStyle computed=element.Style.Computed; // Is this along x? if(property.IsXProperty){ // Yep! BakePX(parentStyle.InnerWidth-computed.PaddingLeft-computed.PaddingRight); }else{ // Nope! BakePX(parentStyle.InnerHeight-computed.PaddingTop-computed.PaddingBottom); } break; case ValueType.Inherit: InheritFrom(parentStyle[property]); break; case ValueType.Calc: computed=element.Style.Computed; int size=0; // Is this along x? if(property.IsXProperty){ // Yep! size=parentStyle.InnerWidth-computed.PaddingLeft-computed.PaddingRight; }else{ // Nope! size=parentStyle.InnerHeight-computed.PaddingTop-computed.PaddingBottom; } PX=Calculation.Run(size); break; default: computed=element.Style.Computed; // It's a box or point - compute all values [y,x,y,x] // Both will have the first two values: bool useWidth=(Type==ValueType.Point); //x is first for a point. // Don't include padding in the value. int paddingWidth=computed.PaddingLeft+computed.PaddingRight; int paddingHeight=computed.PaddingTop+computed.PaddingBottom; // The cached fontsize if any of these use EM; Chances are more than one will. int parentFontSize=-1; for(int i=0;i<InnerValues.Length;i++){ Value innerValue=InnerValues[i]; if(innerValue.Type==ValueType.Em){ if(parentFontSize==-1){ parentFontSize=ParentFontSize(parentStyle); } innerValue.BakePX(parentFontSize); }else{ // Whats the block size? if(useWidth){ innerValue.BakePX(parentStyle.InnerWidth-paddingWidth); }else{ innerValue.BakePX(parentStyle.InnerHeight-paddingHeight); } } // And flip useWidth: useWidth=!useWidth; } break; } }
/// <summary>Adds a CSS property to the global set. /// This is generally done automatically, but you can also add one manually if you wish.</summary> /// <param name="property">The property to add.</param> /// <returns>True if adding it was successful.</returns> public static bool Add(CssProperty property){ string[] tags=property.GetProperties(); if(tags==null||tags.Length==0){ return false; } for(int i=0;i<tags.Length;i++){ // Grab the property: string propertyName=tags[i].ToLower(); // Is it the first? If so, set the name: if(i==0){ property.Name=propertyName; } // Add it to properties: Properties[propertyName]=property; if(property.IsTextual){ // Add it to text properties too: TextProperties[propertyName]=property; } } return true; }
/// <summary>Converts this relative value (such as a percentage or em) into a fixed one.</summary> /// <param name="property">The property that this value represents and is being made absolute.</param> /// <param name="element">The element holding all the values that represent 100%.</param> public void MakeAbsolute(CssProperty property, Element element) { if (element.ParentNode == null) { PX = 0; return; } ComputedStyle parentStyle = element.ParentNode.Style.Computed; switch (Type) { case ValueType.Em: BakePX(ParentFontSize(parentStyle)); break; case ValueType.Percentage: ComputedStyle computed = element.Style.Computed; // Is this along x? if (property.IsXProperty) { // Yep! BakePX(parentStyle.InnerWidth - computed.PaddingLeft - computed.PaddingRight); } else { // Nope! BakePX(parentStyle.InnerHeight - computed.PaddingTop - computed.PaddingBottom); } break; case ValueType.Inherit: InheritFrom(parentStyle[property]); break; case ValueType.Calc: computed = element.Style.Computed; int size = 0; // Is this along x? if (property.IsXProperty) { // Yep! size = parentStyle.InnerWidth - computed.PaddingLeft - computed.PaddingRight; } else { // Nope! size = parentStyle.InnerHeight - computed.PaddingTop - computed.PaddingBottom; } PX = Calculation.Run(size); break; default: computed = element.Style.Computed; // It's a box or point - compute all values [y,x,y,x] // Both will have the first two values: bool useWidth = (Type == ValueType.Point); //x is first for a point. // Don't include padding in the value. int paddingWidth = computed.PaddingLeft + computed.PaddingRight; int paddingHeight = computed.PaddingTop + computed.PaddingBottom; // The cached fontsize if any of these use EM; Chances are more than one will. int parentFontSize = -1; for (int i = 0; i < InnerValues.Length; i++) { Value innerValue = InnerValues[i]; if (innerValue.Type == ValueType.Em) { if (parentFontSize == -1) { parentFontSize = ParentFontSize(parentStyle); } innerValue.BakePX(parentFontSize); } else { // Whats the block size? if (useWidth) { innerValue.BakePX(parentStyle.InnerWidth - paddingWidth); } else { innerValue.BakePX(parentStyle.InnerHeight - paddingHeight); } } // And flip useWidth: useWidth = !useWidth; } break; } }
/// <summary>Starts animating the named property and target value. Must not be composite properties. /// (e.g. color-overlay-r instead of color-overlay)</summary> /// <param name="property">The property to update.</param> /// <param name="innerIndex">The inner index of the property to update.</param> /// <param name="value">The target value of the property.</param> /// <param name="updateCss">True if this property should update CSS/ the screen when it's progressed.</param> private void Animate(CssProperty property,int innerIndex,Css.Value value,bool updateCss){ // Check if this property is already animated - if so, interrupt it and override with our new values. // There won't be many actively animated properties, so looping through the update queue is fast anyway. AnimatedProperty animProperty=GetAnimatedProperty(Animating,property,innerIndex); if(animProperty!=null){ animProperty.Animate(this,value,ConstantSpeedTime,TimeToAccelerateFor,TimeToDecelerateFor,updateCss); }else{ // Otherwise we want to create a new AnimatedProperty and stick it into the queue: animProperty=new AnimatedProperty(this,property,innerIndex,value,ConstantSpeedTime,TimeToAccelerateFor,TimeToDecelerateFor,updateCss); animProperty.AddToQueue(); } }
/// <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[CssProperty property]{ get{ Value result; Properties.TryGetValue(property,out result); return result; } set{ Properties[property]=value; } }
/// <summary>Gets or creates the base value for the given property. /// The base value is essentially the value held directly in this style sheet. /// E.g. if the value you're setting is the R channel of color-overlay, this sets up the color-overlay value for you.</summary> /// <returns>The raw value (which may have just been created).</returns> public Css.Value GetRawValue(CssProperty property,ValueType type){ Css.Value propertyValue; // Does it exist already? if(!Properties.TryGetValue(property,out propertyValue)){ // Nope! Create it now. Does the computed style hold a value instead? ComputedStyle computed=GetComputed(); if(computed!=null && computed.Properties.TryGetValue(property,out propertyValue) && propertyValue!=null){ // Let's derive from the computed form. propertyValue=propertyValue.Copy(); Properties[property]=propertyValue; }else{ // Needs to be created. Properties[property]=propertyValue=new Value(); if(type==ValueType.Null){ type=ValueType.Rectangle; } // Set the default value: property.SetDefault(propertyValue,type); if(type==ValueType.Inherit){ // Set inherit: propertyValue.Type=ValueType.Inherit; } } } if(propertyValue.Type==ValueType.Inherit && type!=ValueType.Inherit){ // Special case - we need to duplicate it. Properties[property]=propertyValue=propertyValue.Copy(); propertyValue.Type=type; } return propertyValue; }
public override void OnChanged(CssProperty property, Value newValue) { // Update the computed object: Computed.ChangeProperty(property, newValue); }
public static ValueType TypeOf(CssProperty property,ref string value){ if(value=="inherit"){ return ValueType.Inherit; } if(property.Name=="background-image"){ value=value.Replace("url(","").Replace(")","").Replace("'","").Replace("\"",""); } if(property.Type!=ValueType.Null){ return property.Type; } return TypeOf(value); }
//--------------------------------------
/// <summary>Called when somebody dynamically updates a stylesheet. Currently does nothing.</summary> public override void OnChanged(CssProperty property, Value newValue) { // Would need to find all elements that this css selector affects and call RecomputeRequired on them. }
/// <summary>Sets the named property on this style to the given value. An inner value may be set; For example, /// setting the red component of color-overlay (color-overlay-r) becomes color-overlay and an innerIndex of 0.</summary> /// <param name="property">The property to set or overwrite. e.g. "display".</param> /// <param name="value">The value to set the property to, e.g. "none".</param> /// <param name="innerIndex">The index of the inner value to set, if any. -1 to set the whole property.</param> private void Set(string cssProperty, string value, int innerIndex, bool important) { if (Element != null && Element.Document.AotDocument) { return; } // Get the property: CssProperty property = CssProperties.Get(cssProperty); if (property == null) { // It doesn't exist! return; } if (value == "") { value = null; } if (value == null) { Properties.Remove(property); // Was in there (and not blank) - change it. OnChanged(property, null); return; } // Get the type of the property: ValueType type = Css.Value.TypeOf(property, ref value); // Read or create the raw property value: Value propertyValue = GetRawValue(property, type); if (innerIndex != -1) { // Writing to an inner value, e.g. border-left. Grab it: Value innerValue = propertyValue[innerIndex]; if (innerValue == null) { innerValue = propertyValue[innerIndex] = new Value(); } innerValue.Set(value); // Apply its importance: innerValue.Important = important; } else { if (type == ValueType.Null) { propertyValue.Set(value); } else { propertyValue.Set(value, type); } // Apply its importance: propertyValue.Important = important; } // Let the sheet know the value changed: if (type == ValueType.Null) { OnChanged(property, null); } else { OnChanged(property, propertyValue); } }
/// <summary>called when the named property changes.</summary> /// <param name="property">The property that changed.</param> /// <param name="newValue">It's new fully parsed value. May be null.</param> public virtual void OnChanged(CssProperty property,Value newValue){ }
public override void OnChanged(CssProperty property,Value newValue){ // Update the computed object: Computed.ChangeProperty(property,newValue); }
private void AnimateComposite(CssProperty property,Css.Value value){ bool isPoint=(value.Type==Css.ValueType.Point); Animate(property,0,value[0],false); Animate(property,1,value[1],isPoint); if(!isPoint){ Animate(property,2,value[2],false); Animate(property,3,value[3],true); } }
/// <summary>called when the named property changes.</summary> /// <param name="property">The property that changed.</param> /// <param name="newValue">It's new fully parsed value. May be null.</param> public virtual void OnChanged(CssProperty property, Value newValue) { }
/// <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{ Value result; // Get the property: int innerIndex; CssProperty property = CssProperties.Get(cssProperty, out innerIndex); if (property == null) { return(null); } if (Properties.TryGetValue(property, out result)) { if (innerIndex != -1) { // Grab the inner index: result = result[innerIndex]; } } return(result); } set{ // Get the CSS property: int innerIndex; CssProperty property = CssProperties.Get(cssProperty, out innerIndex); if (property == null) { return; } if (innerIndex != -1) { // Apply to inner value. // First, get the value we're applying the inner property to: Css.Value mainValue = GetRawValue(property, value.Type); // And apply it now: mainValue[innerIndex] = value; // Update value to the property which actually changed: value = mainValue; return; } else { // Applying it to a main property: if (value == null) { // Remove it: Properties.Remove(property); } else { // Add it now: Properties[property] = value; } } // Let the sheet know the value changed: if (value == null || value.Type == ValueType.Null) { OnChanged(property, null); } else { OnChanged(property, value); } } }