File scoped namespace

This commit is contained in:
2022-05-07 19:40:54 +02:00
parent b161ded92e
commit 9bf95ebe4e
126 changed files with 2562 additions and 2598 deletions

View File

@@ -1,89 +1,88 @@
using Avalonia.Input;
using FileTime.App.Core.Command;
namespace FileTime.GuiApp.Configuration
namespace FileTime.GuiApp.Configuration;
public class CommandBindingConfiguration
{
public class CommandBindingConfiguration
public List<KeyConfig> Keys { get; set; } = new List<KeyConfig>();
public Commands Command { get; set; } = Commands.None;
public string KeysDisplayText => GetKeysDisplayText();
public CommandBindingConfiguration() { }
public CommandBindingConfiguration(Commands command, IEnumerable<KeyConfig> keys)
{
public List<KeyConfig> Keys { get; set; } = new List<KeyConfig>();
Keys = new List<KeyConfig>(keys);
Command = command;
}
public Commands Command { get; set; } = Commands.None;
public CommandBindingConfiguration(Commands command, KeyConfig key)
{
Keys = new List<KeyConfig>() { key };
Command = command;
}
public string KeysDisplayText => GetKeysDisplayText();
public CommandBindingConfiguration(Commands command, IEnumerable<Key> keys)
{
Keys = keys.Select(k => new KeyConfig(k)).ToList();
Command = command;
}
public CommandBindingConfiguration() { }
public CommandBindingConfiguration(Commands command, Key key)
{
Keys = new List<KeyConfig>() { new KeyConfig(key) };
Command = command;
}
public CommandBindingConfiguration(Commands command, IEnumerable<KeyConfig> keys)
public string GetKeysDisplayText()
{
var s = "";
foreach (var k in Keys)
{
Keys = new List<KeyConfig>(keys);
Command = command;
}
var keyString = k.Key.ToString();
public CommandBindingConfiguration(Commands command, KeyConfig key)
{
Keys = new List<KeyConfig>() { key };
Command = command;
}
public CommandBindingConfiguration(Commands command, IEnumerable<Key> keys)
{
Keys = keys.Select(k => new KeyConfig(k)).ToList();
Command = command;
}
public CommandBindingConfiguration(Commands command, Key key)
{
Keys = new List<KeyConfig>() { new KeyConfig(key) };
Command = command;
}
public string GetKeysDisplayText()
{
var s = "";
foreach (var k in Keys)
if (keyString.Length == 1)
{
var keyString = k.Key.ToString();
if (keyString.Length == 1)
{
s += AddKeyWithCtrlOrAlt(k, s, (_, _, _) => k.Shift ? keyString.ToUpper() : keyString.ToLower());
}
else
{
s += AddKeyWithCtrlOrAlt(k, s, AddSpecialKey);
}
s += AddKeyWithCtrlOrAlt(k, s, (_, _, _) => k.Shift ? keyString.ToUpper() : keyString.ToLower());
}
else
{
s += AddKeyWithCtrlOrAlt(k, s, AddSpecialKey);
}
return s;
}
private static string AddKeyWithCtrlOrAlt(KeyConfig key, string currentText, Func<KeyConfig, string, bool, string> keyProcessor)
{
var s = "";
return s;
}
bool ctrlOrAlt = key.Ctrl || key.Alt;
private static string AddKeyWithCtrlOrAlt(KeyConfig key, string currentText, Func<KeyConfig, string, bool, string> keyProcessor)
{
var s = "";
if (ctrlOrAlt && currentText.Length > 0 && currentText.Last() != ' ') s += " ";
bool ctrlOrAlt = key.Ctrl || key.Alt;
if (key.Ctrl) s += "CTRL+";
if (key.Alt) s += "ALT+";
s += keyProcessor(key, currentText, ctrlOrAlt);
if (ctrlOrAlt && currentText.Length > 0 && currentText.Last() != ' ') s += " ";
if (ctrlOrAlt) s += " ";
if (key.Ctrl) s += "CTRL+";
if (key.Alt) s += "ALT+";
s += keyProcessor(key, currentText, ctrlOrAlt);
return s;
}
if (ctrlOrAlt) s += " ";
private static string AddSpecialKey(KeyConfig key, string currentText, bool wasCtrlOrAlt)
{
var s = "";
return s;
}
if (currentText.Length > 0 && currentText.Last() != ' ' && !wasCtrlOrAlt) s += " ";
s += key.Key.ToString();
if (!wasCtrlOrAlt) s += " ";
private static string AddSpecialKey(KeyConfig key, string currentText, bool wasCtrlOrAlt)
{
var s = "";
return s;
}
if (currentText.Length > 0 && currentText.Last() != ' ' && !wasCtrlOrAlt) s += " ";
s += key.Key.ToString();
if (!wasCtrlOrAlt) s += " ";
return s;
}
}

View File

@@ -1,9 +1,8 @@
namespace FileTime.GuiApp.Configuration
namespace FileTime.GuiApp.Configuration;
public class KeyBindingConfiguration
{
public class KeyBindingConfiguration
{
public bool UseDefaultBindings { get; set; } = true;
public List<CommandBindingConfiguration> DefaultKeyBindings { get; set; } = new();
public List<CommandBindingConfiguration> KeyBindings { get; set; } = new();
}
public bool UseDefaultBindings { get; set; } = true;
public List<CommandBindingConfiguration> DefaultKeyBindings { get; set; } = new();
public List<CommandBindingConfiguration> KeyBindings { get; set; } = new();
}

View File

@@ -1,32 +1,31 @@
using Avalonia.Input;
namespace FileTime.GuiApp.Configuration
namespace FileTime.GuiApp.Configuration;
public class KeyConfig
{
public class KeyConfig
public Key Key { get; set; }
public bool Shift { get; set; }
public bool Alt { get; set; }
public bool Ctrl { get; set; }
public KeyConfig() { }
public KeyConfig(
Key key,
bool shift = false,
bool alt = false,
bool ctrl = false)
{
public Key Key { get; set; }
public bool Shift { get; set; }
public bool Alt { get; set; }
public bool Ctrl { get; set; }
public KeyConfig() { }
public KeyConfig(
Key key,
bool shift = false,
bool alt = false,
bool ctrl = false)
{
Key = key;
Shift = shift;
Alt = alt;
Ctrl = ctrl;
}
public bool AreEquals(KeyConfig otherKeyConfig) =>
Key == otherKeyConfig.Key
&& Alt == otherKeyConfig.Alt
&& Shift == otherKeyConfig.Shift
&& Ctrl == otherKeyConfig.Ctrl;
Key = key;
Shift = shift;
Alt = alt;
Ctrl = ctrl;
}
public bool AreEquals(KeyConfig otherKeyConfig) =>
Key == otherKeyConfig.Key
&& Alt == otherKeyConfig.Alt
&& Shift == otherKeyConfig.Shift
&& Ctrl == otherKeyConfig.Ctrl;
}

View File

