Console size scan
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using DeclarativeProperty;
|
using DeclarativeProperty;
|
||||||
|
using FileTime.Core.Models;
|
||||||
|
|
||||||
namespace FileTime.App.ContainerSizeScanner;
|
namespace FileTime.App.ContainerSizeScanner;
|
||||||
|
|
||||||
@@ -7,7 +8,7 @@ public class ChildElementPreview : ISizePreviewItem
|
|||||||
public ChildElementPreview(ISizeScanElement element)
|
public ChildElementPreview(ISizeScanElement element)
|
||||||
{
|
{
|
||||||
Name = element.Name;
|
Name = element.Name;
|
||||||
Size = element.Size;
|
Size = new DeclarativeProperty<long>(((IElement) element).Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ public record SizeScanElement : ISizeScanElement
|
|||||||
public required DateTime? ModifiedAt { get; init;}
|
public required DateTime? ModifiedAt { get; init;}
|
||||||
|
|
||||||
public required IDeclarativeProperty<long> Size { get; init; }
|
public required IDeclarativeProperty<long> Size { get; init; }
|
||||||
|
|
||||||
|
long IElement.Size => Size.Value;
|
||||||
|
|
||||||
public bool IsHidden => false;
|
public bool IsHidden => false;
|
||||||
public bool IsExists => true;
|
public bool IsExists => true;
|
||||||
public SupportsDelete CanDelete => SupportsDelete.False;
|
public SupportsDelete CanDelete => SupportsDelete.False;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using DeclarativeProperty;
|
using DeclarativeProperty;
|
||||||
using FileTime.Core.Enums;
|
using FileTime.Core.Enums;
|
||||||
using FileTime.Core.Models;
|
using FileTime.Core.Models;
|
||||||
using FileTime.Core.Models.Extensions;
|
|
||||||
using FileTime.Core.Timeline;
|
using FileTime.Core.Timeline;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
@@ -104,10 +103,7 @@ public class SizeScanTask : ISizeScanTask
|
|||||||
{
|
{
|
||||||
if (_cancelled) return;
|
if (_cancelled) return;
|
||||||
|
|
||||||
var fileExtension = element.GetExtension<FileExtension>();
|
var sizeProperty = new DeclarativeProperty<long>(element.Size);
|
||||||
var size = fileExtension?.Size ?? 0;
|
|
||||||
|
|
||||||
var sizeProperty = new DeclarativeProperty<long>(size);
|
|
||||||
var childName = sizeScanContainer.FullName!.GetChild(element.Name).Path;
|
var childName = sizeScanContainer.FullName!.GetChild(element.Name).Path;
|
||||||
|
|
||||||
var childElement = new SizeScanElement
|
var childElement = new SizeScanElement
|
||||||
|
|||||||
@@ -25,4 +25,9 @@
|
|||||||
<ProjectReference Include="..\..\Library\GeneralInputKey\GeneralInputKey.csproj" />
|
<ProjectReference Include="..\..\Library\GeneralInputKey\GeneralInputKey.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Models\Traits\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ namespace FileTime.App.Core.ViewModels;
|
|||||||
|
|
||||||
public interface IElementViewModel :
|
public interface IElementViewModel :
|
||||||
IItemViewModel,
|
IItemViewModel,
|
||||||
ISizeProvider,
|
IInitable<IElement, ITabViewModel, ItemViewModelType>,
|
||||||
IInitable<IElement, ITabViewModel, ItemViewModelType>
|
ISizeProvider
|
||||||
{
|
{
|
||||||
IElement? Element { get; }
|
IElement? Element { get; }
|
||||||
}
|
}
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
using FileTime.App.Core.Models.Enums;
|
|
||||||
using FileTime.Core.Models;
|
|
||||||
using FileTime.Core.Models.Extensions;
|
|
||||||
using InitableService;
|
|
||||||
|
|
||||||
namespace FileTime.App.Core.ViewModels;
|
|
||||||
|
|
||||||
public interface IFileViewModel : IElementViewModel, IInitable<IElement, FileExtension, ITabViewModel, ItemViewModelType>
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -44,4 +44,5 @@
|
|||||||
<ProjectReference Include="..\FileTime.App.Search\FileTime.App.Search.csproj" />
|
<ProjectReference Include="..\FileTime.App.Search\FileTime.App.Search.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace FileTime.GuiApp.App.Helper;
|
namespace FileTime.App.Core.Helpers;
|
||||||
|
|
||||||
public static class ColorHelper
|
public static class ColorHelper
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using FileTime.App.ContainerSizeScanner;
|
||||||
|
|
||||||
|
namespace FileTime.App.Core.Helpers;
|
||||||
|
|
||||||
|
public static class SizePreviewItemHelper
|
||||||
|
{
|
||||||
|
public static (byte r, byte g, byte b) GetItemColor(
|
||||||
|
ObservableCollection<ISizePreviewItem> items,
|
||||||
|
ISizePreviewItem currentItem,
|
||||||
|
double hueDiff = 0,
|
||||||
|
double lightness = 0.75
|
||||||
|
)
|
||||||
|
{
|
||||||
|
var i = 0;
|
||||||
|
for (; i < items.Count; i++)
|
||||||
|
{
|
||||||
|
if (items[i].Name == currentItem.Name) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var hue = (360d * i / (items.Count < 1 ? 1 : items.Count)) + hueDiff;
|
||||||
|
if (hue > 360) hue -= 360;
|
||||||
|
if (hue < 0) hue += 360;
|
||||||
|
|
||||||
|
return ColorHelper.HlsToRgb(hue, lightness, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -321,7 +321,7 @@ public class NavigationUserCommandHandlerService : UserCommandHandlerServiceBase
|
|||||||
{
|
{
|
||||||
if (_selectedTab is null || _currentItems?.Value is null) return Task.CompletedTask;
|
if (_selectedTab is null || _currentItems?.Value is null) return Task.CompletedTask;
|
||||||
|
|
||||||
var newSelectedItem = getNewSelected(_currentItems.Value);
|
var newSelectedItem = getNewSelected(_currentItems.Value.ToArray());
|
||||||
if (newSelectedItem == null) return Task.CompletedTask;
|
if (newSelectedItem == null) return Task.CompletedTask;
|
||||||
|
|
||||||
if (_selectedTab.Tab is { } tab)
|
if (_selectedTab.Tab is { } tab)
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ public static class Startup
|
|||||||
serviceCollection.TryAddTransient<ITabViewModel, TabViewModel>();
|
serviceCollection.TryAddTransient<ITabViewModel, TabViewModel>();
|
||||||
serviceCollection.TryAddTransient<IContainerViewModel, ContainerViewModel>();
|
serviceCollection.TryAddTransient<IContainerViewModel, ContainerViewModel>();
|
||||||
serviceCollection.TryAddTransient<IElementViewModel, ElementViewModel>();
|
serviceCollection.TryAddTransient<IElementViewModel, ElementViewModel>();
|
||||||
serviceCollection.TryAddTransient<IFileViewModel, FileViewModel>();
|
|
||||||
serviceCollection.TryAddTransient<IItemNameConverterService, ItemNameConverterService>();
|
serviceCollection.TryAddTransient<IItemNameConverterService, ItemNameConverterService>();
|
||||||
serviceCollection.TryAddTransient<ElementPreviewViewModel>();
|
serviceCollection.TryAddTransient<ElementPreviewViewModel>();
|
||||||
serviceCollection.TryAddSingleton<IUserCommandHandlerService, UserCommandHandlerService>();
|
serviceCollection.TryAddSingleton<IUserCommandHandlerService, UserCommandHandlerService>();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using FileTime.Core.Models;
|
|||||||
|
|
||||||
namespace FileTime.App.Core.ViewModels;
|
namespace FileTime.App.Core.ViewModels;
|
||||||
|
|
||||||
public partial class ContainerViewModel : ItemViewModel, IContainerViewModel
|
public class ContainerViewModel : ItemViewModel, IContainerViewModel
|
||||||
{
|
{
|
||||||
public IContainer? Container => BaseItem as IContainer;
|
public IContainer? Container => BaseItem as IContainer;
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ using FileTime.Core.Models;
|
|||||||
|
|
||||||
namespace FileTime.App.Core.ViewModels;
|
namespace FileTime.App.Core.ViewModels;
|
||||||
|
|
||||||
public partial class ElementViewModel : ItemViewModel, IElementViewModel
|
public class ElementViewModel : ItemViewModel, IElementViewModel
|
||||||
{
|
{
|
||||||
|
private readonly DeclarativeProperty<long> _size = new(0);
|
||||||
public IElement? Element => BaseItem as Element;
|
public IElement? Element => BaseItem as Element;
|
||||||
|
|
||||||
public ElementViewModel(IItemNameConverterService itemNameConverterService, IAppState appState) : base(itemNameConverterService, appState)
|
public ElementViewModel(IItemNameConverterService itemNameConverterService, IAppState appState) : base(itemNameConverterService, appState)
|
||||||
@@ -14,7 +15,10 @@ public partial class ElementViewModel : ItemViewModel, IElementViewModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void Init(IElement item, ITabViewModel parentTab, ItemViewModelType itemViewModelType)
|
public void Init(IElement item, ITabViewModel parentTab, ItemViewModelType itemViewModelType)
|
||||||
=> Init((IItem)item, parentTab, itemViewModelType);
|
{
|
||||||
|
Init((IItem) item, parentTab, itemViewModelType);
|
||||||
public IDeclarativeProperty<long> Size { get; protected set; } = new DeclarativeProperty<long>(0);
|
_size.SetValueSafe(item.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDeclarativeProperty<long> Size => _size;
|
||||||
}
|
}
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
using DeclarativeProperty;
|
|
||||||
using FileTime.App.Core.Models.Enums;
|
|
||||||
using FileTime.App.Core.Services;
|
|
||||||
using FileTime.Core.Models;
|
|
||||||
using FileTime.Core.Models.Extensions;
|
|
||||||
|
|
||||||
namespace FileTime.App.Core.ViewModels;
|
|
||||||
|
|
||||||
public partial class FileViewModel : ElementViewModel, IFileViewModel
|
|
||||||
{
|
|
||||||
public FileViewModel(IItemNameConverterService itemNameConverterService, IAppState appState) : base(itemNameConverterService, appState)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init(IElement item, FileExtension fileExtension, ITabViewModel parentTab, ItemViewModelType itemViewModelType)
|
|
||||||
{
|
|
||||||
Init(item, parentTab, itemViewModelType);
|
|
||||||
Size = new DeclarativeProperty<long>(fileExtension.Size ?? 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,6 @@ using FileTime.App.Core.Models.Enums;
|
|||||||
using FileTime.App.Core.Services;
|
using FileTime.App.Core.Services;
|
||||||
using FileTime.Core.Enums;
|
using FileTime.Core.Enums;
|
||||||
using FileTime.Core.Models;
|
using FileTime.Core.Models;
|
||||||
using FileTime.Core.Models.Extensions;
|
|
||||||
using FileTime.Core.Services;
|
using FileTime.Core.Services;
|
||||||
using FileTime.Core.Timeline;
|
using FileTime.Core.Timeline;
|
||||||
using InitableService;
|
using InitableService;
|
||||||
@@ -205,19 +204,6 @@ public partial class TabViewModel : ITabViewModel
|
|||||||
return containerViewModel;
|
return containerViewModel;
|
||||||
}
|
}
|
||||||
else if (item is IElement element)
|
else if (item is IElement element)
|
||||||
{
|
|
||||||
var fileExtension = element.GetExtension<FileExtension>();
|
|
||||||
|
|
||||||
if (fileExtension is not null)
|
|
||||||
{
|
|
||||||
var fileViewModel = _serviceProvider
|
|
||||||
.GetInitableResolver<IElement, FileExtension, ITabViewModel, ItemViewModelType>(
|
|
||||||
element, fileExtension, this, type)
|
|
||||||
.GetRequiredService<IFileViewModel>();
|
|
||||||
|
|
||||||
return fileViewModel;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
var elementViewModel = _serviceProvider
|
var elementViewModel = _serviceProvider
|
||||||
.GetInitableResolver<IElement, ITabViewModel, ItemViewModelType>(element, this, type)
|
.GetInitableResolver<IElement, ITabViewModel, ItemViewModelType>(element, this, type)
|
||||||
@@ -225,7 +211,6 @@ public partial class TabViewModel : ITabViewModel
|
|||||||
|
|
||||||
return elementViewModel;
|
return elementViewModel;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
throw new ArgumentException($"{nameof(item)} is not {nameof(IContainer)} neither {nameof(IElement)}");
|
throw new ArgumentException($"{nameof(item)} is not {nameof(IContainer)} neither {nameof(IElement)}");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
using FileTime.App.Core.Models;
|
using System.Collections.ObjectModel;
|
||||||
|
using FileTime.App.ContainerSizeScanner;
|
||||||
|
using FileTime.App.Core.Helpers;
|
||||||
|
using FileTime.App.Core.Models;
|
||||||
using FileTime.App.Core.ViewModels.ItemPreview;
|
using FileTime.App.Core.ViewModels.ItemPreview;
|
||||||
using FileTime.ConsoleUI.App.Preview;
|
using FileTime.ConsoleUI.App.Preview;
|
||||||
using FileTime.ConsoleUI.App.Styling;
|
using FileTime.ConsoleUI.App.Styling;
|
||||||
|
using Humanizer.Bytes;
|
||||||
|
using TerminalUI.Color;
|
||||||
using TerminalUI.Controls;
|
using TerminalUI.Controls;
|
||||||
using TerminalUI.Extensions;
|
using TerminalUI.Extensions;
|
||||||
using TerminalUI.Models;
|
using TerminalUI.Models;
|
||||||
@@ -13,11 +18,18 @@ public class ItemPreviews
|
|||||||
{
|
{
|
||||||
private readonly ITheme _theme;
|
private readonly ITheme _theme;
|
||||||
private readonly IConsoleAppState _appState;
|
private readonly IConsoleAppState _appState;
|
||||||
|
private readonly IColorProvider _colorProvider;
|
||||||
|
private ItemsControl<ContainerPreview, ISizePreviewItem> _sizePreviews;
|
||||||
|
|
||||||
public ItemPreviews(ITheme theme, IConsoleAppState appState)
|
public ItemPreviews(
|
||||||
|
ITheme theme,
|
||||||
|
IConsoleAppState appState,
|
||||||
|
IColorProvider colorProvider
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_theme = theme;
|
_theme = theme;
|
||||||
_appState = appState;
|
_appState = appState;
|
||||||
|
_colorProvider = colorProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IView<IRootViewModel> View()
|
public IView<IRootViewModel> View()
|
||||||
@@ -39,6 +51,10 @@ public class ItemPreviews
|
|||||||
ElementPreviews()
|
ElementPreviews()
|
||||||
.WithDataContextBinding<IRootViewModel, IElementPreviewViewModel>(
|
.WithDataContextBinding<IRootViewModel, IElementPreviewViewModel>(
|
||||||
dc => (IElementPreviewViewModel) dc.ItemPreviewService.ItemPreview.Value
|
dc => (IElementPreviewViewModel) dc.ItemPreviewService.ItemPreview.Value
|
||||||
|
),
|
||||||
|
SizeContainerPreview()
|
||||||
|
.WithDataContextBinding<IRootViewModel, ContainerPreview>(
|
||||||
|
dc => (ContainerPreview) dc.ItemPreviewService.ItemPreview.Value
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -46,6 +62,125 @@ public class ItemPreviews
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IView<ContainerPreview> SizeContainerPreview()
|
||||||
|
{
|
||||||
|
var sizePreviews = new ItemsControl<ContainerPreview, ISizePreviewItem>
|
||||||
|
{
|
||||||
|
Orientation = Orientation.Horizontal,
|
||||||
|
Margin = "0 0 0 1"
|
||||||
|
};
|
||||||
|
sizePreviews.Setup(c => c.Bind(
|
||||||
|
c,
|
||||||
|
dc => dc.TopItems,
|
||||||
|
c => c.ItemsSource));
|
||||||
|
|
||||||
|
_sizePreviews = sizePreviews;
|
||||||
|
|
||||||
|
sizePreviews.ItemTemplate = SizeContainerItem;
|
||||||
|
|
||||||
|
var root = new Grid<ContainerPreview>
|
||||||
|
{
|
||||||
|
RowDefinitionsObject = "Auto Auto",
|
||||||
|
ChildInitializer =
|
||||||
|
{
|
||||||
|
sizePreviews,
|
||||||
|
new ItemsControl<ContainerPreview, ISizePreviewItem>
|
||||||
|
{
|
||||||
|
Extensions = {new GridPositionExtension(0, 1)},
|
||||||
|
ItemTemplate = () =>
|
||||||
|
{
|
||||||
|
var root = new Grid<ISizePreviewItem>
|
||||||
|
{
|
||||||
|
ColumnDefinitionsObject = "5 11 *",
|
||||||
|
ChildInitializer =
|
||||||
|
{
|
||||||
|
new Rectangle<ISizePreviewItem>
|
||||||
|
{
|
||||||
|
Height = 1,
|
||||||
|
Width = 3
|
||||||
|
}
|
||||||
|
.Setup(r => r.Bind(
|
||||||
|
r,
|
||||||
|
dc => GenerateSizeBackground(_sizePreviews.DataContext.TopItems, dc),
|
||||||
|
r => r.Fill)),
|
||||||
|
new TextBlock<ISizePreviewItem>
|
||||||
|
{
|
||||||
|
Extensions = {new GridPositionExtension(1, 0)},
|
||||||
|
TextAlignment = TextAlignment.Right,
|
||||||
|
Margin = "0 0 1 0"
|
||||||
|
}
|
||||||
|
.Setup(t => t.Bind(
|
||||||
|
t,
|
||||||
|
dc => dc.Size.Value,
|
||||||
|
t => t.Text,
|
||||||
|
v => ByteSize.FromBytes(v).ToString())),
|
||||||
|
new TextBlock<ISizePreviewItem>
|
||||||
|
{
|
||||||
|
Extensions = {new GridPositionExtension(2, 0)}
|
||||||
|
}
|
||||||
|
.Setup(t => t.Bind(
|
||||||
|
t,
|
||||||
|
dc => dc.Name,
|
||||||
|
t => t.Text))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.Setup(c => c.Bind(
|
||||||
|
c,
|
||||||
|
dc => dc.TopItems,
|
||||||
|
c => c.ItemsSource))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
root.Bind(
|
||||||
|
root,
|
||||||
|
dc => dc.Name == ContainerPreview.PreviewName,
|
||||||
|
r => r.IsVisible);
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Grid<ISizePreviewItem> SizeContainerItem()
|
||||||
|
{
|
||||||
|
var root = new Grid<ISizePreviewItem>
|
||||||
|
{
|
||||||
|
ChildInitializer =
|
||||||
|
{
|
||||||
|
new Rectangle<ISizePreviewItem>
|
||||||
|
{
|
||||||
|
Height = 1
|
||||||
|
}
|
||||||
|
.Setup(r => r.Bind(
|
||||||
|
r,
|
||||||
|
dc => GenerateSizeBackground(_sizePreviews.DataContext.TopItems, dc),
|
||||||
|
r => r.Fill))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
root.Bind(
|
||||||
|
root,
|
||||||
|
dc => GetWidth(dc.Size.Value, _sizePreviews.DataContext.TopItems, _sizePreviews.ActualWidth),
|
||||||
|
r => r.Width);
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int? GetWidth(long sizeValue, ObservableCollection<ISizePreviewItem>? dataContextTopItems, int rootActualWidth)
|
||||||
|
=> dataContextTopItems is null
|
||||||
|
? 0
|
||||||
|
: (int) Math.Floor((double) rootActualWidth * sizeValue / dataContextTopItems.Select(i => i.Size.Value).Sum());
|
||||||
|
|
||||||
|
private IColor? GenerateSizeBackground(ObservableCollection<ISizePreviewItem> topItems, ISizePreviewItem? dc)
|
||||||
|
{
|
||||||
|
if (dc is null) return null;
|
||||||
|
var (r, g, b) = SizePreviewItemHelper.GetItemColor(topItems, dc);
|
||||||
|
|
||||||
|
return _colorProvider.FromRgb(new Rgb(r, g, b), ColorType.Background);
|
||||||
|
}
|
||||||
|
|
||||||
private IView<IElementPreviewViewModel> ElementPreviews()
|
private IView<IElementPreviewViewModel> ElementPreviews()
|
||||||
{
|
{
|
||||||
var view = new Grid<IElementPreviewViewModel>
|
var view = new Grid<IElementPreviewViewModel>
|
||||||
@@ -60,7 +195,6 @@ public class ItemPreviews
|
|||||||
t,
|
t,
|
||||||
dc => dc.Mode == ItemPreviewMode.Unknown,
|
dc => dc.Mode == ItemPreviewMode.Unknown,
|
||||||
t => t.IsVisible,
|
t => t.IsVisible,
|
||||||
v => v,
|
|
||||||
fallbackValue: false)),
|
fallbackValue: false)),
|
||||||
new TextBlock<IElementPreviewViewModel>
|
new TextBlock<IElementPreviewViewModel>
|
||||||
{
|
{
|
||||||
@@ -70,7 +204,6 @@ public class ItemPreviews
|
|||||||
t,
|
t,
|
||||||
dc => dc.Mode == ItemPreviewMode.Empty,
|
dc => dc.Mode == ItemPreviewMode.Empty,
|
||||||
t => t.IsVisible,
|
t => t.IsVisible,
|
||||||
v => v,
|
|
||||||
fallbackValue: false)),
|
fallbackValue: false)),
|
||||||
new Grid<IElementPreviewViewModel>
|
new Grid<IElementPreviewViewModel>
|
||||||
{
|
{
|
||||||
@@ -120,7 +253,6 @@ public class ItemPreviews
|
|||||||
t,
|
t,
|
||||||
dc => dc.Mode == ItemPreviewMode.Text,
|
dc => dc.Mode == ItemPreviewMode.Text,
|
||||||
t => t.IsVisible,
|
t => t.IsVisible,
|
||||||
v => v,
|
|
||||||
fallbackValue: false)),
|
fallbackValue: false)),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -128,8 +260,7 @@ public class ItemPreviews
|
|||||||
view.Bind(
|
view.Bind(
|
||||||
view,
|
view,
|
||||||
dc => dc.Name == ElementPreviewViewModel.PreviewName,
|
dc => dc.Name == ElementPreviewViewModel.PreviewName,
|
||||||
v => v.IsVisible,
|
v => v.IsVisible
|
||||||
v => v
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\AppCommon\FileTime.App.ContainerSizeScanner\FileTime.App.ContainerSizeScanner.csproj" />
|
||||||
<ProjectReference Include="..\..\AppCommon\FileTime.App.Core\FileTime.App.Core.csproj" />
|
<ProjectReference Include="..\..\AppCommon\FileTime.App.Core\FileTime.App.Core.csproj" />
|
||||||
<ProjectReference Include="..\..\AppCommon\FileTime.App.FrequencyNavigation\FileTime.App.FrequencyNavigation.csproj" />
|
<ProjectReference Include="..\..\AppCommon\FileTime.App.FrequencyNavigation\FileTime.App.FrequencyNavigation.csproj" />
|
||||||
<ProjectReference Include="..\..\Library\TerminalUI\TerminalUI.csproj" />
|
<ProjectReference Include="..\..\Library\TerminalUI\TerminalUI.csproj" />
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using FileTime.App.Core.Models.Enums;
|
using FileTime.App.Core.Models.Enums;
|
||||||
|
using FileTime.App.Core.Models.Traits;
|
||||||
using FileTime.App.Core.ViewModels;
|
using FileTime.App.Core.ViewModels;
|
||||||
using FileTime.ConsoleUI.App.Configuration;
|
using FileTime.ConsoleUI.App.Configuration;
|
||||||
using FileTime.ConsoleUI.App.Controls;
|
using FileTime.ConsoleUI.App.Controls;
|
||||||
@@ -479,7 +480,9 @@ public class MainWindow
|
|||||||
|
|
||||||
list.Bind(
|
list.Bind(
|
||||||
list,
|
list,
|
||||||
dc => dc.AppState.SelectedTab.Value.SelectedsChildren.Value.Count > 0,
|
dc =>
|
||||||
|
dc.AppState.SelectedTab.Value.SelectedsChildren.Value.Count > 0
|
||||||
|
&& dc.ItemPreviewService.ItemPreview.Value == null,
|
||||||
l => l.IsVisible,
|
l => l.IsVisible,
|
||||||
fallbackValue: false);
|
fallbackValue: false);
|
||||||
|
|
||||||
@@ -544,28 +547,9 @@ public class MainWindow
|
|||||||
if (!options.ShowAttributes) return;
|
if (!options.ShowAttributes) return;
|
||||||
t.Bind(
|
t.Bind(
|
||||||
t,
|
t,
|
||||||
dc => ((IContainer) dc.BaseItem).Items.Count,
|
dc => dc is ISizeProvider
|
||||||
tb => tb.Text,
|
? ((ISizeProvider) dc).Size.Value
|
||||||
t => $" {t}");
|
: ((ISizeProvider) dc.BaseItem).Size.Value,
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.Setup(s => s.Bind(
|
|
||||||
s,
|
|
||||||
dc => dc.BaseItem.Type == AbsolutePathType.Container,
|
|
||||||
s => s.IsVisible)),
|
|
||||||
new StackPanel<IItemViewModel>
|
|
||||||
{
|
|
||||||
Extensions = {new GridPositionExtension(1, 0)},
|
|
||||||
ChildInitializer =
|
|
||||||
{
|
|
||||||
new TextBlock<IItemViewModel>()
|
|
||||||
.Setup(t =>
|
|
||||||
{
|
|
||||||
if (!options.ShowAttributes) return;
|
|
||||||
t.Bind(
|
|
||||||
t,
|
|
||||||
dc => ((IElementViewModel) dc).Size.Value,
|
|
||||||
tb => tb.Text,
|
tb => tb.Text,
|
||||||
v =>
|
v =>
|
||||||
{
|
{
|
||||||
@@ -573,13 +557,23 @@ public class MainWindow
|
|||||||
|
|
||||||
return $"{b.LargestWholeNumberValue:0.#} " + b.GetLargestWholeNumberSymbol(NumberFormatInfo.CurrentInfo).First();
|
return $"{b.LargestWholeNumberValue:0.#} " + b.GetLargestWholeNumberSymbol(NumberFormatInfo.CurrentInfo).First();
|
||||||
});
|
});
|
||||||
})
|
}),
|
||||||
}
|
|
||||||
}
|
/*new TextBlock<IItemViewModel>()
|
||||||
.Setup(s => s.Bind(
|
.Setup(t =>
|
||||||
|
{
|
||||||
|
if (!options.ShowAttributes) return;
|
||||||
|
t.Bind(
|
||||||
|
t,
|
||||||
|
dc => ((IContainer) dc.BaseItem).Items.Count,
|
||||||
|
tb => tb.Text,
|
||||||
|
t => $" {t,4}");
|
||||||
|
}).Setup(s => s.Bind(
|
||||||
s,
|
s,
|
||||||
dc => dc.BaseItem.Type == AbsolutePathType.Element,
|
dc => dc.BaseItem.Type == AbsolutePathType.Container,
|
||||||
s => s.IsVisible))
|
s => s.IsVisible))*/
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.ExceptionServices;
|
|
||||||
using FileTime.App.Core;
|
using FileTime.App.Core;
|
||||||
using FileTime.App.Core.Configuration;
|
using FileTime.App.Core.Configuration;
|
||||||
using FileTime.ConsoleUI;
|
using FileTime.ConsoleUI;
|
||||||
@@ -52,7 +50,6 @@ try
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
driver?.Clear();
|
|
||||||
driver?.SetCursorVisible(true);
|
driver?.SetCursorVisible(true);
|
||||||
driver?.Dispose();
|
driver?.Dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public static class Startup
|
|||||||
{
|
{
|
||||||
public static readonly Dictionary<string, Func<IConsoleDriver>> Drivers = new()
|
public static readonly Dictionary<string, Func<IConsoleDriver>> Drivers = new()
|
||||||
{
|
{
|
||||||
["windows"] = () => new XTermDriver(),
|
["xterm"] = () => new XTermDriver(),
|
||||||
["dotnet"] = () => new DotnetDriver()
|
["dotnet"] = () => new DotnetDriver()
|
||||||
};
|
};
|
||||||
public static IServiceCollection AddConsoleDriver(this IServiceCollection serviceCollection)
|
public static IServiceCollection AddConsoleDriver(this IServiceCollection serviceCollection)
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
namespace FileTime.Core.Models.Extensions;
|
|
||||||
|
|
||||||
public record FileExtension(long? Size);
|
|
||||||
@@ -2,5 +2,5 @@ namespace FileTime.Core.Models;
|
|||||||
|
|
||||||
public interface IElement : IItem
|
public interface IElement : IItem
|
||||||
{
|
{
|
||||||
|
long Size { get; }
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
using FileTime.Core.Models;
|
using FileTime.Core.Models;
|
||||||
using FileTime.Core.Models.Extensions;
|
|
||||||
using FileTime.Core.Timeline;
|
using FileTime.Core.Timeline;
|
||||||
|
|
||||||
namespace FileTime.Core.Command.Copy;
|
namespace FileTime.Core.Command.Copy;
|
||||||
@@ -20,7 +19,7 @@ public class CalculateStrategy : ICopyStrategy
|
|||||||
public async Task CopyAsync(AbsolutePath from, AbsolutePath to, CopyCommandContext context)
|
public async Task CopyAsync(AbsolutePath from, AbsolutePath to, CopyCommandContext context)
|
||||||
{
|
{
|
||||||
var resolvedFrom = await from.ResolveAsync();
|
var resolvedFrom = await from.ResolveAsync();
|
||||||
_operationStatuses.Add(new OperationProgress(from.Path.Path, (resolvedFrom as IElement)?.GetExtension<FileExtension>()?.Size ?? 0L));
|
_operationStatuses.Add(new OperationProgress(from.Path.Path, (resolvedFrom as IElement)?.Size ?? 0L));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task CreateContainerAsync(IContainer target, string name, PointInTime currentTime) => Task.CompletedTask;
|
public Task CreateContainerAsync(IContainer target, string name, PointInTime currentTime) => Task.CompletedTask;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ public record Element(
|
|||||||
SupportsDelete CanDelete,
|
SupportsDelete CanDelete,
|
||||||
bool CanRename,
|
bool CanRename,
|
||||||
string? Attributes,
|
string? Attributes,
|
||||||
|
long Size,
|
||||||
IContentProvider Provider,
|
IContentProvider Provider,
|
||||||
PointInTime PointInTime,
|
PointInTime PointInTime,
|
||||||
ObservableCollection<Exception> Exceptions,
|
ObservableCollection<Exception> Exceptions,
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ using DeclarativeProperty;
|
|||||||
using DynamicData;
|
using DynamicData;
|
||||||
using FileTime.Core.Helper;
|
using FileTime.Core.Helper;
|
||||||
using FileTime.Core.Models;
|
using FileTime.Core.Models;
|
||||||
using FileTime.Core.Models.Extensions;
|
|
||||||
using FileTime.Core.Timeline;
|
using FileTime.Core.Timeline;
|
||||||
using ObservableComputations;
|
using ObservableComputations;
|
||||||
using IContainer = FileTime.Core.Models.IContainer;
|
using IContainer = FileTime.Core.Models.IContainer;
|
||||||
@@ -178,12 +177,12 @@ public class Tab : ITab
|
|||||||
|
|
||||||
private static long GetSize(IItem item)
|
private static long GetSize(IItem item)
|
||||||
{
|
{
|
||||||
if (item is IElement element && element.GetExtension<FileExtension>() is { } fileExtension)
|
if (item is IElement element)
|
||||||
{
|
{
|
||||||
return fileExtension.Size ?? -1;
|
return element.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -2;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IItem MapItem(AbsolutePath item)
|
private static IItem MapItem(AbsolutePath item)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using Avalonia.Data.Converters;
|
|||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using FileTime.App.ContainerSizeScanner;
|
using FileTime.App.ContainerSizeScanner;
|
||||||
using FileTime.GuiApp.App.Helper;
|
using FileTime.App.Core.Helpers;
|
||||||
|
|
||||||
namespace FileTime.GuiApp.App.Converters;
|
namespace FileTime.GuiApp.App.Converters;
|
||||||
|
|
||||||
@@ -16,18 +16,12 @@ public class ItemSizeToBrushConverter : IMultiValueConverter
|
|||||||
{
|
{
|
||||||
if (values is [ISizePreviewItem previewItem, ContainerPreview sizeContainerViewModel])
|
if (values is [ISizePreviewItem previewItem, ContainerPreview sizeContainerViewModel])
|
||||||
{
|
{
|
||||||
var items = sizeContainerViewModel.TopItems;
|
var (r, g, b) = SizePreviewItemHelper.GetItemColor(
|
||||||
var i = 0;
|
sizeContainerViewModel.TopItems,
|
||||||
for (; i < items.Count; i++)
|
previewItem,
|
||||||
{
|
HueDiff,
|
||||||
if (items[i].Name == previewItem.Name) break;
|
Lightness
|
||||||
}
|
);
|
||||||
|
|
||||||
var hue = (360d * i / (items.Count < 1 ? 1 : items.Count)) + HueDiff;
|
|
||||||
if (hue > 360) hue -= 360;
|
|
||||||
if (hue < 0) hue += 360;
|
|
||||||
|
|
||||||
var (r, g, b) = ColorHelper.HlsToRgb(hue, Lightness, 1);
|
|
||||||
|
|
||||||
var task = Dispatcher.UIThread.InvokeAsync(() => new SolidColorBrush(Color.FromRgb(r, g, b)));
|
var task = Dispatcher.UIThread.InvokeAsync(() => new SolidColorBrush(Color.FromRgb(r, g, b)));
|
||||||
task.Wait();
|
task.Wait();
|
||||||
|
|||||||
@@ -1,48 +1,52 @@
|
|||||||
<UserControl
|
<UserControl
|
||||||
Background="{Binding ViewMode.Value, Converter={StaticResource ItemViewModeToBackgroundConverter}}"
|
|
||||||
HorizontalAlignment="Stretch"
|
|
||||||
HorizontalContentAlignment="Stretch"
|
|
||||||
d:DesignHeight="450"
|
|
||||||
d:DesignWidth="800"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
x:Class="FileTime.GuiApp.App.Views.ItemView"
|
x:Class="FileTime.GuiApp.App.Views.ItemView"
|
||||||
x:CompileBindings="True"
|
|
||||||
x:DataType="appcore:IItemViewModel"
|
|
||||||
x:Name="ItemRoot"
|
|
||||||
xmlns="https://github.com/avaloniaui"
|
xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:appcore="using:FileTime.App.Core.ViewModels"
|
xmlns:appcore="using:FileTime.App.Core.ViewModels"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:guiappvm="using:FileTime.GuiApp.App.ViewModels"
|
xmlns:guiappvm="using:FileTime.GuiApp.App.ViewModels"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:traits="clr-namespace:FileTime.App.Core.Models.Traits;assembly=FileTime.App.Core.Abstraction"
|
xmlns:traits="clr-namespace:FileTime.App.Core.Models.Traits;assembly=FileTime.App.Core.Abstraction"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
x:Name="ItemRoot"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
HorizontalContentAlignment="Stretch"
|
||||||
|
d:DesignHeight="450"
|
||||||
|
d:DesignWidth="800"
|
||||||
|
x:CompileBindings="True"
|
||||||
|
x:DataType="appcore:IItemViewModel"
|
||||||
|
Background="{Binding ViewMode.Value, Converter={StaticResource ItemViewModeToBackgroundConverter}}"
|
||||||
|
mc:Ignorable="d">
|
||||||
<Grid
|
<Grid
|
||||||
ColumnDefinitions="20,*,Auto"
|
x:Name="RootGrid"
|
||||||
Margin="3"
|
Margin="3"
|
||||||
x:Name="RootGrid">
|
ColumnDefinitions="20,*,Auto">
|
||||||
<Grid.Styles>
|
<Grid.Styles>
|
||||||
<Style Selector="TextBlock">
|
<Style Selector="TextBlock">
|
||||||
<Setter Property="Foreground" Value="{Binding DataContext.ViewMode.Value, Converter={StaticResource ItemViewModeToForegroundConverter}, ElementName=ItemRoot}" x:CompileBindings="False" />
|
<Setter x:CompileBindings="False" Property="Foreground" Value="{Binding DataContext.ViewMode.Value, Converter={StaticResource ItemViewModeToForegroundConverter}, ElementName=ItemRoot}" />
|
||||||
</Style>
|
</Style>
|
||||||
</Grid.Styles>
|
</Grid.Styles>
|
||||||
<Image
|
<Image
|
||||||
|
Width="18"
|
||||||
Height="18"
|
Height="18"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
Source="{Binding Converter={StaticResource ItemToImageConverter}}"
|
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Width="18" />
|
Source="{Binding Converter={StaticResource ItemToImageConverter}}" />
|
||||||
|
|
||||||
<ItemsControl
|
<ItemsControl
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
HorizontalAlignment="Stretch"
|
|
||||||
Margin="5,0,0,0"
|
Margin="5,0,0,0"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
VerticalAlignment="Center">
|
VerticalAlignment="Center">
|
||||||
<ItemsControl.ItemsSource>
|
<ItemsControl.ItemsSource>
|
||||||
<MultiBinding Converter="{StaticResource NamePartShrinkerConverter}">
|
<MultiBinding Converter="{StaticResource NamePartShrinkerConverter}">
|
||||||
<MultiBinding.Bindings>
|
<MultiBinding.Bindings>
|
||||||
<Binding Path="DisplayName^" />
|
<Binding Path="DisplayName^" />
|
||||||
<Binding ElementName="RootGrid" Path="Bounds.Width" />
|
<Binding
|
||||||
<Binding ElementName="ItemRoot" Path="ShowAttributes" />
|
ElementName="RootGrid"
|
||||||
|
Path="Bounds.Width" />
|
||||||
|
<Binding
|
||||||
|
ElementName="ItemRoot"
|
||||||
|
Path="ShowAttributes" />
|
||||||
</MultiBinding.Bindings>
|
</MultiBinding.Bindings>
|
||||||
</MultiBinding>
|
</MultiBinding>
|
||||||
</ItemsControl.ItemsSource>
|
</ItemsControl.ItemsSource>
|
||||||
@@ -54,52 +58,50 @@
|
|||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate x:DataType="guiappvm:ItemNamePartViewModel">
|
<DataTemplate x:DataType="guiappvm:ItemNamePartViewModel">
|
||||||
<Grid>
|
<Grid>
|
||||||
<TextBlock Text="{Binding Text}" TextDecorations="{Binding TextDecorations}" />
|
<TextBlock
|
||||||
|
Text="{Binding Text}"
|
||||||
|
TextDecorations="{Binding TextDecorations}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ItemsControl.ItemTemplate>
|
</ItemsControl.ItemTemplate>
|
||||||
</ItemsControl>
|
</ItemsControl>
|
||||||
|
|
||||||
<Grid Grid.Column="2" IsVisible="{Binding ShowAttributes, ElementName=ItemRoot}">
|
<Grid
|
||||||
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
|
Grid.Column="2"
|
||||||
|
IsVisible="{Binding ShowAttributes, ElementName=ItemRoot}">
|
||||||
|
<StackPanel
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
Orientation="Horizontal">
|
||||||
<TextBlock
|
<TextBlock
|
||||||
|
Width="50"
|
||||||
Classes="SmallText"
|
Classes="SmallText"
|
||||||
IsVisible="{Binding Converter={StaticResource IsTypeConverter}, ConverterParameter={x:Type appcore:IElementViewModel}}"
|
IsVisible="{Binding Converter={StaticResource IsTypeConverter}, ConverterParameter={x:Type appcore:IElementViewModel}}"
|
||||||
Text="{Binding BaseItem.DisplayName, Converter={StaticResource GetFileExtensionConverter}}"
|
Text="{Binding BaseItem.DisplayName, Converter={StaticResource GetFileExtensionConverter}}" />
|
||||||
Width="50" />
|
<Grid
|
||||||
<Grid DataContext="{Binding BaseItem}" IsVisible="{Binding Converter={StaticResource IsTypeConverter}, ConverterParameter={x:Type traits:ISizeProvider}}">
|
DataContext="{Binding BaseItem}"
|
||||||
|
IsVisible="{Binding Converter={StaticResource IsTypeConverter}, ConverterParameter={x:Type traits:ISizeProvider}}">
|
||||||
<TextBlock
|
<TextBlock
|
||||||
|
Width="60"
|
||||||
|
x:DataType="traits:ISizeProvider"
|
||||||
Classes="SmallText"
|
Classes="SmallText"
|
||||||
Text="{Binding Size.Value, Converter={StaticResource FormatSizeConverter}}"
|
Text="{Binding Size.Value, Converter={StaticResource FormatSizeConverter}}"
|
||||||
TextAlignment="Right"
|
TextAlignment="Right" />
|
||||||
Width="60"
|
|
||||||
x:DataType="traits:ISizeProvider" />
|
|
||||||
</Grid>
|
|
||||||
<Grid IsVisible="{Binding BaseItem, Converter={StaticResource IsNotTypeConverter}, ConverterParameter={x:Type traits:ISizeProvider}}">
|
|
||||||
|
|
||||||
<TextBlock
|
|
||||||
Classes="SmallText"
|
|
||||||
IsVisible="{Binding Converter={StaticResource IsTypeConverter}, ConverterParameter={x:Type traits:ISizeProvider}}"
|
|
||||||
Text="{Binding Size.Value, Converter={StaticResource FormatSizeConverter}}"
|
|
||||||
TextAlignment="Right"
|
|
||||||
Width="60"
|
|
||||||
x:DataType="traits:ISizeProvider" />
|
|
||||||
</Grid>
|
</Grid>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
|
Width="95"
|
||||||
Classes="SmallText"
|
Classes="SmallText"
|
||||||
Text="{Binding ModifiedAt, Converter={StaticResource DateTimeConverter}, ConverterParameter=yyyy-MM-dd}"
|
Text="{Binding ModifiedAt, Converter={StaticResource DateTimeConverter}, ConverterParameter=yyyy-MM-dd}"
|
||||||
TextAlignment="Right"
|
TextAlignment="Right" />
|
||||||
Width="95" />
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
|
Width="35"
|
||||||
Classes="SmallText"
|
Classes="SmallText"
|
||||||
Text="{Binding ModifiedAt, Converter={StaticResource DateTimeConverter}, ConverterParameter=hh:mm}"
|
Text="{Binding ModifiedAt, Converter={StaticResource DateTimeConverter}, ConverterParameter=hh:mm}"
|
||||||
TextAlignment="Right"
|
TextAlignment="Right" />
|
||||||
Width="35" />
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
|
Width="45"
|
||||||
Classes="SmallText"
|
Classes="SmallText"
|
||||||
Text="{Binding BaseItem.Attributes}"
|
Text="{Binding BaseItem.Attributes}"
|
||||||
TextAlignment="Right"
|
TextAlignment="Right" />
|
||||||
Width="45" />
|
|
||||||
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ public class ItemPreview
|
|||||||
SupportsDelete.True,
|
SupportsDelete.True,
|
||||||
true,
|
true,
|
||||||
"attr",
|
"attr",
|
||||||
|
0,
|
||||||
null!,
|
null!,
|
||||||
PointInTime.Present,
|
PointInTime.Present,
|
||||||
new ObservableCollection<Exception>(),
|
new ObservableCollection<Exception>(),
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ using FileTime.GuiApp.App.Font;
|
|||||||
using FileTime.GuiApp.App.ViewModels;
|
using FileTime.GuiApp.App.ViewModels;
|
||||||
using FileTime.GuiApp.App.Views;
|
using FileTime.GuiApp.App.Views;
|
||||||
using FileTime.Server;
|
using FileTime.Server;
|
||||||
using FileTime.Server.Common;
|
|
||||||
using FileTime.Tools.Compression;
|
using FileTime.Tools.Compression;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|||||||
@@ -6,49 +6,24 @@ public class AnsiColorProvider : ColorProviderBase
|
|||||||
{
|
{
|
||||||
var finalColor = ParseInternal(color, type);
|
var finalColor = ParseInternal(color, type);
|
||||||
|
|
||||||
finalColor ??= ParseHexColor(color, type);
|
finalColor ??= FromRgb(color, type);
|
||||||
|
|
||||||
if (finalColor is not null) return finalColor;
|
if (finalColor is not null) return finalColor;
|
||||||
|
|
||||||
throw new NotSupportedException($"Color can not be parsed. {color}");
|
throw new NotSupportedException($"Color can not be parsed. {color}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IColor? ParseHexColor(string color, ColorType colorType)
|
private IColor? FromRgb(string color, ColorType type)
|
||||||
{
|
{
|
||||||
if (!color.StartsWith("#")) return null;
|
if (ParseHexColor(color) is var (r, g, b))
|
||||||
if (color.Length == 4)
|
|
||||||
{
|
{
|
||||||
var r = ColorCharToColorByte(color[1]);
|
return new ColorRgb(r, g, b, type);
|
||||||
var g = ColorCharToColorByte(color[2]);
|
|
||||||
var b = ColorCharToColorByte(color[3]);
|
|
||||||
|
|
||||||
r += (byte) (r << 4);
|
|
||||||
g += (byte) (g << 4);
|
|
||||||
b += (byte) (b << 4);
|
|
||||||
|
|
||||||
return new ColorRgb(r, g, b, colorType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (color.Length == 7)
|
return null;
|
||||||
{
|
|
||||||
var r = (byte) (ColorCharToColorByte(color[1]) << 4 | ColorCharToColorByte(color[2]));
|
|
||||||
var g = (byte) (ColorCharToColorByte(color[3]) << 4 | ColorCharToColorByte(color[4]));
|
|
||||||
var b = (byte) (ColorCharToColorByte(color[5]) << 4 | ColorCharToColorByte(color[6]));
|
|
||||||
|
|
||||||
return new ColorRgb(r, g, b, colorType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NotSupportedException($"Hex color can not be parsed. {color}");
|
public override IColor FromRgb(Rgb rgb, ColorType type) => new ColorRgb(rgb.R, rgb.G, rgb.B, type);
|
||||||
}
|
|
||||||
|
|
||||||
private static byte ColorCharToColorByte(char color) =>
|
|
||||||
color switch
|
|
||||||
{
|
|
||||||
>= '0' and <= '9' => (byte) (color - '0'),
|
|
||||||
>= 'A' and <= 'F' => (byte) (color - 'A' + 10),
|
|
||||||
>= 'a' and <= 'f' => (byte) (color - 'a' + 10),
|
|
||||||
_ => throw new NotSupportedException($"Hex color can not be parsed. {color}")
|
|
||||||
};
|
|
||||||
|
|
||||||
public override IColor BlackForeground { get; } = new Color256(0, ColorType.Foreground);
|
public override IColor BlackForeground { get; } = new Color256(0, ColorType.Foreground);
|
||||||
public override IColor BlueForeground { get; } = new Color256(12, ColorType.Foreground);
|
public override IColor BlueForeground { get; } = new Color256(12, ColorType.Foreground);
|
||||||
|
|||||||
@@ -3,6 +3,44 @@
|
|||||||
public abstract class ColorProviderBase : IColorProvider
|
public abstract class ColorProviderBase : IColorProvider
|
||||||
{
|
{
|
||||||
public abstract IColor Parse(string color, ColorType type);
|
public abstract IColor Parse(string color, ColorType type);
|
||||||
|
public abstract IColor FromRgb(Rgb rgb, ColorType type);
|
||||||
|
|
||||||
|
protected static Rgb? ParseHexColor(string color)
|
||||||
|
{
|
||||||
|
if (!color.StartsWith("#")) return null;
|
||||||
|
if (color.Length == 4)
|
||||||
|
{
|
||||||
|
var r = ColorCharToColorByte(color[1]);
|
||||||
|
var g = ColorCharToColorByte(color[2]);
|
||||||
|
var b = ColorCharToColorByte(color[3]);
|
||||||
|
|
||||||
|
r += (byte) (r << 4);
|
||||||
|
g += (byte) (g << 4);
|
||||||
|
b += (byte) (b << 4);
|
||||||
|
|
||||||
|
return new(r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (color.Length == 7)
|
||||||
|
{
|
||||||
|
var r = (byte) (ColorCharToColorByte(color[1]) << 4 | ColorCharToColorByte(color[2]));
|
||||||
|
var g = (byte) (ColorCharToColorByte(color[3]) << 4 | ColorCharToColorByte(color[4]));
|
||||||
|
var b = (byte) (ColorCharToColorByte(color[5]) << 4 | ColorCharToColorByte(color[6]));
|
||||||
|
|
||||||
|
return new(r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte ColorCharToColorByte(char color) =>
|
||||||
|
color switch
|
||||||
|
{
|
||||||
|
>= '0' and <= '9' => (byte) (color - '0'),
|
||||||
|
>= 'A' and <= 'F' => (byte) (color - 'A' + 10),
|
||||||
|
>= 'a' and <= 'f' => (byte) (color - 'a' + 10),
|
||||||
|
_ => throw new NotSupportedException($"Hex color can not be parsed. {color}")
|
||||||
|
};
|
||||||
|
|
||||||
protected IColor? ParseInternal(string color, ColorType type)
|
protected IColor? ParseInternal(string color, ColorType type)
|
||||||
=> (color.ToLower(), type) switch
|
=> (color.ToLower(), type) switch
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ public readonly record struct ColorRgb(byte R, byte G, byte B, ColorType Type) :
|
|||||||
public string ToConsoleColor()
|
public string ToConsoleColor()
|
||||||
=> Type switch
|
=> Type switch
|
||||||
{
|
{
|
||||||
ColorType.Foreground => $"\x1b[38;2;{R};{G};{B};m",
|
ColorType.Foreground => $"\x1b[38;2;{R};{G};{B}m",
|
||||||
ColorType.Background => $"\x1b[48;2;{R};{G};{B};m",
|
ColorType.Background => $"\x1b[48;2;{R};{G};{B}m",
|
||||||
_ => throw new InvalidEnumArgumentException(nameof(Type), (int) Type, typeof(ColorType))
|
_ => throw new InvalidEnumArgumentException(nameof(Type), (int) Type, typeof(ColorType))
|
||||||
};
|
};
|
||||||
public IColor AsForeground() => this with {Type = ColorType.Foreground};
|
public IColor AsForeground() => this with {Type = ColorType.Foreground};
|
||||||
|
|||||||
@@ -1,48 +1,143 @@
|
|||||||
namespace TerminalUI.Color;
|
// ReSharper disable InconsistentNaming
|
||||||
|
namespace TerminalUI.Color;
|
||||||
|
|
||||||
public class ConsoleColorProvider : ColorProviderBase
|
public class ConsoleColorProvider : ColorProviderBase
|
||||||
{
|
{
|
||||||
|
private static readonly List<(Rgb, IColor)> Foregrounds;
|
||||||
|
private static readonly List<(Rgb, IColor)> Backgrounds;
|
||||||
|
|
||||||
|
static ConsoleColorProvider()
|
||||||
|
{
|
||||||
|
Foregrounds = new List<(Rgb, IColor)>
|
||||||
|
{
|
||||||
|
(new Rgb(0, 0, 0), _blackForeground),
|
||||||
|
(new Rgb(0, 0, 128), _darkBlueForeground),
|
||||||
|
(new Rgb(0, 128, 0), _darkGreenForeground),
|
||||||
|
(new Rgb(0, 128, 128), _darkCyanForeground),
|
||||||
|
(new Rgb(128, 0, 0), _darkRedForeground),
|
||||||
|
(new Rgb(128, 0, 128), _darkMagentaForeground),
|
||||||
|
(new Rgb(128, 128, 0), _darkYellowForeground),
|
||||||
|
(new Rgb(192, 192, 192), _grayForeground),
|
||||||
|
(new Rgb(128, 128, 128), _darkGrayForeground),
|
||||||
|
(new Rgb(0, 0, 255), _blueForeground),
|
||||||
|
(new Rgb(0, 255, 0), _greenForeground),
|
||||||
|
(new Rgb(0, 255, 255), _cyanForeground),
|
||||||
|
(new Rgb(255, 0, 0), _redForeground),
|
||||||
|
(new Rgb(255, 0, 255), _magentaForeground),
|
||||||
|
(new Rgb(255, 255, 0), _yellowForeground),
|
||||||
|
(new Rgb(255, 255, 255), _whiteForeground),
|
||||||
|
};
|
||||||
|
|
||||||
|
Backgrounds = new List<(Rgb, IColor)>
|
||||||
|
{
|
||||||
|
(new Rgb(0, 0, 0), _blackBackground),
|
||||||
|
(new Rgb(0, 0, 128), _darkBlueBackground),
|
||||||
|
(new Rgb(0, 128, 0), _darkGreenBackground),
|
||||||
|
(new Rgb(0, 128, 128), _darkCyanBackground),
|
||||||
|
(new Rgb(128, 0, 0), _darkRedBackground),
|
||||||
|
(new Rgb(128, 0, 128), _darkMagentaBackground),
|
||||||
|
(new Rgb(128, 128, 0), _darkYellowBackground),
|
||||||
|
(new Rgb(192, 192, 192), _grayBackground),
|
||||||
|
(new Rgb(128, 128, 128), _darkGrayBackground),
|
||||||
|
(new Rgb(0, 0, 255), _blueBackground),
|
||||||
|
(new Rgb(0, 255, 0), _greenBackground),
|
||||||
|
(new Rgb(0, 255, 255), _cyanBackground),
|
||||||
|
(new Rgb(255, 0, 0), _redBackground),
|
||||||
|
(new Rgb(255, 0, 255), _magentaBackground),
|
||||||
|
(new Rgb(255, 255, 0), _yellowBackground),
|
||||||
|
(new Rgb(255, 255, 255), _whiteBackground),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public override IColor Parse(string color, ColorType type)
|
public override IColor Parse(string color, ColorType type)
|
||||||
{
|
{
|
||||||
var finalColor = ParseInternal(color, type);
|
var finalColor = ParseInternal(color, type);
|
||||||
if (finalColor is not null) return finalColor;
|
if (finalColor is not null) return finalColor;
|
||||||
|
|
||||||
//TODO get closest color
|
//TODO get closest color
|
||||||
|
var rgb = ParseHexColor(color);
|
||||||
|
|
||||||
|
if (rgb is null)
|
||||||
|
{
|
||||||
throw new NotSupportedException($"Color can not be parsed. {color}");
|
throw new NotSupportedException($"Color can not be parsed. {color}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IColor BlackForeground { get; } = new ConsoleColor(System.ConsoleColor.Black, ColorType.Foreground);
|
return FromRgb(rgb.Value, type);
|
||||||
public override IColor BlueForeground { get; } = new ConsoleColor(System.ConsoleColor.Blue, ColorType.Foreground);
|
}
|
||||||
public override IColor CyanForeground { get; } = new ConsoleColor(System.ConsoleColor.Cyan, ColorType.Foreground);
|
|
||||||
public override IColor DarkBlueForeground { get; } = new ConsoleColor(System.ConsoleColor.DarkBlue, ColorType.Foreground);
|
public override IColor FromRgb(Rgb rgb, ColorType type)
|
||||||
public override IColor DarkCyanForeground { get; } = new ConsoleColor(System.ConsoleColor.DarkCyan, ColorType.Foreground);
|
=> type == ColorType.Background
|
||||||
public override IColor DarkGrayForeground { get; } = new ConsoleColor(System.ConsoleColor.DarkGray, ColorType.Foreground);
|
? ApproximateColor(rgb, Backgrounds)
|
||||||
public override IColor DarkGreenForeground { get; } = new ConsoleColor(System.ConsoleColor.DarkGreen, ColorType.Foreground);
|
: ApproximateColor(rgb, Foregrounds);
|
||||||
public override IColor DarkMagentaForeground { get; } = new ConsoleColor(System.ConsoleColor.DarkMagenta, ColorType.Foreground);
|
|
||||||
public override IColor DarkRedForeground { get; } = new ConsoleColor(System.ConsoleColor.DarkRed, ColorType.Foreground);
|
protected IColor ApproximateColor(Rgb rgb, IEnumerable<(Rgb, IColor)> colors)
|
||||||
public override IColor DarkYellowForeground { get; } = new ConsoleColor(System.ConsoleColor.DarkYellow, ColorType.Foreground);
|
=> colors.MinBy(c => c.Item1 - rgb).Item2;
|
||||||
public override IColor GrayForeground { get; } = new ConsoleColor(System.ConsoleColor.Gray, ColorType.Foreground);
|
|
||||||
public override IColor GreenForeground { get; } = new ConsoleColor(System.ConsoleColor.Green, ColorType.Foreground);
|
public override IColor BlackForeground => _blackForeground;
|
||||||
public override IColor MagentaForeground { get; } = new ConsoleColor(System.ConsoleColor.Magenta, ColorType.Foreground);
|
public override IColor BlueForeground => _blueForeground;
|
||||||
public override IColor RedForeground { get; } = new ConsoleColor(System.ConsoleColor.Red, ColorType.Foreground);
|
public override IColor CyanForeground => _cyanForeground;
|
||||||
public override IColor WhiteForeground { get; } = new ConsoleColor(System.ConsoleColor.White, ColorType.Foreground);
|
public override IColor DarkBlueForeground => _darkBlueForeground;
|
||||||
public override IColor YellowForeground { get; } = new ConsoleColor(System.ConsoleColor.Yellow, ColorType.Foreground);
|
public override IColor DarkCyanForeground => _darkCyanForeground;
|
||||||
|
public override IColor DarkGrayForeground => _darkGrayForeground;
|
||||||
public override IColor BlackBackground => new ConsoleColor(System.ConsoleColor.Black, ColorType.Background);
|
public override IColor DarkGreenForeground => _darkGreenForeground;
|
||||||
public override IColor BlueBackground => new ConsoleColor(System.ConsoleColor.Blue, ColorType.Background);
|
public override IColor DarkMagentaForeground => _darkMagentaForeground;
|
||||||
public override IColor CyanBackground => new ConsoleColor(System.ConsoleColor.Cyan, ColorType.Background);
|
public override IColor DarkRedForeground => _darkRedForeground;
|
||||||
public override IColor DarkBlueBackground => new ConsoleColor(System.ConsoleColor.DarkBlue, ColorType.Background);
|
public override IColor DarkYellowForeground => _darkYellowForeground;
|
||||||
public override IColor DarkCyanBackground => new ConsoleColor(System.ConsoleColor.DarkCyan, ColorType.Background);
|
public override IColor GrayForeground => _grayForeground;
|
||||||
public override IColor DarkGrayBackground => new ConsoleColor(System.ConsoleColor.DarkGray, ColorType.Background);
|
public override IColor GreenForeground => _greenForeground;
|
||||||
public override IColor DarkGreenBackground => new ConsoleColor(System.ConsoleColor.DarkGreen, ColorType.Background);
|
public override IColor MagentaForeground => _magentaForeground;
|
||||||
public override IColor DarkMagentaBackground => new ConsoleColor(System.ConsoleColor.DarkMagenta, ColorType.Background);
|
public override IColor RedForeground => _redForeground;
|
||||||
public override IColor DarkRedBackground => new ConsoleColor(System.ConsoleColor.DarkRed, ColorType.Background);
|
public override IColor WhiteForeground => _whiteForeground;
|
||||||
public override IColor DarkYellowBackground => new ConsoleColor(System.ConsoleColor.DarkYellow, ColorType.Background);
|
public override IColor YellowForeground => _yellowForeground;
|
||||||
public override IColor GrayBackground => new ConsoleColor(System.ConsoleColor.Gray, ColorType.Background);
|
|
||||||
public override IColor GreenBackground => new ConsoleColor(System.ConsoleColor.Green, ColorType.Background);
|
public override IColor BlackBackground => _blackBackground;
|
||||||
public override IColor MagentaBackground => new ConsoleColor(System.ConsoleColor.Magenta, ColorType.Background);
|
public override IColor BlueBackground => _blueBackground;
|
||||||
public override IColor RedBackground => new ConsoleColor(System.ConsoleColor.Red, ColorType.Background);
|
public override IColor CyanBackground => _cyanBackground;
|
||||||
public override IColor WhiteBackground => new ConsoleColor(System.ConsoleColor.White, ColorType.Background);
|
public override IColor DarkBlueBackground => _darkBlueBackground;
|
||||||
public override IColor YellowBackground => new ConsoleColor(System.ConsoleColor.Yellow, ColorType.Background);
|
public override IColor DarkCyanBackground => _darkCyanBackground;
|
||||||
|
public override IColor DarkGrayBackground => _darkGrayBackground;
|
||||||
|
public override IColor DarkGreenBackground => _darkGreenBackground;
|
||||||
|
public override IColor DarkMagentaBackground => _darkMagentaBackground;
|
||||||
|
public override IColor DarkRedBackground => _darkRedBackground;
|
||||||
|
public override IColor DarkYellowBackground => _darkYellowBackground;
|
||||||
|
public override IColor GrayBackground => _grayBackground;
|
||||||
|
public override IColor GreenBackground => _greenBackground;
|
||||||
|
public override IColor MagentaBackground => _magentaBackground;
|
||||||
|
public override IColor RedBackground => _redBackground;
|
||||||
|
public override IColor WhiteBackground => _whiteBackground;
|
||||||
|
public override IColor YellowBackground => _yellowBackground;
|
||||||
|
|
||||||
|
private static readonly IColor _blackForeground = new ConsoleColor(System.ConsoleColor.Black, ColorType.Foreground);
|
||||||
|
private static readonly IColor _blueForeground = new ConsoleColor(System.ConsoleColor.Blue, ColorType.Foreground);
|
||||||
|
private static readonly IColor _cyanForeground = new ConsoleColor(System.ConsoleColor.Cyan, ColorType.Foreground);
|
||||||
|
private static readonly IColor _darkBlueForeground = new ConsoleColor(System.ConsoleColor.DarkBlue, ColorType.Foreground);
|
||||||
|
private static readonly IColor _darkCyanForeground = new ConsoleColor(System.ConsoleColor.DarkCyan, ColorType.Foreground);
|
||||||
|
private static readonly IColor _darkGrayForeground = new ConsoleColor(System.ConsoleColor.DarkGray, ColorType.Foreground);
|
||||||
|
private static readonly IColor _darkGreenForeground = new ConsoleColor(System.ConsoleColor.DarkGreen, ColorType.Foreground);
|
||||||
|
private static readonly IColor _darkMagentaForeground = new ConsoleColor(System.ConsoleColor.DarkMagenta, ColorType.Foreground);
|
||||||
|
private static readonly IColor _darkRedForeground = new ConsoleColor(System.ConsoleColor.DarkRed, ColorType.Foreground);
|
||||||
|
private static readonly IColor _darkYellowForeground = new ConsoleColor(System.ConsoleColor.DarkYellow, ColorType.Foreground);
|
||||||
|
private static readonly IColor _grayForeground = new ConsoleColor(System.ConsoleColor.Gray, ColorType.Foreground);
|
||||||
|
private static readonly IColor _greenForeground = new ConsoleColor(System.ConsoleColor.Green, ColorType.Foreground);
|
||||||
|
private static readonly IColor _magentaForeground = new ConsoleColor(System.ConsoleColor.Magenta, ColorType.Foreground);
|
||||||
|
private static readonly IColor _redForeground = new ConsoleColor(System.ConsoleColor.Red, ColorType.Foreground);
|
||||||
|
private static readonly IColor _whiteForeground = new ConsoleColor(System.ConsoleColor.White, ColorType.Foreground);
|
||||||
|
private static readonly IColor _yellowForeground = new ConsoleColor(System.ConsoleColor.Yellow, ColorType.Foreground);
|
||||||
|
|
||||||
|
private static readonly IColor _blackBackground = new ConsoleColor(System.ConsoleColor.Black, ColorType.Background);
|
||||||
|
private static readonly IColor _blueBackground = new ConsoleColor(System.ConsoleColor.Blue, ColorType.Background);
|
||||||
|
private static readonly IColor _cyanBackground = new ConsoleColor(System.ConsoleColor.Cyan, ColorType.Background);
|
||||||
|
private static readonly IColor _darkBlueBackground = new ConsoleColor(System.ConsoleColor.DarkBlue, ColorType.Background);
|
||||||
|
private static readonly IColor _darkCyanBackground = new ConsoleColor(System.ConsoleColor.DarkCyan, ColorType.Background);
|
||||||
|
private static readonly IColor _darkGrayBackground = new ConsoleColor(System.ConsoleColor.DarkGray, ColorType.Background);
|
||||||
|
private static readonly IColor _darkGreenBackground = new ConsoleColor(System.ConsoleColor.DarkGreen, ColorType.Background);
|
||||||
|
private static readonly IColor _darkMagentaBackground = new ConsoleColor(System.ConsoleColor.DarkMagenta, ColorType.Background);
|
||||||
|
private static readonly IColor _darkRedBackground = new ConsoleColor(System.ConsoleColor.DarkRed, ColorType.Background);
|
||||||
|
private static readonly IColor _darkYellowBackground = new ConsoleColor(System.ConsoleColor.DarkYellow, ColorType.Background);
|
||||||
|
private static readonly IColor _grayBackground = new ConsoleColor(System.ConsoleColor.Gray, ColorType.Background);
|
||||||
|
private static readonly IColor _greenBackground = new ConsoleColor(System.ConsoleColor.Green, ColorType.Background);
|
||||||
|
private static readonly IColor _magentaBackground = new ConsoleColor(System.ConsoleColor.Magenta, ColorType.Background);
|
||||||
|
private static readonly IColor _redBackground = new ConsoleColor(System.ConsoleColor.Red, ColorType.Background);
|
||||||
|
private static readonly IColor _whiteBackground = new ConsoleColor(System.ConsoleColor.White, ColorType.Background);
|
||||||
|
private static readonly IColor _yellowBackground = new ConsoleColor(System.ConsoleColor.Yellow, ColorType.Background);
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
public interface IColorProvider
|
public interface IColorProvider
|
||||||
{
|
{
|
||||||
IColor Parse(string color, ColorType type);
|
IColor Parse(string color, ColorType type);
|
||||||
|
IColor FromRgb(Rgb rgb, ColorType type);
|
||||||
|
|
||||||
IColor BlackForeground { get; }
|
IColor BlackForeground { get; }
|
||||||
IColor BlueForeground { get; }
|
IColor BlueForeground { get; }
|
||||||
|
|||||||
33
src/Library/TerminalUI/Color/Rgb.cs
Normal file
33
src/Library/TerminalUI/Color/Rgb.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace TerminalUI.Color;
|
||||||
|
|
||||||
|
[DebuggerDisplay("R = {R}, G = {G}, B = {B}")]
|
||||||
|
public readonly struct Rgb
|
||||||
|
{
|
||||||
|
public readonly byte R;
|
||||||
|
public readonly byte G;
|
||||||
|
public readonly byte B;
|
||||||
|
|
||||||
|
public Rgb(byte r, byte g, byte b)
|
||||||
|
{
|
||||||
|
R = r;
|
||||||
|
G = g;
|
||||||
|
B = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double operator -(Rgb left, Rgb right)
|
||||||
|
{
|
||||||
|
var r = Math.Abs(left.R - right.R);
|
||||||
|
var g = Math.Abs(left.G - right.G);
|
||||||
|
var b = Math.Abs(left.B - right.B);
|
||||||
|
return (double)(r + g + b) / 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Deconstruct(out byte r, out byte g, out byte b)
|
||||||
|
{
|
||||||
|
r = R;
|
||||||
|
g = G;
|
||||||
|
b = B;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,6 +36,7 @@ public sealed class XTermDriver : DotnetDriver
|
|||||||
public override void ResetStyle()
|
public override void ResetStyle()
|
||||||
{
|
{
|
||||||
Write("\x1b[0m");
|
Write("\x1b[0m");
|
||||||
|
base.ResetStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetBackgroundColor(IColor background)
|
public override void SetBackgroundColor(IColor background)
|
||||||
|
|||||||
@@ -127,11 +127,18 @@ public sealed class Grid<T> : ChildCollectionView<Grid<T>, T>, IVisibilityChange
|
|||||||
|
|
||||||
protected override Size CalculateSize()
|
protected override Size CalculateSize()
|
||||||
{
|
{
|
||||||
return WithCalculatedSize(
|
if (Width.HasValue && Height.HasValue)
|
||||||
|
{
|
||||||
|
return new Size(Width.Value, Height.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
var size = WithCalculatedSize(
|
||||||
RenderContext.Empty,
|
RenderContext.Empty,
|
||||||
new Option<Size>(new Size(0, 0), false),
|
new Option<Size>(new Size(0, 0), false),
|
||||||
CalculateSizeInternal);
|
CalculateSizeInternal);
|
||||||
|
|
||||||
|
return new Size(Width ?? size.Width, Height ?? size.Height);
|
||||||
|
|
||||||
Size CalculateSizeInternal(in RenderContext _, ReadOnlySpan<int> columnWidths, ReadOnlySpan<int> rowHeights)
|
Size CalculateSizeInternal(in RenderContext _, ReadOnlySpan<int> columnWidths, ReadOnlySpan<int> rowHeights)
|
||||||
{
|
{
|
||||||
var width = 0;
|
var width = 0;
|
||||||
@@ -153,11 +160,14 @@ public sealed class Grid<T> : ChildCollectionView<Grid<T>, T>, IVisibilityChange
|
|||||||
|
|
||||||
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;
|
var width = Width ?? size.Width;
|
||||||
|
var height = Height ?? size.Height;
|
||||||
|
|
||||||
|
if (width == 0 || height == 0) return false;
|
||||||
|
|
||||||
return WithCalculatedSize(
|
return WithCalculatedSize(
|
||||||
renderContext,
|
renderContext,
|
||||||
new Option<Size>(size, true),
|
new Option<Size>(new Size(width, height), true),
|
||||||
DefaultRendererInternal
|
DefaultRendererInternal
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ public sealed partial class Rectangle<T> : View<Rectangle<T>, T>, IDisplayView
|
|||||||
protected override bool DefaultRenderer(in RenderContext renderContext, Position position, Size size)
|
protected override bool DefaultRenderer(in RenderContext renderContext, Position position, Size size)
|
||||||
{
|
{
|
||||||
var fillColor = Fill ?? Background ?? renderContext.Background;
|
var fillColor = Fill ?? Background ?? renderContext.Background;
|
||||||
var renderState = new RenderState(position, size, fillColor);
|
var renderSize = new Size(Width ?? size.Width, Height ?? size.Height);
|
||||||
|
var renderState = new RenderState(position, renderSize, fillColor);
|
||||||
var skipRender = !renderContext.ForceRerender && !NeedsRerender(renderState);
|
var skipRender = !renderContext.ForceRerender && !NeedsRerender(renderState);
|
||||||
_lastRenderState = renderState;
|
_lastRenderState = renderState;
|
||||||
|
|
||||||
@@ -41,7 +42,7 @@ public sealed partial class Rectangle<T> : View<Rectangle<T>, T>, IDisplayView
|
|||||||
RenderEmpty(
|
RenderEmpty(
|
||||||
renderContext,
|
renderContext,
|
||||||
position,
|
position,
|
||||||
size,
|
renderSize,
|
||||||
skipRender,
|
skipRender,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -146,8 +146,8 @@ public abstract partial class View<TConcrete, T> : IView<T> where TConcrete : Vi
|
|||||||
|
|
||||||
if (!IsVisible) return false;
|
if (!IsVisible) return false;
|
||||||
|
|
||||||
ActualWidth = size.Width;
|
ActualWidth = Width ?? size.Width;
|
||||||
ActualHeight = size.Height;
|
ActualHeight = Height ?? size.Height;
|
||||||
|
|
||||||
if (RenderMethod is null)
|
if (RenderMethod is null)
|
||||||
{
|
{
|
||||||
@@ -167,10 +167,14 @@ public abstract partial class View<TConcrete, T> : IView<T> where TConcrete : Vi
|
|||||||
);
|
);
|
||||||
|
|
||||||
size = new Size(
|
size = new Size(
|
||||||
size.Width - Margin.Left - Margin.Right,
|
ActualWidth - Margin.Left - Margin.Right,
|
||||||
size.Height - Margin.Top - Margin.Bottom
|
ActualHeight - Margin.Top - Margin.Bottom
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
else if (Width.HasValue || Height.HasValue)
|
||||||
|
{
|
||||||
|
size = new Size(ActualWidth, ActualHeight);
|
||||||
|
}
|
||||||
|
|
||||||
bool renderResult;
|
bool renderResult;
|
||||||
if (Background != null || Foreground != null)
|
if (Background != null || Foreground != null)
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ public class BinaryTracker : ExpressionTrackerBase
|
|||||||
ExpressionType.GreaterThanOrEqual => (v1, v2) => Comparer.Default.Compare(v1, v2) >= 0,
|
ExpressionType.GreaterThanOrEqual => (v1, v2) => Comparer.Default.Compare(v1, v2) >= 0,
|
||||||
ExpressionType.LessThan => (v1, v2) => Comparer.Default.Compare(v1, v2) < 0,
|
ExpressionType.LessThan => (v1, v2) => Comparer.Default.Compare(v1, v2) < 0,
|
||||||
ExpressionType.LessThanOrEqual => (v1, v2) => Comparer.Default.Compare(v1, v2) <= 0,
|
ExpressionType.LessThanOrEqual => (v1, v2) => Comparer.Default.Compare(v1, v2) <= 0,
|
||||||
|
ExpressionType.AndAlso => (v1, v2) => v1 is true && v2 is true,
|
||||||
|
ExpressionType.OrElse => (v1, v2) => v1 is true || v2 is true,
|
||||||
_ => throw new NotImplementedException()
|
_ => throw new NotImplementedException()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using System.Linq.Expressions;
|
||||||
|
|
||||||
|
namespace TerminalUI.ExpressionTrackers;
|
||||||
|
|
||||||
|
public class TypeBinaryTracker : ExpressionTrackerBase
|
||||||
|
{
|
||||||
|
private readonly IExpressionTracker _childExpressionTracker;
|
||||||
|
private readonly Func<object?, bool> _computer;
|
||||||
|
|
||||||
|
public TypeBinaryTracker(TypeBinaryExpression typeBinaryExpression, IExpressionTracker childExpressionTracker)
|
||||||
|
{
|
||||||
|
_childExpressionTracker = childExpressionTracker;
|
||||||
|
ArgumentNullException.ThrowIfNull(childExpressionTracker);
|
||||||
|
|
||||||
|
SubscribeToValueChanges = false;
|
||||||
|
SubscribeToTracker(childExpressionTracker);
|
||||||
|
|
||||||
|
_computer = typeBinaryExpression.NodeType switch
|
||||||
|
{
|
||||||
|
ExpressionType.TypeIs => o => o is not null && typeBinaryExpression.TypeOperand.IsInstanceOfType(o),
|
||||||
|
_ => throw new NotImplementedException()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
protected override object? ComputeValue()
|
||||||
|
=> _computer(_childExpressionTracker.GetValue());
|
||||||
|
}
|
||||||
@@ -80,10 +80,11 @@ public abstract class PropertyTrackerBase<TSource, TExpressionResult>
|
|||||||
{
|
{
|
||||||
return new ConstantTracker(constantExpression.Value);
|
return new ConstantTracker(constantExpression.Value);
|
||||||
}
|
}
|
||||||
/*else if (expression is not ConstantExpression)
|
else if (expression is TypeBinaryExpression typeBinaryExpression)
|
||||||
{
|
{
|
||||||
Debug.Assert(false, "Unknown expression type " + expression.GetType());
|
var childExpression = FindReactiveProperties(typeBinaryExpression.Expression, parameters);
|
||||||
}*/
|
return new TypeBinaryTracker(typeBinaryExpression, childExpression);
|
||||||
|
}
|
||||||
|
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using DynamicData;
|
|||||||
using FileTime.Core.ContentAccess;
|
using FileTime.Core.ContentAccess;
|
||||||
using FileTime.Core.Enums;
|
using FileTime.Core.Enums;
|
||||||
using FileTime.Core.Models;
|
using FileTime.Core.Models;
|
||||||
using FileTime.Core.Models.Extensions;
|
|
||||||
using FileTime.Core.Timeline;
|
using FileTime.Core.Timeline;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
@@ -356,11 +355,6 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
|
|||||||
var parent = new AbsolutePath(_timelessContentProvider, pointInTime, parentFullName,
|
var parent = new AbsolutePath(_timelessContentProvider, pointInTime, parentFullName,
|
||||||
AbsolutePathType.Container);
|
AbsolutePathType.Container);
|
||||||
|
|
||||||
var extensions = new ExtensionCollection()
|
|
||||||
{
|
|
||||||
new FileExtension(fileInfo.Length)
|
|
||||||
};
|
|
||||||
|
|
||||||
return new Element(
|
return new Element(
|
||||||
fileInfo.Name,
|
fileInfo.Name,
|
||||||
fileInfo.Name,
|
fileInfo.Name,
|
||||||
@@ -374,10 +368,11 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
|
|||||||
SupportsDelete.True,
|
SupportsDelete.True,
|
||||||
true,
|
true,
|
||||||
GetFileAttributes(fileInfo),
|
GetFileAttributes(fileInfo),
|
||||||
|
fileInfo.Length,
|
||||||
this,
|
this,
|
||||||
pointInTime,
|
pointInTime,
|
||||||
new ObservableCollection<Exception>(),
|
new ObservableCollection<Exception>(),
|
||||||
extensions.AsReadOnly()
|
new ExtensionCollection().AsReadOnly()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user