From 87117cc110327cca43cf009b88c2b05a3333133a Mon Sep 17 00:00:00 2001 From: Robert Date: Sat, 6 Nov 2021 16:47:12 +0100 Subject: [PATCH] Device properties - Implemented first tab --- .../Controls/DeviceVisualizer.cs | 10 +- .../Converters/ColorToSKColorConverter.cs | 38 ++++ .../Converters/SKColorToColorConverter.cs | 38 ++++ .../Services/Builders/NotificationBuilder.cs | 2 +- .../Styles/InfoBar.axaml | 11 +- .../Ninject/Factories/IVMFactory.cs | 7 +- .../ViewModels/DeviceInfoTabViewModel.cs | 2 +- .../ViewModels/DeviceLedsTabViewModel.cs | 12 +- .../DevicePropertiesTabViewModel.cs | 53 +++-- .../ViewModels/DevicePropertiesViewModel.cs | 16 +- .../ViewModels/InputMappingsTabViewModel.cs | 7 +- .../Device/Views/DeviceInfoTabView.axaml | 8 + .../Device/Views/DeviceInfoTabView.axaml.cs | 19 ++ .../Device/Views/DeviceLedsTabView.axaml | 8 + .../Device/Views/DeviceLedsTabView.axaml.cs | 19 ++ .../Views/DevicePropertiesTabView.axaml | 197 ++++++++++++++++++ .../Views/DevicePropertiesTabView.axaml.cs | 28 +++ .../Device/Views/DevicePropertiesView.axaml | 25 ++- .../Device/Views/InputMappingsTabView.axaml | 8 + .../Views/InputMappingsTabView.axaml.cs | 19 ++ .../Workshop/ViewModels/WorkshopViewModel.cs | 19 +- .../Screens/Workshop/Views/WorkshopView.axaml | 23 +- .../Styles/TextBlock.axaml | 6 + 23 files changed, 520 insertions(+), 55 deletions(-) create mode 100644 src/Artemis.UI.Avalonia.Shared/Converters/ColorToSKColorConverter.cs create mode 100644 src/Artemis.UI.Avalonia.Shared/Converters/SKColorToColorConverter.cs create mode 100644 src/Artemis.UI.Avalonia/Screens/Device/Views/DeviceInfoTabView.axaml create mode 100644 src/Artemis.UI.Avalonia/Screens/Device/Views/DeviceInfoTabView.axaml.cs create mode 100644 src/Artemis.UI.Avalonia/Screens/Device/Views/DeviceLedsTabView.axaml create mode 100644 src/Artemis.UI.Avalonia/Screens/Device/Views/DeviceLedsTabView.axaml.cs create mode 100644 src/Artemis.UI.Avalonia/Screens/Device/Views/DevicePropertiesTabView.axaml create mode 100644 src/Artemis.UI.Avalonia/Screens/Device/Views/DevicePropertiesTabView.axaml.cs create mode 100644 src/Artemis.UI.Avalonia/Screens/Device/Views/InputMappingsTabView.axaml create mode 100644 src/Artemis.UI.Avalonia/Screens/Device/Views/InputMappingsTabView.axaml.cs diff --git a/src/Artemis.UI.Avalonia.Shared/Controls/DeviceVisualizer.cs b/src/Artemis.UI.Avalonia.Shared/Controls/DeviceVisualizer.cs index 4b5503fcb..d25ce1e17 100644 --- a/src/Artemis.UI.Avalonia.Shared/Controls/DeviceVisualizer.cs +++ b/src/Artemis.UI.Avalonia.Shared/Controls/DeviceVisualizer.cs @@ -51,20 +51,20 @@ namespace Artemis.UI.Avalonia.Shared.Controls // Determine the scale required to fit the desired size of the control double scale = Math.Min(Bounds.Width / _deviceBounds.Width, Bounds.Height / _deviceBounds.Height); - + DrawingContext.PushedState? boundsPush = null; try { // Scale the visualization in the desired bounding box if (Bounds.Width > 0 && Bounds.Height > 0) - boundsPush = drawingContext.PushPostTransform(Matrix.CreateScale(scale, scale)); + boundsPush = drawingContext.PushPreTransform(Matrix.CreateScale(scale, scale)); // Apply device rotation - using DrawingContext.PushedState translationPush = drawingContext.PushPostTransform(Matrix.CreateTranslation(0 - _deviceBounds.Left, 0 - _deviceBounds.Top)); - using DrawingContext.PushedState rotationPush = drawingContext.PushPostTransform(Matrix.CreateRotation(Device.Rotation)); + using DrawingContext.PushedState translationPush = drawingContext.PushPreTransform(Matrix.CreateTranslation(0 - _deviceBounds.Left, 0 - _deviceBounds.Top)); + using DrawingContext.PushedState rotationPush = drawingContext.PushPreTransform(Matrix.CreateRotation(Matrix.ToRadians(Device.Rotation))); // Apply device scale - using DrawingContext.PushedState scalePush = drawingContext.PushPostTransform(Matrix.CreateScale(Device.Scale, Device.Scale)); + using DrawingContext.PushedState scalePush = drawingContext.PushPreTransform(Matrix.CreateScale(Device.Scale, Device.Scale)); // Render device and LED images if (_deviceImage != null) diff --git a/src/Artemis.UI.Avalonia.Shared/Converters/ColorToSKColorConverter.cs b/src/Artemis.UI.Avalonia.Shared/Converters/ColorToSKColorConverter.cs new file mode 100644 index 000000000..728b6cc55 --- /dev/null +++ b/src/Artemis.UI.Avalonia.Shared/Converters/ColorToSKColorConverter.cs @@ -0,0 +1,38 @@ +using System; +using System.Globalization; +using Avalonia.Data.Converters; +using Avalonia.Media; +using FluentAvalonia.UI.Media; +using SkiaSharp; + +namespace Artemis.UI.Avalonia.Shared.Converters +{ + /// + /// Converts into . + /// + public class ColorToSKColorConverter : IValueConverter + { + /// + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is Color avaloniaColor) + return new SKColor(avaloniaColor.R, avaloniaColor.G, avaloniaColor.B, avaloniaColor.A); + if (value is Color2 fluentAvaloniaColor) + return new SKColor(fluentAvaloniaColor.R, fluentAvaloniaColor.G, fluentAvaloniaColor.B, fluentAvaloniaColor.A); + + return SKColor.Empty; + } + + /// + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + Color result = new(0, 0, 0, 0); + if (value is SKColor skColor) + result = new Color(skColor.Alpha, skColor.Red, skColor.Green, skColor.Blue); + + if (targetType == typeof(Color2)) + return (Color2) result; + return result; + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI.Avalonia.Shared/Converters/SKColorToColorConverter.cs b/src/Artemis.UI.Avalonia.Shared/Converters/SKColorToColorConverter.cs new file mode 100644 index 000000000..78968e4f9 --- /dev/null +++ b/src/Artemis.UI.Avalonia.Shared/Converters/SKColorToColorConverter.cs @@ -0,0 +1,38 @@ +using System; +using System.Globalization; +using Avalonia.Data.Converters; +using Avalonia.Media; +using FluentAvalonia.UI.Media; +using SkiaSharp; + +namespace Artemis.UI.Avalonia.Shared.Converters +{ + /// + /// Converts into . + /// + public class SKColorToColorConverter : IValueConverter + { + /// + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + Color result = new(0, 0, 0, 0); + if (value is SKColor skColor) + result = new Color(skColor.Alpha, skColor.Red, skColor.Green, skColor.Blue); + + if (targetType == typeof(Color2)) + return (Color2) result; + return result; + } + + /// + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is Color avaloniaColor) + return new SKColor(avaloniaColor.R, avaloniaColor.G, avaloniaColor.B, avaloniaColor.A); + if (value is Color2 fluentAvaloniaColor) + return new SKColor(fluentAvaloniaColor.R, fluentAvaloniaColor.G, fluentAvaloniaColor.B, fluentAvaloniaColor.A); + + return SKColor.Empty; + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI.Avalonia.Shared/Services/Builders/NotificationBuilder.cs b/src/Artemis.UI.Avalonia.Shared/Services/Builders/NotificationBuilder.cs index 5b3379a9c..ee07690e9 100644 --- a/src/Artemis.UI.Avalonia.Shared/Services/Builders/NotificationBuilder.cs +++ b/src/Artemis.UI.Avalonia.Shared/Services/Builders/NotificationBuilder.cs @@ -10,7 +10,7 @@ namespace Artemis.UI.Avalonia.Shared.Services.Builders { private readonly InfoBar _infoBar; private readonly Window _parent; - private TimeSpan _timeout = TimeSpan.FromSeconds(3); + private TimeSpan _timeout = TimeSpan.FromSeconds(5); public NotificationBuilder(Window parent) { diff --git a/src/Artemis.UI.Avalonia.Shared/Styles/InfoBar.axaml b/src/Artemis.UI.Avalonia.Shared/Styles/InfoBar.axaml index 10bb2febd..e58b3b634 100644 --- a/src/Artemis.UI.Avalonia.Shared/Styles/InfoBar.axaml +++ b/src/Artemis.UI.Avalonia.Shared/Styles/InfoBar.axaml @@ -10,10 +10,19 @@ + \ No newline at end of file diff --git a/src/Artemis.UI.Avalonia/Ninject/Factories/IVMFactory.cs b/src/Artemis.UI.Avalonia/Ninject/Factories/IVMFactory.cs index df19cdc88..d1066fe06 100644 --- a/src/Artemis.UI.Avalonia/Ninject/Factories/IVMFactory.cs +++ b/src/Artemis.UI.Avalonia/Ninject/Factories/IVMFactory.cs @@ -1,4 +1,5 @@ -using Artemis.Core; +using System.Collections.ObjectModel; +using Artemis.Core; using Artemis.UI.Avalonia.Screens.Device.ViewModels; using Artemis.UI.Avalonia.Screens.Root.ViewModels; using Artemis.UI.Avalonia.Screens.SurfaceEditor.ViewModels; @@ -13,6 +14,10 @@ namespace Artemis.UI.Avalonia.Ninject.Factories public interface IDeviceVmFactory : IVmFactory { DevicePropertiesViewModel DevicePropertiesViewModel(ArtemisDevice device); + DevicePropertiesTabViewModel DevicePropertiesTabViewModel(ArtemisDevice device); + DeviceInfoTabViewModel DeviceInfoTabViewModel(ArtemisDevice device); + DeviceLedsTabViewModel DeviceLedsTabViewModel(ArtemisDevice device, ObservableCollection selectedLeds); + InputMappingsTabViewModel InputMappingsTabViewModel(ArtemisDevice device, ObservableCollection selectedLeds); } public interface ISidebarVmFactory : IVmFactory diff --git a/src/Artemis.UI.Avalonia/Screens/Device/ViewModels/DeviceInfoTabViewModel.cs b/src/Artemis.UI.Avalonia/Screens/Device/ViewModels/DeviceInfoTabViewModel.cs index 0e8ffadb6..0e065f8be 100644 --- a/src/Artemis.UI.Avalonia/Screens/Device/ViewModels/DeviceInfoTabViewModel.cs +++ b/src/Artemis.UI.Avalonia/Screens/Device/ViewModels/DeviceInfoTabViewModel.cs @@ -10,7 +10,7 @@ namespace Artemis.UI.Avalonia.Screens.Device.ViewModels public DeviceInfoTabViewModel(ArtemisDevice device) { Device = device; - DisplayName = "INFO"; + DisplayName = "Info"; DefaultLayoutPath = Device.DeviceProvider.LoadLayout(Device).FilePath; } diff --git a/src/Artemis.UI.Avalonia/Screens/Device/ViewModels/DeviceLedsTabViewModel.cs b/src/Artemis.UI.Avalonia/Screens/Device/ViewModels/DeviceLedsTabViewModel.cs index b2c44ea2f..176ee1819 100644 --- a/src/Artemis.UI.Avalonia/Screens/Device/ViewModels/DeviceLedsTabViewModel.cs +++ b/src/Artemis.UI.Avalonia/Screens/Device/ViewModels/DeviceLedsTabViewModel.cs @@ -11,17 +11,17 @@ namespace Artemis.UI.Avalonia.Screens.Device.ViewModels { public class DeviceLedsTabViewModel : ActivatableViewModelBase { - private readonly DevicePropertiesViewModel _devicePropertiesViewModel; + private readonly ObservableCollection _selectedLeds; - public DeviceLedsTabViewModel(ArtemisDevice device, DevicePropertiesViewModel devicePropertiesViewModel) + public DeviceLedsTabViewModel(ArtemisDevice device, ObservableCollection selectedLeds) { - _devicePropertiesViewModel = devicePropertiesViewModel; + _selectedLeds = selectedLeds; Device = device; - DisplayName = "LEDS"; - LedViewModels = new ObservableCollection(Device.Leds.Select(l => new DeviceLedsTabLedViewModel(l, _devicePropertiesViewModel.SelectedLeds))); + DisplayName = "LEDs"; + LedViewModels = new ObservableCollection(Device.Leds.Select(l => new DeviceLedsTabLedViewModel(l, _selectedLeds))); - this.WhenActivated(disposables => _devicePropertiesViewModel.SelectedLeds.ToObservableChangeSet().Subscribe(_ => UpdateSelectedLeds()).DisposeWith(disposables)); + this.WhenActivated(disposables => _selectedLeds.ToObservableChangeSet().Subscribe(_ => UpdateSelectedLeds()).DisposeWith(disposables)); } public ArtemisDevice Device { get; } diff --git a/src/Artemis.UI.Avalonia/Screens/Device/ViewModels/DevicePropertiesTabViewModel.cs b/src/Artemis.UI.Avalonia/Screens/Device/ViewModels/DevicePropertiesTabViewModel.cs index e3abe2e7d..1d51a69c9 100644 --- a/src/Artemis.UI.Avalonia/Screens/Device/ViewModels/DevicePropertiesTabViewModel.cs +++ b/src/Artemis.UI.Avalonia/Screens/Device/ViewModels/DevicePropertiesTabViewModel.cs @@ -1,11 +1,11 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.ComponentModel; using System.Threading.Tasks; using Artemis.Core; using Artemis.Core.Services; using Artemis.UI.Avalonia.Shared.Services.Builders; using Artemis.UI.Avalonia.Shared.Services.Interfaces; -using FluentAvalonia.UI.Controls; using ReactiveUI; using SkiaSharp; @@ -18,9 +18,9 @@ namespace Artemis.UI.Avalonia.Screens.Device.ViewModels private readonly float _initialBlueScale; private readonly float _initialGreenScale; private readonly float _initialRedScale; + private readonly INotificationService _notificationService; private readonly IRgbService _rgbService; private readonly IWindowService _windowService; - private readonly INotificationService _notificationService; private float _blueScale; private SKColor _currentColor; private bool _displayOnDevices; @@ -31,6 +31,12 @@ namespace Artemis.UI.Avalonia.Screens.Device.ViewModels private int _x; private int _y; +#pragma warning disable CS8618 // Design-time constructor + public DevicePropertiesTabViewModel() + { + } +#pragma warning restore CS8618 + public DevicePropertiesTabViewModel(ArtemisDevice device, ICoreService coreService, IRgbService rgbService, IWindowService windowService, INotificationService notificationService) { _coreService = coreService; @@ -40,7 +46,7 @@ namespace Artemis.UI.Avalonia.Screens.Device.ViewModels _categories = new List(device.Categories); Device = device; - DisplayName = "PROPERTIES"; + DisplayName = "Properties"; X = (int) Device.X; Y = (int) Device.Y; @@ -55,6 +61,11 @@ namespace Artemis.UI.Avalonia.Screens.Device.ViewModels _initialRedScale = Device.RedScale; _initialGreenScale = Device.GreenScale; _initialBlueScale = Device.BlueScale; + + this.WhenAnyValue(x => x.RedScale, x => x.GreenScale, x => x.BlueScale).Subscribe(_ => ApplyScaling()); + + Device.PropertyChanged += DeviceOnPropertyChanged; + _coreService.FrameRendering += OnFrameRendering; } public ArtemisDevice Device { get; } @@ -223,16 +234,16 @@ namespace Artemis.UI.Avalonia.Screens.Device.ViewModels Device.BlueScale = _initialBlueScale; } - protected void OnActivate() + /// + protected override void Dispose(bool disposing) { - _coreService.FrameRendering += OnFrameRendering; - Device.PropertyChanged += DeviceOnPropertyChanged; - } + if (disposing) + { + _coreService.FrameRendering -= OnFrameRendering; + Device.PropertyChanged -= DeviceOnPropertyChanged; + } - protected void OnDeactivate() - { - _coreService.FrameRendering -= OnFrameRendering; - Device.PropertyChanged -= DeviceOnPropertyChanged; + base.Dispose(disposing); } private bool GetCategory(DeviceCategory category) @@ -250,21 +261,19 @@ namespace Artemis.UI.Avalonia.Screens.Device.ViewModels this.RaisePropertyChanged($"Has{category}Category"); } - private void DeviceOnPropertyChanged(object sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == nameof(Device.CustomLayoutPath) || e.PropertyName == nameof(Device.DisableDefaultLayout)) Task.Run(() => _rgbService.ApplyBestDeviceLayout(Device)); - } - - private void OnFrameRendering(object sender, FrameRenderingEventArgs e) + private void OnFrameRendering(object? sender, FrameRenderingEventArgs e) { if (!_displayOnDevices) return; - using SKPaint overlayPaint = new() - { - Color = CurrentColor - }; + using SKPaint overlayPaint = new() {Color = CurrentColor}; e.Canvas.DrawRect(0, 0, e.Canvas.LocalClipBounds.Width, e.Canvas.LocalClipBounds.Height, overlayPaint); } + + private void DeviceOnPropertyChanged(object? sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(Device.CustomLayoutPath) || e.PropertyName == nameof(Device.DisableDefaultLayout)) + Task.Run(() => _rgbService.ApplyBestDeviceLayout(Device)); + } } } \ No newline at end of file diff --git a/src/Artemis.UI.Avalonia/Screens/Device/ViewModels/DevicePropertiesViewModel.cs b/src/Artemis.UI.Avalonia/Screens/Device/ViewModels/DevicePropertiesViewModel.cs index 70c0aad7c..26341477a 100644 --- a/src/Artemis.UI.Avalonia/Screens/Device/ViewModels/DevicePropertiesViewModel.cs +++ b/src/Artemis.UI.Avalonia/Screens/Device/ViewModels/DevicePropertiesViewModel.cs @@ -1,16 +1,28 @@ using System.Collections.ObjectModel; using Artemis.Core; +using Artemis.UI.Avalonia.Ninject.Factories; +using RGB.NET.Core; +using ArtemisLed = Artemis.Core.ArtemisLed; namespace Artemis.UI.Avalonia.Screens.Device.ViewModels { public class DevicePropertiesViewModel : ActivatableViewModelBase { - public DevicePropertiesViewModel(ArtemisDevice device) + public DevicePropertiesViewModel(ArtemisDevice device, IDeviceVmFactory deviceVmFactory) { Device = device; + SelectedLeds = new ObservableCollection(); + Tabs = new ObservableCollection(); + + Tabs.Add(deviceVmFactory.DevicePropertiesTabViewModel(device)); + Tabs.Add(deviceVmFactory.DeviceInfoTabViewModel(device)); + if (Device .DeviceType == RGBDeviceType.Keyboard) + Tabs.Add(deviceVmFactory.InputMappingsTabViewModel(device, SelectedLeds)); + Tabs.Add(deviceVmFactory.DeviceLedsTabViewModel(device, SelectedLeds)); } public ArtemisDevice Device { get; } - public ObservableCollection SelectedLeds { get; } = new(); + public ObservableCollection SelectedLeds { get; } + public ObservableCollection Tabs { get; } } } \ No newline at end of file diff --git a/src/Artemis.UI.Avalonia/Screens/Device/ViewModels/InputMappingsTabViewModel.cs b/src/Artemis.UI.Avalonia/Screens/Device/ViewModels/InputMappingsTabViewModel.cs index 1226f17f7..16e688a11 100644 --- a/src/Artemis.UI.Avalonia/Screens/Device/ViewModels/InputMappingsTabViewModel.cs +++ b/src/Artemis.UI.Avalonia/Screens/Device/ViewModels/InputMappingsTabViewModel.cs @@ -14,17 +14,20 @@ namespace Artemis.UI.Avalonia.Screens.Device.ViewModels { private readonly IRgbService _rgbService; private readonly IInputService _inputService; + private readonly ObservableCollection _selectedLeds; private ArtemisLed _selectedLed; - public InputMappingsTabViewModel(ArtemisDevice device, IRgbService rgbService, IInputService inputService) + public InputMappingsTabViewModel(ArtemisDevice device, ObservableCollection selectedLeds, IRgbService rgbService, IInputService inputService) { if (device.DeviceType != RGBDeviceType.Keyboard) throw new ArtemisUIException("The input mappings tab only supports keyboards"); + _rgbService = rgbService; _inputService = inputService; + _selectedLeds = selectedLeds; Device = device; - DisplayName = "INPUT MAPPINGS"; + DisplayName = "Input Mappings"; InputMappings = new ObservableCollection<(ArtemisLed, ArtemisLed)>(); } diff --git a/src/Artemis.UI.Avalonia/Screens/Device/Views/DeviceInfoTabView.axaml b/src/Artemis.UI.Avalonia/Screens/Device/Views/DeviceInfoTabView.axaml new file mode 100644 index 000000000..7ab1fb957 --- /dev/null +++ b/src/Artemis.UI.Avalonia/Screens/Device/Views/DeviceInfoTabView.axaml @@ -0,0 +1,8 @@ + + Welcome to Avalonia! + diff --git a/src/Artemis.UI.Avalonia/Screens/Device/Views/DeviceInfoTabView.axaml.cs b/src/Artemis.UI.Avalonia/Screens/Device/Views/DeviceInfoTabView.axaml.cs new file mode 100644 index 000000000..704d98805 --- /dev/null +++ b/src/Artemis.UI.Avalonia/Screens/Device/Views/DeviceInfoTabView.axaml.cs @@ -0,0 +1,19 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace Artemis.UI.Avalonia.Screens.Device.Views +{ + public partial class DeviceInfoTabView : UserControl + { + public DeviceInfoTabView() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + } +} diff --git a/src/Artemis.UI.Avalonia/Screens/Device/Views/DeviceLedsTabView.axaml b/src/Artemis.UI.Avalonia/Screens/Device/Views/DeviceLedsTabView.axaml new file mode 100644 index 000000000..1b9e80874 --- /dev/null +++ b/src/Artemis.UI.Avalonia/Screens/Device/Views/DeviceLedsTabView.axaml @@ -0,0 +1,8 @@ + + Welcome to Avalonia! + diff --git a/src/Artemis.UI.Avalonia/Screens/Device/Views/DeviceLedsTabView.axaml.cs b/src/Artemis.UI.Avalonia/Screens/Device/Views/DeviceLedsTabView.axaml.cs new file mode 100644 index 000000000..5c080c933 --- /dev/null +++ b/src/Artemis.UI.Avalonia/Screens/Device/Views/DeviceLedsTabView.axaml.cs @@ -0,0 +1,19 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace Artemis.UI.Avalonia.Screens.Device.Views +{ + public partial class DeviceLedsTabView : UserControl + { + public DeviceLedsTabView() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + } +} diff --git a/src/Artemis.UI.Avalonia/Screens/Device/Views/DevicePropertiesTabView.axaml b/src/Artemis.UI.Avalonia/Screens/Device/Views/DevicePropertiesTabView.axaml new file mode 100644 index 000000000..d185ab91d --- /dev/null +++ b/src/Artemis.UI.Avalonia/Screens/Device/Views/DevicePropertiesTabView.axaml @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + Categories + + + Artemis uses categories to determine where the layers of imported profiles are applied to. + + + You can hover over a category for a more detailed description. + + + + + + + + + + + + + Surface properties + + + X-coordinate + + mm + + Y-coordinate + + mm + + Scale + + times + + Rotation + + deg + + + + + + + + Color calibration + + + + Use the sliders below to adjust the colors of your device so that it matches your other devices. + + + + + + + + + + Layout + + + The device layout is used to determine the position of LEDs and to create the visual representation of the device you see on the left side of this window. + + + + + + Don't load default layout + + + + + + + + + + + + Learn more about layouts on the wiki + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.UI.Avalonia/Screens/Device/Views/DevicePropertiesTabView.axaml.cs b/src/Artemis.UI.Avalonia/Screens/Device/Views/DevicePropertiesTabView.axaml.cs new file mode 100644 index 000000000..a8b8c6e05 --- /dev/null +++ b/src/Artemis.UI.Avalonia/Screens/Device/Views/DevicePropertiesTabView.axaml.cs @@ -0,0 +1,28 @@ +using System.Threading.Tasks; +using Artemis.UI.Avalonia.Screens.Device.ViewModels; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Input; +using Avalonia.Markup.Xaml; +using Avalonia.ReactiveUI; + +namespace Artemis.UI.Avalonia.Screens.Device.Views +{ + public partial class DevicePropertiesTabView : ReactiveUserControl + { + public DevicePropertiesTabView() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + + private void InputElement_OnPointerReleased(object? sender, PointerReleasedEventArgs e) + { + ViewModel?.BrowseCustomLayout(); + } + } +} diff --git a/src/Artemis.UI.Avalonia/Screens/Device/Views/DevicePropertiesView.axaml b/src/Artemis.UI.Avalonia/Screens/Device/Views/DevicePropertiesView.axaml index 62ef30ac7..23c5676a5 100644 --- a/src/Artemis.UI.Avalonia/Screens/Device/Views/DevicePropertiesView.axaml +++ b/src/Artemis.UI.Avalonia/Screens/Device/Views/DevicePropertiesView.axaml @@ -6,13 +6,12 @@ mc:Ignorable="d" d:DesignWidth="1200" d:DesignHeight="800" x:Class="Artemis.UI.Avalonia.Screens.Device.Views.DevicePropertiesView" Title="Artemis | Device Properties" - Width="1200" - Height="800" - ExtendClientAreaToDecorationsHint="True"> - - - - + Width="1250" + Height="900" + ExtendClientAreaToDecorationsHint="True" + Padding="0 32 0 0"> + + @@ -33,7 +32,11 @@ ShowColors="True" Margin="20" /> - + @@ -43,7 +46,7 @@ - + @@ -51,8 +54,8 @@ - - + + diff --git a/src/Artemis.UI.Avalonia/Screens/Device/Views/InputMappingsTabView.axaml b/src/Artemis.UI.Avalonia/Screens/Device/Views/InputMappingsTabView.axaml new file mode 100644 index 000000000..50bbb2dbb --- /dev/null +++ b/src/Artemis.UI.Avalonia/Screens/Device/Views/InputMappingsTabView.axaml @@ -0,0 +1,8 @@ + + Welcome to Avalonia! + diff --git a/src/Artemis.UI.Avalonia/Screens/Device/Views/InputMappingsTabView.axaml.cs b/src/Artemis.UI.Avalonia/Screens/Device/Views/InputMappingsTabView.axaml.cs new file mode 100644 index 000000000..e54cccf45 --- /dev/null +++ b/src/Artemis.UI.Avalonia/Screens/Device/Views/InputMappingsTabView.axaml.cs @@ -0,0 +1,19 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace Artemis.UI.Avalonia.Screens.Device.Views +{ + public partial class InputMappingsTabView : UserControl + { + public InputMappingsTabView() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + } +} diff --git a/src/Artemis.UI.Avalonia/Screens/Workshop/ViewModels/WorkshopViewModel.cs b/src/Artemis.UI.Avalonia/Screens/Workshop/ViewModels/WorkshopViewModel.cs index ac1f19193..b4d5f0e2f 100644 --- a/src/Artemis.UI.Avalonia/Screens/Workshop/ViewModels/WorkshopViewModel.cs +++ b/src/Artemis.UI.Avalonia/Screens/Workshop/ViewModels/WorkshopViewModel.cs @@ -1,12 +1,27 @@ -using ReactiveUI; +using System.Reactive; +using Artemis.UI.Avalonia.Shared.Services.Builders; +using Artemis.UI.Avalonia.Shared.Services.Interfaces; +using ReactiveUI; namespace Artemis.UI.Avalonia.Screens.Workshop.ViewModels { public class WorkshopViewModel : MainScreenViewModel { - public WorkshopViewModel(IScreen hostScreen) : base(hostScreen, "workshop") + private readonly INotificationService _notificationService; + + public WorkshopViewModel(IScreen hostScreen, INotificationService notificationService) : base(hostScreen, "workshop") { + _notificationService = notificationService; + DisplayName = "Workshop"; + ShowNotification = ReactiveCommand.Create(ExecuteShowNotification); + } + + public ReactiveCommand ShowNotification { get; set; } + + private void ExecuteShowNotification(NotificationSeverity severity) + { + _notificationService.CreateNotification().WithTitle("Test title").WithMessage("Test message").WithSeverity(severity).Show(); } } } \ No newline at end of file diff --git a/src/Artemis.UI.Avalonia/Screens/Workshop/Views/WorkshopView.axaml b/src/Artemis.UI.Avalonia/Screens/Workshop/Views/WorkshopView.axaml index da819c6eb..facc02cb6 100644 --- a/src/Artemis.UI.Avalonia/Screens/Workshop/Views/WorkshopView.axaml +++ b/src/Artemis.UI.Avalonia/Screens/Workshop/Views/WorkshopView.axaml @@ -2,7 +2,28 @@ 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:builders="clr-namespace:Artemis.UI.Avalonia.Shared.Services.Builders;assembly=Artemis.UI.Avalonia.Shared" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="Artemis.UI.Avalonia.Screens.Workshop.Views.WorkshopView"> - Workshop!! :3 + + Workshop!! :3 + + + Notification tests + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.UI.Avalonia/Styles/TextBlock.axaml b/src/Artemis.UI.Avalonia/Styles/TextBlock.axaml index 50d958e52..facc8aa6f 100644 --- a/src/Artemis.UI.Avalonia/Styles/TextBlock.axaml +++ b/src/Artemis.UI.Avalonia/Styles/TextBlock.axaml @@ -17,21 +17,27 @@