@@ -3,125 +3,124 @@ using FileTime.App.Core.Command;
using System;
using System.Collections.Generic;
namespace FileTime.GuiApp.Configuration
namespace FileTime.GuiApp.Configuration;
public static class MainConfiguration
{
public static class MainConfiguration
private static readonly Lazy<List<CommandBindingConfiguration>> _defaultKeybindings = new(InitDefaultKeyBindings);
public static Dictionary<string, string> Configuration { get; }
static MainConfiguration()
{
private static readonly Lazy<List<CommandBindingConfiguration>> _defaultKeybindings = new(InitDefaultKeyBindings);
Configuration = new();
PopulateDefaultEditorPrograms(Configuration);
PopulateDefaultKeyBindings(Configuration, _defaultKeybindings.Value, SectionNames.KeybindingSectionName + ":" + nameof(KeyBindingConfiguration.DefaultKeyBindings));
}
public static Dictionary<string, string> Configuration { get; }
static MainConfiguration()
private static void PopulateDefaultKeyBindings(Dictionary<string, string> configuration, List<CommandBindingConfiguration> commandBindingConfigs, string basePath)
{
for (var i = 0; i < commandBindingConfigs.Count; i++)
{
Configuration = new();
PopulateDefaultEditorPrograms(Configuration);
PopulateDefaultKeyBindings(Configuration, _defaultKeybindings.Value, SectionNames.KeybindingSectionName + ":" + nameof(KeyBindingConfiguration.DefaultKeyBindings));
}
var baseKey = basePath + $":[{i}]:";
var commandBindingConfig = commandBindingConfigs[i];
configuration.Add(baseKey + nameof(CommandBindingConfiguration.Command), commandBindingConfig.Command.ToString());
private static void PopulateDefaultKeyBindings(Dictionary<string, string> configuration, List<CommandBindingConfiguration> commandBindingConfigs, string basePath)
{
for (var i = 0; i < commandBindingConfigs.Count; i++)
for (var j = 0; j < commandBindingConfig.Keys.Count; j++)
{
var baseKey = basePath + $":[{i}]:";
var commandBindingConfig = commandBindingConfigs[i];
configuration.Add(baseKey + nameof(CommandBindingConfiguration.Command), commandBindingConfig.Command.ToString());
for (var j = 0; j < commandBindingConfig.Keys.Count; j++)
{
var key = commandBindingConfig.Keys[j];
var keyBaseKey = baseKey + $"keys:[{j}]:";
configuration.Add(keyBaseKey + nameof(KeyConfig.Key), key.Key.ToString());
configuration.Add(keyBaseKey + nameof(KeyConfig.Shift), key.Shift.ToString());
configuration.Add(keyBaseKey + nameof(KeyConfig.Alt), key.Alt.ToString());
configuration.Add(keyBaseKey + nameof(KeyConfig.Ctrl), key.Ctrl.ToString());
}
var key = commandBindingConfig.Keys[j];
var keyBaseKey = baseKey + $"keys:[{j}]:";
configuration.Add(keyBaseKey + nameof(KeyConfig.Key), key.Key.ToString());
configuration.Add(keyBaseKey + nameof(KeyConfig.Shift), key.Shift.ToString());
configuration.Add(keyBaseKey + nameof(KeyConfig.Alt), key.Alt.ToString());
configuration.Add(keyBaseKey + nameof(KeyConfig.Ctrl), key.Ctrl.ToString());
}
}
}
private static List<CommandBindingConfiguration> InitDefaultKeyBindings()
private static List<CommandBindingConfiguration> InitDefaultKeyBindings()
{
return new List<CommandBindingConfiguration>()
{
return new List<CommandBindingConfiguration>()
{
new CommandBindingConfiguration(Commands.AutoRefresh, new KeyConfig(Key.R, shift: true)),
new CommandBindingConfiguration(Commands.ChangeTimelineMode, new[] { Key.T, Key.M }),
new CommandBindingConfiguration(Commands.CloseTab, Key.Q),
new CommandBindingConfiguration(Commands.Compress, new[] { Key.Y, Key.C }),
new CommandBindingConfiguration(Commands.Copy, new[] { Key.Y, Key.Y }),
new CommandBindingConfiguration(Commands.CopyHash, new[] { Key.C, Key.H }),
new CommandBindingConfiguration(Commands.CopyPath, new[] { Key.C, Key.P }),
new CommandBindingConfiguration(Commands.CreateContainer, Key.F7),
new CommandBindingConfiguration(Commands.CreateContainer, new[] { Key.C, Key.C }),
new CommandBindingConfiguration(Commands.CreateElement, new[] { Key.C, Key.E }),
new CommandBindingConfiguration(Commands.Cut, new[] { Key.D, Key.D }),
new CommandBindingConfiguration(Commands.Edit, new KeyConfig(Key.F4)),
new CommandBindingConfiguration(Commands.EnterRapidTravel, new KeyConfig(Key.OemComma, shift: true)),
new CommandBindingConfiguration(Commands.FindByName, new[] { Key.F, Key.N }),
new CommandBindingConfiguration(Commands.FindByNameRegex, new[] { Key.F, Key.R }),
new CommandBindingConfiguration(Commands.GoToHome, new[] { Key.G, Key.H }),
new CommandBindingConfiguration(Commands.GoToPath, new KeyConfig(Key.L, ctrl: true)),
new CommandBindingConfiguration(Commands.GoToPath, new[] { Key.G, Key.P }),
new CommandBindingConfiguration(Commands.GoToProvider, new[] { Key.G, Key.T }),
new CommandBindingConfiguration(Commands.GoToRoot, new[] { Key.G, Key.R }),
new CommandBindingConfiguration(Commands.HardDelete, new[] { new KeyConfig(Key.D,shift: true), new KeyConfig(Key.D, shift: true) }),
new CommandBindingConfiguration(Commands.Mark, Key.Space),
new CommandBindingConfiguration(Commands.MoveToLast, new KeyConfig(Key.G, shift: true)),
new CommandBindingConfiguration(Commands.MoveToFirst, new[] { Key.G, Key.G }),
new CommandBindingConfiguration(Commands.NextTimelineBlock, Key.L ),
new CommandBindingConfiguration(Commands.NextTimelineCommand, Key.J ),
new CommandBindingConfiguration(Commands.OpenInFileBrowser, new[] { Key.O, Key.E }),
new CommandBindingConfiguration(Commands.PasteMerge, new[] { Key.P, Key.P }),
new CommandBindingConfiguration(Commands.PasteOverwrite, new[] { Key.P, Key.O }),
new CommandBindingConfiguration(Commands.PasteSkip, new[] { Key.P, Key.S }),
new CommandBindingConfiguration(Commands.PinFavorite, new[] { Key.F, Key.P }),
new CommandBindingConfiguration(Commands.PreviousTimelineBlock, Key.H ),
new CommandBindingConfiguration(Commands.PreviousTimelineCommand, Key.K ),
new CommandBindingConfiguration(Commands.Refresh, Key.R),
new CommandBindingConfiguration(Commands.Rename, Key.F2),
new CommandBindingConfiguration(Commands.Rename, new[] { Key.C, Key.W }),
new CommandBindingConfiguration(Commands.RunCommand, new KeyConfig(Key.D4, shift: true)),
new CommandBindingConfiguration(Commands.ScanContainerSize, new[] { Key.C, Key.S }),
new CommandBindingConfiguration(Commands.ShowAllShotcut, Key.F1),
new CommandBindingConfiguration(Commands.SoftDelete, new[] { new KeyConfig(Key.D), new KeyConfig(Key.D, shift: true) }),
new CommandBindingConfiguration(Commands.SwitchToLastTab, Key.D9),
new CommandBindingConfiguration(Commands.SwitchToTab1, Key.D1),
new CommandBindingConfiguration(Commands.SwitchToTab2, Key.D2),
new CommandBindingConfiguration(Commands.SwitchToTab3, Key.D3),
new CommandBindingConfiguration(Commands.SwitchToTab4, Key.D4),
new CommandBindingConfiguration(Commands.SwitchToTab5, Key.D5),
new CommandBindingConfiguration(Commands.SwitchToTab6, Key.D6),
new CommandBindingConfiguration(Commands.SwitchToTab7, Key.D7),
new CommandBindingConfiguration(Commands.SwitchToTab8, Key.D8),
new CommandBindingConfiguration(Commands.TimelinePause, new[] { Key.T, Key.P }),
new CommandBindingConfiguration(Commands.TimelineRefresh, new[] { Key.T, Key.R }),
new CommandBindingConfiguration(Commands.TimelineStart, new[] { Key.T, Key.S }),
new CommandBindingConfiguration(Commands.ToggleAdvancedIcons, new[] { Key.Z, Key.I }),
new CommandBindingConfiguration(Commands.GoUp, Key.Left),
new CommandBindingConfiguration(Commands.Open, Key.Right),
new CommandBindingConfiguration(Commands.OpenOrRun, Key.Enter),
new CommandBindingConfiguration(Commands.MoveCursorUp, Key.Up),
new CommandBindingConfiguration(Commands.MoveCursorDown, Key.Down),
new CommandBindingConfiguration(Commands.MoveCursorUpPage, Key.PageUp),
new CommandBindingConfiguration(Commands.MoveCursorDownPage, Key.PageDown),
};
}
new CommandBindingConfiguration(Commands.AutoRefresh, new KeyConfig(Key.R, shift: true)),
new CommandBindingConfiguration(Commands.ChangeTimelineMode, new[] { Key.T, Key.M }),
new CommandBindingConfiguration(Commands.CloseTab, Key.Q),
new CommandBindingConfiguration(Commands.Compress, new[] { Key.Y, Key.C }),
new CommandBindingConfiguration(Commands.Copy, new[] { Key.Y, Key.Y }),
new CommandBindingConfiguration(Commands.CopyHash, new[] { Key.C, Key.H }),
new CommandBindingConfiguration(Commands.CopyPath, new[] { Key.C, Key.P }),
new CommandBindingConfiguration(Commands.CreateContainer, Key.F7),
new CommandBindingConfiguration(Commands.CreateContainer, new[] { Key.C, Key.C }),
new CommandBindingConfiguration(Commands.CreateElement, new[] { Key.C, Key.E }),
new CommandBindingConfiguration(Commands.Cut, new[] { Key.D, Key.D }),
new CommandBindingConfiguration(Commands.Edit, new KeyConfig(Key.F4)),
new CommandBindingConfiguration(Commands.EnterRapidTravel, new KeyConfig(Key.OemComma, shift: true)),
new CommandBindingConfiguration(Commands.FindByName, new[] { Key.F, Key.N }),
new CommandBindingConfiguration(Commands.FindByNameRegex, new[] { Key.F, Key.R }),
new CommandBindingConfiguration(Commands.GoToHome, new[] { Key.G, Key.H }),
new CommandBindingConfiguration(Commands.GoToPath, new KeyConfig(Key.L, ctrl: true)),
new CommandBindingConfiguration(Commands.GoToPath, new[] { Key.G, Key.P }),
new CommandBindingConfiguration(Commands.GoToProvider, new[] { Key.G, Key.T }),
new CommandBindingConfiguration(Commands.GoToRoot, new[] { Key.G, Key.R }),
new CommandBindingConfiguration(Commands.HardDelete, new[] { new KeyConfig(Key.D,shift: true), new KeyConfig(Key.D, shift: true) }),
new CommandBindingConfiguration(Commands.Mark, Key.Space),
new CommandBindingConfiguration(Commands.MoveToLast, new KeyConfig(Key.G, shift: true)),
new CommandBindingConfiguration(Commands.MoveToFirst, new[] { Key.G, Key.G }),
new CommandBindingConfiguration(Commands.NextTimelineBlock, Key.L ),
new CommandBindingConfiguration(Commands.NextTimelineCommand, Key.J ),
new CommandBindingConfiguration(Commands.OpenInFileBrowser, new[] { Key.O, Key.E }),
new CommandBindingConfiguration(Commands.PasteMerge, new[] { Key.P, Key.P }),
new CommandBindingConfiguration(Commands.PasteOverwrite, new[] { Key.P, Key.O }),
new CommandBindingConfiguration(Commands.PasteSkip, new[] { Key.P, Key.S }),
new CommandBindingConfiguration(Commands.PinFavorite, new[] { Key.F, Key.P }),
new CommandBindingConfiguration(Commands.PreviousTimelineBlock, Key.H ),
new CommandBindingConfiguration(Commands.PreviousTimelineCommand, Key.K ),
new CommandBindingConfiguration(Commands.Refresh, Key.R),
new CommandBindingConfiguration(Commands.Rename, Key.F2),
new CommandBindingConfiguration(Commands.Rename, new[] { Key.C, Key.W }),
new CommandBindingConfiguration(Commands.RunCommand, new KeyConfig(Key.D4, shift: true)),
new CommandBindingConfiguration(Commands.ScanContainerSize, new[] { Key.C, Key.S }),
new CommandBindingConfiguration(Commands.ShowAllShotcut, Key.F1),
new CommandBindingConfiguration(Commands.SoftDelete, new[] { new KeyConfig(Key.D), new KeyConfig(Key.D, shift: true) }),
new CommandBindingConfiguration(Commands.SwitchToLastTab, Key.D9),
new CommandBindingConfiguration(Commands.SwitchToTab1, Key.D1),
new CommandBindingConfiguration(Commands.SwitchToTab2, Key.D2),
new CommandBindingConfiguration(Commands.SwitchToTab3, Key.D3),
new CommandBindingConfiguration(Commands.SwitchToTab4, Key.D4),
new CommandBindingConfiguration(Commands.SwitchToTab5, Key.D5),
new CommandBindingConfiguration(Commands.SwitchToTab6, Key.D6),
new CommandBindingConfiguration(Commands.SwitchToTab7, Key.D7),
new CommandBindingConfiguration(Commands.SwitchToTab8, Key.D8),
new CommandBindingConfiguration(Commands.TimelinePause, new[] { Key.T, Key.P }),
new CommandBindingConfiguration(Commands.TimelineRefresh, new[] { Key.T, Key.R }),
new CommandBindingConfiguration(Commands.TimelineStart, new[] { Key.T, Key.S }),
new CommandBindingConfiguration(Commands.ToggleAdvancedIcons, new[] { Key.Z, Key.I }),
new CommandBindingConfiguration(Commands.GoUp, Key.Left),
new CommandBindingConfiguration(Commands.Open, Key.Right),
new CommandBindingConfiguration(Commands.OpenOrRun, Key.Enter),
new CommandBindingConfiguration(Commands.MoveCursorUp, Key.Up),
new CommandBindingConfiguration(Commands.MoveCursorDown, Key.Down),
new CommandBindingConfiguration(Commands.MoveCursorUpPage, Key.PageUp),
new CommandBindingConfiguration(Commands.MoveCursorDownPage, Key.PageDown),
};
}
private static void PopulateDefaultEditorPrograms(Dictionary<string, string> configuration)
private static void PopulateDefaultEditorPrograms(Dictionary<string, string> configuration)
{
var editorPrograms = new List<ProgramConfiguration>()
{
var editorPrograms = new List<ProgramConfiguration>()
{
new ProgramConfiguration(@"c:\Program Files\Notepad++\notepad++.exe"),
new ProgramConfiguration("notepad.exe"),
};
new ProgramConfiguration(@"c:\Program Files\Notepad++\notepad++.exe"),
new ProgramConfiguration("notepad.exe"),
};
for (var i = 0; i < editorPrograms.Count; i++)
{
if (editorPrograms[i].Path is not string path) continue;
configuration.Add($"{SectionNames.ProgramsSectionName}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Path)}", path);
for (var i = 0; i < editorPrograms.Count; i++)
{
if (editorPrograms[i].Path is not string path) continue;
configuration.Add($"{SectionNames.ProgramsSectionName}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Path)}", path);
if (editorPrograms[i].Arguments is string arguments)
{
configuration.Add($"{SectionNames.ProgramsSectionName}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Arguments)}", arguments);
}
if (editorPrograms[i].Arguments is string arguments)
{
configuration.Add($"{SectionNames.ProgramsSectionName}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Arguments)}", arguments);
}
}
}

View File

@@ -1,16 +1,15 @@
namespace FileTime.GuiApp.Configuration
namespace FileTime.GuiApp.Configuration;
public class ProgramConfiguration
{
public class ProgramConfiguration
public string? Path { get; set; }
public string? Arguments { get; set; }
public ProgramConfiguration() { }
public ProgramConfiguration(string? path, string? arguments = null)
{
public string? Path { get; set; }
public string? Arguments { get; set; }
public ProgramConfiguration() { }
public ProgramConfiguration(string? path, string? arguments = null)
{
Path = path;
Arguments = arguments;
}
Path = path;
Arguments = arguments;
}
}

View File

@@ -1,10 +1,9 @@
using System.Collections.Generic;
namespace FileTime.GuiApp.Configuration
namespace FileTime.GuiApp.Configuration;
public class ProgramsConfiguration
{
public class ProgramsConfiguration
{
public List<ProgramConfiguration> DefaultEditorPrograms { get; set; } = new();
public List<ProgramConfiguration> EditorPrograms { get; set; } = new();
}
public List<ProgramConfiguration> DefaultEditorPrograms { get; set; } = new();
public List<ProgramConfiguration> EditorPrograms { get; set; } = new();
}

View File

@@ -1,8 +1,7 @@
namespace FileTime.GuiApp.Configuration
namespace FileTime.GuiApp.Configuration;
public static class SectionNames
{
public static class SectionNames
{
public const string KeybindingSectionName = "KeyBindings";
public const string ProgramsSectionName = "Programs";
}
public const string KeybindingSectionName = "KeyBindings";
public const string ProgramsSectionName = "Programs";
}

View File

@@ -6,6 +6,10 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="0.10.13" />
</ItemGroup>

View File

@@ -1,4 +1,3 @@
namespace FileTime.GuiApp.Models
{
public record SpecialKeysStatus(bool IsAltPressed, bool IsShiftPressed, bool IsCtrlPressed);
}
namespace FileTime.GuiApp.Models;
public record SpecialKeysStatus(bool IsAltPressed, bool IsShiftPressed, bool IsCtrlPressed);

View File

@@ -1,4 +1,3 @@
namespace FileTime.GuiApp.Services
{
public interface IDefaultModeKeyInputHandler : IKeyInputHandler { }
}
namespace FileTime.GuiApp.Services;
public interface IDefaultModeKeyInputHandler : IKeyInputHandler { }

View File

@@ -1,10 +1,9 @@
using Avalonia.Input;
using FileTime.GuiApp.Models;
namespace FileTime.GuiApp.Services
namespace FileTime.GuiApp.Services;
public interface IKeyInputHandler
{
public interface IKeyInputHandler
{
Task HandleInputKey(Key key, SpecialKeysStatus specialKeysStatus, Action<bool> setHandled);
}
Task HandleInputKey(Key key, SpecialKeysStatus specialKeysStatus, Action<bool> setHandled);
}

View File

@@ -1,9 +1,8 @@
using Avalonia.Input;
namespace FileTime.GuiApp.Services
namespace FileTime.GuiApp.Services;
public interface IKeyInputHandlerService
{
public interface IKeyInputHandlerService
{
Task ProcessKeyDown(Key key, KeyModifiers keyModifiers, Action<bool> setHandled);
}
Task ProcessKeyDown(Key key, KeyModifiers keyModifiers, Action<bool> setHandled);
}

View File

@@ -1,11 +1,10 @@
using FileTime.GuiApp.Configuration;
namespace FileTime.GuiApp.Services
namespace FileTime.GuiApp.Services;
public interface IKeyboardConfigurationService
{
public interface IKeyboardConfigurationService
{
IReadOnlyList<CommandBindingConfiguration> CommandBindings { get; }
IReadOnlyList<CommandBindingConfiguration> UniversalCommandBindings { get; }
IReadOnlyList<CommandBindingConfiguration> AllShortcut { get; }
}
IReadOnlyList<CommandBindingConfiguration> CommandBindings { get; }
IReadOnlyList<CommandBindingConfiguration> UniversalCommandBindings { get; }
IReadOnlyList<CommandBindingConfiguration> AllShortcut { get; }
}

View File

@@ -1,4 +1,3 @@
namespace FileTime.GuiApp.Services
{
public interface IRapidTravelModeKeyInputHandler : IKeyInputHandler { }
}
namespace FileTime.GuiApp.Services;
public interface IRapidTravelModeKeyInputHandler : IKeyInputHandler { }

View File

@@ -1,14 +1,13 @@
using FileTime.App.Core.ViewModels;
using FileTime.GuiApp.Configuration;
namespace FileTime.GuiApp.ViewModels
namespace FileTime.GuiApp.ViewModels;
public interface IGuiAppState : IAppState
{
public interface IGuiAppState : IAppState
{
List<KeyConfig> PreviousKeys { get; }
bool IsAllShortcutVisible { get; set; }
bool NoCommandFound { get; set; }
string? MessageBoxText { get; set; }
List<CommandBindingConfiguration> PossibleCommands { get; set; }
}
List<KeyConfig> PreviousKeys { get; }
bool IsAllShortcutVisible { get; set; }
bool NoCommandFound { get; set; }
string? MessageBoxText { get; set; }
List<CommandBindingConfiguration> PossibleCommands { get; set; }
}

View File

@@ -7,40 +7,39 @@ using FileTime.GuiApp.Views;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace FileTime.GuiApp
namespace FileTime.GuiApp;
public partial class App : Application
{
public partial class App : Application
static App()
{
static App()
{
DI.ServiceProvider ??= DependencyInjection
.RegisterDefaultServices()
.AddConfiguration()
.RegisterLogging()
.RegisterServices()
.AddViewModels()
.BuildServiceProvider()
.InitSerilog();
DI.ServiceProvider ??= DependencyInjection
.RegisterDefaultServices()
.AddConfiguration()
.RegisterLogging()
.RegisterServices()
.AddViewModels()
.BuildServiceProvider()
.InitSerilog();
var logger = DI.ServiceProvider.GetRequiredService<ILogger<App>>();
logger.LogInformation("App initialization completed");
}
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
var logger = DI.ServiceProvider.GetRequiredService<ILogger<App>>();
logger.LogInformation("App initialization completed");
}
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
desktop.MainWindow = new MainWindow
{
desktop.MainWindow = new MainWindow
{
DataContext = new MainWindowLoadingViewModel(),
};
}
base.OnFrameworkInitializationCompleted();
DataContext = new MainWindowLoadingViewModel(),
};
}
base.OnFrameworkInitializationCompleted();
}
}

