csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
5.0 KiB
152 lines
5.0 KiB
// -----------------------------------------------------------------------
|
|
// <copyright file="RoutedEvent.cs" company="Steven Kirk">
|
|
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|
// </copyright>
|
|
// -----------------------------------------------------------------------
|
|
|
|
namespace Perspex.Interactivity
|
|
{
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq.Expressions;
|
|
using System.Reflection;
|
|
|
|
[Flags]
|
|
public enum RoutingStrategies
|
|
{
|
|
Direct = 0x01,
|
|
Tunnel = 0x02,
|
|
Bubble = 0x04,
|
|
}
|
|
|
|
public class RoutedEvent
|
|
{
|
|
private List<ClassEventSubscription> subscriptions = new List<ClassEventSubscription>();
|
|
|
|
public RoutedEvent(
|
|
string name,
|
|
RoutingStrategies routingStrategies,
|
|
Type eventArgsType,
|
|
Type ownerType)
|
|
{
|
|
Contract.Requires<NullReferenceException>(name != null);
|
|
Contract.Requires<NullReferenceException>(eventArgsType != null);
|
|
Contract.Requires<NullReferenceException>(ownerType != null);
|
|
Contract.Requires<InvalidCastException>(typeof(RoutedEventArgs).GetTypeInfo().IsAssignableFrom(eventArgsType.GetTypeInfo()));
|
|
Contract.Requires<InvalidCastException>(typeof(IInteractive).GetTypeInfo().IsAssignableFrom(ownerType.GetTypeInfo()));
|
|
|
|
this.EventArgsType = eventArgsType;
|
|
this.Name = name;
|
|
this.OwnerType = ownerType;
|
|
this.RoutingStrategies = routingStrategies;
|
|
}
|
|
|
|
public Type EventArgsType
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
public string Name
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
public Type OwnerType
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
public RoutingStrategies RoutingStrategies
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
public static RoutedEvent<TEventArgs> Register<TOwner, TEventArgs>(
|
|
string name,
|
|
RoutingStrategies routingStrategy)
|
|
where TOwner : IInteractive
|
|
where TEventArgs : RoutedEventArgs
|
|
{
|
|
Contract.Requires<NullReferenceException>(name != null);
|
|
|
|
return new RoutedEvent<TEventArgs>(name, routingStrategy, typeof(TOwner));
|
|
}
|
|
|
|
public static RoutedEvent<TEventArgs> Register<TEventArgs>(
|
|
string name,
|
|
RoutingStrategies routingStrategy,
|
|
Type ownerType)
|
|
where TEventArgs : RoutedEventArgs
|
|
{
|
|
Contract.Requires<NullReferenceException>(name != null);
|
|
|
|
return new RoutedEvent<TEventArgs>(name, routingStrategy, ownerType);
|
|
}
|
|
|
|
public void AddClassHandler(Type type, EventHandler<RoutedEventArgs> handler, RoutingStrategies routes)
|
|
{
|
|
this.subscriptions.Add(new ClassEventSubscription
|
|
{
|
|
TargetType = type,
|
|
Handler = handler,
|
|
Routes = routes,
|
|
});
|
|
}
|
|
|
|
internal void InvokeClassHandlers(object sender, RoutedEventArgs e)
|
|
{
|
|
foreach (var sub in this.subscriptions)
|
|
{
|
|
if (sub.TargetType.GetTypeInfo().IsAssignableFrom(sender.GetType().GetTypeInfo()) &&
|
|
((e.Route == RoutingStrategies.Direct) || (e.Route & sub.Routes) != 0) &&
|
|
(!e.Handled || sub.AlsoIfHandled))
|
|
{
|
|
sub.Handler.DynamicInvoke(sender, e);
|
|
}
|
|
}
|
|
}
|
|
|
|
private class ClassEventSubscription : EventSubscription
|
|
{
|
|
public Type TargetType { get; set; }
|
|
}
|
|
}
|
|
|
|
public class RoutedEvent<TEventArgs> : RoutedEvent
|
|
where TEventArgs : RoutedEventArgs
|
|
{
|
|
public RoutedEvent(string name, RoutingStrategies routingStrategies, Type ownerType)
|
|
: base(name, routingStrategies, typeof(TEventArgs), ownerType)
|
|
{
|
|
Contract.Requires<NullReferenceException>(name != null);
|
|
Contract.Requires<NullReferenceException>(ownerType != null);
|
|
Contract.Requires<InvalidCastException>(typeof(IInteractive).GetTypeInfo().IsAssignableFrom(ownerType.GetTypeInfo()));
|
|
}
|
|
|
|
public void AddClassHandler<TTarget>(
|
|
Func<TTarget, Action<TEventArgs>> handler,
|
|
RoutingStrategies routes = RoutingStrategies.Direct | RoutingStrategies.Bubble)
|
|
where TTarget : class
|
|
{
|
|
this.AddClassHandler(typeof(TTarget), (s, e) => ClassHandlerAdapter<TTarget>(s, e, handler), routes);
|
|
}
|
|
|
|
private static void ClassHandlerAdapter<TTarget>(
|
|
object sender,
|
|
RoutedEventArgs e,
|
|
Func<TTarget, Action<TEventArgs>> handler) where TTarget : class
|
|
{
|
|
var target = sender as TTarget;
|
|
var args = e as TEventArgs;
|
|
|
|
if (target != null && args != null)
|
|
{
|
|
handler(target)(args);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|