Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
455 changes: 450 additions & 5 deletions .editorconfig

Large diffs are not rendered by default.

220 changes: 82 additions & 138 deletions src/FlaUInspect/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Windows;
using FlaUInspect.Core;
using FlaUInspect.Core.Logger;
Expand All @@ -13,141 +12,86 @@ namespace FlaUInspect;

public partial class App {

public static IServiceProvider Services { get; private set; } = null!;
public static FlaUiAppOptions FlaUiAppOptions { get; } = new ();

public static InternalLogger Logger { get; } = new ();

protected override void OnStartup(StartupEventArgs e) {
base.OnStartup(e);

ServiceCollection services = new ();
services.AddSingleton<ISettingsService<FlaUiAppSettings>>(_ => new JsonSettingsService<FlaUiAppSettings>(Path.Combine(AppContext.BaseDirectory, $"appsettings.json")));
Services = services.BuildServiceProvider();

ISettingsService<FlaUiAppSettings> settingsService = Services.GetRequiredService<ISettingsService<FlaUiAppSettings>>();
FlaUiAppSettings flaUiAppSettings = settingsService.Load();
ApplyAppOption(flaUiAppSettings);

//InternalLogger logger = new ();
Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
StartupViewModel startupViewModel = new ();
StartupWindow startupWindow = new (Logger) { DataContext = startupViewModel };
Current.MainWindow = startupWindow;
startupWindow.Show();

//Preload light theme
SetTheme(flaUiAppSettings);

Task.Run(() => startupViewModel.Init());

return;
AssemblyFileVersionAttribute? versionAttribute = Assembly.GetEntryAssembly()?.GetCustomAttribute(typeof(AssemblyFileVersionAttribute)) as AssemblyFileVersionAttribute;
string applicationVersion = versionAttribute?.Version ?? "N/A";
string windowHandle = string.Empty;

if (e.Args.Length > 0) {
windowHandle = e.Args[0];
}

#if AUTOMATION_UIA3
MainViewModel mainViewModel = new (AutomationType.UIA3, applicationVersion, windowHandle, logger);
MainWindow mainWindow = new () { DataContext = mainViewModel };

//Re-enable normal shutdown mode.
Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
Current.MainWindow = mainWindow;
mainWindow.Show();
#elif AUTOMATION_UIA2
MainViewModel mainViewModel = new (AutomationType.UIA2, applicationVersion, windowHandle, logger);
MainWindow mainWindow = new() { DataContext = mainViewModel };

//Re-enable normal shutdown mode.
Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
Current.MainWindow = mainWindow;
mainWindow.Show();
#else
// Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
// ChooseVersionWindow dialog = new ();
//
// if (dialog.ShowDialog() == true) {
//
// MainViewModel mainViewModel = new (dialog.SelectedAutomationType, applicationVersion, windowHandle, Logger);
// MainWindow mainWindow = new () { DataContext = mainViewModel };
//
// //Re-enable normal shutdown mode.
// Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
// Current.MainWindow = mainWindow;
// mainWindow.Show();
// }
#endif
}

public static void ApplyAppOption(FlaUiAppSettings settings) {
// Apply theme
Current.Dispatcher.Invoke(() => {
SetTheme(settings);
});

ThicknessConverter converter = new ();
FlaUiAppSettings cloneSetting = settings.Clone() as FlaUiAppSettings;

if (settings.HoverOverlay != null) {
Thickness hoverMargin = (Thickness)converter.ConvertFromString(cloneSetting.HoverOverlay.Margin);
FlaUiAppOptions.HoverOverlay = () => new ElementOverlay(
new ElementOverlayConfiguration(cloneSetting.HoverOverlay.Size,
hoverMargin,
ColorTranslator.FromHtml(cloneSetting.HoverOverlay.OverlayColor),
ElementOverlay.GetRectangleFactory(cloneSetting.HoverOverlay.OverlayMode)));
} else {
FlaUiAppOptions.HoverOverlay = FlaUiAppOptions.DefaultOverlay;
}

if (settings.SelectionOverlay != null) {
Thickness selectionMargin = (Thickness)converter.ConvertFromString(cloneSetting.SelectionOverlay.Margin);
FlaUiAppOptions.SelectionOverlay = () => new ElementOverlay(
new ElementOverlayConfiguration(cloneSetting.SelectionOverlay.Size,
selectionMargin,
ColorTranslator.FromHtml(cloneSetting.SelectionOverlay.OverlayColor),
ElementOverlay.GetRectangleFactory(cloneSetting.SelectionOverlay.OverlayMode)));
} else {
FlaUiAppOptions.SelectionOverlay = FlaUiAppOptions.DefaultOverlay;
}

if (settings.PickOverlay != null) {
Thickness pickMargin = (Thickness)converter.ConvertFromString(cloneSetting.PickOverlay.Margin);
FlaUiAppOptions.PickOverlay = () => new ElementOverlay(
new ElementOverlayConfiguration(cloneSetting.PickOverlay.Size,
pickMargin,
ColorTranslator.FromHtml(cloneSetting.PickOverlay.OverlayColor),
ElementOverlay.GetRectangleFactory(cloneSetting.PickOverlay.OverlayMode)));
} else {
FlaUiAppOptions.PickOverlay = FlaUiAppOptions.DefaultOverlay;
}
}

private static void SetTheme(FlaUiAppSettings settings) {
ResourceDictionary newTheme = new();

switch (settings.Theme) {
case "Dark":
newTheme.Source = new Uri("/FlaUInspect;component/Themes/DarkTheme.xaml", UriKind.Relative);
break;
default:
newTheme.Source = new Uri("/FlaUInspect;component/Themes/LightTheme.xaml", UriKind.Relative);
break;
}

// Remove existing theme dictionaries
for (int i = Current.Resources.MergedDictionaries.Count - 1; i >= 0; i--) {
ResourceDictionary dict = Current.Resources.MergedDictionaries[i];

if (dict.Source != null && (dict.Source.OriginalString.Contains("Themes/DarkTheme.xaml") || dict.Source.OriginalString.Contains("Themes/LightTheme.xaml"))) {
Current.Resources.MergedDictionaries.RemoveAt(i);
}
}

// Add the new theme dictionary
Current.Resources.MergedDictionaries.Add(newTheme);
}
public static IServiceProvider Services { get; private set; } = null!;
public static FlaUiAppOptions FlaUiAppOptions { get; } = new();

public static InternalLogger Logger { get; } = new();

protected override async void OnStartup(StartupEventArgs e) {
base.OnStartup(e);

ServiceCollection services = new();
_ = services.AddSingleton<ISettingsService<FlaUiAppSettings>>(_ => new JsonSettingsService<FlaUiAppSettings>(Path.Combine(AppContext.BaseDirectory, $"appsettings.json")));
Services = services.BuildServiceProvider();

var settingsService = Services.GetRequiredService<ISettingsService<FlaUiAppSettings>>();
var flaUiAppSettings = settingsService.Load();
ApplyAppOption(flaUiAppSettings);

//InternalLogger logger = new ();
Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
StartupViewModel startupViewModel = new();
StartupWindow startupWindow = new(Logger) { DataContext = startupViewModel };
Current.MainWindow = startupWindow;
startupWindow.Show();

//Preload light theme
SetTheme(flaUiAppSettings);

await Task.Run(startupViewModel.Init);
}

public static void ApplyAppOption(FlaUiAppSettings settings) {
// Apply theme
Current.Dispatcher.Invoke(() => SetTheme(settings));

if (settings is null) return;

ThicknessConverter converter = new();
var cloneSetting = (FlaUiAppSettings)settings.Clone();

FlaUiAppOptions.HoverOverlay = cloneSetting.HoverOverlay != null
? (() => new ElementOverlay(
new ElementOverlayConfiguration(cloneSetting.HoverOverlay.Size,
(Thickness)(converter.ConvertFromString(cloneSetting.HoverOverlay.Margin) ?? new()),
ColorTranslator.FromHtml(cloneSetting.HoverOverlay.OverlayColor),
ElementOverlay.GetRectangleFactory(cloneSetting.HoverOverlay.OverlayMode))))
: FlaUiAppOptions.DefaultOverlay;

FlaUiAppOptions.SelectionOverlay = cloneSetting.SelectionOverlay != null
? (() => new ElementOverlay(
new ElementOverlayConfiguration(cloneSetting.SelectionOverlay.Size,
(Thickness)(converter.ConvertFromString(cloneSetting.SelectionOverlay.Margin) ?? new()),
ColorTranslator.FromHtml(cloneSetting.SelectionOverlay.OverlayColor),
ElementOverlay.GetRectangleFactory(cloneSetting.SelectionOverlay.OverlayMode))))
: FlaUiAppOptions.DefaultOverlay;

FlaUiAppOptions.PickOverlay = cloneSetting.PickOverlay != null
? (() => new ElementOverlay(
new ElementOverlayConfiguration(cloneSetting.PickOverlay.Size,
(Thickness)(converter.ConvertFromString(cloneSetting.PickOverlay.Margin) ?? new()),
ColorTranslator.FromHtml(cloneSetting.PickOverlay.OverlayColor),
ElementOverlay.GetRectangleFactory(cloneSetting.PickOverlay.OverlayMode))))
: FlaUiAppOptions.DefaultOverlay;
}

private static void SetTheme(FlaUiAppSettings settings) {
ResourceDictionary newTheme = new() {
Source = settings.Theme switch {
"Dark" => new Uri("/FlaUInspect;component/Themes/DarkTheme.xaml", UriKind.Relative),
_ => new Uri("/FlaUInspect;component/Themes/LightTheme.xaml", UriKind.Relative),
}
};

// Remove existing theme dictionaries
for (var i = Current.Resources.MergedDictionaries.Count - 1; i >= 0; i--) {
var dict = Current.Resources.MergedDictionaries[i];

if (dict.Source != null && (dict.Source.OriginalString.Contains("Themes/DarkTheme.xaml") || dict.Source.OriginalString.Contains("Themes/LightTheme.xaml")))
Current.Resources.MergedDictionaries.RemoveAt(i);
}

// Add the new theme dictionary
Current.Resources.MergedDictionaries.Add(newTheme);
}
}
8 changes: 4 additions & 4 deletions src/FlaUInspect/Controls/CheckBoxes.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@
<SolidColorBrush x:Key="OptionMark.Disabled.Background" Color="{DynamicResource PrimaryDisabledColor}"/>
<SolidColorBrush x:Key="OptionMark.Disabled.Border" Color="{DynamicResource DisabledTextColor}"/>
<SolidColorBrush x:Key="OptionMark.Disabled.Glyph" Color="{DynamicResource DisabledTextColor}"/>

