using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using Tango.Core.EventArguments;
public static class FrameworkElementExtensions
{
#region Mouse Or Touch Events
///
/// Registers for mouse or touch down.
///
/// The element.
/// The relative to.
/// The handler.
public static void RegisterForMouseOrTouchDown(this FrameworkElement element, FrameworkElement relativeTo, EventHandler handler)
{
bool mousePressed = false;
bool touchDown = false;
MouseButtonEventHandler mouseDownHandler = (x, e) =>
{
if (!touchDown)
{
mousePressed = true;
var args = new MouseOrTouchEventArgs()
{
Location = new Point(e.GetPosition(relativeTo != null ? relativeTo : element).X, e.GetPosition(relativeTo != null ? relativeTo : element).Y),
Source = e.Source,
OriginalSource = e.OriginalSource,
Handled = e.Handled,
GetPositionAction = e.GetPosition
};
handler(element, args);
e.Handled = args.Handled;
}
else
{
touchDown = false;
}
};
//element.MouseDown += mouseDownHandler;
element.AddHandler(FrameworkElement.MouseDownEvent, mouseDownHandler);
EventHandler touchDownHandler = (x, e) =>
{
if (!mousePressed)
{
touchDown = true;
var args = new MouseOrTouchEventArgs()
{
Location = new Point(e.GetTouchPoint(relativeTo != null ? relativeTo : element).Position.X, e.GetTouchPoint(relativeTo != null ? relativeTo : element).Position.Y),
Source = e.Source,
OriginalSource = e.OriginalSource,
Handled = e.Handled,
GetPositionAction = (s) => { return e.GetTouchPoint(s).Position; },
TouchDevice = e.TouchDevice,
};
handler(element, args);
e.Handled = args.Handled;
}
else
{
touchDown = false;
}
};
//element.TouchDown += touchDownHandler;
element.AddHandler(FrameworkElement.TouchDownEvent, touchDownHandler);
MouseButtonEventHandler mouseUpHandler = (_, __) =>
{
touchDown = false;
mousePressed = false;
};
//element.MouseUp += mouseUpHandler;
element.AddHandler(FrameworkElement.MouseUpEvent, mouseUpHandler);
//element.TouchDown += (_, __) =>
//{
//};
}
///
/// Registers for mouse or touch down.
///
/// The element.
/// The handler.
public static void RegisterForMouseOrTouchDown(this FrameworkElement element, EventHandler handler)
{
RegisterForMouseOrTouchDown(element, null, handler);
}
///
/// Registers for mouse or touch up.
///
/// The element.
/// The relative to.
/// The handler.
public static void RegisterForMouseOrTouchUp(this FrameworkElement element, FrameworkElement relativeTo, EventHandler handler)
{
bool mouseReleased = false;
bool touchReleased = false;
MouseButtonEventHandler mouseUpHandler = (x, e) =>
{
if (!touchReleased)
{
mouseReleased = true;
var args = new MouseOrTouchEventArgs()
{
Location = new Point(e.GetPosition(relativeTo != null ? relativeTo : element).X, e.GetPosition(relativeTo != null ? relativeTo : element).Y),
Source = e.Source,
OriginalSource = e.OriginalSource,
Handled = e.Handled,
GetPositionAction = e.GetPosition
};
handler(element, args);
e.Handled = args.Handled;
}
else
{
touchReleased = false;
}
};
//element.MouseUp += mouseUpHandler;
element.AddHandler(FrameworkElement.MouseUpEvent, mouseUpHandler);
EventHandler touchUpHandler = (x, e) =>
{
if (!mouseReleased)
{
touchReleased = true;
var args = new MouseOrTouchEventArgs()
{
Location = new Point(e.GetTouchPoint(relativeTo != null ? relativeTo : element).Position.X, e.GetTouchPoint(relativeTo != null ? relativeTo : element).Position.Y),
Source = e.Source,
OriginalSource = e.OriginalSource,
Handled = e.Handled,
GetPositionAction = (s) => { return e.GetTouchPoint(s).Position; },
TouchDevice = e.TouchDevice,
};
handler(element, args);
e.Handled = args.Handled;
}
else
{
touchReleased = false;
}
};
//element.TouchUp += touchUpHandler;
element.AddHandler(FrameworkElement.TouchUpEvent, touchUpHandler);
EventHandler touchDownHandler = (_, __) =>
{
touchReleased = false;
mouseReleased = false;
};
//element.TouchDown += touchDownHandler;
element.AddHandler(FrameworkElement.TouchDownEvent, touchDownHandler);
}
///
/// Registers for mouse or touch up.
///
/// The element.
/// The handler.
public static void RegisterForMouseOrTouchUp(this FrameworkElement element, EventHandler handler)
{
RegisterForMouseOrTouchUp(element, null, handler);
}
///
/// Registers for preview mouse or touch down.
///
/// The element.
/// The relative to.
/// The handler.
public static void RegisterForPreviewMouseOrTouchDown(this FrameworkElement element, FrameworkElement relativeTo, EventHandler handler)
{
bool mousePressed = false;
bool touchDown = false;
MouseButtonEventHandler previewMouseDownHandler = (x, e) =>
{
if (!touchDown)
{
mousePressed = true;
var args = new MouseOrTouchEventArgs()
{
Location = new Point(e.GetPosition(relativeTo != null ? relativeTo : element).X, e.GetPosition(relativeTo != null ? relativeTo : element).Y),
Source = e.Source,
OriginalSource = e.OriginalSource,
Handled = e.Handled,
GetPositionAction = e.GetPosition
};
handler(element, args);
e.Handled = args.Handled;
}
else
{
touchDown = false;
}
};
element.AddHandler(FrameworkElement.PreviewMouseDownEvent, previewMouseDownHandler);
//element.PreviewMouseDown += previewMouseDownHandler;
EventHandler previewTouchDownHandler = (x, e) =>
{
if (!mousePressed)
{
touchDown = true;
var args = new MouseOrTouchEventArgs()
{
Location = new Point(e.GetTouchPoint(relativeTo != null ? relativeTo : element).Position.X, e.GetTouchPoint(relativeTo != null ? relativeTo : element).Position.Y),
Source = e.Source,
OriginalSource = e.OriginalSource,
Handled = e.Handled,
GetPositionAction = (s) => { return e.GetTouchPoint(s).Position; },
TouchDevice = e.TouchDevice,
};
handler(element, args);
e.Handled = args.Handled;
}
else
{
touchDown = false;
}
};
//element.PreviewTouchDown += previewTouchDownHandler;
element.AddHandler(FrameworkElement.PreviewTouchDownEvent, previewTouchDownHandler);
MouseButtonEventHandler previewMouseUpHandler = (_, __) =>
{
touchDown = false;
mousePressed = false;
};
//element.PreviewMouseUp += previewMouseUpHandler;
element.AddHandler(FrameworkElement.PreviewMouseUpEvent, previewMouseUpHandler);
}
///
/// Registers for preview mouse or touch down.
///
/// The element.
/// The handler.
public static void RegisterForPreviewMouseOrTouchDown(this FrameworkElement element, EventHandler handler)
{
RegisterForPreviewMouseOrTouchDown(element, null, handler);
}
///
/// Registers for preview mouse or touch up.
///
/// The element.
/// The relative to.
/// The handler.
public static void RegisterForPreviewMouseOrTouchUp(this FrameworkElement element, FrameworkElement relativeTo, EventHandler handler)
{
bool mouseReleased = false;
bool touchReleased = false;
MouseButtonEventHandler previewMouseUpHandler = (x, e) =>
{
if (!touchReleased)
{
mouseReleased = true;
var args = new MouseOrTouchEventArgs()
{
Location = new Point(e.GetPosition(relativeTo != null ? relativeTo : element).X, e.GetPosition(relativeTo != null ? relativeTo : element).Y),
Source = e.Source,
OriginalSource = e.OriginalSource,
Handled = e.Handled,
GetPositionAction = e.GetPosition
};
handler(element, args);
e.Handled = args.Handled;
}
else
{
touchReleased = false;
}
};
//element.PreviewMouseUp += previewMouseUpHandler;
element.AddHandler(FrameworkElement.PreviewMouseUpEvent, previewMouseUpHandler);
EventHandler previewTouchHandler = (x, e) =>
{
if (!mouseReleased)
{
touchReleased = true;
var args = new MouseOrTouchEventArgs()
{
Location = new Point(e.GetTouchPoint(relativeTo != null ? relativeTo : element).Position.X, e.GetTouchPoint(relativeTo != null ? relativeTo : element).Position.Y),
Source = e.Source,
OriginalSource = e.OriginalSource,
Handled = e.Handled,
GetPositionAction = (s) => { return e.GetTouchPoint(s).Position; },
TouchDevice = e.TouchDevice,
};
handler(element, args);
e.Handled = args.Handled;
}
else
{
touchReleased = false;
}
};
//element.PreviewTouchUp += previewTouchHandler;
element.AddHandler(FrameworkElement.PreviewTouchUpEvent, previewTouchHandler);
EventHandler previewTouchDownHandler = (_, __) =>
{
touchReleased = false;
mouseReleased = false;
};
//element.PreviewTouchDown += previewTouchDownHandler;
element.AddHandler(FrameworkElement.PreviewTouchDownEvent, previewTouchDownHandler);
}
///
/// Registers for preview mouse or touch up.
///
/// The element.
/// The handler.
public static void RegisterForPreviewMouseOrTouchUp(this FrameworkElement element, EventHandler handler)
{
RegisterForPreviewMouseOrTouchUp(element, null, handler);
}
///
/// Registers for mouse or touch move.
///
/// The element.
/// The relative to.
/// The handler.
public static void RegisterForMouseOrTouchMove(this FrameworkElement element, FrameworkElement relativeTo, EventHandler handler)
{
bool _isTouch = false;
MouseEventHandler mouseHandler = (x, e) =>
{
if (!_isTouch)
{
var args = new MouseOrTouchEventArgs()
{
Location = new Point(e.GetPosition(relativeTo != null ? relativeTo : element).X, e.GetPosition(relativeTo != null ? relativeTo : element).Y),
Source = e.Source,
OriginalSource = e.OriginalSource,
Handled = e.Handled,
GetPositionAction = e.GetPosition
};
handler(element, args);
e.Handled = args.Handled;
}
};
//element.MouseMove += mouseHandler;
element.AddHandler(FrameworkElement.MouseMoveEvent, mouseHandler);
EventHandler touchHandler = (x, e) =>
{
_isTouch = true;
var args = new MouseOrTouchEventArgs()
{
Location = new Point(e.GetTouchPoint(relativeTo != null ? relativeTo : element).Position.X, e.GetTouchPoint(relativeTo != null ? relativeTo : element).Position.Y),
Source = e.Source,
OriginalSource = e.OriginalSource,
Handled = e.Handled,
GetPositionAction = (s) => { return e.GetTouchPoint(s).Position; },
TouchDevice = e.TouchDevice,
};
handler(element, args);
e.Handled = args.Handled;
};
//element.TouchMove += touchHandler;
element.AddHandler(FrameworkElement.TouchMoveEvent, touchHandler);
}
///
/// Registers for mouse or touch move.
///
/// The element.
/// The handler.
public static void RegisterForMouseOrTouchMove(this FrameworkElement element, EventHandler handler)
{
RegisterForMouseOrTouchMove(element, null, handler);
}
///
/// Registers for mouse or stylus move.
///
/// The element.
/// The relative to.
/// The handler.
public static void RegisterForMouseOrStylusMove(this FrameworkElement element, FrameworkElement relativeTo, EventHandler handler)
{
bool _isTouch = false;
MouseEventHandler mouseHandler = (x, e) =>
{
if (!_isTouch)
{
var args = new MouseOrTouchEventArgs()
{
Location = new Point(e.GetPosition(relativeTo != null ? relativeTo : element).X, e.GetPosition(relativeTo != null ? relativeTo : element).Y),
Source = e.Source,
OriginalSource = e.OriginalSource,
Handled = e.Handled,
GetPositionAction = e.GetPosition
};
handler(element, args);
e.Handled = args.Handled;
if (Mouse.LeftButton == MouseButtonState.Pressed)
{
var a = 5;
}
}
};
//element.MouseMove += mouseHandler;
element.AddHandler(FrameworkElement.MouseMoveEvent, mouseHandler);
StylusEventHandler touchHandler = (x, e) =>
{
_isTouch = true;
var args = new MouseOrTouchEventArgs()
{
Location = new Point(e.GetPosition(relativeTo != null ? relativeTo : element).X, e.GetPosition(relativeTo != null ? relativeTo : element).Y),
Source = e.Source,
OriginalSource = e.OriginalSource,
Handled = e.Handled,
GetPositionAction = (s) => { return e.GetPosition(s); },
StylusDevice = e.StylusDevice,
};
handler(element, args);
e.Handled = args.Handled;
};
//element.TouchMove += touchHandler;
element.AddHandler(FrameworkElement.StylusMoveEvent, touchHandler);
}
///
/// Registers for mouse or stylus move.
///
/// The element.
/// The handler.
public static void RegisterForMouseOrStylusMove(this FrameworkElement element, EventHandler handler)
{
RegisterForMouseOrStylusMove(element, null, handler);
}
///
/// Registers for mouse or stylus move.
///
/// The element.
/// The relative to.
/// The handler.
public static void RegisterForPreviewMouseOrStylusMove(this FrameworkElement element, FrameworkElement relativeTo, EventHandler handler)
{
bool _isTouch = false;
MouseEventHandler mouseHandler = (x, e) =>
{
if (!_isTouch)
{
var args = new MouseOrTouchEventArgs()
{
Location = new Point(e.GetPosition(relativeTo != null ? relativeTo : element).X, e.GetPosition(relativeTo != null ? relativeTo : element).Y),
Source = e.Source,
OriginalSource = e.OriginalSource,
Handled = e.Handled,
GetPositionAction = e.GetPosition
};
handler(element, args);
e.Handled = args.Handled;
if (Mouse.LeftButton == MouseButtonState.Pressed)
{
var a = 5;
}
}
};
//element.MouseMove += mouseHandler;
element.AddHandler(FrameworkElement.PreviewMouseMoveEvent, mouseHandler);
StylusEventHandler touchHandler = (x, e) =>
{
_isTouch = true;
var args = new MouseOrTouchEventArgs()
{
Location = new Point(e.GetPosition(relativeTo != null ? relativeTo : element).X, e.GetPosition(relativeTo != null ? relativeTo : element).Y),
Source = e.Source,
OriginalSource = e.OriginalSource,
Handled = e.Handled,
GetPositionAction = (s) => { return e.GetPosition(s); },
StylusDevice = e.StylusDevice,
};
handler(element, args);
e.Handled = args.Handled;
};
//element.TouchMove += touchHandler;
element.AddHandler(FrameworkElement.StylusMoveEvent, touchHandler);
}
///
/// Registers for mouse or stylus move.
///
/// The element.
/// The handler.
public static void RegisterForPreviewMouseOrStylusMove(this FrameworkElement element, EventHandler handler)
{
RegisterForPreviewMouseOrStylusMove(element, null, handler);
}
#endregion
#region Loaded
///
/// Registers for the element loaded event. if the element is already loaded will invoke the handler immediately.
///
/// The element.
/// The handler.
public static void RegisterForLoadedOrNow(this FrameworkElement element, EventHandler handler)
{
if (element.IsLoaded)
{
handler(element, new EventArgs());
}
else
{
bool isLoaded = false;
element.AddHandler(FrameworkElement.LoadedEvent, new RoutedEventHandler((x, y) =>
{
if (!isLoaded)
{
isLoaded = true;
handler(element, new EventArgs());
}
}));
}
}
#endregion
#region Visual Tree
///
/// A recursive search for a child of type T in memory and not on logical/visual tree.
///
///
/// The element.
///
public static T FindChildOffline(this FrameworkElement element) where T : DependencyObject
{
if (element == null) return null;
PropertyInfo contentProp = element.GetType().GetProperty("Child");
if (contentProp == null)
{
contentProp = element.GetType().GetProperty("Content");
}
if (contentProp != null)
{
var value = contentProp.GetValue(element);
if (value != null)
{
if (value.GetType() == typeof(T))
{
return (T)value;
}
else
{
return FindChildOffline(value as FrameworkElement);
}
}
}
if (element is Panel)
{
foreach (var child in (element as Panel).Children.OfType())
{
if (child.GetType() == typeof(T))
{
return child as T;
}
else
{
var result = FindChildOffline(child);
if (result != null)
{
return result;
}
}
}
}
var contentAtt = element.GetType().GetCustomAttribute();
if (contentAtt != null)
{
contentProp = element.GetType().GetProperty(contentAtt.Name);
if (contentProp != null)
{
var content = contentProp.GetValue(element);
if (content != null)
{
if (content is IEnumerable)
{
foreach (var child in (content as IEnumerable))
{
if (child.GetType() == typeof(T))
{
return child as T;
}
else
{
var result = FindChildOffline(child as FrameworkElement);
if (result != null)
{
return result;
}
}
}
}
else
{
var result = FindChildOffline(content as FrameworkElement);
if (result != null)
{
return result;
}
}
}
}
}
return null;
}
#endregion
#region Bitmaps
///
/// Creates a bitmap source from the framework element.
///
/// The element.
///
public static RenderTargetBitmap TakeSnapshot(this FrameworkElement element)
{
int nWidth = (int)Math.Ceiling(element.ActualWidth);
int nHeight = (int)Math.Ceiling(element.ActualHeight);
RenderTargetBitmap oTargetBitmap = new RenderTargetBitmap(
nWidth,
nHeight,
96,
96,
PixelFormats.Pbgra32
);
DrawingVisual oDrawingVisual = new DrawingVisual();
using (DrawingContext oDrawingContext = oDrawingVisual.RenderOpen())
{
VisualBrush oVisualBrush = new VisualBrush(element) { Stretch = Stretch.Fill };
oDrawingContext.DrawRectangle(
oVisualBrush,
null,
new Rect(
new Point(),
new Size(nWidth, nHeight)
)
);
oDrawingContext.Close();
oTargetBitmap.Render(oDrawingVisual);
}
return oTargetBitmap;
}
#endregion
#region Animations
///
/// Starts a double animation on the specified property.
///
/// The element.
/// The property.
/// The duration.
/// The acceleration.
/// The deceleration.
/// The on complete.
///
public static DoubleAnimation StartDoubleAnimation(this FrameworkElement element, DependencyProperty property, TimeSpan duration, double to, double? from = null, double? acceleration = null, double? deceleration = null, Action onComplete = null, bool autoReverse = false)
{
DoubleAnimation ani = new DoubleAnimation();
ani.Duration = duration;
ani.AutoReverse = autoReverse;
if (acceleration.HasValue)
{
ani.AccelerationRatio = acceleration.Value;
}
if (deceleration.HasValue)
{
ani.DecelerationRatio = deceleration.Value;
}
if (ani.From.HasValue)
{
ani.From = from.Value;
}
ani.To = to;
ani.Completed += (x, y) => onComplete?.Invoke();
element.BeginAnimation(property, ani);
return ani;
}
#endregion
#region Size
///
/// Ensures the element has height other than NaN. If the element height equals NaN, the method will assign ActualHeight to Height.
///
/// The element.
public static void EnsureHeight(this FrameworkElement element)
{
if (double.IsNaN(element.Height))
{
element.Height = element.ActualHeight;
}
}
#endregion
}