1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2026-02-04 10:53:31 +00:00

Add most of the UI code for profile configuration

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

View File

@ -0,0 +1,8 @@
namespace Artemis.Core;
/// <summary>
/// Represents a configuration item that accepts ColorGradient input from the user.
/// </summary>
public class ConfigurationColorGradientItem : ConfigurationInputItem<ColorGradient>
{
}

View File

@ -5,4 +5,7 @@
/// </summary> /// </summary>
public class ConfigurationNumericItem : ConfigurationInputItem<Numeric> public class ConfigurationNumericItem : ConfigurationInputItem<Numeric>
{ {
public Numeric? Minimum { get; set; }
public Numeric? Maximum { get; set; }
public bool Slider { get; set; }
} }

View File

@ -308,12 +308,12 @@ public class ProfileConfiguration : BreakableModel, IStorageModel, IDisposable,
ConfigurationSections.Add(new ConfigurationSection() ConfigurationSections.Add(new ConfigurationSection()
{ {
Name = "General (slot 0)", Name = "General (slot 0)",
Slot = 0, Slot = 2,
}); });
ConfigurationSections.Add(new ConfigurationSection() ConfigurationSections.Add(new ConfigurationSection()
{ {
Name = "Other (slot 1)", Name = "Other (slot 1)",
Slot = 1 Slot = 2
}); });
ConfigurationSections.Add(new ConfigurationSection() ConfigurationSections.Add(new ConfigurationSection()
{ {
@ -321,11 +321,14 @@ public class ProfileConfiguration : BreakableModel, IStorageModel, IDisposable,
Slot = 2 Slot = 2
}); });
ConfigurationSections[0].Items.Add(new ConfigurationTextItem() {Text = "This is a placeholder text item in the General section."}); ConfigurationSections[0].Items.Add(new ConfigurationTextItem() {Text = "This is a placeholder text item in the General section."});
ConfigurationSections[0].Items.Add(new ConfigurationNumericItem() {Name = "Numeric item"}); ConfigurationSections[0].Items.Add(new ConfigurationNumericItem() {Name = "Numeric item", Description = "This one also has a description"});
ConfigurationSections[0].Items.Add(new ConfigurationBooleanItem() {Name = "Do the thing?", TrueText = "Absolutely", FalseText = "Nope"}); ConfigurationSections[0].Items.Add(new ConfigurationBooleanItem() {Name = "Do the thing?", TrueText = "Absolutely", FalseText = "Nope"});
ConfigurationSections[1].Items.Add(new ConfigurationTextItem() {Text = "This is a placeholder text item in the Other section."}); ConfigurationSections[1].Items.Add(new ConfigurationTextItem() {Text = "This is a placeholder text item in the Other section."});
ConfigurationSections[2].Items.Add(new ConfigurationTextItem() {Text = "This is a placeholder text item in the Something else section."}); ConfigurationSections[2].Items.Add(new ConfigurationTextItem() {Text = "This is a placeholder text item in the Something else section."});
ConfigurationSections[2].Items.Add(new ConfigurationTextItem() {Text = "This is another placeholder text item in the Something else section."}); ConfigurationSections[2].Items.Add(new ConfigurationTextItem() {Text = "This is another placeholder text item in the Something else section."});
ConfigurationSections[2].Items.Add(new ConfigurationNumericItem() {Name = "Numeric item", Description = "This one uses a slider", Minimum = 0, Maximum = 10, Slider = true});
ConfigurationSections[2].Items.Add(new ConfigurationColorGradientItem() {Name = "Color gradient"});
ConfigurationSections[2].Items.Add(new ConfigurationSKColorItem() {Name = "A simple color", Description = "Again with a description"});
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization; using System.Globalization;
namespace Artemis.Core; namespace Artemis.Core;
@ -11,7 +12,8 @@ namespace Artemis.Core;
/// Usage outside that context is not recommended due to conversion overhead. /// Usage outside that context is not recommended due to conversion overhead.
/// </para> /// </para>
/// </summary> /// </summary>
public readonly struct Numeric : IComparable<Numeric>, IConvertible [TypeConverter(typeof(NumericTypeConverter))]
public readonly struct Numeric : IComparable<Numeric>, IConvertible, IEquatable<Numeric>
{ {
private readonly float _value; private readonly float _value;

View File

@ -0,0 +1,90 @@
using System;
using System.ComponentModel;
using System.Globalization;
namespace Artemis.Core;
/// <summary>
/// Type converter for <see cref="Numeric" /> to support Avalonia binding from other numeric types
/// </summary>
public class NumericTypeConverter : TypeConverter
{
/// <inheritdoc />
public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
{
return sourceType == typeof(double) ||
sourceType == typeof(float) ||
sourceType == typeof(int) ||
sourceType == typeof(long) ||
sourceType == typeof(byte) ||
sourceType == typeof(short) ||
sourceType == typeof(decimal) ||
sourceType == typeof(uint) ||
sourceType == typeof(ulong) ||
sourceType == typeof(ushort) ||
sourceType == typeof(sbyte) ||
sourceType == typeof(string) ||
base.CanConvertFrom(context, sourceType);
}
/// <inheritdoc />
public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType)
{
return destinationType == typeof(double) ||
destinationType == typeof(float) ||
destinationType == typeof(int) ||
destinationType == typeof(long) ||
destinationType == typeof(byte) ||
destinationType == typeof(short) ||
destinationType == typeof(decimal) ||
destinationType == typeof(uint) ||
destinationType == typeof(ulong) ||
destinationType == typeof(ushort) ||
destinationType == typeof(sbyte) ||
destinationType == typeof(string) ||
base.CanConvertTo(context, destinationType);
}
/// <inheritdoc />
public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
{
return value switch
{
double d => new Numeric(d),
float f => new Numeric(f),
int i => new Numeric(i),
long l => new Numeric(l),
byte b => new Numeric(b),
short s => new Numeric(s),
decimal dec => new Numeric((double)dec),
uint ui => new Numeric(ui),
ulong ul => new Numeric((long)ul),
ushort us => new Numeric(us),
sbyte sb => new Numeric(sb),
string str => Numeric.TryParse(str, out Numeric result) ? result : throw new FormatException($"Unable to convert '{str}' to Numeric"),
_ => base.ConvertFrom(context, culture, value)
};
}
/// <inheritdoc />
public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType)
{
if (value is Numeric numeric)
{
if (destinationType == typeof(double)) return (double)numeric;
if (destinationType == typeof(float)) return (float)numeric;
if (destinationType == typeof(int)) return (int)numeric;
if (destinationType == typeof(long)) return (long)numeric;
if (destinationType == typeof(byte)) return (byte)numeric;
if (destinationType == typeof(short)) return (short)numeric;
if (destinationType == typeof(decimal)) return (decimal)numeric;
if (destinationType == typeof(uint)) return (uint)numeric;
if (destinationType == typeof(ulong)) return (ulong)numeric;
if (destinationType == typeof(ushort)) return (ushort)numeric;
if (destinationType == typeof(sbyte)) return (sbyte)numeric;
if (destinationType == typeof(string)) return numeric.ToString(CultureInfo.InvariantCulture);
}
return base.ConvertTo(context, culture, value, destinationType);
}
}

