/// <summary> /// Initializes the specified element and its descendants by hooking property bindings and events. /// </summary> /// <param name="element">The element.</param> private void InitElement(SkiaFrameworkElement element) { if (!GetIsInitialized(element)) { if (EnableBinding) { foreach (var bindingProperty in element.GetBindingProperties()) { var container = BindingEventContainer.Generate(element, bindingProperty); container.ValueChanged += OnBindingContainerValueChanged; _containers.Add(container); _bindingThrottlers.Add(container.BindingProperty, new ActionThrottle(TimeSpan.FromMilliseconds(1000d / BindingFPS), _host.Dispatcher)); } } element.ChildAdded += Element_ChildAdded; element.ChildRemoved += Element_ChildRemoved; SetIsInitialized(element, true); } foreach (var child in element.Children) { InitElement(child); } }
private static SkiaFrameworkElement LoadTreeInternal(FrameworkElement root) { SkiaFrameworkElement item = SkiaElementResolver.Default.CreateElementFor(root); if (item != null) { for (int i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++) { var element = VisualTreeHelper.GetChild(root, i) as FrameworkElement; if (element != null) { var treeItem = LoadTreeInternal(element); if (treeItem != null) { treeItem.Parent = item; item.Children.Add(treeItem); } } } return(item); } return(null); }
private List <SkiaFrameworkElement> Flatten(SkiaFrameworkElement element, List <SkiaFrameworkElement> list) { list.Add(element); foreach (var item in element.Children) { Flatten(item, list); } return(list); }
/// <summary> /// Performs a rendering pass on the specified <see cref="SkiaFrameworkElement"/> and its descendants. /// </summary> /// <param name="element">The element.</param> /// <param name="mode">The mode.</param> protected void RenderSingle(SkiaFrameworkElement element, BindingPropertyMode mode) { SkiaFrameworkElement toRender = element.Parent != null ? element.Parent : element; var bounds = toRender.Bounds; if (mode == BindingPropertyMode.AffectsLayout) { toRender.InvalidateBounds(); if (toRender.Bounds.Contains(bounds)) { bounds = toRender.Bounds; } else { bounds.Width += 1; bounds.Height += 1; } } if (bounds.Left < Source.Width && bounds.Top < Source.Height) { Source.Lock(); T context = CreateDrawingContext(); context.BeginDrawing(); context.ClipRect(bounds, new CornerRadius()); context.Clear(Colors.Transparent); SkiaTree.Root.Invalidate(context, bounds, 1); context.EndDrawing(); if (bounds.Right > Source.Width) { bounds.Width = Source.Width - bounds.Left; } if (bounds.Bottom > Source.Height) { bounds.Height = Source.Height - bounds.Top; } OnRenderCompleted(Source.BackBuffer, (int)Source.Width, (int)Source.Height, (int)Source.Width * 4); Source.AddDirtyRect(new Int32Rect((int)Math.Max(bounds.Left, 0), (int)Math.Max(bounds.Top, 0), (int)bounds.Width, (int)bounds.Height)); Source.Unlock(); } }
/// <summary> /// Generates a new <see cref="BindingEventContainer"/> for the specified Skia element and binding property. /// </summary> /// <param name="skiaElement">The skia element.</param> /// <param name="bindingProperty">The binding property.</param> /// <returns></returns> public static BindingEventContainer Generate(SkiaFrameworkElement skiaElement, BindingProperty bindingProperty) { BindingEventContainer container = new BindingEventContainer(skiaElement, bindingProperty); Binding binding = new Binding(); binding.Mode = BindingMode.OneWay; binding.Source = skiaElement.WpfElement; binding.Path = new PropertyPath(bindingProperty.DependencyProperty); binding.IsAsync = true; BindingOperations.SetBinding(container, BindingEventContainer.ValueProperty, binding); return(container); }
/// <summary> /// Invalidates the specified element <see cref="Bounds"/>. /// </summary> /// <param name="parent">The parent.</param> private void InvalidateBounds(SkiaFrameworkElement parent) { Bounds = GetBounds(); var bounds = Bounds; if (parent != null) { bounds.Offset(parent.Bounds.Left, parent.Bounds.Top); Bounds = bounds; } foreach (var child in Children) { child.InvalidateBounds(this); } }
/// <summary> /// Creates a new instance of a <see cref="SkiaFrameworkElement"/> by looking for a proper registration of the specified <see cref="FrameworkElement"/> type. /// When no registration was found, will return a default instance of <see cref="SkiaFrameworkElement"/>. /// </summary> /// <param name="element">The element.</param> /// <returns></returns> public SkiaFrameworkElement CreateElementFor(FrameworkElement element) { Type skiaType = null; if (_binders.TryGetValue(element.GetType(), out skiaType)) { SkiaFrameworkElement skiaElement = Activator.CreateInstance(skiaType) as SkiaFrameworkElement; skiaElement.WpfElement = element; return(skiaElement); } else { SkiaFrameworkElement defaultElement = Activator.CreateInstance(typeof(SkiaFrameworkElement)) as SkiaFrameworkElement; defaultElement.WpfElement = element; return(defaultElement); } }
private SkiaFrameworkElement Find(SkiaFrameworkElement element, Func <SkiaFrameworkElement, bool> predicate) { if (predicate(element)) { return(element); } foreach (var item in element.Children) { var result = Find(item, predicate); if (result != null) { return(result); } } return(null); }
/// <summary> /// Creates a new <see cref="DrawingStyle"/> based on the specified <see cref="SkiaFrameworkElement"/>. /// </summary> /// <param name="element">The element.</param> /// <returns></returns> public static DrawingStyle FromElement(SkiaFrameworkElement element) { DrawingStyle style = new DrawingStyle(); style.EdgeMode = RenderOptions.GetEdgeMode(element); style.Effect = element.WpfElement.Effect; if (element.Parent != null && element.Parent.WpfElement.RenderTransform != Transform.Identity) { style.Transform = element.Parent.WpfElement.RenderTransform; style.TransformOrigin = element.Parent.WpfElement.RenderTransformOrigin; } else { style.Transform = element.WpfElement.RenderTransform; style.TransformOrigin = element.WpfElement.RenderTransformOrigin; } return(style); }
/// <summary> /// Initializes a new instance of the <see cref="BindingEventContainer"/> class. /// </summary> /// <param name="skiaElement">The skia element.</param> /// <param name="bindingProperty">The binding property.</param> public BindingEventContainer(SkiaFrameworkElement skiaElement, BindingProperty bindingProperty) { SkiaElement = skiaElement; BindingProperty = bindingProperty; }
/// <summary> /// Disposes the specified element. /// </summary> /// <param name="element">The element.</param> private void DisposeElement(SkiaFrameworkElement element) { element.ChildAdded -= Element_ChildAdded; element.ChildRemoved -= Element_ChildRemoved; }
public static bool GetIsInitialized(SkiaFrameworkElement element) { return((bool)element.GetValue(IsInitializedProperty)); }
public static void SetIsInitialized(SkiaFrameworkElement element, bool value) { element.SetValue(IsInitializedProperty, value); }
/// <summary> /// Initializes a new instance of the <see cref="SkiaTree"/> class. /// </summary> /// <param name="root">The root.</param> public SkiaTree(SkiaFrameworkElement root) { Root = root; }