mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-12 03:48:56 +00:00
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:
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user