View File

@@ -9,6 +9,11 @@
<ApplicationIcon>filetime.ico</ApplicationIcon>
<Version>0.0.1</Version>
</PropertyGroup>
<PropertyGroup>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
</PropertyGroup>
<ItemGroup>
<Content Include="filetime.ico" />
</ItemGroup>

View File

@@ -3,19 +3,19 @@ using System.IO;
using Avalonia;
using Avalonia.ReactiveUI;
namespace FileTime.GuiApp
namespace FileTime.GuiApp;
public static class Program
{
public static class Program
public static string AppDataRoot { get; }
public static string EnvironmentName { get; }
static Program()
{
public static string AppDataRoot { get; }
public static string EnvironmentName { get; }
static Program()
{
#if DEBUG
EnvironmentName = "Development";
EnvironmentName = "Development";
AppDataRoot = Path.Combine(Environment.CurrentDirectory, "appdata");
AppDataRoot = Path.Combine(Environment.CurrentDirectory, "appdata");
#else
EnvironmentName = "Release";
@@ -43,20 +43,19 @@ namespace FileTime.GuiApp
if (appDataRoot == null) throw new UnauthorizedAccessException();
AppDataRoot = appDataRoot;
#endif
}
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args) => BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.UseReactiveUI()
.LogToTrace();
}
}
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args) => BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.UseReactiveUI()
.LogToTrace();
}

View File

@@ -11,70 +11,69 @@ using Microsoft.Extensions.DependencyInjection;
using Serilog;
using Serilog.Configuration;
namespace FileTime.GuiApp
namespace FileTime.GuiApp;
public static class Startup
{
public static class Startup
internal static IServiceCollection AddViewModels(this IServiceCollection serviceCollection)
{
internal static IServiceCollection AddViewModels(this IServiceCollection serviceCollection)
{
return serviceCollection
.AddSingleton<MainWindowViewModel>()
.AddSingleton<GuiAppState>()
.AddSingleton<IAppState, GuiAppState>(s => s.GetRequiredService<GuiAppState>())
.AddSingleton<IGuiAppState, GuiAppState>(s => s.GetRequiredService<GuiAppState>());
}
internal static IServiceCollection RegisterServices(this IServiceCollection serviceCollection)
{
return serviceCollection
.AddSingleton<IRxSchedulerService, AvaloniaRxSchedulerService>()
.AddSingleton<IKeyInputHandlerService, KeyInputHandlerService>()
.AddSingleton<IDefaultModeKeyInputHandler, DefaultModeKeyInputHandler>()
.AddSingleton<IKeyboardConfigurationService, KeyboardConfigurationService>()
.AddSingleton<IRapidTravelModeKeyInputHandler, RapidTravelModeKeyInputHandler>();
}
return serviceCollection
.AddSingleton<MainWindowViewModel>()
.AddSingleton<GuiAppState>()
.AddSingleton<IAppState, GuiAppState>(s => s.GetRequiredService<GuiAppState>())
.AddSingleton<IGuiAppState, GuiAppState>(s => s.GetRequiredService<GuiAppState>());
}
internal static IServiceCollection RegisterServices(this IServiceCollection serviceCollection)
{
return serviceCollection
.AddSingleton<IRxSchedulerService, AvaloniaRxSchedulerService>()
.AddSingleton<IKeyInputHandlerService, KeyInputHandlerService>()
.AddSingleton<IDefaultModeKeyInputHandler, DefaultModeKeyInputHandler>()
.AddSingleton<IKeyboardConfigurationService, KeyboardConfigurationService>()
.AddSingleton<IRapidTravelModeKeyInputHandler, RapidTravelModeKeyInputHandler>();
}
internal static IServiceCollection RegisterLogging(this IServiceCollection serviceCollection)
{
return serviceCollection.AddLogging(loggingBuilder =>
loggingBuilder.AddSerilog(dispose: true)
);
}
internal static IServiceCollection RegisterLogging(this IServiceCollection serviceCollection)
{
return serviceCollection.AddLogging(loggingBuilder =>
loggingBuilder.AddSerilog(dispose: true)
);
}
internal static IServiceCollection AddConfiguration(this IServiceCollection serviceCollection)
{
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(MainConfiguration.Configuration)
.AddJsonFile("appsettings.json", optional: true)
.AddJsonFile($"appsettings.{Program.EnvironmentName}.json", true)
.Build();
internal static IServiceCollection AddConfiguration(this IServiceCollection serviceCollection)
{
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(MainConfiguration.Configuration)
.AddJsonFile("appsettings.json", optional: true)
.AddJsonFile($"appsettings.{Program.EnvironmentName}.json", true)
.Build();
return serviceCollection
.Configure<ProgramsConfiguration>(configuration.GetSection(SectionNames.ProgramsSectionName))
.Configure<KeyBindingConfiguration>(configuration.GetSection(SectionNames.KeybindingSectionName))
.AddSingleton<IConfiguration>(configuration);
}
return serviceCollection
.Configure<ProgramsConfiguration>(configuration.GetSection(SectionNames.ProgramsSectionName))
.Configure<KeyBindingConfiguration>(configuration.GetSection(SectionNames.KeybindingSectionName))
.AddSingleton<IConfiguration>(configuration);
}
internal static IServiceProvider InitSerilog(this IServiceProvider serviceProvider)
{
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(serviceProvider.GetService<IConfiguration>())
.Enrich.FromLogContext()
.WriteTo.File(
Path.Combine(Program.AppDataRoot, "logs", "appLog.log"),
fileSizeLimitBytes: 10 * 1024 * 1024,
rollOnFileSizeLimit: true,
rollingInterval: RollingInterval.Day)
.WriteTo.MessageBoxSink(serviceProvider)
.CreateLogger();
internal static IServiceProvider InitSerilog(this IServiceProvider serviceProvider)
{
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(serviceProvider.GetService<IConfiguration>())
.Enrich.FromLogContext()
.WriteTo.File(
Path.Combine(Program.AppDataRoot, "logs", "appLog.log"),
fileSizeLimitBytes: 10 * 1024 * 1024,
rollOnFileSizeLimit: true,
rollingInterval: RollingInterval.Day)
.WriteTo.MessageBoxSink(serviceProvider)
.CreateLogger();
return serviceProvider;
}
return serviceProvider;
}
internal static LoggerConfiguration MessageBoxSink(
this LoggerSinkConfiguration loggerConfiguration,
IServiceProvider serviceProvider)
{
return loggerConfiguration.Sink(serviceProvider.GetService<ToastMessageSink>());
}
internal static LoggerConfiguration MessageBoxSink(
this LoggerSinkConfiguration loggerConfiguration,
IServiceProvider serviceProvider)
{
return loggerConfiguration.Sink(serviceProvider.GetService<ToastMessageSink>());
}
}

