aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/InsufficientLiquidQuantityView.xaml
blob: ad1c2ece398de584c60be5b0184de0dab83137d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<UserControl x:Class="Tango.PPC.UI.Dialogs.InsufficientLiquidQuantityView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:touch="clr-namespace:Tango.Touch.Controls;assembly=Tango.Touch"
             xmlns:local="clr-namespace:Tango.PPC.UI.Dialogs"
             mc:Ignorable="d" 
             Background="{StaticResource TangoPrimaryBackgroundBrush}" Width="700" Height="800" d:DataContext="{d:DesignInstance Type=local:InsufficientLiquidQuantityViewVM, IsDesignTimeCreatable=False}">
    <Grid Margin="20">
        <DockPanel>
            <Grid DockPanel.Dock="Bottom">
                <touch:TouchButton HorizontalAlignment="Right" CornerRadius="25" Command="{Binding OKCommand}" Style="{StaticResource TangoHollowButton}" Width="150" Height="50" VerticalAlignment="Bottom">CLOSE</touch:TouchButton>
            </Grid>
            <StackPanel DockPanel.Dock="Top">
                <Image Source="/Images/cartridge_validation.png" RenderOptions.BitmapScalingMode="Fant" Stretch="Uniform" Height="120"></Image>
                <TextBlock HorizontalAlignment="Center" Margin="0 20 0 0" FontSize="{StaticResource TangoHeaderFontSize}">Insufficient Ink Level</TextBlock>
                <TextBlock Margin="20 10" HorizontalAlignment="Center" TextWrapping="Wrap" TextAlignment="Center">
                    <Run>There seems to be an insufficient ink levels in one or more of the following dispensers.</Run>
                    <Run>The job cannot be completed.</Run>
                </TextBlock>
            </StackPanel>
            <Grid VerticalAlignment="Top" Margin="0 30 0 0">
                <ItemsControl ItemsSource="{Binding Exception.IdsPackLevels}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel HorizontalAlignment="Left" VerticalAlignment="Center" Orientation="Vertical" IsItemsHost="True"></StackPanel>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Grid Margin="0 0 0 4">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="40" />
                                    <ColumnDefinition Width="160" />
                                    <ColumnDefinition Width="1*" />
                                </Grid.ColumnDefinitions>
                                <touch:TouchIcon  VerticalAlignment="Center" Width="24" Height="24">
                                    <touch:TouchIcon.Style>
                                        <Style TargetType="touch:TouchIcon">
                                            <Setter Property="Icon" Value="Check"></Setter>
                                            <Setter Property="Foreground" Value="{StaticResource TangoGreenBrush}"></Setter>
                                            <Style.Triggers>
                                                <DataTrigger Binding="{Binding IsValid}" Value="False">
                                                    <Setter Property="Icon" Value="Alert"></Setter>
                                                    <Setter Property="Foreground" Value="{StaticResource TangoWarningBrush}"></Setter>
                                                </DataTrigger>
                                                <DataTrigger Binding="{Binding IsOverMax}" Value="True">
                                                    <Setter Property="Icon" Value="AlertOctagon"></Setter>
                                                    <Setter Property="Foreground" Value="{StaticResource TangoRedBrush}"></Setter>
                                                </DataTrigger>
                                                <MultiDataTrigger>
                                                    <MultiDataTrigger.Conditions>
                                                        <Condition Binding="{Binding IsValid}" Value="True" />
                                                        <Condition Binding="{Binding IsOverMax}" Value="False" />
                                                    </MultiDataTrigger.Conditions>
                                                    <Setter Property="Icon" Value="Check"></Setter>
                                                    <Setter Property="Foreground" Value="{StaticResource TangoGreenBrush}"></Setter>
                                                </MultiDataTrigger>
                                            </Style.Triggers>
                                        </Style>
                                    </touch:TouchIcon.Style>
                                </touch:TouchIcon>

                                <Border Grid.Column="1" Margin="5 0 0 0" Height="45" Width="150" CornerRadius="3" BorderThickness="1" BorderBrush="{StaticResource TangoLightBorderBrush}">
                                    <Grid>
                                        <Border VerticalAlignment="Center" CornerRadius="3" Loaded="IdsPackLoaded" MinHeight="45" HorizontalAlignment="Left" MinWidth="5">
                                            <Border.Background>
                                                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                                                    <GradientStop Offset="0.5" Color="{Binding IdsPack.LiquidType.LiquidTypeColor}" />
                                                    <GradientStop Offset="1" Color="#4EFFFFFF" />
                                                </LinearGradientBrush>
                                            </Border.Background>
                                        </Border>
                                        <Rectangle Loaded="Limit_Loaded" Stroke="{StaticResource TangoRedBrush}" StrokeThickness="2" HorizontalAlignment="Left">
                                            <Rectangle.Style>
                                                <Style TargetType="Rectangle">
                                                    <Style.Triggers>
                                                        <EventTrigger RoutedEvent="Loaded">
                                                            <EventTrigger.Actions>
                                                                <BeginStoryboard Name="str">
                                                                    <Storyboard>
                                                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Duration="00:00:01" RepeatBehavior="Forever">
                                                                            <DiscreteDoubleKeyFrame KeyTime="00:00:00" Value="1" />
                                                                            <DiscreteDoubleKeyFrame KeyTime="00:00:0.5" Value="0" />
                                                                        </DoubleAnimationUsingKeyFrames>
                                                                    </Storyboard>
                                                                </BeginStoryboard>
                                                            </EventTrigger.Actions>
                                                        </EventTrigger>
                                                        <EventTrigger RoutedEvent="Unloaded">
                                                            <EventTrigger.Actions>
                                                                <RemoveStoryboard BeginStoryboardName="str" />
                                                            </EventTrigger.Actions>
                                                        </EventTrigger>
                                                    </Style.Triggers>
                                                </Style>
                                            </Rectangle.Style>
                                        </Rectangle>


                                        <TextBlock FontSize="{StaticResource TangoSmallFontSize}" Foreground="{StaticResource TangoDarkForegroundBrush}" HorizontalAlignment="Center" Text="{Binding IdsPack.LiquidType.Name}" VerticalAlignment="Center">
                                            <TextBlock.Effect>
                                                <DropShadowEffect ShadowDepth="1" BlurRadius="1" Color="White" />
                                            </TextBlock.Effect>
                                        </TextBlock>

                                    </Grid>
                                </Border>
                                <TextBlock Grid.Column="2" HorizontalAlignment="Left" Text="{Binding Message}" VerticalAlignment="Center" Margin="20,0,0,0" TextWrapping="Wrap" FontSize="{StaticResource TangoSmallFontSize}" Foreground="{StaticResource TangoRedBrush}"></TextBlock>
                            </Grid>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </Grid>
        </DockPanel>
    </Grid>
