mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Sidebar - Added subitems support
This commit is contained in:
parent
229d93901b
commit
99a365be0b
@ -62,7 +62,15 @@ public abstract class RoutableScreen<TScreen> : ActivatableViewModelBase, IRouta
|
|||||||
|
|
||||||
void IRoutableScreen.InternalChangeScreen(object? screen)
|
void IRoutableScreen.InternalChangeScreen(object? screen)
|
||||||
{
|
{
|
||||||
Screen = screen as TScreen;
|
if (screen == null)
|
||||||
|
{
|
||||||
|
Screen = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (screen is not TScreen typedScreen)
|
||||||
|
throw new ArtemisRoutingException($"Screen cannot be hosted, {screen.GetType().Name} is not assignable to {typeof(TScreen).Name}.");
|
||||||
|
Screen = typedScreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
async Task IRoutableScreen.InternalOnNavigating(NavigationArguments args, CancellationToken cancellationToken)
|
async Task IRoutableScreen.InternalOnNavigating(NavigationArguments args, CancellationToken cancellationToken)
|
||||||
|
|||||||
@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
namespace Artemis.UI.Shared.Routing.ParameterParsers;
|
||||||
|
|
||||||
|
internal class IntParameterParser : IRouteParameterParser
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool IsMatch(RouteSegment segment, string source)
|
||||||
|
{
|
||||||
|
return int.TryParse(source, out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public object GetValue(RouteSegment segment, string source)
|
||||||
|
{
|
||||||
|
return int.Parse(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using DryIoc;
|
using DryIoc;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared.Routing;
|
namespace Artemis.UI.Shared.Routing;
|
||||||
|
|||||||
@ -48,11 +48,14 @@ public partial class RouteSegment
|
|||||||
|
|
||||||
private IRouteParameterParser GetParameterParser(string parameterType)
|
private IRouteParameterParser GetParameterParser(string parameterType)
|
||||||
{
|
{
|
||||||
if (parameterType == "guid")
|
return parameterType switch
|
||||||
return new GuidParameterParser();
|
{
|
||||||
|
"guid" => new GuidParameterParser(),
|
||||||
|
"int" => new IntParameterParser(),
|
||||||
|
_ => new StringParameterParser()
|
||||||
|
};
|
||||||
|
|
||||||
// Default to a string parser which just returns the segment as is
|
// Default to a string parser which just returns the segment as is
|
||||||
return new StringParameterParser();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[GeneratedRegex(@"\{(\w+):(\w+)\}")]
|
[GeneratedRegex(@"\{(\w+):(\w+)\}")]
|
||||||
|
|||||||
@ -13,9 +13,15 @@
|
|||||||
|
|
||||||
<!-- Add Styles Here -->
|
<!-- Add Styles Here -->
|
||||||
<Style Selector="ListBox.sidebar-listbox ListBoxItem">
|
<Style Selector="ListBox.sidebar-listbox ListBoxItem">
|
||||||
<Setter Property="MinHeight" Value="35" />
|
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||||
|
<Setter Property="MinHeight" Value="{DynamicResource NavigationViewItemOnLeftMinHeight}" />
|
||||||
</Style>
|
</Style>
|
||||||
<Style Selector="ListBox.sidebar-listbox ContentPresenter">
|
<!-- <Style Selector="ListBox.sidebar-listbox ContentPresenter"> -->
|
||||||
<Setter Property="Margin" Value="0" />
|
<!-- <Setter Property="Margin" Value="0" /> -->
|
||||||
|
<!-- </Style> -->
|
||||||
|
|
||||||
|
<Style Selector="ListBox.sidebar-listbox ListBoxItem /template/ ContentPresenter#PART_ContentPresenter">
|
||||||
|
<Setter Property="MinHeight" Value="{DynamicResource NavigationViewItemOnLeftMinHeight}" />
|
||||||
|
<Setter Property="CornerRadius" Value="{DynamicResource OverlayCornerRadius}" />
|
||||||
</Style>
|
</Style>
|
||||||
</Styles>
|
</Styles>
|
||||||
@ -43,4 +43,16 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AvaloniaResource Include="Assets\**" />
|
<AvaloniaResource Include="Assets\**" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<AdditionalFiles Include="Screens\Workshop\Layout\LayoutDetailsView.axaml" />
|
||||||
|
<AdditionalFiles Include="Screens\Workshop\Layout\LayoutListView.axaml" />
|
||||||
|
<AdditionalFiles Include="Screens\Workshop\Profile\ProfileDetailsView.axaml" />
|
||||||
|
<AdditionalFiles Include="Screens\Workshop\Profile\ProfileListView.axaml" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<UpToDateCheckInput Remove="Screens\Workshop\Categories\Profile\ProfileDetailsView.axaml" />
|
||||||
|
<UpToDateCheckInput Remove="Screens\Workshop\Categories\Profile\ProfileListView.axaml" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
@ -30,6 +31,8 @@ using Artemis.UI.Shared;
|
|||||||
using Artemis.UI.Shared.Routing;
|
using Artemis.UI.Shared.Routing;
|
||||||
using Artemis.WebClient.Updating;
|
using Artemis.WebClient.Updating;
|
||||||
using DryIoc;
|
using DryIoc;
|
||||||
|
using DynamicData;
|
||||||
|
using Material.Icons;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.DryIoc.Factories;
|
namespace Artemis.UI.DryIoc.Factories;
|
||||||
@ -137,7 +140,7 @@ public class SidebarVmFactory : ISidebarVmFactory
|
|||||||
{
|
{
|
||||||
_container = container;
|
_container = container;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SidebarCategoryViewModel SidebarCategoryViewModel(ProfileCategory profileCategory)
|
public SidebarCategoryViewModel SidebarCategoryViewModel(ProfileCategory profileCategory)
|
||||||
{
|
{
|
||||||
return _container.Resolve<SidebarCategoryViewModel>(new object[] { profileCategory });
|
return _container.Resolve<SidebarCategoryViewModel>(new object[] { profileCategory });
|
||||||
|
|||||||
@ -5,6 +5,8 @@ using Artemis.UI.Screens.Settings;
|
|||||||
using Artemis.UI.Screens.Settings.Updating;
|
using Artemis.UI.Screens.Settings.Updating;
|
||||||
using Artemis.UI.Screens.SurfaceEditor;
|
using Artemis.UI.Screens.SurfaceEditor;
|
||||||
using Artemis.UI.Screens.Workshop;
|
using Artemis.UI.Screens.Workshop;
|
||||||
|
using Artemis.UI.Screens.Workshop.Layout;
|
||||||
|
using Artemis.UI.Screens.Workshop.Profile;
|
||||||
using Artemis.UI.Shared.Routing;
|
using Artemis.UI.Shared.Routing;
|
||||||
|
|
||||||
namespace Artemis.UI.Routing;
|
namespace Artemis.UI.Routing;
|
||||||
@ -14,8 +16,15 @@ public static class Routes
|
|||||||
public static List<IRouterRegistration> ArtemisRoutes = new()
|
public static List<IRouterRegistration> ArtemisRoutes = new()
|
||||||
{
|
{
|
||||||
new RouteRegistration<HomeViewModel>("home"),
|
new RouteRegistration<HomeViewModel>("home"),
|
||||||
|
|
||||||
new RouteRegistration<WorkshopViewModel>("workshop"),
|
new RouteRegistration<WorkshopViewModel>("workshop"),
|
||||||
|
new RouteRegistration<ProfileListViewModel>("workshop/profiles/{page:int}"),
|
||||||
|
new RouteRegistration<ProfileDetailsViewModel>("workshop/profiles/{entryId:guid}"),
|
||||||
|
new RouteRegistration<LayoutListViewModel>("workshop/layouts/{page:int}"),
|
||||||
|
new RouteRegistration<LayoutDetailsViewModel>("workshop/layouts/{entryId:guid}"),
|
||||||
|
|
||||||
new RouteRegistration<SurfaceEditorViewModel>("surface-editor"),
|
new RouteRegistration<SurfaceEditorViewModel>("surface-editor"),
|
||||||
|
|
||||||
new RouteRegistration<SettingsViewModel>("settings")
|
new RouteRegistration<SettingsViewModel>("settings")
|
||||||
{
|
{
|
||||||
Children = new List<IRouterRegistration>
|
Children = new List<IRouterRegistration>
|
||||||
@ -25,7 +34,7 @@ public static class Routes
|
|||||||
new RouteRegistration<DevicesTabViewModel>("devices"),
|
new RouteRegistration<DevicesTabViewModel>("devices"),
|
||||||
new RouteRegistration<ReleasesTabViewModel>("releases")
|
new RouteRegistration<ReleasesTabViewModel>("releases")
|
||||||
{
|
{
|
||||||
Children = new List<IRouterRegistration>()
|
Children = new List<IRouterRegistration>
|
||||||
{
|
{
|
||||||
new RouteRegistration<ReleaseDetailsViewModel>("{releaseId:guid}")
|
new RouteRegistration<ReleaseDetailsViewModel>("{releaseId:guid}")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -99,7 +99,6 @@
|
|||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<Style Selector="ListBox.sidebar-listbox ListBoxItem">
|
<Style Selector="ListBox.sidebar-listbox ListBoxItem">
|
||||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
|
||||||
<Setter Property="(i:Interaction.Behaviors)">
|
<Setter Property="(i:Interaction.Behaviors)">
|
||||||
<i:BehaviorCollectionTemplate>
|
<i:BehaviorCollectionTemplate>
|
||||||
<i:BehaviorCollection>
|
<i:BehaviorCollection>
|
||||||
|
|||||||
@ -76,8 +76,8 @@
|
|||||||
x:Name="ProfileIcon"
|
x:Name="ProfileIcon"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
ConfigurationIcon="{CompiledBinding ProfileConfiguration.Icon}"
|
ConfigurationIcon="{CompiledBinding ProfileConfiguration.Icon}"
|
||||||
Width="20"
|
Width="22"
|
||||||
Height="20"
|
Height="22"
|
||||||
Margin="0 0 5 0">
|
Margin="0 0 5 0">
|
||||||
<shared:ProfileConfigurationIcon.Transitions>
|
<shared:ProfileConfigurationIcon.Transitions>
|
||||||
<Transitions>
|
<Transitions>
|
||||||
|
|||||||
@ -4,11 +4,11 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
xmlns:vm="clr-namespace:Artemis.UI.Screens.Sidebar;assembly=Artemis.UI"
|
xmlns:vm="clr-namespace:Artemis.UI.Screens.Sidebar;assembly=Artemis.UI"
|
||||||
x:DataType="vm:SidebarScreenViewModel"
|
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Sidebar.SidebarScreenView">
|
x:Class="Artemis.UI.Screens.Sidebar.SidebarScreenView"
|
||||||
<StackPanel Orientation="Horizontal">
|
x:DataType="vm:SidebarScreenViewModel">
|
||||||
<avalonia:MaterialIcon Kind="{CompiledBinding Icon}" Width="16" Height="16" />
|
<StackPanel Orientation="Horizontal" Background="Transparent" PointerReleased="InputElement_OnPointerReleased" DoubleTapped="InputElement_OnDoubleTapped">
|
||||||
<TextBlock FontSize="12" Margin="10 0" VerticalAlignment="Center" Text="{CompiledBinding DisplayName}" />
|
<avalonia:MaterialIcon Kind="{CompiledBinding Icon}" Width="18" Height="18" />
|
||||||
|
<TextBlock Margin="10 0" VerticalAlignment="Center" FontSize="13" Text="{CompiledBinding DisplayName}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -1,13 +1,25 @@
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Input;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Sidebar;
|
namespace Artemis.UI.Screens.Sidebar;
|
||||||
|
|
||||||
public partial class SidebarScreenView : UserControl
|
public partial class SidebarScreenView : ReactiveUserControl<SidebarScreenViewModel>
|
||||||
{
|
{
|
||||||
public SidebarScreenView()
|
public SidebarScreenView()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InputElement_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
|
||||||
|
{
|
||||||
|
// if (ViewModel != null)
|
||||||
|
// ViewModel.IsExpanded = !ViewModel.IsExpanded;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InputElement_OnDoubleTapped(object? sender, TappedEventArgs e)
|
||||||
|
{
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,25 +1,71 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Linq;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
|
using Artemis.UI.Shared.Routing;
|
||||||
|
using Artemis.UI.Shared.Services;
|
||||||
|
using Avalonia.Threading;
|
||||||
using Material.Icons;
|
using Material.Icons;
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Sidebar;
|
namespace Artemis.UI.Screens.Sidebar;
|
||||||
|
|
||||||
public class SidebarScreenViewModel : ViewModelBase
|
public class SidebarScreenViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
public SidebarScreenViewModel(MaterialIconKind icon, string displayName, string path)
|
private bool _isExpanded;
|
||||||
|
|
||||||
|
public SidebarScreenViewModel(MaterialIconKind icon, string displayName, string path, string? rootPath = null, ObservableCollection<SidebarScreenViewModel>? screens = null)
|
||||||
{
|
{
|
||||||
Icon = icon;
|
Icon = icon;
|
||||||
Path = path;
|
Path = path;
|
||||||
|
RootPath = rootPath ?? path;
|
||||||
DisplayName = displayName;
|
DisplayName = displayName;
|
||||||
|
Screens = screens ?? new ObservableCollection<SidebarScreenViewModel>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MaterialIconKind Icon { get; }
|
public MaterialIconKind Icon { get; }
|
||||||
public string Path { get; }
|
public string Path { get; }
|
||||||
|
public string RootPath { get; }
|
||||||
|
|
||||||
|
public ObservableCollection<SidebarScreenViewModel> Screens { get; }
|
||||||
|
|
||||||
|
public bool IsExpanded
|
||||||
|
{
|
||||||
|
get => _isExpanded;
|
||||||
|
set => RaiseAndSetIfChanged(ref _isExpanded, value);
|
||||||
|
}
|
||||||
|
|
||||||
public bool Matches(string? path)
|
public bool Matches(string? path)
|
||||||
{
|
{
|
||||||
if (path == null)
|
if (path == null)
|
||||||
return false;
|
return false;
|
||||||
return path.StartsWith(Path, StringComparison.InvariantCultureIgnoreCase);
|
return path.StartsWith(RootPath, StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SidebarScreenViewModel? GetMatch(string path)
|
||||||
|
{
|
||||||
|
foreach (SidebarScreenViewModel sidebarScreenViewModel in Screens)
|
||||||
|
{
|
||||||
|
SidebarScreenViewModel? match = sidebarScreenViewModel.GetMatch(path);
|
||||||
|
if (match != null)
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Screens.FirstOrDefault(s => s.Matches(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ExpandIfRequired(SidebarScreenViewModel selected)
|
||||||
|
{
|
||||||
|
if (selected == this && Screens.Any())
|
||||||
|
{
|
||||||
|
IsExpanded = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Screens.Contains(selected))
|
||||||
|
IsExpanded = true;
|
||||||
|
|
||||||
|
foreach (SidebarScreenViewModel sidebarScreenViewModel in Screens)
|
||||||
|
sidebarScreenViewModel.ExpandIfRequired(selected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,7 +3,7 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:sidebar="clr-namespace:Artemis.UI.Screens.Sidebar"
|
xmlns:sidebar="clr-namespace:Artemis.UI.Screens.Sidebar"
|
||||||
mc:Ignorable="d" d:DesignWidth="240" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="240" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Sidebar.SidebarView"
|
x:Class="Artemis.UI.Screens.Sidebar.SidebarView"
|
||||||
@ -20,11 +20,23 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<!-- Built-in screens -->
|
<!-- Built-in screens -->
|
||||||
<ListBox Classes="sidebar-listbox"
|
<TreeView Grid.Row="1"
|
||||||
Grid.Row="1"
|
Margin="10 2"
|
||||||
Margin="10 2"
|
ItemsSource="{CompiledBinding SidebarScreen.Screens}"
|
||||||
ItemsSource="{CompiledBinding SidebarScreens}"
|
SelectedItem="{CompiledBinding SelectedScreen}"
|
||||||
SelectedItem="{CompiledBinding SelectedSidebarScreen}" />
|
ItemContainerTheme="{StaticResource MenuTreeViewItem}">
|
||||||
|
<TreeView.Styles>
|
||||||
|
<Style Selector="TreeViewItem">
|
||||||
|
<Setter Property="IsExpanded" Value="{CompiledBinding IsExpanded, Mode=TwoWay, DataType=sidebar:SidebarScreenViewModel}" />
|
||||||
|
</Style>
|
||||||
|
</TreeView.Styles>
|
||||||
|
<TreeView.ItemTemplate>
|
||||||
|
<TreeDataTemplate ItemsSource="{CompiledBinding Screens}">
|
||||||
|
<ContentControl Content="{CompiledBinding}" />
|
||||||
|
</TreeDataTemplate>
|
||||||
|
</TreeView.ItemTemplate>
|
||||||
|
</TreeView>
|
||||||
|
|
||||||
<Border Grid.Row="2" Margin="8" Height="1" Background="{DynamicResource ButtonBorderBrush}"></Border>
|
<Border Grid.Row="2" Margin="8" Height="1" Background="{DynamicResource ButtonBorderBrush}"></Border>
|
||||||
|
|
||||||
<!-- Categories -->
|
<!-- Categories -->
|
||||||
@ -41,51 +53,51 @@
|
|||||||
<!-- Bottom buttons -->
|
<!-- Bottom buttons -->
|
||||||
<Border Grid.Row="4" Margin="8" Height="1" Background="{DynamicResource ButtonBorderBrush}"></Border>
|
<Border Grid.Row="4" Margin="8" Height="1" Background="{DynamicResource ButtonBorderBrush}"></Border>
|
||||||
<WrapPanel Grid.Row="5" Orientation="Horizontal" HorizontalAlignment="Left" Margin="5 0 5 5">
|
<WrapPanel Grid.Row="5" Orientation="Horizontal" HorizontalAlignment="Left" Margin="5 0 5 5">
|
||||||
<controls:HyperlinkButton Classes="icon-button"
|
<ui:HyperlinkButton Classes="icon-button"
|
||||||
Width="44"
|
Width="44"
|
||||||
Height="44"
|
Height="44"
|
||||||
ToolTip.Tip="View website"
|
ToolTip.Tip="View website"
|
||||||
ToolTip.Placement="Top"
|
ToolTip.Placement="Top"
|
||||||
ToolTip.VerticalOffset="-5"
|
ToolTip.VerticalOffset="-5"
|
||||||
NavigateUri="https://artemis-rgb.com?mtm_campaign=artemis&mtm_kwd=sidebar">
|
NavigateUri="https://artemis-rgb.com?mtm_campaign=artemis&mtm_kwd=sidebar">
|
||||||
<avalonia:MaterialIcon Kind="Web" Width="20" Height="20" />
|
<avalonia:MaterialIcon Kind="Web" Width="20" Height="20" />
|
||||||
</controls:HyperlinkButton>
|
</ui:HyperlinkButton>
|
||||||
<controls:HyperlinkButton Classes="icon-button"
|
<ui:HyperlinkButton Classes="icon-button"
|
||||||
Width="44"
|
Width="44"
|
||||||
Height="44"
|
Height="44"
|
||||||
ToolTip.Tip="View GitHub repository"
|
ToolTip.Tip="View GitHub repository"
|
||||||
ToolTip.Placement="Top"
|
ToolTip.Placement="Top"
|
||||||
ToolTip.VerticalOffset="-5"
|
ToolTip.VerticalOffset="-5"
|
||||||
NavigateUri="https://github.com/Artemis-RGB/Artemis">
|
NavigateUri="https://github.com/Artemis-RGB/Artemis">
|
||||||
<avalonia:MaterialIcon Kind="Github" Width="20" Height="20" />
|
<avalonia:MaterialIcon Kind="Github" Width="20" Height="20" />
|
||||||
</controls:HyperlinkButton>
|
</ui:HyperlinkButton>
|
||||||
<controls:HyperlinkButton Classes="icon-button"
|
<ui:HyperlinkButton Classes="icon-button"
|
||||||
Width="44"
|
Width="44"
|
||||||
Height="44"
|
Height="44"
|
||||||
ToolTip.Tip="View Wiki"
|
ToolTip.Tip="View Wiki"
|
||||||
ToolTip.Placement="Top"
|
ToolTip.Placement="Top"
|
||||||
ToolTip.VerticalOffset="-5"
|
ToolTip.VerticalOffset="-5"
|
||||||
NavigateUri="https://wiki.artemis-rgb.com?mtm_campaign=artemis&mtm_kwd=sidebar">
|
NavigateUri="https://wiki.artemis-rgb.com?mtm_campaign=artemis&mtm_kwd=sidebar">
|
||||||
<avalonia:MaterialIcon Kind="BookOpenOutline" Width="20" Height="20" />
|
<avalonia:MaterialIcon Kind="BookOpenOutline" Width="20" Height="20" />
|
||||||
</controls:HyperlinkButton>
|
</ui:HyperlinkButton>
|
||||||
<controls:HyperlinkButton Classes="icon-button"
|
<ui:HyperlinkButton Classes="icon-button"
|
||||||
Width="44"
|
Width="44"
|
||||||
Height="44"
|
Height="44"
|
||||||
ToolTip.Tip="Join our Discord"
|
ToolTip.Tip="Join our Discord"
|
||||||
ToolTip.Placement="Top"
|
ToolTip.Placement="Top"
|
||||||
ToolTip.VerticalOffset="-5"
|
ToolTip.VerticalOffset="-5"
|
||||||
NavigateUri="https://discord.gg/S3MVaC9">
|
NavigateUri="https://discord.gg/S3MVaC9">
|
||||||
<avalonia:MaterialIcon Kind="Chat" Width="20" Height="20" />
|
<avalonia:MaterialIcon Kind="Chat" Width="20" Height="20" />
|
||||||
</controls:HyperlinkButton>
|
</ui:HyperlinkButton>
|
||||||
<controls:HyperlinkButton Classes="icon-button"
|
<ui:HyperlinkButton Classes="icon-button"
|
||||||
Width="44"
|
Width="44"
|
||||||
Height="44"
|
Height="44"
|
||||||
ToolTip.Tip="View donation options"
|
ToolTip.Tip="View donation options"
|
||||||
ToolTip.Placement="Top"
|
ToolTip.Placement="Top"
|
||||||
ToolTip.VerticalOffset="-5"
|
ToolTip.VerticalOffset="-5"
|
||||||
NavigateUri="https://wiki.artemis-rgb.com/en/donating?mtm_campaign=artemis&mtm_kwd=sidebar">
|
NavigateUri="https://wiki.artemis-rgb.com/en/donating?mtm_campaign=artemis&mtm_kwd=sidebar">
|
||||||
<avalonia:MaterialIcon Kind="Gift" Width="20" Height="20" />
|
<avalonia:MaterialIcon Kind="Gift" Width="20" Height="20" />
|
||||||
</controls:HyperlinkButton>
|
</ui:HyperlinkButton>
|
||||||
</WrapPanel>
|
</WrapPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
@ -23,34 +24,38 @@ namespace Artemis.UI.Screens.Sidebar;
|
|||||||
|
|
||||||
public class SidebarViewModel : ActivatableViewModelBase
|
public class SidebarViewModel : ActivatableViewModelBase
|
||||||
{
|
{
|
||||||
|
public const string ROOT_SCREEN = "root";
|
||||||
|
|
||||||
private readonly IRouter _router;
|
private readonly IRouter _router;
|
||||||
private readonly IWindowService _windowService;
|
private readonly IWindowService _windowService;
|
||||||
private SidebarScreenViewModel? _selectedSidebarScreen;
|
|
||||||
private ReadOnlyObservableCollection<SidebarCategoryViewModel> _sidebarCategories = new(new ObservableCollection<SidebarCategoryViewModel>());
|
private ReadOnlyObservableCollection<SidebarCategoryViewModel> _sidebarCategories = new(new ObservableCollection<SidebarCategoryViewModel>());
|
||||||
|
private SidebarScreenViewModel? _selectedScreen;
|
||||||
|
|
||||||
public SidebarViewModel(IRouter router, IProfileService profileService, IWindowService windowService, ISidebarVmFactory sidebarVmFactory)
|
public SidebarViewModel(IRouter router, IProfileService profileService, IWindowService windowService, ISidebarVmFactory sidebarVmFactory)
|
||||||
{
|
{
|
||||||
_router = router;
|
_router = router;
|
||||||
_windowService = windowService;
|
_windowService = windowService;
|
||||||
|
|
||||||
SidebarScreens = new ObservableCollection<SidebarScreenViewModel>
|
SidebarScreen = new SidebarScreenViewModel(MaterialIconKind.Abacus, ROOT_SCREEN, "", null, new ObservableCollection<SidebarScreenViewModel>()
|
||||||
{
|
{
|
||||||
new(MaterialIconKind.Home, "Home", "home"),
|
new(MaterialIconKind.HomeOutline, "Home", "home"),
|
||||||
#if DEBUG
|
new(MaterialIconKind.TestTube, "Workshop", "workshop", null, new ObservableCollection<SidebarScreenViewModel>
|
||||||
new(MaterialIconKind.TestTube, "Workshop", "workshop"),
|
{
|
||||||
#endif
|
new(MaterialIconKind.FolderVideo, "Profiles", "workshop/profiles/1", "workshop/profiles"),
|
||||||
|
new(MaterialIconKind.KeyboardVariant, "Layouts", "workshop/layouts/1", "workshop/layouts"),
|
||||||
|
}),
|
||||||
new(MaterialIconKind.Devices, "Surface Editor", "surface-editor"),
|
new(MaterialIconKind.Devices, "Surface Editor", "surface-editor"),
|
||||||
new(MaterialIconKind.Cog, "Settings", "settings")
|
new(MaterialIconKind.SettingsOutline, "Settings", "settings")
|
||||||
};
|
});
|
||||||
|
|
||||||
AddCategory = ReactiveCommand.CreateFromTask(ExecuteAddCategory);
|
AddCategory = ReactiveCommand.CreateFromTask(ExecuteAddCategory);
|
||||||
|
this.WhenAnyValue(vm => vm.SelectedScreen).WhereNotNull().Subscribe(NavigateToScreen);
|
||||||
|
this.WhenAnyValue(vm => vm.SelectedScreen).WhereNotNull().Subscribe(s => SidebarScreen.ExpandIfRequired(s));
|
||||||
|
|
||||||
SourceList<ProfileCategory> profileCategories = new();
|
SourceList<ProfileCategory> profileCategories = new();
|
||||||
|
|
||||||
this.WhenAnyValue(vm => vm.SelectedSidebarScreen).WhereNotNull().Subscribe(NavigateToScreen);
|
|
||||||
this.WhenActivated(d =>
|
this.WhenActivated(d =>
|
||||||
{
|
{
|
||||||
_router.CurrentPath.WhereNotNull().Subscribe(r => SelectedSidebarScreen = SidebarScreens.FirstOrDefault(s => s.Matches(r))).DisposeWith(d);
|
_router.CurrentPath.WhereNotNull().Subscribe(r => SelectedScreen = SidebarScreen.GetMatch(r)).DisposeWith(d);
|
||||||
|
|
||||||
Observable.FromEventPattern<ProfileCategoryEventArgs>(x => profileService.ProfileCategoryAdded += x, x => profileService.ProfileCategoryAdded -= x)
|
Observable.FromEventPattern<ProfileCategoryEventArgs>(x => profileService.ProfileCategoryAdded += x, x => profileService.ProfileCategoryAdded -= x)
|
||||||
.Subscribe(e => profileCategories.Add(e.EventArgs.ProfileCategory))
|
.Subscribe(e => profileCategories.Add(e.EventArgs.ProfileCategory))
|
||||||
@ -75,11 +80,17 @@ public class SidebarViewModel : ActivatableViewModelBase
|
|||||||
.DisposeWith(d);
|
.DisposeWith(d);
|
||||||
|
|
||||||
SidebarCategories = categoryViewModels;
|
SidebarCategories = categoryViewModels;
|
||||||
SelectedSidebarScreen = SidebarScreens.First();
|
|
||||||
});
|
});
|
||||||
|
SelectedScreen = SidebarScreen.Screens.First();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObservableCollection<SidebarScreenViewModel> SidebarScreens { get; }
|
public SidebarScreenViewModel SidebarScreen { get; }
|
||||||
|
|
||||||
|
public SidebarScreenViewModel? SelectedScreen
|
||||||
|
{
|
||||||
|
get => _selectedScreen;
|
||||||
|
set => RaiseAndSetIfChanged(ref _selectedScreen, value);
|
||||||
|
}
|
||||||
|
|
||||||
public ReadOnlyObservableCollection<SidebarCategoryViewModel> SidebarCategories
|
public ReadOnlyObservableCollection<SidebarCategoryViewModel> SidebarCategories
|
||||||
{
|
{
|
||||||
@ -87,12 +98,6 @@ public class SidebarViewModel : ActivatableViewModelBase
|
|||||||
set => RaiseAndSetIfChanged(ref _sidebarCategories, value);
|
set => RaiseAndSetIfChanged(ref _sidebarCategories, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SidebarScreenViewModel? SelectedSidebarScreen
|
|
||||||
{
|
|
||||||
get => _selectedSidebarScreen;
|
|
||||||
set => RaiseAndSetIfChanged(ref _selectedSidebarScreen, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReactiveCommand<Unit, Unit> AddCategory { get; }
|
public ReactiveCommand<Unit, Unit> AddCategory { get; }
|
||||||
|
|
||||||
private async Task ExecuteAddCategory()
|
private async Task ExecuteAddCategory()
|
||||||
@ -112,7 +117,7 @@ public class SidebarViewModel : ActivatableViewModelBase
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _router.Navigate(sidebarScreenViewModel.Path, new RouterNavigationOptions {IgnoreOnPartialMatch = true});
|
await _router.Navigate(sidebarScreenViewModel.Path);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -0,0 +1,21 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
|
xmlns:ui="clr-namespace:Artemis.UI"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="Artemis.UI.Screens.Workshop.Layout.LayoutDetailsView">
|
||||||
|
<Border Classes="router-container">
|
||||||
|
<Grid ColumnDefinitions="300,*" Margin="10">
|
||||||
|
<Border Classes="card-condensed" Grid.Column="0" Margin="0 0 10 0">
|
||||||
|
<TextBlock>Side panel</TextBlock>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<Border Classes="card-condensed" Grid.Column="1">
|
||||||
|
<TextBlock>Main panel</TextBlock>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
</UserControl>
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
using Avalonia.Markup.Xaml;
|
||||||
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Workshop.Layout;
|
||||||
|
|
||||||
|
public partial class LayoutDetailsView : ReactiveUserControl<LayoutDetailsViewModel>
|
||||||
|
{
|
||||||
|
public LayoutDetailsView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
AvaloniaXamlLoader.Load(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
using Artemis.UI.Shared;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Workshop.Layout;
|
||||||
|
|
||||||
|
public class LayoutDetailsViewModel : ActivatableViewModelBase
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
22
src/Artemis.UI/Screens/Workshop/Layout/LayoutListView.axaml
Normal file
22
src/Artemis.UI/Screens/Workshop/Layout/LayoutListView.axaml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:layout="clr-namespace:Artemis.UI.Screens.Workshop.Layout"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="Artemis.UI.Screens.Workshop.Layout.LayoutListView"
|
||||||
|
x:DataType="layout:LayoutListViewModel">
|
||||||
|
<Border Classes="router-container">
|
||||||
|
<Grid ColumnDefinitions="300,*" Margin="10">
|
||||||
|
<Border Classes="card-condensed" Grid.Column="0" Margin="0 0 10 0">
|
||||||
|
<TextBlock>Side panel</TextBlock>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<Border Classes="card-condensed" Grid.Column="1">
|
||||||
|
<TextBlock>
|
||||||
|
<Run Text="Layout list main panel, page: " /><Run Text="{CompiledBinding Page}"></Run>
|
||||||
|
</TextBlock>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</UserControl>
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
using Avalonia.Markup.Xaml;
|
||||||
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Workshop.Layout;
|
||||||
|
|
||||||
|
public partial class LayoutListView : ReactiveUserControl<LayoutListViewModel>
|
||||||
|
{
|
||||||
|
public LayoutListView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
AvaloniaXamlLoader.Load(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Artemis.UI.Shared;
|
||||||
|
using Artemis.UI.Shared.Routing;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Workshop.Layout;
|
||||||
|
|
||||||
|
public class LayoutListViewModel : RoutableScreen<ActivatableViewModelBase, WorkshopListParameters>, IMainScreenViewModel
|
||||||
|
{
|
||||||
|
private int _page;
|
||||||
|
|
||||||
|
public int Page
|
||||||
|
{
|
||||||
|
get => _page;
|
||||||
|
set => RaiseAndSetIfChanged(ref _page, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task OnNavigating(WorkshopListParameters parameters, NavigationArguments args, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Page = Math.Max(1, parameters.Page);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewModelBase? TitleBarViewModel => null;
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="Artemis.UI.Screens.Workshop.Profile.ProfileDetailsView">
|
||||||
|
Welcome to Avalonia!
|
||||||
|
</UserControl>
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
using Avalonia.Markup.Xaml;
|
||||||
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Workshop.Profile;
|
||||||
|
|
||||||
|
public partial class ProfileDetailsView : ReactiveUserControl<ProfileDetailsViewModel>
|
||||||
|
{
|
||||||
|
public ProfileDetailsView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
AvaloniaXamlLoader.Load(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
using Artemis.UI.Shared;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Workshop.Profile;
|
||||||
|
|
||||||
|
public class ProfileDetailsViewModel : ActivatableViewModelBase
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:profile="clr-namespace:Artemis.UI.Screens.Workshop.Profile"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="Artemis.UI.Screens.Workshop.Profile.ProfileListView"
|
||||||
|
x:DataType="profile:ProfileListViewModel">
|
||||||
|
<Border Classes="router-container">
|
||||||
|
<Grid ColumnDefinitions="300,*" Margin="10">
|
||||||
|
<Border Classes="card-condensed" Grid.Column="0" Margin="0 0 10 0">
|
||||||
|
<TextBlock>Side panel</TextBlock>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<Border Classes="card-condensed" Grid.Column="1">
|
||||||
|
<TextBlock>
|
||||||
|
<Run Text="Profile list main panel, page: " /><Run Text="{CompiledBinding Page}"></Run>
|
||||||
|
</TextBlock>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</UserControl>
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
using Avalonia.Markup.Xaml;
|
||||||
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Workshop.Profile;
|
||||||
|
|
||||||
|
public partial class ProfileListView : ReactiveUserControl<ProfileListViewModel>
|
||||||
|
{
|
||||||
|
public ProfileListView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
AvaloniaXamlLoader.Load(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Artemis.UI.Shared;
|
||||||
|
using Artemis.UI.Shared.Routing;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Workshop.Profile;
|
||||||
|
|
||||||
|
public class ProfileListViewModel : RoutableScreen<ActivatableViewModelBase, WorkshopListParameters>, IMainScreenViewModel
|
||||||
|
{
|
||||||
|
private int _page;
|
||||||
|
|
||||||
|
public int Page
|
||||||
|
{
|
||||||
|
get => _page;
|
||||||
|
set => RaiseAndSetIfChanged(ref _page, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task OnNavigating(WorkshopListParameters parameters, NavigationArguments args, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Page = Math.Max(1, parameters.Page);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewModelBase? TitleBarViewModel => null;
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
namespace Artemis.UI.Screens.Workshop;
|
||||||
|
|
||||||
|
public class WorkshopListParameters
|
||||||
|
{
|
||||||
|
public int Page { get; set; }
|
||||||
|
}
|
||||||
@ -2,35 +2,13 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:builders="clr-namespace:Artemis.UI.Shared.Services.Builders;assembly=Artemis.UI.Shared"
|
|
||||||
xmlns:controls1="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
|
||||||
xmlns:attachedProperties="clr-namespace:Artemis.UI.Shared.AttachedProperties;assembly=Artemis.UI.Shared"
|
|
||||||
xmlns:workshop="clr-namespace:Artemis.UI.Screens.Workshop"
|
xmlns:workshop="clr-namespace:Artemis.UI.Screens.Workshop"
|
||||||
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
xmlns:ui="clr-namespace:Artemis.UI"
|
||||||
xmlns:gradientPicker="clr-namespace:Artemis.UI.Shared.Controls.GradientPicker;assembly=Artemis.UI.Shared"
|
|
||||||
xmlns:materialIconPicker="clr-namespace:Artemis.UI.Shared.MaterialIconPicker;assembly=Artemis.UI.Shared"
|
|
||||||
xmlns:workshop1="clr-namespace:Artemis.WebClient.Workshop;assembly=Artemis.WebClient.Workshop"
|
|
||||||
mc:Ignorable="d" d:DesignWidth="800"
|
mc:Ignorable="d" d:DesignWidth="800"
|
||||||
x:Class="Artemis.UI.Screens.Workshop.WorkshopView"
|
x:Class="Artemis.UI.Screens.Workshop.WorkshopView"
|
||||||
x:DataType="workshop:WorkshopViewModel">
|
x:DataType="workshop:WorkshopViewModel">
|
||||||
<Border Classes="router-container">
|
<Border Classes="router-container">
|
||||||
<Grid ColumnDefinitions="300,*" Margin="0 10">
|
<TextBlock>Workshop overview</TextBlock>
|
||||||
<Border Classes="card-condensed" Grid.Column="0" Margin="0 0 10 0">
|
|
||||||
<ListBox ItemsSource="{CompiledBinding Test}">
|
|
||||||
<ListBox.ItemTemplate>
|
|
||||||
<DataTemplate x:DataType="workshop1:IGetEntries_Entries_Nodes">
|
|
||||||
<Panel>
|
|
||||||
<StackPanel Margin="4">
|
|
||||||
<TextBlock Text="{CompiledBinding Name}" VerticalAlignment="Center" />
|
|
||||||
<TextBlock Text="{CompiledBinding Author}" VerticalAlignment="Center" Classes="subtitle" FontSize="13" />
|
|
||||||
</StackPanel>
|
|
||||||
</Panel>
|
|
||||||
</DataTemplate>
|
|
||||||
</ListBox.ItemTemplate>
|
|
||||||
</ListBox>
|
|
||||||
</Border>
|
|
||||||
<ContentControl Grid.Column="1" VerticalAlignment="Top" HorizontalAlignment="Right" Content="{CompiledBinding CurrentUserViewModel}" Margin="8"></ContentControl>
|
|
||||||
</Grid>
|
|
||||||
</Border>
|
</Border>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -1,4 +1,3 @@
|
|||||||
using Avalonia.Markup.Xaml;
|
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Workshop;
|
namespace Artemis.UI.Screens.Workshop;
|
||||||
@ -9,5 +8,4 @@ public partial class WorkshopView : ReactiveUserControl<WorkshopViewModel>
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,55 +1,13 @@
|
|||||||
using System;
|
using Artemis.UI.Shared;
|
||||||
using System.Collections.ObjectModel;
|
using Artemis.UI.Shared.Routing;
|
||||||
using System.Reactive;
|
|
||||||
using System.Reactive.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Artemis.Core;
|
|
||||||
using Artemis.UI.Screens.Workshop.CurrentUser;
|
|
||||||
using Artemis.UI.Shared.Services;
|
|
||||||
using Artemis.UI.Shared.Services.Builders;
|
|
||||||
using Artemis.WebClient.Workshop;
|
|
||||||
using Avalonia.Input;
|
|
||||||
using ReactiveUI;
|
|
||||||
using SkiaSharp;
|
|
||||||
using StrawberryShake;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Workshop;
|
namespace Artemis.UI.Screens.Workshop;
|
||||||
|
|
||||||
public class WorkshopViewModel : ActivatableViewModelBase, IMainScreenViewModel
|
public class WorkshopViewModel : RoutableScreen<object>, IMainScreenViewModel
|
||||||
{
|
{
|
||||||
private readonly IWorkshopClient _workshopClient;
|
public WorkshopViewModel()
|
||||||
|
|
||||||
public WorkshopViewModel(IScreen hostScreen, IWorkshopClient workshopClient, CurrentUserViewModel currentUserViewModel) : base(hostScreen, "workshop")
|
|
||||||
{
|
{
|
||||||
CurrentUserViewModel = currentUserViewModel;
|
|
||||||
_workshopClient = workshopClient;
|
|
||||||
DisplayName = "Workshop";
|
|
||||||
|
|
||||||
Task.Run(() => GetEntries());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObservableCollection<IGetEntries_Entries_Nodes> Test { get; set; } = new();
|
public ViewModelBase? TitleBarViewModel => null;
|
||||||
public CurrentUserViewModel CurrentUserViewModel { get; set; }
|
|
||||||
|
|
||||||
private async Task GetEntries()
|
|
||||||
{
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
IOperationResult<IGetEntriesResult> entries = await _workshopClient.GetEntries.ExecuteAsync();
|
|
||||||
if (entries.Data?.Entries?.Nodes == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (IGetEntries_Entries_Nodes getEntriesEntriesNodes in entries.Data.Entries.Nodes)
|
|
||||||
{
|
|
||||||
Console.WriteLine(getEntriesEntriesNodes);
|
|
||||||
Test.Add(getEntriesEntriesNodes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Console.WriteLine(e);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -8,4 +8,12 @@
|
|||||||
|
|
||||||
<!-- <FluentTheme Mode="Dark"></FluentTheme> -->
|
<!-- <FluentTheme Mode="Dark"></FluentTheme> -->
|
||||||
<StyleInclude Source="avares://Artemis.UI.Shared/Styles/Artemis.axaml" />
|
<StyleInclude Source="avares://Artemis.UI.Shared/Styles/Artemis.axaml" />
|
||||||
|
|
||||||
|
<Styles.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<MergeResourceInclude Source="TreeView.axaml"></MergeResourceInclude>
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</Styles.Resources>
|
||||||
</Styles>
|
</Styles>
|
||||||
122
src/Artemis.UI/Styles/TreeView.axaml
Normal file
122
src/Artemis.UI/Styles/TreeView.axaml
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:converters="clr-namespace:Avalonia.Controls.Converters;assembly=Avalonia.Controls"
|
||||||
|
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||||
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
|
x:CompileBindings="True">
|
||||||
|
<Design.PreviewWith>
|
||||||
|
<Border Padding="30" MinWidth="350">
|
||||||
|
<TreeView ItemContainerTheme="{StaticResource MenuTreeViewItem}">
|
||||||
|
<TreeViewItem>
|
||||||
|
<TreeViewItem.Header>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<avalonia:MaterialIcon Kind="Home" Width="16" Height="16" />
|
||||||
|
<TextBlock FontSize="12" Margin="10 0" VerticalAlignment="Center" Text="Home" />
|
||||||
|
</StackPanel>
|
||||||
|
</TreeViewItem.Header>
|
||||||
|
</TreeViewItem>
|
||||||
|
<TreeViewItem IsExpanded="True">
|
||||||
|
<TreeViewItem.Header>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<avalonia:MaterialIcon Kind="TestTube" Width="16" Height="16" />
|
||||||
|
<TextBlock FontSize="12" Margin="10 0" VerticalAlignment="Center" Text="Workshop" />
|
||||||
|
</StackPanel>
|
||||||
|
</TreeViewItem.Header>
|
||||||
|
<TreeViewItem>
|
||||||
|
<TreeViewItem.Header>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<avalonia:MaterialIcon Kind="FolderVideo" Width="16" Height="16" />
|
||||||
|
<TextBlock FontSize="12" Margin="10 0" VerticalAlignment="Center" Text="Profiles" />
|
||||||
|
</StackPanel>
|
||||||
|
</TreeViewItem.Header>
|
||||||
|
</TreeViewItem>
|
||||||
|
<TreeViewItem>
|
||||||
|
<TreeViewItem.Header>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<avalonia:MaterialIcon Kind="KeyboardVariant" Width="16" Height="16" />
|
||||||
|
<TextBlock FontSize="12" Margin="10 0" VerticalAlignment="Center" Text="Layouts" />
|
||||||
|
</StackPanel>
|
||||||
|
</TreeViewItem.Header>
|
||||||
|
</TreeViewItem>
|
||||||
|
</TreeViewItem>
|
||||||
|
<TreeViewItem>
|
||||||
|
<TreeViewItem.Header>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<avalonia:MaterialIcon Kind="Devices" Width="16" Height="16" />
|
||||||
|
<TextBlock FontSize="12" Margin="10 0" VerticalAlignment="Center" Text="Surface Editor" />
|
||||||
|
</StackPanel>
|
||||||
|
</TreeViewItem.Header>
|
||||||
|
</TreeViewItem>
|
||||||
|
<TreeViewItem>
|
||||||
|
<TreeViewItem.Header>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<avalonia:MaterialIcon Kind="Cog" Width="16" Height="16" />
|
||||||
|
<TextBlock FontSize="12" Margin="10 0" VerticalAlignment="Center" Text="Settings" />
|
||||||
|
</StackPanel>
|
||||||
|
</TreeViewItem.Header>
|
||||||
|
</TreeViewItem>
|
||||||
|
</TreeView>
|
||||||
|
</Border>
|
||||||
|
</Design.PreviewWith>
|
||||||
|
|
||||||
|
<x:Double x:Key="TreeViewItemIndent">31</x:Double>
|
||||||
|
<x:Double x:Key="TreeViewItemExpandCollapseChevronSize">12</x:Double>
|
||||||
|
<Thickness x:Key="TreeViewItemExpandCollapseChevronMargin">12, 0, 12, 0</Thickness>
|
||||||
|
<converters:MarginMultiplierConverter Indent="{StaticResource TreeViewItemIndent}"
|
||||||
|
Left="True"
|
||||||
|
x:Key="TreeViewItemLeftMarginConverter" />
|
||||||
|
|
||||||
|
<ControlTheme TargetType="TreeViewItem" x:Key="MenuTreeViewItem" BasedOn="{StaticResource {x:Type TreeViewItem}}">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<ControlTemplate>
|
||||||
|
<StackPanel>
|
||||||
|
<Border Name="PART_LayoutRoot"
|
||||||
|
Classes="TreeViewItemLayoutRoot"
|
||||||
|
Focusable="True"
|
||||||
|
Background="{TemplateBinding Background}"
|
||||||
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
MinHeight="{DynamicResource NavigationViewItemOnLeftMinHeight}"
|
||||||
|
CornerRadius="{DynamicResource OverlayCornerRadius}"
|
||||||
|
TemplatedControl.IsTemplateFocusTarget="True"
|
||||||
|
Margin="2">
|
||||||
|
<Panel>
|
||||||
|
<Grid Name="PART_Header"
|
||||||
|
ColumnDefinitions="12, *, Auto"
|
||||||
|
Margin="{TemplateBinding Level, Mode=OneWay, Converter={StaticResource TreeViewItemLeftMarginConverter}}">
|
||||||
|
<Rectangle Name="SelectionIndicator"
|
||||||
|
Width="3"
|
||||||
|
Height="16"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
RadiusX="2"
|
||||||
|
RadiusY="2"
|
||||||
|
IsVisible="False"
|
||||||
|
Fill="{DynamicResource TreeViewItemSelectionIndicatorForeground}" />
|
||||||
|
|
||||||
|
<ContentPresenter Name="PART_HeaderPresenter"
|
||||||
|
Grid.Column="1"
|
||||||
|
Focusable="False"
|
||||||
|
Content="{TemplateBinding Header}"
|
||||||
|
ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||||
|
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||||
|
VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||||
|
Margin="{TemplateBinding Padding}" />
|
||||||
|
<Panel Name="PART_ExpandCollapseChevronContainer" Grid.Column="2">
|
||||||
|
<ToggleButton Name="PART_ExpandCollapseChevron"
|
||||||
|
Theme="{StaticResource TreeViewChevronButton}"
|
||||||
|
Focusable="False"
|
||||||
|
Margin="{StaticResource TreeViewItemExpandCollapseChevronMargin}"
|
||||||
|
IsChecked="{TemplateBinding IsExpanded, Mode=TwoWay}" />
|
||||||
|
</Panel>
|
||||||
|
</Grid>
|
||||||
|
</Panel>
|
||||||
|
</Border>
|
||||||
|
<ItemsPresenter Name="PART_ItemsPresenter"
|
||||||
|
IsVisible="{TemplateBinding IsExpanded}"
|
||||||
|
ItemsPanel="{TemplateBinding ItemsPanel}" />
|
||||||
|
</StackPanel>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter>
|
||||||
|
</ControlTheme>
|
||||||
|
</ResourceDictionary>
|
||||||
Loading…
x
Reference in New Issue
Block a user