TerminalUI theming, Commands panel
This commit is contained in:
@@ -3,4 +3,5 @@
|
|||||||
public class ConsoleApplicationConfiguration
|
public class ConsoleApplicationConfiguration
|
||||||
{
|
{
|
||||||
public string? ConsoleDriver { get; set; }
|
public string? ConsoleDriver { get; set; }
|
||||||
|
public bool DisableUtf8 { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using TerminalUI.Color;
|
using TerminalUI.Color;
|
||||||
|
|
||||||
namespace FileTime.ConsoleUI.App.Styling;
|
namespace FileTime.ConsoleUI.App.Styling;
|
||||||
|
using IConsoleTheme = TerminalUI.Styling.ITheme;
|
||||||
|
|
||||||
public interface ITheme
|
public interface ITheme
|
||||||
{
|
{
|
||||||
@@ -17,5 +18,6 @@ public interface ITheme
|
|||||||
IColor? SelectedTabBackgroundColor { get; }
|
IColor? SelectedTabBackgroundColor { get; }
|
||||||
IColor? WarningForegroundColor { get; }
|
IColor? WarningForegroundColor { get; }
|
||||||
IColor? ErrorForegroundColor { get; }
|
IColor? ErrorForegroundColor { get; }
|
||||||
|
IConsoleTheme? ConsoleTheme { get; }
|
||||||
ListViewItemTheme ListViewItemTheme { get; }
|
ListViewItemTheme ListViewItemTheme { get; }
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,11 @@
|
|||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using FileTime.App.Core.Services;
|
using FileTime.App.Core.Services;
|
||||||
using FileTime.App.Core.ViewModels;
|
using FileTime.App.Core.ViewModels;
|
||||||
|
using FileTime.ConsoleUI.App.Configuration;
|
||||||
using FileTime.ConsoleUI.App.KeyInputHandling;
|
using FileTime.ConsoleUI.App.KeyInputHandling;
|
||||||
using FileTime.Core.Command.CreateContainer;
|
|
||||||
using FileTime.Core.Models;
|
|
||||||
using FileTime.Core.Timeline;
|
|
||||||
using GeneralInputKey;
|
using GeneralInputKey;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using TerminalUI;
|
using TerminalUI;
|
||||||
using TerminalUI.ConsoleDrivers;
|
using TerminalUI.ConsoleDrivers;
|
||||||
|
|
||||||
@@ -23,40 +21,36 @@ public class App : IApplication
|
|||||||
|
|
||||||
private readonly ILifecycleService _lifecycleService;
|
private readonly ILifecycleService _lifecycleService;
|
||||||
|
|
||||||
private readonly IConsoleAppState _consoleAppState;
|
|
||||||
|
|
||||||
private readonly IAppKeyService<ConsoleKey> _appKeyService;
|
private readonly IAppKeyService<ConsoleKey> _appKeyService;
|
||||||
private readonly MainWindow _mainWindow;
|
private readonly MainWindow _mainWindow;
|
||||||
private readonly IApplicationContext _applicationContext;
|
private readonly IApplicationContext _applicationContext;
|
||||||
private readonly IConsoleDriver _consoleDriver;
|
private readonly IConsoleDriver _consoleDriver;
|
||||||
private readonly IAppState _appState;
|
private readonly IAppState _appState;
|
||||||
private readonly ILogger<App> _logger;
|
private readonly ILogger<App> _logger;
|
||||||
private readonly IServiceProvider _serviceProvider;
|
|
||||||
private readonly IKeyInputHandlerService _keyInputHandlerService;
|
private readonly IKeyInputHandlerService _keyInputHandlerService;
|
||||||
private readonly Thread _renderThread;
|
private readonly Thread _renderThread;
|
||||||
|
|
||||||
public App(
|
public App(
|
||||||
ILifecycleService lifecycleService,
|
ILifecycleService lifecycleService,
|
||||||
IKeyInputHandlerService keyInputHandlerService,
|
IKeyInputHandlerService keyInputHandlerService,
|
||||||
IConsoleAppState consoleAppState,
|
|
||||||
IAppKeyService<ConsoleKey> appKeyService,
|
IAppKeyService<ConsoleKey> appKeyService,
|
||||||
MainWindow mainWindow,
|
MainWindow mainWindow,
|
||||||
IApplicationContext applicationContext,
|
IApplicationContext applicationContext,
|
||||||
IConsoleDriver consoleDriver,
|
IConsoleDriver consoleDriver,
|
||||||
IAppState appState,
|
IAppState appState,
|
||||||
ILogger<App> logger,
|
IOptions<ConsoleApplicationConfiguration> consoleApplicationConfiguration,
|
||||||
IServiceProvider serviceProvider)
|
ILogger<App> logger)
|
||||||
{
|
{
|
||||||
_lifecycleService = lifecycleService;
|
_lifecycleService = lifecycleService;
|
||||||
_keyInputHandlerService = keyInputHandlerService;
|
_keyInputHandlerService = keyInputHandlerService;
|
||||||
_consoleAppState = consoleAppState;
|
|
||||||
_appKeyService = appKeyService;
|
_appKeyService = appKeyService;
|
||||||
_mainWindow = mainWindow;
|
_mainWindow = mainWindow;
|
||||||
_applicationContext = applicationContext;
|
_applicationContext = applicationContext;
|
||||||
_consoleDriver = consoleDriver;
|
_consoleDriver = consoleDriver;
|
||||||
_appState = appState;
|
_appState = appState;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_serviceProvider = serviceProvider;
|
|
||||||
|
_applicationContext.SupportUtf8Output = !consoleApplicationConfiguration.Value.DisableUtf8;
|
||||||
|
|
||||||
_renderThread = new Thread(Render);
|
_renderThread = new Thread(Render);
|
||||||
}
|
}
|
||||||
@@ -81,12 +75,6 @@ public class App : IApplication
|
|||||||
|
|
||||||
var focusManager = _applicationContext.FocusManager;
|
var focusManager = _applicationContext.FocusManager;
|
||||||
|
|
||||||
var command = _serviceProvider.GetRequiredService<CreateContainerCommand>();
|
|
||||||
command.Init(new FullName("local/C:/Test3"), "container1");
|
|
||||||
var scheduler = _serviceProvider.GetRequiredService<ICommandScheduler>();
|
|
||||||
|
|
||||||
scheduler.AddCommand(command);
|
|
||||||
|
|
||||||
while (_applicationContext.IsRunning)
|
while (_applicationContext.IsRunning)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -1,32 +1,87 @@
|
|||||||
using FileTime.App.Core.ViewModels.Timeline;
|
using FileTime.App.Core.ViewModels.Timeline;
|
||||||
|
using FileTime.ConsoleUI.App.Styling;
|
||||||
using TerminalUI.Controls;
|
using TerminalUI.Controls;
|
||||||
using TerminalUI.Extensions;
|
using TerminalUI.Extensions;
|
||||||
|
using TerminalUI.Models;
|
||||||
|
using TerminalUI.Styling.Controls;
|
||||||
|
using TerminalUI.ViewExtensions;
|
||||||
|
|
||||||
namespace FileTime.ConsoleUI.App.Controls;
|
namespace FileTime.ConsoleUI.App.Controls;
|
||||||
|
|
||||||
public class Timeline
|
public class Timeline
|
||||||
{
|
{
|
||||||
|
private readonly IProgressBarTheme? _progressBarTheme;
|
||||||
|
|
||||||
|
public Timeline(ITheme theme)
|
||||||
|
{
|
||||||
|
_progressBarTheme = theme.ConsoleTheme?.ControlThemes.ProgressBar;
|
||||||
|
}
|
||||||
|
|
||||||
public IView<IRootViewModel> View()
|
public IView<IRootViewModel> View()
|
||||||
{
|
{
|
||||||
var root = new Grid<IRootViewModel>
|
var root = new Grid<IRootViewModel>
|
||||||
{
|
{
|
||||||
ChildInitializer =
|
ChildInitializer =
|
||||||
{
|
{
|
||||||
new ItemsControl<IRootViewModel, ICommandTimeStateViewModel>()
|
new ItemsControl<IRootViewModel, ICommandTimeStateViewModel>
|
||||||
{
|
{
|
||||||
|
Orientation = Orientation.Horizontal,
|
||||||
ItemTemplate = () =>
|
ItemTemplate = () =>
|
||||||
{
|
{
|
||||||
var grid = new Grid<ICommandTimeStateViewModel>()
|
var grid = new Grid<ICommandTimeStateViewModel>
|
||||||
{
|
{
|
||||||
|
Margin = "0 0 1 0",
|
||||||
|
Width = 20,
|
||||||
|
RowDefinitionsObject = "Auto Auto",
|
||||||
ChildInitializer =
|
ChildInitializer =
|
||||||
{
|
{
|
||||||
new TextBlock<ICommandTimeStateViewModel>()
|
new Grid<ICommandTimeStateViewModel>
|
||||||
{
|
{
|
||||||
|
ColumnDefinitionsObject = "* Auto",
|
||||||
}.Setup(t => t.Bind(
|
ChildInitializer =
|
||||||
t,
|
{
|
||||||
dc => dc.DisplayLabel.Value,
|
new TextBlock<ICommandTimeStateViewModel>().Setup(t => t.Bind(
|
||||||
t => t.Text))
|
t,
|
||||||
|
dc => dc.DisplayLabel.Value,
|
||||||
|
t => t.Text)),
|
||||||
|
new TextBlock<ICommandTimeStateViewModel>
|
||||||
|
{
|
||||||
|
Width = 5,
|
||||||
|
TextAlignment = TextAlignment.Right,
|
||||||
|
Extensions = {new GridPositionExtension(1, 0)}
|
||||||
|
}.Setup(t => t.Bind(
|
||||||
|
t,
|
||||||
|
dc => dc.TotalProgress.Value,
|
||||||
|
t => t.Text,
|
||||||
|
v => $"{v}%")),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new ProgressBar<ICommandTimeStateViewModel>
|
||||||
|
{
|
||||||
|
Theme = new ProgressBarTheme
|
||||||
|
{
|
||||||
|
ForegroundColor = _progressBarTheme?.ForegroundColor,
|
||||||
|
UnfilledForeground = _progressBarTheme?.UnfilledForeground,
|
||||||
|
FilledCharacter = '\u2594',
|
||||||
|
UnfilledCharacter = '\u2594',
|
||||||
|
Fraction1Per8Character = '\u2594',
|
||||||
|
Fraction2Per8Character = '\u2594',
|
||||||
|
Fraction3Per8Character = '\u2594',
|
||||||
|
Fraction4Per8Character = '\u2594',
|
||||||
|
Fraction5Per8Character = '\u2594',
|
||||||
|
Fraction6Per8Character = '\u2594',
|
||||||
|
Fraction7Per8Character = '\u2594',
|
||||||
|
FractionFull = '\u2594',
|
||||||
|
},
|
||||||
|
Extensions =
|
||||||
|
{
|
||||||
|
new GridPositionExtension(0, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.Setup(p => p.Bind(
|
||||||
|
p,
|
||||||
|
dc => dc.TotalProgress.Value,
|
||||||
|
p => p.Value)),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
using FileTime.ConsoleUI.App;
|
using FileTime.ConsoleUI.App;
|
||||||
using FileTime.ConsoleUI.App.Styling;
|
using FileTime.ConsoleUI.App.Styling;
|
||||||
using TerminalUI.Color;
|
using TerminalUI.Color;
|
||||||
|
using TerminalUI.Styling;
|
||||||
|
using TerminalUI.Styling.Controls;
|
||||||
|
using ITheme = FileTime.ConsoleUI.App.Styling.ITheme;
|
||||||
|
|
||||||
namespace FileTime.ConsoleUI.Styles;
|
namespace FileTime.ConsoleUI.Styles;
|
||||||
|
|
||||||
|
using IConsoleTheme = TerminalUI.Styling.ITheme;
|
||||||
|
using ConsoleTheme = TerminalUI.Styling.Theme;
|
||||||
|
|
||||||
public record Theme(
|
public record Theme(
|
||||||
IColor? DefaultForegroundColor,
|
IColor? DefaultForegroundColor,
|
||||||
IColor? DefaultForegroundAccentColor,
|
IColor? DefaultForegroundAccentColor,
|
||||||
@@ -19,6 +25,7 @@ public record Theme(
|
|||||||
IColor? WarningForegroundColor,
|
IColor? WarningForegroundColor,
|
||||||
IColor? ErrorForegroundColor,
|
IColor? ErrorForegroundColor,
|
||||||
ListViewItemTheme ListViewItemTheme,
|
ListViewItemTheme ListViewItemTheme,
|
||||||
|
IConsoleTheme? ConsoleTheme,
|
||||||
Type? ForegroundColors,
|
Type? ForegroundColors,
|
||||||
Type? BackgroundColors) : ITheme, IColorSampleProvider;
|
Type? BackgroundColors) : ITheme, IColorSampleProvider;
|
||||||
|
|
||||||
@@ -42,6 +49,19 @@ public static class DefaultThemes
|
|||||||
SelectedBackgroundColor: Color256Colors.Backgrounds.Gray,
|
SelectedBackgroundColor: Color256Colors.Backgrounds.Gray,
|
||||||
SelectedForegroundColor: Color256Colors.Foregrounds.Black
|
SelectedForegroundColor: Color256Colors.Foregrounds.Black
|
||||||
),
|
),
|
||||||
|
ConsoleTheme: new ConsoleTheme
|
||||||
|
{
|
||||||
|
ControlThemes = new ControlThemes
|
||||||
|
{
|
||||||
|
ProgressBar = new ProgressBarTheme
|
||||||
|
{
|
||||||
|
ForegroundColor = Color256Colors.Foregrounds.Blue,
|
||||||
|
BackgroundColor = Color256Colors.Backgrounds.Gray,
|
||||||
|
UnfilledForeground = Color256Colors.Foregrounds.Gray,
|
||||||
|
UnfilledBackground = Color256Colors.Backgrounds.Gray,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
ForegroundColors: typeof(Color256Colors.Foregrounds),
|
ForegroundColors: typeof(Color256Colors.Foregrounds),
|
||||||
BackgroundColors: typeof(Color256Colors.Backgrounds)
|
BackgroundColors: typeof(Color256Colors.Backgrounds)
|
||||||
);
|
);
|
||||||
@@ -64,6 +84,19 @@ public static class DefaultThemes
|
|||||||
SelectedBackgroundColor: ConsoleColors.Backgrounds.Gray,
|
SelectedBackgroundColor: ConsoleColors.Backgrounds.Gray,
|
||||||
SelectedForegroundColor: ConsoleColors.Foregrounds.Black
|
SelectedForegroundColor: ConsoleColors.Foregrounds.Black
|
||||||
),
|
),
|
||||||
|
ConsoleTheme: new ConsoleTheme
|
||||||
|
{
|
||||||
|
ControlThemes = new ControlThemes
|
||||||
|
{
|
||||||
|
ProgressBar = new ProgressBarTheme
|
||||||
|
{
|
||||||
|
ForegroundColor = ConsoleColors.Foregrounds.Blue,
|
||||||
|
BackgroundColor = ConsoleColors.Backgrounds.Gray,
|
||||||
|
UnfilledForeground = ConsoleColors.Foregrounds.Gray,
|
||||||
|
UnfilledBackground = ConsoleColors.Backgrounds.Gray
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
ForegroundColors: typeof(ConsoleColors.Foregrounds),
|
ForegroundColors: typeof(ConsoleColors.Foregrounds),
|
||||||
BackgroundColors: typeof(ConsoleColors.Backgrounds)
|
BackgroundColors: typeof(ConsoleColors.Backgrounds)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -9,8 +9,13 @@ using Microsoft.Extensions.Configuration;
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using Serilog.Debugging;
|
using Serilog.Debugging;
|
||||||
|
using TerminalUI;
|
||||||
|
using TerminalUI.Color;
|
||||||
using TerminalUI.ConsoleDrivers;
|
using TerminalUI.ConsoleDrivers;
|
||||||
|
using TerminalUI.Styling;
|
||||||
|
using ITheme = FileTime.ConsoleUI.App.Styling.ITheme;
|
||||||
|
|
||||||
|
Console.OutputEncoding = System.Text.Encoding.UTF8;
|
||||||
IConsoleDriver? driver = null;
|
IConsoleDriver? driver = null;
|
||||||
|
|
||||||
(AppDataRoot, EnvironmentName) = Init.InitDevelopment();
|
(AppDataRoot, EnvironmentName) = Init.InitDevelopment();
|
||||||
@@ -28,6 +33,11 @@ try
|
|||||||
|
|
||||||
driver.SetCursorVisible(false);
|
driver.SetCursorVisible(false);
|
||||||
|
|
||||||
|
var applicationContext = serviceProvider.GetRequiredService<IApplicationContext>();
|
||||||
|
var theme = serviceProvider.GetRequiredService<ITheme>();
|
||||||
|
|
||||||
|
applicationContext.Theme = theme.ConsoleTheme;
|
||||||
|
|
||||||
var app = serviceProvider.GetRequiredService<IApplication>();
|
var app = serviceProvider.GetRequiredService<IApplication>();
|
||||||
app.Run();
|
app.Run();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class CommandScheduler : ICommandScheduler
|
|||||||
private readonly Subject<FullName> _containerToRefresh = new();
|
private readonly Subject<FullName> _containerToRefresh = new();
|
||||||
|
|
||||||
private readonly object _guard = new();
|
private readonly object _guard = new();
|
||||||
private bool _isRunningEnabled = /*true*/ false;
|
private bool _isRunningEnabled = true;
|
||||||
private bool _resourceIsInUse;
|
private bool _resourceIsInUse;
|
||||||
|
|
||||||
public IObservable<FullName> ContainerToRefresh { get; }
|
public IObservable<FullName> ContainerToRefresh { get; }
|
||||||
|
|||||||
@@ -131,6 +131,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TerminalUI.DependencyInject
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TerminalUI.Tests", "Library\TerminalUI.Tests\TerminalUI.Tests.csproj", "{30B6E288-F314-494B-8550-1329BFF664D2}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TerminalUI.Tests", "Library\TerminalUI.Tests\TerminalUI.Tests.csproj", "{30B6E288-F314-494B-8550-1329BFF664D2}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TerminalUI.Examples", "Library\TerminalUI.Examples\TerminalUI.Examples.csproj", "{14AC0667-A660-4CFC-960E-77E5E5B46D15}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -357,6 +359,10 @@ Global
|
|||||||
{30B6E288-F314-494B-8550-1329BFF664D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{30B6E288-F314-494B-8550-1329BFF664D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{30B6E288-F314-494B-8550-1329BFF664D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{30B6E288-F314-494B-8550-1329BFF664D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{30B6E288-F314-494B-8550-1329BFF664D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
{30B6E288-F314-494B-8550-1329BFF664D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{14AC0667-A660-4CFC-960E-77E5E5B46D15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{14AC0667-A660-4CFC-960E-77E5E5B46D15}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{14AC0667-A660-4CFC-960E-77E5E5B46D15}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{14AC0667-A660-4CFC-960E-77E5E5B46D15}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@@ -418,6 +424,7 @@ Global
|
|||||||
{91AE5B64-042B-4660-A8E8-D247E6E14A1E} = {07CA18AA-B85D-4DEE-BB86-F569F6029853}
|
{91AE5B64-042B-4660-A8E8-D247E6E14A1E} = {07CA18AA-B85D-4DEE-BB86-F569F6029853}
|
||||||
{E72F6430-0E6E-4818-BD5F-114893ACB18E} = {07CA18AA-B85D-4DEE-BB86-F569F6029853}
|
{E72F6430-0E6E-4818-BD5F-114893ACB18E} = {07CA18AA-B85D-4DEE-BB86-F569F6029853}
|
||||||
{30B6E288-F314-494B-8550-1329BFF664D2} = {07CA18AA-B85D-4DEE-BB86-F569F6029853}
|
{30B6E288-F314-494B-8550-1329BFF664D2} = {07CA18AA-B85D-4DEE-BB86-F569F6029853}
|
||||||
|
{14AC0667-A660-4CFC-960E-77E5E5B46D15} = {07CA18AA-B85D-4DEE-BB86-F569F6029853}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {859FB3DF-C60A-46B1-82E5-90274905D1EF}
|
SolutionGuid = {859FB3DF-C60A-46B1-82E5-90274905D1EF}
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
using TerminalUI.Color;
|
||||||
|
using TerminalUI.ConsoleDrivers;
|
||||||
|
using TerminalUI.Controls;
|
||||||
|
using TerminalUI.Models;
|
||||||
|
|
||||||
|
namespace TerminalUI.Examples.Controls;
|
||||||
|
|
||||||
|
public class ProgressBarExamples
|
||||||
|
{
|
||||||
|
private readonly IApplicationContext _applicationContext;
|
||||||
|
private static readonly IConsoleDriver _driver;
|
||||||
|
|
||||||
|
static ProgressBarExamples()
|
||||||
|
{
|
||||||
|
_driver = new DotnetDriver();
|
||||||
|
_driver.Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProgressBarExamples(IApplicationContext applicationContext)
|
||||||
|
{
|
||||||
|
_applicationContext = applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadingExample()
|
||||||
|
{
|
||||||
|
var progressBar = CreateProgressBar<object>(0);
|
||||||
|
for (var i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
progressBar.Value = i;
|
||||||
|
RenderProgressBar(progressBar, new Position(0, 0));
|
||||||
|
Thread.Sleep(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PaletteExample()
|
||||||
|
{
|
||||||
|
RenderProgressBar(CreateProgressBar<object>(100), new Position(0, 0));
|
||||||
|
for (var i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
RenderProgressBar(CreateProgressBar<object>(10 * (i + 1)), new Position(0, i + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProgressBar<T> CreateProgressBar<T>(int percent) =>
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Value = percent,
|
||||||
|
Attached = true,
|
||||||
|
ApplicationContext = _applicationContext
|
||||||
|
};
|
||||||
|
|
||||||
|
private void RenderProgressBar<T>(ProgressBar<T> progressBar, Position position)
|
||||||
|
{
|
||||||
|
var renderContext = new RenderContext(
|
||||||
|
_driver,
|
||||||
|
true,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
new()
|
||||||
|
);
|
||||||
|
progressBar.Render(renderContext, position, new Size(10, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
22
src/Library/TerminalUI.Examples/Mocks/MockRenderEngine.cs
Normal file
22
src/Library/TerminalUI.Examples/Mocks/MockRenderEngine.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using TerminalUI.Controls;
|
||||||
|
|
||||||
|
namespace TerminalUI.Examples.Mocks;
|
||||||
|
|
||||||
|
public class MockRenderEngine : IRenderEngine
|
||||||
|
{
|
||||||
|
public void RequestRerender(IView view)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void VisibilityChanged(IView view)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddViewToPermanentRenderGroup(IView view)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Run()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
32
src/Library/TerminalUI.Examples/Program.cs
Normal file
32
src/Library/TerminalUI.Examples/Program.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// See https://aka.ms/new-console-template for more information
|
||||||
|
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using TerminalUI;
|
||||||
|
using TerminalUI.Color;
|
||||||
|
using TerminalUI.DependencyInjection;
|
||||||
|
using TerminalUI.Examples.Controls;
|
||||||
|
using TerminalUI.Examples.Mocks;
|
||||||
|
using TerminalUI.Styling;
|
||||||
|
using TerminalUI.Styling.Controls;
|
||||||
|
|
||||||
|
Console.OutputEncoding = System.Text.Encoding.UTF8;
|
||||||
|
var services = new ServiceCollection()
|
||||||
|
.AddTerminalUi()
|
||||||
|
.AddSingleton<IRenderEngine, MockRenderEngine>();
|
||||||
|
IServiceProvider provider = services.BuildServiceProvider();
|
||||||
|
|
||||||
|
var applicationContext = provider.GetRequiredService<IApplicationContext>();
|
||||||
|
applicationContext.Theme = new Theme
|
||||||
|
{
|
||||||
|
ControlThemes = new ControlThemes
|
||||||
|
{
|
||||||
|
ProgressBar = new ProgressBarTheme
|
||||||
|
{
|
||||||
|
ForegroundColor = ConsoleColors.Foregrounds.Blue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Console.CursorVisible = false;
|
||||||
|
new ProgressBarExamples(applicationContext).LoadingExample();
|
||||||
|
Console.CursorVisible = true;
|
||||||
19
src/Library/TerminalUI.Examples/TerminalUI.Examples.csproj
Normal file
19
src/Library/TerminalUI.Examples/TerminalUI.Examples.csproj
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\TerminalUI.DependencyInjection\TerminalUI.DependencyInjection.csproj" />
|
||||||
|
<ProjectReference Include="..\TerminalUI\TerminalUI.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using FileTime.App.Core.Models;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using TerminalUI.ConsoleDrivers;
|
using TerminalUI.ConsoleDrivers;
|
||||||
|
using TerminalUI.Styling;
|
||||||
|
|
||||||
namespace TerminalUI;
|
namespace TerminalUI;
|
||||||
|
|
||||||
@@ -16,8 +16,10 @@ public class ApplicationContext : IApplicationContext
|
|||||||
public IFocusManager FocusManager => _focusManager.Value;
|
public IFocusManager FocusManager => _focusManager.Value;
|
||||||
public ILoggerFactory? LoggerFactory => _loggerFactory.Value;
|
public ILoggerFactory? LoggerFactory => _loggerFactory.Value;
|
||||||
public IRenderEngine RenderEngine => _renderEngine.Value;
|
public IRenderEngine RenderEngine => _renderEngine.Value;
|
||||||
|
public ITheme? Theme { get; set; }
|
||||||
public bool IsRunning { get; set; }
|
public bool IsRunning { get; set; }
|
||||||
public char EmptyCharacter { get; init; } = ' ';
|
public char EmptyCharacter { get; init; } = ' ';
|
||||||
|
public bool SupportUtf8Output { get; set; } = true;
|
||||||
|
|
||||||
public ApplicationContext(IServiceProvider serviceProvider)
|
public ApplicationContext(IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ public class DotnetDriver : IConsoleDriver
|
|||||||
public ConsoleKeyInfo ReadKey() => Console.ReadKey(true);
|
public ConsoleKeyInfo ReadKey() => Console.ReadKey(true);
|
||||||
|
|
||||||
public void SetCursorVisible(bool cursorVisible) => Console.CursorVisible = cursorVisible;
|
public void SetCursorVisible(bool cursorVisible) => Console.CursorVisible = cursorVisible;
|
||||||
|
|
||||||
public virtual void SetForegroundColor(IColor foreground)
|
public virtual void SetForegroundColor(IColor foreground)
|
||||||
{
|
{
|
||||||
if (foreground is not ConsoleColor consoleColor) throw new NotSupportedException();
|
if (foreground is not ConsoleColor consoleColor) throw new NotSupportedException();
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ namespace TerminalUI.ConsoleDrivers;
|
|||||||
public sealed class XTermDriver : DotnetDriver
|
public sealed class XTermDriver : DotnetDriver
|
||||||
{
|
{
|
||||||
private Position _initialCursorPosition;
|
private Position _initialCursorPosition;
|
||||||
|
|
||||||
public override bool Init()
|
public override bool Init()
|
||||||
{
|
{
|
||||||
_initialCursorPosition = GetCursorPosition();
|
_initialCursorPosition = GetCursorPosition();
|
||||||
|
|||||||
@@ -153,6 +153,8 @@ public sealed class Grid<T> : ChildContainerView<Grid<T>, T>, IVisibilityChangeH
|
|||||||
|
|
||||||
protected override bool DefaultRenderer(in RenderContext renderContext, Position position, Size size)
|
protected override bool DefaultRenderer(in RenderContext renderContext, Position position, Size size)
|
||||||
{
|
{
|
||||||
|
if (size.Width == 0 || size.Height == 0) return false;
|
||||||
|
|
||||||
return WithCalculatedSize(
|
return WithCalculatedSize(
|
||||||
renderContext,
|
renderContext,
|
||||||
new Option<Size>(size, true),
|
new Option<Size>(size, true),
|
||||||
@@ -177,29 +179,34 @@ public sealed class Grid<T> : ChildContainerView<Grid<T>, T>, IVisibilityChangeH
|
|||||||
);
|
);
|
||||||
var viewsByPosition = GroupViewsByPosition(columnWidths.Length, rowHeights.Length);
|
var viewsByPosition = GroupViewsByPosition(columnWidths.Length, rowHeights.Length);
|
||||||
|
|
||||||
|
var anyRendered = false;
|
||||||
for (var column = 0; column < columnWidths.Length; column++)
|
for (var column = 0; column < columnWidths.Length; column++)
|
||||||
{
|
{
|
||||||
for (var row = 0; row < rowHeights.Length; row++)
|
for (var row = 0; row < rowHeights.Length; row++)
|
||||||
{
|
{
|
||||||
RenderViewsByPosition(
|
anyRendered =
|
||||||
childContext,
|
RenderViewsByPosition(
|
||||||
position,
|
childContext,
|
||||||
columnWidths,
|
position,
|
||||||
rowHeights,
|
size,
|
||||||
viewsByPosition,
|
columnWidths,
|
||||||
column,
|
rowHeights,
|
||||||
row,
|
viewsByPosition,
|
||||||
forceRerenderChildren
|
column,
|
||||||
);
|
row,
|
||||||
|
forceRerenderChildren
|
||||||
|
)
|
||||||
|
|| anyRendered;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return anyRendered;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderViewsByPosition(RenderContext context,
|
private bool RenderViewsByPosition(RenderContext context,
|
||||||
Position gridPosition,
|
Position gridPosition,
|
||||||
|
Size gridSize,
|
||||||
ReadOnlySpan<int> columnWidths,
|
ReadOnlySpan<int> columnWidths,
|
||||||
ReadOnlySpan<int> rowHeights,
|
ReadOnlySpan<int> rowHeights,
|
||||||
IReadOnlyDictionary<(int, int), List<IView>> viewsByPosition,
|
IReadOnlyDictionary<(int, int), List<IView>> viewsByPosition,
|
||||||
@@ -207,7 +214,7 @@ public sealed class Grid<T> : ChildContainerView<Grid<T>, T>, IVisibilityChangeH
|
|||||||
int row,
|
int row,
|
||||||
IReadOnlyList<IView> forceRerenderChildren)
|
IReadOnlyList<IView> forceRerenderChildren)
|
||||||
{
|
{
|
||||||
if (!viewsByPosition.TryGetValue((column, row), out var children)) return;
|
if (!viewsByPosition.TryGetValue((column, row), out var children)) return false;
|
||||||
|
|
||||||
var width = columnWidths[column];
|
var width = columnWidths[column];
|
||||||
var height = rowHeights[row];
|
var height = rowHeights[row];
|
||||||
@@ -221,6 +228,18 @@ public sealed class Grid<T> : ChildContainerView<Grid<T>, T>, IVisibilityChangeH
|
|||||||
row
|
row
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (renderPosition.X + width > gridPosition.X + gridSize.Width)
|
||||||
|
{
|
||||||
|
renderSize = renderSize with {Width = gridPosition.X + gridSize.Width - renderPosition.X};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (renderPosition.Y + height > gridPosition.Y + gridSize.Height)
|
||||||
|
{
|
||||||
|
renderSize = renderSize with {Height = gridPosition.Y + gridSize.Height - renderPosition.Y};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (renderSize.Width == 0 || renderSize.Height == 0) return false;
|
||||||
|
|
||||||
var needsRerender = children.Any(forceRerenderChildren.Contains);
|
var needsRerender = children.Any(forceRerenderChildren.Contains);
|
||||||
if (needsRerender)
|
if (needsRerender)
|
||||||
{
|
{
|
||||||
@@ -251,6 +270,8 @@ public sealed class Grid<T> : ChildContainerView<Grid<T>, T>, IVisibilityChangeH
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
static Position GetRenderPosition(
|
static Position GetRenderPosition(
|
||||||
Position gridPosition,
|
Position gridPosition,
|
||||||
ReadOnlySpan<int> columnWidths,
|
ReadOnlySpan<int> columnWidths,
|
||||||
|
|||||||
168
src/Library/TerminalUI/Controls/ProgressBar.cs
Normal file
168
src/Library/TerminalUI/Controls/ProgressBar.cs
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
using PropertyChanged.SourceGenerator;
|
||||||
|
using TerminalUI.Color;
|
||||||
|
using TerminalUI.Models;
|
||||||
|
using TerminalUI.Styling.Controls;
|
||||||
|
|
||||||
|
namespace TerminalUI.Controls;
|
||||||
|
|
||||||
|
public partial class ProgressBar<T> : View<ProgressBar<T>, T>
|
||||||
|
{
|
||||||
|
private record RenderState(
|
||||||
|
Position Position,
|
||||||
|
Size Size,
|
||||||
|
int Minimum,
|
||||||
|
int Maximum,
|
||||||
|
int Value,
|
||||||
|
char? LeftCap,
|
||||||
|
char? RightCap,
|
||||||
|
char? Fill,
|
||||||
|
char? Unfilled,
|
||||||
|
IColor? UnfilledForeground,
|
||||||
|
IColor? UnfilledBackground);
|
||||||
|
|
||||||
|
private RenderState? _lastRenderState;
|
||||||
|
|
||||||
|
[Notify] private int _minimum = 0;
|
||||||
|
[Notify] private int _maximum = 100;
|
||||||
|
[Notify] private int _value = 0;
|
||||||
|
[Notify] private IProgressBarTheme? _theme;
|
||||||
|
|
||||||
|
private IProgressBarTheme? AppTheme => ApplicationContext?.Theme?.ControlThemes.ProgressBar;
|
||||||
|
|
||||||
|
public ProgressBar()
|
||||||
|
{
|
||||||
|
RerenderProperties.Add(nameof(Minimum));
|
||||||
|
RerenderProperties.Add(nameof(Maximum));
|
||||||
|
RerenderProperties.Add(nameof(Value));
|
||||||
|
RerenderProperties.Add(nameof(Theme));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected override Size CalculateSize() => new(5, 1);
|
||||||
|
|
||||||
|
protected override bool DefaultRenderer(in RenderContext renderContext, Position position, Size size)
|
||||||
|
{
|
||||||
|
if (size.Width == 0 || size.Height == 0) return false;
|
||||||
|
var theme = AppTheme;
|
||||||
|
|
||||||
|
var foreground = Foreground ?? (_theme ?? theme)?.ForegroundColor ?? renderContext.Foreground;
|
||||||
|
var background = Background ?? (_theme ?? theme)?.BackgroundColor ?? renderContext.Background;
|
||||||
|
var unfilledForeground = (_theme ?? theme)?.UnfilledForeground ?? renderContext.Foreground;
|
||||||
|
var unfilledBackground = (_theme ?? theme)?.UnfilledBackground ?? renderContext.Background;
|
||||||
|
var unfilledCharacter = (_theme ?? theme)?.UnfilledCharacter ?? ApplicationContext?.EmptyCharacter ?? ' ';
|
||||||
|
var fillCharacter = (_theme ?? theme)?.FilledCharacter ?? '█';
|
||||||
|
var leftCap = (_theme ?? theme)?.LeftCap;
|
||||||
|
var rightCap = (_theme ?? theme)?.RightCap;
|
||||||
|
|
||||||
|
var renderState = new RenderState(
|
||||||
|
position,
|
||||||
|
size,
|
||||||
|
Minimum,
|
||||||
|
Maximum,
|
||||||
|
Value,
|
||||||
|
leftCap,
|
||||||
|
rightCap,
|
||||||
|
fillCharacter,
|
||||||
|
unfilledCharacter,
|
||||||
|
unfilledForeground,
|
||||||
|
unfilledBackground);
|
||||||
|
|
||||||
|
if (!renderContext.ForceRerender && !NeedsRerender(renderState)) return false;
|
||||||
|
|
||||||
|
_lastRenderState = renderState;
|
||||||
|
var driver = renderContext.ConsoleDriver;
|
||||||
|
|
||||||
|
var borderWidth =
|
||||||
|
(leftCap.HasValue ? 1 : 0)
|
||||||
|
+ (rightCap.HasValue ? 1 : 0);
|
||||||
|
|
||||||
|
var progress = (double) (Value - Minimum) / (Maximum - Minimum);
|
||||||
|
var progressAvailableSpace = size.Width - borderWidth;
|
||||||
|
var progressWidth = progress * progressAvailableSpace;
|
||||||
|
var progressQuotientWidth = (int) Math.Floor(progressWidth);
|
||||||
|
var progressRemainderWidth = progressAvailableSpace - progressQuotientWidth - 1;
|
||||||
|
if (progressRemainderWidth < 0) progressRemainderWidth = 0;
|
||||||
|
|
||||||
|
Span<char> filledText = stackalloc char[progressQuotientWidth];
|
||||||
|
var transientChar = unfilledCharacter;
|
||||||
|
|
||||||
|
filledText.Fill(fillCharacter);
|
||||||
|
if (ApplicationContext!.SupportUtf8Output)
|
||||||
|
{
|
||||||
|
var remained = progressWidth - progressQuotientWidth;
|
||||||
|
transientChar = remained switch
|
||||||
|
{
|
||||||
|
< 0.125 => unfilledCharacter,
|
||||||
|
< 0.250 => (_theme ?? theme)?.Fraction1Per8Character ?? '\u258F',
|
||||||
|
< 0.375 => (_theme ?? theme)?.Fraction2Per8Character ?? '\u258E',
|
||||||
|
< 0.500 => (_theme ?? theme)?.Fraction3Per8Character ?? '\u258D',
|
||||||
|
< 0.675 => (_theme ?? theme)?.Fraction4Per8Character ?? '\u258C',
|
||||||
|
< 0.750 => (_theme ?? theme)?.Fraction5Per8Character ?? '\u258B',
|
||||||
|
< 0.875 => (_theme ?? theme)?.Fraction6Per8Character ?? '\u258A',
|
||||||
|
< 0_001 => (_theme ?? theme)?.Fraction7Per8Character ?? '\u2589',
|
||||||
|
_ => (_theme ?? theme)?.FractionFull ?? '\u2588',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
SetColor(driver, foreground, background);
|
||||||
|
|
||||||
|
// Left border
|
||||||
|
var textStartPosition = position;
|
||||||
|
if (leftCap.HasValue)
|
||||||
|
{
|
||||||
|
RenderText(leftCap.Value, driver, position, size with {Width = 1});
|
||||||
|
textStartPosition = textStartPosition with {X = textStartPosition.X + 1};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filled
|
||||||
|
RenderText(
|
||||||
|
filledText,
|
||||||
|
driver,
|
||||||
|
textStartPosition,
|
||||||
|
size with {Width = progressQuotientWidth}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Transient character
|
||||||
|
if (progressQuotientWidth < progressAvailableSpace)
|
||||||
|
{
|
||||||
|
SetColor(driver, foreground, unfilledBackground);
|
||||||
|
RenderText(
|
||||||
|
transientChar,
|
||||||
|
driver,
|
||||||
|
textStartPosition with {X = textStartPosition.X + progressQuotientWidth},
|
||||||
|
size with {Width = 1}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unfilled
|
||||||
|
if (progressRemainderWidth != 0)
|
||||||
|
{
|
||||||
|
Span<char> unfilledText = stackalloc char[progressRemainderWidth];
|
||||||
|
unfilledText.Fill(unfilledCharacter);
|
||||||
|
|
||||||
|
SetColor(driver, unfilledForeground, unfilledBackground);
|
||||||
|
RenderText(
|
||||||
|
unfilledText,
|
||||||
|
driver,
|
||||||
|
textStartPosition with {X = textStartPosition.X + progressQuotientWidth + 1},
|
||||||
|
size with {Width = progressRemainderWidth}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right border
|
||||||
|
if (rightCap.HasValue)
|
||||||
|
{
|
||||||
|
SetColor(driver, foreground, background);
|
||||||
|
RenderText(
|
||||||
|
rightCap.Value,
|
||||||
|
driver,
|
||||||
|
position with {X = position.X + size.Width - 1},
|
||||||
|
size with {Width = 1});
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool NeedsRerender(RenderState renderState)
|
||||||
|
=> _lastRenderState is null || _lastRenderState != renderState;
|
||||||
|
}
|
||||||
@@ -78,16 +78,7 @@ public sealed partial class TextBlock<T> : View<TextBlock<T>, T>, IDisplayView
|
|||||||
_placeholderRenderDone = false;
|
_placeholderRenderDone = false;
|
||||||
|
|
||||||
var driver = renderContext.ConsoleDriver;
|
var driver = renderContext.ConsoleDriver;
|
||||||
driver.ResetColor();
|
SetColor(driver, foreground, background);
|
||||||
if (foreground is not null)
|
|
||||||
{
|
|
||||||
driver.SetForegroundColor(foreground);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (background is not null)
|
|
||||||
{
|
|
||||||
driver.SetBackgroundColor(background);
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderText(_textLines, driver, position, size, TransformText);
|
RenderText(_textLines, driver, position, size, TransformText);
|
||||||
|
|
||||||
|
|||||||
@@ -104,16 +104,7 @@ public sealed partial class TextBox<T> : View<TextBox<T>, T>, IFocusable, IDispl
|
|||||||
_lastRenderState = renderStatus;
|
_lastRenderState = renderStatus;
|
||||||
|
|
||||||
var driver = renderContext.ConsoleDriver;
|
var driver = renderContext.ConsoleDriver;
|
||||||
driver.ResetColor();
|
SetColor(driver, foreground, background);
|
||||||
if (foreground is not null)
|
|
||||||
{
|
|
||||||
driver.SetForegroundColor(foreground);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (background is not null)
|
|
||||||
{
|
|
||||||
driver.SetBackgroundColor(background);
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderEmpty(renderContext, position, size);
|
RenderEmpty(renderContext, position, size);
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,21 @@ public abstract partial class View<TConcrete, T> : IView<T> where TConcrete : Vi
|
|||||||
|
|
||||||
public virtual Size GetRequestedSize()
|
public virtual Size GetRequestedSize()
|
||||||
{
|
{
|
||||||
var size = CalculateSize();
|
Size size;
|
||||||
|
if (Width.HasValue && Height.HasValue)
|
||||||
|
{
|
||||||
|
size = new Size(Width.Value, Height.Value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size = CalculateSize();
|
||||||
|
|
||||||
|
if (Width.HasValue)
|
||||||
|
size = size with {Width = Width.Value};
|
||||||
|
|
||||||
|
if (Height.HasValue)
|
||||||
|
size = size with {Height = Height.Value};
|
||||||
|
}
|
||||||
|
|
||||||
if (MinWidth.HasValue && size.Width < MinWidth.Value)
|
if (MinWidth.HasValue && size.Width < MinWidth.Value)
|
||||||
size = size with {Width = MinWidth.Value};
|
size = size with {Width = MinWidth.Value};
|
||||||
@@ -220,8 +234,14 @@ public abstract partial class View<TConcrete, T> : IView<T> where TConcrete : Vi
|
|||||||
text = text[..size.Width];
|
text = text[..size.Width];
|
||||||
}
|
}
|
||||||
|
|
||||||
driver.SetCursorPosition(currentPosition);
|
try
|
||||||
driver.Write(text);
|
{
|
||||||
|
driver.SetCursorPosition(currentPosition);
|
||||||
|
driver.Write(text);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,6 +309,18 @@ public abstract partial class View<TConcrete, T> : IView<T> where TConcrete : Vi
|
|||||||
driver.Write(contentString);
|
driver.Write(contentString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
protected void SetColor(IConsoleDriver driver, IColor? foreground, IColor? background)
|
||||||
|
{
|
||||||
|
driver.ResetColor();
|
||||||
|
if (foreground is not null)
|
||||||
|
{
|
||||||
|
driver.SetForegroundColor(foreground);
|
||||||
|
}
|
||||||
|
if(background is not null)
|
||||||
|
{
|
||||||
|
driver.SetBackgroundColor(background);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void SetColorsForDriver(in RenderContext renderContext)
|
protected void SetColorsForDriver(in RenderContext renderContext)
|
||||||
{
|
{
|
||||||
@@ -296,15 +328,7 @@ public abstract partial class View<TConcrete, T> : IView<T> where TConcrete : Vi
|
|||||||
|
|
||||||
var foreground = Foreground ?? renderContext.Foreground;
|
var foreground = Foreground ?? renderContext.Foreground;
|
||||||
var background = Background ?? renderContext.Background;
|
var background = Background ?? renderContext.Background;
|
||||||
if (foreground is not null)
|
SetColor(driver, foreground, background);
|
||||||
{
|
|
||||||
driver.SetForegroundColor(foreground);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (background is not null)
|
|
||||||
{
|
|
||||||
driver.SetBackgroundColor(background);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TChild CreateChild<TChild>() where TChild : IView<T>, new()
|
public TChild CreateChild<TChild>() where TChild : IView<T>, new()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using FileTime.App.Core.Models;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using TerminalUI.ConsoleDrivers;
|
using TerminalUI.ConsoleDrivers;
|
||||||
|
using TerminalUI.Styling;
|
||||||
|
|
||||||
namespace TerminalUI;
|
namespace TerminalUI;
|
||||||
|
|
||||||
@@ -12,4 +12,6 @@ public interface IApplicationContext
|
|||||||
ILoggerFactory? LoggerFactory { get; }
|
ILoggerFactory? LoggerFactory { get; }
|
||||||
char EmptyCharacter { get; }
|
char EmptyCharacter { get; }
|
||||||
IFocusManager FocusManager { get; }
|
IFocusManager FocusManager { get; }
|
||||||
|
bool SupportUtf8Output { get; set; }
|
||||||
|
ITheme? Theme { get; set; }
|
||||||
}
|
}
|
||||||
8
src/Library/TerminalUI/Styling/ControlThemes.cs
Normal file
8
src/Library/TerminalUI/Styling/ControlThemes.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using TerminalUI.Styling.Controls;
|
||||||
|
|
||||||
|
namespace TerminalUI.Styling;
|
||||||
|
|
||||||
|
public class ControlThemes : IControlThemes
|
||||||
|
{
|
||||||
|
public required IProgressBarTheme ProgressBar { get; init; }
|
||||||
|
}
|
||||||
23
src/Library/TerminalUI/Styling/Controls/IProgressBarTheme.cs
Normal file
23
src/Library/TerminalUI/Styling/Controls/IProgressBarTheme.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using TerminalUI.Color;
|
||||||
|
|
||||||
|
namespace TerminalUI.Styling.Controls;
|
||||||
|
|
||||||
|
public interface IProgressBarTheme
|
||||||
|
{
|
||||||
|
IColor? ForegroundColor { get; init; }
|
||||||
|
IColor? BackgroundColor { get; init; }
|
||||||
|
IColor? UnfilledForeground { get; init; }
|
||||||
|
IColor? UnfilledBackground { get; init; }
|
||||||
|
char? FilledCharacter { get; init; }
|
||||||
|
char? UnfilledCharacter { get; init; }
|
||||||
|
char? Fraction1Per8Character { get; init; }
|
||||||
|
char? Fraction2Per8Character { get; init; }
|
||||||
|
char? Fraction3Per8Character { get; init; }
|
||||||
|
char? Fraction4Per8Character { get; init; }
|
||||||
|
char? Fraction5Per8Character { get; init; }
|
||||||
|
char? Fraction6Per8Character { get; init; }
|
||||||
|
char? Fraction7Per8Character { get; init; }
|
||||||
|
char? FractionFull { get; init; }
|
||||||
|
char? LeftCap { get; init; }
|
||||||
|
char? RightCap { get; init; }
|
||||||
|
}
|
||||||
43
src/Library/TerminalUI/Styling/Controls/ProgressBarTheme.cs
Normal file
43
src/Library/TerminalUI/Styling/Controls/ProgressBarTheme.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
using TerminalUI.Color;
|
||||||
|
|
||||||
|
namespace TerminalUI.Styling.Controls;
|
||||||
|
|
||||||
|
public class ProgressBarTheme : IProgressBarTheme
|
||||||
|
{
|
||||||
|
public ProgressBarTheme(){}
|
||||||
|
public ProgressBarTheme(ProgressBarTheme theme)
|
||||||
|
{
|
||||||
|
ForegroundColor = theme.ForegroundColor;
|
||||||
|
BackgroundColor = theme.BackgroundColor;
|
||||||
|
UnfilledForeground = theme.UnfilledForeground;
|
||||||
|
UnfilledBackground = theme.UnfilledBackground;
|
||||||
|
FilledCharacter = theme.FilledCharacter;
|
||||||
|
UnfilledCharacter = theme.UnfilledCharacter;
|
||||||
|
Fraction1Per8Character = theme.Fraction1Per8Character;
|
||||||
|
Fraction2Per8Character = theme.Fraction2Per8Character;
|
||||||
|
Fraction3Per8Character = theme.Fraction3Per8Character;
|
||||||
|
Fraction4Per8Character = theme.Fraction4Per8Character;
|
||||||
|
Fraction5Per8Character = theme.Fraction5Per8Character;
|
||||||
|
Fraction6Per8Character = theme.Fraction6Per8Character;
|
||||||
|
Fraction7Per8Character = theme.Fraction7Per8Character;
|
||||||
|
FractionFull = theme.FractionFull;
|
||||||
|
LeftCap = theme.LeftCap;
|
||||||
|
RightCap = theme.RightCap;
|
||||||
|
}
|
||||||
|
public IColor? ForegroundColor { get; init; }
|
||||||
|
public IColor? BackgroundColor { get; init; }
|
||||||
|
public IColor? UnfilledForeground { get; init; }
|
||||||
|
public IColor? UnfilledBackground { get; init; }
|
||||||
|
public char? FilledCharacter { get; init; }
|
||||||
|
public char? UnfilledCharacter { get; init; }
|
||||||
|
public char? Fraction1Per8Character { get; init; }
|
||||||
|
public char? Fraction2Per8Character { get; init; }
|
||||||
|
public char? Fraction3Per8Character { get; init; }
|
||||||
|
public char? Fraction4Per8Character { get; init; }
|
||||||
|
public char? Fraction5Per8Character { get; init; }
|
||||||
|
public char? Fraction6Per8Character { get; init; }
|
||||||
|
public char? Fraction7Per8Character { get; init; }
|
||||||
|
public char? FractionFull { get; init; }
|
||||||
|
public char? LeftCap { get; init; }
|
||||||
|
public char? RightCap { get; init; }
|
||||||
|
}
|
||||||
8
src/Library/TerminalUI/Styling/IControlThemes.cs
Normal file
8
src/Library/TerminalUI/Styling/IControlThemes.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using TerminalUI.Styling.Controls;
|
||||||
|
|
||||||
|
namespace TerminalUI.Styling;
|
||||||
|
|
||||||
|
public interface IControlThemes
|
||||||
|
{
|
||||||
|
IProgressBarTheme ProgressBar { get; init; }
|
||||||
|
}
|
||||||
6
src/Library/TerminalUI/Styling/ITheme.cs
Normal file
6
src/Library/TerminalUI/Styling/ITheme.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace TerminalUI.Styling;
|
||||||
|
|
||||||
|
public interface ITheme
|
||||||
|
{
|
||||||
|
IControlThemes ControlThemes { get; init; }
|
||||||
|
}
|
||||||
6
src/Library/TerminalUI/Styling/Theme.cs
Normal file
6
src/Library/TerminalUI/Styling/Theme.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace TerminalUI.Styling;
|
||||||
|
|
||||||
|
public class Theme : ITheme
|
||||||
|
{
|
||||||
|
public required IControlThemes ControlThemes { get; init; }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user