Skip to content

Commit

Permalink
feat: Added property change propagation notification for CompositionO…
Browse files Browse the repository at this point in the history
…bjects
  • Loading branch information
VitezslavImrysek committed Jul 30, 2021
1 parent 10f2466 commit 543b834
Show file tree
Hide file tree
Showing 14 changed files with 528 additions and 269 deletions.
56 changes: 49 additions & 7 deletions src/Uno.UWP/UI/Composition/CompositionClip.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,59 @@ namespace Windows.UI.Composition
{
public partial class CompositionClip : CompositionObject
{
private Matrix3x2 _transformMatrix = Matrix3x2.Identity;
private Vector2 _scale = new Vector2(1, 1);
private float _rotationAngleInDegrees;
private float _rotationAngle;
private Vector2 _offset = Vector2.Zero;
private Vector2 _centerPoint = Vector2.Zero;
private Vector2 _anchorPoint = Vector2.Zero;

internal CompositionClip(Compositor compositor) : base(compositor)
{

}

public Matrix3x2 TransformMatrix { get; set; }
public Vector2 Scale { get; set; }
public float RotationAngleInDegrees { get; set; }
public float RotationAngle { get; set; }
public Vector2 Offset { get; set; }
public Vector2 CenterPoint { get; set; }
public Vector2 AnchorPoint { get; set; }
public Matrix3x2 TransformMatrix
{
get => _transformMatrix;
set => SetProperty(ref _transformMatrix, value);
}

public Vector2 Scale
{
get => _scale;
set => SetProperty(ref _scale, value);
}

public float RotationAngleInDegrees
{
get => _rotationAngleInDegrees;
set => SetProperty(ref _rotationAngleInDegrees, value);
}

public float RotationAngle
{
get => _rotationAngle;
set => SetProperty(ref _rotationAngle, value);
}

public Vector2 Offset
{
get => _offset;
set => SetProperty(ref _offset, value);
}

public Vector2 CenterPoint
{
get => _centerPoint;
set => SetProperty(ref _centerPoint, value);
}

public Vector2 AnchorPoint
{
get => _anchorPoint;
set => SetProperty(ref _anchorPoint, value);
}
}
}
25 changes: 2 additions & 23 deletions src/Uno.UWP/UI/Composition/CompositionColorBrush.cs
Original file line number Diff line number Diff line change
@@ -1,43 +1,22 @@
#nullable enable

using System;
using System.Collections.Generic;
using Uno.Disposables;
using Windows.UI;

namespace Windows.UI.Composition
{
public partial class CompositionColorBrush : CompositionBrush
{
private List<Action> _colorChangedHandlers = new List<Action>();
private Color _color;

internal CompositionColorBrush() => throw new NotSupportedException();

public CompositionColorBrush(Compositor compositor) : base(compositor)
internal CompositionColorBrush(Compositor compositor) : base(compositor)
{

}

public Color Color
{
get { return _color; }
set { _color = value; OnColorChanged(); }
}

private void OnColorChanged()
{
foreach (var handler in _colorChangedHandlers)
{
handler();
}
}

internal IDisposable RegisterColorChanged(Action onColorChanged)
{
_colorChangedHandlers.Add(onColorChanged);

return Disposable.Create(() => _colorChangedHandlers.Remove(onColorChanged));
set { SetProperty(ref _color, value); }
}
}
}
12 changes: 9 additions & 3 deletions src/Uno.UWP/UI/Composition/CompositionGeometricClip.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,26 @@

namespace Windows.UI.Composition
{
public partial class CompositionGeometricClip : global::Windows.UI.Composition.CompositionClip
public partial class CompositionGeometricClip : CompositionClip
{
private CompositionViewBox? _viewBox;
private CompositionGeometry? _geometry;

public CompositionGeometricClip(Compositor compositor) : base(compositor)
{

}

public CompositionViewBox? ViewBox
{
get; set;
get => _viewBox;
set => SetProperty(ref _viewBox, value);
}

public CompositionGeometry? Geometry
{
get; set;
get => _geometry;
set => SetProperty(ref _geometry, value);
}
}
}
177 changes: 173 additions & 4 deletions src/Uno.UWP/UI/Composition/CompositionObject.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
#nullable enable

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Windows.Foundation.Metadata;
using Windows.UI.Core;

