public override bool OnReadValue(Style styleBlock, Css.Value value, int start, out int size) { if (value != null) { // Get a quick ref to the actual value to check: value = value[start]; #if NETFX_CORE if ( (RawType != null && RawType.GetTypeInfo().IsAssignableFrom(value.GetType().GetTypeInfo())) || value.Type == Type ) { size = 1; return(true); } #else if ( (RawType != null && RawType.IsAssignableFrom(value.GetType())) || value.Type == Type ) { size = 1; return(true); } #endif } size = 0; return(false); }
/// <summary> /// Sets the clipping region of the specified <see cref="RenderContext"/>. /// </summary> /// <param name="renderer">The <see cref="RenderContext"/> to have its clipping region set.</param> protected virtual void SetClip(RenderContext renderer) { Css.Value clip = ClipPath; if (clip == null) { return; } _previousClip = renderer.ClipRegion; // Get the shape from the clip value: Css.Value nextValue; ShapeProvider shape = clip.ToShape(this, renderer, out nextValue); if (clip != nextValue) { // Overwrite the raw clip var: ClipPath = nextValue; } if (shape != null) { // Get the region now: renderer.SetClip(shape.GetRegion(this, renderer), false); } }
/// <summary> /// Sets a time curve which progresses the overall slides animation. /// Almost always linear but change it for advanced effects.</summary> public void setTimingFunction(Css.Value timingFunc) { // The function to use: Blaze.VectorPath path = null; if (timingFunc != null) { // Get the defined vector path: path = timingFunc.GetPath( style == null? null : style.RenderData, Css.Properties.TimelineTimingFunction.GlobalProperty ); } if (path == null) { progressSampler = null; } else { if (!(path is Blaze.RasterVectorPath)) { Blaze.RasterVectorPath rvp = new Blaze.RasterVectorPath(); path.CopyInto(rvp); rvp.ToStraightLines(); path = rvp; } progressSampler = new Blaze.CurveSampler(path); progressSampler.Reset(); } }
/// <summary>Gets all child elements with the given tag.</summary> /// <param name="selector">The selector string to match.</param> /// <returns>The set of all tags with this tag.</returns> public HTMLCollection querySelectorAll(string selector, bool one) { // Create results set: HTMLCollection results = new HTMLCollection(); if (string.IsNullOrEmpty(selector)) { // Empty set: return(results); } // Create the lexer: Css.CssLexer lexer = new Css.CssLexer(selector, this); // Read a value: Css.Value value = lexer.ReadValue(); // Read the selectors from the value: List <Selector> selectors = new List <Selector>(); Css.CssLexer.ReadSelectors(null, value, selectors); // Create a blank event to store the targets, if any: CssEvent e = new CssEvent(); // Perform the selection process: querySelectorAll(selectors.ToArray(), results, e, false); return(results); }
public override bool OnAttributeChange(string property) { // Global CSS properties. Width, height, fill, stroke, visibility, font-family,font-style etc are handled here. Css.CssProperty cssProperty = Css.CssProperties.Get(property); // Style refresh: if (Style.Computed.FirstMatch != null) { // This is a runtime attribute change. // We must consider if it's affecting the style or not: Style.Computed.AttributeChanged(property); } if (cssProperty != null) { // It's a CSS property! Apply to style: Css.Value value = ValueHelpers.Get(getAttribute(property)); style[cssProperty] = value; } else if (property == "x") { style.left = getAttribute("x"); } else if (property == "y") { style.top = getAttribute("y"); } else if (!base.OnAttributeChange(property)) { return(false); } return(true); }
/// <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="timeCurve">Optional curve used to describe the progression of the animation. /// X is time, Y is value. Null acts like linear (a line from 0,0 to 1,1).</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, Blaze.VectorPath timeCurve, bool updateCss) { Animation = animation; CurrentTime = 0f; UpdateCss = updateCss; RawTarget = targetValue; if (timeCurve == null) { ProgressSampler = null; } else { if (!(timeCurve is Blaze.RasterVectorPath)) { Blaze.RasterVectorPath rvp = new Blaze.RasterVectorPath(); timeCurve.CopyInto(rvp); rvp.ToStraightLines(); timeCurve = rvp; } ProgressSampler = new Blaze.CurveSampler(timeCurve); ProgressSampler.Reset(); } }
/// <summary>Sets the defaults for one or more transform functions.</summary> private void SetDefaults(Css.Value set) { // Get as a function: Css.Functions.Transformation tf = set as Css.Functions.Transformation; if (tf != null) { tf.SetDefaults(); return; } // Should be a set: if (set is Css.ValueSet) { for (int i = 0; i < set.Count; i++) { // Get as a function: tf = set[i] as Css.Functions.Transformation; if (tf != null) { tf.SetDefaults(); } } } }
private void Complete() { // Remove from the update queue: Stop(); // Set target to the result. Css.Value target = RawTarget.Copy(); // Write it straight out to the computed style: // (Internally handles any aliases for us) Animation.ComputedStyle[InnerPropertyInfo] = target; // If it's not an alias, update hostValue: if (!InnerPropertyInfo.IsAlias) { PropertyValueObject = RawTarget; } if (UpdateCss) { // If we're the main animation (updateCss is true), tell the style it changed: // Note that in grouped properties, only the last one actually runs the update. Animation.ComputedStyle.ChangeProperty(PropertyInfo, PropertyValueObject); // And call the done function: Animation.Finished(); } }
/// <summary>Resolves the marker for the given computed style.</summary> public static string GetOrdinal(ComputedStyle style, bool prefixed) { // Get the list style type for this element: Css.Value value = style[Css.Properties.ListStyleType.GlobalProperty]; if (value == null) { // Disc is the default: return(style.reflowDocument.GetOrdinal(style.Element.childElementIndex + 1, "disc", prefixed) + " "); } else if (value.IsType(typeof(Css.Keywords.None))) { return(""); } // Get textual name: string name = value.Text; // Is it a named set? string result = style.reflowDocument.GetOrdinal(style.Element.childElementIndex + 1, name, prefixed); if (result == null) { // It's possibly the symbols() function or alternatively it's just some text. // Assume it's some text for now! result = value.Text; } return(result); }
/// <summary>Gets a CSS standard value. Typically e.g. "2in".</summary> public static Css.Value Get(string valueText) { // Load it (never null): Css.Value value = Css.Value.Load(valueText); return(value); }
public override bool OnReadValue(Style styleBlock, Css.Value value, int start, out int size) { int setCount = Set.Length; int usedUp = 0; size = 0; // Unfortunately this is required to be worst-case n^2, but n is usually very small (typically just 2). bool somethingWasSpent = true; while (somethingWasSpent) { // Clear the flag: somethingWasSpent = false; for (int b = 0; b < setCount; b++) { // If it has been 'spent' then ignore this one. if (Used[b]) { continue; } int currentSize; if (Set[b].OnReadValue(styleBlock, value, start, out currentSize)) { // 'b' has now been used up. Used[b] = true; // Move start and size along: start += currentSize; size += currentSize; // We now go again if there's any that have not been used up. somethingWasSpent = true; usedUp++; break; } } if (usedUp == setCount) { // Used them all up. break; } } // Clear used: for (int i = 0; i < setCount; i++) { Used[i] = false; } // Valid if at least 1 matched. return(size != 0); }
public override bool OnReadValue(Style styleBlock, Css.Value value, int start, out int size) { if (!Value.OnReadValue(styleBlock, value, start, out size)) { size = 0; } // Ok either way: return(true); }
/// <summary>Starts animating the named property and target value.</summary> /// <param name="property">The property to update. May be an alias or composite.</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, 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); if (animProperty != null) { animProperty.Animate(this, value, TimeCurve, updateCss); } else { // Otherwise we want to create one or more AnimatedProperties and stick them into the queue. // Get or create the initial value: Css.Value hostValue; Css.Value rawValue = property.GetOrCreateValue(Animating, ComputedStyle, false, out hostValue); if (rawValue is Css.ValueSet) { // A special case is when animating a value set. Each one needs to actually animate separately. // E.g. padding:40px 20px; then animating to just padding:30px; for (int i = 0; i < rawValue.Count; i++) { // Create it now: animProperty = new AnimatedProperty(this, property.GetAliased(i, true)); // Setup the value: animProperty.SetupValue(hostValue, rawValue[i]); // Get the target value: Css.Value target = (value is Css.ValueSet) ? value[i] : value; // Animate it now: animProperty.Animate(this, target, TimeCurve, updateCss); animProperty.AddToQueue(); } } else { // Create it now: animProperty = new AnimatedProperty(this, property); // Setup the value: animProperty.SetupValue(hostValue, rawValue); // Animate it now: animProperty.Animate(this, value, TimeCurve, updateCss); animProperty.AddToQueue(); } } }
public override bool OnReadValue(Style styleBlock, Css.Value value, int start, out int size) { if (value[start].GetRawDecimal() == RawLiteral) { size = 1; return(true); } size = 0; return(false); }
public override bool OnReadValue(Style styleBlock, Css.Value value, int start, out int size) { // Check if it's inherit or initial: if (value is Css.Keywords.Initial || value is Css.Keywords.Inherit) { // Apply it! size = 1; if (SetInfo != null) { // Indicate that we've been set: SetInfo.Set = true; } styleBlock[RawProperty] = value; return(true); } Css.Spec.Value spec = RawProperty.Specification; if (spec.OnReadValue(styleBlock, value, start, out size)) { // Apply it! if (SetInfo != null) { // Indicate that we've been set: SetInfo.Set = true; } if (size == 1) { styleBlock[RawProperty] = value[start]; } else { // Chop out a segment: Css.ValueSet set = new Css.ValueSet(new Css.Value[size]); for (int i = 0; i < size; i++) { set[i] = value[start + i]; } // Apply: styleBlock[RawProperty] = set; } return(true); } size = 0; return(false); }
public override bool OnReadValue(Style styleBlock, Css.Value value, int start, out int size) { for (int i = 0; i < Set.Length; i++) { if (Set[i].OnReadValue(styleBlock, value, start, out size)) { return(true); } } size = 0; return(false); }
public override bool OnReadValue(Style styleBlock, Css.Value value, int start, out int size) { Css.CssFunction func = value[start] as Css.CssFunction; if (func != null && func.Name == Name) { size = 1; return(true); } size = 0; return(false); }
/// <summary>Gets the named CSS property as a colour. If it's not found, the given default is used.</summary> protected Color GetFilterColour(CssProperty prop, Color deflt) { // Resolve the property (it must know its own default): Css.Value value = ComputedStyle.Resolve(prop); if (value == null) { return(deflt); } // Get as a colour: return(value.GetColour(RenderData, prop)); }
/// <summary>Resolves the named CSS property into a decimal value held in the computed style.</summary> protected float ResolveDecimal(Css.CssProperty prop) { // Reslove now: Css.Value val = ComputedStyle.Resolve(prop); if (val == null) { // Use initial value to avoid this one. return(0f); } return(val.GetDecimal(RenderData, prop)); }
/// <summary>Animates css properties on this element.</summary> /// <param name="css">A set of target css properties, e.g. "rotate-x:45deg;scale-y:110%;".</param> /// <param name="duration">The time, in seconds, to take animating the properties.</param> /// <param name="cssTimeFunction">The timing function (CSS). /// Can be anything that's valid CSS; e.g. "steps(3)" or "ease". Note that "ease" is the default in CSS.</summary> /// <returns>An animation instance which can be used to track progress.</returns> public UIAnimation animate(string css, float duration, string cssTimeFunction) { // Load the CSS function: Css.Value value = Css.Value.Load(cssTimeFunction); Blaze.VectorPath timeFunc = null; if (value != null) { // Get as a path: timeFunc = value.GetPath(null, null); } return(new UIAnimation(this, css, duration, timeFunc)); }
public override void OnComputeBox(Renderman renderer, Css.LayoutBox box, ref bool widthUndefined, ref bool heightUndefined) { RectangleProvider rect = Rectangle; // Check to see if w/h was updated via CSS: Css.Value newWidth = Width; Css.Value newHeight = Height; if (rect.Width != newWidth || rect.Height != newHeight) { rect.Width = newWidth; rect.Height = newHeight; RebuildPath(); } }
/// <summary>Sets up general information for a particular animation and starts running it.</summary> private void Setup(Node animating, Style style, float duration, Blaze.VectorPath timeCurve) { Animating = animating; ComputedStyle = (animating as IRenderableNode).ComputedStyle; if (duration <= 0f) { duration = 0f; } Duration = duration; TimeCurve = timeCurve; // Start animating the properties now. foreach (KeyValuePair <CssProperty, Css.Value> kvp in style.Properties) { // Get the value: Css.Value value = kvp.Value; // Get the property: CssProperty property = kvp.Key; // Grab the type: Css.ValueType type = value.Type; // Animate it (note that we don't need to copy it): if (property == Css.Properties.TransformProperty.GlobalProperty) { // Special case for animating transform. AnimateTransform(value); } else if (type == Css.ValueType.Set) { int count = value.Count; for (int i = 0; i < count; i++) { // Get the correct aliased property and animate it: Animate(property.GetAliased(i, true), value[i], (i == (count - 1))); } } else { Animate(property, value, true); } } }
private void BuildFilter(RenderContext renderer, bool withCssFilter) { // Get a path to draw: VectorPath path = GetPath(this, renderer); if (Visibility == VisibilityMode.Hidden || !PushTransforms(renderer)) { return; } if (withCssFilter) { // Get the filter CSS property: Css.Value filterValue = style.Computed[Css.Properties.Filter.GlobalProperty]; if (filterValue != null) { string filterPath = filterValue.Text; Element filter = document.getElementById(filterPath) as SVGFilterElement; if (filter != null) { PopTransforms(renderer); // filter.ApplyFilter(this, renderer, (r) => this.BuildFilter(r, false)); // Don't render normally. return; } } } SetClip(renderer); if (path != null) { BuildFill(path, renderer); BuildStroke(path, renderer); } else { BuildChildren(renderer); } ResetClip(renderer); PopTransforms(renderer); }
/// <summary>Scrolls the element by the given values.</summary> /// <param name="x">The change in x pixels.</param> /// <param name="y">The change in y pixels.</param> public void scrollBy(float x, float y) { if (x == 0f && y == 0f) { return; } // Get the scroll value (if there is one): Css.Value scroll = Style.Computed.Scroll; if (scroll == null) { scrollTo(x, y); return; } float top = (scroll[0] == null) ? 0f : scroll[0].GetDecimal(RenderData, null); float left = (scroll[1] == null) ? 0f : scroll[1].GetDecimal(RenderData, null); scrollTo(left + x, top + y); }
/// <summary>Special case when animating CSS transform.</summary> private void AnimateTransform(Css.Value value) { // 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. CssProperty property = Css.Properties.TransformProperty.GlobalProperty; AnimatedTransformProperty animProperty = GetAnimatedProperty(Animating, property) as AnimatedTransformProperty; bool isNew = (animProperty == null); if (isNew) { // Create it now: animProperty = new AnimatedTransformProperty(this); // Add to queue: animProperty.AddToQueue(); } animProperty.Animate(this, value, TimeCurve, true); }
/// <summary>Called when the thumb is being dragged.</summary> public override bool OnDrag(PowerUI.DragEvent mouseEvent) { // Get the amount of pixels the pointer moved by: float deltaX = AllowX ? mouseEvent.deltaX : 0f; float deltaY = AllowY ? mouseEvent.deltaY : 0f; if (deltaX == 0f && deltaY == 0f) { return(false); } // Resize now! ComputedStyle cs = ToResize_.Style.Computed; if (deltaX != 0f) { // Width is.. Css.Value width = cs[Css.Properties.Width.GlobalProperty]; // Update it: deltaX += width.GetDecimal(ToResize_.RenderData, Css.Properties.Width.GlobalProperty); // Write it back out: cs.ChangeProperty(Css.Properties.Width.GlobalProperty, new Css.Units.DecimalUnit(deltaX)); } if (deltaY != 0f) { // Height is.. Css.Value height = cs[Css.Properties.Height.GlobalProperty]; // Update it: deltaY += height.GetDecimal(ToResize_.RenderData, Css.Properties.Height.GlobalProperty); // Write it back out: cs.ChangeProperty(Css.Properties.Height.GlobalProperty, new Css.Units.DecimalUnit(deltaY)); } return(false); }
/// <summary>Sets the clipping boundary from the given computed style.</summary> /// <param name="style">The computed style to find the clipping boundary from.</param> public void SetBoundary(ComputedStyle computed, LayoutBox box) { bool visibleX = (box.OverflowX == VisibilityMode.Visible); bool visibleY = (box.OverflowY == VisibilityMode.Visible); if (visibleX && visibleY) { return; } BoxRegion newBoundary = null; if (visibleX) { newBoundary = new BoxRegion(ClippingBoundary.X, box.Y + box.FixedStyleOffsetTop, ClippingBoundary.Width, box.InnerHeight); } else if (visibleY) { newBoundary = new BoxRegion(box.X + box.FixedStyleOffsetLeft, ClippingBoundary.Y, box.InnerWidth, ClippingBoundary.Height); } else { newBoundary = new BoxRegion(box.X + box.FixedStyleOffsetLeft, box.Y + box.FixedStyleOffsetTop, box.InnerWidth, box.InnerHeight); } // Should it be clipped? Css.Value clipValue = computed[Css.Properties.ClipMode.GlobalProperty]; if (clipValue == null || clipValue.IsType(typeof(Css.Keywords.None)) || clipValue.GetBoolean(computed.RenderData, Css.Properties.ClipMode.GlobalProperty)) { newBoundary.ClipBy(ClippingBoundary); } else { ScreenClip = false; } ClippingBoundary = newBoundary; }
public override bool OnReadValue(Style styleBlock, Css.Value value, int start, out int size) { int setCount = Set.Length; size = 0; for (int i = 0; i < setCount; i++) { int currentSize; if (Set[i].OnReadValue(styleBlock, value, start, out currentSize)) { start += currentSize; size += currentSize; } else { size = 0; return(false); } } // All ok! return(true); }
/// <summary>Loads a timeline from the given JSON.</summary> public void load(Json.JSObject json) { if (started) { // Reset if needed: reset(); } duration = null; // First, check for the 'tracks' field: Json.JSObject trackData = json["tracks"]; if (trackData == null) { // Considered to be a single track. // Try loading it now: Track track = Track.loadFromJson(this, json); if (track == null) { // Empty: tracks = new Track[0]; } else { // We have at least 1 entry in a track. tracks = new Track[1]; // We now need to detect what kind of track it is based on what it provides. // If it's a style track, the first element tracks[0] = track; } } else { // Optional default language (must be before tracks load): string lang = json.String("lang"); if (!string.IsNullOrEmpty(lang)) { defaultLanguage = lang.Trim().ToLower(); } // Must be an indexed array: var trackArray = trackData as Json.JSIndexedArray; if (trackArray == null) { loadFailed("'tracks' must be an indexed array.", this); } // Fully defined timeline. int length = trackArray.length; // Create track set: tracks = new Track[length]; // Load each one: for (int i = 0; i < length; i++) { // Load the track now: tracks[i] = Track.loadFromJson(this, trackArray[i]); } // Optional duration: string durationText = json.String("duration"); if (!string.IsNullOrEmpty(durationText)) { // Load it as a CSS value: duration = Css.Value.Load(durationText); } } status_ = TIMELINE_STARTED; }
/// <summary>Figures out what kind of lerp is required with the given from/to values.</summary> public void ApplyValues(Css.Value from, Css.Value to) { // Get computed: if (from != null) { from = from.Computed; if (from.IsType(typeof(Css.Keywords.None))) { from = null; } } if (to != null) { to = to.Computed; if (to.IsType(typeof(Css.Keywords.None))) { to = null; } } // If both are null, do nothing. if (to == null && from == null) { return; } // If either is a cached transformValue, pull the origin: if (to != null && to is Css.Units.TransformValue) { Css.Units.TransformValue rawTo = to as Css.Units.TransformValue; to = rawTo.Origin; } if (from != null && from is Css.Units.TransformValue) { Css.Units.TransformValue rawFrom = from as Css.Units.TransformValue; from = rawFrom.Origin; } // If one or the other is null then it acts like the identity of the other. if (to != null && from != null) { // Check for functional equiv: if (!to.FunctionalEquals(from)) { // Matrix interpolation :'( // Bake both matrices: RenderableData rd = Animation.ComputedStyle.RenderData; Matrix4x4 fromMatrix = Css.Properties.TransformProperty.Compute(from, rd); Matrix4x4 toMatrix = Css.Properties.TransformProperty.Compute(to, rd); // If either is 3D then they both are treated as 3D values: if (Css.Properties.TransformProperty.Is3D(from) || Css.Properties.TransformProperty.Is3D(to)) { // 3D! // Write out into this value (no prep required here): FromFunctions = new InterpolationMatrix3D(fromMatrix); ToFunctions = new InterpolationMatrix3D(toMatrix); } else { // 2D! // Write out into this value: InterpolationMatrix fromInt = new InterpolationMatrix(fromMatrix); InterpolationMatrix toInt = new InterpolationMatrix(toMatrix); // Prep for interpolation: fromInt.PrepareForInterpolate(toInt); ToFunctions = toInt; FromFunctions = fromInt; } // Copy the from value: ActiveFunctions = FromFunctions.Copy(); // Write it back out: WriteOut(); return; } } // Interpolate every parameter of each function (if the other is null, use 0) // Note! The same function can appear multiple times. ToFunctions = to; FromFunctions = from; if (FromFunctions == null) { // Copy to (going from none) and set it all as zero: ActiveFunctions = ToFunctions.Copy(); // Set it all to 'zero' (it's e.g. 1 for scale though!) SetDefaults(ActiveFunctions); } else { // Copy from: ActiveFunctions = FromFunctions.Copy(); } // Write it back out: WriteOut(); }