10 changed files with 420 additions and 8 deletions
@ -0,0 +1,14 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="MouseEventArgs.cs" company="Steven Kirk">
|
|||
// Copyright 2013 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.Input |
|||
{ |
|||
using System; |
|||
|
|||
public class MouseEventArgs : RoutedEventArgs |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,106 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="Interactive.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex |
|||
{ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Diagnostics.Contracts; |
|||
using System.Reactive; |
|||
using System.Reactive.Linq; |
|||
|
|||
public class Interactive : Visual |
|||
{ |
|||
private Dictionary<RoutedEvent, List<Delegate>> eventHandlers = new Dictionary<RoutedEvent, List<Delegate>>(); |
|||
|
|||
public void AddHandler(RoutedEvent routedEvent, Delegate handler) |
|||
{ |
|||
Contract.Requires<NullReferenceException>(routedEvent != null); |
|||
Contract.Requires<NullReferenceException>(handler != null); |
|||
|
|||
List<Delegate> delegates; |
|||
|
|||
if (!this.eventHandlers.TryGetValue(routedEvent, out delegates)) |
|||
{ |
|||
delegates = new List<Delegate>(); |
|||
this.eventHandlers.Add(routedEvent, delegates); |
|||
} |
|||
|
|||
delegates.Add(handler); |
|||
} |
|||
|
|||
public IObservable<EventPattern<T>> GetObservable<T>(RoutedEvent<T> routedEvent) where T : RoutedEventArgs |
|||
{ |
|||
Contract.Requires<NullReferenceException>(routedEvent != null); |
|||
|
|||
return Observable.FromEventPattern<T>( |
|||
handler => this.AddHandler(routedEvent, handler), |
|||
handler => this.RemoveHandler(routedEvent, handler)); |
|||
} |
|||
|
|||
public void RemoveHandler(RoutedEvent routedEvent, Delegate handler) |
|||
{ |
|||
Contract.Requires<NullReferenceException>(routedEvent != null); |
|||
Contract.Requires<NullReferenceException>(handler != null); |
|||
|
|||
List<Delegate> delegates; |
|||
|
|||
if (this.eventHandlers.TryGetValue(routedEvent, out delegates)) |
|||
{ |
|||
delegates.Remove(handler); |
|||
} |
|||
} |
|||
|
|||
public void RaiseEvent(RoutedEventArgs e) |
|||
{ |
|||
Contract.Requires<NullReferenceException>(e != null); |
|||
|
|||
if (e.RoutedEvent != null) |
|||
{ |
|||
switch (e.RoutedEvent.RoutingStrategy) |
|||
{ |
|||
case RoutingStrategy.Bubble: |
|||
this.BubbleEvent(e); |
|||
break; |
|||
case RoutingStrategy.Direct: |
|||
this.RaiseEventImpl(e); |
|||
break; |
|||
default: |
|||
throw new NotImplementedException(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private void BubbleEvent(RoutedEventArgs e) |
|||
{ |
|||
Contract.Requires<NullReferenceException>(e != null); |
|||
|
|||
Interactive target = this; |
|||
|
|||
while (target != null) |
|||
{ |
|||
target.RaiseEventImpl(e); |
|||
target = target.GetVisualAncestor<Interactive>(); |
|||
} |
|||
} |
|||
|
|||
private void RaiseEventImpl(RoutedEventArgs e) |
|||
{ |
|||
Contract.Requires<NullReferenceException>(e != null); |
|||
|
|||
List<Delegate> delegates; |
|||
|
|||
if (this.eventHandlers.TryGetValue(e.RoutedEvent, out delegates)) |
|||
{ |
|||
foreach (Delegate handler in delegates) |
|||
{ |
|||
// TODO: Implement the Handled stuff.
|
|||
handler.DynamicInvoke(this, e); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,87 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="RoutedEvent.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex |
|||
{ |
|||
using System; |
|||
using System.Diagnostics.Contracts; |
|||
using System.Reflection; |
|||
|
|||
public enum RoutingStrategy |
|||
{ |
|||
Tunnel, |
|||
Bubble, |
|||
Direct, |
|||
} |
|||
|
|||
public class RoutedEvent |
|||
{ |
|||
public RoutedEvent( |
|||
string name, |
|||
RoutingStrategy routingStrategy, |
|||
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(Interactive).GetTypeInfo().IsAssignableFrom(ownerType.GetTypeInfo())); |
|||
|
|||
this.EventArgsType = eventArgsType; |
|||
this.Name = name; |
|||
this.OwnerType = ownerType; |
|||
this.RoutingStrategy = routingStrategy; |
|||
} |
|||
|
|||
public Type EventArgsType |
|||
{ |
|||
get; |
|||
private set; |
|||
} |
|||
|
|||
public string Name |
|||
{ |
|||
get; |
|||
private set; |
|||
} |
|||
|
|||
public Type OwnerType |
|||
{ |
|||
get; |
|||
private set; |
|||
} |
|||
|
|||
public RoutingStrategy RoutingStrategy |
|||
{ |
|||
get; |
|||
private set; |
|||
} |
|||
|
|||
public static RoutedEvent<TEventArgs> Register<TOwner, TEventArgs>( |
|||
string name, |
|||
RoutingStrategy routingStrategy) |
|||
where TOwner : Interactive |
|||
where TEventArgs : RoutedEventArgs |
|||
{ |
|||
Contract.Requires<NullReferenceException>(name != null); |
|||
|
|||
return new RoutedEvent<TEventArgs>(name, routingStrategy, typeof(TOwner)); |
|||
} |
|||
} |
|||
|
|||
public class RoutedEvent<TEventArgs> : RoutedEvent |
|||
where TEventArgs : RoutedEventArgs |
|||
{ |
|||
public RoutedEvent(string name, RoutingStrategy routingStrategy, Type ownerType) |
|||
: base(name, routingStrategy, typeof(TEventArgs), ownerType) |
|||
{ |
|||
Contract.Requires<NullReferenceException>(name != null); |
|||
Contract.Requires<NullReferenceException>(ownerType != null); |
|||
Contract.Requires<InvalidCastException>(typeof(Interactive).GetTypeInfo().IsAssignableFrom(ownerType.GetTypeInfo())); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="RoutedEventArgs.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex |
|||
{ |
|||
using System; |
|||
|
|||
public class RoutedEventArgs : EventArgs |
|||
{ |
|||
public RoutedEventArgs() |
|||
{ |
|||
} |
|||
|
|||
public RoutedEventArgs(RoutedEvent routedEvent) |
|||
{ |
|||
this.RoutedEvent = routedEvent; |
|||
} |
|||
|
|||
public RoutedEventArgs(RoutedEvent routedEvent, object source) |
|||
{ |
|||
this.RoutedEvent = routedEvent; |
|||
this.Source = source; |
|||
} |
|||
|
|||
public bool Handled { get; set; } |
|||
|
|||
public object OriginalSource { get; set; } |
|||
|
|||
public RoutedEvent RoutedEvent { get; set; } |
|||
|
|||
public object Source { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,65 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="VisualExtensions.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex |
|||
{ |
|||
using System; |
|||
using System.Diagnostics.Contracts; |
|||
using System.Linq; |
|||
|
|||
public static class VisualExtensions |
|||
{ |
|||
public static T GetVisualAncestor<T>(this Visual visual) where T : Visual |
|||
{ |
|||
Contract.Requires<NullReferenceException>(visual != null); |
|||
|
|||
visual = visual.VisualParent; |
|||
|
|||
while (visual != null) |
|||
{ |
|||
if (visual is T) |
|||
{ |
|||
return (T)visual; |
|||
} |
|||
else |
|||
{ |
|||
visual = visual.VisualParent; |
|||
} |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
public static Visual GetVisualAt(this Visual visual, Point p) |
|||
{ |
|||
Contract.Requires<NullReferenceException>(visual != null); |
|||
|
|||
if (visual.Bounds.Contains(p)) |
|||
{ |
|||
p -= visual.Bounds.Position; |
|||
|
|||
if (visual.VisualChildren.Any()) |
|||
{ |
|||
foreach (Visual child in visual.VisualChildren) |
|||
{ |
|||
Visual hit = child.GetVisualAt(p); |
|||
|
|||
if (hit != null) |
|||
{ |
|||
return hit; |
|||
} |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
return visual; |
|||
} |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue