|
|
@@ -4,6 +4,7 @@
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Linq;
|
|
|
+using System.Runtime.CompilerServices;
|
|
|
using Avalonia.Layout;
|
|
|
using Avalonia.VisualTree;
|
|
|
|
|
|
@@ -170,10 +171,9 @@ namespace Avalonia.Interactivity
|
|
|
|
|
|
e.Route = RoutingStrategies.Bubble;
|
|
|
|
|
|
- foreach (var target in this.GetBubbleEventRoute())
|
|
|
- {
|
|
|
- ((Interactive)target).RaiseEventImpl(e);
|
|
|
- }
|
|
|
+ var traverser = HierarchyTraverser<RaiseEventTraverse, NopTraverse>.Create(e);
|
|
|
+
|
|
|
+ traverser.Traverse(this);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
@@ -186,10 +186,9 @@ namespace Avalonia.Interactivity
|
|
|
|
|
|
e.Route = RoutingStrategies.Tunnel;
|
|
|
|
|
|
- foreach (var target in this.GetTunnelEventRoute())
|
|
|
- {
|
|
|
- ((Interactive)target).RaiseEventImpl(e);
|
|
|
- }
|
|
|
+ var traverser = HierarchyTraverser<NopTraverse, RaiseEventTraverse>.Create(e);
|
|
|
+
|
|
|
+ traverser.Traverse(this);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
@@ -262,5 +261,67 @@ namespace Avalonia.Interactivity
|
|
|
_subscriptions.Remove(_subscription);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ private interface ITraverse
|
|
|
+ {
|
|
|
+ void Execute(IInteractive target, RoutedEventArgs e);
|
|
|
+ }
|
|
|
+
|
|
|
+ private struct NopTraverse : ITraverse
|
|
|
+ {
|
|
|
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
+ public void Execute(IInteractive target, RoutedEventArgs e)
|
|
|
+ {
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private struct RaiseEventTraverse : ITraverse
|
|
|
+ {
|
|
|
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
+ public void Execute(IInteractive target, RoutedEventArgs e)
|
|
|
+ {
|
|
|
+ ((Interactive)target).RaiseEventImpl(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Traverses interactive hierarchy allowing for raising events.
|
|
|
+ /// </summary>
|
|
|
+ /// <typeparam name="TPreTraverse">Called before parent is traversed.</typeparam>
|
|
|
+ /// <typeparam name="TPostTraverse">Called after parent has been traversed.</typeparam>
|
|
|
+ private struct HierarchyTraverser<TPreTraverse, TPostTraverse>
|
|
|
+ where TPreTraverse : struct, ITraverse
|
|
|
+ where TPostTraverse : struct, ITraverse
|
|
|
+ {
|
|
|
+ private TPreTraverse _preTraverse;
|
|
|
+ private TPostTraverse _postTraverse;
|
|
|
+ private readonly RoutedEventArgs _args;
|
|
|
+
|
|
|
+ private HierarchyTraverser(TPreTraverse preTraverse, TPostTraverse postTraverse, RoutedEventArgs args)
|
|
|
+ {
|
|
|
+ _preTraverse = preTraverse;
|
|
|
+ _postTraverse = postTraverse;
|
|
|
+ _args = args;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static HierarchyTraverser<TPreTraverse, TPostTraverse> Create(RoutedEventArgs args)
|
|
|
+ {
|
|
|
+ return new HierarchyTraverser<TPreTraverse, TPostTraverse>(new TPreTraverse(), new TPostTraverse(), args);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Traverse(IInteractive target)
|
|
|
+ {
|
|
|
+ _preTraverse.Execute(target, _args);
|
|
|
+
|
|
|
+ IInteractive parent = target.InteractiveParent;
|
|
|
+
|
|
|
+ if (parent != null)
|
|
|
+ {
|
|
|
+ Traverse(parent);
|
|
|
+ }
|
|
|
+
|
|
|
+ _postTraverse.Execute(target, _args);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|