View File

@ -21,41 +21,44 @@
</VisualBrush.Visual> </VisualBrush.Visual>
</VisualBrush> </VisualBrush>
</UserControl.Resources> </UserControl.Resources>
<ZoomBorder Name="ZoomBorder" <Border Classes="card" Padding="0">
Stretch="None" <Panel>
ClipToBounds="True" <ZoomBorder Name="ZoomBorder"
Focusable="True" Stretch="None"
VerticalAlignment="Stretch" ClipToBounds="True"
HorizontalAlignment="Stretch" Focusable="True"
Background="{StaticResource LargeCheckerboardBrush}" VerticalAlignment="Stretch"
ZoomChanged="ZoomBorder_OnZoomChanged"> HorizontalAlignment="Stretch"
<Grid Name="ContainerGrid" Background="Transparent"> Background="{StaticResource LargeCheckerboardBrush}"
<Grid.Transitions> ZoomChanged="ZoomBorder_OnZoomChanged">
<Transitions> <Grid Name="ContainerGrid" Background="Transparent">
<TransformOperationsTransition Property="RenderTransform" Duration="0:0:0.2" Easing="CubicEaseOut" /> <Grid.Transitions>
</Transitions> <Transitions>
</Grid.Transitions> <TransformOperationsTransition Property="RenderTransform" Duration="0:0:0.2" Easing="CubicEaseOut" />
</Transitions>
<!-- The bottom layer consists of devices --> </Grid.Transitions>
<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>
<!-- 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" <Border CornerRadius="0 0 8 0"
VerticalAlignment="Top" VerticalAlignment="Top"
HorizontalAlignment="Left" HorizontalAlignment="Left"
@ -66,6 +69,7 @@
<TextBlock Text="{CompiledBinding ProfileConfiguration.Name}" /> <TextBlock Text="{CompiledBinding ProfileConfiguration.Name}" />
</StackPanel> </StackPanel>
</Border> </Border>
</Grid> </Panel>
</ZoomBorder> </Border>
</UserControl> </UserControl>

