mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-12 11:56:30 +00:00
Event condition - Added toggle off mode
Profile editor - Added element copy/pasting Shared UI - Fix namespaces
This commit is contained in:
1 parent
8c7bbc3f0f
commit
52f2338154
84 files changed
+1059
-608
No files matched your search
+13
-3
@@ -2,8 +2,8 @@
|
||||
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:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker;assembly=Artemis.UI.Shared"
|
||||
xmlns:conditionTypes="clr-namespace:Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes"
|
||||
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.DataModelPicker;assembly=Artemis.UI.Shared"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes.EventConditionView"
|
||||
x:DataType="conditionTypes:EventConditionViewModel">
|
||||
@@ -17,9 +17,9 @@
|
||||
<dataModelPicker:DataModelPickerButton Placeholder="Select an event"
|
||||
DockPanel.Dock="Top"
|
||||
HorizontalAlignment="Stretch"
|
||||
FilterTypes="{CompiledBinding FilterTypes}"
|
||||
DataModelPath="{CompiledBinding EventPath}"
|
||||
ShowFullPath="{CompiledBinding ShowFullPaths.Value}"/>
|
||||
ShowFullPath="{CompiledBinding ShowFullPaths.Value}"
|
||||
IsEventPicker="True"/>
|
||||
|
||||
<TextBlock DockPanel.Dock="Top">When the event fires..</TextBlock>
|
||||
<ComboBox PlaceholderText="Select a play mode" HorizontalAlignment="Stretch" DockPanel.Dock="Top" SelectedIndex="{CompiledBinding SelectedTriggerMode}">
|
||||
@@ -48,6 +48,16 @@
|
||||
</ComboBoxItem>
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock DockPanel.Dock="Top" IsVisible="{CompiledBinding ShowToggleOffOptions}">When toggling off..</TextBlock>
|
||||
<ComboBox PlaceholderText="Select a play mode"
|
||||
HorizontalAlignment="Stretch"
|
||||
DockPanel.Dock="Top"
|
||||
SelectedIndex="{CompiledBinding SelectedToggleOffMode}"
|
||||
IsVisible="{CompiledBinding ShowToggleOffOptions}">
|
||||
<ComboBoxItem>Finish the main segment</ComboBoxItem>
|
||||
<ComboBoxItem>Skip forward to the end segment</ComboBoxItem>
|
||||
</ComboBox>
|
||||
|
||||
<Button DockPanel.Dock="Bottom"
|
||||
ToolTip.Tip="Open editor"
|
||||
Margin="0 15 0 5"
|
||||
|
||||
+17
-7
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reactive;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Core;
|
||||
@@ -19,11 +17,13 @@ public class EventConditionViewModel : ActivatableViewModelBase
|
||||
{
|
||||
private readonly EventCondition _eventCondition;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly ObservableAsPropertyHelper<bool> _showOverlapOptions;
|
||||
private readonly IWindowService _windowService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ObservableAsPropertyHelper<bool> _showOverlapOptions;
|
||||
private readonly ObservableAsPropertyHelper<bool> _showToggleOffOptions;
|
||||
private readonly IWindowService _windowService;
|
||||
private ObservableAsPropertyHelper<DataModelPath?>? _eventPath;
|
||||
private ObservableAsPropertyHelper<int>? _selectedOverlapMode;
|
||||
private ObservableAsPropertyHelper<int>? _selectedToggleOffMode;
|
||||
private ObservableAsPropertyHelper<int>? _selectedTriggerMode;
|
||||
|
||||
public EventConditionViewModel(EventCondition eventCondition, IProfileEditorService profileEditorService, IWindowService windowService, ISettingsService settingsService)
|
||||
@@ -35,20 +35,24 @@ public class EventConditionViewModel : ActivatableViewModelBase
|
||||
_showOverlapOptions = this.WhenAnyValue(vm => vm.SelectedTriggerMode)
|
||||
.Select(m => m == 0)
|
||||
.ToProperty(this, vm => vm.ShowOverlapOptions);
|
||||
_showToggleOffOptions = this.WhenAnyValue(vm => vm.SelectedTriggerMode)
|
||||
.Select(m => m == 1)
|
||||
.ToProperty(this, vm => vm.ShowToggleOffOptions);
|
||||
|
||||
this.WhenActivated(d =>
|
||||
{
|
||||
_eventPath = eventCondition.WhenAnyValue(c => c.EventPath).ToProperty(this, vm => vm.EventPath).DisposeWith(d);
|
||||
_selectedTriggerMode = eventCondition.WhenAnyValue(c => c.TriggerMode).Select(m => (int) m).ToProperty(this, vm => vm.SelectedTriggerMode).DisposeWith(d);
|
||||
_selectedOverlapMode = eventCondition.WhenAnyValue(c => c.OverlapMode).Select(m => (int) m).ToProperty(this, vm => vm.SelectedOverlapMode).DisposeWith(d);
|
||||
_selectedToggleOffMode = eventCondition.WhenAnyValue(c => c.OverlapMode).Select(m => (int) m).ToProperty(this, vm => vm.SelectedOverlapMode).DisposeWith(d);
|
||||
});
|
||||
|
||||
OpenEditor = ReactiveCommand.CreateFromTask(ExecuteOpenEditor);
|
||||
}
|
||||
|
||||
public ObservableCollection<Type> FilterTypes { get; } = new() {typeof(IDataModelEvent)};
|
||||
public ReactiveCommand<Unit, Unit> OpenEditor { get; }
|
||||
public bool ShowOverlapOptions => _showOverlapOptions.Value;
|
||||
public bool ShowToggleOffOptions => _showToggleOffOptions.Value;
|
||||
public bool IsConditionForLayer => _eventCondition.ProfileElement is Layer;
|
||||
public PluginSetting<bool> ShowFullPaths => _settingsService.GetSetting("ProfileEditor.ShowFullPaths", false);
|
||||
|
||||
@@ -69,7 +73,13 @@ public class EventConditionViewModel : ActivatableViewModelBase
|
||||
get => _selectedOverlapMode?.Value ?? 0;
|
||||
set => _profileEditorService.ExecuteCommand(new UpdateEventOverlapMode(_eventCondition, (EventOverlapMode) value));
|
||||
}
|
||||
|
||||
|
||||
public int SelectedToggleOffMode
|
||||
{
|
||||
get => _selectedToggleOffMode?.Value ?? 0;
|
||||
set => _profileEditorService.ExecuteCommand(new UpdateEventToggleOffMode(_eventCondition, (EventToggleOffMode) value));
|
||||
}
|
||||
|
||||
private async Task ExecuteOpenEditor()
|
||||
{
|
||||
await _windowService.ShowDialogAsync<NodeScriptWindowViewModel, bool>(("nodeScript", _eventCondition.NodeScript));
|
||||
|
||||
-4
@@ -28,10 +28,8 @@ public class ProfileTreeViewDropHandler : DropHandlerBase
|
||||
result = Validate<TreeItemViewModel>(treeView, e, sourceContext, targetContext, true);
|
||||
|
||||
if (sender is ItemsControl itemsControl)
|
||||
{
|
||||
foreach (TreeViewItem treeViewItem in GetFlattenedTreeView(itemsControl))
|
||||
SetDraggingPseudoClasses(treeViewItem, TreeDropType.None);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -39,10 +37,8 @@ public class ProfileTreeViewDropHandler : DropHandlerBase
|
||||
public override void Cancel(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is ItemsControl itemsControl)
|
||||
{
|
||||
foreach (TreeViewItem treeViewItem in GetFlattenedTreeView(itemsControl))
|
||||
SetDraggingPseudoClasses(treeViewItem, TreeDropType.None);
|
||||
}
|
||||
|
||||
base.Cancel(sender, e);
|
||||
}
|
||||
|
||||
@@ -32,9 +32,9 @@
|
||||
Classes="condensed"
|
||||
IsVisible="{CompiledBinding Renaming}"
|
||||
Text="{CompiledBinding RenameValue}"
|
||||
x:Name="Input"
|
||||
x:Name="Input"
|
||||
KeyUp="InputElement_OnKeyUp"
|
||||
LostFocus="InputElement_OnLostFocus"/>
|
||||
LostFocus="InputElement_OnLostFocus" />
|
||||
<TextBlock Grid.Column="2" IsVisible="{CompiledBinding !Renaming}" Text="{Binding Folder.Name}" VerticalAlignment="Center" />
|
||||
<ToggleButton Grid.Column="3"
|
||||
Classes="icon-button icon-button-small"
|
||||
|
||||
+62
-24
@@ -1,33 +1,71 @@
|
||||
using Artemis.Core;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.Storage.Entities.Profile;
|
||||
using Artemis.UI.Extensions;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor.Commands;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
||||
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree;
|
||||
|
||||
public class FolderTreeItemViewModel : TreeItemViewModel
|
||||
{
|
||||
public class FolderTreeItemViewModel : TreeItemViewModel
|
||||
public FolderTreeItemViewModel(TreeItemViewModel? parent,
|
||||
Folder folder,
|
||||
IWindowService windowService,
|
||||
IProfileEditorService profileEditorService,
|
||||
ILayerBrushService layerBrushService,
|
||||
IProfileEditorVmFactory profileEditorVmFactory,
|
||||
IRgbService rgbService)
|
||||
: base(parent, folder, windowService, profileEditorService, rgbService, layerBrushService, profileEditorVmFactory)
|
||||
{
|
||||
public FolderTreeItemViewModel(TreeItemViewModel? parent,
|
||||
Folder folder,
|
||||
IWindowService windowService,
|
||||
IProfileEditorService profileEditorService,
|
||||
ILayerBrushService layerBrushService,
|
||||
IProfileEditorVmFactory profileEditorVmFactory,
|
||||
IRgbService rgbService)
|
||||
: base(parent, folder, windowService, profileEditorService, rgbService, layerBrushService, profileEditorVmFactory)
|
||||
{
|
||||
Folder = folder;
|
||||
}
|
||||
|
||||
public Folder Folder { get; }
|
||||
|
||||
|
||||
#region Overrides of TreeItemViewModel
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool SupportsChildren => true;
|
||||
|
||||
#endregion
|
||||
Folder = folder;
|
||||
}
|
||||
|
||||
public Folder Folder { get; }
|
||||
|
||||
|
||||
#region Overrides of TreeItemViewModel
|
||||
|
||||
protected override async Task ExecuteDuplicate()
|
||||
{
|
||||
await ProfileEditorService.SaveProfileAsync();
|
||||
|
||||
FolderEntity copy = CoreJson.DeserializeObject<FolderEntity>(CoreJson.SerializeObject(Folder.FolderEntity, true), true)!;
|
||||
copy.Id = Guid.NewGuid();
|
||||
copy.Name = Folder.Parent.GetNewFolderName(copy.Name + " - copy");
|
||||
|
||||
Folder copied = new(Folder.Profile, Folder.Parent, copy);
|
||||
ProfileEditorService.ExecuteCommand(new AddProfileElement(copied, Folder.Parent, Folder.Order - 1));
|
||||
}
|
||||
|
||||
protected override async Task ExecuteCopy()
|
||||
{
|
||||
await ProfileEditorService.SaveProfileAsync();
|
||||
await Folder.CopyToClipboard();
|
||||
}
|
||||
|
||||
protected override async Task ExecutePaste()
|
||||
{
|
||||
if (Folder.Parent is not Folder parent)
|
||||
return;
|
||||
RenderProfileElement? pasted = await parent.PasteChildFromClipboard();
|
||||
if (pasted == null)
|
||||
return;
|
||||
|
||||
// If the target contains an element with the same name, affix with " - copy"
|
||||
if (parent.Children.Any(c => c.Name == pasted.Name))
|
||||
pasted.Name = parent.GetNewFolderName(pasted.Name + " - copy");
|
||||
|
||||
ProfileEditorService.ExecuteCommand(new AddProfileElement(pasted, parent, Folder.Order - 1));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool SupportsChildren => true;
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -18,14 +18,14 @@
|
||||
<avalonia:MaterialIcon Kind="AlertCircle" />
|
||||
</Button>
|
||||
<avalonia:MaterialIcon Grid.Column="1" Kind="{CompiledBinding Layer.LayerBrush.Descriptor.Icon, FallbackValue=Layers}" Margin="0 0 5 0" />
|
||||
<TextBox Grid.Column="2"
|
||||
<TextBox Grid.Column="2"
|
||||
Margin="-5 0 0 0"
|
||||
Classes="condensed"
|
||||
x:Name="Input"
|
||||
IsVisible="{CompiledBinding Renaming}"
|
||||
Text="{CompiledBinding RenameValue}"
|
||||
KeyUp="InputElement_OnKeyUp"
|
||||
LostFocus="InputElement_OnLostFocus"></TextBox>
|
||||
LostFocus="InputElement_OnLostFocus" />
|
||||
<TextBlock Grid.Column="2" IsVisible="{CompiledBinding !Renaming}" Text="{CompiledBinding Layer.Name}" VerticalAlignment="Center" />
|
||||
<ToggleButton Grid.Column="3"
|
||||
Classes="icon-button icon-button-small"
|
||||
|
||||
@@ -1,32 +1,71 @@
|
||||
using Artemis.Core;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.Storage.Entities.Profile;
|
||||
using Artemis.UI.Extensions;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor.Commands;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
||||
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree;
|
||||
|
||||
public class LayerTreeItemViewModel : TreeItemViewModel
|
||||
{
|
||||
public class LayerTreeItemViewModel : TreeItemViewModel
|
||||
public LayerTreeItemViewModel(TreeItemViewModel? parent,
|
||||
Layer layer,
|
||||
IWindowService windowService,
|
||||
IProfileEditorService profileEditorService,
|
||||
IRgbService rgbService,
|
||||
ILayerBrushService layerBrushService,
|
||||
IProfileEditorVmFactory profileEditorVmFactory)
|
||||
: base(parent, layer, windowService, profileEditorService, rgbService, layerBrushService, profileEditorVmFactory)
|
||||
{
|
||||
public LayerTreeItemViewModel(TreeItemViewModel? parent,
|
||||
Layer layer,
|
||||
IWindowService windowService,
|
||||
IProfileEditorService profileEditorService,
|
||||
IRgbService rgbService,
|
||||
ILayerBrushService layerBrushService,
|
||||
IProfileEditorVmFactory profileEditorVmFactory)
|
||||
: base(parent, layer, windowService, profileEditorService, rgbService, layerBrushService, profileEditorVmFactory)
|
||||
{
|
||||
Layer = layer;
|
||||
}
|
||||
|
||||
public Layer Layer { get; }
|
||||
|
||||
#region Overrides of TreeItemViewModel
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool SupportsChildren => false;
|
||||
|
||||
#endregion
|
||||
Layer = layer;
|
||||
}
|
||||
|
||||
public Layer Layer { get; }
|
||||
|
||||
#region Overrides of TreeItemViewModel
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task ExecuteDuplicate()
|
||||
{
|
||||
await ProfileEditorService.SaveProfileAsync();
|
||||
|
||||
LayerEntity copy = CoreJson.DeserializeObject<LayerEntity>(CoreJson.SerializeObject(Layer.LayerEntity, true), true)!;
|
||||
copy.Id = Guid.NewGuid();
|
||||
copy.Name = Layer.Parent.GetNewFolderName(copy.Name + " - copy");
|
||||
|
||||
Layer copied = new(Layer.Profile, Layer.Parent, copy);
|
||||
ProfileEditorService.ExecuteCommand(new AddProfileElement(copied, Layer.Parent, Layer.Order - 1));
|
||||
}
|
||||
|
||||
protected override async Task ExecuteCopy()
|
||||
{
|
||||
await ProfileEditorService.SaveProfileAsync();
|
||||
await Layer.CopyToClipboard();
|
||||
}
|
||||
|
||||
protected override async Task ExecutePaste()
|
||||
{
|
||||
if (Layer.Parent is not Folder parent)
|
||||
return;
|
||||
RenderProfileElement? pasted = await parent.PasteChildFromClipboard();
|
||||
if (pasted == null)
|
||||
return;
|
||||
|
||||
// If the target contains an element with the same name, affix with " - copy"
|
||||
if (parent.Children.Any(c => c.Name == pasted.Name))
|
||||
pasted.Name = parent.GetNewLayerName(pasted.Name + " - copy");
|
||||
|
||||
ProfileEditorService.ExecuteCommand(new AddProfileElement(pasted, parent, Layer.Order - 1));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool SupportsChildren => false;
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.ProfileTree.ProfileTreeView"
|
||||
x:DataType="profileTree:ProfileTreeViewModel">
|
||||
<!-- These cause binding errors, not my fault - https://github.com/AvaloniaUI/Avalonia/issues/5762 -->
|
||||
<!-- These cause binding errors, not my fault - https://github.com/AvaloniaUI/Avalonia/issues/5762 -->
|
||||
<UserControl.KeyBindings>
|
||||
<KeyBinding Gesture="Escape" Command="{Binding ClearSelection}" />
|
||||
<KeyBinding Gesture="F2" Command="{Binding RenameSelected}" />
|
||||
@@ -101,7 +101,7 @@
|
||||
<TreeDataTemplate ItemsSource="{Binding Children}">
|
||||
<ContentControl Content="{Binding}" x:DataType="profileTree:TreeItemViewModel">
|
||||
<ContentControl.ContextFlyout>
|
||||
<MenuFlyout>
|
||||
<MenuFlyout IsOpen="{CompiledBinding IsFlyoutOpen, Mode=OneWayToSource}">
|
||||
<MenuItem Header="Add new folder" Command="{CompiledBinding AddFolder}">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="CreateNewFolder" />
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
@@ -17,10 +15,10 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree;
|
||||
|
||||
public class ProfileTreeView : ReactiveUserControl<ProfileTreeViewModel>
|
||||
{
|
||||
private TreeView _treeView;
|
||||
private Image? _dragAdorner;
|
||||
private Point _dragStartPosition;
|
||||
private Point _elementDragOffset;
|
||||
private TreeView _treeView;
|
||||
|
||||
public ProfileTreeView()
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
@@ -88,6 +89,26 @@ public class ProfileTreeViewModel : TreeItemViewModel
|
||||
SelectedChild?.Paste.Execute().Subscribe();
|
||||
}
|
||||
|
||||
public void UpdateCanPaste()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override Task ExecuteDuplicate()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
protected override Task ExecuteCopy()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
protected override Task ExecutePaste()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
private void SelectCurrentProfileElement(RenderProfileElement? element)
|
||||
{
|
||||
if (SelectedChild?.ProfileElement == element)
|
||||
|
||||
@@ -8,22 +8,28 @@ using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Extensions;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor.Commands;
|
||||
using Avalonia;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree;
|
||||
|
||||
public abstract class TreeItemViewModel : ActivatableViewModelBase
|
||||
{
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly ILayerBrushService _layerBrushService;
|
||||
private readonly IProfileEditorVmFactory _profileEditorVmFactory;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly IWindowService _windowService;
|
||||
protected readonly IProfileEditorService ProfileEditorService;
|
||||
private bool _canPaste;
|
||||
private RenderProfileElement? _currentProfileElement;
|
||||
private bool _isExpanded;
|
||||
private bool _isFlyoutOpen;
|
||||
private ProfileElement? _profileElement;
|
||||
private string? _renameValue;
|
||||
private bool _renaming;
|
||||
@@ -35,63 +41,31 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
|
||||
ILayerBrushService layerBrushService,
|
||||
IProfileEditorVmFactory profileEditorVmFactory)
|
||||
{
|
||||
ProfileEditorService = profileEditorService;
|
||||
_rgbService = rgbService;
|
||||
_layerBrushService = layerBrushService;
|
||||
_windowService = windowService;
|
||||
_profileEditorService = profileEditorService;
|
||||
_profileEditorVmFactory = profileEditorVmFactory;
|
||||
|
||||
Parent = parent;
|
||||
ProfileElement = profileElement;
|
||||
|
||||
AddLayer = ReactiveCommand.Create(() =>
|
||||
{
|
||||
if (ProfileElement is Layer targetLayer)
|
||||
{
|
||||
Layer layer = new(targetLayer.Parent, targetLayer.GetNewLayerName());
|
||||
layerBrushService.ApplyDefaultBrush(layer);
|
||||
|
||||
layer.AddLeds(rgbService.EnabledDevices.SelectMany(d => d.Leds));
|
||||
profileEditorService.ExecuteCommand(new AddProfileElement(layer, targetLayer.Parent, targetLayer.Order));
|
||||
}
|
||||
else if (ProfileElement != null)
|
||||
{
|
||||
Layer layer = new(ProfileElement, ProfileElement.GetNewLayerName());
|
||||
layerBrushService.ApplyDefaultBrush(layer);
|
||||
|
||||
layer.AddLeds(rgbService.EnabledDevices.SelectMany(d => d.Leds));
|
||||
profileEditorService.ExecuteCommand(new AddProfileElement(layer, ProfileElement, 0));
|
||||
}
|
||||
});
|
||||
|
||||
AddFolder = ReactiveCommand.Create(() =>
|
||||
{
|
||||
if (ProfileElement is Layer targetLayer)
|
||||
profileEditorService.ExecuteCommand(new AddProfileElement(new Folder(targetLayer.Parent, targetLayer.Parent.GetNewFolderName()), targetLayer.Parent, targetLayer.Order));
|
||||
else if (ProfileElement != null)
|
||||
profileEditorService.ExecuteCommand(new AddProfileElement(new Folder(ProfileElement, ProfileElement.GetNewFolderName()), ProfileElement, 0));
|
||||
});
|
||||
|
||||
Rename = ReactiveCommand.Create(() =>
|
||||
{
|
||||
Renaming = true;
|
||||
RenameValue = ProfileElement?.Name;
|
||||
});
|
||||
|
||||
Duplicate = ReactiveCommand.Create(() => throw new NotImplementedException());
|
||||
Copy = ReactiveCommand.Create(() => throw new NotImplementedException());
|
||||
Paste = ReactiveCommand.Create(() => throw new NotImplementedException());
|
||||
|
||||
Delete = ReactiveCommand.Create(() =>
|
||||
{
|
||||
if (ProfileElement is RenderProfileElement renderProfileElement)
|
||||
profileEditorService.ExecuteCommand(new RemoveProfileElement(renderProfileElement));
|
||||
});
|
||||
AddLayer = ReactiveCommand.Create(ExecuteAddLayer);
|
||||
AddFolder = ReactiveCommand.Create(ExecuteAddFolder);
|
||||
Rename = ReactiveCommand.Create(ExecuteRename);
|
||||
Delete = ReactiveCommand.Create(ExecuteDelete);
|
||||
Duplicate = ReactiveCommand.CreateFromTask(ExecuteDuplicate);
|
||||
Copy = ReactiveCommand.CreateFromTask(ExecuteCopy);
|
||||
Paste = ReactiveCommand.CreateFromTask(ExecutePaste, this.WhenAnyValue(vm => vm.CanPaste));
|
||||
|
||||
this.WhenActivated(d =>
|
||||
{
|
||||
_profileEditorService.ProfileElement.Subscribe(element => _currentProfileElement = element).DisposeWith(d);
|
||||
ProfileEditorService.ProfileElement.Subscribe(element => _currentProfileElement = element).DisposeWith(d);
|
||||
SubscribeToProfileElement(d);
|
||||
CreateTreeItems();
|
||||
});
|
||||
|
||||
this.WhenAnyValue(vm => vm.IsFlyoutOpen).Subscribe(UpdateCanPaste);
|
||||
}
|
||||
|
||||
public ProfileElement? ProfileElement
|
||||
@@ -106,12 +80,24 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
|
||||
set => RaiseAndSetIfChanged(ref _isExpanded, value);
|
||||
}
|
||||
|
||||
public bool IsFlyoutOpen
|
||||
{
|
||||
get => _isFlyoutOpen;
|
||||
set => RaiseAndSetIfChanged(ref _isFlyoutOpen, value);
|
||||
}
|
||||
|
||||
public bool Renaming
|
||||
{
|
||||
get => _renaming;
|
||||
set => RaiseAndSetIfChanged(ref _renaming, value);
|
||||
}
|
||||
|
||||
public bool CanPaste
|
||||
{
|
||||
get => _canPaste;
|
||||
set => RaiseAndSetIfChanged(ref _canPaste, value);
|
||||
}
|
||||
|
||||
public TreeItemViewModel? Parent { get; set; }
|
||||
public ObservableCollection<TreeItemViewModel> Children { get; } = new();
|
||||
|
||||
@@ -154,7 +140,7 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
|
||||
return;
|
||||
}
|
||||
|
||||
_profileEditorService.ExecuteCommand(new RenameProfileElement(ProfileElement, RenameValue));
|
||||
ProfileEditorService.ExecuteCommand(new RenameProfileElement(ProfileElement, RenameValue));
|
||||
Renaming = false;
|
||||
}
|
||||
|
||||
@@ -169,18 +155,24 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
|
||||
return;
|
||||
|
||||
if (ProfileElement != null && elementViewModel.ProfileElement != null)
|
||||
_profileEditorService.ExecuteCommand(new MoveProfileElement(ProfileElement, elementViewModel.ProfileElement, targetIndex));
|
||||
ProfileEditorService.ExecuteCommand(new MoveProfileElement(ProfileElement, elementViewModel.ProfileElement, targetIndex));
|
||||
}
|
||||
|
||||
protected abstract Task ExecuteDuplicate();
|
||||
protected abstract Task ExecuteCopy();
|
||||
protected abstract Task ExecutePaste();
|
||||
|
||||
protected void SubscribeToProfileElement(CompositeDisposable d)
|
||||
{
|
||||
if (ProfileElement == null)
|
||||
return;
|
||||
|
||||
Observable.FromEventPattern<ProfileElementEventArgs>(x => ProfileElement.ChildAdded += x, x => ProfileElement.ChildAdded -= x)
|
||||
.Subscribe(c => AddTreeItemIfMissing(c.EventArgs.ProfileElement)).DisposeWith(d);
|
||||
.Subscribe(c => AddTreeItemIfMissing(c.EventArgs.ProfileElement))
|
||||
.DisposeWith(d);
|
||||
Observable.FromEventPattern<ProfileElementEventArgs>(x => ProfileElement.ChildRemoved += x, x => ProfileElement.ChildRemoved -= x)
|
||||
.Subscribe(c => RemoveTreeItemsIfFound(c.Sender, c.EventArgs.ProfileElement)).DisposeWith(d);
|
||||
.Subscribe(c => RemoveTreeItemsIfFound(c.Sender, c.EventArgs.ProfileElement))
|
||||
.DisposeWith(d);
|
||||
}
|
||||
|
||||
protected void RemoveTreeItemsIfFound(object? sender, ProfileElement profileElement)
|
||||
@@ -202,7 +194,7 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
|
||||
newSelection = parent;
|
||||
}
|
||||
|
||||
_profileEditorService.ChangeCurrentProfileElement(newSelection as RenderProfileElement);
|
||||
ProfileEditorService.ChangeCurrentProfileElement(newSelection as RenderProfileElement);
|
||||
}
|
||||
|
||||
protected void AddTreeItemIfMissing(ProfileElement profileElement)
|
||||
@@ -217,7 +209,7 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
|
||||
|
||||
// Select the newly added element
|
||||
if (profileElement is RenderProfileElement renderProfileElement)
|
||||
_profileEditorService.ChangeCurrentProfileElement(renderProfileElement);
|
||||
ProfileEditorService.ChangeCurrentProfileElement(renderProfileElement);
|
||||
}
|
||||
|
||||
protected void CreateTreeItems()
|
||||
@@ -236,4 +228,56 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
|
||||
Children.Add(_profileEditorVmFactory.LayerTreeItemViewModel(this, layer));
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteDelete()
|
||||
{
|
||||
if (ProfileElement is RenderProfileElement renderProfileElement)
|
||||
ProfileEditorService.ExecuteCommand(new RemoveProfileElement(renderProfileElement));
|
||||
}
|
||||
|
||||
private void ExecuteRename()
|
||||
{
|
||||
Renaming = true;
|
||||
RenameValue = ProfileElement?.Name;
|
||||
}
|
||||
|
||||
private void ExecuteAddFolder()
|
||||
{
|
||||
if (ProfileElement is Layer targetLayer)
|
||||
ProfileEditorService.ExecuteCommand(new AddProfileElement(new Folder(targetLayer.Parent, targetLayer.Parent.GetNewFolderName()), targetLayer.Parent, targetLayer.Order));
|
||||
else if (ProfileElement != null)
|
||||
ProfileEditorService.ExecuteCommand(new AddProfileElement(new Folder(ProfileElement, ProfileElement.GetNewFolderName()), ProfileElement, 0));
|
||||
}
|
||||
|
||||
private void ExecuteAddLayer()
|
||||
{
|
||||
if (ProfileElement is Layer targetLayer)
|
||||
{
|
||||
Layer layer = new(targetLayer.Parent, targetLayer.GetNewLayerName());
|
||||
_layerBrushService.ApplyDefaultBrush(layer);
|
||||
|
||||
layer.AddLeds(_rgbService.EnabledDevices.SelectMany(d => d.Leds));
|
||||
ProfileEditorService.ExecuteCommand(new AddProfileElement(layer, targetLayer.Parent, targetLayer.Order));
|
||||
}
|
||||
else if (ProfileElement != null)
|
||||
{
|
||||
Layer layer = new(ProfileElement, ProfileElement.GetNewLayerName());
|
||||
_layerBrushService.ApplyDefaultBrush(layer);
|
||||
|
||||
layer.AddLeds(_rgbService.EnabledDevices.SelectMany(d => d.Leds));
|
||||
ProfileEditorService.ExecuteCommand(new AddProfileElement(layer, ProfileElement, 0));
|
||||
}
|
||||
}
|
||||
|
||||
private async void UpdateCanPaste(bool isFlyoutOpen)
|
||||
{
|
||||
if (Application.Current?.Clipboard == null)
|
||||
{
|
||||
CanPaste = false;
|
||||
return;
|
||||
}
|
||||
|
||||
string[] formats = await Application.Current.Clipboard.GetFormatsAsync();
|
||||
CanPaste = formats.Contains(ProfileElementExtensions.ClipboardDataFormat);
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,8 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:Artemis.UI.Screens.ProfileEditor.Properties"
|
||||
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
||||
xmlns:timeline="clr-namespace:Artemis.UI.Screens.ProfileEditor.Properties.Timeline"
|
||||
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.Properties.Timeline.TimelineView"
|
||||
x:DataType="timeline:TimelineViewModel">
|
||||
@@ -23,7 +23,7 @@
|
||||
</TreeDataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<controls:SelectionRectangle Name="SelectionRectangle" InputElement="{CompiledBinding $parent}" SelectionFinished="SelectionRectangle_OnSelectionFinished"></controls:SelectionRectangle>
|
||||
<shared:SelectionRectangle Name="SelectionRectangle" InputElement="{CompiledBinding $parent}" SelectionFinished="SelectionRectangle_OnSelectionFinished"></shared:SelectionRectangle>
|
||||
</Grid>
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Keyframes;
|
||||
using Artemis.UI.Shared.Controls;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Events;
|
||||
using Artemis.UI.Shared.Extensions;
|
||||
using Avalonia;
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
||||
xmlns:sharedConverters="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared"
|
||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
||||
xmlns:viewModel="clr-namespace:Artemis.UI.Screens.ProfileEditor.Properties.Tree"
|
||||
xmlns:properties="clr-namespace:Artemis.UI.Screens.ProfileEditor.Properties"
|
||||
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.Properties.Tree.TreeGroupView">
|
||||
<UserControl.Resources>
|
||||
@@ -68,7 +68,7 @@
|
||||
<!-- Type: LayerBrushRoot -->
|
||||
<Grid IsVisible="{Binding GroupType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static viewModel:LayerPropertyGroupType.LayerBrushRoot}}"
|
||||
ColumnDefinitions="Auto,Auto,Auto,*">
|
||||
<controls:ArtemisIcon Grid.Column="0"
|
||||
<shared:ArtemisIcon Grid.Column="0"
|
||||
Icon="{Binding LayerBrush.Descriptor.Icon}"
|
||||
Width="16"
|
||||
Height="16"
|
||||
@@ -104,7 +104,7 @@
|
||||
<Grid Height="24"
|
||||
IsVisible="{Binding GroupType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static viewModel:LayerPropertyGroupType.LayerEffectRoot}}"
|
||||
ColumnDefinitions="Auto,Auto,Auto,Auto,*,Auto">
|
||||
<controls:ArtemisIcon
|
||||
<shared:ArtemisIcon
|
||||
Grid.Column="0"
|
||||
Cursor="SizeNorthSouth"
|
||||
Icon="{Binding LayerEffect.Descriptor.Icon}"
|
||||
|
||||
+5
-5
@@ -2,19 +2,19 @@
|
||||
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:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
||||
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.VisualEditor.Tools.SelectionAddToolView" ClipToBounds="False">
|
||||
<Grid>
|
||||
<controls:SelectionRectangle InputElement="{Binding $parent[ZoomBorder]}"
|
||||
<shared:SelectionRectangle InputElement="{Binding $parent[ZoomBorder]}"
|
||||
BorderBrush="{DynamicResource SystemAccentColor}"
|
||||
BorderRadius="8"
|
||||
BorderThickness="2"
|
||||
SelectionFinished="SelectionRectangle_OnSelectionFinished"
|
||||
ZoomRatio="{Binding $parent[ZoomBorder].ZoomX}">
|
||||
<controls:SelectionRectangle.Background>
|
||||
<shared:SelectionRectangle.Background>
|
||||
<SolidColorBrush Color="{DynamicResource SystemAccentColorLight1}" Opacity="0.2"></SolidColorBrush>
|
||||
</controls:SelectionRectangle.Background>
|
||||
</controls:SelectionRectangle>
|
||||
</shared:SelectionRectangle.Background>
|
||||
</shared:SelectionRectangle>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
+5
-5
@@ -2,21 +2,21 @@
|
||||
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:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
||||
xmlns:paz="clr-namespace:Avalonia.Controls.PanAndZoom;assembly=Avalonia.Controls.PanAndZoom"
|
||||
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.VisualEditor.Tools.SelectionRemoveToolView"
|
||||
ClipToBounds="False">
|
||||
<Grid>
|
||||
<controls:SelectionRectangle InputElement="{Binding $parent[paz:ZoomBorder]}"
|
||||
<shared:SelectionRectangle InputElement="{Binding $parent[paz:ZoomBorder]}"
|
||||
BorderBrush="{DynamicResource SystemAccentColor}"
|
||||
BorderRadius="8"
|
||||
BorderThickness="2"
|
||||
SelectionFinished="SelectionRectangle_OnSelectionFinished"
|
||||
ZoomRatio="{Binding $parent[ZoomBorder].ZoomX}">
|
||||
<controls:SelectionRectangle.Background>
|
||||
<shared:SelectionRectangle.Background>
|
||||
<SolidColorBrush Color="{DynamicResource SystemAccentColorLight1}" Opacity="0.2"></SolidColorBrush>
|
||||
</controls:SelectionRectangle.Background>
|
||||
</controls:SelectionRectangle>
|
||||
</shared:SelectionRectangle.Background>
|
||||
</shared:SelectionRectangle>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -4,8 +4,8 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:paz="clr-namespace:Avalonia.Controls.PanAndZoom;assembly=Avalonia.Controls.PanAndZoom"
|
||||
xmlns:core="clr-namespace:Artemis.Core;assembly=Artemis.Core"
|
||||
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
||||
xmlns:visualEditor="clr-namespace:Artemis.UI.Screens.ProfileEditor.VisualEditor"
|
||||
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.VisualEditor.VisualEditorView"
|
||||
x:DataType="visualEditor:VisualEditorViewModel">
|
||||
@@ -53,7 +53,7 @@
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="core:ArtemisDevice">
|
||||
<controls:DeviceVisualizer Device="{Binding}" ShowColors="True" />
|
||||
<shared:DeviceVisualizer Device="{Binding}" ShowColors="True" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
@@ -88,7 +88,11 @@
|
||||
<SolidColorBrush Color="{DynamicResource CardStrokeColorDefaultSolid}" Opacity="0.65"></SolidColorBrush>
|
||||
</Border.Background>
|
||||
<StackPanel Orientation="Horizontal" Margin="8">
|
||||
<controls:ProfileConfigurationIcon ConfigurationIcon="{CompiledBinding ProfileConfiguration.Icon}" Margin="0 0 5 0"></controls:ProfileConfigurationIcon>
|
||||
<shared:ProfileConfigurationIcon ConfigurationIcon="{CompiledBinding ProfileConfiguration.Icon}"
|
||||
Foreground="{DynamicResource ToolTipForeground}"
|
||||
Width="18"
|
||||
Height="18"
|
||||
Margin="0 0 5 0"></shared:ProfileConfigurationIcon>
|
||||
<TextBlock Text="{CompiledBinding ProfileConfiguration.Name}"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
Reference in new issue
Block a user