Add most of the UI code for profile configuration

This commit is contained in:
Robert committed 2026-01-24 13:06:08 +01:00
1 parent 3004293051
commit 77a4d8201e
29 files changed
+508 -68

No files matched your search

@@ -21,51 +21,55 @@
</VisualBrush.Visual>
</VisualBrush>
</UserControl.Resources>
<ZoomBorder Name="ZoomBorder"
Stretch="None"
ClipToBounds="True"
Focusable="True"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Background="{StaticResource LargeCheckerboardBrush}"
ZoomChanged="ZoomBorder_OnZoomChanged">
<Grid Name="ContainerGrid" Background="Transparent">
<Grid.Transitions>
<Transitions>
<TransformOperationsTransition Property="RenderTransform" Duration="0:0:0.2" Easing="CubicEaseOut" />
</Transitions>
</Grid.Transitions>
<Border Classes="card" Padding="0">
<Panel>
<ZoomBorder Name="ZoomBorder"
Stretch="None"
ClipToBounds="True"
Focusable="True"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Background="{StaticResource LargeCheckerboardBrush}"
ZoomChanged="ZoomBorder_OnZoomChanged">
<Grid Name="ContainerGrid" Background="Transparent">
<Grid.Transitions>
<Transitions>
<TransformOperationsTransition Property="RenderTransform" Duration="0:0:0.2" Easing="CubicEaseOut" />
</Transitions>
</Grid.Transitions>
<!-- The bottom layer consists of devices -->
<ItemsControl Name="DevicesContainer" ItemsSource="{CompiledBinding Devices}" ClipToBounds="False">
<ItemsControl.Styles>
<Style Selector="ContentPresenter" x:DataType="core:ArtemisDevice">
<Setter Property="Canvas.Left" Value="{CompiledBinding X}" />
<Setter Property="Canvas.Top" Value="{CompiledBinding Y}" />
</Style>
</ItemsControl.Styles>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="core:ArtemisDevice">
<shared:DeviceVisualizer Device="{CompiledBinding}" ShowColors="True" RenderOptions.BitmapInterpolationMode="MediumQuality" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Border CornerRadius="0 0 8 0"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Background="{DynamicResource ControlFillColorDefaultBrush}"
<!-- The bottom layer consists of devices -->
<ItemsControl Name="DevicesContainer" ItemsSource="{CompiledBinding Devices}" ClipToBounds="False">
<ItemsControl.Styles>
<Style Selector="ContentPresenter" x:DataType="core:ArtemisDevice">
<Setter Property="Canvas.Left" Value="{CompiledBinding X}" />
<Setter Property="Canvas.Top" Value="{CompiledBinding Y}" />
</Style>
</ItemsControl.Styles>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="core:ArtemisDevice">
<shared:DeviceVisualizer Device="{CompiledBinding}" ShowColors="True" RenderOptions.BitmapInterpolationMode="MediumQuality" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</ZoomBorder>
<Border CornerRadius="0 0 8 0"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Background="{DynamicResource ControlFillColorDefaultBrush}"
IsVisible="{CompiledBinding ProfileConfiguration, Converter={x:Static ObjectConverters.IsNotNull}}">
<StackPanel Orientation="Horizontal" Margin="8">
<shared:ProfileConfigurationIcon ConfigurationIcon="{CompiledBinding ProfileConfiguration.Icon}" Width="18" Height="18" CornerRadius="3" Margin="0 0 5 0" />
<TextBlock Text="{CompiledBinding ProfileConfiguration.Name}" />
</StackPanel>
</Border>
</Grid>
</ZoomBorder>
</Panel>
</Border>
</UserControl>
@@ -0,0 +1,26 @@
<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:section="clr-namespace:Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section.ConfigurationBooleanItemView"
x:DataType="section:ConfigurationBooleanItemViewModel">
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" VerticalAlignment="Center">
<TextBlock Text="{CompiledBinding Item.Name}" TextWrapping="Wrap" />
<TextBlock Classes="subtitle"
TextWrapping="Wrap"
Text="{CompiledBinding Item.Description}"
IsVisible="{CompiledBinding Item.Description, Converter={x:Static StringConverters.IsNotNullOrEmpty}}" />
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<ToggleSwitch IsChecked="{CompiledBinding Item.Value}"
OnContent="{CompiledBinding Item.TrueText}"
OffContent="{CompiledBinding Item.FalseText}"
MinWidth="0"
Margin="0 -10"
FlowDirection="RightToLeft"/>
</StackPanel>
</Grid>
</UserControl>
@@ -0,0 +1,14 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using ReactiveUI.Avalonia;
namespace Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section;
public partial class ConfigurationBooleanItemView : ReactiveUserControl<ConfigurationStringItemViewModel>
{
public ConfigurationBooleanItemView()
{
InitializeComponent();
}
}
@@ -0,0 +1,14 @@
using Artemis.Core;
using Artemis.UI.Shared;
namespace Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section;
public class ConfigurationBooleanItemViewModel : ActivatableViewModelBase
{
public ConfigurationBooleanItem Item { get; }
public ConfigurationBooleanItemViewModel(ConfigurationBooleanItem item)
{
Item = item;
}
}
@@ -0,0 +1,24 @@
<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:section="clr-namespace:Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section"
xmlns:gradientPicker="clr-namespace:Artemis.UI.Shared.Controls.GradientPicker;assembly=Artemis.UI.Shared"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section.ConfigurationColorGradientItemView"
x:DataType="section:ConfigurationColorGradientItemViewModel">
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" VerticalAlignment="Center">
<TextBlock Text="{CompiledBinding Item.Name}" TextWrapping="Wrap" />
<TextBlock Classes="subtitle"
TextWrapping="Wrap"
Text="{CompiledBinding Item.Description}"
IsVisible="{CompiledBinding Item.Description, Converter={x:Static StringConverters.IsNotNullOrEmpty}}" />
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<gradientPicker:GradientPickerButton Width="150"
ColorGradient="{CompiledBinding Item.Value}"
VerticalAlignment="Center"/>
</StackPanel>
</Grid>
</UserControl>
@@ -0,0 +1,14 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using ReactiveUI.Avalonia;
namespace Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section;
public partial class ConfigurationColorGradientItemView : ReactiveUserControl<ConfigurationColorGradientItemViewModel>
{
public ConfigurationColorGradientItemView()
{
InitializeComponent();
}
}
@@ -0,0 +1,14 @@
using Artemis.Core;
using Artemis.UI.Shared;
namespace Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section;
public class ConfigurationColorGradientItemViewModel : ActivatableViewModelBase
{
public ConfigurationColorGradientItemViewModel(ConfigurationColorGradientItem item)
{
Item = item;
}
public ConfigurationColorGradientItem Item { get; }
}
@@ -0,0 +1,32 @@
<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:section="clr-namespace:Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section"
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:behaviors="clr-namespace:Artemis.UI.Shared.Behaviors;assembly=Artemis.UI.Shared"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section.ConfigurationNumericItemView"
x:DataType="section:ConfigurationNumericItemViewModel">
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" VerticalAlignment="Center">
<TextBlock Text="{CompiledBinding Item.Name}" TextWrapping="Wrap" />
<TextBlock Classes="subtitle"
TextWrapping="Wrap"
Text="{CompiledBinding Item.Description}"
IsVisible="{CompiledBinding Item.Description, Converter={x:Static StringConverters.IsNotNullOrEmpty}}" />
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<controls:NumberBox Width="150" IsVisible="{CompiledBinding !Item.Slider}">
<Interaction.Behaviors>
<behaviors:LostFocusNumberBoxBindingBehavior Value="{CompiledBinding Item.Value}" />
</Interaction.Behaviors>
</controls:NumberBox>
<Slider Minimum="{CompiledBinding Item.Minimum}"
Maximum="{CompiledBinding Item.Maximum}"
Width="150"
IsVisible="{CompiledBinding Item.Slider}"
Value="{CompiledBinding Item.Value, Mode=TwoWay}" />
</StackPanel>
</Grid>
</UserControl>
@@ -0,0 +1,14 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using ReactiveUI.Avalonia;
namespace Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section;
public partial class ConfigurationNumericItemView : ReactiveUserControl<ConfigurationStringItemViewModel>
{
public ConfigurationNumericItemView()
{
InitializeComponent();
}
}
@@ -0,0 +1,14 @@
using Artemis.Core;
using Artemis.UI.Shared;
namespace Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section;
public class ConfigurationNumericItemViewModel : ActivatableViewModelBase
{
public ConfigurationNumericItem Item { get; }
public ConfigurationNumericItemViewModel(ConfigurationNumericItem item)
{
Item = item;
}
}
@@ -0,0 +1,26 @@
<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:section="clr-namespace:Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section"
xmlns:behaviors="clr-namespace:Artemis.UI.Shared.Behaviors;assembly=Artemis.UI.Shared"
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section.ConfigurationSKColorItemView"
x:DataType="section:ConfigurationSKColorItemViewModel">
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" VerticalAlignment="Center">
<TextBlock Text="{CompiledBinding Item.Name}" TextWrapping="Wrap" />
<TextBlock Classes="subtitle"
TextWrapping="Wrap"
Text="{CompiledBinding Item.Description}"
IsVisible="{CompiledBinding Item.Description, Converter={x:Static StringConverters.IsNotNullOrEmpty}}" />
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<controls:ColorPickerButton Color="{CompiledBinding Item.Value, Converter={StaticResource SKColorToColorConverter}}"
ShowAcceptDismissButtons="False"
FlyoutPlacement="Right" />
</StackPanel>
</Grid>
</UserControl>
@@ -0,0 +1,14 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using ReactiveUI.Avalonia;
namespace Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section;
public partial class ConfigurationSKColorItemView : ReactiveUserControl<ConfigurationStringItemViewModel>
{
public ConfigurationSKColorItemView()
{
InitializeComponent();
}
}
@@ -0,0 +1,14 @@
using Artemis.Core;
using Artemis.UI.Shared;
namespace Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section;
public class ConfigurationSKColorItemViewModel : ActivatableViewModelBase
{
public ConfigurationSKColorItemViewModel(ConfigurationSKColorItem item)
{
Item = item;
}
public ConfigurationSKColorItem Item { get; }
}
@@ -10,9 +10,25 @@
<StackPanel>
<TextBlock Theme="{StaticResource SubtitleTextBlockStyle}" Text="{CompiledBinding ConfigurationSection.Name}"/>
<Border Classes="card-separator" />
<ScrollViewer>
<TextBlock>Test</TextBlock>
</ScrollViewer>
<ItemsControl ItemsSource="{CompiledBinding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Classes="device-view-model-container">
<!-- Your existing item template goes here -->
<ContentControl Content="{CompiledBinding}"/>
<Border Classes="card-separator" Name="Separator" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.Styles>
<Styles>
<Style Selector="ContentPresenter:nth-last-child(1) > StackPanel > Border#Separator">
<Setter Property="IsVisible" Value="False" />
</Style>
</Styles>
</ItemsControl.Styles>
</ItemsControl>
</StackPanel>
</Border>
</UserControl>
@@ -1,4 +1,5 @@
using Artemis.Core;
using System.Collections.ObjectModel;
using Artemis.Core;
using Artemis.UI.Shared;
namespace Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section;
@@ -6,9 +7,26 @@ namespace Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section;
public class ConfigurationSectionViewModel : ActivatableViewModelBase
{
public ConfigurationSection ConfigurationSection { get; }
public ObservableCollection<ActivatableViewModelBase> Items { get; }
public ConfigurationSectionViewModel(ConfigurationSection configurationSection)
{
ConfigurationSection = configurationSection;
Items = [];
foreach (IConfigurationItem item in ConfigurationSection.Items)
{
if (item is ConfigurationTextItem textItem)
Items.Add(new ConfigurationTextItemViewModel(textItem));
else if (item is ConfigurationStringItem stringItem)
Items.Add(new ConfigurationStringItemViewModel(stringItem));
else if (item is ConfigurationBooleanItem booleanItem)
Items.Add(new ConfigurationBooleanItemViewModel(booleanItem));
else if (item is ConfigurationNumericItem numberItem)
Items.Add(new ConfigurationNumericItemViewModel(numberItem));
else if (item is ConfigurationSKColorItem colorItem)
Items.Add(new ConfigurationSKColorItemViewModel(colorItem));
else if (item is ConfigurationColorGradientItem colorGradientItem)
Items.Add(new ConfigurationColorGradientItemViewModel(colorGradientItem));
}
}
}
@@ -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:section="clr-namespace:Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section.ConfigurationStringItemView"
x:DataType="section:ConfigurationStringItemViewModel">
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" VerticalAlignment="Center">
<TextBlock Text="{CompiledBinding Item.Name}" TextWrapping="Wrap" />
<TextBlock Classes="subtitle"
TextWrapping="Wrap"
Text="{CompiledBinding Item.Description}"
IsVisible="{CompiledBinding Item.Description, Converter={x:Static StringConverters.IsNotNullOrEmpty}}" />
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<TextBox Text="{CompiledBinding Item.Value, Mode=TwoWay}" MinWidth="150" />
</StackPanel>
</Grid>
</UserControl>
@@ -0,0 +1,14 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using ReactiveUI.Avalonia;
namespace Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section;
public partial class ConfigurationStringItemView : ReactiveUserControl<ConfigurationStringItemViewModel>
{
public ConfigurationStringItemView()
{
InitializeComponent();
}
}
@@ -0,0 +1,14 @@
using Artemis.Core;
using Artemis.UI.Shared;
namespace Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section;
public class ConfigurationStringItemViewModel : ActivatableViewModelBase
{
public ConfigurationStringItem Item { get; }
public ConfigurationStringItemViewModel(ConfigurationStringItem item)
{
Item = item;
}
}
@@ -2,9 +2,9 @@
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:slot="clr-namespace:Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Slot"
xmlns:section="clr-namespace:Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Slot.SlotView"
x:DataType="slot:SlotViewModel">
Welcome to Avalonia!
x:Class="Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section.ConfigurationTextItemView"
x:DataType="section:ConfigurationTextItemViewModel">
<TextBlock Text="{CompiledBinding Item.Text}"></TextBlock>
</UserControl>
@@ -1,12 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using ReactiveUI.Avalonia;
namespace Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Slot;
namespace Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section;
public partial class SlotView : UserControl
public partial class ConfigurationTextItemView : ReactiveUserControl<ConfigurationTextItemViewModel>
{
public SlotView()
public ConfigurationTextItemView()
{
InitializeComponent();
}
@@ -0,0 +1,14 @@
using Artemis.Core;
using Artemis.UI.Shared;
namespace Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section;
public class ConfigurationTextItemViewModel : ActivatableViewModelBase
{
public ConfigurationTextItem Item { get; }
public ConfigurationTextItemViewModel(ConfigurationTextItem item)
{
Item = item;
}
}
@@ -1,8 +0,0 @@
using Artemis.UI.Shared;
namespace Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Slot;
public class SlotViewModel : ActivatableViewModelBase
{
}
@@ -7,12 +7,32 @@
x:Class="Artemis.UI.Screens.ProfileEditor.ConfigureProfileView"
x:DataType="profileEditor:ConfigureProfileViewModel">
<Border Classes="router-container" Padding="8">
<Grid RowDefinitions="0.6*, 0.6*" ColumnDefinitions="0.3*, 0.3*, 0.4*" ColumnSpacing="8" RowSpacing="8">
<Grid RowDefinitions="0.6*, Auto" ColumnDefinitions="0.3*, 0.3*, Auto" ColumnSpacing="8" RowSpacing="8">
<ContentControl Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Content="{CompiledBinding PreviewViewModel}" />
<ItemsControl Grid.Column="0" Grid.Row="1" ItemsSource="{CompiledBinding BottomLeftSections}"/>
<ItemsControl Grid.Column="1" Grid.Row="1" ItemsSource="{CompiledBinding BottomRightSections}"/>
<ItemsControl Grid.Column="2" Grid.Row="0" Grid.RowSpan="2" ItemsSource="{CompiledBinding SideSections}"/>
<ItemsControl Grid.Column="0" Grid.Row="1" ItemsSource="{CompiledBinding BottomLeftSections}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Spacing="8"></StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<ItemsControl Grid.Column="1" Grid.Row="1" ItemsSource="{CompiledBinding BottomRightSections}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Spacing="8"></StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<ScrollViewer Grid.Column="2" Grid.Row="0" Grid.RowSpan="2">
<ItemsControl ItemsSource="{CompiledBinding SideSections}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Spacing="8"></StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
</Grid>
</Border>
</UserControl>