View File

@@ -6,6 +6,10 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.Core\FileTime.App.Core.csproj" />
<ProjectReference Include="..\FileTime.GuiApp.Abstractions\FileTime.GuiApp.Abstractions.csproj" />

View File

@@ -2,23 +2,22 @@ using FileTime.App.Core.ViewModels;
using FileTime.GuiApp.Configuration;
using MvvmGen;
namespace FileTime.GuiApp.ViewModels
namespace FileTime.GuiApp.ViewModels;
[ViewModel]
public partial class GuiAppState : AppStateBase, IGuiAppState
{
[ViewModel]
public partial class GuiAppState : AppStateBase, IGuiAppState
{
[Property]
private bool _isAllShortcutVisible;
[Property]
private bool _isAllShortcutVisible;
[Property]
private bool _noCommandFound;
[Property]
private bool _noCommandFound;
[Property]
private string? _messageBoxText;
[Property]
private string? _messageBoxText;
[Property]
private List<CommandBindingConfiguration> _possibleCommands = new();
[Property]
private List<CommandBindingConfiguration> _possibleCommands = new();
public List<KeyConfig> PreviousKeys { get; } = new();
}
public List<KeyConfig> PreviousKeys { get; } = new();
}

View File

@@ -1,54 +1,53 @@
using System.Globalization;
using Avalonia.Data.Converters;
namespace FileTime.GuiApp.Converters
namespace FileTime.GuiApp.Converters;
public enum ComparisonCondition
{
public enum ComparisonCondition
Equal,
GreaterThan,
LessThan,
LessThanOrEqual,
NotEqual,
GreaterThanOrEqual
}
public class CompareConverter : IValueConverter
{
public ComparisonCondition ComparisonCondition { get; set; } = ComparisonCondition.Equal;
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
Equal,
GreaterThan,
LessThan,
LessThanOrEqual,
NotEqual,
GreaterThanOrEqual
return Compare(value, parameter);
}
public class CompareConverter : IValueConverter
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
public ComparisonCondition ComparisonCondition { get; set; } = ComparisonCondition.Equal;
throw new NotImplementedException();
}
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
private bool Compare(object? value, object? parameter)
{
if (ComparisonCondition == ComparisonCondition.GreaterThan)
{
return Compare(value, parameter);
if (value is int valueInt && (parameter is int parameterInt || int.TryParse(parameter?.ToString(), out parameterInt))) return valueInt > parameterInt;
else if (value is double valueDouble && (parameter is double parameterDouble || double.TryParse(parameter?.ToString(), out parameterDouble))) return valueDouble > parameterDouble;
else throw new NotSupportedException();
}
else if (ComparisonCondition == ComparisonCondition.NotEqual)
{
if (value is int valueInt && (parameter is int parameterInt || int.TryParse(parameter?.ToString(), out parameterInt))) return valueInt != parameterInt;
else if (value is double valueDouble && (parameter is double parameterDouble || double.TryParse(parameter?.ToString(), out parameterDouble))) return valueDouble != parameterDouble;
return value != parameter;
}
else if (ComparisonCondition == ComparisonCondition.Equal)
{
if (value is int valueInt && (parameter is int parameterInt || int.TryParse(parameter?.ToString(), out parameterInt))) return valueInt == parameterInt;
else if (value is double valueDouble && (parameter is double parameterDouble || double.TryParse(parameter?.ToString(), out parameterDouble))) return valueDouble == parameterDouble;
else if (value?.GetType().IsEnum ?? false && Enum.TryParse(value.GetType(), parameter?.ToString(), out var _)) return value.ToString() == parameter?.ToString();
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
private bool Compare(object? value, object? parameter)
{
if (ComparisonCondition == ComparisonCondition.GreaterThan)
{
if (value is int valueInt && (parameter is int parameterInt || int.TryParse(parameter?.ToString(), out parameterInt))) return valueInt > parameterInt;
else if (value is double valueDouble && (parameter is double parameterDouble || double.TryParse(parameter?.ToString(), out parameterDouble))) return valueDouble > parameterDouble;
else throw new NotSupportedException();
}
else if (ComparisonCondition == ComparisonCondition.NotEqual)
{
if (value is int valueInt && (parameter is int parameterInt || int.TryParse(parameter?.ToString(), out parameterInt))) return valueInt != parameterInt;
else if (value is double valueDouble && (parameter is double parameterDouble || double.TryParse(parameter?.ToString(), out parameterDouble))) return valueDouble != parameterDouble;
return value != parameter;
}
else if (ComparisonCondition == ComparisonCondition.Equal)
{
if (value is int valueInt && (parameter is int parameterInt || int.TryParse(parameter?.ToString(), out parameterInt))) return valueInt == parameterInt;
else if (value is double valueDouble && (parameter is double parameterDouble || double.TryParse(parameter?.ToString(), out parameterDouble))) return valueDouble == parameterDouble;
else if (value?.GetType().IsEnum ?? false && Enum.TryParse(value.GetType(), parameter?.ToString(), out var _)) return value.ToString() == parameter?.ToString();
}
return value == parameter;
}
return value == parameter;
}
}

View File

@@ -1,18 +1,17 @@
using System.Globalization;
using Avalonia.Data.Converters;
namespace FileTime.GuiApp.Converters
{
public class DateTimeConverter : IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) =>
value is DateTime dateTime && parameter is string parameterS
? dateTime.ToString(parameterS)
: value;
namespace FileTime.GuiApp.Converters;
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public class DateTimeConverter : IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) =>
value is DateTime dateTime && parameter is string parameterS
? dateTime.ToString(parameterS)
: value;
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

View File

@@ -1,45 +1,44 @@
using System.Globalization;
using Avalonia.Data.Converters;
namespace FileTime.GuiApp.Converters
namespace FileTime.GuiApp.Converters;
public class ExceptionToStringConverter : IValueConverter
{
public class ExceptionToStringConverter : IValueConverter
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
if (value is not Exception e) return value;
if (e is UnauthorizedAccessException)
{
if (value is not Exception e) return value;
if (e is UnauthorizedAccessException)
{
return e.Message;
}
else if (e.InnerException != null)
{
return TraverseInnerException(e);
}
return FormatException(e);
return e.Message;
}
else if (e.InnerException != null)
{
return TraverseInnerException(e);
}
private static string TraverseInnerException(Exception e)
{
string s = "";
if (e.InnerException != null) s += TraverseInnerException(e.InnerException) + Environment.NewLine;
else return FormatException(e);
return FormatException(e);
}
s += "In: " + FormatException(e);
private static string TraverseInnerException(Exception e)
{
string s = "";
if (e.InnerException != null) s += TraverseInnerException(e.InnerException) + Environment.NewLine;
else return FormatException(e);
return s;
}
s += "In: " + FormatException(e);
private static string FormatException(Exception e)
{
return $"{e.Message} ({e.GetType().FullName})";
}
return s;
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
private static string FormatException(Exception e)
{
return $"{e.Message} ({e.GetType().FullName})";
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

View File

@@ -1,47 +1,46 @@
using System.Globalization;
using Avalonia.Data.Converters;
namespace FileTime.GuiApp.Converters
namespace FileTime.GuiApp.Converters;
public class FormatSizeConverter : IValueConverter
{
public class FormatSizeConverter : IValueConverter
private const long OneKiloByte = 1024;
private const long OneMegaByte = OneKiloByte * 1024;
private const long OneGigaByte = OneMegaByte * 1024;
private const long OneTerraByte = OneGigaByte * 1024;
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
private const long OneKiloByte = 1024;
private const long OneMegaByte = OneKiloByte * 1024;
private const long OneGigaByte = OneMegaByte * 1024;
private const long OneTerraByte = OneGigaByte * 1024;
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
return (value, int.TryParse(parameter?.ToString(), out var prec)) switch
{
return (value, int.TryParse(parameter?.ToString(), out var prec)) switch
{
(long size, true) => ToSizeString(size, prec),
(long size, false) => ToSizeString(size),
(null, _) => "...",
_ => value
};
}
(long size, true) => ToSizeString(size, prec),
(long size, false) => ToSizeString(size),
(null, _) => "...",
_ => value
};
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public static string ToSizeString(long fileSize, int precision = 1)
{
var fileSizeD = (decimal)fileSize;
var (size, suffix) = fileSize switch
{
throw new NotImplementedException();
}
> OneTerraByte => (fileSizeD / OneTerraByte, "T"),
> OneGigaByte => (fileSizeD / OneGigaByte, "G"),
> OneMegaByte => (fileSizeD / OneMegaByte, "M"),
> OneKiloByte => (fileSizeD / OneKiloByte, "K"),
_ => (fileSizeD, "B")
};
public static string ToSizeString(long fileSize, int precision = 1)
{
var fileSizeD = (decimal)fileSize;
var (size, suffix) = fileSize switch
{
> OneTerraByte => (fileSizeD / OneTerraByte, "T"),
> OneGigaByte => (fileSizeD / OneGigaByte, "G"),
> OneMegaByte => (fileSizeD / OneMegaByte, "M"),
> OneKiloByte => (fileSizeD / OneKiloByte, "K"),
_ => (fileSizeD, "B")
};
var result = string.Format("{0:N" + precision + "}", size).Replace(',', '.');
var result = string.Format("{0:N" + precision + "}", size).Replace(',', '.');
if (result.Contains('.')) result = result.TrimEnd('0').TrimEnd('.');
return result + " " + suffix;
}
if (result.Contains('.')) result = result.TrimEnd('0').TrimEnd('.');
return result + " " + suffix;
}
}

View File

@@ -3,22 +3,21 @@ using Avalonia.Data.Converters;
using FileTime.App.Core.Services;
using Microsoft.Extensions.DependencyInjection;
namespace FileTime.GuiApp.Converters
namespace FileTime.GuiApp.Converters;
public class GetFileExtensionConverter : IValueConverter
{
public class GetFileExtensionConverter : IValueConverter
private IItemNameConverterService? _itemNameConverterService;
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
private IItemNameConverterService? _itemNameConverterService;
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is not string fullName) return value;
_itemNameConverterService ??= DI.ServiceProvider.GetRequiredService<IItemNameConverterService>();
if (value is not string fullName) return value;
_itemNameConverterService ??= DI.ServiceProvider.GetRequiredService<IItemNameConverterService>();
return _itemNameConverterService.GetFileExtension(fullName);
}
return _itemNameConverterService.GetFileExtension(fullName);
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