</UserControl>
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

    /// <summary>
    /// Registers for mouse or touch down.
    /// </summary>
    /// <param name="element">The element.</param>
    /// <param name="relativeTo">The relative to.</param>
    /// <param name="handler">The handler.</param>
    public static void RegisterForMouseOrTouchDown(this FrameworkElement element, FrameworkElement relativeTo, EventHandler<MouseOrTouchEventArgs> 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<TouchEventArgs> 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 += (_, __) =>
        //{

        //};
    }

    /// <summary>
    /// Registers for mouse or touch down.
    /// </summary>
    /// <param name="element">The element.</param>
    /// <param name="handler">The handler.</param>
    public static void RegisterForMouseOrTouchDown(this FrameworkElement element, EventHandler<MouseOrTouchEventArgs> handler)
    {
        RegisterForMouseOrTouchDown(element, null, handler);
    }

    /// <summary>
    /// Registers for mouse or touch up.
    /// </summary>
    /// <param name="element">The element.</param>
    /// <param name="relativeTo">The relative to.</param>
    /// <param name="handler">The handler.</param>
    public static void RegisterForMouseOrTouchUp(this FrameworkElement element, FrameworkElement relativeTo, EventHandler<MouseOrTouchEventArgs> 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<TouchEventArgs> 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<TouchEventArgs> touchDownHandler = (_, __) =>
        {
            touchReleased = false;
            mouseReleased = false;
        };

        //element.TouchDown += touchDownHandler;
        element.AddHandler(FrameworkElement.TouchDownEvent, touchDownHandler);
    }

    /// <summary>
    /// Registers for mouse or touch up.
    /// </summary>
    /// <param name="element">The element.</param>
    /// <param name="handler">The handler.</param>
    public static void RegisterForMouseOrTouchUp(this FrameworkElement element, EventHandler<MouseOrTouchEventArgs> handler)
    {
        RegisterForMouseOrTouchUp(element, null, handler);
    }

    /// <summary>
    /// Registers for preview mouse or touch down.
    /// </summary>
    /// <param name="element">The element.</param>
    /// <param name="relativeTo">The relative to.</param>
    /// <param name="handler">The handler.</param>
    public static void RegisterForPreviewMouseOrTouchDown(this FrameworkElement element, FrameworkElement relativeTo, EventHandler<MouseOrTouchEventArgs> 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<TouchEventArgs> 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);
    }

    /// <summary>
    /// Registers for preview mouse or touch down.
    /// </summary>
    /// <param name="element">The element.</param>
    /// <param name="handler">The handler.</param>
    public static void RegisterForPreviewMouseOrTouchDown(this FrameworkElement element, EventHandler<MouseOrTouchEventArgs> handler)
    {
        RegisterForPreviewMouseOrTouchDown(element, null, handler);
    }

    /// <summary>
    /// Registers for preview mouse or touch up.
    /// </summary>
    /// <param name="element">The element.</param>
    /// <param name="relativeTo">The relative to.</param>
    /// <param name="handler">The handler.</param>
    public static void RegisterForPreviewMouseOrTouchUp(this FrameworkElement element, FrameworkElement relativeTo, EventHandler<MouseOrTouchEventArgs> 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<TouchEventArgs> 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<TouchEventArgs> previewTouchDownHandler = (_, __) =>
        {
            touchReleased = false;
            mouseReleased = false;
        };

        //element.PreviewTouchDown += previewTouchDownHandler;
        element.AddHandler(FrameworkElement.PreviewTouchDownEvent, previewTouchDownHandler);
    }

    /// <summary>
    /// Registers for preview mouse or touch up.
    /// </summary>
    /// <param name="element">The element.</param>
    /// <param name="handler">The handler.</param>
    public static void RegisterForPreviewMouseOrTouchUp(this FrameworkElement element, EventHandler<MouseOrTouchEventArgs> handler)
    {
        RegisterForPreviewMouseOrTouchUp(element, null, handler);
    }

    /// <summary>
    /// Registers for mouse or touch move.
    /// </summary>
    /// <param name="element">The element.</param>
    /// <param name="relativeTo">The relative to.</param>
    /// <param name="handler">The handler.</param>
    public static void RegisterForMouseOrTouchMove(this FrameworkElement element, FrameworkElement relativeTo, EventHandler<MouseOrTouchEventArgs> 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<TouchEventArgs> 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);
    }

    /// <summary>
    /// Registers for mouse or touch move.
    /// </summary>
    /// <param name="element">The element.</param>
    /// <param name="handler">The handler.</param>
    public static void RegisterForMouseOrTouchMove(this FrameworkElement element, EventHandler<MouseOrTouchEventArgs> handler)
    {
        RegisterForMouseOrTouchMove(element, null, handler);
    }

    /// <summary>
    /// Registers for mouse or stylus move.
    /// </summary>
    /// <param name="element">The element.</param>
    /// <param name="relativeTo">The relative to.</param>
    /// <param name="handler">The handler.</param>
    public static void RegisterForMouseOrStylusMove(this FrameworkElement element, FrameworkElement relativeTo, EventHandler<MouseOrTouchEventArgs> 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);
    }

    /// <summary>
    /// Registers for mouse or stylus move.
    /// </summary>
    /// <param name="element">The element.</param>
    /// <param name="handler">The handler.</param>
    public static void RegisterForMouseOrStylusMove(this FrameworkElement element, EventHandler<MouseOrTouchEventArgs> handler)
    {
        RegisterForMouseOrStylusMove(element, null, handler);
    }

    /// <summary>
    /// Registers for mouse or stylus move.
    /// </summary>
    /// <param name="element">The element.</param>
    /// <param name="relativeTo">The relative to.</param>
    /// <param name="handler">The handler.</param>
    public static void RegisterForPreviewMouseOrStylusMove(this FrameworkElement element, FrameworkElement relativeTo, EventHandler<MouseOrTouchEventArgs> 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);
    }

    /// <summary>
    /// Registers for mouse or stylus move.
    /// </summary>
    /// <param name="element">The element.</param>
    /// <param name="handler">The handler.</param>
    public static void RegisterForPreviewMouseOrStylusMove(this FrameworkElement element, EventHandler<MouseOrTouchEventArgs> handler)
    {
        RegisterForPreviewMouseOrStylusMove(element, null, handler);
    }

    #endregion

    #region Loaded

    /// <summary>
    /// Registers for the element loaded event. if the element is already loaded will invoke the handler immediately.
    /// </summary>
    /// <param name="element">The element.</param>
    /// <param name="handler">The handler.</param>
    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
    /// <summary>
    /// A recursive search for a child of type T in memory and not on logical/visual tree.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="element">The element.</param>
    /// <returns></returns>
    public static T FindChildOffline<T>(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<T>(value as FrameworkElement);
                }
            }
        }

        if (element is Panel)
        {
            foreach (var child in (element as Panel).Children.OfType<FrameworkElement>())
            {
                if (child.GetType() == typeof(T))
                {
                    return child as T;
                }
                else
                {
                    var result = FindChildOffline<T>(child);

                    if (result != null)
                    {
                        return result;
                    }
                }
            }
        }

        var contentAtt = element.GetType().GetCustomAttribute<ContentPropertyAttribute>();

        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<T>(child as FrameworkElement);

                                if (result != null)
                                {
                                    return result;
                                }
                            }
                        }
                    }
                    else
                    {
                        var result = FindChildOffline<T>(content as FrameworkElement);

                        if (result != null)
                        {
                            return result;
                        }
                    }
                }
            }
        }

        return null;
    }
    #endregion

    #region Bitmaps

    /// <summary>
    /// Creates a bitmap source from the framework element.
    /// </summary>
    /// <param name="element">The element.</param>
    /// <returns></returns>
    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

    /// <summary>
    /// Starts a double animation on the specified property.
    /// </summary>
    /// <param name="element">The element.</param>
    /// <param name="property">The property.</param>
    /// <param name="duration">The duration.</param>
    /// <param name="acceleration">The acceleration.</param>
    /// <param name="deceleration">The deceleration.</param>
    /// <param name="onComplete">The on complete.</param>
    /// <returns></returns>
    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

    /// <summary>
    /// Ensures the element has height other than NaN. If the element height equals NaN, the method will assign ActualHeight to Height.
    /// </summary>
    /// <param name="element">The element.</param>
    public static void EnsureHeight(this FrameworkElement element)
    {
        if (double.IsNaN(element.Height))
        {
            element.Height = element.ActualHeight;
        }
    }

    #endregion
}