Skip to content

Commit

Permalink
Add IsEnabled property
Browse files Browse the repository at this point in the history
Fixe From NaN value
  • Loading branch information
Seuleuzeuh committed Aug 20, 2020
1 parent 5ba3bd8 commit c49a3b9
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 60 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ Simple TabTip / Virtual Keyboard integration for WPF apps with touchscreen and/o

## Package

Available via [nuget](https://www.nuget.org/packages/WPFTabTipMixedHardware/) ![Nuget](https://img.shields.io/nuget/v/WPFTabTipMixedHardware)
Available via [nuget](https://www.nuget.org/packages/WPFTabTipMixedHardware/) ![Nuget](https://img.shields.io/nuget/v/WPFTabTipMixedHardware) ![Nuget](https://img.shields.io/nuget/vpre/WPFTabTipMixedHardware)

## Getting started

You can bind TabTip automation logic to any `UIElement`. Virtual Keyboard will open when any such element will get touched/clicker/focused, and it will close when element will lose focus. Not only that, but `TabTipAutomation` will move `UIElement` (or `Window`) into view, so that TabTip will not block focused element.
Expand Down
47 changes: 33 additions & 14 deletions UITest/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,44 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:UITest"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="525"
Height="350"
mc:Ignorable="d">
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<RichTextBox Grid.ColumnSpan="3" InputScope="Url"/>
<Button Grid.Row="1" Content="Do Nothing"/>
<Button Grid.Row="1" x:Name="btn_NewWindow" Content="New Window" Grid.Column="1" Click="btn_NewWindow_OnClick"/>
<Button Grid.Row="1" x:Name="btn_KeyboardDescriptions" Content="Get Keyboard Descriptions" Grid.Column="2" Click="btn_KeyboardDescriptions_OnClick"/>
<TextBox Grid.Row="2" Grid.ColumnSpan="3" InputScope="Number"/>
<RichTextBox Grid.ColumnSpan="3"
InputScope="Url" />
<Button Grid.Row="1"
Content="Do Nothing" />
<Button x:Name="btn_NewWindow"
Grid.Row="1"
Grid.Column="1"
Click="btn_NewWindow_OnClick"
Content="New Window" />
<Button x:Name="btn_KeyboardDescriptions"
Grid.Row="1"
Grid.Column="2"
Click="btn_KeyboardDescriptions_OnClick"
Content="Get Keyboard Descriptions" />
<TextBox Grid.Row="2"
Grid.ColumnSpan="3"
InputScope="Number" />
<CheckBox Grid.Row="3"
Click="CheckBox_Click"
Content="TabTipAutomation Enabled"
IsChecked="True" />
</Grid>
</Window>
9 changes: 9 additions & 0 deletions UITest/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public MainWindow()
{
InitializeComponent();

TabTipAutomation.AutomationTriggers = TabTipAutomationTrigger.OnMouse | TabTipAutomationTrigger.OnTouch;
TabTipAutomation.BindTo<TextBox>();
TabTipAutomation.BindTo<RichTextBox>();
TabTipAutomation.ExceptionCatched += TabTipAutomationOnTest;
Expand Down Expand Up @@ -56,5 +57,13 @@ private static List<string> QueryWmiKeyboards()
private void btn_NewWindow_OnClick(object sender, RoutedEventArgs e) => new DialogWindow().Show();

private void btn_KeyboardDescriptions_OnClick(object sender, RoutedEventArgs e) => GetKeyboardDescriptions();

private void CheckBox_Click(object sender, RoutedEventArgs e)
{
if (sender is CheckBox checkBox)
{
checkBox.IsChecked = TabTipAutomation.IsEnabled = !TabTipAutomation.IsEnabled;
}
}
}
}
46 changes: 22 additions & 24 deletions WPFTabTip/Helpers/AnimationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -221,21 +221,17 @@ private static void MoveRootVisualBy(FrameworkElement rootVisual, double moveBy)
return;

Storyboard moveRootVisualStoryboard = GetOrCreateMoveRootVisualStoryboard(rootVisual);

DoubleAnimation doubleAnimation = moveRootVisualStoryboard.Children.First() as DoubleAnimation;

if (doubleAnimation != null)
if (moveRootVisualStoryboard.Children.First() is DoubleAnimation doubleAnimation)
{
Window window = rootVisual as Window;
if (window != null)
if (rootVisual is Window window)
{
doubleAnimation.From = window.Top;
doubleAnimation.To = window.Top + moveBy;
doubleAnimation.From = GetValidDoubleValue(window.Top);
doubleAnimation.To = GetValidDoubleValue(window.Top) + moveBy;
}
else
{
doubleAnimation.From = doubleAnimation.To ?? 0;
doubleAnimation.To = (doubleAnimation.To ?? 0) + moveBy;
doubleAnimation.From = GetValidDoubleValue(doubleAnimation.To);
doubleAnimation.To = GetValidDoubleValue(doubleAnimation.To) + moveBy;
}
}

Expand All @@ -245,27 +241,31 @@ private static void MoveRootVisualBy(FrameworkElement rootVisual, double moveBy)
private static void MoveRootVisualTo(FrameworkElement rootVisual, double moveTo)
{
Storyboard moveRootVisualStoryboard = GetOrCreateMoveRootVisualStoryboard(rootVisual);

DoubleAnimation doubleAnimation = moveRootVisualStoryboard.Children.First() as DoubleAnimation;

if (doubleAnimation != null)
if (moveRootVisualStoryboard.Children.FirstOrDefault() is DoubleAnimation doubleAnimation)
{
Window window = rootVisual as Window;
if (window != null)
if (rootVisual is Window window)
{
doubleAnimation.From = window.Top;
doubleAnimation.To = moveTo;
doubleAnimation.From = GetValidDoubleValue(window.Top);
doubleAnimation.To = GetValidDoubleValue(moveTo);
}
else
{
doubleAnimation.From = doubleAnimation.To ?? 0;
doubleAnimation.To = moveTo;
doubleAnimation.From = GetValidDoubleValue(doubleAnimation.To);
doubleAnimation.To = GetValidDoubleValue(moveTo);
}
}

moveRootVisualStoryboard.Begin();
}

private static double GetValidDoubleValue(double? from)
{
if (from.HasValue && from.Value != double.NaN)
return from.Value;

return 0;
}

internal static void GetUIElementInToWorkAreaWithTabTipOpened(UIElement element)
{
try
Expand All @@ -274,8 +274,7 @@ internal static void GetUIElementInToWorkAreaWithTabTipOpened(UIElement element)
Rectangle workAreaWithTabTipOpened = GetWorkAreaWithTabTipOpened(element);

Rectangle uiElementRectangle;
Window window = rootVisualForAnimation as Window;
if (window != null && workAreaWithTabTipOpened.Height >= window.Height)
if (rootVisualForAnimation is Window window && workAreaWithTabTipOpened.Height >= window.Height)
uiElementRectangle = GetWindowRectangle(window);
else
uiElementRectangle = GetUIElementRect(element);
Expand Down Expand Up @@ -307,9 +306,8 @@ internal static void GetEverythingInToWorkAreaWithTabTipClosed()
{
foreach (KeyValuePair<FrameworkElement, Storyboard> moveRootVisualStoryboard in MoveRootVisualStoryboards)
{
Window window = moveRootVisualStoryboard.Key as Window;
// if window exist also check if it has not been closed
if (window != null && new WindowInteropHelper(window).Handle != IntPtr.Zero)
if (moveRootVisualStoryboard.Key is Window window && new WindowInteropHelper(window).Handle != IntPtr.Zero)
MoveRootVisualBy(
rootVisual: window,
moveBy: GetYOffsetToMoveUIElementInToWorkArea(
Expand Down
41 changes: 25 additions & 16 deletions WPFTabTip/TabTipAutomation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ public static TabTipAutomationTrigger AutomationTriggers
/// </summary>
public static TimeSpan WaitBeforeCloseKeyboard { get; set; } = TimeSpan.FromMilliseconds(100);

/// <summary>
/// Describe the activation state of the TabTipAutomation functionnality.
/// Default value is True
/// </summary>
public static bool IsEnabled { get; set; } = true;

/// <summary>
/// Subscribe to this event if you want to know about exceptions (errors) in this library
/// </summary>
Expand Down Expand Up @@ -95,24 +101,27 @@ private static void AutomateTabTipClose(IObservable<Tuple<UIElement, bool>> focu

private static bool AnotherAuthorizedElementFocused()
{
try
if (IsEnabled)
{
IInputElement inputElement = null;
Application.Current?.Dispatcher?.Invoke(() =>
try
{
inputElement = Keyboard.FocusedElement;
});
IInputElement inputElement = null;
Application.Current?.Dispatcher?.Invoke(() =>
{
inputElement = Keyboard.FocusedElement;
});

if (inputElement is UIElement element)
if (inputElement is UIElement element)
{
var type = inputElement.GetType();
return BindedUIElements.Any(t => t == type || type.IsAssignableFrom(t) || t.IsAssignableFrom(type));
}
}
catch (Exception ex)
{
var type = inputElement.GetType();
return BindedUIElements.Any(t => t == type || type.IsAssignableFrom(t) || t.IsAssignableFrom(type));
ExceptionCatched?.Invoke(ex);
}
}
catch (Exception ex)
{
ExceptionCatched?.Invoke(ex);
}

return false;
}
Expand All @@ -130,7 +139,7 @@ private static void AutomateTabTipOpen(IObservable<Tuple<UIElement, bool>> focus

private static void TouchDownRoutedEventHandler(object sender, RoutedEventArgs eventArgs)
{
if (sender is UIElement element)
if (sender is UIElement element && IsEnabled)
{
System.Diagnostics.Debug.WriteLine($"TouchDownEvent on type {element.GetType()} from {element.ToString()}");
FocusSubject.OnNext(new Tuple<UIElement, bool>(element, true));
Expand Down Expand Up @@ -167,7 +176,7 @@ public static void BindTo<T>() where T : UIElement
routedEvent: UIElement.PreviewMouseDownEvent,
handler: new RoutedEventHandler((s, e) =>
{
if (s is UIElement element)
if (s is UIElement element && IsEnabled)
{
System.Diagnostics.Debug.WriteLine($"PreviewMouseDownEvent on type {element.GetType()} from {element.GetHashCode()} Source:{e.Source} OriginalSource:{e.OriginalSource}");
FocusSubject.OnNext(new Tuple<UIElement, bool>(element, true));
Expand All @@ -183,7 +192,7 @@ public static void BindTo<T>() where T : UIElement
routedEvent: UIElement.GotFocusEvent,
handler: new RoutedEventHandler((s, e) =>
{
if (s is UIElement element)
if (s is UIElement element && IsEnabled)
{
System.Diagnostics.Debug.WriteLine($"GotFocusEvent on type {element.GetType()} from {element.ToString()}");
FocusSubject.OnNext(new Tuple<UIElement, bool>(element, true));
Expand All @@ -197,7 +206,7 @@ public static void BindTo<T>() where T : UIElement
routedEvent: UIElement.LostFocusEvent,
handler: new RoutedEventHandler((s, e) =>
{
if (s is UIElement element)
if (s is UIElement element && IsEnabled)
{
System.Diagnostics.Debug.WriteLine($"LostFocusEvent on type {element.GetType()} from {element.ToString()}");
FocusSubject.OnNext(new Tuple<UIElement, bool>(element, false));
Expand Down
10 changes: 5 additions & 5 deletions WPFTabTip/WPFTabTipMixedHardware.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@
<PropertyGroup>
<TargetFrameworks>net47</TargetFrameworks>
<Title>WPFTabTipMixedHardware</Title>
<Version>1.3.2</Version>
<Version>1.3.3-alpha</Version>
<Copyright></Copyright>
<Description>Simple TabTip / Virtual Keyboard integration for WPF apps with mixed Keyboard and Touchscreen</Description>
<Authors>Morgan SOULLEZ</Authors>
<Company>Morgan SOULLEZ</Company>
<PackageProjectUrl>https://github.com/seuleuzeuh/WPFTabTipMixedhardware/</PackageProjectUrl>
<RepositoryUrl>https://github.com/seuleuzeuh/WPFTabTipMixedhardware/</RepositoryUrl>
<PackageTags>WPF Touchscreen TabTip Keyboard Virtual W10</PackageTags>
<PackageReleaseNotes>- Better configuration with new AutomationTriggers Property
- Fix exception occur during closing App</PackageReleaseNotes>
<AssemblyVersion>1.3.2</AssemblyVersion>
<FileVersion>1.3.2</FileVersion>
<PackageReleaseNotes>- Add IsEnabled property</PackageReleaseNotes>
<AssemblyVersion>1.3.3</AssemblyVersion>
<FileVersion>1.3.3</FileVersion>
<PackageLicenseFile>LICENSE.md</PackageLicenseFile>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Reactive.Core" Version="4.2.0" />
Expand Down

0 comments on commit c49a3b9

Please sign in to comment.