mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Event condition - Added toggle off mode
Profile editor - Added element copy/pasting Shared UI - Fix namespaces
This commit is contained in:
parent
8c7bbc3f0f
commit
52f2338154
@ -75,6 +75,9 @@
|
|||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cinput_005Cevents/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cinput_005Cevents/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cinput_005Cinterfaces/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cinput_005Cinterfaces/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cinterfaces/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cinterfaces/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cprocessmonitor/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cprocessmonitor_005Cevents/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cprocessmonitor_005Cinterfaces/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cregistration/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cregistration/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cregistration_005Cinterfaces/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cregistration_005Cinterfaces/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cstorage/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cstorage/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Core.Internal;
|
using Artemis.Core.Internal;
|
||||||
|
using Artemis.Core.VisualScripting.Internal;
|
||||||
using Artemis.Storage.Entities.Profile.Abstract;
|
using Artemis.Storage.Entities.Profile.Abstract;
|
||||||
using Artemis.Storage.Entities.Profile.Conditions;
|
using Artemis.Storage.Entities.Profile.Conditions;
|
||||||
|
|
||||||
@ -13,13 +14,15 @@ public class EventCondition : CorePropertyChanged, INodeScriptCondition
|
|||||||
{
|
{
|
||||||
private readonly string _displayName;
|
private readonly string _displayName;
|
||||||
private readonly EventConditionEntity _entity;
|
private readonly EventConditionEntity _entity;
|
||||||
private EventDefaultNode _eventNode;
|
private IEventConditionNode _startNode;
|
||||||
private DataModelPath? _eventPath;
|
private DataModelPath? _eventPath;
|
||||||
private DateTime _lastProcessedTrigger;
|
|
||||||
private EventOverlapMode _overlapMode;
|
|
||||||
private NodeScript<bool> _script;
|
private NodeScript<bool> _script;
|
||||||
private EventTriggerMode _triggerMode;
|
|
||||||
private bool _wasMet;
|
private bool _wasMet;
|
||||||
|
private DateTime _lastProcessedTrigger;
|
||||||
|
private object? _lastProcessedValue;
|
||||||
|
private EventOverlapMode _overlapMode;
|
||||||
|
private EventTriggerMode _triggerMode;
|
||||||
|
private EventToggleOffMode _toggleOffMode;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the <see cref="EventCondition" /> class
|
/// Creates a new instance of the <see cref="EventCondition" /> class
|
||||||
@ -30,7 +33,7 @@ public class EventCondition : CorePropertyChanged, INodeScriptCondition
|
|||||||
|
|
||||||
_entity = new EventConditionEntity();
|
_entity = new EventConditionEntity();
|
||||||
_displayName = profileElement.GetType().Name;
|
_displayName = profileElement.GetType().Name;
|
||||||
_eventNode = new EventDefaultNode {X = -300};
|
_startNode = new EventConditionEventStartNode {X = -300};
|
||||||
_script = new NodeScript<bool>($"Activate {_displayName}", $"Whether or not the event should activate the {_displayName}", ProfileElement.Profile);
|
_script = new NodeScript<bool>($"Activate {_displayName}", $"Whether or not the event should activate the {_displayName}", ProfileElement.Profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +43,7 @@ public class EventCondition : CorePropertyChanged, INodeScriptCondition
|
|||||||
|
|
||||||
_entity = entity;
|
_entity = entity;
|
||||||
_displayName = profileElement.GetType().Name;
|
_displayName = profileElement.GetType().Name;
|
||||||
_eventNode = new EventDefaultNode();
|
_startNode = new EventConditionEventStartNode();
|
||||||
_script = null!;
|
_script = null!;
|
||||||
|
|
||||||
Load();
|
Load();
|
||||||
@ -83,18 +86,70 @@ public class EventCondition : CorePropertyChanged, INodeScriptCondition
|
|||||||
set => SetAndNotify(ref _overlapMode, value);
|
set => SetAndNotify(ref _overlapMode, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the mode for render elements when toggling off the event when using <see cref="EventTriggerMode.Toggle"/>.
|
||||||
|
/// </summary>
|
||||||
|
public EventToggleOffMode ToggleOffMode
|
||||||
|
{
|
||||||
|
get => _toggleOffMode;
|
||||||
|
set => SetAndNotify(ref _toggleOffMode, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the event node, applying the selected event
|
/// Updates the event node, applying the selected event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void UpdateEventNode()
|
public void UpdateEventNode()
|
||||||
{
|
{
|
||||||
IDataModelEvent? dataModelEvent = EventPath?.GetValue() as IDataModelEvent;
|
if (EventPath == null)
|
||||||
_eventNode.CreatePins(dataModelEvent);
|
return;
|
||||||
|
|
||||||
if (dataModelEvent != null && !Script.Nodes.Contains(_eventNode))
|
Type? pathType = EventPath.GetPropertyType();
|
||||||
Script.AddNode(_eventNode);
|
if (pathType == null)
|
||||||
else if (dataModelEvent == null && Script.Nodes.Contains(_eventNode))
|
return;
|
||||||
Script.RemoveNode(_eventNode);
|
|
||||||
|
// Create an event node if the path type is a data model event
|
||||||
|
if (pathType.IsAssignableTo(typeof(IDataModelEvent)))
|
||||||
|
{
|
||||||
|
EventConditionEventStartNode eventNode;
|
||||||
|
// Ensure the start node is an event node
|
||||||
|
if (_startNode is not EventConditionEventStartNode node)
|
||||||
|
{
|
||||||
|
eventNode = new EventConditionEventStartNode();
|
||||||
|
ReplaceStartNode(eventNode);
|
||||||
|
_startNode = eventNode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
eventNode = node;
|
||||||
|
|
||||||
|
IDataModelEvent? dataModelEvent = EventPath?.GetValue() as IDataModelEvent;
|
||||||
|
eventNode.CreatePins(dataModelEvent);
|
||||||
|
}
|
||||||
|
// Create a value changed node if the path type is a regular value
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Ensure the start nod is a value changed node
|
||||||
|
EventConditionValueChangedStartNode valueChangedNode;
|
||||||
|
// Ensure the start node is an event node
|
||||||
|
if (_startNode is not EventConditionValueChangedStartNode node)
|
||||||
|
{
|
||||||
|
valueChangedNode = new EventConditionValueChangedStartNode();
|
||||||
|
ReplaceStartNode(valueChangedNode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
valueChangedNode = node;
|
||||||
|
|
||||||
|
valueChangedNode.UpdateOutputPins(EventPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReplaceStartNode(IEventConditionNode newStartNode)
|
||||||
|
{
|
||||||
|
if (Script.Nodes.Contains(_startNode))
|
||||||
|
Script.RemoveNode(_startNode);
|
||||||
|
|
||||||
|
_startNode = newStartNode;
|
||||||
|
if (!Script.Nodes.Contains(_startNode))
|
||||||
|
Script.AddNode(_startNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -103,15 +158,30 @@ public class EventCondition : CorePropertyChanged, INodeScriptCondition
|
|||||||
/// <returns>The start node of the event script, if any.</returns>
|
/// <returns>The start node of the event script, if any.</returns>
|
||||||
public INode GetStartNode()
|
public INode GetStartNode()
|
||||||
{
|
{
|
||||||
return _eventNode;
|
return _startNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool Evaluate()
|
private bool Evaluate()
|
||||||
{
|
{
|
||||||
if (EventPath?.GetValue() is not IDataModelEvent dataModelEvent || dataModelEvent.LastTrigger <= _lastProcessedTrigger)
|
if (EventPath == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
object? value = EventPath.GetValue();
|
||||||
|
if (_startNode is EventConditionEventStartNode)
|
||||||
|
{
|
||||||
|
if (value is not IDataModelEvent dataModelEvent || dataModelEvent.LastTrigger <= _lastProcessedTrigger)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
_lastProcessedTrigger = dataModelEvent.LastTrigger;
|
_lastProcessedTrigger = dataModelEvent.LastTrigger;
|
||||||
|
}
|
||||||
|
else if (_startNode is EventConditionValueChangedStartNode valueChangedNode)
|
||||||
|
{
|
||||||
|
if (Equals(value, _lastProcessedValue))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
valueChangedNode.UpdateValues(value, _lastProcessedValue);
|
||||||
|
_lastProcessedValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
if (!Script.ExitNodeConnected)
|
if (!Script.ExitNodeConnected)
|
||||||
return true;
|
return true;
|
||||||
@ -151,6 +221,8 @@ public class EventCondition : CorePropertyChanged, INodeScriptCondition
|
|||||||
{
|
{
|
||||||
if (IsMet && !_wasMet)
|
if (IsMet && !_wasMet)
|
||||||
ProfileElement.Timeline.JumpToStart();
|
ProfileElement.Timeline.JumpToStart();
|
||||||
|
if (!IsMet && _wasMet && ToggleOffMode == EventToggleOffMode.SkipToEnd)
|
||||||
|
ProfileElement.Timeline.JumpToEndSegment();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -191,6 +263,7 @@ public class EventCondition : CorePropertyChanged, INodeScriptCondition
|
|||||||
{
|
{
|
||||||
TriggerMode = (EventTriggerMode) _entity.TriggerMode;
|
TriggerMode = (EventTriggerMode) _entity.TriggerMode;
|
||||||
OverlapMode = (EventOverlapMode) _entity.OverlapMode;
|
OverlapMode = (EventOverlapMode) _entity.OverlapMode;
|
||||||
|
ToggleOffMode = (EventToggleOffMode) _entity.ToggleOffMode;
|
||||||
|
|
||||||
if (_entity.EventPath != null)
|
if (_entity.EventPath != null)
|
||||||
EventPath = new DataModelPath(_entity.EventPath);
|
EventPath = new DataModelPath(_entity.EventPath);
|
||||||
@ -206,6 +279,8 @@ public class EventCondition : CorePropertyChanged, INodeScriptCondition
|
|||||||
{
|
{
|
||||||
_entity.TriggerMode = (int) TriggerMode;
|
_entity.TriggerMode = (int) TriggerMode;
|
||||||
_entity.OverlapMode = (int) OverlapMode;
|
_entity.OverlapMode = (int) OverlapMode;
|
||||||
|
_entity.ToggleOffMode = (int) ToggleOffMode;
|
||||||
|
|
||||||
Script.Save();
|
Script.Save();
|
||||||
_entity.Script = Script?.Entity;
|
_entity.Script = Script?.Entity;
|
||||||
EventPath?.Save();
|
EventPath?.Save();
|
||||||
@ -221,9 +296,9 @@ public class EventCondition : CorePropertyChanged, INodeScriptCondition
|
|||||||
Script.Load();
|
Script.Load();
|
||||||
|
|
||||||
// The load action may have created an event node, use that one over the one we have here
|
// The load action may have created an event node, use that one over the one we have here
|
||||||
INode? existingEventNode = Script.Nodes.FirstOrDefault(n => n.Id == EventDefaultNode.NodeId);
|
INode? existingEventNode = Script.Nodes.FirstOrDefault(n => n.Id == EventConditionEventStartNode.NodeId || n.Id == EventConditionValueChangedStartNode.NodeId);
|
||||||
if (existingEventNode != null)
|
if (existingEventNode != null)
|
||||||
_eventNode = (EventDefaultNode) existingEventNode;
|
_startNode = (IEventConditionNode) existingEventNode;
|
||||||
|
|
||||||
UpdateEventNode();
|
UpdateEventNode();
|
||||||
Script.LoadConnections();
|
Script.LoadConnections();
|
||||||
@ -269,3 +344,19 @@ public enum EventOverlapMode
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Ignore
|
Ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a mode for render elements when toggling off the event when using <see cref="EventTriggerMode.Toggle"/>.
|
||||||
|
/// </summary>
|
||||||
|
public enum EventToggleOffMode
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// When the event toggles the condition off, finish the the current run of the main timeline
|
||||||
|
/// </summary>
|
||||||
|
Finish,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When the event toggles the condition off, skip to the end segment of the timeline
|
||||||
|
/// </summary>
|
||||||
|
SkipToEnd
|
||||||
|
}
|
||||||
@ -1,67 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Artemis.Core
|
|
||||||
{
|
|
||||||
internal class DataModelValueChangedEvent<T> : IDataModelEvent
|
|
||||||
{
|
|
||||||
public DataModelValueChangedEvent(DataModelPath path)
|
|
||||||
{
|
|
||||||
Path = path;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataModelPath Path { get; }
|
|
||||||
public T? LastValue { get; private set; }
|
|
||||||
public T? CurrentValue { get; private set; }
|
|
||||||
public DateTime LastTrigger { get; private set; }
|
|
||||||
public TimeSpan TimeSinceLastTrigger => DateTime.Now - LastTrigger;
|
|
||||||
public int TriggerCount { get; private set; }
|
|
||||||
public Type ArgumentsType { get; } = typeof(DataModelValueChangedEventArgs<T>);
|
|
||||||
public string TriggerPastParticiple => "changed";
|
|
||||||
public bool TrackHistory { get; set; } = false;
|
|
||||||
public DataModelEventArgs? LastEventArgumentsUntyped { get; private set; }
|
|
||||||
public List<DataModelEventArgs> EventArgumentsHistoryUntyped { get; } = new();
|
|
||||||
|
|
||||||
public void Update()
|
|
||||||
{
|
|
||||||
if (!Path.IsValid)
|
|
||||||
return;
|
|
||||||
|
|
||||||
object? value = Path.GetValue();
|
|
||||||
if (value != null)
|
|
||||||
CurrentValue = (T?) value;
|
|
||||||
else
|
|
||||||
CurrentValue = default;
|
|
||||||
|
|
||||||
if (!Equals(LastValue, CurrentValue))
|
|
||||||
Trigger();
|
|
||||||
|
|
||||||
LastValue = CurrentValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset()
|
|
||||||
{
|
|
||||||
TriggerCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Trigger()
|
|
||||||
{
|
|
||||||
LastEventArgumentsUntyped = new DataModelValueChangedEventArgs<T>(CurrentValue, LastValue);
|
|
||||||
LastTrigger = DateTime.Now;
|
|
||||||
TriggerCount++;
|
|
||||||
|
|
||||||
OnEventTriggered();
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Events
|
|
||||||
|
|
||||||
public event EventHandler? EventTriggered;
|
|
||||||
|
|
||||||
internal virtual void OnEventTriggered()
|
|
||||||
{
|
|
||||||
EventTriggered?.Invoke(this, EventArgs.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
using Artemis.Core.Modules;
|
|
||||||
|
|
||||||
namespace Artemis.Core
|
|
||||||
{
|
|
||||||
internal class DataModelValueChangedEventArgs<T> : DataModelEventArgs
|
|
||||||
{
|
|
||||||
public DataModelValueChangedEventArgs(T? currentValue, T? previousValue)
|
|
||||||
{
|
|
||||||
CurrentValue = currentValue;
|
|
||||||
PreviousValue = previousValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataModelProperty(Description = "The current value of the property")]
|
|
||||||
public T? CurrentValue { get; }
|
|
||||||
[DataModelProperty(Description = "The previous value of the property")]
|
|
||||||
public T? PreviousValue { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -334,20 +334,18 @@ namespace Artemis.Core
|
|||||||
/// Explorer
|
/// Explorer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The resulting name i.e. <c>New layer</c> or <c>New layer (2)</c></returns>
|
/// <returns>The resulting name i.e. <c>New layer</c> or <c>New layer (2)</c></returns>
|
||||||
public string GetNewLayerName()
|
public string GetNewLayerName(string baseName = "New layer")
|
||||||
{
|
{
|
||||||
if (!Children.Any(c => c is Layer))
|
if (!Children.Any(c => c is Layer && c.Name == baseName))
|
||||||
return "New layer";
|
return baseName;
|
||||||
|
|
||||||
// Grab existing unnamed layers and get the first available number
|
int current = 2;
|
||||||
// Looks slow but it's not https://stackoverflow.com/a/8865806/5015269
|
while (true)
|
||||||
Regex regex = new(@"New layer \((\d+)\)");
|
{
|
||||||
int firstAvailable = Enumerable.Range(1, int.MaxValue)
|
if (Children.All(c => c is Layer && c.Name != $"{baseName} ({current})"))
|
||||||
.Except(Children.Where(c => c is Layer && c.Name != null && regex.IsMatch(c.Name))
|
return $"{baseName} ({current})";
|
||||||
.Select(c => int.Parse(regex.Match(c.Name!).Groups[1].Value))
|
current++;
|
||||||
.OrderBy(i => i))
|
}
|
||||||
.First();
|
|
||||||
return $"New layer ({firstAvailable})";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -355,20 +353,18 @@ namespace Artemis.Core
|
|||||||
/// in Explorer
|
/// in Explorer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The resulting name i.e. <c>New folder</c> or <c>New folder (2)</c></returns>
|
/// <returns>The resulting name i.e. <c>New folder</c> or <c>New folder (2)</c></returns>
|
||||||
public string GetNewFolderName()
|
public string GetNewFolderName(string baseName = "New folder")
|
||||||
{
|
{
|
||||||
if (!Children.Any(c => c is Folder))
|
if (!Children.Any(c => c is Folder && c.Name == baseName))
|
||||||
return "New folder";
|
return baseName;
|
||||||
|
|
||||||
// Grab existing unnamed layers and get the first available number
|
int current = 2;
|
||||||
// Looks slow but it's not https://stackoverflow.com/a/8865806/5015269
|
while (true)
|
||||||
Regex regex = new(@"New folder \((\d+)\)");
|
{
|
||||||
int firstAvailable = Enumerable.Range(1, int.MaxValue)
|
if (Children.All(c => c is Folder && c.Name != $"{baseName} ({current})"))
|
||||||
.Except(Children.Where(c => c is Folder && c.Name != null && regex.IsMatch(c.Name))
|
return $"{baseName} ({current})";
|
||||||
.Select(c => int.Parse(regex.Match(c.Name!).Groups[1].Value))
|
current++;
|
||||||
.OrderBy(i => i))
|
}
|
||||||
.First();
|
|
||||||
return $"New folder ({firstAvailable})";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@ -38,13 +38,14 @@ namespace Artemis.Core.Services
|
|||||||
// ReSharper disable UnusedParameter.Local
|
// ReSharper disable UnusedParameter.Local
|
||||||
public CoreService(IKernel kernel,
|
public CoreService(IKernel kernel,
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
StorageMigrationService _, // injected to ensure migration runs early
|
StorageMigrationService _1, // injected to ensure migration runs early
|
||||||
ISettingsService settingsService,
|
ISettingsService settingsService,
|
||||||
IPluginManagementService pluginManagementService,
|
IPluginManagementService pluginManagementService,
|
||||||
IRgbService rgbService,
|
IRgbService rgbService,
|
||||||
IProfileService profileService,
|
IProfileService profileService,
|
||||||
IModuleService moduleService,
|
IModuleService moduleService,
|
||||||
IScriptingService scriptingService)
|
IScriptingService scriptingService,
|
||||||
|
IProcessMonitorService _2)
|
||||||
{
|
{
|
||||||
Kernel = kernel;
|
Kernel = kernel;
|
||||||
Constants.CorePlugin.Kernel = kernel;
|
Constants.CorePlugin.Kernel = kernel;
|
||||||
|
|||||||
@ -11,7 +11,6 @@ namespace Artemis.Core.Services
|
|||||||
internal class ProcessMonitorService : IProcessMonitorService
|
internal class ProcessMonitorService : IProcessMonitorService
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly Timer _processScanTimer;
|
|
||||||
private readonly ProcessComparer _comparer;
|
private readonly ProcessComparer _comparer;
|
||||||
private Process[] _lastScannedProcesses;
|
private Process[] _lastScannedProcesses;
|
||||||
|
|
||||||
@ -19,16 +18,15 @@ namespace Artemis.Core.Services
|
|||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_lastScannedProcesses = Process.GetProcesses();
|
_lastScannedProcesses = Process.GetProcesses();
|
||||||
_processScanTimer = new Timer(1000);
|
Timer processScanTimer = new(1000);
|
||||||
_processScanTimer.Elapsed += OnTimerElapsed;
|
processScanTimer.Elapsed += OnTimerElapsed;
|
||||||
_processScanTimer.Start();
|
processScanTimer.Start();
|
||||||
_comparer = new ProcessComparer();
|
_comparer = new ProcessComparer();
|
||||||
|
|
||||||
ProcessActivationRequirement.ProcessMonitorService = this;
|
ProcessActivationRequirement.ProcessMonitorService = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler<ProcessEventArgs>? ProcessStarted;
|
public event EventHandler<ProcessEventArgs>? ProcessStarted;
|
||||||
|
|
||||||
public event EventHandler<ProcessEventArgs>? ProcessStopped;
|
public event EventHandler<ProcessEventArgs>? ProcessStopped;
|
||||||
|
|
||||||
public IEnumerable<Process> GetRunningProcesses()
|
public IEnumerable<Process> GetRunningProcesses()
|
||||||
@ -36,7 +34,7 @@ namespace Artemis.Core.Services
|
|||||||
return _lastScannedProcesses;
|
return _lastScannedProcesses;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTimerElapsed(object sender, ElapsedEventArgs e)
|
private void OnTimerElapsed(object? sender, ElapsedEventArgs e)
|
||||||
{
|
{
|
||||||
Process[] newProcesses = Process.GetProcesses();
|
Process[] newProcesses = Process.GetProcesses();
|
||||||
foreach (Process startedProcess in newProcesses.Except(_lastScannedProcesses, _comparer))
|
foreach (Process startedProcess in newProcesses.Except(_lastScannedProcesses, _comparer))
|
||||||
@ -64,7 +62,7 @@ namespace Artemis.Core.Services
|
|||||||
return x.Id == y.Id && x.ProcessName == y.ProcessName && x.SessionId == y.SessionId;
|
return x.Id == y.Id && x.ProcessName == y.ProcessName && x.SessionId == y.SessionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetHashCode(Process obj)
|
public int GetHashCode(Process? obj)
|
||||||
{
|
{
|
||||||
if (obj == null) return 0;
|
if (obj == null) return 0;
|
||||||
return obj.Id;
|
return obj.Id;
|
||||||
|
|||||||
@ -0,0 +1,80 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using Artemis.Core.Modules;
|
||||||
|
using Artemis.Core.VisualScripting.Internal;
|
||||||
|
using Humanizer;
|
||||||
|
|
||||||
|
namespace Artemis.Core.Internal;
|
||||||
|
|
||||||
|
internal class EventConditionEventStartNode : DefaultNode, IEventConditionNode
|
||||||
|
{
|
||||||
|
internal static readonly Guid NodeId = new("278735FE-69E9-4A73-A6B8-59E83EE19305");
|
||||||
|
private readonly List<OutputPin> _pinBucket = new();
|
||||||
|
private readonly Dictionary<PropertyInfo, OutputPin> _propertyPins;
|
||||||
|
private IDataModelEvent? _dataModelEvent;
|
||||||
|
|
||||||
|
public EventConditionEventStartNode() : base(NodeId, "Event Arguments", "Contains the event arguments that triggered the evaluation")
|
||||||
|
{
|
||||||
|
_propertyPins = new Dictionary<PropertyInfo, OutputPin>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreatePins(IDataModelEvent? dataModelEvent)
|
||||||
|
{
|
||||||
|
if (_dataModelEvent == dataModelEvent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (Pins.Any())
|
||||||
|
RemovePin((Pin) Pins.First());
|
||||||
|
_propertyPins.Clear();
|
||||||
|
|
||||||
|
_dataModelEvent = dataModelEvent;
|
||||||
|
if (dataModelEvent == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (PropertyInfo propertyInfo in dataModelEvent.ArgumentsType
|
||||||
|
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
|
||||||
|
.Where(p => p.CustomAttributes.All(a => a.AttributeType != typeof(DataModelIgnoreAttribute))))
|
||||||
|
_propertyPins.Add(propertyInfo, CreateOrAddOutputPin(propertyInfo.PropertyType, propertyInfo.Name.Humanize()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Evaluate()
|
||||||
|
{
|
||||||
|
if (_dataModelEvent?.LastEventArgumentsUntyped == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach ((PropertyInfo propertyInfo, OutputPin outputPin) in _propertyPins)
|
||||||
|
{
|
||||||
|
if (outputPin.ConnectedTo.Any())
|
||||||
|
outputPin.Value = propertyInfo.GetValue(_dataModelEvent.LastEventArgumentsUntyped) ?? outputPin.Type.GetDefault()!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates or adds an input pin to the node using a bucket.
|
||||||
|
/// The bucket might grow a bit over time as the user edits the node but pins won't get lost, enabling undo/redo in the
|
||||||
|
/// editor.
|
||||||
|
/// </summary>
|
||||||
|
private OutputPin CreateOrAddOutputPin(Type valueType, string displayName)
|
||||||
|
{
|
||||||
|
// Grab the first pin from the bucket that isn't on the node yet
|
||||||
|
OutputPin? pin = _pinBucket.FirstOrDefault(p => !Pins.Contains(p));
|
||||||
|
|
||||||
|
// If there is none, create a new one and add it to the bucket
|
||||||
|
if (pin == null)
|
||||||
|
{
|
||||||
|
pin = CreateOutputPin(valueType, displayName);
|
||||||
|
_pinBucket.Add(pin);
|
||||||
|
}
|
||||||
|
// If there was a pin in the bucket, update it's type and display name and reuse it
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pin.ChangeType(valueType);
|
||||||
|
pin.Name = displayName;
|
||||||
|
AddPin(pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pin;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
using System;
|
||||||
|
using Artemis.Core.VisualScripting.Internal;
|
||||||
|
|
||||||
|
namespace Artemis.Core.Internal;
|
||||||
|
|
||||||
|
internal class EventConditionValueChangedStartNode : DefaultNode, IEventConditionNode
|
||||||
|
{
|
||||||
|
internal static readonly Guid NodeId = new("F9A270DB-A231-4800-BAB3-DC1F96856756");
|
||||||
|
private object? _newValue;
|
||||||
|
private object? _oldValue;
|
||||||
|
|
||||||
|
public EventConditionValueChangedStartNode() : base(NodeId, "Changed values", "Contains the old and new values of the property chat was changed.")
|
||||||
|
{
|
||||||
|
NewValue = CreateOutputPin(typeof(object), "New value");
|
||||||
|
OldValue = CreateOutputPin(typeof(object), "Old value");
|
||||||
|
}
|
||||||
|
|
||||||
|
public OutputPin NewValue { get; }
|
||||||
|
public OutputPin OldValue { get; }
|
||||||
|
|
||||||
|
public void UpdateOutputPins(DataModelPath dataModelPath)
|
||||||
|
{
|
||||||
|
Type? type = dataModelPath?.GetPropertyType();
|
||||||
|
if (Numeric.IsTypeCompatible(type))
|
||||||
|
type = typeof(Numeric);
|
||||||
|
type ??= typeof(object);
|
||||||
|
|
||||||
|
if (NewValue.Type != type)
|
||||||
|
NewValue.ChangeType(type);
|
||||||
|
if (OldValue.Type != type)
|
||||||
|
OldValue.ChangeType(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateValues(object? newValue, object? oldValue)
|
||||||
|
{
|
||||||
|
_newValue = newValue;
|
||||||
|
_oldValue = oldValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Evaluate()
|
||||||
|
{
|
||||||
|
NewValue.Value = _newValue;
|
||||||
|
OldValue.Value = _oldValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,82 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using Artemis.Core.Modules;
|
|
||||||
using Humanizer;
|
|
||||||
|
|
||||||
namespace Artemis.Core.Internal
|
|
||||||
{
|
|
||||||
internal class EventDefaultNode : DefaultNode
|
|
||||||
{
|
|
||||||
internal static readonly Guid NodeId = new("278735FE-69E9-4A73-A6B8-59E83EE19305");
|
|
||||||
private readonly Dictionary<PropertyInfo, OutputPin> _propertyPins;
|
|
||||||
private readonly List<OutputPin> _pinBucket = new();
|
|
||||||
private IDataModelEvent? _dataModelEvent;
|
|
||||||
|
|
||||||
public EventDefaultNode() : base(NodeId, "Event Arguments", "Contains the event arguments that triggered the evaluation")
|
|
||||||
{
|
|
||||||
_propertyPins = new Dictionary<PropertyInfo, OutputPin>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CreatePins(IDataModelEvent? dataModelEvent)
|
|
||||||
{
|
|
||||||
if (_dataModelEvent == dataModelEvent)
|
|
||||||
return;
|
|
||||||
|
|
||||||
while (Pins.Any())
|
|
||||||
RemovePin((Pin) Pins.First());
|
|
||||||
_propertyPins.Clear();
|
|
||||||
|
|
||||||
_dataModelEvent = dataModelEvent;
|
|
||||||
if (dataModelEvent == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (PropertyInfo propertyInfo in dataModelEvent.ArgumentsType
|
|
||||||
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
|
|
||||||
.Where(p => p.CustomAttributes.All(a => a.AttributeType != typeof(DataModelIgnoreAttribute))))
|
|
||||||
{
|
|
||||||
_propertyPins.Add(propertyInfo, CreateOrAddOutputPin(propertyInfo.PropertyType, propertyInfo.Name.Humanize()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Evaluate()
|
|
||||||
{
|
|
||||||
if (_dataModelEvent?.LastEventArgumentsUntyped == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach ((PropertyInfo propertyInfo, OutputPin outputPin) in _propertyPins)
|
|
||||||
{
|
|
||||||
if (outputPin.ConnectedTo.Any())
|
|
||||||
outputPin.Value = propertyInfo.GetValue(_dataModelEvent.LastEventArgumentsUntyped) ?? outputPin.Type.GetDefault()!;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates or adds an input pin to the node using a bucket.
|
|
||||||
/// The bucket might grow a bit over time as the user edits the node but pins won't get lost, enabling undo/redo in the
|
|
||||||
/// editor.
|
|
||||||
/// </summary>
|
|
||||||
private OutputPin CreateOrAddOutputPin(Type valueType, string displayName)
|
|
||||||
{
|
|
||||||
// Grab the first pin from the bucket that isn't on the node yet
|
|
||||||
OutputPin? pin = _pinBucket.FirstOrDefault(p => !Pins.Contains(p));
|
|
||||||
|
|
||||||
// If there is none, create a new one and add it to the bucket
|
|
||||||
if (pin == null)
|
|
||||||
{
|
|
||||||
pin = CreateOutputPin(valueType, displayName);
|
|
||||||
_pinBucket.Add(pin);
|
|
||||||
}
|
|
||||||
// If there was a pin in the bucket, update it's type and display name and reuse it
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pin.ChangeType(valueType);
|
|
||||||
pin.Name = displayName;
|
|
||||||
AddPin(pin);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pin;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Artemis.Core.VisualScripting.Internal
|
||||||
|
{
|
||||||
|
internal interface IEventConditionNode : INode
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,6 +7,7 @@ namespace Artemis.Storage.Entities.Profile.Conditions
|
|||||||
{
|
{
|
||||||
public int TriggerMode { get; set; }
|
public int TriggerMode { get; set; }
|
||||||
public int OverlapMode { get; set; }
|
public int OverlapMode { get; set; }
|
||||||
|
public int ToggleOffMode { get; set; }
|
||||||
public DataModelPathEntity EventPath { get; set; }
|
public DataModelPathEntity EventPath { get; set; }
|
||||||
public NodeScriptEntity Script { get; set; }
|
public NodeScriptEntity Script { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,6 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Shared.Controls.ArtemisIcon">
|
x:Class="Artemis.UI.Shared.ArtemisIcon">
|
||||||
Welcome to Avalonia!
|
Welcome to Avalonia!
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@ -8,7 +8,7 @@ using Avalonia.Svg.Skia;
|
|||||||
using Material.Icons;
|
using Material.Icons;
|
||||||
using Material.Icons.Avalonia;
|
using Material.Icons.Avalonia;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared.Controls
|
namespace Artemis.UI.Shared
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a control that can display an arbitrary kind of icon.
|
/// Represents a control that can display an arbitrary kind of icon.
|
||||||
|
|||||||
@ -13,10 +13,11 @@ using Avalonia;
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
using Avalonia.Data;
|
using Avalonia.Data;
|
||||||
|
using Avalonia.Threading;
|
||||||
using Material.Icons.Avalonia;
|
using Material.Icons.Avalonia;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared.Controls.DataModelPicker;
|
namespace Artemis.UI.Shared.DataModelPicker;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a data model picker picker that can be used to select a data model path.
|
/// Represents a data model picker picker that can be used to select a data model path.
|
||||||
@ -52,29 +53,32 @@ public class DataModelPicker : TemplatedControl
|
|||||||
public static readonly StyledProperty<DataModelPropertiesViewModel?> DataModelViewModelProperty =
|
public static readonly StyledProperty<DataModelPropertiesViewModel?> DataModelViewModelProperty =
|
||||||
AvaloniaProperty.Register<DataModelPicker, DataModelPropertiesViewModel?>(nameof(DataModelViewModel));
|
AvaloniaProperty.Register<DataModelPicker, DataModelPropertiesViewModel?>(nameof(DataModelViewModel));
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A list of data model view models to show
|
|
||||||
/// </summary>
|
|
||||||
public static readonly StyledProperty<ObservableCollection<DataModelPropertiesViewModel>?> ExtraDataModelViewModelsProperty =
|
|
||||||
AvaloniaProperty.Register<DataModelPicker, ObservableCollection<DataModelPropertiesViewModel>?>(nameof(ExtraDataModelViewModels), new ObservableCollection<DataModelPropertiesViewModel>());
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of types to filter the selectable paths on.
|
/// A list of types to filter the selectable paths on.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly StyledProperty<ObservableCollection<Type>?> FilterTypesProperty =
|
public static readonly StyledProperty<ObservableCollection<Type>?> FilterTypesProperty =
|
||||||
AvaloniaProperty.Register<DataModelPicker, ObservableCollection<Type>?>(nameof(FilterTypes), new ObservableCollection<Type>());
|
AvaloniaProperty.Register<DataModelPicker, ObservableCollection<Type>?>(nameof(FilterTypes), new ObservableCollection<Type>());
|
||||||
|
|
||||||
private MaterialIcon? _currentPathIcon;
|
/// <summary>
|
||||||
private TextBlock? _currentPathDisplay;
|
/// Gets or sets a boolean indicating whether the picker is in event picker mode.
|
||||||
|
/// When <see langword="true" /> event children aren't selectable and non-events are described as "{PropertyName}
|
||||||
|
/// changed".
|
||||||
|
/// </summary>
|
||||||
|
public static readonly StyledProperty<bool> IsEventPickerProperty =
|
||||||
|
AvaloniaProperty.Register<DataModelPicker, bool>(nameof(IsEventPicker));
|
||||||
|
|
||||||
private TextBlock? _currentPathDescription;
|
private TextBlock? _currentPathDescription;
|
||||||
|
private TextBlock? _currentPathDisplay;
|
||||||
|
|
||||||
|
private MaterialIcon? _currentPathIcon;
|
||||||
private TreeView? _dataModelTreeView;
|
private TreeView? _dataModelTreeView;
|
||||||
|
private DispatcherTimer? _updateTimer;
|
||||||
|
|
||||||
static DataModelPicker()
|
static DataModelPicker()
|
||||||
{
|
{
|
||||||
ModulesProperty.Changed.Subscribe(ModulesChanged);
|
ModulesProperty.Changed.Subscribe(ModulesChanged);
|
||||||
DataModelPathProperty.Changed.Subscribe(DataModelPathPropertyChanged);
|
DataModelPathProperty.Changed.Subscribe(DataModelPathPropertyChanged);
|
||||||
DataModelViewModelProperty.Changed.Subscribe(DataModelViewModelPropertyChanged);
|
DataModelViewModelProperty.Changed.Subscribe(DataModelViewModelPropertyChanged);
|
||||||
ExtraDataModelViewModelsProperty.Changed.Subscribe(ExtraDataModelViewModelsChanged);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -126,15 +130,6 @@ public class DataModelPicker : TemplatedControl
|
|||||||
private set => SetValue(DataModelViewModelProperty, value);
|
private set => SetValue(DataModelViewModelProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A list of data model view models to show.
|
|
||||||
/// </summary>
|
|
||||||
public ObservableCollection<DataModelPropertiesViewModel>? ExtraDataModelViewModels
|
|
||||||
{
|
|
||||||
get => GetValue(ExtraDataModelViewModelsProperty);
|
|
||||||
set => SetValue(ExtraDataModelViewModelsProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of types to filter the selectable paths on.
|
/// A list of types to filter the selectable paths on.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -144,6 +139,17 @@ public class DataModelPicker : TemplatedControl
|
|||||||
set => SetValue(FilterTypesProperty, value);
|
set => SetValue(FilterTypesProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a boolean indicating whether the picker is in event picker mode.
|
||||||
|
/// When <see langword="true" /> event children aren't selectable and non-events are described as "{PropertyName}
|
||||||
|
/// changed".
|
||||||
|
/// </summary>
|
||||||
|
public bool IsEventPicker
|
||||||
|
{
|
||||||
|
get => GetValue(IsEventPickerProperty);
|
||||||
|
set => SetValue(IsEventPickerProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when a new path has been selected
|
/// Occurs when a new path has been selected
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -158,42 +164,6 @@ public class DataModelPicker : TemplatedControl
|
|||||||
DataModelPathSelected?.Invoke(this, e);
|
DataModelPathSelected?.Invoke(this, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Overrides of TemplatedControl
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
|
||||||
{
|
|
||||||
if (_dataModelTreeView != null)
|
|
||||||
_dataModelTreeView.SelectionChanged -= DataModelTreeViewOnSelectionChanged;
|
|
||||||
|
|
||||||
_currentPathIcon = e.NameScope.Find<MaterialIcon>("CurrentPathIcon");
|
|
||||||
_currentPathDisplay = e.NameScope.Find<TextBlock>("CurrentPathDisplay");
|
|
||||||
_currentPathDescription = e.NameScope.Find<TextBlock>("CurrentPathDescription");
|
|
||||||
_dataModelTreeView = e.NameScope.Find<TreeView>("DataModelTreeView");
|
|
||||||
|
|
||||||
if (_dataModelTreeView != null)
|
|
||||||
_dataModelTreeView.SelectionChanged += DataModelTreeViewOnSelectionChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Overrides of Visual
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
|
||||||
{
|
|
||||||
GetDataModel();
|
|
||||||
UpdateCurrentPath(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
|
||||||
{
|
|
||||||
DataModelViewModel?.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private static void ModulesChanged(AvaloniaPropertyChangedEventArgs<ObservableCollection<Module>?> e)
|
private static void ModulesChanged(AvaloniaPropertyChangedEventArgs<ObservableCollection<Module>?> e)
|
||||||
{
|
{
|
||||||
if (e.Sender is DataModelPicker dataModelPicker)
|
if (e.Sender is DataModelPicker dataModelPicker)
|
||||||
@ -212,11 +182,6 @@ public class DataModelPicker : TemplatedControl
|
|||||||
e.OldValue.Value.Dispose();
|
e.OldValue.Value.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ExtraDataModelViewModelsChanged(AvaloniaPropertyChangedEventArgs<ObservableCollection<DataModelPropertiesViewModel>?> e)
|
|
||||||
{
|
|
||||||
// TODO, the original did nothing here either and I can't remember why
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ExecuteSelectPropertyCommand(DataModelVisualizationViewModel selected)
|
private void ExecuteSelectPropertyCommand(DataModelVisualizationViewModel selected)
|
||||||
{
|
{
|
||||||
if (selected.DataModelPath == null)
|
if (selected.DataModelPath == null)
|
||||||
@ -228,6 +193,14 @@ public class DataModelPicker : TemplatedControl
|
|||||||
OnDataModelPathSelected(new DataModelSelectedEventArgs(DataModelPath));
|
OnDataModelPathSelected(new DataModelSelectedEventArgs(DataModelPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Update(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (DataModelUIService == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DataModelViewModel?.Update(DataModelUIService, new DataModelUpdateConfiguration(!IsEventPicker));
|
||||||
|
}
|
||||||
|
|
||||||
private void GetDataModel()
|
private void GetDataModel()
|
||||||
{
|
{
|
||||||
if (DataModelUIService == null)
|
if (DataModelUIService == null)
|
||||||
@ -251,10 +224,11 @@ public class DataModelPicker : TemplatedControl
|
|||||||
|
|
||||||
private void DataModelOnUpdateRequested(object? sender, EventArgs e)
|
private void DataModelOnUpdateRequested(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
DataModelViewModel?.ApplyTypeFilter(true, FilterTypes?.ToArray() ?? Type.EmptyTypes);
|
if (DataModelUIService == null || DataModelViewModel == null)
|
||||||
if (ExtraDataModelViewModels == null) return;
|
return;
|
||||||
foreach (DataModelPropertiesViewModel extraDataModelViewModel in ExtraDataModelViewModels)
|
|
||||||
extraDataModelViewModel.ApplyTypeFilter(true, FilterTypes?.ToArray() ?? Type.EmptyTypes);
|
DataModelViewModel.Update(DataModelUIService, new DataModelUpdateConfiguration(IsEventPicker));
|
||||||
|
DataModelViewModel.ApplyTypeFilter(true, FilterTypes?.ToArray() ?? Type.EmptyTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DataModelTreeViewOnSelectionChanged(object? sender, SelectionChangedEventArgs e)
|
private void DataModelTreeViewOnSelectionChanged(object? sender, SelectionChangedEventArgs e)
|
||||||
@ -295,6 +269,45 @@ public class DataModelPicker : TemplatedControl
|
|||||||
_currentPathDescription.Text = DataModelPath.GetPropertyDescription()?.Description;
|
_currentPathDescription.Text = DataModelPath.GetPropertyDescription()?.Description;
|
||||||
if (_currentPathIcon != null)
|
if (_currentPathIcon != null)
|
||||||
_currentPathIcon.Kind = DataModelPath.GetPropertyType().GetTypeIcon();
|
_currentPathIcon.Kind = DataModelPath.GetPropertyType().GetTypeIcon();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Overrides of TemplatedControl
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||||
|
{
|
||||||
|
if (_dataModelTreeView != null)
|
||||||
|
_dataModelTreeView.SelectionChanged -= DataModelTreeViewOnSelectionChanged;
|
||||||
|
|
||||||
|
_currentPathIcon = e.NameScope.Find<MaterialIcon>("CurrentPathIcon");
|
||||||
|
_currentPathDisplay = e.NameScope.Find<TextBlock>("CurrentPathDisplay");
|
||||||
|
_currentPathDescription = e.NameScope.Find<TextBlock>("CurrentPathDescription");
|
||||||
|
_dataModelTreeView = e.NameScope.Find<TreeView>("DataModelTreeView");
|
||||||
|
|
||||||
|
if (_dataModelTreeView != null)
|
||||||
|
_dataModelTreeView.SelectionChanged += DataModelTreeViewOnSelectionChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Overrides of Visual
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||||
|
{
|
||||||
|
GetDataModel();
|
||||||
|
UpdateCurrentPath(true);
|
||||||
|
_updateTimer = new DispatcherTimer(TimeSpan.FromMilliseconds(200), DispatcherPriority.Normal, Update);
|
||||||
|
_updateTimer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||||
|
{
|
||||||
|
DataModelViewModel?.Dispose();
|
||||||
|
_updateTimer?.Stop();
|
||||||
|
_updateTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
@ -3,8 +3,7 @@ using System.Collections.ObjectModel;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Modules;
|
using Artemis.Core.Modules;
|
||||||
using Artemis.UI.Shared.Controls.Flyouts;
|
using Artemis.UI.Shared.Flyouts;
|
||||||
using Artemis.UI.Shared.DataModelVisualization.Shared;
|
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
@ -13,7 +12,7 @@ using Avalonia.Interactivity;
|
|||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using FluentAvalonia.Core;
|
using FluentAvalonia.Core;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared.Controls.DataModelPicker;
|
namespace Artemis.UI.Shared.DataModelPicker;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a button that can be used to pick a data model path in a flyout.
|
/// Represents a button that can be used to pick a data model path in a flyout.
|
||||||
@ -68,18 +67,20 @@ public class DataModelPickerButton : TemplatedControl
|
|||||||
public static readonly StyledProperty<ObservableCollection<Module>?> ModulesProperty =
|
public static readonly StyledProperty<ObservableCollection<Module>?> ModulesProperty =
|
||||||
AvaloniaProperty.Register<DataModelPicker, ObservableCollection<Module>?>(nameof(Modules), new ObservableCollection<Module>());
|
AvaloniaProperty.Register<DataModelPicker, ObservableCollection<Module>?>(nameof(Modules), new ObservableCollection<Module>());
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A list of data model view models to show
|
|
||||||
/// </summary>
|
|
||||||
public static readonly StyledProperty<ObservableCollection<DataModelPropertiesViewModel>?> ExtraDataModelViewModelsProperty =
|
|
||||||
AvaloniaProperty.Register<DataModelPicker, ObservableCollection<DataModelPropertiesViewModel>?>(nameof(ExtraDataModelViewModels), new ObservableCollection<DataModelPropertiesViewModel>());
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of types to filter the selectable paths on.
|
/// A list of types to filter the selectable paths on.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly StyledProperty<ObservableCollection<Type>?> FilterTypesProperty =
|
public static readonly StyledProperty<ObservableCollection<Type>?> FilterTypesProperty =
|
||||||
AvaloniaProperty.Register<DataModelPicker, ObservableCollection<Type>?>(nameof(FilterTypes), new ObservableCollection<Type>());
|
AvaloniaProperty.Register<DataModelPicker, ObservableCollection<Type>?>(nameof(FilterTypes), new ObservableCollection<Type>());
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a boolean indicating whether the picker is in event picker mode.
|
||||||
|
/// When <see langword="true" /> event children aren't selectable and non-events are described as "{PropertyName}
|
||||||
|
/// changed".
|
||||||
|
/// </summary>
|
||||||
|
public static readonly StyledProperty<bool> IsEventPickerProperty =
|
||||||
|
AvaloniaProperty.Register<DataModelPicker, bool>(nameof(IsEventPicker));
|
||||||
|
|
||||||
private bool _attached;
|
private bool _attached;
|
||||||
private bool _flyoutActive;
|
private bool _flyoutActive;
|
||||||
private Button? _button;
|
private Button? _button;
|
||||||
@ -165,15 +166,6 @@ public class DataModelPickerButton : TemplatedControl
|
|||||||
set => SetValue(ModulesProperty, value);
|
set => SetValue(ModulesProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A list of data model view models to show.
|
|
||||||
/// </summary>
|
|
||||||
public ObservableCollection<DataModelPropertiesViewModel>? ExtraDataModelViewModels
|
|
||||||
{
|
|
||||||
get => GetValue(ExtraDataModelViewModelsProperty);
|
|
||||||
set => SetValue(ExtraDataModelViewModelsProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of types to filter the selectable paths on.
|
/// A list of types to filter the selectable paths on.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -183,6 +175,17 @@ public class DataModelPickerButton : TemplatedControl
|
|||||||
set => SetValue(FilterTypesProperty, value);
|
set => SetValue(FilterTypesProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a boolean indicating whether the picker is in event picker mode.
|
||||||
|
/// When <see langword="true" /> event children aren't selectable and non-events are described as "{PropertyName}
|
||||||
|
/// changed".
|
||||||
|
/// </summary>
|
||||||
|
public bool IsEventPicker
|
||||||
|
{
|
||||||
|
get => GetValue(IsEventPickerProperty);
|
||||||
|
set => SetValue(IsEventPickerProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Raised when the flyout opens.
|
/// Raised when the flyout opens.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -239,14 +242,24 @@ public class DataModelPickerButton : TemplatedControl
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// If a valid path is selected, gather all its segments and create a visual representation of the path
|
||||||
string? formattedPath = null;
|
string? formattedPath = null;
|
||||||
if (DataModelPath != null && DataModelPath.IsValid)
|
if (DataModelPath != null && DataModelPath.IsValid)
|
||||||
formattedPath = string.Join(" › ", DataModelPath.Segments.Where(s => s.GetPropertyDescription() != null).Select(s => s.GetPropertyDescription()!.Name));
|
formattedPath = string.Join(" › ", DataModelPath.Segments.Where(s => s.GetPropertyDescription() != null).Select(s => s.GetPropertyDescription()!.Name));
|
||||||
|
|
||||||
|
// Always show the full path in the tooltip
|
||||||
ToolTip.SetTip(_button, formattedPath);
|
ToolTip.SetTip(_button, formattedPath);
|
||||||
_label.Text = ShowFullPath
|
|
||||||
|
// Reuse the tooltip value when showing the full path, otherwise only show the last segment
|
||||||
|
string? labelText = ShowFullPath
|
||||||
? formattedPath
|
? formattedPath
|
||||||
: DataModelPath?.Segments.LastOrDefault()?.GetPropertyDescription()?.Name ?? DataModelPath?.Segments.LastOrDefault()?.Identifier;
|
: DataModelPath?.Segments.LastOrDefault()?.GetPropertyDescription()?.Name ?? DataModelPath?.Segments.LastOrDefault()?.Identifier;
|
||||||
|
|
||||||
|
// Add "changed" to the end of the display value if this is an event picker but no event was picked
|
||||||
|
if (IsEventPicker && labelText != null && DataModelPath?.GetPropertyType()?.IsAssignableTo(typeof(IDataModelEvent)) == false)
|
||||||
|
labelText += " changed";
|
||||||
|
|
||||||
|
_label.Text = labelText ?? Placeholder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,8 +270,8 @@ public class DataModelPickerButton : TemplatedControl
|
|||||||
|
|
||||||
// Logic here is taken from Fluent Avalonia's ColorPicker which also reuses the same control since it's large
|
// Logic here is taken from Fluent Avalonia's ColorPicker which also reuses the same control since it's large
|
||||||
_flyout.DataModelPicker.DataModelPath = DataModelPath;
|
_flyout.DataModelPicker.DataModelPath = DataModelPath;
|
||||||
_flyout.DataModelPicker.ExtraDataModelViewModels = ExtraDataModelViewModels;
|
|
||||||
_flyout.DataModelPicker.FilterTypes = FilterTypes;
|
_flyout.DataModelPicker.FilterTypes = FilterTypes;
|
||||||
|
_flyout.DataModelPicker.IsEventPicker = IsEventPicker;
|
||||||
_flyout.DataModelPicker.Modules = Modules;
|
_flyout.DataModelPicker.Modules = Modules;
|
||||||
_flyout.DataModelPicker.ShowDataModelValues = ShowDataModelValues;
|
_flyout.DataModelPicker.ShowDataModelValues = ShowDataModelValues;
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,7 @@ using Avalonia.Rendering;
|
|||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using Avalonia.Visuals.Media.Imaging;
|
using Avalonia.Visuals.Media.Imaging;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared.Controls
|
namespace Artemis.UI.Shared
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Visualizes an <see cref="ArtemisDevice" /> with optional per-LED colors
|
/// Visualizes an <see cref="ArtemisDevice" /> with optional per-LED colors
|
||||||
|
|||||||
@ -11,7 +11,7 @@ using Color = Avalonia.Media.Color;
|
|||||||
using Point = Avalonia.Point;
|
using Point = Avalonia.Point;
|
||||||
using SolidColorBrush = Avalonia.Media.SolidColorBrush;
|
using SolidColorBrush = Avalonia.Media.SolidColorBrush;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared.Controls
|
namespace Artemis.UI.Shared
|
||||||
{
|
{
|
||||||
internal class DeviceVisualizerLed
|
internal class DeviceVisualizerLed
|
||||||
{
|
{
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Shared.Controls.EnumComboBox">
|
x:Class="Artemis.UI.Shared.EnumComboBox">
|
||||||
<ComboBox x:Name="EnumComboBox" HorizontalAlignment="Stretch">
|
<ComboBox x:Name="EnumComboBox" HorizontalAlignment="Stretch">
|
||||||
<ComboBox.ItemTemplate>
|
<ComboBox.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
|
|||||||
@ -8,7 +8,7 @@ using Avalonia.Data;
|
|||||||
using Avalonia.LogicalTree;
|
using Avalonia.LogicalTree;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared.Controls
|
namespace Artemis.UI.Shared
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a combobox that can display the values of an enum.
|
/// Represents a combobox that can display the values of an enum.
|
||||||
|
|||||||
@ -5,7 +5,7 @@ using FluentAvalonia.Core;
|
|||||||
using FluentAvalonia.UI.Controls;
|
using FluentAvalonia.UI.Controls;
|
||||||
using FluentAvalonia.UI.Controls.Primitives;
|
using FluentAvalonia.UI.Controls.Primitives;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared.Controls.Flyouts;
|
namespace Artemis.UI.Shared.Flyouts;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines a flyout that hosts a data model picker.
|
/// Defines a flyout that hosts a data model picker.
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared.Controls.Flyouts;
|
namespace Artemis.UI.Shared.Flyouts;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines a flyout that hosts a gradient picker.
|
/// Defines a flyout that hosts a gradient picker.
|
||||||
|
|||||||
@ -16,7 +16,7 @@ using FluentAvalonia.UI.Media;
|
|||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using Button = Avalonia.Controls.Button;
|
using Button = Avalonia.Controls.Button;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared.Controls.GradientPicker;
|
namespace Artemis.UI.Shared.GradientPicker;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a gradient picker that can be used to edit a gradient.
|
/// Represents a gradient picker that can be used to edit a gradient.
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.UI.Shared.Controls.Flyouts;
|
using Artemis.UI.Shared.Flyouts;
|
||||||
using Artemis.UI.Shared.Providers;
|
using Artemis.UI.Shared.Providers;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
@ -13,7 +13,7 @@ using Avalonia.Media;
|
|||||||
using FluentAvalonia.Core;
|
using FluentAvalonia.Core;
|
||||||
using Button = FluentAvalonia.UI.Controls.Button;
|
using Button = FluentAvalonia.UI.Controls.Button;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared.Controls.GradientPicker;
|
namespace Artemis.UI.Shared.GradientPicker;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a gradient picker box that can be used to edit a gradient
|
/// Represents a gradient picker box that can be used to edit a gradient
|
||||||
|
|||||||
@ -2,11 +2,10 @@
|
|||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Metadata;
|
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared.Controls.GradientPicker;
|
namespace Artemis.UI.Shared.GradientPicker;
|
||||||
|
|
||||||
public class GradientPickerColorStop : TemplatedControl
|
public class GradientPickerColorStop : TemplatedControl
|
||||||
{
|
{
|
||||||
|
|||||||
@ -2,9 +2,9 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls"
|
xmlns:shared="clr-namespace:Artemis.UI.Shared"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Shared.Controls.HotkeyBox">
|
x:Class="Artemis.UI.Shared.HotkeyBox">
|
||||||
|
|
||||||
<UserControl.Styles>
|
<UserControl.Styles>
|
||||||
<Style Selector="TextBox#DisplayTextBox:focus:not(TextBox:empty)">
|
<Style Selector="TextBox#DisplayTextBox:focus:not(TextBox:empty)">
|
||||||
@ -17,7 +17,7 @@
|
|||||||
</Style>
|
</Style>
|
||||||
</UserControl.Styles>
|
</UserControl.Styles>
|
||||||
|
|
||||||
<controls:NoInputTextBox x:Name="DisplayTextBox"
|
<shared:NoInputTextBox x:Name="DisplayTextBox"
|
||||||
Watermark="{Binding $parent.Watermark}"
|
Watermark="{Binding $parent.Watermark}"
|
||||||
UseFloatingWatermark="{Binding $parent.UseFloatingWatermark}"
|
UseFloatingWatermark="{Binding $parent.UseFloatingWatermark}"
|
||||||
Classes="clearButton"
|
Classes="clearButton"
|
||||||
|
|||||||
@ -11,7 +11,7 @@ using Avalonia.Markup.Xaml;
|
|||||||
using Humanizer;
|
using Humanizer;
|
||||||
using Material.Icons;
|
using Material.Icons;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared.Controls
|
namespace Artemis.UI.Shared
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a control that can be used to display or edit <see cref="Core.Hotkey"/> instances.
|
/// Represents a control that can be used to display or edit <see cref="Core.Hotkey"/> instances.
|
||||||
|
|||||||
@ -3,7 +3,7 @@ using Avalonia.Controls;
|
|||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Styling;
|
using Avalonia.Styling;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared.Controls
|
namespace Artemis.UI.Shared
|
||||||
{
|
{
|
||||||
internal class NoInputTextBox : TextBox, IStyleable
|
internal class NoInputTextBox : TextBox, IStyleable
|
||||||
{
|
{
|
||||||
|
|||||||
@ -3,5 +3,5 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Shared.Controls.ProfileConfigurationIcon">
|
x:Class="Artemis.UI.Shared.ProfileConfigurationIcon">
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@ -10,7 +10,7 @@ using Avalonia.Svg.Skia;
|
|||||||
using Material.Icons;
|
using Material.Icons;
|
||||||
using Material.Icons.Avalonia;
|
using Material.Icons.Avalonia;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared.Controls
|
namespace Artemis.UI.Shared
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a control that can display the icon of a specific <see cref="ProfileConfiguration"/>.
|
/// Represents a control that can display the icon of a specific <see cref="ProfileConfiguration"/>.
|
||||||
|
|||||||
@ -6,7 +6,7 @@ using Avalonia.Controls;
|
|||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared.Controls;
|
namespace Artemis.UI.Shared;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Visualizes an <see cref="ArtemisDevice" /> with optional per-LED colors
|
/// Visualizes an <see cref="ArtemisDevice" /> with optional per-LED colors
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.UI.Shared.Controls;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Shared.Events
|
namespace Artemis.UI.Shared.Events
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using Artemis.UI.Shared.Controls;
|
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,38 @@
|
|||||||
|
using Artemis.Core;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Shared.Services.ProfileEditor.Commands;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a profile editor command that can be used to update an event condition's overlap mode.
|
||||||
|
/// </summary>
|
||||||
|
public class UpdateEventToggleOffMode : IProfileEditorCommand
|
||||||
|
{
|
||||||
|
private readonly EventCondition _eventCondition;
|
||||||
|
private readonly EventToggleOffMode _value;
|
||||||
|
private readonly EventToggleOffMode _oldValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of the <see cref="UpdateEventOverlapMode" /> class.
|
||||||
|
/// </summary>
|
||||||
|
public UpdateEventToggleOffMode(EventCondition eventCondition, EventToggleOffMode value)
|
||||||
|
{
|
||||||
|
_eventCondition = eventCondition;
|
||||||
|
_value = value;
|
||||||
|
_oldValue = eventCondition.ToggleOffMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string DisplayName => "Update event toggle off mode";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Execute()
|
||||||
|
{
|
||||||
|
_eventCondition.ToggleOffMode = _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Undo()
|
||||||
|
{
|
||||||
|
_eventCondition.ToggleOffMode = _oldValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,9 +1,9 @@
|
|||||||
<Styles xmlns="https://github.com/avaloniaui"
|
<Styles xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:controls1="clr-namespace:Artemis.UI.Shared.Controls"
|
xmlns:gradientPicker="clr-namespace:Artemis.UI.Shared.GradientPicker"
|
||||||
xmlns:gradientPicker="clr-namespace:Artemis.UI.Shared.Controls.GradientPicker"
|
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.DataModelPicker"
|
||||||
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker">
|
xmlns:controls1="clr-namespace:Artemis.UI.Shared">
|
||||||
<Design.PreviewWith>
|
<Design.PreviewWith>
|
||||||
<Border Padding="50">
|
<Border Padding="50">
|
||||||
<StackPanel Spacing="5">
|
<StackPanel Spacing="5">
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
<Styles xmlns="https://github.com/avaloniaui"
|
<Styles xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:dataModel="clr-namespace:Artemis.UI.Shared.DataModelVisualization.Shared"
|
xmlns:dataModel="clr-namespace:Artemis.UI.Shared.DataModelVisualization.Shared"
|
||||||
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker"
|
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia">
|
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
|
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.DataModelPicker">
|
||||||
<Design.PreviewWith>
|
<Design.PreviewWith>
|
||||||
<dataModelPicker:DataModelPicker />
|
<dataModelPicker:DataModelPicker />
|
||||||
</Design.PreviewWith>
|
</Design.PreviewWith>
|
||||||
@ -20,7 +20,22 @@
|
|||||||
RowDefinitions="*"
|
RowDefinitions="*"
|
||||||
MinHeight="38"
|
MinHeight="38"
|
||||||
IsVisible="{Binding DataModelPath, RelativeSource={RelativeSource TemplatedParent}, Converter={x:Static ObjectConverters.IsNotNull}}">
|
IsVisible="{Binding DataModelPath, RelativeSource={RelativeSource TemplatedParent}, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||||
<avalonia:MaterialIcon Grid.Column="0" Grid.Row="0" Name="CurrentPathIcon" Kind="QuestionMarkCircle" Height="22" Width="22" Margin="5 0 15 0" />
|
<avalonia:MaterialIcon Grid.Column="0"
|
||||||
|
Grid.Row="0"
|
||||||
|
Name="CurrentPathIcon"
|
||||||
|
Kind="QuestionMarkCircle"
|
||||||
|
Height="22"
|
||||||
|
Width="22"
|
||||||
|
Margin="5 0 15 0"
|
||||||
|
IsVisible="{Binding !IsEventPicker, RelativeSource={RelativeSource TemplatedParent}}"/>
|
||||||
|
<avalonia:MaterialIcon Grid.Column="0"
|
||||||
|
Grid.Row="0"
|
||||||
|
Name="EventIcon"
|
||||||
|
Kind="LightningBolt"
|
||||||
|
Height="22"
|
||||||
|
Width="22"
|
||||||
|
Margin="5 0 15 0"
|
||||||
|
IsVisible="{Binding IsEventPicker, RelativeSource={RelativeSource TemplatedParent}}"/>
|
||||||
<StackPanel Grid.Column="1" Grid.Row="0" VerticalAlignment="Center">
|
<StackPanel Grid.Column="1" Grid.Row="0" VerticalAlignment="Center">
|
||||||
<TextBlock Name="CurrentPathDisplay" Classes="BodyStrongTextBlockStyle" MaxHeight="50" />
|
<TextBlock Name="CurrentPathDisplay" Classes="BodyStrongTextBlockStyle" MaxHeight="50" />
|
||||||
<TextBlock Name="CurrentPathDescription" Classes="BodyTextBlockStyle" Foreground="{DynamicResource TextFillColorSecondary}" MaxHeight="50" />
|
<TextBlock Name="CurrentPathDescription" Classes="BodyTextBlockStyle" Foreground="{DynamicResource TextFillColorSecondary}" MaxHeight="50" />
|
||||||
@ -42,6 +57,7 @@
|
|||||||
<TreeView.Styles>
|
<TreeView.Styles>
|
||||||
<Style Selector="TreeViewItem">
|
<Style Selector="TreeViewItem">
|
||||||
<Setter Property="IsExpanded" Value="{Binding IsVisualizationExpanded, Mode=TwoWay}" />
|
<Setter Property="IsExpanded" Value="{Binding IsVisualizationExpanded, Mode=TwoWay}" />
|
||||||
|
<Setter Property="IsEnabled" Value="{Binding IsMatchingFilteredTypes, Mode=OneWay}" />
|
||||||
</Style>
|
</Style>
|
||||||
</TreeView.Styles>
|
</TreeView.Styles>
|
||||||
<TreeView.DataTemplates>
|
<TreeView.DataTemplates>
|
||||||
@ -58,7 +74,13 @@
|
|||||||
|
|
||||||
<TreeDataTemplate DataType="{x:Type dataModel:DataModelPropertyViewModel}">
|
<TreeDataTemplate DataType="{x:Type dataModel:DataModelPropertyViewModel}">
|
||||||
<Grid ColumnDefinitions="Auto,*">
|
<Grid ColumnDefinitions="Auto,*">
|
||||||
<TextBlock Grid.Column="0" Text="{Binding PropertyDescription.Name}" ToolTip.Tip="{Binding PropertyDescription.Description}" />
|
<StackPanel Grid.Column="0" Orientation="Horizontal">
|
||||||
|
<TextBlock Text="{Binding PropertyDescription.Name}" ToolTip.Tip="{Binding PropertyDescription.Description}" />
|
||||||
|
<TextBlock Text=" changed"
|
||||||
|
ToolTip.Tip="{Binding PropertyDescription.Description}"
|
||||||
|
IsVisible="{Binding IsEventPicker, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type dataModelPicker:DataModelPicker}}}"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
<ContentControl Grid.Column="1" Content="{Binding DisplayViewModel}" FontFamily="Consolas" Margin="0 0 10 0" />
|
<ContentControl Grid.Column="1" Content="{Binding DisplayViewModel}" FontFamily="Consolas" Margin="0 0 10 0" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</TreeDataTemplate>
|
</TreeDataTemplate>
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
<Styles xmlns="https://github.com/avaloniaui"
|
<Styles xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker"
|
|
||||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:gradientPicker="clr-namespace:Artemis.UI.Shared.Controls.GradientPicker">
|
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.DataModelPicker"
|
||||||
|
xmlns:gradientPicker="clr-namespace:Artemis.UI.Shared.GradientPicker">
|
||||||
<Design.PreviewWith>
|
<Design.PreviewWith>
|
||||||
<Border Padding="20" Width="200">
|
<Border Padding="20" Width="200">
|
||||||
<StackPanel Spacing="5">
|
<StackPanel Spacing="5">
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
<Styles xmlns="https://github.com/avaloniaui"
|
<Styles xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:controls="using:Artemis.UI.Shared.Controls.GradientPicker"
|
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
xmlns:core="clr-namespace:Artemis.Core;assembly=Artemis.Core"
|
xmlns:core="clr-namespace:Artemis.Core;assembly=Artemis.Core"
|
||||||
xmlns:fluent="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:fluent="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:converters="clr-namespace:Artemis.UI.Shared.Converters">
|
xmlns:converters="clr-namespace:Artemis.UI.Shared.Converters"
|
||||||
|
xmlns:gradientPicker="clr-namespace:Artemis.UI.Shared.GradientPicker">
|
||||||
<Styles.Resources>
|
<Styles.Resources>
|
||||||
<VisualBrush x:Key="LightCheckerboardBrush" TileMode="Tile" Stretch="Uniform" DestinationRect="3,0,10,10">
|
<VisualBrush x:Key="LightCheckerboardBrush" TileMode="Tile" Stretch="Uniform" DestinationRect="3,0,10,10">
|
||||||
<VisualBrush.Visual>
|
<VisualBrush.Visual>
|
||||||
@ -18,10 +18,10 @@
|
|||||||
</VisualBrush>
|
</VisualBrush>
|
||||||
</Styles.Resources>
|
</Styles.Resources>
|
||||||
<Design.PreviewWith>
|
<Design.PreviewWith>
|
||||||
<controls:GradientPicker />
|
<gradientPicker:GradientPicker />
|
||||||
</Design.PreviewWith>
|
</Design.PreviewWith>
|
||||||
|
|
||||||
<Style Selector="controls|GradientPickerColorStop /template/ Border.stop-handle">
|
<Style Selector="gradientPicker|GradientPickerColorStop /template/ Border.stop-handle">
|
||||||
<Setter Property="CornerRadius" Value="18" />
|
<Setter Property="CornerRadius" Value="18" />
|
||||||
<Setter Property="Width" Value="18" />
|
<Setter Property="Width" Value="18" />
|
||||||
<Setter Property="Height" Value="60" />
|
<Setter Property="Height" Value="60" />
|
||||||
@ -30,32 +30,32 @@
|
|||||||
<Setter Property="BorderBrush" Value="{DynamicResource ToolTipBorderBrush}" />
|
<Setter Property="BorderBrush" Value="{DynamicResource ToolTipBorderBrush}" />
|
||||||
<Setter Property="Cursor" Value="Hand" />
|
<Setter Property="Cursor" Value="Hand" />
|
||||||
</Style>
|
</Style>
|
||||||
<Style Selector="controls|GradientPickerColorStop /template/ Border.stop-handle > Border">
|
<Style Selector="gradientPicker|GradientPickerColorStop /template/ Border.stop-handle > Border">
|
||||||
<Setter Property="CornerRadius" Value="18" />
|
<Setter Property="CornerRadius" Value="18" />
|
||||||
<Setter Property="BorderThickness" Value="3" />
|
<Setter Property="BorderThickness" Value="3" />
|
||||||
<Setter Property="BorderBrush" Value="{DynamicResource SolidBackgroundFillColorQuarternaryBrush}" />
|
<Setter Property="BorderBrush" Value="{DynamicResource SolidBackgroundFillColorQuarternaryBrush}" />
|
||||||
<Setter Property="Background" Value="{DynamicResource LightCheckerboardBrush}" />
|
<Setter Property="Background" Value="{DynamicResource LightCheckerboardBrush}" />
|
||||||
</Style>
|
</Style>
|
||||||
<Style Selector="controls|GradientPickerColorStop /template/ Border.stop-handle > Border > Border">
|
<Style Selector="gradientPicker|GradientPickerColorStop /template/ Border.stop-handle > Border > Border">
|
||||||
<Setter Property="CornerRadius" Value="18" />
|
<Setter Property="CornerRadius" Value="18" />
|
||||||
<Setter Property="BorderThickness" Value="2" />
|
<Setter Property="BorderThickness" Value="2" />
|
||||||
<Setter Property="Margin" Value="-1" />
|
<Setter Property="Margin" Value="-1" />
|
||||||
<Setter Property="BorderBrush" Value="{DynamicResource SolidBackgroundFillColorSecondaryBrush}" />
|
<Setter Property="BorderBrush" Value="{DynamicResource SolidBackgroundFillColorSecondaryBrush}" />
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<Style Selector="controls|GradientPickerColorStop:selected /template/ Border.stop-handle > Border">
|
<Style Selector="gradientPicker|GradientPickerColorStop:selected /template/ Border.stop-handle > Border">
|
||||||
<Setter Property="BorderBrush" Value="{DynamicResource SystemAccentColorLight2}" />
|
<Setter Property="BorderBrush" Value="{DynamicResource SystemAccentColorLight2}" />
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<Style Selector="controls|GradientPicker Border#Gradient">
|
<Style Selector="gradientPicker|GradientPicker Border#Gradient">
|
||||||
<Setter Property="Height" Value="40" />
|
<Setter Property="Height" Value="40" />
|
||||||
<Setter Property="CornerRadius" Value="4" />
|
<Setter Property="CornerRadius" Value="4" />
|
||||||
</Style>
|
</Style>
|
||||||
<Style Selector="controls|GradientPicker Border#Gradient Border">
|
<Style Selector="gradientPicker|GradientPicker Border#Gradient Border">
|
||||||
<Setter Property="CornerRadius" Value="4" />
|
<Setter Property="CornerRadius" Value="4" />
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<Style Selector="controls|GradientPicker Border.stop-position">
|
<Style Selector="gradientPicker|GradientPicker Border.stop-position">
|
||||||
<Setter Property="Background" Value="{DynamicResource SolidBackgroundFillColorBaseBrush}" />
|
<Setter Property="Background" Value="{DynamicResource SolidBackgroundFillColorBaseBrush}" />
|
||||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrush}" />
|
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrush}" />
|
||||||
<Setter Property="BorderThickness" Value="1" />
|
<Setter Property="BorderThickness" Value="1" />
|
||||||
@ -65,12 +65,12 @@
|
|||||||
<Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" />
|
<Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" />
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<Style Selector="controls|GradientPicker Border.stop-position TextBlock">
|
<Style Selector="gradientPicker|GradientPicker Border.stop-position TextBlock">
|
||||||
<Setter Property="VerticalAlignment" Value="Center" />
|
<Setter Property="VerticalAlignment" Value="Center" />
|
||||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<Style Selector="controls|GradientPicker">
|
<Style Selector="gradientPicker|GradientPicker">
|
||||||
<Style.Resources>
|
<Style.Resources>
|
||||||
<converters:ColorGradientToGradientStopsConverter x:Key="ColorGradientToGradientStopsConverter" />
|
<converters:ColorGradientToGradientStopsConverter x:Key="ColorGradientToGradientStopsConverter" />
|
||||||
<converters:SKColorToColorConverter x:Key="SKColorToColorConverter" />
|
<converters:SKColorToColorConverter x:Key="SKColorToColorConverter" />
|
||||||
@ -103,11 +103,11 @@
|
|||||||
</ItemsControl.Styles>
|
</ItemsControl.Styles>
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate DataType="core:ColorGradientStop">
|
<DataTemplate DataType="core:ColorGradientStop">
|
||||||
<controls:GradientPickerColorStop ColorStop="{Binding}"
|
<gradientPicker:GradientPickerColorStop ColorStop="{Binding}"
|
||||||
PositionReference="{Binding $parent[Border]}"
|
PositionReference="{Binding $parent[Border]}"
|
||||||
Classes="gradient-handle"
|
Classes="gradient-handle"
|
||||||
GradientPicker="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls:GradientPicker}}}">
|
GradientPicker="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type gradientPicker:GradientPicker}}}">
|
||||||
</controls:GradientPickerColorStop>
|
</gradientPicker:GradientPickerColorStop>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ItemsControl.ItemTemplate>
|
</ItemsControl.ItemTemplate>
|
||||||
<ItemsControl.ItemsPanel>
|
<ItemsControl.ItemsPanel>
|
||||||
@ -202,7 +202,7 @@
|
|||||||
<Button Name="DeleteButton"
|
<Button Name="DeleteButton"
|
||||||
Grid.Column="3"
|
Grid.Column="3"
|
||||||
Classes="icon-button"
|
Classes="icon-button"
|
||||||
Command="{Binding DeleteStop, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls:GradientPicker}}}"
|
Command="{Binding DeleteStop, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type gradientPicker:GradientPicker}}}"
|
||||||
CommandParameter="{Binding}">
|
CommandParameter="{Binding}">
|
||||||
<avalonia:MaterialIcon Kind="Close" />
|
<avalonia:MaterialIcon Kind="Close" />
|
||||||
</Button>
|
</Button>
|
||||||
@ -247,7 +247,7 @@
|
|||||||
</Setter>
|
</Setter>
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<Style Selector="controls|GradientPickerColorStop.gradient-handle">
|
<Style Selector="gradientPicker|GradientPickerColorStop.gradient-handle">
|
||||||
<Style.Resources>
|
<Style.Resources>
|
||||||
<converters:SKColorToBrushConverter x:Key="SKColorToBrushConverter" />
|
<converters:SKColorToBrushConverter x:Key="SKColorToBrushConverter" />
|
||||||
</Style.Resources>
|
</Style.Resources>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<Styles xmlns="https://github.com/avaloniaui"
|
<Styles xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:gradientPicker="clr-namespace:Artemis.UI.Shared.Controls.GradientPicker"
|
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia">
|
xmlns:gradientPicker="clr-namespace:Artemis.UI.Shared.GradientPicker">
|
||||||
<Design.PreviewWith>
|
<Design.PreviewWith>
|
||||||
<Border Padding="20" Width="200">
|
<Border Padding="20" Width="200">
|
||||||
<StackPanel Spacing="5">
|
<StackPanel Spacing="5">
|
||||||
|
|||||||
@ -32,7 +32,7 @@
|
|||||||
<TreeViewItem Header="SubItem Item3" />
|
<TreeViewItem Header="SubItem Item3" />
|
||||||
</TreeViewItem>
|
</TreeViewItem>
|
||||||
</TreeViewItem>
|
</TreeViewItem>
|
||||||
<TreeViewItem Header="Item3" />
|
<TreeViewItem Header="Item3" IsEnabled="False"/>
|
||||||
<TreeViewItem Header="Item4" />
|
<TreeViewItem Header="Item4" />
|
||||||
</TreeView>
|
</TreeView>
|
||||||
</Border>
|
</Border>
|
||||||
@ -94,6 +94,10 @@
|
|||||||
<Setter Property="Margin" Value="0"></Setter>
|
<Setter Property="Margin" Value="0"></Setter>
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="TreeView TreeViewItem[IsEnabled=False]">
|
||||||
|
<Setter Property="Foreground" Value="{DynamicResource ButtonDisabledForegroundThemeBrush}"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
<!-- <Style Selector="TreeView.no-right-margin TreeViewItem /template/ Border#TreeViewItemLayoutRoot"> -->
|
<!-- <Style Selector="TreeView.no-right-margin TreeViewItem /template/ Border#TreeViewItemLayoutRoot"> -->
|
||||||
<!-- <Setter Property="Margin" Value="2 2 0 2"/> -->
|
<!-- <Setter Property="Margin" Value="2 2 0 2"/> -->
|
||||||
<!-- </Style> -->
|
<!-- </Style> -->
|
||||||
|
|||||||
@ -5,7 +5,7 @@ using Artemis.Core.Ninject;
|
|||||||
using Artemis.UI.Exceptions;
|
using Artemis.UI.Exceptions;
|
||||||
using Artemis.UI.Ninject;
|
using Artemis.UI.Ninject;
|
||||||
using Artemis.UI.Screens.Root;
|
using Artemis.UI.Screens.Root;
|
||||||
using Artemis.UI.Shared.Controls.DataModelPicker;
|
using Artemis.UI.Shared.DataModelPicker;
|
||||||
using Artemis.UI.Shared.Ninject;
|
using Artemis.UI.Shared.Ninject;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using Artemis.VisualScripting.Ninject;
|
using Artemis.VisualScripting.Ninject;
|
||||||
|
|||||||
@ -2,12 +2,12 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
|
||||||
xmlns:propertyInput="clr-namespace:Artemis.UI.DefaultTypes.PropertyInput"
|
xmlns:propertyInput="clr-namespace:Artemis.UI.DefaultTypes.PropertyInput"
|
||||||
|
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.DefaultTypes.PropertyInput.BoolPropertyInputView"
|
x:Class="Artemis.UI.DefaultTypes.PropertyInput.BoolPropertyInputView"
|
||||||
x:DataType="propertyInput:BoolPropertyInputViewModel">
|
x:DataType="propertyInput:BoolPropertyInputViewModel">
|
||||||
<controls:EnumComboBox Classes="condensed"
|
<shared:EnumComboBox Classes="condensed"
|
||||||
Width="200"
|
Width="200"
|
||||||
Value="{CompiledBinding SelectedBooleanOption}"
|
Value="{CompiledBinding SelectedBooleanOption}"
|
||||||
VerticalAlignment="Center" />
|
VerticalAlignment="Center" />
|
||||||
|
|||||||
@ -2,8 +2,8 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:gradientPicker="clr-namespace:Artemis.UI.Shared.Controls.GradientPicker;assembly=Artemis.UI.Shared"
|
|
||||||
xmlns:propertyInput="clr-namespace:Artemis.UI.DefaultTypes.PropertyInput"
|
xmlns:propertyInput="clr-namespace:Artemis.UI.DefaultTypes.PropertyInput"
|
||||||
|
xmlns:gradientPicker="clr-namespace:Artemis.UI.Shared.GradientPicker;assembly=Artemis.UI.Shared"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.DefaultTypes.PropertyInput.ColorGradientPropertyInputView"
|
x:Class="Artemis.UI.DefaultTypes.PropertyInput.ColorGradientPropertyInputView"
|
||||||
x:DataType="propertyInput:ColorGradientPropertyInputViewModel">
|
x:DataType="propertyInput:ColorGradientPropertyInputViewModel">
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using Artemis.UI.Shared.Controls.GradientPicker;
|
using Artemis.UI.Shared.GradientPicker;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
|
|||||||
@ -2,8 +2,8 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns: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"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.DefaultTypes.PropertyInput.EnumPropertyInputView">
|
x:Class="Artemis.UI.DefaultTypes.PropertyInput.EnumPropertyInputView">
|
||||||
<controls:EnumComboBox Classes="condensed" Width="200" Value="{Binding InputValue}" VerticalAlignment="Center" />
|
<shared:EnumComboBox Classes="condensed" Width="200" Value="{Binding InputValue}" VerticalAlignment="Center" />
|
||||||
</UserControl>
|
</UserControl>
|
||||||
65
src/Artemis.UI/Extensions/ProfileElementExtensions.cs
Normal file
65
src/Artemis.UI/Extensions/ProfileElementExtensions.cs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Artemis.Core;
|
||||||
|
using Artemis.Storage.Entities.Profile;
|
||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Input;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Extensions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides static extension methods for UI related profile element tasks.
|
||||||
|
/// </summary>
|
||||||
|
public static class ProfileElementExtensions
|
||||||
|
{
|
||||||
|
public const string ClipboardDataFormat = "Artemis.ProfileElement";
|
||||||
|
|
||||||
|
public static async Task CopyToClipboard(this Folder folder)
|
||||||
|
{
|
||||||
|
if (Application.Current?.Clipboard == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DataObject dataObject = new();
|
||||||
|
string copy = CoreJson.SerializeObject(folder.FolderEntity, true);
|
||||||
|
dataObject.Set(ClipboardDataFormat, copy);
|
||||||
|
await Application.Current.Clipboard.SetDataObjectAsync(dataObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task CopyToClipboard(this Layer layer)
|
||||||
|
{
|
||||||
|
if (Application.Current?.Clipboard == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DataObject dataObject = new();
|
||||||
|
string copy = CoreJson.SerializeObject(layer.LayerEntity, true);
|
||||||
|
dataObject.Set(ClipboardDataFormat, copy);
|
||||||
|
await Application.Current.Clipboard.SetDataObjectAsync(dataObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static async Task<RenderProfileElement?> PasteChildFromClipboard(this Folder parent)
|
||||||
|
{
|
||||||
|
if (Application.Current?.Clipboard == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
byte[]? bytes = (byte[]?) await Application.Current.Clipboard.GetDataAsync(ClipboardDataFormat);
|
||||||
|
if (bytes == null!)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
object? entity = CoreJson.DeserializeObject(Encoding.Unicode.GetString(bytes), true);
|
||||||
|
switch (entity)
|
||||||
|
{
|
||||||
|
case FolderEntity folderEntity:
|
||||||
|
folderEntity.Id = Guid.NewGuid();
|
||||||
|
return new Folder(parent.Profile, parent, folderEntity);
|
||||||
|
case LayerEntity layerEntity:
|
||||||
|
layerEntity.Id = Guid.NewGuid();
|
||||||
|
return new Layer(parent.Profile, parent, layerEntity);
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,13 +2,13 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns: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"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Debugger.Performance.PerformanceDebugPluginView">
|
x:Class="Artemis.UI.Screens.Debugger.Performance.PerformanceDebugPluginView">
|
||||||
<Border Classes="card-condensed" Margin="0 5">
|
<Border Classes="card-condensed" Margin="0 5">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<Grid ColumnDefinitions="40,*">
|
<Grid ColumnDefinitions="40,*">
|
||||||
<controls:ArtemisIcon Grid.Column="0" Icon="{Binding Plugin.Info.ResolvedIcon}" Width="24" Height="24" />
|
<shared:ArtemisIcon Grid.Column="0" Icon="{Binding Plugin.Info.ResolvedIcon}" Width="24" Height="24" />
|
||||||
<TextBlock Grid.Column="1" VerticalAlignment="Center" Classes="h5" Text="{Binding Plugin.Info.Name}" />
|
<TextBlock Grid.Column="1" VerticalAlignment="Center" Classes="h5" Text="{Binding Plugin.Info.Name}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|||||||
@ -2,8 +2,8 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
|
||||||
xmlns:controls1="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:controls1="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
|
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||||
mc:Ignorable="d" d:DesignWidth="1200" d:DesignHeight="800"
|
mc:Ignorable="d" d:DesignWidth="1200" d:DesignHeight="800"
|
||||||
x:Class="Artemis.UI.Screens.Device.DevicePropertiesView"
|
x:Class="Artemis.UI.Screens.Device.DevicePropertiesView"
|
||||||
Icon="/Assets/Images/Logo/application.ico"
|
Icon="/Assets/Images/Logo/application.ico"
|
||||||
@ -26,7 +26,7 @@
|
|||||||
</Grid.Background>
|
</Grid.Background>
|
||||||
<Grid Grid.Column="0" Name="DeviceDisplayGrid">
|
<Grid Grid.Column="0" Name="DeviceDisplayGrid">
|
||||||
<!-- No need to provide LEDs to highlight as LEDs are already physically highlighted -->
|
<!-- No need to provide LEDs to highlight as LEDs are already physically highlighted -->
|
||||||
<controls:DeviceVisualizer Device="{Binding Device}"
|
<shared:DeviceVisualizer Device="{Binding Device}"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
ShowColors="True"
|
ShowColors="True"
|
||||||
|
|||||||
@ -4,13 +4,13 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:controls1="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"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Device.DeviceSettingsView">
|
x:Class="Artemis.UI.Screens.Device.DeviceSettingsView">
|
||||||
<Border Classes="card" Padding="0" Width="200" ClipToBounds="True" Margin="5">
|
<Border Classes="card" Padding="0" Width="200" ClipToBounds="True" Margin="5">
|
||||||
<Grid RowDefinitions="140,*,Auto">
|
<Grid RowDefinitions="140,*,Auto">
|
||||||
<Rectangle Grid.Row="0" Fill="{DynamicResource CheckerboardBrush}"/>
|
<Rectangle Grid.Row="0" Fill="{DynamicResource CheckerboardBrush}"/>
|
||||||
<controls1:DeviceVisualizer VerticalAlignment="Center"
|
<shared:DeviceVisualizer VerticalAlignment="Center"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
Margin="5"
|
Margin="5"
|
||||||
ShowColors="False"
|
ShowColors="False"
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
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"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Plugins.PluginFeatureView">
|
x:Class="Artemis.UI.Screens.Plugins.PluginFeatureView">
|
||||||
<Grid ColumnDefinitions="30,*,Auto">
|
<Grid ColumnDefinitions="30,*,Auto">
|
||||||
@ -23,7 +23,7 @@
|
|||||||
</Grid.ContextFlyout>
|
</Grid.ContextFlyout>
|
||||||
|
|
||||||
<!-- Icon column -->
|
<!-- Icon column -->
|
||||||
<controls:ArtemisIcon Grid.Column="0"
|
<shared:ArtemisIcon Grid.Column="0"
|
||||||
Icon="{Binding FeatureInfo.ResolvedIcon}"
|
Icon="{Binding FeatureInfo.ResolvedIcon}"
|
||||||
Width="20"
|
Width="20"
|
||||||
Height="20"
|
Height="20"
|
||||||
|
|||||||
@ -4,13 +4,13 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:controls1="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="900" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="900" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Plugins.PluginSettingsView">
|
x:Class="Artemis.UI.Screens.Plugins.PluginSettingsView">
|
||||||
<Border Classes="card" Padding="15" Margin="0 5">
|
<Border Classes="card" Padding="15" Margin="0 5">
|
||||||
<Grid RowDefinitions="*,Auto" ColumnDefinitions="4*,5*">
|
<Grid RowDefinitions="*,Auto" ColumnDefinitions="4*,5*">
|
||||||
<Grid Grid.Row="0" RowDefinitions="Auto,Auto,*" ColumnDefinitions="80,*">
|
<Grid Grid.Row="0" RowDefinitions="Auto,Auto,*" ColumnDefinitions="80,*">
|
||||||
<controls1:ArtemisIcon Icon="{Binding Plugin.Info.ResolvedIcon}"
|
<shared:ArtemisIcon Icon="{Binding Plugin.Info.ResolvedIcon}"
|
||||||
Width="48"
|
Width="48"
|
||||||
Height="48"
|
Height="48"
|
||||||
Margin="0 5 0 0"
|
Margin="0 5 0 0"
|
||||||
|
|||||||
@ -2,8 +2,8 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker;assembly=Artemis.UI.Shared"
|
|
||||||
xmlns:conditionTypes="clr-namespace:Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes"
|
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"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes.EventConditionView"
|
x:Class="Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes.EventConditionView"
|
||||||
x:DataType="conditionTypes:EventConditionViewModel">
|
x:DataType="conditionTypes:EventConditionViewModel">
|
||||||
@ -17,9 +17,9 @@
|
|||||||
<dataModelPicker:DataModelPickerButton Placeholder="Select an event"
|
<dataModelPicker:DataModelPickerButton Placeholder="Select an event"
|
||||||
DockPanel.Dock="Top"
|
DockPanel.Dock="Top"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
FilterTypes="{CompiledBinding FilterTypes}"
|
|
||||||
DataModelPath="{CompiledBinding EventPath}"
|
DataModelPath="{CompiledBinding EventPath}"
|
||||||
ShowFullPath="{CompiledBinding ShowFullPaths.Value}"/>
|
ShowFullPath="{CompiledBinding ShowFullPaths.Value}"
|
||||||
|
IsEventPicker="True"/>
|
||||||
|
|
||||||
<TextBlock DockPanel.Dock="Top">When the event fires..</TextBlock>
|
<TextBlock DockPanel.Dock="Top">When the event fires..</TextBlock>
|
||||||
<ComboBox PlaceholderText="Select a play mode" HorizontalAlignment="Stretch" DockPanel.Dock="Top" SelectedIndex="{CompiledBinding SelectedTriggerMode}">
|
<ComboBox PlaceholderText="Select a play mode" HorizontalAlignment="Stretch" DockPanel.Dock="Top" SelectedIndex="{CompiledBinding SelectedTriggerMode}">
|
||||||
@ -48,6 +48,16 @@
|
|||||||
</ComboBoxItem>
|
</ComboBoxItem>
|
||||||
</ComboBox>
|
</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"
|
<Button DockPanel.Dock="Bottom"
|
||||||
ToolTip.Tip="Open editor"
|
ToolTip.Tip="Open editor"
|
||||||
Margin="0 15 0 5"
|
Margin="0 15 0 5"
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
using System;
|
using System.Reactive;
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Reactive;
|
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
@ -19,11 +17,13 @@ public class EventConditionViewModel : ActivatableViewModelBase
|
|||||||
{
|
{
|
||||||
private readonly EventCondition _eventCondition;
|
private readonly EventCondition _eventCondition;
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
private readonly ObservableAsPropertyHelper<bool> _showOverlapOptions;
|
|
||||||
private readonly IWindowService _windowService;
|
|
||||||
private readonly ISettingsService _settingsService;
|
private readonly ISettingsService _settingsService;
|
||||||
|
private readonly ObservableAsPropertyHelper<bool> _showOverlapOptions;
|
||||||
|
private readonly ObservableAsPropertyHelper<bool> _showToggleOffOptions;
|
||||||
|
private readonly IWindowService _windowService;
|
||||||
private ObservableAsPropertyHelper<DataModelPath?>? _eventPath;
|
private ObservableAsPropertyHelper<DataModelPath?>? _eventPath;
|
||||||
private ObservableAsPropertyHelper<int>? _selectedOverlapMode;
|
private ObservableAsPropertyHelper<int>? _selectedOverlapMode;
|
||||||
|
private ObservableAsPropertyHelper<int>? _selectedToggleOffMode;
|
||||||
private ObservableAsPropertyHelper<int>? _selectedTriggerMode;
|
private ObservableAsPropertyHelper<int>? _selectedTriggerMode;
|
||||||
|
|
||||||
public EventConditionViewModel(EventCondition eventCondition, IProfileEditorService profileEditorService, IWindowService windowService, ISettingsService settingsService)
|
public EventConditionViewModel(EventCondition eventCondition, IProfileEditorService profileEditorService, IWindowService windowService, ISettingsService settingsService)
|
||||||
@ -35,20 +35,24 @@ public class EventConditionViewModel : ActivatableViewModelBase
|
|||||||
_showOverlapOptions = this.WhenAnyValue(vm => vm.SelectedTriggerMode)
|
_showOverlapOptions = this.WhenAnyValue(vm => vm.SelectedTriggerMode)
|
||||||
.Select(m => m == 0)
|
.Select(m => m == 0)
|
||||||
.ToProperty(this, vm => vm.ShowOverlapOptions);
|
.ToProperty(this, vm => vm.ShowOverlapOptions);
|
||||||
|
_showToggleOffOptions = this.WhenAnyValue(vm => vm.SelectedTriggerMode)
|
||||||
|
.Select(m => m == 1)
|
||||||
|
.ToProperty(this, vm => vm.ShowToggleOffOptions);
|
||||||
|
|
||||||
this.WhenActivated(d =>
|
this.WhenActivated(d =>
|
||||||
{
|
{
|
||||||
_eventPath = eventCondition.WhenAnyValue(c => c.EventPath).ToProperty(this, vm => vm.EventPath).DisposeWith(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);
|
_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);
|
_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);
|
OpenEditor = ReactiveCommand.CreateFromTask(ExecuteOpenEditor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObservableCollection<Type> FilterTypes { get; } = new() {typeof(IDataModelEvent)};
|
|
||||||
public ReactiveCommand<Unit, Unit> OpenEditor { get; }
|
public ReactiveCommand<Unit, Unit> OpenEditor { get; }
|
||||||
public bool ShowOverlapOptions => _showOverlapOptions.Value;
|
public bool ShowOverlapOptions => _showOverlapOptions.Value;
|
||||||
|
public bool ShowToggleOffOptions => _showToggleOffOptions.Value;
|
||||||
public bool IsConditionForLayer => _eventCondition.ProfileElement is Layer;
|
public bool IsConditionForLayer => _eventCondition.ProfileElement is Layer;
|
||||||
public PluginSetting<bool> ShowFullPaths => _settingsService.GetSetting("ProfileEditor.ShowFullPaths", false);
|
public PluginSetting<bool> ShowFullPaths => _settingsService.GetSetting("ProfileEditor.ShowFullPaths", false);
|
||||||
|
|
||||||
@ -70,6 +74,12 @@ public class EventConditionViewModel : ActivatableViewModelBase
|
|||||||
set => _profileEditorService.ExecuteCommand(new UpdateEventOverlapMode(_eventCondition, (EventOverlapMode) value));
|
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()
|
private async Task ExecuteOpenEditor()
|
||||||
{
|
{
|
||||||
await _windowService.ShowDialogAsync<NodeScriptWindowViewModel, bool>(("nodeScript", _eventCondition.NodeScript));
|
await _windowService.ShowDialogAsync<NodeScriptWindowViewModel, bool>(("nodeScript", _eventCondition.NodeScript));
|
||||||
|
|||||||
@ -28,10 +28,8 @@ public class ProfileTreeViewDropHandler : DropHandlerBase
|
|||||||
result = Validate<TreeItemViewModel>(treeView, e, sourceContext, targetContext, true);
|
result = Validate<TreeItemViewModel>(treeView, e, sourceContext, targetContext, true);
|
||||||
|
|
||||||
if (sender is ItemsControl itemsControl)
|
if (sender is ItemsControl itemsControl)
|
||||||
{
|
|
||||||
foreach (TreeViewItem treeViewItem in GetFlattenedTreeView(itemsControl))
|
foreach (TreeViewItem treeViewItem in GetFlattenedTreeView(itemsControl))
|
||||||
SetDraggingPseudoClasses(treeViewItem, TreeDropType.None);
|
SetDraggingPseudoClasses(treeViewItem, TreeDropType.None);
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -39,10 +37,8 @@ public class ProfileTreeViewDropHandler : DropHandlerBase
|
|||||||
public override void Cancel(object? sender, RoutedEventArgs e)
|
public override void Cancel(object? sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (sender is ItemsControl itemsControl)
|
if (sender is ItemsControl itemsControl)
|
||||||
{
|
|
||||||
foreach (TreeViewItem treeViewItem in GetFlattenedTreeView(itemsControl))
|
foreach (TreeViewItem treeViewItem in GetFlattenedTreeView(itemsControl))
|
||||||
SetDraggingPseudoClasses(treeViewItem, TreeDropType.None);
|
SetDraggingPseudoClasses(treeViewItem, TreeDropType.None);
|
||||||
}
|
|
||||||
|
|
||||||
base.Cancel(sender, e);
|
base.Cancel(sender, e);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,17 @@
|
|||||||
using Artemis.Core;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
|
using Artemis.Storage.Entities.Profile;
|
||||||
|
using Artemis.UI.Extensions;
|
||||||
using Artemis.UI.Ninject.Factories;
|
using Artemis.UI.Ninject.Factories;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
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,
|
public FolderTreeItemViewModel(TreeItemViewModel? parent,
|
||||||
@ -25,9 +31,41 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
|||||||
|
|
||||||
#region Overrides of TreeItemViewModel
|
#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 />
|
/// <inheritdoc />
|
||||||
public override bool SupportsChildren => true;
|
public override bool SupportsChildren => true;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@ -25,7 +25,7 @@
|
|||||||
IsVisible="{CompiledBinding Renaming}"
|
IsVisible="{CompiledBinding Renaming}"
|
||||||
Text="{CompiledBinding RenameValue}"
|
Text="{CompiledBinding RenameValue}"
|
||||||
KeyUp="InputElement_OnKeyUp"
|
KeyUp="InputElement_OnKeyUp"
|
||||||
LostFocus="InputElement_OnLostFocus"></TextBox>
|
LostFocus="InputElement_OnLostFocus" />
|
||||||
<TextBlock Grid.Column="2" IsVisible="{CompiledBinding !Renaming}" Text="{CompiledBinding Layer.Name}" VerticalAlignment="Center" />
|
<TextBlock Grid.Column="2" IsVisible="{CompiledBinding !Renaming}" Text="{CompiledBinding Layer.Name}" VerticalAlignment="Center" />
|
||||||
<ToggleButton Grid.Column="3"
|
<ToggleButton Grid.Column="3"
|
||||||
Classes="icon-button icon-button-small"
|
Classes="icon-button icon-button-small"
|
||||||
|
|||||||
@ -1,11 +1,17 @@
|
|||||||
using Artemis.Core;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
|
using Artemis.Storage.Entities.Profile;
|
||||||
|
using Artemis.UI.Extensions;
|
||||||
using Artemis.UI.Ninject.Factories;
|
using Artemis.UI.Ninject.Factories;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
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,
|
public LayerTreeItemViewModel(TreeItemViewModel? parent,
|
||||||
@ -24,9 +30,42 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
|||||||
|
|
||||||
#region Overrides of TreeItemViewModel
|
#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 />
|
/// <inheritdoc />
|
||||||
public override bool SupportsChildren => false;
|
public override bool SupportsChildren => false;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@ -101,7 +101,7 @@
|
|||||||
<TreeDataTemplate ItemsSource="{Binding Children}">
|
<TreeDataTemplate ItemsSource="{Binding Children}">
|
||||||
<ContentControl Content="{Binding}" x:DataType="profileTree:TreeItemViewModel">
|
<ContentControl Content="{Binding}" x:DataType="profileTree:TreeItemViewModel">
|
||||||
<ContentControl.ContextFlyout>
|
<ContentControl.ContextFlyout>
|
||||||
<MenuFlyout>
|
<MenuFlyout IsOpen="{CompiledBinding IsFlyoutOpen, Mode=OneWayToSource}">
|
||||||
<MenuItem Header="Add new folder" Command="{CompiledBinding AddFolder}">
|
<MenuItem Header="Add new folder" Command="{CompiledBinding AddFolder}">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
<avalonia:MaterialIcon Kind="CreateNewFolder" />
|
<avalonia:MaterialIcon Kind="CreateNewFolder" />
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
@ -17,10 +15,10 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree;
|
|||||||
|
|
||||||
public class ProfileTreeView : ReactiveUserControl<ProfileTreeViewModel>
|
public class ProfileTreeView : ReactiveUserControl<ProfileTreeViewModel>
|
||||||
{
|
{
|
||||||
private TreeView _treeView;
|
|
||||||
private Image? _dragAdorner;
|
private Image? _dragAdorner;
|
||||||
private Point _dragStartPosition;
|
private Point _dragStartPosition;
|
||||||
private Point _elementDragOffset;
|
private Point _elementDragOffset;
|
||||||
|
private TreeView _treeView;
|
||||||
|
|
||||||
public ProfileTreeView()
|
public ProfileTreeView()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.Ninject.Factories;
|
using Artemis.UI.Ninject.Factories;
|
||||||
@ -88,6 +89,26 @@ public class ProfileTreeViewModel : TreeItemViewModel
|
|||||||
SelectedChild?.Paste.Execute().Subscribe();
|
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)
|
private void SelectCurrentProfileElement(RenderProfileElement? element)
|
||||||
{
|
{
|
||||||
if (SelectedChild?.ProfileElement == element)
|
if (SelectedChild?.ProfileElement == element)
|
||||||
|
|||||||
@ -8,22 +8,28 @@ using System.Reactive.Linq;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
|
using Artemis.UI.Extensions;
|
||||||
using Artemis.UI.Ninject.Factories;
|
using Artemis.UI.Ninject.Factories;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||||
using Artemis.UI.Shared.Services.ProfileEditor.Commands;
|
using Artemis.UI.Shared.Services.ProfileEditor.Commands;
|
||||||
|
using Avalonia;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree;
|
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree;
|
||||||
|
|
||||||
public abstract class TreeItemViewModel : ActivatableViewModelBase
|
public abstract class TreeItemViewModel : ActivatableViewModelBase
|
||||||
{
|
{
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly ILayerBrushService _layerBrushService;
|
||||||
private readonly IProfileEditorVmFactory _profileEditorVmFactory;
|
private readonly IProfileEditorVmFactory _profileEditorVmFactory;
|
||||||
|
private readonly IRgbService _rgbService;
|
||||||
private readonly IWindowService _windowService;
|
private readonly IWindowService _windowService;
|
||||||
|
protected readonly IProfileEditorService ProfileEditorService;
|
||||||
|
private bool _canPaste;
|
||||||
private RenderProfileElement? _currentProfileElement;
|
private RenderProfileElement? _currentProfileElement;
|
||||||
private bool _isExpanded;
|
private bool _isExpanded;
|
||||||
|
private bool _isFlyoutOpen;
|
||||||
private ProfileElement? _profileElement;
|
private ProfileElement? _profileElement;
|
||||||
private string? _renameValue;
|
private string? _renameValue;
|
||||||
private bool _renaming;
|
private bool _renaming;
|
||||||
@ -35,63 +41,31 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
|
|||||||
ILayerBrushService layerBrushService,
|
ILayerBrushService layerBrushService,
|
||||||
IProfileEditorVmFactory profileEditorVmFactory)
|
IProfileEditorVmFactory profileEditorVmFactory)
|
||||||
{
|
{
|
||||||
|
ProfileEditorService = profileEditorService;
|
||||||
|
_rgbService = rgbService;
|
||||||
|
_layerBrushService = layerBrushService;
|
||||||
_windowService = windowService;
|
_windowService = windowService;
|
||||||
_profileEditorService = profileEditorService;
|
|
||||||
_profileEditorVmFactory = profileEditorVmFactory;
|
_profileEditorVmFactory = profileEditorVmFactory;
|
||||||
|
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
ProfileElement = profileElement;
|
ProfileElement = profileElement;
|
||||||
|
|
||||||
AddLayer = ReactiveCommand.Create(() =>
|
AddLayer = ReactiveCommand.Create(ExecuteAddLayer);
|
||||||
{
|
AddFolder = ReactiveCommand.Create(ExecuteAddFolder);
|
||||||
if (ProfileElement is Layer targetLayer)
|
Rename = ReactiveCommand.Create(ExecuteRename);
|
||||||
{
|
Delete = ReactiveCommand.Create(ExecuteDelete);
|
||||||
Layer layer = new(targetLayer.Parent, targetLayer.GetNewLayerName());
|
Duplicate = ReactiveCommand.CreateFromTask(ExecuteDuplicate);
|
||||||
layerBrushService.ApplyDefaultBrush(layer);
|
Copy = ReactiveCommand.CreateFromTask(ExecuteCopy);
|
||||||
|
Paste = ReactiveCommand.CreateFromTask(ExecutePaste, this.WhenAnyValue(vm => vm.CanPaste));
|
||||||
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));
|
|
||||||
});
|
|
||||||
|
|
||||||
this.WhenActivated(d =>
|
this.WhenActivated(d =>
|
||||||
{
|
{
|
||||||
_profileEditorService.ProfileElement.Subscribe(element => _currentProfileElement = element).DisposeWith(d);
|
ProfileEditorService.ProfileElement.Subscribe(element => _currentProfileElement = element).DisposeWith(d);
|
||||||
SubscribeToProfileElement(d);
|
SubscribeToProfileElement(d);
|
||||||
CreateTreeItems();
|
CreateTreeItems();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.WhenAnyValue(vm => vm.IsFlyoutOpen).Subscribe(UpdateCanPaste);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProfileElement? ProfileElement
|
public ProfileElement? ProfileElement
|
||||||
@ -106,12 +80,24 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
|
|||||||
set => RaiseAndSetIfChanged(ref _isExpanded, value);
|
set => RaiseAndSetIfChanged(ref _isExpanded, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsFlyoutOpen
|
||||||
|
{
|
||||||
|
get => _isFlyoutOpen;
|
||||||
|
set => RaiseAndSetIfChanged(ref _isFlyoutOpen, value);
|
||||||
|
}
|
||||||
|
|
||||||
public bool Renaming
|
public bool Renaming
|
||||||
{
|
{
|
||||||
get => _renaming;
|
get => _renaming;
|
||||||
set => RaiseAndSetIfChanged(ref _renaming, value);
|
set => RaiseAndSetIfChanged(ref _renaming, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool CanPaste
|
||||||
|
{
|
||||||
|
get => _canPaste;
|
||||||
|
set => RaiseAndSetIfChanged(ref _canPaste, value);
|
||||||
|
}
|
||||||
|
|
||||||
public TreeItemViewModel? Parent { get; set; }
|
public TreeItemViewModel? Parent { get; set; }
|
||||||
public ObservableCollection<TreeItemViewModel> Children { get; } = new();
|
public ObservableCollection<TreeItemViewModel> Children { get; } = new();
|
||||||
|
|
||||||
@ -154,7 +140,7 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_profileEditorService.ExecuteCommand(new RenameProfileElement(ProfileElement, RenameValue));
|
ProfileEditorService.ExecuteCommand(new RenameProfileElement(ProfileElement, RenameValue));
|
||||||
Renaming = false;
|
Renaming = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,18 +155,24 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (ProfileElement != null && elementViewModel.ProfileElement != null)
|
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)
|
protected void SubscribeToProfileElement(CompositeDisposable d)
|
||||||
{
|
{
|
||||||
if (ProfileElement == null)
|
if (ProfileElement == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Observable.FromEventPattern<ProfileElementEventArgs>(x => ProfileElement.ChildAdded += x, x => ProfileElement.ChildAdded -= x)
|
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)
|
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)
|
protected void RemoveTreeItemsIfFound(object? sender, ProfileElement profileElement)
|
||||||
@ -202,7 +194,7 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
|
|||||||
newSelection = parent;
|
newSelection = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
_profileEditorService.ChangeCurrentProfileElement(newSelection as RenderProfileElement);
|
ProfileEditorService.ChangeCurrentProfileElement(newSelection as RenderProfileElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void AddTreeItemIfMissing(ProfileElement profileElement)
|
protected void AddTreeItemIfMissing(ProfileElement profileElement)
|
||||||
@ -217,7 +209,7 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
|
|||||||
|
|
||||||
// Select the newly added element
|
// Select the newly added element
|
||||||
if (profileElement is RenderProfileElement renderProfileElement)
|
if (profileElement is RenderProfileElement renderProfileElement)
|
||||||
_profileEditorService.ChangeCurrentProfileElement(renderProfileElement);
|
ProfileEditorService.ChangeCurrentProfileElement(renderProfileElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void CreateTreeItems()
|
protected void CreateTreeItems()
|
||||||
@ -236,4 +228,56 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
|
|||||||
Children.Add(_profileEditorVmFactory.LayerTreeItemViewModel(this, layer));
|
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:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:local="clr-namespace:Artemis.UI.Screens.ProfileEditor.Properties"
|
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: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"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.ProfileEditor.Properties.Timeline.TimelineView"
|
x:Class="Artemis.UI.Screens.ProfileEditor.Properties.Timeline.TimelineView"
|
||||||
x:DataType="timeline:TimelineViewModel">
|
x:DataType="timeline:TimelineViewModel">
|
||||||
@ -23,7 +23,7 @@
|
|||||||
</TreeDataTemplate>
|
</TreeDataTemplate>
|
||||||
</ItemsControl.ItemTemplate>
|
</ItemsControl.ItemTemplate>
|
||||||
</ItemsControl>
|
</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>
|
</Grid>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Keyframes;
|
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.Events;
|
||||||
using Artemis.UI.Shared.Extensions;
|
using Artemis.UI.Shared.Extensions;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
|
|||||||
@ -3,11 +3,11 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
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:sharedConverters="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared"
|
||||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
||||||
xmlns:viewModel="clr-namespace:Artemis.UI.Screens.ProfileEditor.Properties.Tree"
|
xmlns:viewModel="clr-namespace:Artemis.UI.Screens.ProfileEditor.Properties.Tree"
|
||||||
xmlns:properties="clr-namespace:Artemis.UI.Screens.ProfileEditor.Properties"
|
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"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.ProfileEditor.Properties.Tree.TreeGroupView">
|
x:Class="Artemis.UI.Screens.ProfileEditor.Properties.Tree.TreeGroupView">
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
@ -68,7 +68,7 @@
|
|||||||
<!-- Type: LayerBrushRoot -->
|
<!-- Type: LayerBrushRoot -->
|
||||||
<Grid IsVisible="{Binding GroupType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static viewModel:LayerPropertyGroupType.LayerBrushRoot}}"
|
<Grid IsVisible="{Binding GroupType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static viewModel:LayerPropertyGroupType.LayerBrushRoot}}"
|
||||||
ColumnDefinitions="Auto,Auto,Auto,*">
|
ColumnDefinitions="Auto,Auto,Auto,*">
|
||||||
<controls:ArtemisIcon Grid.Column="0"
|
<shared:ArtemisIcon Grid.Column="0"
|
||||||
Icon="{Binding LayerBrush.Descriptor.Icon}"
|
Icon="{Binding LayerBrush.Descriptor.Icon}"
|
||||||
Width="16"
|
Width="16"
|
||||||
Height="16"
|
Height="16"
|
||||||
@ -104,7 +104,7 @@
|
|||||||
<Grid Height="24"
|
<Grid Height="24"
|
||||||
IsVisible="{Binding GroupType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static viewModel:LayerPropertyGroupType.LayerEffectRoot}}"
|
IsVisible="{Binding GroupType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static viewModel:LayerPropertyGroupType.LayerEffectRoot}}"
|
||||||
ColumnDefinitions="Auto,Auto,Auto,Auto,*,Auto">
|
ColumnDefinitions="Auto,Auto,Auto,Auto,*,Auto">
|
||||||
<controls:ArtemisIcon
|
<shared:ArtemisIcon
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Cursor="SizeNorthSouth"
|
Cursor="SizeNorthSouth"
|
||||||
Icon="{Binding LayerEffect.Descriptor.Icon}"
|
Icon="{Binding LayerEffect.Descriptor.Icon}"
|
||||||
|
|||||||
@ -2,19 +2,19 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns: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"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.ProfileEditor.VisualEditor.Tools.SelectionAddToolView" ClipToBounds="False">
|
x:Class="Artemis.UI.Screens.ProfileEditor.VisualEditor.Tools.SelectionAddToolView" ClipToBounds="False">
|
||||||
<Grid>
|
<Grid>
|
||||||
<controls:SelectionRectangle InputElement="{Binding $parent[ZoomBorder]}"
|
<shared:SelectionRectangle InputElement="{Binding $parent[ZoomBorder]}"
|
||||||
BorderBrush="{DynamicResource SystemAccentColor}"
|
BorderBrush="{DynamicResource SystemAccentColor}"
|
||||||
BorderRadius="8"
|
BorderRadius="8"
|
||||||
BorderThickness="2"
|
BorderThickness="2"
|
||||||
SelectionFinished="SelectionRectangle_OnSelectionFinished"
|
SelectionFinished="SelectionRectangle_OnSelectionFinished"
|
||||||
ZoomRatio="{Binding $parent[ZoomBorder].ZoomX}">
|
ZoomRatio="{Binding $parent[ZoomBorder].ZoomX}">
|
||||||
<controls:SelectionRectangle.Background>
|
<shared:SelectionRectangle.Background>
|
||||||
<SolidColorBrush Color="{DynamicResource SystemAccentColorLight1}" Opacity="0.2"></SolidColorBrush>
|
<SolidColorBrush Color="{DynamicResource SystemAccentColorLight1}" Opacity="0.2"></SolidColorBrush>
|
||||||
</controls:SelectionRectangle.Background>
|
</shared:SelectionRectangle.Background>
|
||||||
</controls:SelectionRectangle>
|
</shared:SelectionRectangle>
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -2,21 +2,21 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
|
||||||
xmlns:paz="clr-namespace:Avalonia.Controls.PanAndZoom;assembly=Avalonia.Controls.PanAndZoom"
|
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"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.ProfileEditor.VisualEditor.Tools.SelectionRemoveToolView"
|
x:Class="Artemis.UI.Screens.ProfileEditor.VisualEditor.Tools.SelectionRemoveToolView"
|
||||||
ClipToBounds="False">
|
ClipToBounds="False">
|
||||||
<Grid>
|
<Grid>
|
||||||
<controls:SelectionRectangle InputElement="{Binding $parent[paz:ZoomBorder]}"
|
<shared:SelectionRectangle InputElement="{Binding $parent[paz:ZoomBorder]}"
|
||||||
BorderBrush="{DynamicResource SystemAccentColor}"
|
BorderBrush="{DynamicResource SystemAccentColor}"
|
||||||
BorderRadius="8"
|
BorderRadius="8"
|
||||||
BorderThickness="2"
|
BorderThickness="2"
|
||||||
SelectionFinished="SelectionRectangle_OnSelectionFinished"
|
SelectionFinished="SelectionRectangle_OnSelectionFinished"
|
||||||
ZoomRatio="{Binding $parent[ZoomBorder].ZoomX}">
|
ZoomRatio="{Binding $parent[ZoomBorder].ZoomX}">
|
||||||
<controls:SelectionRectangle.Background>
|
<shared:SelectionRectangle.Background>
|
||||||
<SolidColorBrush Color="{DynamicResource SystemAccentColorLight1}" Opacity="0.2"></SolidColorBrush>
|
<SolidColorBrush Color="{DynamicResource SystemAccentColorLight1}" Opacity="0.2"></SolidColorBrush>
|
||||||
</controls:SelectionRectangle.Background>
|
</shared:SelectionRectangle.Background>
|
||||||
</controls:SelectionRectangle>
|
</shared:SelectionRectangle>
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -4,8 +4,8 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:paz="clr-namespace:Avalonia.Controls.PanAndZoom;assembly=Avalonia.Controls.PanAndZoom"
|
xmlns:paz="clr-namespace:Avalonia.Controls.PanAndZoom;assembly=Avalonia.Controls.PanAndZoom"
|
||||||
xmlns:core="clr-namespace:Artemis.Core;assembly=Artemis.Core"
|
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: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"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.ProfileEditor.VisualEditor.VisualEditorView"
|
x:Class="Artemis.UI.Screens.ProfileEditor.VisualEditor.VisualEditorView"
|
||||||
x:DataType="visualEditor:VisualEditorViewModel">
|
x:DataType="visualEditor:VisualEditorViewModel">
|
||||||
@ -53,7 +53,7 @@
|
|||||||
</ItemsControl.ItemsPanel>
|
</ItemsControl.ItemsPanel>
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate DataType="core:ArtemisDevice">
|
<DataTemplate DataType="core:ArtemisDevice">
|
||||||
<controls:DeviceVisualizer Device="{Binding}" ShowColors="True" />
|
<shared:DeviceVisualizer Device="{Binding}" ShowColors="True" />
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ItemsControl.ItemTemplate>
|
</ItemsControl.ItemTemplate>
|
||||||
</ItemsControl>
|
</ItemsControl>
|
||||||
@ -88,7 +88,11 @@
|
|||||||
<SolidColorBrush Color="{DynamicResource CardStrokeColorDefaultSolid}" Opacity="0.65"></SolidColorBrush>
|
<SolidColorBrush Color="{DynamicResource CardStrokeColorDefaultSolid}" Opacity="0.65"></SolidColorBrush>
|
||||||
</Border.Background>
|
</Border.Background>
|
||||||
<StackPanel Orientation="Horizontal" Margin="8">
|
<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}"/>
|
<TextBlock Text="{CompiledBinding ProfileConfiguration.Name}"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:layerBrushes="clr-namespace:Artemis.Core.LayerBrushes;assembly=Artemis.Core"
|
xmlns:layerBrushes="clr-namespace:Artemis.Core.LayerBrushes;assembly=Artemis.Core"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
|
||||||
xmlns:settings="clr-namespace:Artemis.UI.Screens.Settings"
|
xmlns:settings="clr-namespace:Artemis.UI.Screens.Settings"
|
||||||
|
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||||
mc:Ignorable="d" d:DesignWidth="1000" d:DesignHeight="2400"
|
mc:Ignorable="d" d:DesignWidth="1000" d:DesignHeight="2400"
|
||||||
x:Class="Artemis.UI.Screens.Settings.GeneralTabView"
|
x:Class="Artemis.UI.Screens.Settings.GeneralTabView"
|
||||||
x:DataType="settings:GeneralTabViewModel">
|
x:DataType="settings:GeneralTabViewModel">
|
||||||
@ -61,7 +61,7 @@
|
|||||||
</TextBlock>
|
</TextBlock>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||||
<controls:EnumComboBox Width="150" Value="{CompiledBinding UIColorScheme.Value}" />
|
<shared:EnumComboBox Width="150" Value="{CompiledBinding UIColorScheme.Value}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Separator Classes="card-separator" />
|
<Separator Classes="card-separator" />
|
||||||
@ -76,7 +76,7 @@
|
|||||||
</TextBlock>
|
</TextBlock>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||||
<controls:EnumComboBox Width="150" Value="{CompiledBinding CoreLoggingLevel.Value}" />
|
<shared:EnumComboBox Width="150" Value="{CompiledBinding CoreLoggingLevel.Value}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Separator Classes="card-separator" />
|
<Separator Classes="card-separator" />
|
||||||
|
|||||||
@ -3,12 +3,12 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:core="clr-namespace:Artemis.Core;assembly=Artemis.Core"
|
xmlns:core="clr-namespace:Artemis.Core;assembly=Artemis.Core"
|
||||||
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
|
||||||
xmlns:converters="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared"
|
xmlns:converters="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
xmlns:svg="clr-namespace:Avalonia.Svg.Skia;assembly=Avalonia.Svg.Skia"
|
xmlns:svg="clr-namespace:Avalonia.Svg.Skia;assembly=Avalonia.Svg.Skia"
|
||||||
xmlns:local="clr-namespace:Artemis.UI.Screens.Sidebar"
|
xmlns:local="clr-namespace:Artemis.UI.Screens.Sidebar"
|
||||||
xmlns:controls1="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:controls1="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
|
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="850"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="850"
|
||||||
x:Class="Artemis.UI.Screens.Sidebar.ProfileConfigurationEditView"
|
x:Class="Artemis.UI.Screens.Sidebar.ProfileConfigurationEditView"
|
||||||
Title="{Binding DisplayName}"
|
Title="{Binding DisplayName}"
|
||||||
@ -55,7 +55,7 @@
|
|||||||
<ComboBox.ItemTemplate>
|
<ComboBox.ItemTemplate>
|
||||||
<DataTemplate DataType="{x:Type local:ProfileModuleViewModel}">
|
<DataTemplate DataType="{x:Type local:ProfileModuleViewModel}">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<controls:ArtemisIcon Icon="{Binding Icon}" Width="16" Height="16" Margin="0 0 5 0" />
|
<shared:ArtemisIcon Icon="{Binding Icon}" Width="16" Height="16" Margin="0 0 5 0" />
|
||||||
<TextBlock Text="{Binding Name}" />
|
<TextBlock Text="{Binding Name}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
@ -148,7 +148,7 @@
|
|||||||
IsChecked="{Binding HotkeyMode, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static core:ProfileConfigurationHotkeyMode.EnableDisable}}" />
|
IsChecked="{Binding HotkeyMode, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static core:ProfileConfigurationHotkeyMode.EnableDisable}}" />
|
||||||
</WrapPanel>
|
</WrapPanel>
|
||||||
|
|
||||||
<controls:HotkeyBox Watermark="Toggle hotkey"
|
<shared:HotkeyBox Watermark="Toggle hotkey"
|
||||||
Hotkey="{Binding EnableHotkey}"
|
Hotkey="{Binding EnableHotkey}"
|
||||||
IsVisible="{Binding HotkeyMode, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static core:ProfileConfigurationHotkeyMode.Toggle}}"
|
IsVisible="{Binding HotkeyMode, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static core:ProfileConfigurationHotkeyMode.Toggle}}"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
@ -158,8 +158,8 @@
|
|||||||
IsVisible="{Binding HotkeyMode, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static core:ProfileConfigurationHotkeyMode.EnableDisable}}"
|
IsVisible="{Binding HotkeyMode, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static core:ProfileConfigurationHotkeyMode.EnableDisable}}"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
Margin="0 5 0 0">
|
Margin="0 5 0 0">
|
||||||
<controls:HotkeyBox Watermark="Enable hotkey" Hotkey="{Binding EnableHotkey}" Margin="0 0 4 0" Width="200"/>
|
<shared:HotkeyBox Watermark="Enable hotkey" Hotkey="{Binding EnableHotkey}" Margin="0 0 4 0" Width="200"/>
|
||||||
<controls:HotkeyBox Watermark="Disable hotkey" Hotkey="{Binding DisableHotkey}" Margin="4 0 0 0" Width="200"/>
|
<shared:HotkeyBox Watermark="Disable hotkey" Hotkey="{Binding DisableHotkey}" Margin="4 0 0 0" Width="200"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
|
||||||
xmlns:local="clr-namespace:Artemis.UI.Screens.Sidebar"
|
xmlns:local="clr-namespace:Artemis.UI.Screens.Sidebar"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Sidebar.SidebarCategoryView">
|
x:Class="Artemis.UI.Screens.Sidebar.SidebarCategoryView">
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
||||||
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
|
||||||
xmlns:sidebar="clr-namespace:Artemis.UI.Screens.Sidebar"
|
xmlns:sidebar="clr-namespace:Artemis.UI.Screens.Sidebar"
|
||||||
|
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Sidebar.SidebarProfileConfigurationView"
|
x:Class="Artemis.UI.Screens.Sidebar.SidebarProfileConfigurationView"
|
||||||
x:DataType="sidebar:SidebarProfileConfigurationViewModel">
|
x:DataType="sidebar:SidebarProfileConfigurationViewModel">
|
||||||
@ -68,7 +68,7 @@
|
|||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
</UserControl.ContextMenu>
|
</UserControl.ContextMenu>
|
||||||
<Grid ColumnDefinitions="Auto,*,Auto,Auto">
|
<Grid ColumnDefinitions="Auto,*,Auto,Auto">
|
||||||
<controls:ProfileConfigurationIcon Grid.Column="0"
|
<shared:ProfileConfigurationIcon Grid.Column="0"
|
||||||
x:Name="ProfileIcon"
|
x:Name="ProfileIcon"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
ConfigurationIcon="{CompiledBinding ProfileConfiguration.Icon}"
|
ConfigurationIcon="{CompiledBinding ProfileConfiguration.Icon}"
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns: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"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.SurfaceEditor.SurfaceDeviceView">
|
x:Class="Artemis.UI.Screens.SurfaceEditor.SurfaceDeviceView">
|
||||||
<Grid>
|
<Grid>
|
||||||
@ -20,7 +20,7 @@
|
|||||||
</Style>
|
</Style>
|
||||||
</Grid.Styles>
|
</Grid.Styles>
|
||||||
|
|
||||||
<controls:DeviceVisualizer Device="{Binding Device}" ShowColors="True"/>
|
<shared:DeviceVisualizer Device="{Binding Device}" ShowColors="True"/>
|
||||||
<Border x:Name="SurfaceDeviceBorder"
|
<Border x:Name="SurfaceDeviceBorder"
|
||||||
Classes="selection-border"
|
Classes="selection-border"
|
||||||
Classes.selection-border-selected="{Binding Highlighted}"
|
Classes.selection-border-selected="{Binding Highlighted}"
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:paz="clr-namespace:Avalonia.Controls.PanAndZoom;assembly=Avalonia.Controls.PanAndZoom"
|
xmlns:paz="clr-namespace:Avalonia.Controls.PanAndZoom;assembly=Avalonia.Controls.PanAndZoom"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
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"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.SurfaceEditor.SurfaceEditorView">
|
x:Class="Artemis.UI.Screens.SurfaceEditor.SurfaceEditorView">
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
@ -101,15 +101,15 @@
|
|||||||
</ItemsControl.ItemTemplate>
|
</ItemsControl.ItemTemplate>
|
||||||
</ItemsControl>
|
</ItemsControl>
|
||||||
|
|
||||||
<controls:SelectionRectangle Name="SelectionRectangle"
|
<shared:SelectionRectangle Name="SelectionRectangle"
|
||||||
InputElement="{Binding #ZoomBorder}"
|
InputElement="{Binding #ZoomBorder}"
|
||||||
SelectionUpdated="SelectionRectangle_OnSelectionUpdated"
|
SelectionUpdated="SelectionRectangle_OnSelectionUpdated"
|
||||||
BorderBrush="{DynamicResource SystemAccentColor}"
|
BorderBrush="{DynamicResource SystemAccentColor}"
|
||||||
BorderRadius="8">
|
BorderRadius="8">
|
||||||
<controls:SelectionRectangle.Background>
|
<shared:SelectionRectangle.Background>
|
||||||
<SolidColorBrush Color="{DynamicResource SystemAccentColorLight1}" Opacity="0.2"></SolidColorBrush>
|
<SolidColorBrush Color="{DynamicResource SystemAccentColorLight1}" Opacity="0.2"></SolidColorBrush>
|
||||||
</controls:SelectionRectangle.Background>
|
</shared:SelectionRectangle.Background>
|
||||||
</controls:SelectionRectangle>
|
</shared:SelectionRectangle>
|
||||||
|
|
||||||
<Border Name="SurfaceBounds"
|
<Border Name="SurfaceBounds"
|
||||||
VerticalAlignment="Top"
|
VerticalAlignment="Top"
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
using Artemis.UI.Shared.Controls;
|
using Artemis.UI.Shared;
|
||||||
using Artemis.UI.Shared.Events;
|
using Artemis.UI.Shared.Events;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:paz="clr-namespace:Avalonia.Controls.PanAndZoom;assembly=Avalonia.Controls.PanAndZoom"
|
xmlns:paz="clr-namespace:Avalonia.Controls.PanAndZoom;assembly=Avalonia.Controls.PanAndZoom"
|
||||||
xmlns:visualScripting="clr-namespace:Artemis.UI.Screens.VisualScripting"
|
xmlns:visualScripting="clr-namespace:Artemis.UI.Screens.VisualScripting"
|
||||||
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"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.VisualScripting.NodeScriptView"
|
x:Class="Artemis.UI.Screens.VisualScripting.NodeScriptView"
|
||||||
x:DataType="visualScripting:NodeScriptViewModel"
|
x:DataType="visualScripting:NodeScriptViewModel"
|
||||||
@ -76,16 +76,16 @@
|
|||||||
</ItemsControl.Styles>
|
</ItemsControl.Styles>
|
||||||
</ItemsControl>
|
</ItemsControl>
|
||||||
|
|
||||||
<controls:SelectionRectangle Name="SelectionRectangle"
|
<shared:SelectionRectangle Name="SelectionRectangle"
|
||||||
InputElement="{Binding #ZoomBorder}"
|
InputElement="{Binding #ZoomBorder}"
|
||||||
SelectionUpdated="SelectionRectangle_OnSelectionUpdated"
|
SelectionUpdated="SelectionRectangle_OnSelectionUpdated"
|
||||||
SelectionFinished="SelectionRectangle_OnSelectionFinished"
|
SelectionFinished="SelectionRectangle_OnSelectionFinished"
|
||||||
BorderBrush="{DynamicResource SystemAccentColor}"
|
BorderBrush="{DynamicResource SystemAccentColor}"
|
||||||
BorderRadius="8">
|
BorderRadius="8">
|
||||||
<controls:SelectionRectangle.Background>
|
<shared:SelectionRectangle.Background>
|
||||||
<SolidColorBrush Color="{DynamicResource SystemAccentColorLight1}" Opacity="0.2"></SolidColorBrush>
|
<SolidColorBrush Color="{DynamicResource SystemAccentColorLight1}" Opacity="0.2"></SolidColorBrush>
|
||||||
</controls:SelectionRectangle.Background>
|
</shared:SelectionRectangle.Background>
|
||||||
</controls:SelectionRectangle>
|
</shared:SelectionRectangle>
|
||||||
</Grid>
|
</Grid>
|
||||||
</paz:ZoomBorder>
|
</paz:ZoomBorder>
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ using System.Reactive.Disposables;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Events;
|
using Artemis.Core.Events;
|
||||||
using Artemis.UI.Shared.Controls;
|
using Artemis.UI.Shared;
|
||||||
using Artemis.UI.Shared.Events;
|
using Artemis.UI.Shared.Events;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
@ -153,7 +153,7 @@ public class NodeScriptView : ReactiveUserControl<NodeScriptViewModel>
|
|||||||
|
|
||||||
private void ZoomBorder_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
|
private void ZoomBorder_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
|
||||||
{
|
{
|
||||||
if (!_selectionRectangle.IsSelecting)
|
if (!_selectionRectangle.IsSelecting && e.InitialPressMouseButton == MouseButton.Left)
|
||||||
ViewModel?.ClearNodeSelection();
|
ViewModel?.ClearNodeSelection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,16 +3,16 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:builders="clr-namespace:Artemis.UI.Shared.Services.Builders;assembly=Artemis.UI.Shared"
|
xmlns:builders="clr-namespace:Artemis.UI.Shared.Services.Builders;assembly=Artemis.UI.Shared"
|
||||||
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
|
||||||
xmlns:controls1="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:controls1="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:attachedProperties="clr-namespace:Artemis.UI.Shared.AttachedProperties;assembly=Artemis.UI.Shared"
|
xmlns:attachedProperties="clr-namespace:Artemis.UI.Shared.AttachedProperties;assembly=Artemis.UI.Shared"
|
||||||
xmlns:workshop="clr-namespace:Artemis.UI.Screens.Workshop"
|
xmlns:workshop="clr-namespace:Artemis.UI.Screens.Workshop"
|
||||||
xmlns:gradientPicker="clr-namespace:Artemis.UI.Shared.Controls.GradientPicker;assembly=Artemis.UI.Shared"
|
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||||
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker;assembly=Artemis.UI.Shared"
|
xmlns:gradientPicker="clr-namespace:Artemis.UI.Shared.GradientPicker;assembly=Artemis.UI.Shared"
|
||||||
mc:Ignorable="d" d:DesignWidth="800"
|
mc:Ignorable="d" d:DesignWidth="800"
|
||||||
x:Class="Artemis.UI.Screens.Workshop.WorkshopView"
|
x:Class="Artemis.UI.Screens.Workshop.WorkshopView"
|
||||||
x:DataType="workshop:WorkshopViewModel">
|
x:DataType="workshop:WorkshopViewModel">
|
||||||
<Border Classes="router-container">
|
<Border Classes="router-container">
|
||||||
|
<ScrollViewer>
|
||||||
<StackPanel Margin="12" Spacing="5">
|
<StackPanel Margin="12" Spacing="5">
|
||||||
<Border Classes="card">
|
<Border Classes="card">
|
||||||
<StackPanel Spacing="5">
|
<StackPanel Spacing="5">
|
||||||
@ -37,31 +37,32 @@
|
|||||||
Notification test (success)
|
Notification test (success)
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<controls:HotkeyBox Watermark="Some hotkey" Width="250" HorizontalAlignment="Left" />
|
<shared:HotkeyBox Watermark="Some hotkey" Width="250" HorizontalAlignment="Left" />
|
||||||
|
|
||||||
<controls1:NumberBox
|
<controls1:NumberBox
|
||||||
attachedProperties:NumberBoxAssist.PrefixText="$"
|
attachedProperties:NumberBoxAssist.PrefixText="$"
|
||||||
attachedProperties:NumberBoxAssist.SuffixText="%"></controls1:NumberBox>
|
attachedProperties:NumberBoxAssist.SuffixText="%">
|
||||||
|
</controls1:NumberBox>
|
||||||
|
|
||||||
<TextBox
|
<TextBox
|
||||||
attachedProperties:TextBoxAssist.PrefixText="$"
|
attachedProperties:TextBoxAssist.PrefixText="$"
|
||||||
attachedProperties:TextBoxAssist.SuffixText="%"></TextBox>
|
attachedProperties:TextBoxAssist.SuffixText="%">
|
||||||
|
</TextBox>
|
||||||
|
|
||||||
<StackPanel Orientation="Horizontal" Spacing="5">
|
<StackPanel Orientation="Horizontal" Spacing="5">
|
||||||
<Border Classes="card" Cursor="{CompiledBinding Cursor}">
|
<Border Classes="card" Cursor="{CompiledBinding Cursor}">
|
||||||
<TextBlock Text="{CompiledBinding SelectedCursor}"></TextBlock>
|
<TextBlock Text="{CompiledBinding SelectedCursor}"></TextBlock>
|
||||||
</Border>
|
</Border>
|
||||||
<controls:EnumComboBox Value="{CompiledBinding SelectedCursor}"></controls:EnumComboBox>
|
<shared:EnumComboBox Value="{CompiledBinding SelectedCursor}"></shared:EnumComboBox>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<Button Command="{Binding CreateRandomGradient}">
|
<Button Command="{Binding CreateRandomGradient}">
|
||||||
Create random gradient
|
Create random gradient
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
|
||||||
<gradientPicker:GradientPickerButton ColorGradient="{CompiledBinding ColorGradient}" IsCompact="True" />
|
<gradientPicker:GradientPickerButton ColorGradient="{CompiledBinding ColorGradient}" IsCompact="True" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
</Border>
|
</Border>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
using Artemis.Core;
|
||||||
|
using Artemis.Core.Events;
|
||||||
|
|
||||||
|
namespace Artemis.VisualScripting.Nodes.Branching;
|
||||||
|
|
||||||
|
[Node("Branch", "Forwards one of two values depending on an input boolean", "Branching", InputType = typeof(object), OutputType = typeof(object))]
|
||||||
|
public class BooleanBranchNode : Node
|
||||||
|
{
|
||||||
|
public BooleanBranchNode() : base("Branch", "Forwards one of two values depending on an input boolean")
|
||||||
|
{
|
||||||
|
BooleanInput = CreateInputPin<bool>();
|
||||||
|
TrueInput = CreateInputPin(typeof(object), "True");
|
||||||
|
FalseInput = CreateInputPin(typeof(object), "False");
|
||||||
|
|
||||||
|
Output = CreateOutputPin(typeof(object));
|
||||||
|
|
||||||
|
TrueInput.PinConnected += InputPinConnected;
|
||||||
|
FalseInput.PinConnected += InputPinConnected;
|
||||||
|
TrueInput.PinDisconnected += InputPinDisconnected;
|
||||||
|
FalseInput.PinDisconnected += InputPinDisconnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InputPinConnected(object? sender, SingleValueEventArgs<IPin> e)
|
||||||
|
{
|
||||||
|
if (TrueInput.ConnectedTo.Any() && !FalseInput.ConnectedTo.Any())
|
||||||
|
ChangeType(TrueInput.ConnectedTo.First().Type);
|
||||||
|
if (FalseInput.ConnectedTo.Any() && !TrueInput.ConnectedTo.Any())
|
||||||
|
ChangeType(FalseInput.ConnectedTo.First().Type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InputPinDisconnected(object? sender, SingleValueEventArgs<IPin> e)
|
||||||
|
{
|
||||||
|
if (!TrueInput.ConnectedTo.Any() && !FalseInput.ConnectedTo.Any())
|
||||||
|
ChangeType(typeof(object));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ChangeType(Type type)
|
||||||
|
{
|
||||||
|
TrueInput.ChangeType(type);
|
||||||
|
FalseInput.ChangeType(type);
|
||||||
|
Output.ChangeType(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputPin<bool> BooleanInput { get; set; }
|
||||||
|
public InputPin TrueInput { get; set; }
|
||||||
|
public InputPin FalseInput { get; set; }
|
||||||
|
|
||||||
|
public OutputPin Output { get; set; }
|
||||||
|
|
||||||
|
#region Overrides of Node
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Evaluate()
|
||||||
|
{
|
||||||
|
Output.Value = BooleanInput.Value ? TrueInput.Value : FalseInput.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
@ -12,8 +12,9 @@ public class DataModelEventNode : Node<DataModelPathEntity, DataModelEventNodeCu
|
|||||||
private int _currentIndex;
|
private int _currentIndex;
|
||||||
private Type _currentType;
|
private Type _currentType;
|
||||||
private DataModelPath? _dataModelPath;
|
private DataModelPath? _dataModelPath;
|
||||||
private DateTime _lastTrigger;
|
|
||||||
private bool _updating;
|
private bool _updating;
|
||||||
|
private DateTime _lastTrigger;
|
||||||
|
private object? _lastPathValue;
|
||||||
|
|
||||||
public DataModelEventNode() : base("Data Model-Event", "Responds to a data model event trigger")
|
public DataModelEventNode() : base("Data Model-Event", "Responds to a data model event trigger")
|
||||||
{
|
{
|
||||||
@ -47,27 +48,44 @@ public class DataModelEventNode : Node<DataModelPathEntity, DataModelEventNodeCu
|
|||||||
|
|
||||||
public override void Evaluate()
|
public override void Evaluate()
|
||||||
{
|
{
|
||||||
object? outputValue = null;
|
object? pathValue = _dataModelPath?.GetValue();
|
||||||
if (_dataModelPath?.GetValue() is IDataModelEvent dataModelEvent)
|
bool hasTriggered = pathValue is IDataModelEvent dataModelEvent
|
||||||
|
? EvaluateEvent(dataModelEvent)
|
||||||
|
: EvaluateValue(pathValue);
|
||||||
|
|
||||||
|
if (hasTriggered)
|
||||||
{
|
{
|
||||||
if (dataModelEvent.LastTrigger > _lastTrigger)
|
|
||||||
{
|
|
||||||
_lastTrigger = dataModelEvent.LastTrigger;
|
|
||||||
_currentIndex++;
|
_currentIndex++;
|
||||||
|
|
||||||
if (_currentIndex >= CycleValues.Count())
|
if (_currentIndex >= CycleValues.Count())
|
||||||
_currentIndex = 0;
|
_currentIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
outputValue = CycleValues.ElementAt(_currentIndex).PinValue;
|
object? outputValue = CycleValues.ElementAt(_currentIndex).PinValue;
|
||||||
}
|
|
||||||
|
|
||||||
if (Output.Type.IsInstanceOfType(outputValue))
|
if (Output.Type.IsInstanceOfType(outputValue))
|
||||||
Output.Value = outputValue;
|
Output.Value = outputValue;
|
||||||
else if (Output.Type.IsValueType)
|
else if (Output.Type.IsValueType)
|
||||||
Output.Value = Output.Type.GetDefault()!;
|
Output.Value = Output.Type.GetDefault()!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool EvaluateEvent(IDataModelEvent dataModelEvent)
|
||||||
|
{
|
||||||
|
if (dataModelEvent.LastTrigger <= _lastTrigger)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_lastTrigger = dataModelEvent.LastTrigger;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool EvaluateValue(object? pathValue)
|
||||||
|
{
|
||||||
|
if (Equals(pathValue, _lastPathValue))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_lastPathValue = pathValue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private void CycleValuesOnPinAdded(object? sender, SingleValueEventArgs<IPin> e)
|
private void CycleValuesOnPinAdded(object? sender, SingleValueEventArgs<IPin> e)
|
||||||
{
|
{
|
||||||
e.Value.PinConnected += OnPinConnected;
|
e.Value.PinConnected += OnPinConnected;
|
||||||
@ -109,7 +127,6 @@ public class DataModelEventNode : Node<DataModelPathEntity, DataModelEventNodeCu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void UpdateDataModelPath()
|
private void UpdateDataModelPath()
|
||||||
{
|
{
|
||||||
DataModelPath? old = _dataModelPath;
|
DataModelPath? old = _dataModelPath;
|
||||||
|
|||||||
@ -2,8 +2,8 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker;assembly=Artemis.UI.Shared"
|
|
||||||
xmlns:screens="clr-namespace:Artemis.VisualScripting.Nodes.DataModel.Screens"
|
xmlns:screens="clr-namespace:Artemis.VisualScripting.Nodes.DataModel.Screens"
|
||||||
|
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.DataModelPicker;assembly=Artemis.UI.Shared"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.VisualScripting.Nodes.DataModel.Screens.DataModelEventNodeCustomView"
|
x:Class="Artemis.VisualScripting.Nodes.DataModel.Screens.DataModelEventNodeCustomView"
|
||||||
x:DataType="screens:DataModelEventNodeCustomViewModel">
|
x:DataType="screens:DataModelEventNodeCustomViewModel">
|
||||||
@ -11,6 +11,8 @@
|
|||||||
DataModelPath="{CompiledBinding DataModelPath}"
|
DataModelPath="{CompiledBinding DataModelPath}"
|
||||||
Modules="{CompiledBinding Modules}"
|
Modules="{CompiledBinding Modules}"
|
||||||
ShowDataModelValues="{CompiledBinding ShowDataModelValues.Value}"
|
ShowDataModelValues="{CompiledBinding ShowDataModelValues.Value}"
|
||||||
FilterTypes="{CompiledBinding FilterTypes}"
|
ShowFullPath="{CompiledBinding ShowFullPaths.Value}"
|
||||||
VerticalAlignment="Top"/>
|
IsEventPicker="True"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
MaxWidth="300"/>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -50,7 +50,6 @@ public class DataModelEventNodeCustomViewModel : CustomNodeViewModel
|
|||||||
|
|
||||||
public PluginSetting<bool> ShowFullPaths { get; }
|
public PluginSetting<bool> ShowFullPaths { get; }
|
||||||
public PluginSetting<bool> ShowDataModelValues { get; }
|
public PluginSetting<bool> ShowDataModelValues { get; }
|
||||||
public ObservableCollection<Type> FilterTypes { get; } = new() {typeof(IDataModelEvent)};
|
|
||||||
|
|
||||||
public ObservableCollection<Module>? Modules
|
public ObservableCollection<Module>? Modules
|
||||||
{
|
{
|
||||||
|
|||||||
@ -2,8 +2,8 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker;assembly=Artemis.UI.Shared"
|
|
||||||
xmlns:screens="clr-namespace:Artemis.VisualScripting.Nodes.DataModel.Screens"
|
xmlns:screens="clr-namespace:Artemis.VisualScripting.Nodes.DataModel.Screens"
|
||||||
|
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.DataModelPicker;assembly=Artemis.UI.Shared"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.VisualScripting.Nodes.DataModel.Screens.DataModelNodeCustomView"
|
x:Class="Artemis.VisualScripting.Nodes.DataModel.Screens.DataModelNodeCustomView"
|
||||||
x:DataType="screens:DataModelNodeCustomViewModel">
|
x:DataType="screens:DataModelNodeCustomViewModel">
|
||||||
@ -11,5 +11,6 @@
|
|||||||
DataModelPath="{CompiledBinding DataModelPath}"
|
DataModelPath="{CompiledBinding DataModelPath}"
|
||||||
Modules="{CompiledBinding Modules}"
|
Modules="{CompiledBinding Modules}"
|
||||||
ShowDataModelValues="{CompiledBinding ShowDataModelValues.Value}"
|
ShowDataModelValues="{CompiledBinding ShowDataModelValues.Value}"
|
||||||
ShowFullPath="{CompiledBinding ShowFullPaths.Value}"/>
|
ShowFullPath="{CompiledBinding ShowFullPaths.Value}"
|
||||||
|
MaxWidth="300"/>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -9,7 +9,7 @@
|
|||||||
<ComboBox IsEnabled="{CompiledBinding EnumValues.Count}"
|
<ComboBox IsEnabled="{CompiledBinding EnumValues.Count}"
|
||||||
Items="{CompiledBinding EnumValues}"
|
Items="{CompiledBinding EnumValues}"
|
||||||
SelectedIndex="{CompiledBinding CurrentValue}"
|
SelectedIndex="{CompiledBinding CurrentValue}"
|
||||||
PlaceholderText="Connect a pin..."
|
PlaceholderText="Select a value"
|
||||||
Classes="condensed"
|
Classes="condensed"
|
||||||
VerticalAlignment="Center" />
|
VerticalAlignment="Center" />
|
||||||
</UserControl>
|
</UserControl>
|
||||||
Loading…
x
Reference in New Issue
Block a user