View File

@ -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>

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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();
}
}

View File

@ -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; }
}

View File

@ -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>

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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();
}
}

View File

@ -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; }
}

View File

@ -10,9 +10,25 @@
<StackPanel> <StackPanel>
<TextBlock Theme="{StaticResource SubtitleTextBlockStyle}" Text="{CompiledBinding ConfigurationSection.Name}"/> <TextBlock Theme="{StaticResource SubtitleTextBlockStyle}" Text="{CompiledBinding ConfigurationSection.Name}"/>
<Border Classes="card-separator" /> <Border Classes="card-separator" />
<ScrollViewer>
<TextBlock>Test</TextBlock> <ItemsControl ItemsSource="{CompiledBinding Items}">
</ScrollViewer> <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> </StackPanel>
</Border> </Border>
</UserControl> </UserControl>

View File

@ -1,4 +1,5 @@
using Artemis.Core; using System.Collections.ObjectModel;
using Artemis.Core;
using Artemis.UI.Shared; using Artemis.UI.Shared;
namespace Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section; namespace Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section;
@ -6,9 +7,26 @@ namespace Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section;
public class ConfigurationSectionViewModel : ActivatableViewModelBase public class ConfigurationSectionViewModel : ActivatableViewModelBase
{ {
public ConfigurationSection ConfigurationSection { get; } public ConfigurationSection ConfigurationSection { get; }
public ObservableCollection<ActivatableViewModelBase> Items { get; }
public ConfigurationSectionViewModel(ConfigurationSection configurationSection) public ConfigurationSectionViewModel(ConfigurationSection configurationSection)
{ {
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));
}
} }
} }

View File

@ -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>

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -2,9 +2,9 @@
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: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" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Slot.SlotView" x:Class="Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Section.ConfigurationTextItemView"
x:DataType="slot:SlotViewModel"> x:DataType="section:ConfigurationTextItemViewModel">
Welcome to Avalonia! <TextBlock Text="{CompiledBinding Item.Text}"></TextBlock>
</UserControl> </UserControl>

View File

@ -1,12 +1,13 @@
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml; 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(); InitializeComponent();
} }

View File

@ -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;
}
}

View File

@ -1,8 +0,0 @@
using Artemis.UI.Shared;
namespace Artemis.UI.Screens.ProfileEditor.ConfigurationPanels.Slot;
public class SlotViewModel : ActivatableViewModelBase
{
}

View File

@ -7,12 +7,32 @@
x:Class="Artemis.UI.Screens.ProfileEditor.ConfigureProfileView" x:Class="Artemis.UI.Screens.ProfileEditor.ConfigureProfileView"
x:DataType="profileEditor:ConfigureProfileViewModel"> x:DataType="profileEditor:ConfigureProfileViewModel">
<Border Classes="router-container" Padding="8"> <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}" /> <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="0" Grid.Row="1" ItemsSource="{CompiledBinding BottomLeftSections}">
<ItemsControl Grid.Column="1" Grid.Row="1" ItemsSource="{CompiledBinding BottomRightSections}"/> <ItemsControl.ItemsPanel>
<ItemsControl Grid.Column="2" Grid.Row="0" Grid.RowSpan="2" ItemsSource="{CompiledBinding SideSections}"/> <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> </Grid>
</Border> </Border>
</UserControl> </UserControl>

View File

@ -9,7 +9,7 @@
<ItemsControl ItemsSource="{CompiledBinding DeviceViewModels}"> <ItemsControl ItemsSource="{CompiledBinding DeviceViewModels}">
<ItemsControl.ItemTemplate> <ItemsControl.ItemTemplate>
<DataTemplate x:DataType="layoutFinder:LayoutFinderDeviceViewModel"> <DataTemplate x:DataType="layoutFinder:LayoutFinderDeviceViewModel">
<StackPanel Classes="device-view-model-container"> <StackPanel>
<!-- Your existing item template goes here --> <!-- Your existing item template goes here -->
<ContentControl Content="{CompiledBinding}"/> <ContentControl Content="{CompiledBinding}"/>
<Border Classes="card-separator" Name="Separator" /> <Border Classes="card-separator" Name="Separator" />