View File

@@ -3,39 +3,38 @@ using Avalonia.Data.Converters;
using Avalonia.Media;
using FileTime.App.Core.Models.Enums;
namespace FileTime.GuiApp.Converters
namespace FileTime.GuiApp.Converters;
public class ItemViewModeToBrushConverter : IValueConverter
{
public class ItemViewModeToBrushConverter : IValueConverter
public Brush? DefaultBrush { get; set; }
public Brush? AlternativeBrush { get; set; }
public Brush? SelectedBrush { get; set; }
public Brush? MarkedBrush { get; set; }
public Brush? MarkedSelectedBrush { get; set; }
public Brush? MarkedAlternativeBrush { get; set; }
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
public Brush? DefaultBrush { get; set; }
public Brush? AlternativeBrush { get; set; }
public Brush? SelectedBrush { get; set; }
public Brush? MarkedBrush { get; set; }
public Brush? MarkedSelectedBrush { get; set; }
public Brush? MarkedAlternativeBrush { get; set; }
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
if (value is ItemViewMode viewMode)
{
if (value is ItemViewMode viewMode)
return viewMode switch
{
return viewMode switch
{
ItemViewMode.Default => DefaultBrush,
ItemViewMode.Alternative => AlternativeBrush,
ItemViewMode.Selected => SelectedBrush,
ItemViewMode.Marked => MarkedBrush,
ItemViewMode.MarkedSelected => MarkedSelectedBrush,
ItemViewMode.MarkedAlternative => MarkedAlternativeBrush,
_ => throw new NotImplementedException()
};
}
return value;
ItemViewMode.Default => DefaultBrush,
ItemViewMode.Alternative => AlternativeBrush,
ItemViewMode.Selected => SelectedBrush,
ItemViewMode.Marked => MarkedBrush,
ItemViewMode.MarkedSelected => MarkedSelectedBrush,
ItemViewMode.MarkedAlternative => MarkedAlternativeBrush,
_ => throw new NotImplementedException()
};
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
return value;
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

View File

@@ -3,35 +3,34 @@ using Avalonia.Data.Converters;
using FileTime.App.Core.Models.Enums;
using FileTime.App.Core.ViewModels;
namespace FileTime.GuiApp.Converters
namespace FileTime.GuiApp.Converters;
public class ItemViewModelIsAttributeTypeConverter : IValueConverter
{
public class ItemViewModelIsAttributeTypeConverter : IValueConverter
public bool Invert { get; set; }
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
public bool Invert { get; set; }
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
var attributeType = GetAttributeType(value);
if (parameter == null) return attributeType;
var result = parameter is ItemAttributeType targetAttribute && attributeType == targetAttribute;
if (Invert && parameter is ItemAttributeType) result = !result;
return result;
}
var attributeType = GetAttributeType(value);
if (parameter == null) return attributeType;
var result = parameter is ItemAttributeType targetAttribute && attributeType == targetAttribute;
if (Invert && parameter is ItemAttributeType) result = !result;
return result;
}
private static ItemAttributeType? GetAttributeType(object? value)
private static ItemAttributeType? GetAttributeType(object? value)
{
return value switch
{
return value switch
{
IFileViewModel => ItemAttributeType.File,
IContainerSizeContainerViewModel => ItemAttributeType.SizeContainer,
IElementViewModel => ItemAttributeType.Element,
IContainerViewModel => ItemAttributeType.Container,
_ => null
};
}
IFileViewModel => ItemAttributeType.File,
IContainerSizeContainerViewModel => ItemAttributeType.SizeContainer,
IElementViewModel => ItemAttributeType.Element,
IContainerViewModel => ItemAttributeType.Container,
_ => null
};
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

View File

@@ -4,112 +4,111 @@ using Avalonia.Media;
using FileTime.App.Core.Models;
using FileTime.GuiApp.ViewModels;
namespace FileTime.GuiApp.Converters
namespace FileTime.GuiApp.Converters;
public class NamePartShrinkerConverter : IMultiValueConverter
{
public class NamePartShrinkerConverter : IMultiValueConverter
private const int PixelPerChar = 8;
public object? Convert(IList<object?> values, Type targetType, object? parameter, CultureInfo culture)
{
private const int PixelPerChar = 8;
public object? Convert(IList<object?> values, Type targetType, object? parameter, CultureInfo culture)
if (values.Count > 0 && values[0] is IList<ItemNamePart> nameParts)
{
if (values.Count > 0 && values[0] is IList<ItemNamePart> nameParts)
var attributeWidth = values[2] is bool b && b ? 340 : 0;
var newNameParts = nameParts;
if (values.Count > 1 && values[1] is double width && width > 0)
{
var attributeWidth = values[2] is bool b && b ? 340 : 0;
var newNameParts = nameParts;
if (values.Count > 1 && values[1] is double width && width > 0)
{
newNameParts = GetNamePartsForWidth(nameParts, width - attributeWidth);
}
return newNameParts.Select(p => new ItemNamePartViewModel(p.Text, p.IsSpecial ? TextDecorations.Underline : null)).ToList();
newNameParts = GetNamePartsForWidth(nameParts, width - attributeWidth);
}
return null;
return newNameParts.Select(p => new ItemNamePartViewModel(p.Text, p.IsSpecial ? TextDecorations.Underline : null)).ToList();
}
return null;
}
private static List<ItemNamePart> GetNamePartsForWidth(IList<ItemNamePart> nameParts, double maxWidth)
{
//Best case, we are in the range
var textLength = nameParts.Select(p => p.Text.Length).Sum();
if (textLength * PixelPerChar <= maxWidth)
{
return nameParts.ToList();
}
private static List<ItemNamePart> GetNamePartsForWidth(IList<ItemNamePart> nameParts, double maxWidth)
//Trying at least with the special parts
var newNameParts = new ItemNamePart?[nameParts.Count];
for (var i = 0; i < nameParts.Count; i++)
{
//Best case, we are in the range
var textLength = nameParts.Select(p => p.Text.Length).Sum();
if (textLength * PixelPerChar <= maxWidth)
if (nameParts[i].IsSpecial)
{
return nameParts.ToList();
newNameParts[i] = nameParts[i];
}
//Trying at least with the special parts
var newNameParts = new ItemNamePart?[nameParts.Count];
for (var i = 0; i < nameParts.Count; i++)
{
if (nameParts[i].IsSpecial)
{
newNameParts[i] = nameParts[i];
}
}
return GetNamePartsForWidthOptimistic(nameParts, newNameParts, maxWidth);
}
private static List<ItemNamePart> GetNamePartsForWidthOptimistic(IList<ItemNamePart> nameParts, ItemNamePart?[] newNameParts, double maxWidth)
return GetNamePartsForWidthOptimistic(nameParts, newNameParts, maxWidth);
}
private static List<ItemNamePart> GetNamePartsForWidthOptimistic(IList<ItemNamePart> nameParts, ItemNamePart?[] newNameParts, double maxWidth)
{
var trimmedIndexes = new List<int>();
for (var i = 0; i < newNameParts.Length; i++)
{
var trimmedIndexes = new List<int>();
for (var i = 0; i < newNameParts.Length; i++)
if (newNameParts[i] == null)
{
if (newNameParts[i] == null)
{
trimmedIndexes.Add(i);
newNameParts[i] = new ItemNamePart("...");
}
trimmedIndexes.Add(i);
newNameParts[i] = new ItemNamePart("...");
}
var textLength = newNameParts.Select(p => p?.Text.Length ?? 0).Sum();
if (textLength * PixelPerChar > maxWidth)
{
return GetNamePartsForWidthPessimistic(nameParts, maxWidth);
}
foreach (var trimmedIndex in trimmedIndexes)
{
var baseTextLength = newNameParts.Select((p, i) => i == trimmedIndex ? 0 : (p?.Text.Length ?? 0)).Sum();
var proposedText = nameParts[trimmedIndex].Text;
var trimmed = false;
while ((baseTextLength + proposedText.Length + (trimmed ? 3 : 0)) * PixelPerChar > maxWidth)
{
proposedText = proposedText[0..^1];
trimmed = true;
}
newNameParts[trimmedIndex] = new ItemNamePart(proposedText + (trimmed ? "..." : ""));
if (trimmed) break;
}
return newNameParts.Where(f => f is not null).ToList()!;
}
private static List<ItemNamePart> GetNamePartsForWidthPessimistic(IList<ItemNamePart> nameParts, double maxWidth)
var textLength = newNameParts.Select(p => p?.Text.Length ?? 0).Sum();
if (textLength * PixelPerChar > maxWidth)
{
var newNameParts = new List<ItemNamePart>(nameParts);
foreach (var namePart in nameParts)
{
var baseTextLength = newNameParts.Select(p => p.Text.Length).Sum();
var proposedText = namePart.Text;
var trimmed = false;
while ((baseTextLength + 3) * PixelPerChar > maxWidth && proposedText != "")
{
proposedText = proposedText[0..^1];
trimmed = true;
}
if (!string.IsNullOrWhiteSpace(proposedText)) newNameParts.Add(new ItemNamePart(proposedText, namePart.IsSpecial));
if (trimmed) break;
}
if (newNameParts.Last().IsSpecial)
{
newNameParts.Add(new ItemNamePart("..."));
}
else
{
var last = newNameParts.Last();
last.Text += "...";
}
return newNameParts;
return GetNamePartsForWidthPessimistic(nameParts, maxWidth);
}
foreach (var trimmedIndex in trimmedIndexes)
{
var baseTextLength = newNameParts.Select((p, i) => i == trimmedIndex ? 0 : (p?.Text.Length ?? 0)).Sum();
var proposedText = nameParts[trimmedIndex].Text;
var trimmed = false;
while ((baseTextLength + proposedText.Length + (trimmed ? 3 : 0)) * PixelPerChar > maxWidth)
{
proposedText = proposedText[0..^1];
trimmed = true;
}
newNameParts[trimmedIndex] = new ItemNamePart(proposedText + (trimmed ? "..." : ""));
if (trimmed) break;
}
return newNameParts.Where(f => f is not null).ToList()!;
}
private static List<ItemNamePart> GetNamePartsForWidthPessimistic(IList<ItemNamePart> nameParts, double maxWidth)
{
var newNameParts = new List<ItemNamePart>(nameParts);
foreach (var namePart in nameParts)
{
var baseTextLength = newNameParts.Select(p => p.Text.Length).Sum();
var proposedText = namePart.Text;
var trimmed = false;
while ((baseTextLength + 3) * PixelPerChar > maxWidth && proposedText != "")
{
proposedText = proposedText[0..^1];
trimmed = true;
}
if (!string.IsNullOrWhiteSpace(proposedText)) newNameParts.Add(new ItemNamePart(proposedText, namePart.IsSpecial));
if (trimmed) break;
}
if (newNameParts.Last().IsSpecial)
{
newNameParts.Add(new ItemNamePart("..."));
}
else
{
var last = newNameParts.Last();
last.Text += "...";
}
return newNameParts;
}
}

View File

