public override void Apply(ComputedStyle style,Value value){ // Is it lit? bool lit=(value!=null && value.Boolean); if(!lit && style.Shading==null){ // Essentially ignore it anyway. return; } if(style.Shading==null){ // It's lit: style.RequireShading().Lit=true; }else{ // It's not lit: style.Shading.Lit=false; // Optimise - might no longer need the shading info: style.Shading.Optimise(); } // Request a layout now: style.RequestLayout(); }
public override void Apply(ComputedStyle style,Value value){ // Got text at all?: if(GetText(style)==null){ return; } // Apply the property: if(value==null || value.Text=="none"){ // Clear the shadow: style.TextShadow=null; }else{ // The glow properties: int blur=0; Color colour=Color.black; ShadowData data=style.TextShadow; if(data==null){ data=new ShadowData(); style.TextShadow=data; } data.HOffset=value[0].PX; data.VOffset=value[1].PX; // Grab the blur: Value innerValue=value[2]; if(innerValue.Type==ValueType.Color){ colour=innerValue.ToColor(); }else{ blur=innerValue.PX; // Grab the colour: innerValue=value[3]; if(innerValue.Type==ValueType.Color){ colour=innerValue.ToColor(); } } if(colour.a==1f){ // Default transparency: colour.a=0.8f; } data.Colour=colour; data.Blur=blur; } // Apply the changes - doesn't change anything about the actual text, so we just want a layout: style.RequestLayout(); }
/// <summary>Animates this property now.</summary> /// <param name="animation">The animation that this property is a part of.</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 void Animate(UIAnimation animation, string targetValue, float constantSpeedTime, float timeToAccelerateFor, float timeToDecelerateFor, bool updateCss) { // Get the target float value for calculating our transition speeds as an object: Css.Value targetValueObject = new Css.Value(); targetValueObject.Set(targetValue); Animate(animation, targetValueObject, constantSpeedTime, timeToAccelerateFor, timeToDecelerateFor, updateCss); }
/// <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); }
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>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>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(); } }
public override void OnLoaded(string type) { ComputedStyle computed = Element.Style.Computed; if (computed.BGImage == null) { return; } Image = computed.BGImage.Image; if (Image == null) { return; } float width = (float)Image.Width(); float height = (float)Image.Height(); // Figure out the aspect ratios: AspectRatio = width / height; InverseAspectRatio = height / width; if (Image.PixelPerfect) { width *= ScreenInfo.ResolutionScale; height *= ScreenInfo.ResolutionScale; } // Compute the tag width: TagWidth = new Css.Value((int)width + "fpx", Css.ValueType.Pixels); // Compute the tag height: TagHeight = new Css.Value((int)height + "fpx", Css.ValueType.Pixels); // Act like we're setting tag properties: // This is so that class/ID/Style can override any of them. computed.ChangeTagProperty("height", TagHeight); computed.ChangeTagProperty("width", TagWidth); computed.ChangeTagProperty("background-repeat", new Css.Value("no-repeat", Css.ValueType.Text)); computed.ChangeTagProperty("background-size", new Css.Value("100% 100%", Css.ValueType.Point)); }
public override void Apply(ComputedStyle style,Value value){ ShaderSet family=null; // Apply: if(value!=null){ // Lowercase so we can have the best chance at spotting the standard set (which is optimised for). string familyLC=value.Text.ToLower(); if(familyLC!="standardui" && familyLC!="standard" && familyLC!="" && familyLC!="none"){ // Get the family: family=ShaderSet.Get(value.Text); } } // Apply it here: if(style.Shading!=null){ // Update it: style.Shading.Shaders=family; if(family==null){ // Check if the shading data is no longer in use: style.Shading.Optimise(); } }else if(family!=null){ style.RequireShading().Shaders=family; } // Request a layout now: style.RequestLayout(); }
/// <summary>Animates this property now.</summary> /// <param name="animation">The animation that this property is a part of.</param> /// <param name="targetValue">The parsed 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 void Animate(UIAnimation animation, Css.Value targetValue, float constantSpeedTime, float timeToAccelerateFor, float timeToDecelerateFor, bool updateCss) { Animation = animation; ValueObject.Type = targetValue.Type; Stage = 0; Speed = 0f; CurrentTime = 0f; UpdateCss = updateCss; PropertyAfter = PropertyBefore = null; // Find the max speed. This is what we accelerate to. // Speed (y) / time (x) graph: // /| |-| |\ // A B C. A = accelerate, b=constant, c=decelerate. // Max speed = top y value. // Distance travelled = area of the graph. This should match target - current value. TargetValue = targetValue.ToFloat(); float unitsDelta = TargetValue - ActiveValue; MaxSpeed = (unitsDelta * UI.RedrawRate) / ((0.5f * timeToAccelerateFor) + constantSpeedTime + (0.5f * timeToDecelerateFor)); if (timeToAccelerateFor == 0f) { // Skip acceleration stage. Stage = 1; Speed = MaxSpeed; } else { Acceleration = MaxSpeed * UI.RedrawRate / timeToAccelerateFor; } if (timeToDecelerateFor != 0f) { Deceleration = MaxSpeed * UI.RedrawRate / timeToDecelerateFor; } }
//--------------------------------------
/// <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); } }
public override void OnChanged(CssProperty property,Value newValue){ // Update the computed object: Computed.ChangeProperty(property,newValue); }
public override void OnLoaded(string type){ ComputedStyle computed=Element.Style.Computed; if(computed.BGImage==null){ return; } Image=computed.BGImage.Image; if(Image==null){ return; } float width=(float)Image.Width(); float height=(float)Image.Height(); // Figure out the aspect ratios: AspectRatio=width/height; InverseAspectRatio=height/width; if(Image.PixelPerfect){ width*=ScreenInfo.ResolutionScale; height*=ScreenInfo.ResolutionScale; } // Compute the tag width: TagWidth=new Css.Value((int)width+"fpx",Css.ValueType.Pixels); // Compute the tag height: TagHeight=new Css.Value((int)height+"fpx",Css.ValueType.Pixels); // Act like we're setting tag properties: // This is so that class/ID/Style can override any of them. computed.ChangeTagProperty("height",TagHeight); computed.ChangeTagProperty("width",TagWidth); computed.ChangeTagProperty("background-repeat",new Css.Value("no-repeat",Css.ValueType.Text)); computed.ChangeTagProperty("background-size",new Css.Value("100% 100%",Css.ValueType.Point)); }
/// <summary>Inherits from the given parent value by copying them.</summary> /// <param name="parent">The value to inherit from.</param> public void InheritFrom(Value parent){ // e.g. font-size:inherit; // Simply copies the parent objects properties exactly. if(parent==null){ PX=0; Text=null; Boolean=false; InnerValues=null; Single=0f; }else{ PX=parent.PX; Text=parent.Text; Single=parent.Single; Boolean=parent.Boolean; InnerValues=parent.InnerValues; } }
/// <summary>Animates this property now.</summary> /// <param name="animation">The animation that this property is a part of.</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 void Animate(UIAnimation animation,string targetValue,float constantSpeedTime,float timeToAccelerateFor,float timeToDecelerateFor,bool updateCss){ // Get the target float value for calculating our transition speeds as an object: Css.Value targetValueObject=new Css.Value(); targetValueObject.Set(targetValue); Animate(animation,targetValueObject,constantSpeedTime,timeToAccelerateFor,timeToDecelerateFor,updateCss); }
/// <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); } } }
/// <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); } } }
/// <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>Duplicates this value.</summary> /// <returns>A duplicated copy of this value. Note that if this value has inner values, they are copied too.</returns> public Value Copy(){ Value result=new Value(); result.Type=Type; result.PX=PX; result.Text=Text; result.Single=Single; result.Boolean=Boolean; if(InnerValues!=null){ result.InnerValues=new Value[InnerValues.Length]; for(int i=0;i<InnerValues.Length;i++){ Value value=InnerValues[i]; if(value==null){ continue; } result[i]=value.Copy(); } } return result; }
/// <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>Checks if two values are equal.</summary> /// <param name="value">The value to check for equality with this. Always returns false if null.</param> /// <returns>True if this and the given value are equal; false otherwise.</returns> public bool Equals(Value value){ if(value==null || value.Type!=Type){ return false; } switch(Type){ case ValueType.Null: return true; case ValueType.Boolean: return (value.Boolean==Boolean); case ValueType.Pixels: return (value.PX==PX); case ValueType.Percentage: return (value.Single==Single); case ValueType.Em: return (value.Single==Single); case ValueType.Radians: return (value.Single==Single); case ValueType.Degrees: return (value.Single==Single); case ValueType.Single: return (value.Single==Single); case ValueType.Text: return (value.Text==Text); case ValueType.Calc: return (value.Single==Single); default: if(InnerValues==null){ return (value.InnerValues==null); }else if(value.InnerValues==null){ return (InnerValues==null); } for(int i=InnerValues.Length-1;i>=0;i--){ if(InnerValues[i]==null){ if(value.InnerValues[i]!=null){ return false; } }else if(!InnerValues[i].Equals(value.InnerValues[i])){ return false; } } return true; } }
/// <summary>Apply this CSS style to the given computed style. /// Note that you can grab the element from the computed style if you need that.</summary> /// <param name="style">The computed style to apply the property to.</param> /// <param name="value">The new value being applied.</param> public virtual void Apply(ComputedStyle style,Value value){}
/// <summary>Offsets this percentage value by a given percentage or pixel value.</summary> public void Offset(Value by){ if(Single==1f){ // Take from it. if(by.PX!=0){ // Set: PX=-by.PX; }else{ // Decrease: Single-=by.Single; } }else{ // Add to it. if(by.PX!=0){ // Set: PX=by.PX; }else{ // Increase: Single+=by.Single; } } // It's a mixed unit type: Type=ValueType.Mixed; }
public override void Apply(ComputedStyle style,Value value){ // Got any text at all?: if(GetText(style)==null){ return; } // Apply the property: if(value==null || value.Text=="none"){ // Clear the stroke: style.TextStroke=null; }else{ // The stroke properties: int blur=0; Color colour=Color.black; int thickness=value[0].PX; if(thickness==0){ style.TextStroke=null; }else{ StrokeData data=style.TextStroke; if(data==null){ data=new StrokeData(); style.TextStroke=data; } data.Thickness=thickness; // Grab the blur: Value innerValue=value[1]; if(innerValue.Type==ValueType.Color){ colour=innerValue.ToColor(); }else{ blur=innerValue.PX; // Grab the colour: innerValue=value[2]; if(innerValue.Type==ValueType.Color){ colour=innerValue.ToColor(); } } data.Colour=colour; data.Blur=blur; } } // Apply the changes - doesn't change anything about the actual text, so we just want a layout: style.RequestLayout(); }
/// <summary>Sets defaults for the given number of inner values.</summary> /// <param name="count">The number of inner values to setup.</param> public void SetInnerValues(int count){ if(InnerValues==null||InnerValues.Length!=count){ InnerValues=new Value[count]; for(int i=0;i<count;i++){ InnerValues[i]=new Value(); } } }