TextBox, PropertyChangeHandler
This commit is contained in:
@@ -3,6 +3,7 @@ using FileTime.App.Core.Models;
|
||||
using FileTime.App.Core.Services;
|
||||
using FileTime.App.Core.ViewModels;
|
||||
using FileTime.ConsoleUI.App.KeyInputHandling;
|
||||
using GeneralInputKey;
|
||||
using TerminalUI;
|
||||
using TerminalUI.ConsoleDrivers;
|
||||
|
||||
@@ -54,7 +55,6 @@ public class App : IApplication
|
||||
_applicationContext.IsRunning = false;
|
||||
};
|
||||
|
||||
_mainWindow.Initialize();
|
||||
foreach (var rootView in _mainWindow.RootViews())
|
||||
{
|
||||
_applicationContext.EventLoop.AddViewToRender(rootView);
|
||||
@@ -63,6 +63,8 @@ public class App : IApplication
|
||||
_applicationContext.IsRunning = true;
|
||||
_renderThread.Start();
|
||||
|
||||
var focusManager = _applicationContext.FocusManager;
|
||||
|
||||
while (_applicationContext.IsRunning)
|
||||
{
|
||||
if (_consoleDriver.CanRead())
|
||||
@@ -76,13 +78,22 @@ public class App : IApplication
|
||||
(key.Modifiers & ConsoleModifiers.Shift) != 0,
|
||||
(key.Modifiers & ConsoleModifiers.Control) != 0
|
||||
);
|
||||
|
||||
|
||||
var keyEventArgs = new GeneralKeyEventArgs
|
||||
{
|
||||
Key = mappedKey
|
||||
Key = mappedKey,
|
||||
KeyChar = key.KeyChar,
|
||||
SpecialKeysStatus = specialKeysStatus
|
||||
};
|
||||
|
||||
_keyInputHandlerService.HandleKeyInput(keyEventArgs, specialKeysStatus);
|
||||
|
||||
if (focusManager.Focused is { } focused)
|
||||
{
|
||||
focused.HandleKeyInput(keyEventArgs);
|
||||
}
|
||||
else
|
||||
{
|
||||
_keyInputHandlerService.HandleKeyInput(keyEventArgs, specialKeysStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
129
src/ConsoleApp/FileTime.ConsoleUI.App/Controls/CommandPalette.cs
Normal file
129
src/ConsoleApp/FileTime.ConsoleUI.App/Controls/CommandPalette.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
using FileTime.App.CommandPalette.Services;
|
||||
using FileTime.App.CommandPalette.ViewModels;
|
||||
using FileTime.ConsoleUI.App.Styling;
|
||||
using GeneralInputKey;
|
||||
using TerminalUI.Controls;
|
||||
using TerminalUI.Extensions;
|
||||
using TerminalUI.Models;
|
||||
using TerminalUI.ViewExtensions;
|
||||
|
||||
namespace FileTime.ConsoleUI.App.Controls;
|
||||
|
||||
public class CommandPalette
|
||||
{
|
||||
private readonly ITheme _theme;
|
||||
private readonly ICommandPaletteService _commandPaletteService;
|
||||
|
||||
public CommandPalette(ITheme theme, ICommandPaletteService commandPaletteService)
|
||||
{
|
||||
_theme = theme;
|
||||
_commandPaletteService = commandPaletteService;
|
||||
}
|
||||
public Border<IRootViewModel> View()
|
||||
{
|
||||
var inputTextBox = new TextBox<IRootViewModel>()
|
||||
.WithKeyHandler(k =>
|
||||
{
|
||||
if (k.Key == Keys.Escape)
|
||||
{
|
||||
_commandPaletteService.CloseCommandPalette();
|
||||
}
|
||||
});
|
||||
|
||||
var root = new Border<IRootViewModel>
|
||||
{
|
||||
Margin = 5,
|
||||
Padding = 1,
|
||||
MaxWidth = 50,
|
||||
Content = new Grid<IRootViewModel>
|
||||
{
|
||||
RowDefinitionsObject = "Auto *",
|
||||
ChildInitializer =
|
||||
{
|
||||
new Border<IRootViewModel>
|
||||
{
|
||||
Margin = new Thickness(0, 0, 0, 2),
|
||||
Content = inputTextBox
|
||||
},
|
||||
new ListView<IRootViewModel, ICommandPaletteEntryViewModel>
|
||||
{
|
||||
Extensions =
|
||||
{
|
||||
new GridPositionExtension(0, 1)
|
||||
},
|
||||
ItemTemplate = item =>
|
||||
{
|
||||
var root = new Grid<ICommandPaletteEntryViewModel>
|
||||
{
|
||||
ColumnDefinitionsObject = "* Auto",
|
||||
ChildInitializer =
|
||||
{
|
||||
new TextBlock<ICommandPaletteEntryViewModel>()
|
||||
.Setup(t => t.Bind(
|
||||
t,
|
||||
d => d.Title,
|
||||
t => t.Text)),
|
||||
new TextBlock<ICommandPaletteEntryViewModel>
|
||||
{
|
||||
Extensions =
|
||||
{
|
||||
new GridPositionExtension(1, 0)
|
||||
}
|
||||
}
|
||||
.Setup(t => t.Bind(
|
||||
t,
|
||||
d => d.Shortcuts,
|
||||
t => t.Text))
|
||||
}
|
||||
};
|
||||
|
||||
item.Bind(
|
||||
item.Parent,
|
||||
d => d.CommandPalette.SelectedItem == item ? _theme.ListViewItemTheme.SelectedBackgroundColor : null,
|
||||
t => t.Background
|
||||
);
|
||||
|
||||
item.Bind(
|
||||
item.Parent,
|
||||
d => d.CommandPalette.SelectedItem == item ? _theme.ListViewItemTheme.SelectedForegroundColor : null,
|
||||
t => t.Foreground
|
||||
);
|
||||
|
||||
return root;
|
||||
}
|
||||
}.Setup(t => t.Bind(
|
||||
t,
|
||||
d => d.CommandPalette.FilteredMatches,
|
||||
t => t.ItemsSource
|
||||
))
|
||||
.Setup(t => t.Bind(
|
||||
t,
|
||||
d => d.CommandPalette.SelectedItem,
|
||||
t => t.SelectedItem
|
||||
))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
root.WithPropertyChangedHandler(r => r.IsVisible,
|
||||
(_, _, isVisible) =>
|
||||
{
|
||||
if (isVisible)
|
||||
{
|
||||
inputTextBox.Focus();
|
||||
}
|
||||
else
|
||||
{
|
||||
inputTextBox.UnFocus();
|
||||
}
|
||||
});
|
||||
|
||||
root.Bind(
|
||||
root,
|
||||
d => d.CommandPalette.ShowWindow.Value,
|
||||
t => t.IsVisible,
|
||||
r => r);
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
||||
@@ -25,8 +25,4 @@
|
||||
<ProjectReference Include="..\FileTime.ConsoleUI.App.Abstractions\FileTime.ConsoleUI.App.Abstractions.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Controls\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using FileTime.App.Core.Models;
|
||||
using FileTime.App.Core.Services;
|
||||
using GeneralInputKey;
|
||||
|
||||
namespace FileTime.ConsoleUI.App.KeyInputHandling;
|
||||
|
||||
@@ -70,6 +71,7 @@ public class ConsoleAppKeyService : IAppKeyService<ConsoleKey>
|
||||
{ConsoleKey.Enter, Keys.Enter},
|
||||
{ConsoleKey.Escape, Keys.Escape},
|
||||
{ConsoleKey.Backspace, Keys.Backspace},
|
||||
{ConsoleKey.Delete, Keys.Delete},
|
||||
{ConsoleKey.Spacebar, Keys.Space},
|
||||
{ConsoleKey.PageUp, Keys.PageUp},
|
||||
{ConsoleKey.PageDown, Keys.PageDown},
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using FileTime.App.Core.Models.Enums;
|
||||
using FileTime.App.Core.Services;
|
||||
using FileTime.App.Core.ViewModels;
|
||||
using GeneralInputKey;
|
||||
|
||||
namespace FileTime.ConsoleUI.App.KeyInputHandling;
|
||||
|
||||
@@ -23,13 +24,15 @@ public class KeyInputHandlerService : IKeyInputHandlerService
|
||||
|
||||
public void HandleKeyInput(GeneralKeyEventArgs keyEvent, SpecialKeysStatus specialKeysStatus)
|
||||
{
|
||||
if (keyEvent.Handled) return;
|
||||
|
||||
if (_appState.ViewMode.Value == ViewMode.Default)
|
||||
{
|
||||
Task.Run(async () => await _defaultModeKeyInputHandler.HandleInputKey(keyEvent, specialKeysStatus)).Wait();
|
||||
Task.Run(async () => await _defaultModeKeyInputHandler.HandleInputKey(keyEvent)).Wait();
|
||||
}
|
||||
else
|
||||
{
|
||||
Task.Run(async () => await _rapidTravelModeKeyInputHandler.HandleInputKey(keyEvent, specialKeysStatus)).Wait();
|
||||
Task.Run(async () => await _rapidTravelModeKeyInputHandler.HandleInputKey(keyEvent)).Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
using FileTime.App.Core.Models.Enums;
|
||||
using FileTime.App.Core.ViewModels;
|
||||
using FileTime.ConsoleUI.App.Controls;
|
||||
using FileTime.ConsoleUI.App.Styling;
|
||||
using FileTime.Core.Enums;
|
||||
using TerminalUI;
|
||||
using TerminalUI.Color;
|
||||
@@ -15,25 +17,47 @@ public class MainWindow
|
||||
private readonly IRootViewModel _rootViewModel;
|
||||
private readonly IApplicationContext _applicationContext;
|
||||
private readonly ITheme _theme;
|
||||
private readonly CommandPalette _commandPalette;
|
||||
|
||||
private IView _root;
|
||||
private readonly Lazy<IView> _root;
|
||||
|
||||
public MainWindow(
|
||||
IRootViewModel rootViewModel,
|
||||
IApplicationContext applicationContext,
|
||||
ITheme theme)
|
||||
ITheme theme,
|
||||
CommandPalette commandPalette)
|
||||
{
|
||||
_rootViewModel = rootViewModel;
|
||||
_applicationContext = applicationContext;
|
||||
_theme = theme;
|
||||
_commandPalette = commandPalette;
|
||||
_root = new Lazy<IView>(Initialize);
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
public IEnumerable<IView> RootViews() => new[]
|
||||
{
|
||||
_root.Value
|
||||
};
|
||||
|
||||
public Grid<IRootViewModel> Initialize()
|
||||
{
|
||||
var root = new Grid<IRootViewModel>
|
||||
{
|
||||
Name = "root",
|
||||
DataContext = _rootViewModel,
|
||||
ApplicationContext = _applicationContext,
|
||||
ChildInitializer =
|
||||
{
|
||||
MainContent(),
|
||||
_commandPalette.View()
|
||||
}
|
||||
};
|
||||
return root;
|
||||
}
|
||||
|
||||
private Grid<IRootViewModel> MainContent() =>
|
||||
new()
|
||||
{
|
||||
RowDefinitionsObject = "Auto * Auto",
|
||||
ChildInitializer =
|
||||
{
|
||||
@@ -108,8 +132,6 @@ public class MainWindow
|
||||
}
|
||||
}
|
||||
};
|
||||
_root = root;
|
||||
}
|
||||
|
||||
private IView<IRootViewModel> PossibleCommands()
|
||||
{
|
||||
@@ -309,11 +331,6 @@ public class MainWindow
|
||||
return list;
|
||||
}
|
||||
|
||||
public IEnumerable<IView> RootViews() => new IView[]
|
||||
{
|
||||
_root
|
||||
};
|
||||
|
||||
private IColor? ToForegroundColor(ItemViewMode viewMode, AbsolutePathType absolutePathType) =>
|
||||
(viewMode, absolutePathType) switch
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using FileTime.App.Core.ViewModels;
|
||||
using FileTime.App.CommandPalette.ViewModels;
|
||||
using FileTime.App.Core.ViewModels;
|
||||
|
||||
namespace FileTime.ConsoleUI.App;
|
||||
|
||||
@@ -8,12 +9,15 @@ public class RootViewModel : IRootViewModel
|
||||
public string MachineName => Environment.MachineName;
|
||||
public IPossibleCommandsViewModel PossibleCommands { get; }
|
||||
public IConsoleAppState AppState { get; }
|
||||
|
||||
public ICommandPaletteViewModel CommandPalette { get; }
|
||||
|
||||
public RootViewModel(
|
||||
IConsoleAppState appState,
|
||||
IPossibleCommandsViewModel possibleCommands)
|
||||
IPossibleCommandsViewModel possibleCommands,
|
||||
ICommandPaletteViewModel commandPalette)
|
||||
{
|
||||
AppState = appState;
|
||||
PossibleCommands = possibleCommands;
|
||||
CommandPalette = commandPalette;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
using FileTime.App.Core.Configuration;
|
||||
using FileTime.App.Core.Models;
|
||||
using FileTime.App.Core.Services;
|
||||
using FileTime.App.Core.ViewModels;
|
||||
using FileTime.ConsoleUI.App.Configuration;
|
||||
using FileTime.ConsoleUI.App.Controls;
|
||||
using FileTime.ConsoleUI.App.KeyInputHandling;
|
||||
using FileTime.ConsoleUI.App.Services;
|
||||
using FileTime.Core.Interactions;
|
||||
@@ -19,7 +21,6 @@ public static class Startup
|
||||
public static IServiceCollection AddConsoleServices(this IServiceCollection services, IConfigurationRoot configuration)
|
||||
{
|
||||
services.TryAddSingleton<IApplication, App>();
|
||||
services.TryAddSingleton<MainWindow>();
|
||||
services.TryAddSingleton<IConsoleAppState, ConsoleAppState>();
|
||||
services.TryAddSingleton<IAppState>(sp => sp.GetRequiredService<IConsoleAppState>());
|
||||
services.TryAddSingleton<IUserCommunicationService, ConsoleUserCommunicationService>();
|
||||
@@ -29,6 +30,7 @@ public static class Startup
|
||||
services.AddSingleton<CustomLoggerSink>();
|
||||
services.TryAddSingleton(new ApplicationConfiguration(true));
|
||||
services.TryAddSingleton<IRootViewModel, RootViewModel>();
|
||||
services.TryAddSingleton<IFocusManager, FocusManager>();
|
||||
|
||||
services.Configure<ConsoleApplicationConfiguration>(configuration);
|
||||
|
||||
@@ -36,9 +38,17 @@ public static class Startup
|
||||
=> new ApplicationContext
|
||||
{
|
||||
ConsoleDriver = sp.GetRequiredService<IConsoleDriver>(),
|
||||
LoggerFactory = sp.GetRequiredService<ILoggerFactory>()
|
||||
LoggerFactory = sp.GetRequiredService<ILoggerFactory>(),
|
||||
FocusManager = sp.GetRequiredService<IFocusManager>(),
|
||||
}
|
||||
);
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddConsoleViews(this IServiceCollection services)
|
||||
{
|
||||
services.TryAddSingleton<MainWindow>();
|
||||
services.TryAddSingleton<CommandPalette>();
|
||||
return services;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user