Separate version
This commit is contained in:
1 parent
a2574dc955
commit
db61ae9567
587 files changed
+44639
-657
No files matched your search
@@ -0,0 +1,172 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace HandyControl.Expression.Media
|
||||
{
|
||||
[TypeConverter(typeof(GeometryEffectConverter))]
|
||||
public abstract class GeometryEffect : Freezable
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
private static GeometryEffect defaultGeometryEffect;
|
||||
|
||||
public static readonly DependencyProperty GeometryEffectProperty =
|
||||
DependencyProperty.RegisterAttached("GeometryEffect", typeof(GeometryEffect),
|
||||
typeof(GeometryEffect),
|
||||
new DrawingPropertyMetadata(DefaultGeometryEffect,
|
||||
DrawingPropertyMetadataOptions.AffectsRender, OnGeometryEffectChanged));
|
||||
|
||||
protected Geometry CachedGeometry;
|
||||
|
||||
private bool _effectInvalidated;
|
||||
|
||||
static GeometryEffect()
|
||||
{
|
||||
DrawingPropertyMetadata.DrawingPropertyChanged +=
|
||||
delegate(object sender, DrawingPropertyChangedEventArgs args)
|
||||
{
|
||||
if (sender is GeometryEffect effect && args.Metadata.AffectsRender)
|
||||
effect.InvalidateGeometry(InvalidateGeometryReasons.PropertyChanged);
|
||||
};
|
||||
}
|
||||
|
||||
public static GeometryEffect DefaultGeometryEffect =>
|
||||
defaultGeometryEffect ?? (defaultGeometryEffect = new NoGeometryEffect());
|
||||
|
||||
public Geometry OutputGeometry =>
|
||||
CachedGeometry;
|
||||
|
||||
protected internal DependencyObject Parent { get; private set; }
|
||||
|
||||
protected internal virtual void Attach(DependencyObject obj)
|
||||
{
|
||||
if (Parent != null) Detach();
|
||||
_effectInvalidated = true;
|
||||
CachedGeometry = null;
|
||||
if (InvalidateParent(obj)) Parent = obj;
|
||||
}
|
||||
|
||||
public new GeometryEffect CloneCurrentValue()
|
||||
{
|
||||
return (GeometryEffect) base.CloneCurrentValue();
|
||||
}
|
||||
|
||||
protected override Freezable CreateInstanceCore()
|
||||
{
|
||||
return (Freezable) Activator.CreateInstance(GetType());
|
||||
}
|
||||
|
||||
protected abstract GeometryEffect DeepCopy();
|
||||
|
||||
protected internal virtual void Detach()
|
||||
{
|
||||
_effectInvalidated = true;
|
||||
CachedGeometry = null;
|
||||
if (Parent != null)
|
||||
{
|
||||
InvalidateParent(Parent);
|
||||
Parent = null;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract bool Equals(GeometryEffect geometryEffect);
|
||||
|
||||
public static GeometryEffect GetGeometryEffect(DependencyObject obj)
|
||||
{
|
||||
return (GeometryEffect) obj.GetValue(GeometryEffectProperty);
|
||||
}
|
||||
|
||||
public bool InvalidateGeometry(InvalidateGeometryReasons reasons)
|
||||
{
|
||||
if (_effectInvalidated) return false;
|
||||
_effectInvalidated = true;
|
||||
if (reasons != InvalidateGeometryReasons.ParentInvalidated) InvalidateParent(Parent);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool InvalidateParent(DependencyObject parent)
|
||||
{
|
||||
if (parent is IShape shape)
|
||||
{
|
||||
shape.InvalidateGeometry(InvalidateGeometryReasons.ChildInvalidated);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (parent is GeometryEffect effect)
|
||||
{
|
||||
effect.InvalidateGeometry(InvalidateGeometryReasons.ChildInvalidated);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void OnGeometryEffectChanged(DependencyObject obj,
|
||||
DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var oldValue = e.OldValue as GeometryEffect;
|
||||
var newValue = e.NewValue as GeometryEffect;
|
||||
if (!Equals(oldValue, newValue))
|
||||
{
|
||||
if (oldValue != null && obj.Equals(oldValue.Parent)) oldValue.Detach();
|
||||
if (newValue != null)
|
||||
{
|
||||
if (newValue.Parent != null)
|
||||
{
|
||||
obj.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
var effect = newValue.CloneCurrentValue();
|
||||
obj.SetValue(GeometryEffectProperty, effect);
|
||||
}), DispatcherPriority.Send, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
newValue.Attach(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool ProcessGeometry(Geometry input)
|
||||
{
|
||||
var flag = false;
|
||||
if (_effectInvalidated)
|
||||
{
|
||||
flag |= UpdateCachedGeometry(input);
|
||||
_effectInvalidated = false;
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
public static void SetGeometryEffect(DependencyObject obj, GeometryEffect value)
|
||||
{
|
||||
obj.SetValue(GeometryEffectProperty, value);
|
||||
}
|
||||
|
||||
protected abstract bool UpdateCachedGeometry(Geometry input);
|
||||
|
||||
|
||||
private class NoGeometryEffect : GeometryEffect
|
||||
{
|
||||
protected override GeometryEffect DeepCopy()
|
||||
{
|
||||
return new NoGeometryEffect();
|
||||
}
|
||||
|
||||
public override bool Equals(GeometryEffect geometryEffect)
|
||||
{
|
||||
if (geometryEffect != null) return geometryEffect is NoGeometryEffect;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool UpdateCachedGeometry(Geometry input)
|
||||
{
|
||||
CachedGeometry = input;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user