@@ -1,27 +1,26 @@
using System.Globalization;
using Avalonia.Data.Converters;
namespace FileTime.GuiApp.Converters
namespace FileTime.GuiApp.Converters;
public class SplitStringConverter : IValueConverter
{
public class SplitStringConverter : IValueConverter
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
if (value is string path && parameter is string separator)
{
if (value is string path && parameter is string separator)
{
return path.Split(separator);
}
else if (value is string path2 && parameter is char separator2)
{
return path2.Split(separator2);
}
return value;
return path.Split(separator);
}
else if (value is string path2 && parameter is char separator2)
{
return path2.Split(separator2);
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
return value;
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

View File

@@ -1,7 +1,6 @@
namespace FileTime.GuiApp
namespace FileTime.GuiApp;
public static class DI
{
public static class DI
{
public static IServiceProvider ServiceProvider { get; set; } = null!;
}
public static IServiceProvider ServiceProvider { get; set; } = null!;
}

View File

@@ -1,10 +1,9 @@
using FileTime.GuiApp.Configuration;
namespace FileTime.GuiApp.Extensions
namespace FileTime.GuiApp.Extensions;
public static class KeyConfigExtensions
{
public static class KeyConfigExtensions
{
public static bool AreKeysEqual(this IReadOnlyList<KeyConfig> collection1, IReadOnlyList<KeyConfig> collection2)
public static bool AreKeysEqual(this IReadOnlyList<KeyConfig> collection1, IReadOnlyList<KeyConfig> collection2)
=> collection1.Count == collection2.Count && collection1.Zip(collection2).All(t => t.First.AreEquals(t.Second));
}
}

View File

@@ -6,6 +6,10 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
</PropertyGroup>
<ItemGroup>
<None Remove="Assets\filetime.ico" />
</ItemGroup>

View File

@@ -1,24 +1,23 @@
using Serilog.Core;
using Serilog.Events;
namespace FileTime.GuiApp.Logging
namespace FileTime.GuiApp.Logging;
public class ToastMessageSink : ILogEventSink
{
public class ToastMessageSink : ILogEventSink
//private readonly IDialogService dialogService;
public ToastMessageSink(/*IDialogService dialogService*/)
{
//private readonly IDialogService dialogService;
public ToastMessageSink(/*IDialogService dialogService*/)
{
//this.dialogService = dialogService;
}
public void Emit(LogEvent logEvent)
{
/*if (logEvent.Level >= LogEventLevel.Error)
{
var message = logEvent.RenderMessage();
dialogService.ShowToastMessage(message);
}*/
}
//this.dialogService = dialogService;
}
}
public void Emit(LogEvent logEvent)
{
/*if (logEvent.Level >= LogEventLevel.Error)
{
var message = logEvent.RenderMessage();
dialogService.ShowToastMessage(message);
}*/
}
}

View File

@@ -1,20 +1,19 @@
namespace FileTime.GuiApp.Models
namespace FileTime.GuiApp.Models;
public class InputElementWrapper
{
public class InputElementWrapper
/*public InputElement InputElement { get; }
public string Value { get; set; }
public object? Option { get; set; }
public char? PasswordChar { get; set; }
public InputElementWrapper(InputElement inputElement, string? defaultValue = null)
{
/*public InputElement InputElement { get; }
public string Value { get; set; }
public object? Option { get; set; }
public char? PasswordChar { get; set; }
public InputElementWrapper(InputElement inputElement, string? defaultValue = null)
{
InputElement = inputElement;
Value = defaultValue ?? "";
PasswordChar = inputElement.InputType == InputType.Password ? '*' : null;
}*/
}
}
InputElement = inputElement;
Value = defaultValue ?? "";
PasswordChar = inputElement.InputType == InputType.Password ? '*' : null;
}*/
}

View File

@@ -2,12 +2,11 @@ using System.Reactive.Concurrency;
using FileTime.App.Core.Services;
using ReactiveUI;
namespace FileTime.GuiApp.Services
{
public class AvaloniaRxSchedulerService : IRxSchedulerService
{
public IScheduler GetUIScheduler() => RxApp.MainThreadScheduler;
namespace FileTime.GuiApp.Services;
public IScheduler GetWorkerScheduler() => RxApp.TaskpoolScheduler;
}
public class AvaloniaRxSchedulerService : IRxSchedulerService
{
public IScheduler GetUIScheduler() => RxApp.MainThreadScheduler;
public IScheduler GetWorkerScheduler() => RxApp.TaskpoolScheduler;
}

View File

@@ -10,142 +10,141 @@ using FileTime.GuiApp.Models;
using FileTime.GuiApp.ViewModels;
using Microsoft.Extensions.Logging;
namespace FileTime.GuiApp.Services
namespace FileTime.GuiApp.Services;
public class DefaultModeKeyInputHandler : IDefaultModeKeyInputHandler
{
public class DefaultModeKeyInputHandler : IDefaultModeKeyInputHandler
private readonly IGuiAppState _appState;
private readonly IKeyboardConfigurationService _keyboardConfigurationService;
private readonly List<KeyConfig[]> _keysToSkip = new();
private ITabViewModel? _selectedTab;
private IContainer? _currentLocation;
private readonly ILogger<DefaultModeKeyInputHandler> _logger;
private readonly ICommandHandlerService _commandHandlerService;
public DefaultModeKeyInputHandler(
IGuiAppState appState,
IKeyboardConfigurationService keyboardConfigurationService,
ILogger<DefaultModeKeyInputHandler> logger,
ICommandHandlerService commandHandlerService)
{
private readonly IGuiAppState _appState;
private readonly IKeyboardConfigurationService _keyboardConfigurationService;
private readonly List<KeyConfig[]> _keysToSkip = new();
private ITabViewModel? _selectedTab;
private IContainer? _currentLocation;
private readonly ILogger<DefaultModeKeyInputHandler> _logger;
private readonly ICommandHandlerService _commandHandlerService;
_appState = appState;
_keyboardConfigurationService = keyboardConfigurationService;
_logger = logger;
_commandHandlerService = commandHandlerService;
public DefaultModeKeyInputHandler(
IGuiAppState appState,
IKeyboardConfigurationService keyboardConfigurationService,
ILogger<DefaultModeKeyInputHandler> logger,
ICommandHandlerService commandHandlerService)
_appState.SelectedTab.Subscribe(t => _selectedTab = t);
_appState.SelectedTab.Select(t => t == null ? Observable.Return<IContainer?>(null) : t.CurrentLocation!).Switch().Subscribe(l => _currentLocation = l);
_keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.Up) });
_keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.Down) });
_keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.Tab) });
_keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.PageDown) });
_keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.PageUp) });
_keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.F4, alt: true) });
_keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.LWin) });
_keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.RWin) });
}
public async Task HandleInputKey(Key key, SpecialKeysStatus specialKeysStatus, Action<bool> setHandled)
{
var keyWithModifiers = new KeyConfig(key, shift: specialKeysStatus.IsShiftPressed, alt: specialKeysStatus.IsAltPressed, ctrl: specialKeysStatus.IsCtrlPressed);
_appState.PreviousKeys.Add(keyWithModifiers);
var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys));
selectedCommandBinding ??= _keyboardConfigurationService.CommandBindings.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys));
if (key == Key.Escape)
{
_appState = appState;
_keyboardConfigurationService = keyboardConfigurationService;
_logger = logger;
_commandHandlerService = commandHandlerService;
_appState.SelectedTab.Subscribe(t => _selectedTab = t);
_appState.SelectedTab.Select(t => t == null ? Observable.Return<IContainer?>(null) : t.CurrentLocation!).Switch().Subscribe(l => _currentLocation = l);
_keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.Up) });
_keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.Down) });
_keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.Tab) });
_keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.PageDown) });
_keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.PageUp) });
_keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.F4, alt: true) });
_keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.LWin) });
_keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.RWin) });
}
public async Task HandleInputKey(Key key, SpecialKeysStatus specialKeysStatus, Action<bool> setHandled)
{
var keyWithModifiers = new KeyConfig(key, shift: specialKeysStatus.IsShiftPressed, alt: specialKeysStatus.IsAltPressed, ctrl: specialKeysStatus.IsCtrlPressed);
_appState.PreviousKeys.Add(keyWithModifiers);
var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys));
selectedCommandBinding ??= _keyboardConfigurationService.CommandBindings.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys));
if (key == Key.Escape)
var doGeneralReset = false;
if (_appState.PreviousKeys.Count > 1 || _appState.IsAllShortcutVisible || _appState.MessageBoxText != null)
{
var doGeneralReset = false;
if (_appState.PreviousKeys.Count > 1 || _appState.IsAllShortcutVisible || _appState.MessageBoxText != null)
{
doGeneralReset = true;
}
/*else if (_currentLocation.Container.CanHandleEscape)
{
var escapeResult = await _currentLocation.Container.HandleEscape();
if (escapeResult.NavigateTo != null)
{
setHandled(true);
_appState.PreviousKeys.Clear();
await _appState.SelectedTab.OpenContainer(escapeResult.NavigateTo);
}
else
{
if (escapeResult.Handled)
{
_appState.PreviousKeys.Clear();
}
else
{
doGeneralReset = true;
}
}
}*/
if (doGeneralReset)
doGeneralReset = true;
}
/*else if (_currentLocation.Container.CanHandleEscape)
{
var escapeResult = await _currentLocation.Container.HandleEscape();
if (escapeResult.NavigateTo != null)
{
setHandled(true);
_appState.IsAllShortcutVisible = false;
_appState.MessageBoxText = null;
_appState.PreviousKeys.Clear();
_appState.PossibleCommands = new();
}
}
else if (key == Key.Enter
&& _appState.MessageBoxText != null)
{
_appState.PreviousKeys.Clear();
//_dialogService.ProcessMessageBox();
setHandled(true);
}
else if (selectedCommandBinding != null)
{
setHandled(true);
_appState.PreviousKeys.Clear();
_appState.PossibleCommands = new();
await CallCommandAsync(selectedCommandBinding.Command);
}
else if (_keysToSkip.Any(k => k.AreKeysEqual(_appState.PreviousKeys)))
{
_appState.PreviousKeys.Clear();
_appState.PossibleCommands = new();
return;
}
else if (_appState.PreviousKeys.Count == 2)
{
setHandled(true);
_appState.NoCommandFound = true;
_appState.PreviousKeys.Clear();
_appState.PossibleCommands = new();
}
else
{
setHandled(true);
var possibleCommands = _keyboardConfigurationService.AllShortcut.Where(c => c.Keys[0].AreEquals(keyWithModifiers)).ToList();
if (possibleCommands.Count == 0)
{
_appState.NoCommandFound = true;
_appState.PreviousKeys.Clear();
await _appState.SelectedTab.OpenContainer(escapeResult.NavigateTo);
}
else
{
_appState.PossibleCommands = possibleCommands;
if (escapeResult.Handled)
{
_appState.PreviousKeys.Clear();
}
else
{
doGeneralReset = true;
}
}
}*/
if (doGeneralReset)
{
setHandled(true);
_appState.IsAllShortcutVisible = false;
_appState.MessageBoxText = null;
_appState.PreviousKeys.Clear();
_appState.PossibleCommands = new();
}
}
private async Task CallCommandAsync(Commands command)
else if (key == Key.Enter
&& _appState.MessageBoxText != null)
{
try
_appState.PreviousKeys.Clear();
//_dialogService.ProcessMessageBox();
setHandled(true);
}
else if (selectedCommandBinding != null)
{
setHandled(true);
_appState.PreviousKeys.Clear();
_appState.PossibleCommands = new();
await CallCommandAsync(selectedCommandBinding.Command);
}
else if (_keysToSkip.Any(k => k.AreKeysEqual(_appState.PreviousKeys)))
{
_appState.PreviousKeys.Clear();
_appState.PossibleCommands = new();
return;
}
else if (_appState.PreviousKeys.Count == 2)
{
setHandled(true);
_appState.NoCommandFound = true;
_appState.PreviousKeys.Clear();
_appState.PossibleCommands = new();
}
else
{
setHandled(true);
var possibleCommands = _keyboardConfigurationService.AllShortcut.Where(c => c.Keys[0].AreEquals(keyWithModifiers)).ToList();
if (possibleCommands.Count == 0)
{
await _commandHandlerService.HandleCommandAsync(command);
_appState.NoCommandFound = true;
_appState.PreviousKeys.Clear();
}
catch (Exception e)
else
{
_logger.LogError(e, "Unknown error while running command. {Command} {Error}", command, e);
_appState.PossibleCommands = possibleCommands;
}
}
}
private async Task CallCommandAsync(Commands command)
{
try
{
await _commandHandlerService.HandleCommandAsync(command);
}
catch (Exception e)
{
_logger.LogError(e, "Unknown error while running command. {Command} {Error}", command, e);
}
}
}