namespace Windows.UI.Composition
{
public partial class CompositionObject : global::System.IDisposable
public partial class CompositionObject : IDisposable
{
private object _gate = new object();
private readonly ContextStore _contextStore = new ContextStore();

internal CompositionObject()
{
Expand All @@ -25,17 +27,184 @@ internal CompositionObject(Compositor compositor)

public CoreDispatcher Dispatcher => CoreDispatcher.Main;

public string? Comment { get; set; }

public void StartAnimation(string propertyName, CompositionAnimation animation)
{
StartAnimationCore(propertyName, animation);
}

public void StopAnimation(string propertyName)
{

}

internal virtual void StartAnimationCore(string propertyName, CompositionAnimation animation) { }

public void StopAnimation(string propertyName)
internal void AddContext(CompositionObject context, string? propertyName)
{
_contextStore.AddContext(context, propertyName);
}

public string? Comment { get; set; }
internal void RemoveContext(CompositionObject context, string? propertyName)
{
_contextStore.RemoveContext(context, propertyName);
}

private protected void SetProperty<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
{
var fieldCO = field as CompositionObject;
var valueCO = value as CompositionObject;
if (fieldCO != null || value != null)
{
OnCompositionPropertyChanged(fieldCO, valueCO, propertyName);
}

field = value;

OnPropertyChanged(propertyName, false);
}

private protected void OnChanged() => OnPropertyChanged(null, false);

private protected void OnCompositionPropertyChanged(CompositionObject? oldValue, CompositionObject? newValue) => OnCompositionPropertyChanged(oldValue, newValue, null);

private protected void OnCompositionPropertyChanged(CompositionObject? oldValue, CompositionObject? newValue, string? propertyName)
{
if (oldValue != null)
{
oldValue.RemoveContext(this, propertyName);
}

if (newValue != null)
{
newValue.AddContext(this, propertyName);
}
}

private protected void OnPropertyChanged(string? propertyName, bool isSubPropertyChange)
{
OnPropertyChangedCore(propertyName, isSubPropertyChange);
_contextStore.RaiseChanged();
}

private protected virtual void OnPropertyChangedCore(string? propertyName, bool isSubPropertyChange)
{

}

private class ContextStore
{
private readonly object _lock = new object();
private List<ContextEntry>? _contextEntries = null;

public ContextStore()
{

}

public void AddContext(CompositionObject context, string? propertyName)
{
lock (_lock)
{
AddContextImpl(context, propertyName);
}
}

public void RemoveContext(CompositionObject context, string? propertyName)
{
lock (_lock)
{
RemoveContextImpl(context, propertyName);
}
}

public void RaiseChanged()
{
lock (_lock)
{
RaiseChangedImpl();
}
}

private void AddContextImpl(CompositionObject newContext, string? propertyName)
{
var contextEntries = _contextEntries;
if (contextEntries == null)
{
contextEntries = new List<ContextEntry>();
_contextEntries = contextEntries;
}

contextEntries.Add(new ContextEntry(newContext, propertyName));
}

private void RemoveContextImpl(CompositionObject oldContext, string? propertyName)
{
var contextEntries = _contextEntries;
if (contextEntries == null)
{
return;
}

for (int i = contextEntries.Count - 1; i >= 0; i--)
{
var contextEntry = contextEntries[i];

if (!contextEntry.Context.TryGetTarget(out CompositionObject? context))
{
// Clean up dead references.
contextEntries.RemoveAt(i);
continue;
}

if (context == oldContext && contextEntry.PropertyName == propertyName)
{
contextEntries.RemoveAt(i);
break;
}
}

if (contextEntries.Count == 0)
{
_contextEntries = null;
}
}

private void RaiseChangedImpl()
{
var contextEntries = _contextEntries;
if (contextEntries == null)
{
return;
}

for (int i = contextEntries.Count - 1; i >= 0; i--)
{
var contextEntry = contextEntries[i];

if (!contextEntry.Context.TryGetTarget(out CompositionObject? context))
{
// Clean up dead references.
contextEntries.RemoveAt(i);
continue;
}

context!.OnPropertyChanged(contextEntry.PropertyName, true);
}
}

private class ContextEntry
{
public ContextEntry(CompositionObject context, string? propertyName)
{
Context = new WeakReference<CompositionObject>(context);
PropertyName = propertyName;
}

public WeakReference<CompositionObject> Context { get; }
public string? PropertyName { get; }
}
}
}
}
Loading

0 comments on commit 543b834

Please sign in to comment.