InputHandler, CreateContainer user command

This commit is contained in:
2022-05-19 22:46:25 +02:00
parent 40f36ed845
commit ced0c88a10
28 changed files with 358 additions and 52 deletions

View File

@@ -1,19 +0,0 @@
namespace FileTime.GuiApp.Models;
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)
{
InputElement = inputElement;
Value = defaultValue ?? "";
PasswordChar = inputElement.InputType == InputType.Password ? '*' : null;
}*/
}

View File

@@ -54,8 +54,8 @@ public class DefaultModeKeyInputHandler : IDefaultModeKeyInputHandler
var keyWithModifiers = new KeyConfig(key, shift: specialKeysStatus.IsShiftPressed, alt: specialKeysStatus.IsAltPressed, ctrl: specialKeysStatus.IsCtrlPressed);
_appState.PreviousKeys.Add(keyWithModifiers);
var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.Values.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys));
selectedCommandBinding ??= _keyboardConfigurationService.CommandBindings.Values.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys));
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)
{
@@ -125,7 +125,7 @@ public class DefaultModeKeyInputHandler : IDefaultModeKeyInputHandler
else
{
setHandled(true);
var possibleCommands = _keyboardConfigurationService.AllShortcut.Values.Where(c => c.Keys[0].AreEquals(keyWithModifiers)).ToList();
var possibleCommands = _keyboardConfigurationService.AllShortcut.Where(c => c.Keys[0].AreEquals(keyWithModifiers)).ToList();
if (possibleCommands.Count == 0)
{

View File

@@ -0,0 +1,59 @@
using System.Reactive.Linq;
using DynamicData;
using FileTime.App.Core.Services;
using FileTime.Core.Interactions;
using FileTime.GuiApp.ViewModels;
namespace FileTime.GuiApp.Services;
public class DialogService : IDialogService
{
private readonly IModalService _modalService;
public IObservable<ReadInputsViewModel?> ReadInput { get; }
public DialogService(IModalService modalService)
{
_modalService = modalService;
ReadInput = modalService
.OpenModals
.ToCollection()
.Select(modals =>
(ReadInputsViewModel?)modals.FirstOrDefault(m => m is ReadInputsViewModel)
)
.Publish(null)
.RefCount();
}
public void ReadInputs(IEnumerable<IInputElement> inputs, Action inputHandler, Action? cancelHandler = null)
{
var modalViewModel = new ReadInputsViewModel(HandleReadInputsSuccess, HandleReadInputsCancel)
{
Inputs = inputs.ToList(),
SuccessHandler = inputHandler,
CancelHandler = cancelHandler
};
_modalService.OpenModal(modalViewModel);
}
private void HandleReadInputsSuccess(ReadInputsViewModel readInputsViewModel)
{
_modalService.CloseModal(readInputsViewModel);
readInputsViewModel.SuccessHandler.Invoke();
}
private void HandleReadInputsCancel(ReadInputsViewModel readInputsViewModel)
{
_modalService.CloseModal(readInputsViewModel);
readInputsViewModel.CancelHandler?.Invoke();
}
public Task<bool> ReadInputs(IEnumerable<IInputElement> fields)
{
var taskCompletionSource = new TaskCompletionSource<bool>();
ReadInputs(fields, () => taskCompletionSource.SetResult(true), () => taskCompletionSource.SetResult(false));
return taskCompletionSource.Task;
}
}

View File

@@ -6,14 +6,12 @@ namespace FileTime.GuiApp.Services;
public class KeyboardConfigurationService : IKeyboardConfigurationService
{
public IReadOnlyDictionary<string, CommandBindingConfiguration> CommandBindings { get; }
public IReadOnlyDictionary<string, CommandBindingConfiguration> UniversalCommandBindings { get; }
public IReadOnlyDictionary<string, CommandBindingConfiguration> AllShortcut { get; }
public IReadOnlyList<CommandBindingConfiguration> CommandBindings { get; }
public IReadOnlyList<CommandBindingConfiguration> UniversalCommandBindings { get; }
public IReadOnlyList<CommandBindingConfiguration> AllShortcut { get; }
public KeyboardConfigurationService(IOptions<KeyBindingConfiguration> keyBindingConfiguration)
{
var commandBindings = new Dictionary<string, CommandBindingConfiguration>();
var universalCommandBindings = new Dictionary<string, CommandBindingConfiguration>();
IEnumerable<CommandBindingConfiguration> keyBindings = keyBindingConfiguration.Value.KeyBindings;
if (keyBindingConfiguration.Value.UseDefaultBindings)
@@ -21,6 +19,8 @@ public class KeyboardConfigurationService : IKeyboardConfigurationService
keyBindings = keyBindings.Concat(keyBindingConfiguration.Value.DefaultKeyBindings);
}
var commandBindings = new List<CommandBindingConfiguration>();
var universalCommandBindings = new List<CommandBindingConfiguration>();
foreach (var keyBinding in keyBindings)
{
if (string.IsNullOrWhiteSpace(keyBinding.Command))
@@ -34,17 +34,17 @@ public class KeyboardConfigurationService : IKeyboardConfigurationService
if (IsUniversal(keyBinding))
{
universalCommandBindings.Add(keyBinding.Command, keyBinding);
universalCommandBindings.Add(keyBinding);
}
else
{
commandBindings.Add(keyBinding.Command, keyBinding);
commandBindings.Add(keyBinding);
}
}
CommandBindings = new ReadOnlyDictionary<string, CommandBindingConfiguration>(commandBindings);
UniversalCommandBindings = new ReadOnlyDictionary<string, CommandBindingConfiguration>(universalCommandBindings);
AllShortcut = new ReadOnlyDictionary<string, CommandBindingConfiguration>(new Dictionary<string, CommandBindingConfiguration>(CommandBindings.Concat(UniversalCommandBindings)));
CommandBindings = commandBindings.AsReadOnly();
UniversalCommandBindings = universalCommandBindings.AsReadOnly();
AllShortcut = new List<CommandBindingConfiguration>(UniversalCommandBindings.Concat(CommandBindings)).AsReadOnly();
}
private static bool IsUniversal(CommandBindingConfiguration keyMapping)

View File

@@ -80,7 +80,7 @@ public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler
else
{
var currentKeyAsList = new List<KeyConfig>() {new KeyConfig(key)};
var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.Values.FirstOrDefault(c => c.Keys.AreKeysEqual(currentKeyAsList));
var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.FirstOrDefault(c => c.Keys.AreKeysEqual(currentKeyAsList));
if (selectedCommandBinding != null)
{
setHandled(true);

View File

@@ -21,6 +21,7 @@ namespace FileTime.GuiApp.ViewModels;
[Inject(typeof(IUserCommandHandlerService), PropertyAccessModifier = AccessModifier.Public)]
[Inject(typeof(LifecycleService), PropertyName = "_lifecycleService")]
[Inject(typeof(IItemPreviewService), PropertyAccessModifier = AccessModifier.Public)]
[Inject(typeof(IDialogService), PropertyAccessModifier = AccessModifier.Public)]
public partial class MainWindowViewModel : IMainWindowViewModelBase
{
public bool Loading => false;

View File

@@ -9,6 +9,7 @@
xmlns:vm="using:FileTime.GuiApp.ViewModels"
xmlns:config="using:FileTime.GuiApp.Configuration"
xmlns:appCoreModels="using:FileTime.App.Core.Models"
xmlns:interactions="using:FileTime.Core.Interactions"
Title="FileTime"
d:DesignHeight="450"
d:DesignWidth="800"
@@ -416,9 +417,12 @@
</Grid>
<Grid
IsVisible="{Binding ItemPreviewService.ItemPreview^,Converter={x:Static ObjectConverters.IsNotNull}}">
<TextBlock HorizontalAlignment="Center" Text="Don't know how to preview this item." IsVisible="{Binding ItemPreviewService.ItemPreview^.Mode, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static appCoreModels:ItemPreviewMode.Unknown}}"/>
<TextBlock HorizontalAlignment="Center" Text="Empty" IsVisible="{Binding ItemPreviewService.ItemPreview^.Mode, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static appCoreModels:ItemPreviewMode.Empty}}"/>
<ScrollViewer IsVisible="{Binding ItemPreviewService.ItemPreview^.Mode, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static appCoreModels:ItemPreviewMode.Text}}">
<TextBlock HorizontalAlignment="Center" Text="Don't know how to preview this item."
IsVisible="{Binding ItemPreviewService.ItemPreview^.Mode, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static appCoreModels:ItemPreviewMode.Unknown}}" />
<TextBlock HorizontalAlignment="Center" Text="Empty"
IsVisible="{Binding ItemPreviewService.ItemPreview^.Mode, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static appCoreModels:ItemPreviewMode.Empty}}" />
<ScrollViewer
IsVisible="{Binding ItemPreviewService.ItemPreview^.Mode, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static appCoreModels:ItemPreviewMode.Text}}">
<TextBox
IsReadOnly="True"
x:CompileBindings="False"
@@ -495,7 +499,72 @@
</Grid>
</Grid>
</Grid>
<!-- Borders -->
<Border
Background="{DynamicResource BarelyTransparentBackgroundColor}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
IsVisible="{Binding DialogService.ReadInput^, Converter={x:Static ObjectConverters.IsNotNull}}">
<Border
Background="{DynamicResource ContainerBackgroundBrush}"
Padding="20"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Grid RowDefinitions="Auto,Auto">
<ItemsControl
x:Name="InputList"
Items="{Binding DialogService.ReadInput^.Inputs}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid MinWidth="500" ColumnDefinitions="250,*" Margin="10,5" x:Name="ItemRoot">
<TextBlock
HorizontalAlignment="Left"
VerticalAlignment="Top"
Text="{Binding Label}" />
<Grid Grid.Column="1">
<TextBox
x:DataType="interactions:TextInputElement"
IsVisible="{Binding Type, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static interactions:InputType.Text}}"
VerticalAlignment="Top"
Text="{Binding Value, Mode=TwoWay}" />
<TextBox
x:DataType="interactions:PasswordInputElement"
IsVisible="{Binding Type, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static interactions:InputType.Password}}"
PasswordChar="{Binding PasswordChar}"
VerticalAlignment="Top"
Text="{Binding Value, Mode=TwoWay}" />
<ListBox
x:DataType="interactions:IOptionsInputElement"
Classes="RadioButtonListBox"
IsVisible="{Binding Type, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static interactions:InputType.Options}}"
Items="{Binding Options}"
SelectedItem="{Binding Value}" />
</Grid>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel
DataContext="{Binding DialogService.ReadInput^}"
Grid.Row="1"
Orientation="Horizontal"
Margin="0,10,0,0">
<Button
HorizontalContentAlignment="Center"
Width="80"
Command="{Binding ProcessCommand}"
Content="Ok" />
<Button
HorizontalContentAlignment="Center"
Width="80"
Margin="10,0,0,0"
Command="{Binding CancelCommand}"
Content="Cancel" />
</StackPanel>
</Grid>
</Border>
</Border>
</Grid>

View File

@@ -13,7 +13,6 @@ namespace FileTime.GuiApp.Views;
public partial class MainWindow : Window
{
private readonly ILogger<MainWindow>? _logger;
private InputElementWrapper? _inputElementWrapper;
public MainWindowViewModel? ViewModel
{
@@ -38,17 +37,15 @@ public partial class MainWindow : Window
{
if (DataContext is not MainWindowViewModel)
{
_logger?.LogInformation($"{nameof(MainWindow)} opened, starting {nameof(MainWindowViewModel)} initialization...");
_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);
}
ViewModel?.ProcessKeyDown(e.Key, e.KeyModifiers, h => e.Handled = h);
}
private void HeaderPointerPressed(object sender, PointerPressedEventArgs e)
@@ -78,7 +75,7 @@ public partial class MainWindow : Window
&& sender is StyledElement control)
{
IAbsolutePath? path = null;
if (control.DataContext is IHaveAbsolutePath {Path: { }} haveAbsolutePath)
if (control.DataContext is IHaveAbsolutePath { Path: { } } haveAbsolutePath)
{
path = haveAbsolutePath.Path;
}
@@ -102,7 +99,8 @@ public partial class MainWindow : Window
var resolvedItem = await path.ResolveAsync();
if (resolvedItem is not IContainer resolvedContainer) return;
await ViewModel.UserCommandHandlerService.HandleCommandAsync(new OpenContainerCommand(new AbsolutePath(resolvedContainer)));
await ViewModel.UserCommandHandlerService.HandleCommandAsync(
new OpenContainerCommand(new AbsolutePath(resolvedContainer)));
e.Handled = true;
}
}