View File

@@ -4,53 +4,52 @@ using FileTime.GuiApp.Configuration;
using FileTime.GuiApp.Models;
using FileTime.GuiApp.ViewModels;
namespace FileTime.GuiApp.Services
{
public class KeyInputHandlerService : IKeyInputHandlerService
{
private readonly IGuiAppState _appState;
private readonly IDefaultModeKeyInputHandler _defaultModeKeyInputHandler;
private readonly IRapidTravelModeKeyInputHandler _rapidTravelModeKeyInputHandler;
namespace FileTime.GuiApp.Services;
public KeyInputHandlerService(
IGuiAppState appState,
IDefaultModeKeyInputHandler defaultModeKeyInputHandler,
IRapidTravelModeKeyInputHandler rapidTravelModeKeyInputHandler
)
public class KeyInputHandlerService : IKeyInputHandlerService
{
private readonly IGuiAppState _appState;
private readonly IDefaultModeKeyInputHandler _defaultModeKeyInputHandler;
private readonly IRapidTravelModeKeyInputHandler _rapidTravelModeKeyInputHandler;
public KeyInputHandlerService(
IGuiAppState appState,
IDefaultModeKeyInputHandler defaultModeKeyInputHandler,
IRapidTravelModeKeyInputHandler rapidTravelModeKeyInputHandler
)
{
_appState = appState;
_defaultModeKeyInputHandler = defaultModeKeyInputHandler;
_rapidTravelModeKeyInputHandler = rapidTravelModeKeyInputHandler;
}
public async Task ProcessKeyDown(Key key, KeyModifiers keyModifiers, Action<bool> setHandled)
{
if (key == Key.LeftAlt
|| key == Key.RightAlt
|| key == Key.LeftShift
|| key == Key.RightShift
|| key == Key.LeftCtrl
|| key == Key.RightCtrl)
{
_appState = appState;
_defaultModeKeyInputHandler = defaultModeKeyInputHandler;
_rapidTravelModeKeyInputHandler = rapidTravelModeKeyInputHandler;
return;
}
public async Task ProcessKeyDown(Key key, KeyModifiers keyModifiers, Action<bool> setHandled)
//_appState.NoCommandFound = false;
var isAltPressed = (keyModifiers & KeyModifiers.Alt) == KeyModifiers.Alt;
var isShiftPressed = (keyModifiers & KeyModifiers.Shift) == KeyModifiers.Shift;
var isCtrlPressed = (keyModifiers & KeyModifiers.Control) == KeyModifiers.Control;
var specialKeyStatus = new SpecialKeysStatus(isAltPressed, isShiftPressed, isCtrlPressed);
if (_appState.ViewMode == ViewMode.Default)
{
if (key == Key.LeftAlt
|| key == Key.RightAlt
|| key == Key.LeftShift
|| key == Key.RightShift
|| key == Key.LeftCtrl
|| key == Key.RightCtrl)
{
return;
}
//_appState.NoCommandFound = false;
var isAltPressed = (keyModifiers & KeyModifiers.Alt) == KeyModifiers.Alt;
var isShiftPressed = (keyModifiers & KeyModifiers.Shift) == KeyModifiers.Shift;
var isCtrlPressed = (keyModifiers & KeyModifiers.Control) == KeyModifiers.Control;
var specialKeyStatus = new SpecialKeysStatus(isAltPressed, isShiftPressed, isCtrlPressed);
if (_appState.ViewMode == ViewMode.Default)
{
await _defaultModeKeyInputHandler.HandleInputKey(key, specialKeyStatus, setHandled);
}
else
{
await _rapidTravelModeKeyInputHandler.HandleInputKey(key, specialKeyStatus, setHandled);
}
await _defaultModeKeyInputHandler.HandleInputKey(key, specialKeyStatus, setHandled);
}
else
{
await _rapidTravelModeKeyInputHandler.HandleInputKey(key, specialKeyStatus, setHandled);
}
}
}

View File

@@ -2,60 +2,59 @@ using FileTime.App.Core.Command;
using FileTime.GuiApp.Configuration;
using Microsoft.Extensions.Options;
namespace FileTime.GuiApp.Services
namespace FileTime.GuiApp.Services;
public class KeyboardConfigurationService : IKeyboardConfigurationService
{
public class KeyboardConfigurationService : IKeyboardConfigurationService
public IReadOnlyList<CommandBindingConfiguration> CommandBindings { get; }
public IReadOnlyList<CommandBindingConfiguration> UniversalCommandBindings { get; }
public IReadOnlyList<CommandBindingConfiguration> AllShortcut { get; }
public KeyboardConfigurationService(IOptions<KeyBindingConfiguration> keyBindingConfiguration)
{
public IReadOnlyList<CommandBindingConfiguration> CommandBindings { get; }
public IReadOnlyList<CommandBindingConfiguration> UniversalCommandBindings { get; }
public IReadOnlyList<CommandBindingConfiguration> AllShortcut { get; }
var commandBindings = new List<CommandBindingConfiguration>();
var universalCommandBindings = new List<CommandBindingConfiguration>();
IEnumerable<CommandBindingConfiguration> keyBindings = keyBindingConfiguration.Value.KeyBindings;
public KeyboardConfigurationService(IOptions<KeyBindingConfiguration> keyBindingConfiguration)
if (keyBindingConfiguration.Value.UseDefaultBindings)
{
var commandBindings = new List<CommandBindingConfiguration>();
var universalCommandBindings = new List<CommandBindingConfiguration>();
IEnumerable<CommandBindingConfiguration> keyBindings = keyBindingConfiguration.Value.KeyBindings;
if (keyBindingConfiguration.Value.UseDefaultBindings)
{
keyBindings = keyBindings.Concat(keyBindingConfiguration.Value.DefaultKeyBindings);
}
foreach (var keyBinding in keyBindings)
{
if (keyBinding.Command == Commands.None)
{
throw new FormatException($"No command is set in keybinding for keys '{keyBinding.KeysDisplayText}'");
}
else if (keyBinding.Keys.Count == 0)
{
throw new FormatException($"No keys set in keybinding for command '{keyBinding.Command}'.");
}
if (IsUniversal(keyBinding))
{
universalCommandBindings.Add(keyBinding);
}
else
{
commandBindings.Add(keyBinding);
}
}
CommandBindings = commandBindings.AsReadOnly();
UniversalCommandBindings = universalCommandBindings.AsReadOnly();
AllShortcut = new List<CommandBindingConfiguration>(CommandBindings.Concat(UniversalCommandBindings)).AsReadOnly();
keyBindings = keyBindings.Concat(keyBindingConfiguration.Value.DefaultKeyBindings);
}
private static bool IsUniversal(CommandBindingConfiguration keyMapping)
foreach (var keyBinding in keyBindings)
{
return keyMapping.Command == Commands.GoUp
|| keyMapping.Command == Commands.Open
|| keyMapping.Command == Commands.OpenOrRun
|| keyMapping.Command == Commands.MoveCursorUp
|| keyMapping.Command == Commands.MoveCursorDown
|| keyMapping.Command == Commands.MoveCursorUpPage
|| keyMapping.Command == Commands.MoveCursorDownPage;
if (keyBinding.Command == Commands.None)
{
throw new FormatException($"No command is set in keybinding for keys '{keyBinding.KeysDisplayText}'");
}
else if (keyBinding.Keys.Count == 0)
{
throw new FormatException($"No keys set in keybinding for command '{keyBinding.Command}'.");
}
if (IsUniversal(keyBinding))
{
universalCommandBindings.Add(keyBinding);
}
else
{
commandBindings.Add(keyBinding);
}
}
CommandBindings = commandBindings.AsReadOnly();
UniversalCommandBindings = universalCommandBindings.AsReadOnly();
AllShortcut = new List<CommandBindingConfiguration>(CommandBindings.Concat(UniversalCommandBindings)).AsReadOnly();
}
private static bool IsUniversal(CommandBindingConfiguration keyMapping)
{
return keyMapping.Command == Commands.GoUp
|| keyMapping.Command == Commands.Open
|| keyMapping.Command == Commands.OpenOrRun
|| keyMapping.Command == Commands.MoveCursorUp
|| keyMapping.Command == Commands.MoveCursorDown
|| keyMapping.Command == Commands.MoveCursorUpPage
|| keyMapping.Command == Commands.MoveCursorDownPage;
}
}

View File

@@ -1,88 +1,87 @@
using Avalonia.Input;
using FileTime.GuiApp.Models;
namespace FileTime.GuiApp.Services
{
public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler
{
public async Task HandleInputKey(Key key, SpecialKeysStatus specialKeysStatus, Action<bool> setHandled)
{
/*var keyString = key.ToString();
var updateRapidTravelFilter = false;
namespace FileTime.GuiApp.Services;
if (key == Key.Escape)
public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler
{
public async Task HandleInputKey(Key key, SpecialKeysStatus specialKeysStatus, Action<bool> setHandled)
{
/*var keyString = key.ToString();
var updateRapidTravelFilter = false;
if (key == Key.Escape)
{
setHandled(true);
if (_appState.IsAllShortcutVisible)
{
setHandled(true);
if (_appState.IsAllShortcutVisible)
{
_appState.IsAllShortcutVisible = false;
}
else if (_appState.MessageBoxText != null)
{
_appState.MessageBoxText = null;
}
else
{
await _appState.ExitRapidTravelMode();
}
_appState.IsAllShortcutVisible = false;
}
else if (key == Key.Back)
else if (_appState.MessageBoxText != null)
{
if (_appState.RapidTravelText.Length > 0)
{
setHandled(true);
_appState.RapidTravelText = _appState.RapidTravelText.Substring(0, _appState.RapidTravelText.Length - 1);
updateRapidTravelFilter = true;
}
}
else if (keyString.Length == 1)
{
setHandled(true);
_appState.RapidTravelText += keyString.ToLower();
updateRapidTravelFilter = true;
_appState.MessageBoxText = null;
}
else
{
var currentKeyAsList = new List<KeyConfig>() { new KeyConfig(key) };
var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.FirstOrDefault(c => AreKeysEqual(c.Keys, currentKeyAsList));
if (selectedCommandBinding != null)
{
setHandled(true);
await CallCommandAsync(selectedCommandBinding.Command);
}
await _appState.ExitRapidTravelMode();
}
if (updateRapidTravelFilter)
{
var currentLocation = await _appState.SelectedTab.CurrentLocation.Container.WithoutVirtualContainer(MainPageViewModel.RAPIDTRAVEL);
var newLocation = new VirtualContainer(
currentLocation,
new List<Func<IEnumerable<IContainer>, IEnumerable<IContainer>>>()
{
container => container.Where(c => c.Name.ToLower().Contains(_appState.RapidTravelText))
},
new List<Func<IEnumerable<IElement>, IEnumerable<IElement>>>()
{
element => element.Where(e => e.Name.ToLower().Contains(_appState.RapidTravelText))
},
virtualContainerName: MainPageViewModel.RAPIDTRAVEL
);
await newLocation.Init();
await _appState.SelectedTab.OpenContainer(newLocation);
var selectedItemName = _appState.SelectedTab.SelectedItem?.Item.Name;
var currentLocationItems = await _appState.SelectedTab.CurrentLocation.GetItems();
if (currentLocationItems.FirstOrDefault(i => string.Equals(i.Item.Name, _appState.RapidTravelText, StringComparison.OrdinalIgnoreCase)) is IItemViewModel matchItem)
{
await _appState.SelectedTab.SetCurrentSelectedItem(matchItem.Item);
}
else if (!currentLocationItems.Select(i => i.Item.Name).Any(n => n == selectedItemName))
{
await _appState.SelectedTab.MoveCursorToFirst();
}
}*/
}
else if (key == Key.Back)
{
if (_appState.RapidTravelText.Length > 0)
{
setHandled(true);
_appState.RapidTravelText = _appState.RapidTravelText.Substring(0, _appState.RapidTravelText.Length - 1);
updateRapidTravelFilter = true;
}
}
else if (keyString.Length == 1)
{
setHandled(true);
_appState.RapidTravelText += keyString.ToLower();
updateRapidTravelFilter = true;
}
else
{
var currentKeyAsList = new List<KeyConfig>() { new KeyConfig(key) };
var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.FirstOrDefault(c => AreKeysEqual(c.Keys, currentKeyAsList));
if (selectedCommandBinding != null)
{
setHandled(true);
await CallCommandAsync(selectedCommandBinding.Command);
}
}
if (updateRapidTravelFilter)
{
var currentLocation = await _appState.SelectedTab.CurrentLocation.Container.WithoutVirtualContainer(MainPageViewModel.RAPIDTRAVEL);
var newLocation = new VirtualContainer(
currentLocation,
new List<Func<IEnumerable<IContainer>, IEnumerable<IContainer>>>()
{
container => container.Where(c => c.Name.ToLower().Contains(_appState.RapidTravelText))
},
new List<Func<IEnumerable<IElement>, IEnumerable<IElement>>>()
{
element => element.Where(e => e.Name.ToLower().Contains(_appState.RapidTravelText))
},
virtualContainerName: MainPageViewModel.RAPIDTRAVEL
);
await newLocation.Init();
await _appState.SelectedTab.OpenContainer(newLocation);
var selectedItemName = _appState.SelectedTab.SelectedItem?.Item.Name;
var currentLocationItems = await _appState.SelectedTab.CurrentLocation.GetItems();
if (currentLocationItems.FirstOrDefault(i => string.Equals(i.Item.Name, _appState.RapidTravelText, StringComparison.OrdinalIgnoreCase)) is IItemViewModel matchItem)
{
await _appState.SelectedTab.SetCurrentSelectedItem(matchItem.Item);
}
else if (!currentLocationItems.Select(i => i.Item.Name).Any(n => n == selectedItemName))
{
await _appState.SelectedTab.MoveCursorToFirst();
}
}*/
}
}

View File

@@ -1,7 +1,6 @@
namespace FileTime.GuiApp.ViewModels
namespace FileTime.GuiApp.ViewModels;
public interface IMainWindowViewModelBase
{
public interface IMainWindowViewModelBase
{
bool Loading { get; }
}
bool Loading { get; }
}

View File

@@ -1,16 +1,15 @@
using Avalonia.Media;
namespace FileTime.GuiApp.ViewModels
{
public class ItemNamePartViewModel
{
public string Text { get; set; }
public TextDecorationCollection? TextDecorations { get; set; }
namespace FileTime.GuiApp.ViewModels;
public ItemNamePartViewModel(string text, TextDecorationCollection? textDecorations)
{
Text = text;
TextDecorations = textDecorations;
}
public class ItemNamePartViewModel
{
public string Text { get; set; }
public TextDecorationCollection? TextDecorations { get; set; }
public ItemNamePartViewModel(string text, TextDecorationCollection? textDecorations)
{
Text = text;
TextDecorations = textDecorations;
}
}

View File

@@ -1,7 +1,6 @@
namespace FileTime.GuiApp.ViewModels
namespace FileTime.GuiApp.ViewModels;
public class MainWindowLoadingViewModel : IMainWindowViewModelBase
{
public class MainWindowLoadingViewModel : IMainWindowViewModelBase
{
public bool Loading => true;
}
public bool Loading => true;
}

View File

@@ -11,49 +11,48 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using MvvmGen;
namespace FileTime.GuiApp.ViewModels
namespace FileTime.GuiApp.ViewModels;
[ViewModel]
[Inject(typeof(IAppState), "_appState")]
[Inject(typeof(ILocalContentProvider), "_localContentProvider")]
[Inject(typeof(IServiceProvider), PropertyName = "_serviceProvider")]
[Inject(typeof(ILogger<MainWindowViewModel>), PropertyName = "_logger")]
[Inject(typeof(IKeyInputHandlerService), PropertyName = "_keyInputHandlerService")]
public partial class MainWindowViewModel : IMainWindowViewModelBase
{
[ViewModel]
[Inject(typeof(IAppState), "_appState")]
[Inject(typeof(ILocalContentProvider), "_localContentProvider")]
[Inject(typeof(IServiceProvider), PropertyName = "_serviceProvider")]
[Inject(typeof(ILogger<MainWindowViewModel>), PropertyName = "_logger")]
[Inject(typeof(IKeyInputHandlerService), PropertyName = "_keyInputHandlerService")]
public partial class MainWindowViewModel : IMainWindowViewModelBase
public bool Loading => false;
public IAppState AppState => _appState;
public string Title { get; private set; }
partial void OnInitialize()
{
public bool Loading => false;
public IAppState AppState => _appState;
public string Title { get; private set; }
_logger?.LogInformation($"Starting {nameof(MainWindowViewModel)} initialization...");
partial void OnInitialize()
var version = Assembly.GetEntryAssembly()!.GetName().Version;
var versionString = "Unknwon version";
if (version != null)
{
_logger?.LogInformation($"Starting {nameof(MainWindowViewModel)} initialization...");
var version = Assembly.GetEntryAssembly()!.GetName().Version;
var versionString = "Unknwon version";
if (version != null)
versionString = $"{version.Major}.{version.Minor}.{version.Build}";
if (version.Revision != 0)
{
versionString = $"{version.Major}.{version.Minor}.{version.Build}";
if (version.Revision != 0)
{
versionString += $" ({version.Revision})";
}
}
Title = "FileTime " + versionString;
//TODO: refactor
if (AppState.Tabs.Count == 0)
{
var tab = _serviceProvider.GetInitableResolver<IContainer>(_localContentProvider).GetRequiredService<ITab>();
var tabViewModel = _serviceProvider.GetInitableResolver(tab, 1).GetRequiredService<ITabViewModel>();
_appState.AddTab(tabViewModel);
versionString += $" ({version.Revision})";
}
}
Title = "FileTime " + versionString;
public void ProcessKeyDown(Key key, KeyModifiers keyModifiers, Action<bool> setHandled)
//TODO: refactor
if (AppState.Tabs.Count == 0)
{
_keyInputHandlerService.ProcessKeyDown(key, keyModifiers, setHandled);
var tab = _serviceProvider.GetInitableResolver<IContainer>(_localContentProvider).GetRequiredService<ITab>();
var tabViewModel = _serviceProvider.GetInitableResolver(tab, 1).GetRequiredService<ITabViewModel>();
_appState.AddTab(tabViewModel);
}
}
}
public void ProcessKeyDown(Key key, KeyModifiers keyModifiers, Action<bool> setHandled)
{
_keyInputHandlerService.ProcessKeyDown(key, keyModifiers, setHandled);
}
}

View File

@@ -1,21 +1,20 @@
using Avalonia;
using Avalonia.Controls;
namespace FileTime.GuiApp.Views
namespace FileTime.GuiApp.Views;
public partial class ItemView : UserControl
{
public partial class ItemView : UserControl
public static readonly StyledProperty<bool> ShowAttributesProperty = AvaloniaProperty.Register<ItemView, bool>(nameof(ShowAttributes), true);
public bool ShowAttributes
{
public static readonly StyledProperty<bool> ShowAttributesProperty = AvaloniaProperty.Register<ItemView, bool>(nameof(ShowAttributes), true);
public bool ShowAttributes
{
get => GetValue(ShowAttributesProperty);
set => SetValue(ShowAttributesProperty, value);
}
public ItemView()
{
InitializeComponent();
}
get => GetValue(ShowAttributesProperty);
set => SetValue(ShowAttributesProperty, value);
}
}
public ItemView()
{
InitializeComponent();
}
}

View File

@@ -7,66 +7,65 @@ using FileTime.GuiApp.ViewModels;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace FileTime.GuiApp.Views
namespace FileTime.GuiApp.Views;
public partial class MainWindow : Window
{
public partial class MainWindow : Window
private readonly ILogger<MainWindow>? _logger;
private InputElementWrapper? _inputElementWrapper;
public MainWindowViewModel? ViewModel
{
private readonly ILogger<MainWindow>? _logger;
private InputElementWrapper? _inputElementWrapper;
public MainWindowViewModel? ViewModel
get => DataContext as MainWindowViewModel;
set
{
get => DataContext as MainWindowViewModel;
set
if (value != DataContext)
{
if (value != DataContext)
{
DataContext = value;
}
}
}
public MainWindow()
{
_logger = DI.ServiceProvider.GetService<ILogger<MainWindow>>();
_logger?.LogInformation($"Starting {nameof(MainWindow)} initialization...");
InitializeComponent();
}
private void OnWindowOpened(object sender, EventArgs e)
{
if (DataContext is not MainWindowViewModel)
{
_logger?.LogInformation($"{nameof(MainWindow)} opened, starting {nameof(MainWindowViewModel)} initialization...");
ViewModel = DI.ServiceProvider.GetRequiredService<MainWindowViewModel>();
}
}
private void OnKeyDown(object sender, KeyEventArgs e)
{
if (_inputElementWrapper == null)
{
ViewModel?.ProcessKeyDown(e.Key, e.KeyModifiers, h => e.Handled = h);
}
}
private void HeaderPointerPressed(object sender, PointerPressedEventArgs e)
{
if (e.ClickCount == 2)
{
if (WindowState == WindowState.Maximized)
{
WindowState = WindowState.Normal;
}
else
{
WindowState = WindowState.Maximized;
}
}
else
{
BeginMoveDrag(e);
DataContext = value;
}
}
}
public MainWindow()
{
_logger = DI.ServiceProvider.GetService<ILogger<MainWindow>>();
_logger?.LogInformation($"Starting {nameof(MainWindow)} initialization...");
InitializeComponent();
}
private void OnWindowOpened(object sender, EventArgs e)
{
if (DataContext is not MainWindowViewModel)
{
_logger?.LogInformation($"{nameof(MainWindow)} opened, starting {nameof(MainWindowViewModel)} initialization...");
ViewModel = DI.ServiceProvider.GetRequiredService<MainWindowViewModel>();
}
}
private void OnKeyDown(object sender, KeyEventArgs e)
{
if (_inputElementWrapper == null)
{
ViewModel?.ProcessKeyDown(e.Key, e.KeyModifiers, h => e.Handled = h);
}
}
private void HeaderPointerPressed(object sender, PointerPressedEventArgs e)
{
if (e.ClickCount == 2)
{
if (WindowState == WindowState.Maximized)
{
WindowState = WindowState.Normal;
}
else
{
WindowState = WindowState.Maximized;
}
}
else
{
BeginMoveDrag(e);
}
}
}