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