mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-12 03:48:56 +00:00
Surface - Removed the ArtemisSurface and reworked device loading
This commit is contained in:
1 parent
7ccc9c54fb
commit
056b2bface
50 files changed
+1292
-1506
No files matched your search
@@ -9,12 +9,12 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
{
|
||||
// I hate this about DI, oh well
|
||||
public FolderViewModel(ProfileElement folder,
|
||||
IRgbService rgbService,
|
||||
IProfileEditorService profileEditorService,
|
||||
IDialogService dialogService,
|
||||
IProfileTreeVmFactory profileTreeVmFactory,
|
||||
ILayerBrushService layerBrushService,
|
||||
ISurfaceService surfaceService) :
|
||||
base(folder, profileEditorService, dialogService, profileTreeVmFactory, layerBrushService, surfaceService)
|
||||
ILayerBrushService layerBrushService) :
|
||||
base(folder, rgbService, profileEditorService, dialogService, profileTreeVmFactory, layerBrushService)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -8,12 +8,12 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
public class LayerViewModel : TreeItemViewModel
|
||||
{
|
||||
public LayerViewModel(ProfileElement layer,
|
||||
IRgbService rgbService,
|
||||
IProfileEditorService profileEditorService,
|
||||
IDialogService dialogService,
|
||||
IProfileTreeVmFactory profileTreeVmFactory,
|
||||
ILayerBrushService layerBrushService,
|
||||
ISurfaceService surfaceService) :
|
||||
base(layer, profileEditorService, dialogService, profileTreeVmFactory, layerBrushService, surfaceService)
|
||||
ILayerBrushService layerBrushService) :
|
||||
base(layer, rgbService, profileEditorService, dialogService, profileTreeVmFactory, layerBrushService)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -18,23 +18,23 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
{
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly ILayerBrushService _layerBrushService;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly IProfileTreeVmFactory _profileTreeVmFactory;
|
||||
private readonly ISurfaceService _surfaceService;
|
||||
private ProfileElement _profileElement;
|
||||
|
||||
protected TreeItemViewModel(ProfileElement profileElement,
|
||||
IRgbService rgbService,
|
||||
IProfileEditorService profileEditorService,
|
||||
IDialogService dialogService,
|
||||
IProfileTreeVmFactory profileTreeVmFactory,
|
||||
ILayerBrushService layerBrushService,
|
||||
ISurfaceService surfaceService)
|
||||
ILayerBrushService layerBrushService)
|
||||
{
|
||||
_rgbService = rgbService;
|
||||
_profileEditorService = profileEditorService;
|
||||
_dialogService = dialogService;
|
||||
_profileTreeVmFactory = profileTreeVmFactory;
|
||||
_layerBrushService = layerBrushService;
|
||||
_surfaceService = surfaceService;
|
||||
|
||||
ProfileElement = profileElement;
|
||||
|
||||
@@ -144,7 +144,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
if (brush != null)
|
||||
layer.ChangeLayerBrush(brush);
|
||||
|
||||
layer.AddLeds(_surfaceService.ActiveSurface.Devices.SelectMany(d => d.Leds));
|
||||
layer.AddLeds(_rgbService.EnabledDevices.SelectMany(d => d.Leds));
|
||||
_profileEditorService.UpdateSelectedProfile();
|
||||
_profileEditorService.ChangeSelectedProfileElement(layer);
|
||||
}
|
||||
|
||||
@@ -99,7 +99,10 @@
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
|
||||
<Grid Name="EditorDisplayGrid">
|
||||
<Grid Name="EditorDisplayGrid"
|
||||
shared:SizeObserver.Observe="True"
|
||||
shared:SizeObserver.ObservedHeight="{Binding PanZoomViewModel.CanvasHeight}"
|
||||
shared:SizeObserver.ObservedWidth="{Binding PanZoomViewModel.CanvasWidth}">
|
||||
<Grid.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform ScaleX="{Binding PanZoomViewModel.Zoom}" ScaleY="{Binding PanZoomViewModel.Zoom}" />
|
||||
|
||||
@@ -6,48 +6,48 @@ using System.Windows.Input;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Events;
|
||||
using Artemis.UI.Extensions;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Screens.ProfileEditor.Visualization.Tools;
|
||||
using Artemis.UI.Screens.Shared;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using SkiaSharp;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
{
|
||||
public class ProfileViewModel : Conductor<CanvasViewModel>.Collection.AllActive, IProfileEditorPanelViewModel, IHandle<MainWindowFocusChangedEvent>, IHandle<MainWindowKeyEvent>
|
||||
{
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly ICoreService _coreService;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly IProfileLayerVmFactory _profileLayerVmFactory;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ISurfaceService _surfaceService;
|
||||
private readonly IVisualizationToolVmFactory _visualizationToolVmFactory;
|
||||
|
||||
private int _activeToolIndex;
|
||||
private VisualizationToolViewModel _activeToolViewModel;
|
||||
private PluginSetting<bool> _alwaysApplyDataBindings;
|
||||
private bool _canApplyToLayer;
|
||||
private bool _canSelectEditTool;
|
||||
private BindableCollection<ArtemisDevice> _devices;
|
||||
private BindableCollection<ArtemisLed> _highlightedLeds;
|
||||
private PluginSetting<bool> _highlightSelectedLayer;
|
||||
private PluginSetting<bool> _alwaysApplyDataBindings;
|
||||
private DateTime _lastUpdate;
|
||||
private PanZoomViewModel _panZoomViewModel;
|
||||
private Layer _previousSelectedLayer;
|
||||
private int _previousTool;
|
||||
private DateTime _lastUpdate;
|
||||
|
||||
public ProfileViewModel(IProfileEditorService profileEditorService,
|
||||
IRgbService rgbService,
|
||||
ICoreService coreService,
|
||||
ISurfaceService surfaceService,
|
||||
ISettingsService settingsService,
|
||||
IEventAggregator eventAggregator,
|
||||
IVisualizationToolVmFactory visualizationToolVmFactory,
|
||||
IProfileLayerVmFactory profileLayerVmFactory)
|
||||
{
|
||||
_profileEditorService = profileEditorService;
|
||||
_rgbService = rgbService;
|
||||
_coreService = coreService;
|
||||
_surfaceService = surfaceService;
|
||||
_settingsService = settingsService;
|
||||
_visualizationToolVmFactory = visualizationToolVmFactory;
|
||||
_profileLayerVmFactory = profileLayerVmFactory;
|
||||
@@ -99,25 +99,21 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
{
|
||||
// Remove the tool from the canvas
|
||||
if (_activeToolViewModel != null)
|
||||
{
|
||||
lock (Items)
|
||||
{
|
||||
Items.Remove(_activeToolViewModel);
|
||||
NotifyOfPropertyChange(() => Items);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the new tool
|
||||
SetAndNotify(ref _activeToolViewModel, value);
|
||||
// Add the new tool to the canvas
|
||||
if (_activeToolViewModel != null)
|
||||
{
|
||||
lock (Items)
|
||||
{
|
||||
Items.Add(_activeToolViewModel);
|
||||
NotifyOfPropertyChange(() => Items);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +140,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
Devices = new BindableCollection<ArtemisDevice>();
|
||||
HighlightedLeds = new BindableCollection<ArtemisLed>();
|
||||
|
||||
ApplySurfaceConfiguration(_surfaceService.ActiveSurface);
|
||||
ApplyDevices();
|
||||
ActivateToolByIndex(0);
|
||||
|
||||
ApplyActiveProfile();
|
||||
@@ -156,7 +152,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
_coreService.FrameRendered += OnFrameRendered;
|
||||
|
||||
HighlightSelectedLayer.SettingChanged += HighlightSelectedLayerOnSettingChanged;
|
||||
_surfaceService.ActiveSurfaceConfigurationSelected += OnActiveSurfaceConfigurationSelected;
|
||||
_rgbService.DeviceAdded += RgbServiceOnDevicesModified;
|
||||
_rgbService.DeviceRemoved += RgbServiceOnDevicesModified;
|
||||
_profileEditorService.ProfileSelected += OnProfileSelected;
|
||||
_profileEditorService.ProfileElementSelected += OnProfileElementSelected;
|
||||
_profileEditorService.SelectedProfileElementUpdated += OnSelectedProfileElementUpdated;
|
||||
@@ -168,7 +165,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
{
|
||||
_coreService.FrameRendered -= OnFrameRendered;
|
||||
HighlightSelectedLayer.SettingChanged -= HighlightSelectedLayerOnSettingChanged;
|
||||
_surfaceService.ActiveSurfaceConfigurationSelected -= OnActiveSurfaceConfigurationSelected;
|
||||
_rgbService.DeviceAdded -= RgbServiceOnDevicesModified;
|
||||
_rgbService.DeviceRemoved -= RgbServiceOnDevicesModified;
|
||||
_profileEditorService.ProfileSelected -= OnProfileSelected;
|
||||
_profileEditorService.ProfileElementSelected -= OnProfileElementSelected;
|
||||
_profileEditorService.SelectedProfileElementUpdated -= OnSelectedProfileElementUpdated;
|
||||
@@ -181,9 +179,9 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
base.OnClose();
|
||||
}
|
||||
|
||||
private void OnActiveSurfaceConfigurationSelected(object sender, SurfaceConfigurationEventArgs e)
|
||||
private void RgbServiceOnDevicesModified(object? sender, DeviceEventArgs e)
|
||||
{
|
||||
ApplySurfaceConfiguration(e.Surface);
|
||||
ApplyDevices();
|
||||
}
|
||||
|
||||
private void ApplyActiveProfile()
|
||||
@@ -193,10 +191,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
|
||||
// Add new layers missing a VM
|
||||
foreach (Layer layer in layers)
|
||||
{
|
||||
if (layerViewModels.All(vm => vm.Layer != layer))
|
||||
Items.Add(_profileLayerVmFactory.Create(layer, PanZoomViewModel));
|
||||
}
|
||||
|
||||
// Remove layers that no longer exist
|
||||
IEnumerable<ProfileLayerViewModel> toRemove = layerViewModels.Where(vm => !layers.Contains(vm.Layer));
|
||||
@@ -204,10 +200,10 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
Items.Remove(profileLayerViewModel);
|
||||
}
|
||||
|
||||
private void ApplySurfaceConfiguration(ArtemisSurface surface)
|
||||
private void ApplyDevices()
|
||||
{
|
||||
Devices.Clear();
|
||||
Devices.AddRange(surface.Devices.Where(d => d.IsEnabled).OrderBy(d => d.ZIndex));
|
||||
Devices.AddRange(_rgbService.EnabledDevices.Where(d => d.IsEnabled).OrderBy(d => d.ZIndex));
|
||||
}
|
||||
|
||||
private void UpdateLedsDimStatus()
|
||||
@@ -259,7 +255,15 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
|
||||
public void ResetZoomAndPan()
|
||||
{
|
||||
PanZoomViewModel.Reset();
|
||||
// Create a rect surrounding all devices
|
||||
SKRect rect = new SKRect(
|
||||
Devices.Min(d => d.Rectangle.Left),
|
||||
Devices.Min(d => d.Rectangle.Top),
|
||||
Devices.Max(d => d.Rectangle.Right),
|
||||
Devices.Max(d => d.Rectangle.Bottom)
|
||||
);
|
||||
|
||||
PanZoomViewModel.Reset(rect);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -339,7 +343,9 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
_previousSelectedLayer.Transform.LayerPropertyOnCurrentValueSet += TransformValueChanged;
|
||||
}
|
||||
else
|
||||
{
|
||||
_previousSelectedLayer = null;
|
||||
}
|
||||
|
||||
ApplyActiveProfile();
|
||||
UpdateLedsDimStatus();
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
<StackPanel>
|
||||
<Button Content="Open plugin directory" Command="{s:Action OpenPluginDirectory}" />
|
||||
<Button Content="Open image directory" Command="{s:Action OpenImageDirectory}" />
|
||||
<Button Content="Reload layout" Command="{s:Action ReloadLayout}" />
|
||||
</StackPanel>
|
||||
</materialDesign:PopupBox>
|
||||
</StackPanel>
|
||||
|
||||
@@ -12,12 +12,14 @@ namespace Artemis.UI.Screens.Settings.Debug
|
||||
public class DeviceDebugViewModel : Screen
|
||||
{
|
||||
private readonly IDeviceService _deviceService;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly IDialogService _dialogService;
|
||||
private ArtemisLed _selectedLed;
|
||||
|
||||
public DeviceDebugViewModel(ArtemisDevice device, IDeviceService deviceService, IDialogService dialogService)
|
||||
public DeviceDebugViewModel(ArtemisDevice device, IDeviceService deviceService, IRgbService rgbService, IDialogService dialogService)
|
||||
{
|
||||
_deviceService = deviceService;
|
||||
_rgbService = rgbService;
|
||||
_dialogService = dialogService;
|
||||
Device = device;
|
||||
}
|
||||
@@ -78,6 +80,17 @@ namespace Artemis.UI.Screens.Settings.Debug
|
||||
}
|
||||
}
|
||||
|
||||
public void ReloadLayout()
|
||||
{
|
||||
if (Device.Layout == null)
|
||||
_rgbService.ApplyBestDeviceLayout(Device);
|
||||
else
|
||||
{
|
||||
Device.Layout.ReloadFromDisk();
|
||||
_rgbService.ApplyDeviceLayout(Device, Device.Layout);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// ReSharper restore UnusedMember.Global
|
||||
|
||||
@@ -11,15 +11,15 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
|
||||
public class DeviceSettingsTabViewModel : Conductor<DeviceSettingsViewModel>.Collection.AllActive
|
||||
{
|
||||
private readonly ISettingsVmFactory _settingsVmFactory;
|
||||
private readonly ISurfaceService _surfaceService;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly IDialogService _dialogService;
|
||||
private bool _confirmedDisable;
|
||||
|
||||
public DeviceSettingsTabViewModel(ISurfaceService surfaceService, IDialogService dialogService, ISettingsVmFactory settingsVmFactory)
|
||||
public DeviceSettingsTabViewModel(IRgbService rgbService, IDialogService dialogService, ISettingsVmFactory settingsVmFactory)
|
||||
{
|
||||
DisplayName = "DEVICES";
|
||||
|
||||
_surfaceService = surfaceService;
|
||||
_rgbService = rgbService;
|
||||
_dialogService = dialogService;
|
||||
_settingsVmFactory = settingsVmFactory;
|
||||
}
|
||||
@@ -32,7 +32,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
|
||||
Items.Clear();
|
||||
await Task.Delay(200);
|
||||
|
||||
List<DeviceSettingsViewModel> instances = _surfaceService.ActiveSurface.Devices.Select(d => _settingsVmFactory.CreateDeviceSettingsViewModel(d)).ToList();
|
||||
List<DeviceSettingsViewModel> instances = _rgbService.Devices.Select(d => _settingsVmFactory.CreateDeviceSettingsViewModel(d)).ToList();
|
||||
foreach (DeviceSettingsViewModel deviceSettingsViewModel in instances)
|
||||
Items.Add(deviceSettingsViewModel);
|
||||
});
|
||||
|
||||
@@ -6,7 +6,6 @@ using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Screens.SurfaceEditor.Dialogs;
|
||||
using Artemis.UI.Screens.SurfaceEditor.Visualization;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Humanizer;
|
||||
using RGB.NET.Core;
|
||||
@@ -17,9 +16,9 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
|
||||
public class DeviceSettingsViewModel : Screen
|
||||
{
|
||||
private readonly IDeviceDebugVmFactory _deviceDebugVmFactory;
|
||||
private readonly ISurfaceService _surfaceService;
|
||||
private readonly IDeviceService _deviceService;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly IWindowManager _windowManager;
|
||||
|
||||
public DeviceSettingsViewModel(ArtemisDevice device,
|
||||
@@ -27,13 +26,13 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
|
||||
IDialogService dialogService,
|
||||
IWindowManager windowManager,
|
||||
IDeviceDebugVmFactory deviceDebugVmFactory,
|
||||
ISurfaceService surfaceService)
|
||||
IRgbService rgbService)
|
||||
{
|
||||
_deviceService = deviceService;
|
||||
_dialogService = dialogService;
|
||||
_windowManager = windowManager;
|
||||
_deviceDebugVmFactory = deviceDebugVmFactory;
|
||||
_surfaceService = surfaceService;
|
||||
_rgbService = rgbService;
|
||||
Device = device;
|
||||
|
||||
Type = Device.RgbDevice.DeviceInfo.DeviceType.ToString().Humanize();
|
||||
@@ -53,26 +52,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
|
||||
public bool IsDeviceEnabled
|
||||
{
|
||||
get => Device.IsEnabled;
|
||||
set
|
||||
{
|
||||
Task.Run(() => UpdateIsDeviceEnabled(value));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private async Task UpdateIsDeviceEnabled(bool value)
|
||||
{
|
||||
if (!value)
|
||||
value = !await ((DeviceSettingsTabViewModel)Parent).ShowDeviceDisableDialog();
|
||||
|
||||
Device.IsEnabled = value;
|
||||
NotifyOfPropertyChange(nameof(IsDeviceEnabled));
|
||||
SaveDevice();
|
||||
}
|
||||
|
||||
private void SaveDevice()
|
||||
{
|
||||
_surfaceService.UpdateSurfaceConfiguration(_surfaceService.ActiveSurface, true);
|
||||
set { Task.Run(() => UpdateIsDeviceEnabled(value)); }
|
||||
}
|
||||
|
||||
public void IdentifyDevice()
|
||||
@@ -104,7 +84,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
|
||||
);
|
||||
|
||||
if ((bool) madeChanges)
|
||||
_surfaceService.UpdateSurfaceConfiguration(_surfaceService.ActiveSurface, true);
|
||||
_rgbService.SaveDevice(Device);
|
||||
}
|
||||
|
||||
public async Task ViewProperties()
|
||||
@@ -114,7 +94,25 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
|
||||
);
|
||||
|
||||
if ((bool) madeChanges)
|
||||
_surfaceService.UpdateSurfaceConfiguration(_surfaceService.ActiveSurface, true);
|
||||
_rgbService.SaveDevice(Device);
|
||||
}
|
||||
|
||||
private async Task UpdateIsDeviceEnabled(bool value)
|
||||
{
|
||||
if (!value)
|
||||
value = !await ((DeviceSettingsTabViewModel) Parent).ShowDeviceDisableDialog();
|
||||
|
||||
if (value)
|
||||
_rgbService.EnableDevice(Device);
|
||||
else
|
||||
_rgbService.DisableDevice(Device);
|
||||
NotifyOfPropertyChange(nameof(IsDeviceEnabled));
|
||||
SaveDevice();
|
||||
}
|
||||
|
||||
private void SaveDevice()
|
||||
{
|
||||
_rgbService.SaveDevice(Device);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using Artemis.UI.Extensions;
|
||||
using RGB.NET.Core;
|
||||
using SkiaSharp;
|
||||
using Stylet;
|
||||
using Point = System.Windows.Point;
|
||||
|
||||
@@ -144,6 +145,13 @@ namespace Artemis.UI.Screens.Shared
|
||||
PanY = 0;
|
||||
}
|
||||
|
||||
public void Reset(SKRect rect)
|
||||
{
|
||||
Zoom = Math.Min(CanvasWidth / rect.Width, CanvasHeight / rect.Height);
|
||||
PanX = rect.Left * -1 * Zoom;
|
||||
PanY = rect.Top * -1 * Zoom;
|
||||
}
|
||||
|
||||
public Rect TransformContainingRect(Rectangle rect)
|
||||
{
|
||||
return TransformContainingRect(rect.ToWindowsRect(1));
|
||||
@@ -168,11 +176,15 @@ namespace Artemis.UI.Screens.Shared
|
||||
|
||||
private void SetZoomFromPercentage(double value)
|
||||
{
|
||||
double newZoom = value / 100;
|
||||
// Focus towards the center of the zoomed area
|
||||
PanX += newZoom - Zoom;
|
||||
PanY += newZoom - Zoom;
|
||||
Point relative = new((PanX * -1 + CanvasWidth / 2) / Zoom, (PanY * -1 + CanvasHeight / 2) / Zoom);
|
||||
double absoluteX = relative.X * Zoom + PanX;
|
||||
double absoluteY = relative.Y * Zoom + PanY;
|
||||
|
||||
Zoom = value / 100;
|
||||
|
||||
// Focus towards the center of the zoomed area
|
||||
PanX = absoluteX - relative.X * Zoom;
|
||||
PanY = absoluteY - relative.Y * Zoom;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Style="{StaticResource MaterialDesignBody1TextBlock}" TextWrapping="Wrap">
|
||||
Devices are supported through the use of device providers. <LineBreak />
|
||||
EnabledDevices are supported through the use of device providers. <LineBreak />
|
||||
In the list below you can enable device providers for each brand you own by checking <Run Text="Feature enabled" FontWeight="Bold" />.
|
||||
</TextBlock>
|
||||
|
||||
|
||||
@@ -5,23 +5,23 @@ namespace Artemis.UI.Screens.StartupWizard.Steps
|
||||
{
|
||||
public class LayoutStepViewModel : Screen
|
||||
{
|
||||
private readonly ISurfaceService _surfaceService;
|
||||
private readonly IRgbService _rgbService;
|
||||
|
||||
public LayoutStepViewModel(ISurfaceService surfaceService)
|
||||
public LayoutStepViewModel(IRgbService rgbService)
|
||||
{
|
||||
_surfaceService = surfaceService;
|
||||
_rgbService = rgbService;
|
||||
}
|
||||
|
||||
public void ApplyLeftHandedPreset()
|
||||
{
|
||||
_surfaceService.AutoArrange();
|
||||
_rgbService.AutoArrangeDevices();
|
||||
StartupWizardViewModel startupWizardViewModel = (StartupWizardViewModel) Parent;
|
||||
startupWizardViewModel.Continue();
|
||||
}
|
||||
|
||||
public void ApplyRightHandedPreset()
|
||||
{
|
||||
_surfaceService.AutoArrange();
|
||||
_rgbService.AutoArrangeDevices();
|
||||
StartupWizardViewModel startupWizardViewModel = (StartupWizardViewModel) Parent;
|
||||
startupWizardViewModel.Continue();
|
||||
}
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:s="https://github.com/canton7/Stylet"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:Converters="clr-namespace:Artemis.UI.Converters"
|
||||
xmlns:models="clr-namespace:Artemis.Core;assembly=Artemis.Core"
|
||||
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||
xmlns:local="clr-namespace:Artemis.UI.Screens.SurfaceEditor"
|
||||
x:Class="Artemis.UI.Screens.SurfaceEditor.SurfaceEditorView"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="600" d:DesignWidth="600">
|
||||
d:DesignHeight="600" d:DesignWidth="600"
|
||||
d:DataContext="{d:DesignInstance {x:Type local:SurfaceEditorViewModel}}">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
@@ -18,7 +19,6 @@
|
||||
<ResourceDictionary
|
||||
Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.PopupBox.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<Converters:InverseBooleanConverter x:Key="InverseBooleanConverter" />
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid Margin="16">
|
||||
@@ -113,14 +113,17 @@
|
||||
</EventTrigger>
|
||||
</Grid.Triggers>
|
||||
|
||||
<Grid x:Name="EditorDisplayGrid">
|
||||
<Grid x:Name="EditorDisplayGrid"
|
||||
shared:SizeObserver.Observe="True"
|
||||
shared:SizeObserver.ObservedHeight="{Binding PanZoomViewModel.CanvasHeight, Mode=TwoWay}"
|
||||
shared:SizeObserver.ObservedWidth="{Binding PanZoomViewModel.CanvasWidth, Mode=TwoWay}">
|
||||
<Grid.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform ScaleX="{Binding PanZoomViewModel.Zoom}" ScaleY="{Binding PanZoomViewModel.Zoom}" />
|
||||
<TranslateTransform X="{Binding PanZoomViewModel.PanX}" Y="{Binding PanZoomViewModel.PanY}" />
|
||||
</TransformGroup>
|
||||
</Grid.RenderTransform>
|
||||
<ItemsControl ItemsSource="{Binding Devices}">
|
||||
<ItemsControl ItemsSource="{Binding SurfaceDeviceViewModels}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<Canvas />
|
||||
@@ -137,28 +140,28 @@
|
||||
<ContentControl s:View.Model="{Binding}">
|
||||
<ContentControl.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="Identify" Command="{s:Action IdentifyDevice}" CommandParameter="{Binding}">
|
||||
<MenuItem Header="Identify" Command="{s:Action IdentifyDevice}" CommandParameter="{Binding Device}">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="AlarmLight" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<Separator />
|
||||
<MenuItem Header="Bring to Front" Command="{s:Action BringToFront}" CommandParameter="{Binding}">
|
||||
<MenuItem Header="Bring to Front" Command="{s:Action BringToFront}" CommandParameter="{Binding Device}">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="ArrangeBringToFront" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Bring Forward" Command="{s:Action BringForward}" CommandParameter="{Binding}">
|
||||
<MenuItem Header="Bring Forward" Command="{s:Action BringForward}" CommandParameter="{Binding Device}">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="ArrangeBringForward" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Send to Back" Command="{s:Action SendToBack}" CommandParameter="{Binding}">
|
||||
<MenuItem Header="Send to Back" Command="{s:Action SendToBack}" CommandParameter="{Binding Device}">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="ArrangeSendToBack" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Send Backward" Command="{s:Action SendBackward}" CommandParameter="{Binding}">
|
||||
<MenuItem Header="Send Backward" Command="{s:Action SendBackward}" CommandParameter="{Binding Device}">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="ArrangeSendBackward" />
|
||||
</MenuItem.Icon>
|
||||
@@ -167,14 +170,14 @@
|
||||
<!-- Stylet can't disable it for us here, do it ourselves -->
|
||||
<MenuItem Header="Identify input"
|
||||
Command="{s:Action DetectInput}"
|
||||
CommandParameter="{Binding}"
|
||||
CommandParameter="{Binding Device}"
|
||||
IsEnabled="{Binding CanDetectInput}"
|
||||
ToolTip="Teach Artemis which keypresses and/or button presses belong to this device">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="GestureDoubleTap" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="View properties" Command="{s:Action ViewProperties}" CommandParameter="{Binding}">
|
||||
<MenuItem Header="View properties" Command="{s:Action ViewProperties}" CommandParameter="{Binding Device}">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="Gear" />
|
||||
</MenuItem.Icon>
|
||||
@@ -236,29 +239,65 @@
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<ListBox Grid.Row="0" HorizontalContentAlignment="Stretch" ItemsSource="{Binding SurfaceConfigurations}" SelectedItem="{Binding SelectedSurface}">
|
||||
<ListBox.Resources>
|
||||
<DataTemplate DataType="{x:Type models:ArtemisSurface}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{Binding Name}" ToolTip="{Binding Name}"
|
||||
HorizontalAlignment="Left" VerticalAlignment="Center" />
|
||||
<Button Grid.Column="1"
|
||||
Command="{s:Action DeleteSurfaceConfiguration}"
|
||||
CommandParameter="{Binding}"
|
||||
IsEnabled="{Binding IsActive, Converter={StaticResource InverseBooleanConverter}}"
|
||||
Style="{StaticResource MaterialDesignIconForegroundButton}"
|
||||
ToolTip="Delete layout configuration"
|
||||
HorizontalAlignment="Right">
|
||||
<materialDesign:PackIcon Kind="Trashcan" />
|
||||
</Button>
|
||||
</Grid>
|
||||
<ListBox Grid.Row="0" HorizontalContentAlignment="Stretch" ItemsSource="{Binding ListDeviceViewModels}" SelectionMode="Multiple">
|
||||
<ListBox.ItemContainerStyle>
|
||||
<Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource {x:Type ListBoxItem}}">
|
||||
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
|
||||
</Style>
|
||||
|
||||
</ListBox.ItemContainerStyle>
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False">
|
||||
<ContentControl.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="Identify" Command="{s:Action IdentifyDevice}" CommandParameter="{Binding Device}">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="AlarmLight" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<Separator />
|
||||
<MenuItem Header="Bring to Front" Command="{s:Action BringToFront}" CommandParameter="{Binding Device}">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="ArrangeBringToFront" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Bring Forward" Command="{s:Action BringForward}" CommandParameter="{Binding Device}">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="ArrangeBringForward" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Send to Back" Command="{s:Action SendToBack}" CommandParameter="{Binding Device}">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="ArrangeSendToBack" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Send Backward" Command="{s:Action SendBackward}" CommandParameter="{Binding Device}">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="ArrangeSendBackward" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<Separator />
|
||||
<!-- Stylet can't disable it for us here, do it ourselves -->
|
||||
<MenuItem Header="Identify input"
|
||||
Command="{s:Action DetectInput}"
|
||||
CommandParameter="{Binding Device}"
|
||||
IsEnabled="{Binding CanDetectInput}"
|
||||
ToolTip="Teach Artemis which keypresses and/or button presses belong to this device">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="GestureDoubleTap" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="View properties" Command="{s:Action ViewProperties}" CommandParameter="{Binding Device}">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="Gear" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</ContentControl.ContextMenu>
|
||||
</ContentControl>
|
||||
</DataTemplate>
|
||||
</ListBox.Resources>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
<Button Grid.Row="0"
|
||||
Style="{StaticResource MaterialDesignFloatingActionButton}"
|
||||
|
||||
@@ -10,6 +10,7 @@ using System.Windows.Media;
|
||||
using System.Windows.Navigation;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Extensions;
|
||||
using Artemis.UI.Screens.Shared;
|
||||
using Artemis.UI.Screens.SurfaceEditor.Dialogs;
|
||||
using Artemis.UI.Screens.SurfaceEditor.Visualization;
|
||||
@@ -27,49 +28,34 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ISurfaceService _surfaceService;
|
||||
private Cursor _cursor;
|
||||
private ObservableCollection<SurfaceDeviceViewModel> _devices;
|
||||
private PanZoomViewModel _panZoomViewModel;
|
||||
private ArtemisSurface _selectedSurface;
|
||||
private RectangleGeometry _selectionRectangle;
|
||||
private ObservableCollection<ArtemisSurface> _surfaceConfigurations;
|
||||
private PluginSetting<GridLength> _surfaceListWidth;
|
||||
|
||||
public SurfaceEditorViewModel(IRgbService rgbService,
|
||||
ISurfaceService surfaceService,
|
||||
IDialogService dialogService,
|
||||
ISettingsService settingsService,
|
||||
IDeviceService deviceService,
|
||||
IInputService inputService)
|
||||
{
|
||||
DisplayName = "Surface Editor";
|
||||
|
||||
Devices = new ObservableCollection<SurfaceDeviceViewModel>();
|
||||
SurfaceConfigurations = new ObservableCollection<ArtemisSurface>();
|
||||
SelectionRectangle = new RectangleGeometry();
|
||||
PanZoomViewModel = new PanZoomViewModel();
|
||||
Cursor = null;
|
||||
|
||||
SurfaceDeviceViewModels = new BindableCollection<SurfaceDeviceViewModel>();
|
||||
ListDeviceViewModels = new BindableCollection<ListDeviceViewModel>();
|
||||
|
||||
_rgbService = rgbService;
|
||||
_surfaceService = surfaceService;
|
||||
_dialogService = dialogService;
|
||||
_settingsService = settingsService;
|
||||
_deviceService = deviceService;
|
||||
_inputService = inputService;
|
||||
}
|
||||
|
||||
public ObservableCollection<SurfaceDeviceViewModel> Devices
|
||||
{
|
||||
get => _devices;
|
||||
set => SetAndNotify(ref _devices, value);
|
||||
}
|
||||
|
||||
public ObservableCollection<ArtemisSurface> SurfaceConfigurations
|
||||
{
|
||||
get => _surfaceConfigurations;
|
||||
set => SetAndNotify(ref _surfaceConfigurations, value);
|
||||
}
|
||||
public BindableCollection<SurfaceDeviceViewModel> SurfaceDeviceViewModels { get; }
|
||||
public BindableCollection<ListDeviceViewModel> ListDeviceViewModels { get; }
|
||||
|
||||
public RectangleGeometry SelectionRectangle
|
||||
{
|
||||
@@ -95,26 +81,6 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
set => SetAndNotify(ref _cursor, value);
|
||||
}
|
||||
|
||||
public ArtemisSurface SelectedSurface
|
||||
{
|
||||
get => _selectedSurface;
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
SetAndNotify(ref _selectedSurface, value);
|
||||
ApplySelectedSurfaceConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
public ArtemisSurface CreateSurfaceConfiguration(string name)
|
||||
{
|
||||
ArtemisSurface config = _surfaceService.CreateSurfaceConfiguration(name);
|
||||
Execute.PostToUIThread(() => SurfaceConfigurations.Add(config));
|
||||
return config;
|
||||
}
|
||||
|
||||
public void OpenHyperlink(object sender, RequestNavigateEventArgs e)
|
||||
{
|
||||
Core.Utilities.OpenUrl(e.Uri.AbsoluteUri);
|
||||
@@ -126,7 +92,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
if (!confirmed)
|
||||
return;
|
||||
|
||||
_surfaceService.AutoArrange();
|
||||
_rgbService.AutoArrangeDevices();
|
||||
}
|
||||
|
||||
private void LoadWorkspaceSettings()
|
||||
@@ -139,184 +105,112 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
SurfaceListWidth.Save();
|
||||
}
|
||||
|
||||
private void LoadSurfaceConfigurations()
|
||||
{
|
||||
// Get surface configs
|
||||
List<ArtemisSurface> configs = _surfaceService.SurfaceConfigurations.ToList();
|
||||
|
||||
// Get the active config, if empty, create a default config
|
||||
ArtemisSurface activeConfig = _surfaceService.ActiveSurface;
|
||||
if (activeConfig == null)
|
||||
{
|
||||
activeConfig = CreateSurfaceConfiguration("Default");
|
||||
configs.Add(activeConfig);
|
||||
_surfaceService.SetActiveSurfaceConfiguration(activeConfig);
|
||||
}
|
||||
|
||||
Execute.PostToUIThread(() =>
|
||||
{
|
||||
// Populate the UI collection
|
||||
SurfaceConfigurations.Clear();
|
||||
foreach (ArtemisSurface surfaceConfiguration in configs)
|
||||
SurfaceConfigurations.Add(surfaceConfiguration);
|
||||
|
||||
// Set the active config
|
||||
SelectedSurface = activeConfig;
|
||||
});
|
||||
}
|
||||
|
||||
private void ApplySelectedSurfaceConfiguration()
|
||||
{
|
||||
// Make sure all devices have an up-to-date VM
|
||||
Execute.PostToUIThread(() =>
|
||||
{
|
||||
lock (Devices)
|
||||
{
|
||||
List<SurfaceDeviceViewModel> existing = Devices.ToList();
|
||||
List<SurfaceDeviceViewModel> deviceViewModels = new();
|
||||
|
||||
// Add missing/update existing
|
||||
foreach (ArtemisDevice surfaceDeviceConfiguration in SelectedSurface.Devices.Where(d => d.IsEnabled).OrderBy(d => d.ZIndex).ToList())
|
||||
{
|
||||
// Create VMs for missing devices
|
||||
SurfaceDeviceViewModel viewModel = existing.FirstOrDefault(vm => vm.Device.RgbDevice == surfaceDeviceConfiguration.RgbDevice);
|
||||
if (viewModel == null)
|
||||
viewModel = new SurfaceDeviceViewModel(surfaceDeviceConfiguration);
|
||||
// Update existing devices
|
||||
else
|
||||
viewModel.Device = surfaceDeviceConfiguration;
|
||||
|
||||
// Add the viewModel to the list of VMs we want to keep
|
||||
deviceViewModels.Add(viewModel);
|
||||
}
|
||||
|
||||
Devices = new ObservableCollection<SurfaceDeviceViewModel>(deviceViewModels);
|
||||
}
|
||||
});
|
||||
|
||||
_surfaceService.SetActiveSurfaceConfiguration(SelectedSurface);
|
||||
}
|
||||
|
||||
#region Overrides of Screen
|
||||
|
||||
protected override void OnInitialActivate()
|
||||
{
|
||||
LoadSurfaceConfigurations();
|
||||
LoadWorkspaceSettings();
|
||||
SurfaceDeviceViewModels.AddRange(_rgbService.EnabledDevices.OrderBy(d => d.ZIndex).Select(d => new SurfaceDeviceViewModel(d, _rgbService)));
|
||||
ListDeviceViewModels.AddRange(_rgbService.EnabledDevices.OrderBy(d => d.ZIndex * -1).Select(d => new ListDeviceViewModel(d)));
|
||||
base.OnInitialActivate();
|
||||
}
|
||||
|
||||
protected override void OnClose()
|
||||
{
|
||||
SaveWorkspaceSettings();
|
||||
SurfaceDeviceViewModels.Clear();
|
||||
ListDeviceViewModels.Clear();
|
||||
base.OnClose();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Configuration management
|
||||
|
||||
public async Task DeleteSurfaceConfiguration(ArtemisSurface surface)
|
||||
{
|
||||
bool result = await _dialogService.ShowConfirmDialogAt(
|
||||
"SurfaceListDialogHost",
|
||||
"Delete surface configuration",
|
||||
"Are you sure you want to delete\nthis surface configuration?"
|
||||
);
|
||||
if (result)
|
||||
{
|
||||
SurfaceConfigurations.Remove(surface);
|
||||
_surfaceService.DeleteSurfaceConfiguration(surface);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task AddSurfaceConfiguration()
|
||||
{
|
||||
object result = await _dialogService.ShowDialogAt<SurfaceCreateViewModel>("SurfaceListDialogHost");
|
||||
if (result is string name)
|
||||
CreateSurfaceConfiguration(name);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Context menu actions
|
||||
|
||||
public void IdentifyDevice(SurfaceDeviceViewModel surfaceDeviceViewModel)
|
||||
public void IdentifyDevice(ArtemisDevice device)
|
||||
{
|
||||
_deviceService.IdentifyDevice(surfaceDeviceViewModel.Device);
|
||||
_deviceService.IdentifyDevice(device);
|
||||
}
|
||||
|
||||
public void BringToFront(SurfaceDeviceViewModel surfaceDeviceViewModel)
|
||||
public void BringToFront(ArtemisDevice device)
|
||||
{
|
||||
Devices.Move(Devices.IndexOf(surfaceDeviceViewModel), Devices.Count - 1);
|
||||
for (int i = 0; i < Devices.Count; i++)
|
||||
SurfaceDeviceViewModel surfaceDeviceViewModel = SurfaceDeviceViewModels.First(d => d.Device == device);
|
||||
SurfaceDeviceViewModels.Move(SurfaceDeviceViewModels.IndexOf(surfaceDeviceViewModel), SurfaceDeviceViewModels.Count - 1);
|
||||
for (int i = 0; i < SurfaceDeviceViewModels.Count; i++)
|
||||
{
|
||||
SurfaceDeviceViewModel deviceViewModel = Devices[i];
|
||||
SurfaceDeviceViewModel deviceViewModel = SurfaceDeviceViewModels[i];
|
||||
deviceViewModel.Device.ZIndex = i + 1;
|
||||
}
|
||||
ListDeviceViewModels.Sort(l => l.Device.ZIndex * -1);
|
||||
|
||||
_surfaceService.UpdateSurfaceConfiguration(SelectedSurface, true);
|
||||
_rgbService.SaveDevices();
|
||||
}
|
||||
|
||||
public void BringForward(SurfaceDeviceViewModel surfaceDeviceViewModel)
|
||||
public void BringForward(ArtemisDevice device)
|
||||
{
|
||||
int currentIndex = Devices.IndexOf(surfaceDeviceViewModel);
|
||||
int newIndex = Math.Min(currentIndex + 1, Devices.Count - 1);
|
||||
Devices.Move(currentIndex, newIndex);
|
||||
SurfaceDeviceViewModel surfaceDeviceViewModel = SurfaceDeviceViewModels.First(d => d.Device == device);
|
||||
int currentIndex = SurfaceDeviceViewModels.IndexOf(surfaceDeviceViewModel);
|
||||
int newIndex = Math.Min(currentIndex + 1, SurfaceDeviceViewModels.Count - 1);
|
||||
SurfaceDeviceViewModels.Move(currentIndex, newIndex);
|
||||
|
||||
for (int i = 0; i < Devices.Count; i++)
|
||||
for (int i = 0; i < SurfaceDeviceViewModels.Count; i++)
|
||||
{
|
||||
SurfaceDeviceViewModel deviceViewModel = Devices[i];
|
||||
SurfaceDeviceViewModel deviceViewModel = SurfaceDeviceViewModels[i];
|
||||
deviceViewModel.Device.ZIndex = i + 1;
|
||||
}
|
||||
ListDeviceViewModels.Sort(l => l.Device.ZIndex * -1);
|
||||
|
||||
_surfaceService.UpdateSurfaceConfiguration(SelectedSurface, true);
|
||||
_rgbService.SaveDevices();
|
||||
}
|
||||
|
||||
public void SendToBack(SurfaceDeviceViewModel surfaceDeviceViewModel)
|
||||
public void SendToBack(ArtemisDevice device)
|
||||
{
|
||||
Devices.Move(Devices.IndexOf(surfaceDeviceViewModel), 0);
|
||||
for (int i = 0; i < Devices.Count; i++)
|
||||
SurfaceDeviceViewModel surfaceDeviceViewModel = SurfaceDeviceViewModels.First(d => d.Device == device);
|
||||
SurfaceDeviceViewModels.Move(SurfaceDeviceViewModels.IndexOf(surfaceDeviceViewModel), 0);
|
||||
for (int i = 0; i < SurfaceDeviceViewModels.Count; i++)
|
||||
{
|
||||
SurfaceDeviceViewModel deviceViewModel = Devices[i];
|
||||
SurfaceDeviceViewModel deviceViewModel = SurfaceDeviceViewModels[i];
|
||||
deviceViewModel.Device.ZIndex = i + 1;
|
||||
}
|
||||
ListDeviceViewModels.Sort(l => l.Device.ZIndex * -1);
|
||||
|
||||
_surfaceService.UpdateSurfaceConfiguration(SelectedSurface, true);
|
||||
_rgbService.SaveDevices();
|
||||
}
|
||||
|
||||
public void SendBackward(SurfaceDeviceViewModel surfaceDeviceViewModel)
|
||||
public void SendBackward(ArtemisDevice device)
|
||||
{
|
||||
int currentIndex = Devices.IndexOf(surfaceDeviceViewModel);
|
||||
SurfaceDeviceViewModel surfaceDeviceViewModel = SurfaceDeviceViewModels.First(d => d.Device == device);
|
||||
int currentIndex = SurfaceDeviceViewModels.IndexOf(surfaceDeviceViewModel);
|
||||
int newIndex = Math.Max(currentIndex - 1, 0);
|
||||
Devices.Move(currentIndex, newIndex);
|
||||
for (int i = 0; i < Devices.Count; i++)
|
||||
SurfaceDeviceViewModels.Move(currentIndex, newIndex);
|
||||
for (int i = 0; i < SurfaceDeviceViewModels.Count; i++)
|
||||
{
|
||||
SurfaceDeviceViewModel deviceViewModel = Devices[i];
|
||||
SurfaceDeviceViewModel deviceViewModel = SurfaceDeviceViewModels[i];
|
||||
deviceViewModel.Device.ZIndex = i + 1;
|
||||
}
|
||||
ListDeviceViewModels.Sort(l => l.Device.ZIndex * -1);
|
||||
|
||||
_surfaceService.UpdateSurfaceConfiguration(SelectedSurface, true);
|
||||
_rgbService.SaveDevices();
|
||||
}
|
||||
|
||||
public async Task ViewProperties(SurfaceDeviceViewModel surfaceDeviceViewModel)
|
||||
public async Task ViewProperties(ArtemisDevice device)
|
||||
{
|
||||
object madeChanges = await _dialogService.ShowDialog<SurfaceDeviceConfigViewModel>(
|
||||
new Dictionary<string, object> {{"device", surfaceDeviceViewModel.Device}}
|
||||
new Dictionary<string, object> {{"device", device}}
|
||||
);
|
||||
|
||||
if ((bool) madeChanges)
|
||||
_surfaceService.UpdateSurfaceConfiguration(SelectedSurface, true);
|
||||
_rgbService.SaveDevice(device);
|
||||
}
|
||||
|
||||
public async Task DetectInput(SurfaceDeviceViewModel surfaceDeviceViewModel)
|
||||
public async Task DetectInput(ArtemisDevice device)
|
||||
{
|
||||
object madeChanges = await _dialogService.ShowDialog<SurfaceDeviceDetectInputViewModel>(
|
||||
new Dictionary<string, object> {{"device", surfaceDeviceViewModel.Device}}
|
||||
new Dictionary<string, object> {{"device", device}}
|
||||
);
|
||||
|
||||
if ((bool) madeChanges)
|
||||
_surfaceService.UpdateSurfaceConfiguration(SelectedSurface, true);
|
||||
_rgbService.SaveDevice(device);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -377,13 +271,15 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
if (device.SelectionStatus != SelectionStatus.Selected)
|
||||
{
|
||||
if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
|
||||
foreach (SurfaceDeviceViewModel others in Devices)
|
||||
{
|
||||
foreach (SurfaceDeviceViewModel others in SurfaceDeviceViewModels)
|
||||
others.SelectionStatus = SelectionStatus.None;
|
||||
}
|
||||
|
||||
device.SelectionStatus = SelectionStatus.Selected;
|
||||
}
|
||||
|
||||
foreach (SurfaceDeviceViewModel selectedDevice in Devices.Where(d => d.SelectionStatus == SelectionStatus.Selected))
|
||||
foreach (SurfaceDeviceViewModel selectedDevice in SurfaceDeviceViewModels.Where(d => d.SelectionStatus == SelectionStatus.Selected))
|
||||
selectedDevice.StartMouseDrag(relative);
|
||||
}
|
||||
// Start multi-selection
|
||||
@@ -395,6 +291,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
|
||||
// Any time dragging starts, start with a new rect
|
||||
SelectionRectangle.Rect = new Rect();
|
||||
ApplySurfaceSelection();
|
||||
}
|
||||
|
||||
private void StopMouseDrag(object sender, Point position)
|
||||
@@ -403,17 +300,22 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
{
|
||||
RectangleGeometry selectedRect = new(new Rect(_mouseDragStartPoint, position));
|
||||
List<SurfaceDeviceViewModel> devices = HitTestUtilities.GetHitViewModels<SurfaceDeviceViewModel>((Visual) sender, selectedRect);
|
||||
foreach (SurfaceDeviceViewModel device in Devices)
|
||||
foreach (SurfaceDeviceViewModel device in SurfaceDeviceViewModels)
|
||||
{
|
||||
if (devices.Contains(device))
|
||||
device.SelectionStatus = SelectionStatus.Selected;
|
||||
else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
|
||||
device.SelectionStatus = SelectionStatus.None;
|
||||
}
|
||||
}
|
||||
else
|
||||
_surfaceService.UpdateSurfaceConfiguration(SelectedSurface, true);
|
||||
{
|
||||
_rgbService.SaveDevices();
|
||||
}
|
||||
|
||||
_mouseDragStatus = MouseDragStatus.None;
|
||||
_rgbService.IsRenderPaused = false;
|
||||
ApplySurfaceSelection();
|
||||
}
|
||||
|
||||
private void UpdateSelection(object sender, Point position)
|
||||
@@ -425,19 +327,29 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
SelectionRectangle.Rect = selectedRect;
|
||||
|
||||
List<SurfaceDeviceViewModel> devices = HitTestUtilities.GetHitViewModels<SurfaceDeviceViewModel>((Visual) sender, SelectionRectangle);
|
||||
foreach (SurfaceDeviceViewModel device in Devices)
|
||||
foreach (SurfaceDeviceViewModel device in SurfaceDeviceViewModels)
|
||||
{
|
||||
if (devices.Contains(device))
|
||||
device.SelectionStatus = SelectionStatus.Selected;
|
||||
else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
|
||||
device.SelectionStatus = SelectionStatus.None;
|
||||
}
|
||||
|
||||
ApplySurfaceSelection();
|
||||
}
|
||||
|
||||
private void MoveSelected(Point position)
|
||||
{
|
||||
foreach (SurfaceDeviceViewModel device in Devices.Where(d => d.SelectionStatus == SelectionStatus.Selected))
|
||||
foreach (SurfaceDeviceViewModel device in SurfaceDeviceViewModels.Where(d => d.SelectionStatus == SelectionStatus.Selected))
|
||||
device.UpdateMouseDrag(position);
|
||||
}
|
||||
|
||||
private void ApplySurfaceSelection()
|
||||
{
|
||||
foreach (ListDeviceViewModel viewModel in ListDeviceViewModels)
|
||||
viewModel.IsSelected = SurfaceDeviceViewModels.Any(s => s.Device == viewModel.Device && s.SelectionStatus == SelectionStatus.Selected);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Panning and zooming
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<UserControl x:Class="Artemis.UI.Screens.SurfaceEditor.Visualization.ListDeviceView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Artemis.UI.Screens.SurfaceEditor.Visualization"
|
||||
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
d:DataContext="{d:DesignInstance {x:Type local:ListDeviceViewModel}}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="50" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<shared:DeviceVisualizer Device="{Binding Device}" Width="30" Height="30" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Text="{Binding Device.RgbDevice.DeviceInfo.DeviceName}" Grid.Column="1" VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,22 @@
|
||||
using Artemis.Core;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.SurfaceEditor.Visualization
|
||||
{
|
||||
public class ListDeviceViewModel : PropertyChangedBase
|
||||
{
|
||||
private bool _isSelected;
|
||||
public ArtemisDevice Device { get; }
|
||||
|
||||
public bool IsSelected
|
||||
{
|
||||
get => _isSelected;
|
||||
set => SetAndNotify(ref _isSelected, value);
|
||||
}
|
||||
|
||||
public ListDeviceViewModel(ArtemisDevice device)
|
||||
{
|
||||
Device = device;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,10 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:s="https://github.com/canton7/Stylet"
|
||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
||||
xmlns:surfaceEditor="clr-namespace:Artemis.UI.Screens.SurfaceEditor.Visualization"
|
||||
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||
xmlns:local="clr-namespace:Artemis.UI.Screens.SurfaceEditor.Visualization"
|
||||
mc:Ignorable="d"
|
||||
d:DataContext="{d:DesignInstance {x:Type surfaceEditor:SurfaceDeviceViewModel}}"
|
||||
d:DataContext="{d:DesignInstance {x:Type local:SurfaceDeviceViewModel}}"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
Cursor="{Binding Cursor}"
|
||||
MouseEnter="{s:Action MouseEnter}"
|
||||
@@ -20,21 +20,22 @@
|
||||
<Grid>
|
||||
<!-- Content -->
|
||||
<Grid>
|
||||
<shared:DeviceVisualizer Device="{Binding Device}" ShowColors="True" VerticalAlignment="Top" HorizontalAlignment="Left" />
|
||||
|
||||
<Rectangle Fill="{DynamicResource MaterialDesignCardBackground}"
|
||||
Stroke="{DynamicResource MaterialDesignTextBoxBorder}"
|
||||
StrokeThickness="1"
|
||||
Visibility="{Binding Device.RgbDevice.DeviceInfo.Image, ConverterParameter=Inverted, Converter={StaticResource NullToVisibilityConverter}}"
|
||||
Visibility="{Binding Device.Layout.Image, ConverterParameter=Inverted, Converter={StaticResource NullToVisibilityConverter}}"
|
||||
IsHitTestVisible="False"/>
|
||||
<TextBlock Text="{Binding Device.RgbDevice.DeviceInfo.DeviceName}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
TextWrapping="Wrap"
|
||||
TextAlignment="Center"
|
||||
Visibility="{Binding Device.RgbDevice.DeviceInfo.Image, ConverterParameter=Inverted, Converter={StaticResource NullToVisibilityConverter}}"
|
||||
Visibility="{Binding Device.Layout.Image, ConverterParameter=Inverted, Converter={StaticResource NullToVisibilityConverter}}"
|
||||
IsHitTestVisible="False"/>
|
||||
</Grid>
|
||||
|
||||
<shared:DeviceVisualizer Device="{Binding Device}" ShowColors="True" VerticalAlignment="Top" HorizontalAlignment="Left" />
|
||||
|
||||
</Grid>
|
||||
|
||||
<!-- Selection rectangle -->
|
||||
<Rectangle Width="Auto" Height="Auto" StrokeThickness="2">
|
||||
@@ -47,7 +48,7 @@
|
||||
<Rectangle.Style>
|
||||
<Style TargetType="{x:Type Rectangle}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding SelectionStatus}" Value="{x:Static surfaceEditor:SelectionStatus.Hover}">
|
||||
<DataTrigger Binding="{Binding SelectionStatus}" Value="{x:Static local:SelectionStatus.Hover}">
|
||||
<DataTrigger.EnterActions>
|
||||
<StopStoryboard BeginStoryboardName="ToSelected" />
|
||||
<BeginStoryboard x:Name="ToHover">
|
||||
@@ -62,7 +63,7 @@
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.EnterActions>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding SelectionStatus}" Value="{x:Static surfaceEditor:SelectionStatus.Selected}">
|
||||
<DataTrigger Binding="{Binding SelectionStatus}" Value="{x:Static local:SelectionStatus.Selected}">
|
||||
<DataTrigger.EnterActions>
|
||||
<StopStoryboard BeginStoryboardName="ToHover" />
|
||||
<BeginStoryboard x:Name="ToSelected">
|
||||
@@ -77,7 +78,7 @@
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.EnterActions>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding SelectionStatus}" Value="{x:Static surfaceEditor:SelectionStatus.None}">
|
||||
<DataTrigger Binding="{Binding SelectionStatus}" Value="{x:Static local:SelectionStatus.None}">
|
||||
<DataTrigger.EnterActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using RGB.NET.Core;
|
||||
using SkiaSharp;
|
||||
using Stylet;
|
||||
@@ -13,26 +13,19 @@ namespace Artemis.UI.Screens.SurfaceEditor.Visualization
|
||||
{
|
||||
public class SurfaceDeviceViewModel : PropertyChangedBase
|
||||
{
|
||||
private readonly IRgbService _rgbService;
|
||||
private Cursor _cursor;
|
||||
private ArtemisDevice _device;
|
||||
private double _dragOffsetX;
|
||||
private double _dragOffsetY;
|
||||
private SelectionStatus _selectionStatus;
|
||||
|
||||
public SurfaceDeviceViewModel(ArtemisDevice device)
|
||||
public SurfaceDeviceViewModel(ArtemisDevice device, IRgbService rgbService)
|
||||
{
|
||||
Device = device;
|
||||
_rgbService = rgbService;
|
||||
}
|
||||
|
||||
public ArtemisDevice Device
|
||||
{
|
||||
get => _device;
|
||||
set
|
||||
{
|
||||
if (SetAndNotify(ref _device, value)) return;
|
||||
NotifyOfPropertyChange(nameof(DeviceRectangle));
|
||||
}
|
||||
}
|
||||
public ArtemisDevice Device { get; }
|
||||
|
||||
public SelectionStatus SelectionStatus
|
||||
{
|
||||
@@ -40,19 +33,15 @@ namespace Artemis.UI.Screens.SurfaceEditor.Visualization
|
||||
set => SetAndNotify(ref _selectionStatus, value);
|
||||
}
|
||||
|
||||
public bool CanDetectInput => Device.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Keyboard ||
|
||||
Device.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Mouse;
|
||||
|
||||
public Cursor Cursor
|
||||
{
|
||||
get => _cursor;
|
||||
set => SetAndNotify(ref _cursor, value);
|
||||
}
|
||||
|
||||
public Rect DeviceRectangle => Device.RgbDevice == null
|
||||
? new Rect()
|
||||
: new Rect(Device.X, Device.Y, Device.RgbDevice.Boundary.Size.Width, Device.RgbDevice.Boundary.Size.Height);
|
||||
|
||||
public bool CanDetectInput => Device.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Keyboard ||
|
||||
Device.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Mouse;
|
||||
|
||||
|
||||
public void StartMouseDrag(Point mouseStartPosition)
|
||||
{
|
||||
_dragOffsetX = Device.X - mouseStartPosition.X;
|
||||
@@ -115,7 +104,7 @@ namespace Artemis.UI.Screens.SurfaceEditor.Visualization
|
||||
List<SKRect> own = Device.Leds
|
||||
.Select(l => SKRect.Create(l.Rectangle.Left + x, l.Rectangle.Top + y, l.Rectangle.Width, l.Rectangle.Height))
|
||||
.ToList();
|
||||
List<SKRect> others = Device.Surface.Devices
|
||||
List<SKRect> others = _rgbService.EnabledDevices
|
||||
.Where(d => d != Device && d.IsEnabled)
|
||||
.SelectMany(d => d.Leds)
|
||||
.Select(l => SKRect.Create(l.Rectangle.Left + (float) l.Device.X, l.Rectangle.Top + (float) l.Device.Y, l.Rectangle.Width, l.Rectangle.Height))
|
||||
@@ -133,7 +122,7 @@ namespace Artemis.UI.Screens.SurfaceEditor.Visualization
|
||||
BottomLeft,
|
||||
BottomRight
|
||||
}
|
||||
|
||||
|
||||
public enum SelectionStatus
|
||||
{
|
||||
None,
|
||||
|
||||
Reference in new issue
Block a user