Sidebar - Refactored category VM to fix all issues with it I could find

Sidebar - Streamlined design
Sidebar - Increase width on wide window sizes
Profile editor - Implement File and Help menus
This commit is contained in:
Robert committed 2022-05-14 22:57:53 +02:00
1 parent 35f83e58e5
commit 78479c0fa2
79 files changed
+1093 -946

No files matched your search

@@ -151,18 +151,9 @@ namespace Artemis.UI.Screens.Sidebar
if (!await _windowService.ShowConfirmContentDialog("Delete profile", "Are you sure you want to permanently delete this profile?"))
return;
try
{
if (_profileConfiguration.IsBeingEdited)
_profileEditorService.ChangeCurrentProfileConfiguration(null);
_profileService.RemoveProfileConfiguration(_profileConfiguration);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
if (_profileConfiguration.IsBeingEdited)
_profileEditorService.ChangeCurrentProfileConfiguration(null);
_profileService.RemoveProfileConfiguration(_profileConfiguration);
Close(_profileConfiguration);
}
@@ -5,7 +5,8 @@
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:local="clr-namespace:Artemis.UI.Screens.Sidebar"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Sidebar.SidebarCategoryView">
x:Class="Artemis.UI.Screens.Sidebar.SidebarCategoryView"
x:DataType="local:SidebarCategoryViewModel">
<UserControl.Styles>
<Style Selector=":is(Button).category-button">
<Setter Property="IsVisible" Value="False" />
@@ -26,11 +27,14 @@
<Style Selector="Border.fadable.suspended">
<Setter Property="Opacity" Value="1" />
</Style>
<Style Selector=".sidebar-listbox > ListBoxItem">
<Setter Property="Padding" Value="6 0"/>
</Style>
</UserControl.Styles>
<Grid x:Name="ContainerGrid" Margin="0 8 0 0" RowDefinitions="Auto,*">
<Grid Grid.Row="0" Background="Transparent" ColumnDefinitions="Auto,Auto,*,Auto,Auto,Auto">
<Grid Grid.Row="0" Background="Transparent" Margin="0 0 6 0" ColumnDefinitions="Auto,*,Auto,Auto,Auto,Auto">
<avalonia:MaterialIcon Classes.chevron-collapsed="{Binding ShowItems}"
<avalonia:MaterialIcon Classes.chevron-collapsed="{CompiledBinding !IsCollapsed}"
Kind="ChevronUp"
Grid.Column="0"
Margin="5 0"
@@ -44,13 +48,14 @@
</avalonia:MaterialIcon>
<TextBlock Classes="fadable"
Classes.suspended="{Binding IsSuspended}"
Classes.suspended="{CompiledBinding IsSuspended}"
Grid.Column="1"
Padding="0 5"
FontWeight="SemiBold"
FontSize="13"
VerticalAlignment="Center"
Text="{Binding ProfileCategory.Name, FallbackValue='Profile name'}"
Text="{CompiledBinding ProfileCategory.Name, FallbackValue='Profile name'}"
TextTrimming="CharacterEllipsis"
PointerPressed="Title_OnPointerPressed"
Background="Transparent">
<TextBlock.Transitions>
@@ -61,7 +66,7 @@
</TextBlock>
<Border Classes="fadable"
Classes.suspended="{Binding IsSuspended}"
Classes.suspended="{CompiledBinding IsSuspended}"
Grid.Column="1"
BorderBrush="White"
BorderThickness="0.5"
@@ -77,29 +82,34 @@
Grid.Column="2"
ToolTip.Tip="Edit category"
HorizontalAlignment="Right"
Command="{Binding EditCategory}">
Command="{CompiledBinding EditCategory}"
Margin="0 0 2 0">
<avalonia:MaterialIcon Kind="Cog" />
</Button>
<ToggleButton Classes="category-button icon-button icon-button-small"
Grid.Column="3"
ToolTip.Tip="Suspend category"
Margin="5 0"
IsChecked="{Binding IsSuspended}">
<avalonia:MaterialIcon Kind="Pause" />
</ToggleButton>
<Button Classes="icon-button icon-button-small"
Command="{CompiledBinding ToggleSuspended}"
Grid.Column="3"
ToolTip.Tip="Suspend/resume profile"
Margin="0 0 2 0">
<Panel>
<avalonia:MaterialIcon Kind="EyeOff" IsVisible="{CompiledBinding IsSuspended}" />
<avalonia:MaterialIcon Kind="Eye" IsVisible="{CompiledBinding !IsSuspended}" />
</Panel>
</Button>
<Button Classes="category-button icon-button icon-button-small"
Grid.Column="4"
ToolTip.Tip="Add profile"
HorizontalAlignment="Right"
Command="{Binding AddProfile}">
Command="{CompiledBinding AddProfile}"
Margin="0 0 2 0">
<avalonia:MaterialIcon Kind="Plus" />
</Button>
</Grid>
<Border Grid.Row="1">
<ListBox Classes="sidebar-listbox"
Items="{Binding ProfileConfigurations}"
SelectedItem="{Binding SelectedProfileConfiguration}"
Items="{CompiledBinding ProfileConfigurations}"
SelectedItem="{CompiledBinding SelectedProfileConfiguration}"
MinHeight="10"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Disabled">
@@ -1,4 +1,5 @@
using Avalonia.Input;
using System;
using Avalonia.Input;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
@@ -18,8 +19,7 @@ namespace Artemis.UI.Screens.Sidebar
private void Title_OnPointerPressed(object? sender, PointerPressedEventArgs e)
{
if (ViewModel != null)
ViewModel.ShowItems = !ViewModel.ShowItems;
ViewModel?.ToggleCollapsed.Execute().Subscribe();
}
}
}
@@ -1,15 +1,19 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Events;
using Artemis.Core.Services;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
using Artemis.UI.Shared.Services.Builders;
using Artemis.UI.Shared.Services.ProfileEditor;
using DynamicData;
using ReactiveUI;
namespace Artemis.UI.Screens.Sidebar
@@ -21,6 +25,8 @@ namespace Artemis.UI.Screens.Sidebar
private readonly ISidebarVmFactory _vmFactory;
private readonly IWindowService _windowService;
private SidebarProfileConfigurationViewModel? _selectedProfileConfiguration;
private ObservableAsPropertyHelper<bool>? _isCollapsed;
private ObservableAsPropertyHelper<bool>? _isSuspended;
public SidebarCategoryViewModel(SidebarViewModel sidebarViewModel, ProfileCategory profileCategory, IProfileService profileService, IWindowService windowService,
IProfileEditorService profileEditorService, ISidebarVmFactory vmFactory)
@@ -31,24 +37,59 @@ namespace Artemis.UI.Screens.Sidebar
_vmFactory = vmFactory;
ProfileCategory = profileCategory;
SourceCache<ProfileConfiguration, Guid> profileConfigurations = new(t => t.ProfileId);
if (ShowItems)
CreateProfileViewModels();
// Only show items when not collapsed
IObservable<Func<ProfileConfiguration, bool>> profileConfigurationsFilter = this.WhenAnyValue(vm => vm.IsCollapsed).Select(b => new Func<object, bool>(_ => !b));
profileConfigurations.Connect()
.SortBy(c => c.Order)
.Filter(profileConfigurationsFilter)
.Transform(c => _vmFactory.SidebarProfileConfigurationViewModel(_sidebarViewModel, c))
.Bind(out ReadOnlyObservableCollection<SidebarProfileConfigurationViewModel> profileConfigurationViewModels)
.Subscribe();
ProfileConfigurations = profileConfigurationViewModels;
this.WhenActivated(disposables =>
ToggleCollapsed = ReactiveCommand.Create(ExecuteToggleCollapsed);
ToggleSuspended = ReactiveCommand.Create(ExecuteToggleSuspended);
AddProfile = ReactiveCommand.CreateFromTask(ExecuteAddProfile);
EditCategory = ReactiveCommand.CreateFromTask(ExecuteEditCategory);
this.WhenActivated(d =>
{
profileEditorService.ProfileConfiguration
.Subscribe(p => SelectedProfileConfiguration = ProfileConfigurations.FirstOrDefault(c => ReferenceEquals(c.ProfileConfiguration, p)))
.DisposeWith(disposables);
this.WhenAnyValue(vm => vm.SelectedProfileConfiguration)
.WhereNotNull()
.Subscribe(s => profileEditorService.ChangeCurrentProfileConfiguration(s.ProfileConfiguration));
// Update the list of profiles whenever the category fires events
Observable.FromEventPattern<ProfileConfigurationEventArgs>(x => profileCategory.ProfileConfigurationAdded += x, x => profileCategory.ProfileConfigurationAdded -= x)
.Subscribe(e => profileConfigurations.AddOrUpdate(e.EventArgs.ProfileConfiguration))
.DisposeWith(d);
Observable.FromEventPattern<ProfileConfigurationEventArgs>(x => profileCategory.ProfileConfigurationRemoved += x, x => profileCategory.ProfileConfigurationRemoved -= x)
.Subscribe(e => profileConfigurations.Remove(e.EventArgs.ProfileConfiguration))
.DisposeWith(d);
profileEditorService.ProfileConfiguration.Subscribe(p => SelectedProfileConfiguration = ProfileConfigurations.FirstOrDefault(c => ReferenceEquals(c.ProfileConfiguration, p)))
.DisposeWith(d);
_isCollapsed = ProfileCategory.WhenAnyValue(vm => vm.IsCollapsed).ToProperty(this, vm => vm.IsCollapsed).DisposeWith(d);
_isSuspended = ProfileCategory.WhenAnyValue(vm => vm.IsSuspended).ToProperty(this, vm => vm.IsSuspended).DisposeWith(d);
// Change the current profile configuration when a new one is selected
this.WhenAnyValue(vm => vm.SelectedProfileConfiguration).WhereNotNull().Subscribe(s => profileEditorService.ChangeCurrentProfileConfiguration(s.ProfileConfiguration));
});
profileConfigurations.Edit(updater =>
{
foreach (ProfileConfiguration profileConfiguration in profileCategory.ProfileConfigurations)
updater.AddOrUpdate(profileConfiguration);
});
}
public ReactiveCommand<Unit, Unit> ToggleCollapsed { get; }
public ReactiveCommand<Unit, Unit> ToggleSuspended { get; }
public ReactiveCommand<Unit, Unit> AddProfile { get; }
public ReactiveCommand<Unit, Unit> EditCategory { get; }
public ProfileCategory ProfileCategory { get; }
public ReadOnlyObservableCollection<SidebarProfileConfigurationViewModel> ProfileConfigurations { get; }
public ObservableCollection<SidebarProfileConfigurationViewModel> ProfileConfigurations { get; } = new();
public bool IsCollapsed => _isCollapsed?.Value ?? false;
public bool IsSuspended => _isSuspended?.Value ?? false;
public SidebarProfileConfigurationViewModel? SelectedProfileConfiguration
{
@@ -56,34 +97,7 @@ namespace Artemis.UI.Screens.Sidebar
set => RaiseAndSetIfChanged(ref _selectedProfileConfiguration, value);
}
public bool ShowItems
{
get => !ProfileCategory.IsCollapsed;
set
{
ProfileCategory.IsCollapsed = !value;
if (ProfileCategory.IsCollapsed)
ProfileConfigurations.Clear();
else
CreateProfileViewModels();
_profileService.SaveProfileCategory(ProfileCategory);
this.RaisePropertyChanged(nameof(ShowItems));
}
}
public bool IsSuspended
{
get => ProfileCategory.IsSuspended;
set
{
ProfileCategory.IsSuspended = value;
this.RaisePropertyChanged(nameof(IsSuspended));
_profileService.SaveProfileCategory(ProfileCategory);
}
}
public async Task EditCategory()
private async Task ExecuteEditCategory()
{
await _windowService.CreateContentDialog()
.WithTitle("Edit category")
@@ -97,7 +111,7 @@ namespace Artemis.UI.Screens.Sidebar
_sidebarViewModel.UpdateProfileCategories();
}
public async Task AddProfile()
private async Task ExecuteAddProfile()
{
ProfileConfiguration? result = await _windowService.ShowDialogAsync<ProfileConfigurationEditViewModel, ProfileConfiguration?>(
("profileCategory", ProfileCategory),
@@ -106,18 +120,20 @@ namespace Artemis.UI.Screens.Sidebar
if (result != null)
{
SidebarProfileConfigurationViewModel viewModel = _vmFactory.SidebarProfileConfigurationViewModel(_sidebarViewModel, result);
ProfileConfigurations.Insert(0, viewModel);
SelectedProfileConfiguration = viewModel;
}
}
private void CreateProfileViewModels()
private void ExecuteToggleCollapsed()
{
ProfileConfigurations.Clear();
foreach (ProfileConfiguration profileConfiguration in ProfileCategory.ProfileConfigurations.OrderBy(p => p.Order))
ProfileConfigurations.Add(_vmFactory.SidebarProfileConfigurationViewModel(_sidebarViewModel, profileConfiguration));
ProfileCategory.IsCollapsed = !ProfileCategory.IsCollapsed;
_profileService.SaveProfileCategory(ProfileCategory);
}
SelectedProfileConfiguration = ProfileConfigurations.FirstOrDefault(i => i.ProfileConfiguration.IsBeingEdited);
private void ExecuteToggleSuspended()
{
ProfileCategory.IsSuspended = !ProfileCategory.IsSuspended;
_profileService.SaveProfileCategory(ProfileCategory);
}
}
}
@@ -69,11 +69,11 @@
</UserControl.ContextMenu>
<Grid ColumnDefinitions="Auto,*,Auto,Auto">
<shared:ProfileConfigurationIcon Grid.Column="0"
x:Name="ProfileIcon"
VerticalAlignment="Center"
ConfigurationIcon="{CompiledBinding ProfileConfiguration.Icon}"
Width="20"
Height="20" />
x:Name="ProfileIcon"
VerticalAlignment="Center"
ConfigurationIcon="{CompiledBinding ProfileConfiguration.Icon}"
Width="20"
Height="20" />
<TextBlock Grid.Column="1"
x:Name="ProfileName"
@@ -106,15 +106,18 @@
Classes="icon-button icon-button-small"
Grid.Column="2"
ToolTip.Tip="View properties"
HorizontalAlignment="Right">
HorizontalAlignment="Right"
Margin="0 0 2 0">
<avalonia:MaterialIcon Kind="Cog" />
</Button>
<ToggleButton Classes="icon-button icon-button-small"
Grid.Column="3"
ToolTip.Tip="Suspend profile"
Margin="2 0 0 0"
IsChecked="{CompiledBinding IsSuspended}">
<avalonia:MaterialIcon Kind="Pause" />
</ToggleButton>
<Button Classes="icon-button icon-button-small"
Command="{CompiledBinding ToggleSuspended}"
Grid.Column="3"
ToolTip.Tip="Suspend/resume profile">
<Panel>
<avalonia:MaterialIcon Kind="EyeOff" IsVisible="{CompiledBinding IsSuspended}" />
<avalonia:MaterialIcon Kind="Eye" IsVisible="{CompiledBinding !IsSuspended}" />
</Panel>
</Button>
</Grid>
</UserControl>
@@ -26,31 +26,22 @@ namespace Artemis.UI.Screens.Sidebar
ProfileConfiguration = profileConfiguration;
EditProfile = ReactiveCommand.CreateFromTask(ExecuteEditProfile);
ToggleSuspended = ReactiveCommand.Create(ExecuteToggleSuspended);
this.WhenActivated(d =>
{
_isSuspended = ProfileConfiguration.WhenAnyValue(c => c.IsSuspended)
.ToProperty(this, vm => vm.IsSuspended)
.DisposeWith(d);
_isSuspended = ProfileConfiguration.WhenAnyValue(c => c.IsSuspended).ToProperty(this, vm => vm.IsSuspended).DisposeWith(d);
});
_profileService.LoadProfileConfigurationIcon(ProfileConfiguration);
}
public ReactiveCommand<Unit, Unit> EditProfile { get; }
public ReactiveCommand<Unit,Unit> ToggleSuspended { get; }
public bool IsProfileActive => ProfileConfiguration.Profile != null;
public bool IsSuspended => _isSuspended?.Value ?? false;
public bool IsSuspended
{
get => _isSuspended?.Value ?? false;
set
{
ProfileConfiguration.IsSuspended = value;
_profileService.SaveProfileCategory(ProfileConfiguration.Category);
}
}
public async Task ExecuteEditProfile()
private async Task ExecuteEditProfile()
{
ProfileConfiguration? edited = await _windowService.ShowDialogAsync<ProfileConfigurationEditViewModel, ProfileConfiguration?>(
("profileCategory", ProfileConfiguration.Category),
@@ -60,5 +51,11 @@ namespace Artemis.UI.Screens.Sidebar
if (edited != null)
_sidebarViewModel.UpdateProfileCategories();
}
private void ExecuteToggleSuspended()
{
ProfileConfiguration.IsSuspended = !ProfileConfiguration.IsSuspended;
_profileService.SaveProfileCategory(ProfileConfiguration.Category);
}
}
}