<Style TargetType="{x:Type CheckBox}"
BasedOn="{StaticResource {x:Type CheckBox}}">
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}" />
<Setter Property="Background" Value="{StaticResource PrimaryBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource PrimaryBorderBrush}" />
<Setter Property="FocusVisualStyle" Value="{DynamicResource FocusVisual}" />
<Setter Property="Background" Value="{DynamicResource PrimaryBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource PrimaryBorderBrush}" />
<Setter Property="Foreground" Value="{DynamicResource TextBrush}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Template">
Expand Down
102 changes: 51 additions & 51 deletions src/FlaUInspect/Controls/TextBoxes.xaml
Original file line number Diff line number Diff line change
@@ -1,54 +1,54 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<Style BasedOn="{StaticResource {x:Type TextBox}}"
TargetType="TextBox">
<Setter Property="Background" Value="{DynamicResource PrimaryBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource PrimaryBorderBrush}" />
<Setter Property="Foreground" Value="{DynamicResource TextBrush}" />
<Setter Property="BorderThickness" Value="{DynamicResource PrimaryThickness}" />
<Setter Property="KeyboardNavigation.TabNavigation" Value="None" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="AllowDrop" Value="true" />
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst" />
<Setter Property="Stylus.IsFlicksEnabled" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{DynamicResource PrimaryCornerRadius}"
SnapsToDevicePixels="True">
<ScrollViewer x:Name="PART_ContentHost"
Focusable="false"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="border" Property="Opacity" Value="0.56" />
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource PrimaryHoverBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter TargetName="border" Property="BorderBrush" Value="{StaticResource SecondaryBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsInactiveSelectionHighlightEnabled" Value="true" />
<Condition Property="IsSelectionActive" Value="false" />
</MultiTrigger.Conditions>
<Setter Property="SelectionBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}" />
</MultiTrigger>
</Style.Triggers>
</Style>
<Style BasedOn="{StaticResource {x:Type TextBox}}"
TargetType="TextBox">
<Setter Property="Background" Value="{DynamicResource PrimaryBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource PrimaryBorderBrush}" />
<Setter Property="Foreground" Value="{DynamicResource TextBrush}" />
<Setter Property="BorderThickness" Value="{DynamicResource PrimaryThickness}" />
<Setter Property="KeyboardNavigation.TabNavigation" Value="None" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="AllowDrop" Value="true" />
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst" />
<Setter Property="Stylus.IsFlicksEnabled" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{DynamicResource PrimaryCornerRadius}"
SnapsToDevicePixels="True">
<ScrollViewer x:Name="PART_ContentHost"
Focusable="false"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="border" Property="Opacity" Value="0.56" />
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource PrimaryHoverBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource SecondaryBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsInactiveSelectionHighlightEnabled" Value="true" />
<Condition Property="IsSelectionActive" Value="false" />
</MultiTrigger.Conditions>
<Setter Property="SelectionBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}" />
</MultiTrigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
Loading