mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-12 21:38:38 +00:00
Merge branch 'development' into feature/workshop
This commit is contained in:
commit
3860ef0f3d
4
.github/workflows/docfx.yml
vendored
4
.github/workflows/docfx.yml
vendored
@ -18,13 +18,13 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
dotnet-version: "7.0.x"
|
dotnet-version: "7.0.x"
|
||||||
- name: Setup DocFX
|
- name: Setup DocFX
|
||||||
run: choco install docfx -y
|
run: dotnet tool update -g docfx
|
||||||
- name: Build Core
|
- name: Build Core
|
||||||
run: dotnet build src/Artemis.Core/Artemis.Core.csproj
|
run: dotnet build src/Artemis.Core/Artemis.Core.csproj
|
||||||
- name: Build UI.Shared
|
- name: Build UI.Shared
|
||||||
run: dotnet build src/Artemis.UI.Shared/Artemis.UI.Shared.csproj
|
run: dotnet build src/Artemis.UI.Shared/Artemis.UI.Shared.csproj
|
||||||
- name: Build DocFX
|
- name: Build DocFX
|
||||||
run: docfx.exe docfx/docfx_project/docfx.json
|
run: docfx docfx/docfx_project/docfx.json
|
||||||
- name: Upload to FTP
|
- name: Upload to FTP
|
||||||
uses: SamKirkland/FTP-Deploy-Action@4.3.2
|
uses: SamKirkland/FTP-Deploy-Action@4.3.2
|
||||||
with:
|
with:
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
{
|
{
|
||||||
"files": [
|
"files": [
|
||||||
"Artemis.Core/bin/net7.0/Artemis.Core.dll",
|
"Artemis.Core/bin/net7.0/Artemis.Core.dll",
|
||||||
"Artemis.UI.Shared/bin/net7.0/Artemis.UI.Shared.dll",
|
"Artemis.UI.Shared/bin/net7.0/Artemis.UI.Shared.dll"
|
||||||
],
|
],
|
||||||
"src": "../../src"
|
"src": "../../src"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,9 +43,9 @@
|
|||||||
<PackageReference Include="LiteDB" Version="5.0.16" />
|
<PackageReference Include="LiteDB" Version="5.0.16" />
|
||||||
<PackageReference Include="McMaster.NETCore.Plugins" Version="1.4.0" />
|
<PackageReference Include="McMaster.NETCore.Plugins" Version="1.4.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
<PackageReference Include="RGB.NET.Core" Version="2.0.0-prerelease.69" />
|
<PackageReference Include="RGB.NET.Core" Version="2.0.0-prerelease.83" />
|
||||||
<PackageReference Include="RGB.NET.Layout" Version="2.0.0-prerelease.69" />
|
<PackageReference Include="RGB.NET.Layout" Version="2.0.0-prerelease.83" />
|
||||||
<PackageReference Include="RGB.NET.Presets" Version="2.0.0-prerelease.69" />
|
<PackageReference Include="RGB.NET.Presets" Version="2.0.0-prerelease.83" />
|
||||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" />
|
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" />
|
||||||
|
|||||||
@ -16,11 +16,11 @@
|
|||||||
<None Remove=".gitignore" />
|
<None Remove=".gitignore" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Avalonia" Version="11.0.0-preview8" />
|
<PackageReference Include="Avalonia" Version="11.0.0-rc1.1" />
|
||||||
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-preview8" />
|
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-rc1.1" />
|
||||||
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
||||||
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-preview8" />
|
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-rc1.1" />
|
||||||
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-preview8" />
|
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-rc1.1" />
|
||||||
<PackageReference Include="ReactiveUI" Version="18.4.26" />
|
<PackageReference Include="ReactiveUI" Version="18.4.26" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@ -15,11 +15,11 @@
|
|||||||
<None Remove=".gitignore" />
|
<None Remove=".gitignore" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Avalonia" Version="11.0.0-preview8" />
|
<PackageReference Include="Avalonia" Version="11.0.0-rc1.1" />
|
||||||
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-preview8" />
|
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-rc1.1" />
|
||||||
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
||||||
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-preview8" />
|
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-rc1.1" />
|
||||||
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-preview8" />
|
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-rc1.1" />
|
||||||
<PackageReference Include="ReactiveUI" Version="18.4.26" />
|
<PackageReference Include="ReactiveUI" Version="18.4.26" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@ -10,17 +10,17 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Avalonia" Version="11.0.0-preview8" />
|
<PackageReference Include="Avalonia" Version="11.0.0-rc1.1" />
|
||||||
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
||||||
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-preview8" />
|
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-rc1.1" />
|
||||||
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-preview8" />
|
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-rc1.1" />
|
||||||
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.0.0-preview8" />
|
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.0.0-rc1.1" />
|
||||||
<PackageReference Include="DynamicData" Version="7.13.1" />
|
<PackageReference Include="DynamicData" Version="7.13.1" />
|
||||||
<PackageReference Include="FluentAvaloniaUI" Version="2.0.0-preview8" />
|
<PackageReference Include="FluentAvaloniaUI" Version="2.0.0-rc1" />
|
||||||
<PackageReference Include="Material.Icons.Avalonia" Version="2.0.0-preview3" />
|
<PackageReference Include="Material.Icons.Avalonia" Version="2.0.1" />
|
||||||
<PackageReference Include="ReactiveUI" Version="18.4.26" />
|
<PackageReference Include="ReactiveUI" Version="18.4.26" />
|
||||||
<PackageReference Include="ReactiveUI.Validation" Version="3.1.7" />
|
<PackageReference Include="ReactiveUI.Validation" Version="3.1.7" />
|
||||||
<PackageReference Include="RGB.NET.Core" Version="2.0.0-prerelease.69" />
|
<PackageReference Include="RGB.NET.Core" Version="2.0.0-prerelease.83" />
|
||||||
<PackageReference Include="SkiaSharp" Version="2.88.3" />
|
<PackageReference Include="SkiaSharp" Version="2.88.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.Shared.Events;
|
using Artemis.UI.Shared.Events;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
@ -13,6 +14,7 @@ using Avalonia.Media;
|
|||||||
using Avalonia.Media.Imaging;
|
using Avalonia.Media.Imaging;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using RGB.NET.Core;
|
using RGB.NET.Core;
|
||||||
|
using DryIoc;
|
||||||
using Color = RGB.NET.Core.Color;
|
using Color = RGB.NET.Core.Color;
|
||||||
using Point = Avalonia.Point;
|
using Point = Avalonia.Point;
|
||||||
using Size = Avalonia.Size;
|
using Size = Avalonia.Size;
|
||||||
@ -24,20 +26,19 @@ namespace Artemis.UI.Shared;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class DeviceVisualizer : Control
|
public class DeviceVisualizer : Control
|
||||||
{
|
{
|
||||||
private const double UPDATE_FRAME_RATE = 25.0;
|
private readonly ICoreService _coreService;
|
||||||
private readonly List<DeviceVisualizerLed> _deviceVisualizerLeds;
|
private readonly List<DeviceVisualizerLed> _deviceVisualizerLeds;
|
||||||
private readonly DispatcherTimer _timer;
|
|
||||||
|
|
||||||
private Rect _deviceBounds;
|
private Rect _deviceBounds;
|
||||||
private RenderTargetBitmap? _deviceImage;
|
private RenderTargetBitmap? _deviceImage;
|
||||||
private ArtemisDevice? _oldDevice;
|
private ArtemisDevice? _oldDevice;
|
||||||
private bool _loading;
|
private bool _loading;
|
||||||
private Color[] _previousState = Array.Empty<Color>();
|
private Color[] _previousState = Array.Empty<Color>();
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public DeviceVisualizer()
|
public DeviceVisualizer()
|
||||||
{
|
{
|
||||||
_timer = new DispatcherTimer(DispatcherPriority.Background) {Interval = TimeSpan.FromMilliseconds(1000.0 / UPDATE_FRAME_RATE)};
|
_coreService = UI.Locator.Resolve<ICoreService>();
|
||||||
_deviceVisualizerLeds = new List<DeviceVisualizerLed>();
|
_deviceVisualizerLeds = new List<DeviceVisualizerLed>();
|
||||||
|
|
||||||
PointerReleased += OnPointerReleased;
|
PointerReleased += OnPointerReleased;
|
||||||
@ -120,23 +121,26 @@ public class DeviceVisualizer : Control
|
|||||||
if (Device == null)
|
if (Device == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Color[] state = new Color[Device.RgbDevice.Count()];
|
bool difference = false;
|
||||||
bool difference = _previousState.Length != state.Length;
|
|
||||||
|
int newLedCount = Device.RgbDevice.Count();
|
||||||
|
if (_previousState.Length != newLedCount)
|
||||||
|
{
|
||||||
|
_previousState = new Color[newLedCount];
|
||||||
|
difference = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Check all LEDs for differences and copy the colors to a new state
|
// Check all LEDs for differences and copy the colors to a new state
|
||||||
int index = 0;
|
int index = 0;
|
||||||
foreach (Led led in Device.RgbDevice)
|
foreach (Led led in Device.RgbDevice)
|
||||||
{
|
{
|
||||||
if (!difference && !led.Color.Equals(_previousState[index]))
|
if (_previousState[index] != led.Color)
|
||||||
difference = true;
|
difference = true;
|
||||||
|
|
||||||
state[index] = led.Color;
|
_previousState[index] = led.Color;
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the new state for next time
|
|
||||||
_previousState = state;
|
|
||||||
|
|
||||||
return difference;
|
return difference;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,11 +160,14 @@ public class DeviceVisualizer : Control
|
|||||||
|
|
||||||
return geometry.Bounds;
|
return geometry.Bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TimerOnTick(object? sender, EventArgs e)
|
private void OnFrameRendered(object? sender, FrameRenderedEventArgs e)
|
||||||
{
|
{
|
||||||
if (IsDirty() && ShowColors && IsVisible && Opacity > 0)
|
Dispatcher.UIThread.Post(() =>
|
||||||
Update();
|
{
|
||||||
|
if (ShowColors && IsVisible && Opacity > 0 && IsDirty())
|
||||||
|
Update();
|
||||||
|
}, DispatcherPriority.Background);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPointerReleased(object? sender, PointerReleasedEventArgs e)
|
private void OnPointerReleased(object? sender, PointerReleasedEventArgs e)
|
||||||
@ -250,16 +257,16 @@ public class DeviceVisualizer : Control
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
|
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
|
||||||
{
|
{
|
||||||
_timer.Start();
|
_coreService.FrameRendered += OnFrameRendered;
|
||||||
_timer.Tick += TimerOnTick;
|
|
||||||
base.OnAttachedToLogicalTree(e);
|
base.OnAttachedToLogicalTree(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
|
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
|
||||||
{
|
{
|
||||||
_timer.Stop();
|
_coreService.FrameRendered -= OnFrameRendered;
|
||||||
_timer.Tick -= TimerOnTick;
|
|
||||||
base.OnDetachedFromLogicalTree(e);
|
base.OnDetachedFromLogicalTree(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,25 +6,27 @@
|
|||||||
xmlns:sharedControls="clr-namespace:Artemis.UI.Shared.Controls"
|
xmlns:sharedControls="clr-namespace:Artemis.UI.Shared.Controls"
|
||||||
xmlns:attachedProperties="clr-namespace:Artemis.UI.Shared.AttachedProperties"
|
xmlns:attachedProperties="clr-namespace:Artemis.UI.Shared.AttachedProperties"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Shared.Controls.DraggableNumberBox">
|
x:Class="Artemis.UI.Shared.Controls.DraggableNumberBox"
|
||||||
|
Focusable="True">
|
||||||
<UserControl.Styles>
|
<UserControl.Styles>
|
||||||
<Styles>
|
<Styles>
|
||||||
<Style Selector="sharedControls|DraggableNumberBox:not(:focus-within)">
|
<Style Selector="Panel#Container:not(:focus-within)">
|
||||||
<Setter Property="Cursor" Value="{DynamicResource DragHorizontalCursor}" />
|
<Setter Property="Cursor" Value="{DynamicResource DragHorizontalCursor}" />
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<Style Selector="sharedControls|DraggableNumberBox:focus-within Rectangle#DragCollider">
|
<Style Selector="#Container:focus-within Rectangle#DragCollider">
|
||||||
<Setter Property="IsHitTestVisible" Value="False" />
|
<Setter Property="IsHitTestVisible" Value="False" />
|
||||||
</Style>
|
</Style>
|
||||||
<Style Selector="sharedControls|DraggableNumberBox:not(:focus-within) controls|NumberBox#NumberBox">
|
<Style Selector="#Container:not(:focus-within) controls|NumberBox#NumberBox">
|
||||||
<Setter Property="IsHitTestVisible" Value="False" />
|
<Setter Property="IsHitTestVisible" Value="False" />
|
||||||
</Style>
|
</Style>
|
||||||
</Styles>
|
</Styles>
|
||||||
</UserControl.Styles>
|
</UserControl.Styles>
|
||||||
|
|
||||||
<Panel>
|
<Panel Name="Container" Focusable="True">
|
||||||
<controls:NumberBox Name="InnerNumberBox"
|
<controls:NumberBox Name="InnerNumberBox"
|
||||||
AcceptsExpression="True"
|
AcceptsExpression="True"
|
||||||
|
Focusable="True"
|
||||||
LargeChange="{CompiledBinding $parent[sharedControls:DraggableNumberBox].LargeChange}"
|
LargeChange="{CompiledBinding $parent[sharedControls:DraggableNumberBox].LargeChange}"
|
||||||
SmallChange="{CompiledBinding $parent[sharedControls:DraggableNumberBox].SmallChange}"
|
SmallChange="{CompiledBinding $parent[sharedControls:DraggableNumberBox].SmallChange}"
|
||||||
Minimum="{CompiledBinding $parent[sharedControls:DraggableNumberBox].Minimum}"
|
Minimum="{CompiledBinding $parent[sharedControls:DraggableNumberBox].Minimum}"
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Data;
|
using Avalonia.Data;
|
||||||
@ -68,7 +69,7 @@ public partial class DraggableNumberBox : UserControl
|
|||||||
public DraggableNumberBox()
|
public DraggableNumberBox()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
PointerPressed += OnPointerPressed;
|
PointerPressed += OnPointerPressed;
|
||||||
PointerMoved += OnPointerMoved;
|
PointerMoved += OnPointerMoved;
|
||||||
PointerReleased += OnPointerReleased;
|
PointerReleased += OnPointerReleased;
|
||||||
@ -186,8 +187,8 @@ public partial class DraggableNumberBox : UserControl
|
|||||||
|
|
||||||
private void HandleKeyUp(object? sender, KeyEventArgs e)
|
private void HandleKeyUp(object? sender, KeyEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Key == Key.Enter || e.Key == Key.Escape)
|
if (e.Key is Key.Enter or Key.Escape)
|
||||||
FocusManager.Instance?.Focus(Parent as IInputElement);
|
Focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPointerPressed(object? sender, PointerPressedEventArgs e)
|
private void OnPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||||
@ -215,9 +216,9 @@ public partial class DraggableNumberBox : UserControl
|
|||||||
if (!_moved)
|
if (!_moved)
|
||||||
{
|
{
|
||||||
// Let our parent take focus, it would make more sense to take focus ourselves but that hides the collider
|
// Let our parent take focus, it would make more sense to take focus ourselves but that hides the collider
|
||||||
FocusManager.Instance?.Focus(Parent as IInputElement);
|
PseudoClasses.Add("dragging");
|
||||||
|
Focus();
|
||||||
_moved = true;
|
_moved = true;
|
||||||
e.Pointer.Capture(this);
|
|
||||||
DragStarted?.Invoke(this, EventArgs.Empty);
|
DragStarted?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,6 +253,7 @@ public partial class DraggableNumberBox : UserControl
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
_moved = false;
|
_moved = false;
|
||||||
|
PseudoClasses.Remove("dragging");
|
||||||
DragFinished?.Invoke(this, EventArgs.Empty);
|
DragFinished?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@ using Avalonia.Input;
|
|||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
|
using Avalonia.VisualTree;
|
||||||
using DryIoc;
|
using DryIoc;
|
||||||
using FluentAvalonia.Core;
|
using FluentAvalonia.Core;
|
||||||
using Humanizer;
|
using Humanizer;
|
||||||
@ -40,7 +41,7 @@ public partial class HotkeyBox : UserControl
|
|||||||
{
|
{
|
||||||
_inputService.KeyboardKeyDown += InputServiceOnKeyboardKeyDown;
|
_inputService.KeyboardKeyDown += InputServiceOnKeyboardKeyDown;
|
||||||
_inputService.KeyboardKeyUp += InputServiceOnKeyboardKeyUp;
|
_inputService.KeyboardKeyUp += InputServiceOnKeyboardKeyUp;
|
||||||
|
|
||||||
base.OnGotFocus(e);
|
base.OnGotFocus(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,10 +50,10 @@ public partial class HotkeyBox : UserControl
|
|||||||
{
|
{
|
||||||
_inputService.KeyboardKeyDown -= InputServiceOnKeyboardKeyDown;
|
_inputService.KeyboardKeyDown -= InputServiceOnKeyboardKeyDown;
|
||||||
_inputService.KeyboardKeyUp -= InputServiceOnKeyboardKeyUp;
|
_inputService.KeyboardKeyUp -= InputServiceOnKeyboardKeyUp;
|
||||||
|
|
||||||
base.OnLostFocus(e);
|
base.OnLostFocus(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
|
private void OnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Property == HotkeyProperty)
|
if (e.Property == HotkeyProperty)
|
||||||
@ -67,7 +68,7 @@ public partial class HotkeyBox : UserControl
|
|||||||
Hotkey ??= new Hotkey();
|
Hotkey ??= new Hotkey();
|
||||||
Hotkey.Key = e.Key;
|
Hotkey.Key = e.Key;
|
||||||
Hotkey.Modifiers = e.Modifiers;
|
Hotkey.Modifiers = e.Modifiers;
|
||||||
|
|
||||||
Dispatcher.UIThread.Post(() =>
|
Dispatcher.UIThread.Post(() =>
|
||||||
{
|
{
|
||||||
UpdateDisplayTextBox();
|
UpdateDisplayTextBox();
|
||||||
@ -78,7 +79,19 @@ public partial class HotkeyBox : UserControl
|
|||||||
private void InputServiceOnKeyboardKeyUp(object? sender, ArtemisKeyboardKeyEventArgs e)
|
private void InputServiceOnKeyboardKeyUp(object? sender, ArtemisKeyboardKeyEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Modifiers == KeyboardModifierKey.None)
|
if (e.Modifiers == KeyboardModifierKey.None)
|
||||||
Dispatcher.UIThread.Post(() => FocusManager.Instance?.Focus(null));
|
Dispatcher.UIThread.Post(ClearFocus);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearFocus()
|
||||||
|
{
|
||||||
|
InputElement? element = this.FindAncestorOfType<InputElement>();
|
||||||
|
if (element == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool wasFocusable = element.Focusable;
|
||||||
|
element.Focusable = true;
|
||||||
|
element.Focus();
|
||||||
|
element.Focusable = wasFocusable;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateDisplayTextBox()
|
private void UpdateDisplayTextBox()
|
||||||
@ -96,7 +109,7 @@ public partial class HotkeyBox : UserControl
|
|||||||
private void Button_OnClick(object? sender, RoutedEventArgs e)
|
private void Button_OnClick(object? sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
Hotkey = null;
|
Hotkey = null;
|
||||||
FocusManager.Instance?.Focus(null);
|
ClearFocus();
|
||||||
|
|
||||||
UpdateDisplayTextBox();
|
UpdateDisplayTextBox();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,7 +48,7 @@ public class ReactiveAppWindow<TViewModel> : AppWindow, IViewFor<TViewModel> whe
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
TransparencyBackgroundFallback = Brushes.Transparent;
|
TransparencyBackgroundFallback = Brushes.Transparent;
|
||||||
TransparencyLevelHint = WindowTransparencyLevel.Mica;
|
TransparencyLevelHint = new[] {WindowTransparencyLevel.Mica};
|
||||||
TryEnableMicaEffect();
|
TryEnableMicaEffect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,15 @@
|
|||||||
<TextBlock>I'm in a panel yo!</TextBlock>
|
<TextBlock>I'm in a panel yo!</TextBlock>
|
||||||
<Border Classes="card-separator" />
|
<Border Classes="card-separator" />
|
||||||
<TextBlock>I'm in a panel yo!</TextBlock>
|
<TextBlock>I'm in a panel yo!</TextBlock>
|
||||||
|
<Border Classes="card-separator-slim" />
|
||||||
|
<TextBlock>I'm in a panel yo!</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
<Border Classes="card" Margin="20">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock>I'm in a panel yo!</TextBlock>
|
||||||
|
<Border Classes="card-separator-vertical" />
|
||||||
|
<TextBlock>I'm in a panel yo!</TextBlock>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
@ -50,4 +59,23 @@
|
|||||||
<Setter Property="Height" Value="1" />
|
<Setter Property="Height" Value="1" />
|
||||||
|
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="Border.card-separator-slim">
|
||||||
|
<Setter Property="Background" Value="{DynamicResource ButtonBorderBrush}" />
|
||||||
|
<Setter Property="Margin" Value="-12 10" />
|
||||||
|
<Setter Property="Height" Value="1" />
|
||||||
|
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="Border.card-separator-vertical">
|
||||||
|
<Setter Property="Background" Value="{DynamicResource ButtonBorderBrush}" />
|
||||||
|
<Setter Property="Margin" Value="15 -12" />
|
||||||
|
<Setter Property="Width" Value="1" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="Border.card-separator-slim-vertical">
|
||||||
|
<Setter Property="Background" Value="{DynamicResource ButtonBorderBrush}" />
|
||||||
|
<Setter Property="Margin" Value="10 -12" />
|
||||||
|
<Setter Property="Width" Value="1" />
|
||||||
|
</Style>
|
||||||
</Styles>
|
</Styles>
|
||||||
@ -1,7 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
using System.Reactive.Subjects;
|
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Input.Platform;
|
using Avalonia.Input.Platform;
|
||||||
@ -14,12 +12,9 @@ namespace Artemis.UI.Shared;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class UI
|
public static class UI
|
||||||
{
|
{
|
||||||
private static readonly BehaviorSubject<bool> KeyBindingsEnabledSubject = new(false);
|
|
||||||
|
|
||||||
static UI()
|
static UI()
|
||||||
{
|
{
|
||||||
if (KeyboardDevice.Instance != null)
|
KeyBindingsEnabled = InputElement.GotFocusEvent.Raised.Select(e => e.Item2.Source is not TextBox).StartWith(true);
|
||||||
KeyboardDevice.Instance.PropertyChanged += InstanceOnPropertyChanged;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -35,15 +30,5 @@ public static class UI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a boolean indicating whether hotkeys are to be disabled.
|
/// Gets a boolean indicating whether hotkeys are to be disabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static IObservable<bool> KeyBindingsEnabled { get; } = KeyBindingsEnabledSubject.AsObservable();
|
public static IObservable<bool> KeyBindingsEnabled { get; }
|
||||||
|
|
||||||
private static void InstanceOnPropertyChanged(object? sender, PropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
if (KeyboardDevice.Instance == null || e.PropertyName != nameof(KeyboardDevice.FocusedElement))
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool enabled = KeyboardDevice.Instance.FocusedElement is not TextBox;
|
|
||||||
if (KeyBindingsEnabledSubject.Value != enabled)
|
|
||||||
KeyBindingsEnabledSubject.OnNext(enabled);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net7.0-windows10.0.17763.0</TargetFramework>
|
<TargetFramework>net7.0-windows10.0.17763.0</TargetFramework>
|
||||||
@ -21,15 +21,15 @@
|
|||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Avalonia" Version="11.0.0-preview8" />
|
<PackageReference Include="Avalonia" Version="11.0.0-rc1.1" />
|
||||||
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-preview8" />
|
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-rc1.1" />
|
||||||
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
||||||
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-preview8" />
|
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-rc1.1" />
|
||||||
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-preview8" />
|
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-rc1.1" />
|
||||||
<PackageReference Include="Avalonia.Win32" Version="11.0.0-preview8" />
|
<PackageReference Include="Avalonia.Win32" Version="11.0.0-rc1.1" />
|
||||||
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.3" />
|
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.3" />
|
||||||
<PackageReference Include="Microsoft.Win32" Version="2.0.1" />
|
<PackageReference Include="Microsoft.Win32" Version="2.0.1" />
|
||||||
<PackageReference Include="Microsoft.Windows.Compatibility" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Windows.Compatibility" Version="7.0.3" />
|
||||||
<PackageReference Include="RawInput.Sharp" Version="0.1.1" />
|
<PackageReference Include="RawInput.Sharp" Version="0.1.1" />
|
||||||
<PackageReference Include="ReactiveUI" Version="18.4.26" />
|
<PackageReference Include="ReactiveUI" Version="18.4.26" />
|
||||||
<PackageReference Include="SkiaSharp.Vulkan.SharpVk" Version="2.88.3" />
|
<PackageReference Include="SkiaSharp.Vulkan.SharpVk" Version="2.88.3" />
|
||||||
|
|||||||
@ -16,25 +16,25 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Avalonia" Version="11.0.0-preview8" />
|
<PackageReference Include="Avalonia" Version="11.0.0-rc1.1" />
|
||||||
<PackageReference Include="Avalonia.Controls.PanAndZoom" Version="11.0.0-preview8" />
|
<PackageReference Include="Avalonia.Controls.PanAndZoom" Version="11.0.0-rc1.1" />
|
||||||
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-preview8" />
|
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-rc1.1" />
|
||||||
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
||||||
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-preview8" />
|
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-rc1.1" />
|
||||||
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-preview8" />
|
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-rc1.1" />
|
||||||
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.0.0-preview8" />
|
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.0.0-rc1.1" />
|
||||||
<PackageReference Include="DryIoc.dll" Version="5.4.0" />
|
<PackageReference Include="DryIoc.dll" Version="5.4.0" />
|
||||||
<PackageReference Include="DynamicData" Version="7.13.1" />
|
<PackageReference Include="DynamicData" Version="7.13.1" />
|
||||||
<PackageReference Include="FluentAvaloniaUI" Version="2.0.0-preview8" />
|
<PackageReference Include="FluentAvaloniaUI" Version="2.0.0-rc1" />
|
||||||
<PackageReference Include="Flurl.Http" Version="3.2.4" />
|
<PackageReference Include="Flurl.Http" Version="3.2.4" />
|
||||||
<PackageReference Include="Live.Avalonia" Version="1.3.1" />
|
<PackageReference Include="Live.Avalonia" Version="1.3.1" />
|
||||||
<PackageReference Include="Markdown.Avalonia.Tight" Version="11.0.0-c1" />
|
<PackageReference Include="Markdown.Avalonia.Tight" Version="11.0.0-d1" />
|
||||||
<PackageReference Include="Material.Icons.Avalonia" Version="2.0.0-preview3" />
|
<PackageReference Include="Material.Icons.Avalonia" Version="2.0.1" />
|
||||||
<PackageReference Include="Octopus.Octodiff" Version="2.0.261" />
|
<PackageReference Include="Octopus.Octodiff" Version="2.0.261" />
|
||||||
<PackageReference Include="ReactiveUI" Version="18.4.26" />
|
<PackageReference Include="ReactiveUI" Version="18.4.26" />
|
||||||
<PackageReference Include="ReactiveUI.Validation" Version="3.1.7" />
|
<PackageReference Include="ReactiveUI.Validation" Version="3.1.7" />
|
||||||
<PackageReference Include="RGB.NET.Core" Version="2.0.0-prerelease.69" />
|
<PackageReference Include="RGB.NET.Core" Version="2.0.0-prerelease.83" />
|
||||||
<PackageReference Include="RGB.NET.Layout" Version="2.0.0-prerelease.69" />
|
<PackageReference Include="RGB.NET.Layout" Version="2.0.0-prerelease.83" />
|
||||||
<PackageReference Include="SkiaSharp" Version="2.88.3" />
|
<PackageReference Include="SkiaSharp" Version="2.88.3" />
|
||||||
<PackageReference Include="Splat.DryIoc" Version="14.6.8" />
|
<PackageReference Include="Splat.DryIoc" Version="14.6.8" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@ -42,27 +42,4 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AvaloniaResource Include="Assets\**" />
|
<AvaloniaResource Include="Assets\**" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Update="Screens\Settings\Tabs\ReleasesTabView.axaml.cs">
|
|
||||||
<DependentUpon>UpdatingTabView.axaml</DependentUpon>
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Update="Screens\Settings\Updating\ReleaseView.axaml.cs">
|
|
||||||
<DependentUpon>UpdatingTabView.axaml</DependentUpon>
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Update="Screens\Plugins\Features\PluginFeatureView.axaml.cs">
|
|
||||||
<DependentUpon>PluginFeatureView.axaml</DependentUpon>
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Update="Screens\Plugins\Prerequisites\PluginPrerequisiteActionView.axaml.cs">
|
|
||||||
<DependentUpon>PluginPrerequisiteActionView.axaml</DependentUpon>
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Update="Screens\Plugins\Prerequisites\PluginPrerequisiteView.axaml.cs">
|
|
||||||
<DependentUpon>PluginPrerequisiteView.axaml</DependentUpon>
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
</Project>
|
||||||
@ -103,8 +103,9 @@ public class SimpleContextDragBehavior : Behavior<Control>
|
|||||||
|
|
||||||
private void AssociatedObject_PointerPressed(object? sender, PointerPressedEventArgs e)
|
private void AssociatedObject_PointerPressed(object? sender, PointerPressedEventArgs e)
|
||||||
{
|
{
|
||||||
|
IFocusManager? focusManager = TopLevel.GetTopLevel(AssociatedObject)?.FocusManager;
|
||||||
PointerPointProperties properties = e.GetCurrentPoint(AssociatedObject).Properties;
|
PointerPointProperties properties = e.GetCurrentPoint(AssociatedObject).Properties;
|
||||||
if (!properties.IsLeftButtonPressed || FocusManager.Instance?.Current is TextBox)
|
if (!properties.IsLeftButtonPressed || focusManager?.GetFocusedElement() is TextBox)
|
||||||
return;
|
return;
|
||||||
if (e.Source is not Control control || AssociatedObject?.DataContext != control.DataContext)
|
if (e.Source is not Control control || AssociatedObject?.DataContext != control.DataContext)
|
||||||
return;
|
return;
|
||||||
@ -130,8 +131,9 @@ public class SimpleContextDragBehavior : Behavior<Control>
|
|||||||
|
|
||||||
private async void AssociatedObject_PointerMoved(object? sender, PointerEventArgs e)
|
private async void AssociatedObject_PointerMoved(object? sender, PointerEventArgs e)
|
||||||
{
|
{
|
||||||
|
IFocusManager? focusManager = TopLevel.GetTopLevel(AssociatedObject)?.FocusManager;
|
||||||
PointerPointProperties properties = e.GetCurrentPoint(AssociatedObject).Properties;
|
PointerPointProperties properties = e.GetCurrentPoint(AssociatedObject).Properties;
|
||||||
if (!properties.IsLeftButtonPressed || FocusManager.Instance?.Current is TextBox)
|
if (!properties.IsLeftButtonPressed || focusManager?.GetFocusedElement() is TextBox)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_triggerEvent is null)
|
if (_triggerEvent is null)
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Markup.Xaml;
|
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.DefaultTypes.PropertyInput;
|
namespace Artemis.UI.DefaultTypes.PropertyInput;
|
||||||
@ -16,6 +15,6 @@ public partial class StringPropertyInputView : ReactiveUserControl<FloatProperty
|
|||||||
private void OnRoutedKeyUp(object? sender, KeyEventArgs e)
|
private void OnRoutedKeyUp(object? sender, KeyEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Key == Key.Enter || e.Key == Key.Escape)
|
if (e.Key == Key.Enter || e.Key == Key.Escape)
|
||||||
FocusManager.Instance!.Focus(null);
|
Focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -25,6 +25,7 @@ using Artemis.UI.Screens.Sidebar;
|
|||||||
using Artemis.UI.Screens.SurfaceEditor;
|
using Artemis.UI.Screens.SurfaceEditor;
|
||||||
using Artemis.UI.Screens.VisualScripting;
|
using Artemis.UI.Screens.VisualScripting;
|
||||||
using Artemis.UI.Screens.VisualScripting.Pins;
|
using Artemis.UI.Screens.VisualScripting.Pins;
|
||||||
|
using Artemis.UI.Shared;
|
||||||
using DryIoc;
|
using DryIoc;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
@ -39,10 +40,10 @@ public interface IDeviceVmFactory : IVmFactory
|
|||||||
DevicePropertiesViewModel DevicePropertiesViewModel(ArtemisDevice device);
|
DevicePropertiesViewModel DevicePropertiesViewModel(ArtemisDevice device);
|
||||||
DeviceSettingsViewModel DeviceSettingsViewModel(ArtemisDevice device, DevicesTabViewModel devicesTabViewModel);
|
DeviceSettingsViewModel DeviceSettingsViewModel(ArtemisDevice device, DevicesTabViewModel devicesTabViewModel);
|
||||||
DeviceDetectInputViewModel DeviceDetectInputViewModel(ArtemisDevice device);
|
DeviceDetectInputViewModel DeviceDetectInputViewModel(ArtemisDevice device);
|
||||||
DevicePropertiesTabViewModel DevicePropertiesTabViewModel(ArtemisDevice device);
|
DeviceLayoutTabViewModel DeviceLayoutTabViewModel(ArtemisDevice device);
|
||||||
DeviceInfoTabViewModel DeviceInfoTabViewModel(ArtemisDevice device);
|
|
||||||
DeviceLedsTabViewModel DeviceLedsTabViewModel(ArtemisDevice device, ObservableCollection<ArtemisLed> selectedLeds);
|
DeviceLedsTabViewModel DeviceLedsTabViewModel(ArtemisDevice device, ObservableCollection<ArtemisLed> selectedLeds);
|
||||||
InputMappingsTabViewModel InputMappingsTabViewModel(ArtemisDevice device, ObservableCollection<ArtemisLed> selectedLeds);
|
InputMappingsTabViewModel InputMappingsTabViewModel(ArtemisDevice device, ObservableCollection<ArtemisLed> selectedLeds);
|
||||||
|
DeviceGeneralTabViewModel DeviceGeneralTabViewModel(ArtemisDevice device);
|
||||||
}
|
}
|
||||||
public class DeviceFactory : IDeviceVmFactory
|
public class DeviceFactory : IDeviceVmFactory
|
||||||
{
|
{
|
||||||
@ -68,16 +69,11 @@ public class DeviceFactory : IDeviceVmFactory
|
|||||||
return _container.Resolve<DeviceDetectInputViewModel>(new object[] { device });
|
return _container.Resolve<DeviceDetectInputViewModel>(new object[] { device });
|
||||||
}
|
}
|
||||||
|
|
||||||
public DevicePropertiesTabViewModel DevicePropertiesTabViewModel(ArtemisDevice device)
|
public DeviceLayoutTabViewModel DeviceLayoutTabViewModel(ArtemisDevice device)
|
||||||
{
|
{
|
||||||
return _container.Resolve<DevicePropertiesTabViewModel>(new object[] { device });
|
return _container.Resolve<DeviceLayoutTabViewModel>(new object[] { device });
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeviceInfoTabViewModel DeviceInfoTabViewModel(ArtemisDevice device)
|
|
||||||
{
|
|
||||||
return _container.Resolve<DeviceInfoTabViewModel>(new object[] { device });
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeviceLedsTabViewModel DeviceLedsTabViewModel(ArtemisDevice device, ObservableCollection<ArtemisLed> selectedLeds)
|
public DeviceLedsTabViewModel DeviceLedsTabViewModel(ArtemisDevice device, ObservableCollection<ArtemisLed> selectedLeds)
|
||||||
{
|
{
|
||||||
return _container.Resolve<DeviceLedsTabViewModel>(new object[] { device, selectedLeds });
|
return _container.Resolve<DeviceLedsTabViewModel>(new object[] { device, selectedLeds });
|
||||||
@ -87,6 +83,11 @@ public class DeviceFactory : IDeviceVmFactory
|
|||||||
{
|
{
|
||||||
return _container.Resolve<InputMappingsTabViewModel>(new object[] { device, selectedLeds });
|
return _container.Resolve<InputMappingsTabViewModel>(new object[] { device, selectedLeds });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DeviceGeneralTabViewModel DeviceGeneralTabViewModel(ArtemisDevice device)
|
||||||
|
{
|
||||||
|
return _container.Resolve<DeviceGeneralTabViewModel>(new object[] { device });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ISettingsVmFactory : IVmFactory
|
public interface ISettingsVmFactory : IVmFactory
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
<TextBlock TextWrapping="Wrap" Classes="subtitle" Margin="0 10">
|
<TextBlock TextWrapping="Wrap" Classes="subtitle" Margin="0 10">
|
||||||
These performance stats are rather basic, for advanced performance profiling check out the wiki.
|
These performance stats are rather basic, for advanced performance profiling check out the wiki.
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
<controls:HyperlinkButton Grid.Column="1" NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/plugins/profiling">
|
<controls:HyperlinkButton Grid.Column="1" NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/plugins/profiling?mtm_campaign=artemis&mtm_kwd=debugger">
|
||||||
JetBrains Profiling Guide
|
JetBrains Profiling Guide
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@ -1,58 +1,59 @@
|
|||||||
<windowing:AppWindow xmlns="https://github.com/avaloniaui"
|
<windowing:AppWindow xmlns="https://github.com/avaloniaui"
|
||||||
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:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||||
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
|
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
|
||||||
xmlns:windowing="clr-namespace:FluentAvalonia.UI.Windowing;assembly=FluentAvalonia"
|
xmlns:windowing="clr-namespace:FluentAvalonia.UI.Windowing;assembly=FluentAvalonia"
|
||||||
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"
|
||||||
x:DataType="device:DevicePropertiesViewModel"
|
x:DataType="device:DevicePropertiesViewModel"
|
||||||
Icon="/Assets/Images/Logo/application.ico"
|
Icon="/Assets/Images/Logo/application.ico"
|
||||||
Title="Artemis | Device Properties"
|
Title="Artemis | Device Properties"
|
||||||
WindowStartupLocation="CenterOwner"
|
WindowStartupLocation="CenterOwner"
|
||||||
Width="1250"
|
Width="1400"
|
||||||
Height="900">
|
Height="800">
|
||||||
<windowing:AppWindow.KeyBindings>
|
<windowing:AppWindow.KeyBindings>
|
||||||
<KeyBinding Gesture="Escape" Command="{CompiledBinding ClearSelectedLeds}" />
|
<KeyBinding Gesture="Escape" Command="{CompiledBinding ClearSelectedLeds}" />
|
||||||
</windowing:AppWindow.KeyBindings>
|
</windowing:AppWindow.KeyBindings>
|
||||||
<Grid ColumnDefinitions="*,0,1.5*">
|
<Grid ColumnDefinitions="*,0,1.5*">
|
||||||
<Grid.Background>
|
<Border Grid.Column="0" Classes="card" Margin="5">
|
||||||
<VisualBrush TileMode="Tile" Stretch="Uniform" DestinationRect="0,0,25,25">
|
<Border.Background>
|
||||||
<VisualBrush.Visual>
|
<VisualBrush TileMode="Tile" Stretch="Uniform" DestinationRect="0,0,25,25">
|
||||||
<Grid Width="25" Height="25" RowDefinitions="*,*" ColumnDefinitions="*,*">
|
<VisualBrush.Visual>
|
||||||
<Rectangle Grid.Row="0" Grid.Column="0" Fill="Black" Opacity="0.15" />
|
<Grid Width="25" Height="25" RowDefinitions="*,*" ColumnDefinitions="*,*">
|
||||||
<Rectangle Grid.Row="0" Grid.Column="1" />
|
<Rectangle Grid.Row="0" Grid.Column="0" Fill="Black" Opacity="0.15" />
|
||||||
<Rectangle Grid.Row="1" Grid.Column="0" />
|
<Rectangle Grid.Row="0" Grid.Column="1" />
|
||||||
<Rectangle Grid.Row="1" Grid.Column="1" Fill="Black" Opacity="0.15" />
|
<Rectangle Grid.Row="1" Grid.Column="0" />
|
||||||
</Grid>
|
<Rectangle Grid.Row="1" Grid.Column="1" Fill="Black" Opacity="0.15" />
|
||||||
</VisualBrush.Visual>
|
</Grid>
|
||||||
</VisualBrush>
|
</VisualBrush.Visual>
|
||||||
</Grid.Background>
|
</VisualBrush>
|
||||||
<Grid Grid.Column="0" Name="DeviceDisplayGrid" PointerReleased="DeviceDisplayGrid_OnPointerReleased">
|
</Border.Background>
|
||||||
<shared:DeviceVisualizer Device="{CompiledBinding Device}"
|
<Grid Name="DeviceDisplayGrid" PointerReleased="DeviceDisplayGrid_OnPointerReleased">
|
||||||
HorizontalAlignment="Center"
|
<shared:DeviceVisualizer Device="{CompiledBinding Device}"
|
||||||
VerticalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
ShowColors="True"
|
VerticalAlignment="Center"
|
||||||
Margin="20"
|
ShowColors="True"
|
||||||
RenderOptions.BitmapInterpolationMode="MediumQuality"
|
Margin="5"
|
||||||
LedClicked="DeviceVisualizer_OnLedClicked"
|
RenderOptions.BitmapInterpolationMode="MediumQuality"
|
||||||
Clicked="DeviceVisualizer_OnClicked" />
|
LedClicked="DeviceVisualizer_OnLedClicked"
|
||||||
|
Clicked="DeviceVisualizer_OnClicked" />
|
||||||
|
|
||||||
<StackPanel Orientation="Horizontal"
|
<StackPanel Orientation="Horizontal"
|
||||||
VerticalAlignment="Bottom"
|
VerticalAlignment="Bottom"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
Margin="15"
|
IsVisible="{CompiledBinding Device.Layout.RgbLayout.Author, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
|
||||||
IsVisible="{CompiledBinding Device.Layout.RgbLayout.Author, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
|
<TextBlock Classes="h5" Text="Device layout by " />
|
||||||
<TextBlock Classes="h5" Text="Device layout by " />
|
<TextBlock Classes="h5" FontWeight="Bold" Text="{CompiledBinding Device.Layout.RgbLayout.Author}" />
|
||||||
<TextBlock Classes="h5" FontWeight="Bold" Text="{CompiledBinding Device.Layout.RgbLayout.Author}" />
|
</StackPanel>
|
||||||
</StackPanel>
|
</Grid>
|
||||||
</Grid>
|
</Border>
|
||||||
|
|
||||||
|
|
||||||
<GridSplitter Grid.Column="1" Width="15" Margin="-15 0 0 0" Background="Transparent" HorizontalAlignment="Stretch" />
|
<GridSplitter Grid.Column="1" Width="15" Margin="-15 0 0 0" Background="Transparent" HorizontalAlignment="Stretch" />
|
||||||
|
|
||||||
<Border Grid.Column="2" Classes="card-condensed" CornerRadius="10 0 0 0" Margin="0 10 0 0" Background="#ff323232">
|
<Border Grid.Column="2" Classes="card-condensed" Margin="5">
|
||||||
<Panel>
|
<Panel>
|
||||||
<TabControl ItemsSource="{CompiledBinding Tabs}" IsVisible="{CompiledBinding Tabs.Count}" Padding="12">
|
<TabControl ItemsSource="{CompiledBinding Tabs}" IsVisible="{CompiledBinding Tabs.Count}" Padding="12">
|
||||||
<TabControl.ItemTemplate>
|
<TabControl.ItemTemplate>
|
||||||
@ -69,6 +70,6 @@
|
|||||||
|
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<StackPanel Grid.Column="0" Grid.ColumnSpan="3" Classes="notification-container" Name="NotificationContainer" VerticalAlignment="Bottom" HorizontalAlignment="Right" />
|
<StackPanel Grid.Column="0" Grid.ColumnSpan="3" Classes="notification-container" Name="NotificationContainer" VerticalAlignment="Top" HorizontalAlignment="Right" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</windowing:AppWindow>
|
</windowing:AppWindow>
|
||||||
@ -64,8 +64,8 @@ public class DevicePropertiesViewModel : DialogViewModelBase<object>
|
|||||||
|
|
||||||
private void AddTabs()
|
private void AddTabs()
|
||||||
{
|
{
|
||||||
Tabs.Add(_deviceVmFactory.DevicePropertiesTabViewModel(Device));
|
Tabs.Add(_deviceVmFactory.DeviceGeneralTabViewModel(Device));
|
||||||
Tabs.Add(_deviceVmFactory.DeviceInfoTabViewModel(Device));
|
Tabs.Add(_deviceVmFactory.DeviceLayoutTabViewModel(Device));
|
||||||
if (Device.DeviceType == RGBDeviceType.Keyboard)
|
if (Device.DeviceType == RGBDeviceType.Keyboard)
|
||||||
Tabs.Add(_deviceVmFactory.InputMappingsTabViewModel(Device, SelectedLeds));
|
Tabs.Add(_deviceVmFactory.InputMappingsTabViewModel(Device, SelectedLeds));
|
||||||
Tabs.Add(_deviceVmFactory.DeviceLedsTabViewModel(Device, SelectedLeds));
|
Tabs.Add(_deviceVmFactory.DeviceLedsTabViewModel(Device, SelectedLeds));
|
||||||
|
|||||||
210
src/Artemis.UI/Screens/Device/Tabs/DeviceGeneralTabView.axaml
Normal file
210
src/Artemis.UI/Screens/Device/Tabs/DeviceGeneralTabView.axaml
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
|
xmlns:converters="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared"
|
||||||
|
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="650"
|
||||||
|
x:Class="Artemis.UI.Screens.Device.DeviceGeneralTabView"
|
||||||
|
x:DataType="device:DeviceGeneralTabViewModel">
|
||||||
|
<UserControl.Resources>
|
||||||
|
<converters:SKColorToColorConverter x:Key="SKColorToColorConverter" />
|
||||||
|
</UserControl.Resources>
|
||||||
|
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
||||||
|
<Grid RowDefinitions="*,Auto">
|
||||||
|
<StackPanel Grid.Row="0" Orientation="Vertical">
|
||||||
|
<!-- Device information and categories -->
|
||||||
|
<Grid ColumnDefinitions="*,*" RowDefinitions="*,*">
|
||||||
|
<TextBlock Grid.Column="0" Grid.Row="0" Classes="card-title" Text="Information" Margin="10,0,0,0" />
|
||||||
|
<Border Grid.Column="0" Grid.Row="1" Classes="card" Margin="5" x:Name="InformationBorder">
|
||||||
|
<Grid ColumnDefinitions="*,Auto" RowDefinitions="*,*,*,*,*,*">
|
||||||
|
<StackPanel Grid.Row="0" Grid.Column="0">
|
||||||
|
<TextBlock Text="Model" />
|
||||||
|
<TextBlock Classes="subtitle" FontSize="12" TextWrapping="Wrap" Text="{CompiledBinding Device.RgbDevice.DeviceInfo.Model}" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="1" Grid.Column="0">
|
||||||
|
<TextBlock Text="Manufacturer" />
|
||||||
|
<TextBlock Classes="subtitle" FontSize="12" TextWrapping="Wrap" Text="{CompiledBinding Device.RgbDevice.DeviceInfo.Manufacturer}" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="2" Grid.Column="0">
|
||||||
|
<TextBlock Text="Device Type" />
|
||||||
|
<TextBlock Classes="subtitle" FontSize="12" TextWrapping="Wrap" Text="{CompiledBinding Device.RgbDevice.DeviceInfo.DeviceType}" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="3" Grid.Column="0">
|
||||||
|
<TextBlock Text="Size (1px = 1mm)" />
|
||||||
|
<TextBlock Classes="subtitle" FontSize="12" TextWrapping="Wrap" Text="{CompiledBinding Device.RgbDevice.Size}" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="4" Grid.Column="0" IsVisible="{CompiledBinding IsKeyboard}">
|
||||||
|
<TextBlock Text="Physical Layout" />
|
||||||
|
<TextBlock Classes="subtitle" FontSize="12" TextWrapping="Wrap" Text="{CompiledBinding Device.PhysicalLayout}" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="5" Grid.Column="0" IsVisible="{CompiledBinding IsKeyboard}" >
|
||||||
|
<TextBlock Text="Logical Layout" />
|
||||||
|
<TextBlock Classes="subtitle" FontSize="12" TextWrapping="Wrap" Text="{CompiledBinding Device.LogicalLayout}" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<TextBlock Grid.Column="1" Grid.Row="0" Classes="card-title" Text="Categories" Margin="10,0,0,0" />
|
||||||
|
<Border Grid.Row="1" Grid.Column="1" Classes="card" Margin="5" x:Name="CategoryBorder">
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock TextWrapping="Wrap" Text="Artemis uses categories to determine where the layers of imported profiles are applied to." />
|
||||||
|
<Grid ColumnDefinitions="*,Auto" RowDefinitions="*,*,*,*,*" Margin="0,10,0,0">
|
||||||
|
<StackPanel Grid.Row="0" Grid.Column="0" Margin="0,0,0,10">
|
||||||
|
<TextBlock Text="Peripheral" />
|
||||||
|
<TextBlock Classes="subtitle" FontSize="12" TextWrapping="Wrap" Text="A peripheral such as a mouse or keyboard" />
|
||||||
|
</StackPanel>
|
||||||
|
<CheckBox Grid.Row="0" Grid.Column="1" IsChecked="{CompiledBinding HasPeripheralsCategory}" />
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="1" Grid.Column="0" Margin="0,0,0,10">
|
||||||
|
<TextBlock Text="Desk" />
|
||||||
|
<TextBlock Classes="subtitle" FontSize="12" TextWrapping="Wrap" Text="A device acting as desk ornamentation such as a LED strip" />
|
||||||
|
</StackPanel>
|
||||||
|
<CheckBox Grid.Row="1" Grid.Column="1" IsChecked="{CompiledBinding HasDeskCategory}" />
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="2" Grid.Column="0" Margin="0,0,0,10">
|
||||||
|
<TextBlock Text="Monitor" />
|
||||||
|
<TextBlock Classes="subtitle" FontSize="12" TextWrapping="Wrap" Text="A device attached to the monitor such as ambilight LEDs" />
|
||||||
|
</StackPanel>
|
||||||
|
<CheckBox Grid.Row="2" Grid.Column="1" IsChecked="{CompiledBinding HasMonitorCategory}" />
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="3" Grid.Column="0" Margin="0,0,0,10">
|
||||||
|
<TextBlock Text="Case" />
|
||||||
|
<TextBlock Classes="subtitle" FontSize="12" TextWrapping="Wrap" Text="A device inside your computer case" />
|
||||||
|
</StackPanel>
|
||||||
|
<CheckBox Grid.Row="3" Grid.Column="1" IsChecked="{CompiledBinding HasCaseCategory}" />
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="4" Grid.Column="0" Margin="0,0,0,10">
|
||||||
|
<TextBlock Text="Room" />
|
||||||
|
<TextBlock Classes="subtitle" FontSize="12" TextWrapping="Wrap" Text="A device elsewhere in the room" />
|
||||||
|
</StackPanel>
|
||||||
|
<CheckBox Grid.Row="4" Grid.Column="1" IsChecked="{CompiledBinding HasRoomCategory}" />
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Surface and Calibration -->
|
||||||
|
<Grid ColumnDefinitions="*,*" RowDefinitions="*,*">
|
||||||
|
<TextBlock Grid.Column="0" Grid.Row="0" Classes="card-title" Text="Surface" Margin="10,0,0,0" />
|
||||||
|
<Border Grid.Column="0" Grid.Row="1" Classes="card" Margin="5" x:Name="SurfaceBorder">
|
||||||
|
<StackPanel Orientation="Vertical">
|
||||||
|
<TextBlock TextWrapping="Wrap" Text="The device can be rotated and scaled on the surface with the values below." />
|
||||||
|
<Grid ColumnDefinitions="*,Auto,Auto" RowDefinitions="*,*,*,*">
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="0" VerticalAlignment="Center">X-coordinate</TextBlock>
|
||||||
|
<NumericUpDown Grid.Row="0"
|
||||||
|
Grid.Column="1"
|
||||||
|
Margin="10 5"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Value="{CompiledBinding X}" />
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="2" VerticalAlignment="Center">mm</TextBlock>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="1" Grid.Column="0" VerticalAlignment="Center">Y-coordinate</TextBlock>
|
||||||
|
<NumericUpDown Grid.Row="1"
|
||||||
|
Grid.Column="1"
|
||||||
|
Margin="10 5"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Value="{CompiledBinding Y}" />
|
||||||
|
<TextBlock Grid.Row="1" Grid.Column="2" VerticalAlignment="Center">mm</TextBlock>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="2" Grid.Column="0" VerticalAlignment="Center">Scale</TextBlock>
|
||||||
|
<NumericUpDown Grid.Row="2"
|
||||||
|
Grid.Column="1"
|
||||||
|
Margin="10 5"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Increment="0.1"
|
||||||
|
FormatString="F1"
|
||||||
|
Value="{CompiledBinding Scale}" />
|
||||||
|
<TextBlock Grid.Row="2" Grid.Column="2" VerticalAlignment="Center">times</TextBlock>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="3" Grid.Column="0" VerticalAlignment="Center">Rotation</TextBlock>
|
||||||
|
<NumericUpDown Grid.Row="3"
|
||||||
|
Grid.Column="1"
|
||||||
|
Margin="10 5"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Value="{CompiledBinding Rotation}" />
|
||||||
|
<TextBlock Grid.Row="3" Grid.Column="2" VerticalAlignment="Center">deg</TextBlock>
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<TextBlock Grid.Column="1" Grid.Row="0" Classes="card-title" Text="Calibration" Margin="10,0,0,0" />
|
||||||
|
<Border Grid.Row="1" Grid.Column="1" Classes="card" Margin="5" x:Name="CalibrationBorder">
|
||||||
|
<StackPanel Orientation="Vertical">
|
||||||
|
<TextBlock TextWrapping="Wrap" Text="Use the sliders below to adjust the colors of your device so that it matches your other devices." />
|
||||||
|
<Grid ColumnDefinitions="Auto,*,Auto" RowDefinitions="*,*,*">
|
||||||
|
<Label Grid.Row="0" Grid.Column="0" Content="R" VerticalAlignment="Center" />
|
||||||
|
<Slider Grid.Row="0" Grid.Column="1" Minimum="0" Maximum="200" Value="{CompiledBinding RedScale}" Margin="10 0" VerticalAlignment="Center" />
|
||||||
|
<NumericUpDown Grid.Row="0"
|
||||||
|
Grid.Column="2"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Width="65"
|
||||||
|
Value="{CompiledBinding RedScale}"
|
||||||
|
ShowButtonSpinner="False"
|
||||||
|
FormatString="{}{0:0.0}"
|
||||||
|
Minimum="0"
|
||||||
|
Maximum="200"
|
||||||
|
ClipValueToMinMax="True" />
|
||||||
|
|
||||||
|
<Label Grid.Row="1" Grid.Column="0" Content="G" VerticalAlignment="Center" />
|
||||||
|
<Slider Grid.Row="1" Grid.Column="1" Minimum="0" Maximum="200" Value="{CompiledBinding GreenScale}" Margin="10 0" VerticalAlignment="Center" />
|
||||||
|
<NumericUpDown Grid.Row="1"
|
||||||
|
Grid.Column="2"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Width="65"
|
||||||
|
Value="{CompiledBinding GreenScale}"
|
||||||
|
ShowButtonSpinner="False"
|
||||||
|
FormatString="{}{0:0.0}"
|
||||||
|
Minimum="0"
|
||||||
|
Maximum="200"
|
||||||
|
ClipValueToMinMax="True" />
|
||||||
|
|
||||||
|
<Label Grid.Row="2" Grid.Column="0" Content="B" VerticalAlignment="Center" />
|
||||||
|
<Slider Grid.Row="2" Grid.Column="1" Minimum="0" Maximum="200" Value="{CompiledBinding BlueScale}" Margin="10 0" Ticks="100" VerticalAlignment="Center" />
|
||||||
|
<NumericUpDown Grid.Row="2"
|
||||||
|
Grid.Column="2"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Width="65"
|
||||||
|
Value="{CompiledBinding BlueScale}"
|
||||||
|
ShowButtonSpinner="False"
|
||||||
|
FormatString="{}{0:0.0}"
|
||||||
|
Minimum="0"
|
||||||
|
Maximum="200"
|
||||||
|
ClipValueToMinMax="True" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid ColumnDefinitions="Auto,*,Auto">
|
||||||
|
<Button
|
||||||
|
Grid.Column="0"
|
||||||
|
Content="Reset"
|
||||||
|
ToolTip.Tip="Reset the color scaling to what it had previously"
|
||||||
|
Command="{CompiledBinding ResetScaling}"
|
||||||
|
HorizontalAlignment="Center"/>
|
||||||
|
<CheckBox Grid.Column="1" IsChecked="{CompiledBinding DisplayOnDevices}" Content="Preview specific color" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||||
|
|
||||||
|
<controls:ColorPickerButton Grid.Column="2"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Color="{CompiledBinding CurrentColor, Converter={StaticResource SKColorToColorConverter}}"
|
||||||
|
ShowAcceptDismissButtons="False" />
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<Button Grid.Row="1" Margin="5"
|
||||||
|
IsVisible="{CompiledBinding RequiresManualSetup}"
|
||||||
|
Command="{CompiledBinding RestartSetup}"
|
||||||
|
ToolTip.Tip="Restart device setup, allowing you to select a new physical and logical layout">
|
||||||
|
Restart setup
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</ScrollViewer>
|
||||||
|
</UserControl>
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Device;
|
||||||
|
public partial class DeviceGeneralTabView : ReactiveUserControl<DeviceGeneralTabViewModel>
|
||||||
|
{
|
||||||
|
public DeviceGeneralTabView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,53 +1,57 @@
|
|||||||
using System;
|
using Artemis.UI.Shared;
|
||||||
|
using Artemis.UI.Shared;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
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.Shared;
|
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using Artemis.UI.Shared.Services.Builders;
|
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
using RGB.NET.Core;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Device;
|
namespace Artemis.UI.Screens.Device;
|
||||||
|
|
||||||
public class DevicePropertiesTabViewModel : ActivatableViewModelBase
|
public class DeviceGeneralTabViewModel : ActivatableViewModelBase
|
||||||
{
|
{
|
||||||
private readonly List<DeviceCategory> _categories;
|
|
||||||
private readonly ICoreService _coreService;
|
private readonly ICoreService _coreService;
|
||||||
|
private readonly IRgbService _rgbService;
|
||||||
|
private readonly IWindowService _windowService;
|
||||||
|
private readonly List<DeviceCategory> _categories;
|
||||||
|
|
||||||
private readonly float _initialBlueScale;
|
private readonly float _initialBlueScale;
|
||||||
private readonly float _initialGreenScale;
|
private readonly float _initialGreenScale;
|
||||||
private readonly float _initialRedScale;
|
private readonly float _initialRedScale;
|
||||||
private readonly INotificationService _notificationService;
|
|
||||||
private readonly IRgbService _rgbService;
|
|
||||||
private readonly IWindowService _windowService;
|
|
||||||
private float _blueScale;
|
|
||||||
private SKColor _currentColor;
|
|
||||||
private bool _displayOnDevices;
|
|
||||||
private float _greenScale;
|
|
||||||
private float _redScale;
|
|
||||||
private int _rotation;
|
private int _rotation;
|
||||||
private float _scale;
|
private float _scale;
|
||||||
private int _x;
|
private int _x;
|
||||||
private int _y;
|
private int _y;
|
||||||
|
|
||||||
public DevicePropertiesTabViewModel(ArtemisDevice device, ICoreService coreService, IRgbService rgbService, IWindowService windowService, INotificationService notificationService)
|
private float _redScale;
|
||||||
|
private float _greenScale;
|
||||||
|
private float _blueScale;
|
||||||
|
private SKColor _currentColor;
|
||||||
|
private bool _displayOnDevices;
|
||||||
|
|
||||||
|
public DeviceGeneralTabViewModel(ArtemisDevice device, ICoreService coreService, IRgbService rgbService, IWindowService windowService)
|
||||||
{
|
{
|
||||||
_coreService = coreService;
|
_coreService = coreService;
|
||||||
_rgbService = rgbService;
|
_rgbService = rgbService;
|
||||||
_windowService = windowService;
|
_windowService = windowService;
|
||||||
_notificationService = notificationService;
|
|
||||||
_categories = new List<DeviceCategory>(device.Categories);
|
_categories = new List<DeviceCategory>(device.Categories);
|
||||||
|
|
||||||
Device = device;
|
Device = device;
|
||||||
DisplayName = "Properties";
|
DisplayName = "General";
|
||||||
|
X = (int)Device.X;
|
||||||
X = (int) Device.X;
|
Y = (int)Device.Y;
|
||||||
Y = (int) Device.Y;
|
|
||||||
Scale = Device.Scale;
|
Scale = Device.Scale;
|
||||||
Rotation = (int) Device.Rotation;
|
Rotation = (int)Device.Rotation;
|
||||||
RedScale = Device.RedScale * 100f;
|
RedScale = Device.RedScale * 100f;
|
||||||
GreenScale = Device.GreenScale * 100f;
|
GreenScale = Device.GreenScale * 100f;
|
||||||
BlueScale = Device.BlueScale * 100f;
|
BlueScale = Device.BlueScale * 100f;
|
||||||
@ -69,10 +73,13 @@ public class DevicePropertiesTabViewModel : ActivatableViewModelBase
|
|||||||
{
|
{
|
||||||
_coreService.FrameRendering -= OnFrameRendering;
|
_coreService.FrameRendering -= OnFrameRendering;
|
||||||
Device.PropertyChanged -= DeviceOnPropertyChanged;
|
Device.PropertyChanged -= DeviceOnPropertyChanged;
|
||||||
|
Apply();
|
||||||
}).DisposeWith(d);
|
}).DisposeWith(d);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool RequiresManualSetup => !Device.DeviceProvider.CanDetectPhysicalLayout || !Device.DeviceProvider.CanDetectLogicalLayout;
|
||||||
|
|
||||||
public ArtemisDevice Device { get; }
|
public ArtemisDevice Device { get; }
|
||||||
|
|
||||||
public int X
|
public int X
|
||||||
@ -99,6 +106,38 @@ public class DevicePropertiesTabViewModel : ActivatableViewModelBase
|
|||||||
set => RaiseAndSetIfChanged(ref _rotation, value);
|
set => RaiseAndSetIfChanged(ref _rotation, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsKeyboard => Device.DeviceType == RGBDeviceType.Keyboard;
|
||||||
|
|
||||||
|
public bool HasDeskCategory
|
||||||
|
{
|
||||||
|
get => GetCategory(DeviceCategory.Desk);
|
||||||
|
set => SetCategory(DeviceCategory.Desk, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasMonitorCategory
|
||||||
|
{
|
||||||
|
get => GetCategory(DeviceCategory.Monitor);
|
||||||
|
set => SetCategory(DeviceCategory.Monitor, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasCaseCategory
|
||||||
|
{
|
||||||
|
get => GetCategory(DeviceCategory.Case);
|
||||||
|
set => SetCategory(DeviceCategory.Case, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasRoomCategory
|
||||||
|
{
|
||||||
|
get => GetCategory(DeviceCategory.Room);
|
||||||
|
set => SetCategory(DeviceCategory.Room, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasPeripheralsCategory
|
||||||
|
{
|
||||||
|
get => GetCategory(DeviceCategory.Peripherals);
|
||||||
|
set => SetCategory(DeviceCategory.Peripherals, value);
|
||||||
|
}
|
||||||
|
|
||||||
public float RedScale
|
public float RedScale
|
||||||
{
|
{
|
||||||
get => _redScale;
|
get => _redScale;
|
||||||
@ -129,72 +168,19 @@ public class DevicePropertiesTabViewModel : ActivatableViewModelBase
|
|||||||
set => RaiseAndSetIfChanged(ref _displayOnDevices, value);
|
set => RaiseAndSetIfChanged(ref _displayOnDevices, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This solution won't scale well but I don't expect there to be many more categories.
|
private bool GetCategory(DeviceCategory category)
|
||||||
// If for some reason there will be, dynamically creating a view model per category may be more appropriate
|
|
||||||
public bool HasDeskCategory
|
|
||||||
{
|
{
|
||||||
get => GetCategory(DeviceCategory.Desk);
|
return _categories.Contains(category);
|
||||||
set => SetCategory(DeviceCategory.Desk, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasMonitorCategory
|
private void SetCategory(DeviceCategory category, bool value)
|
||||||
{
|
{
|
||||||
get => GetCategory(DeviceCategory.Monitor);
|
if (value && !_categories.Contains(category))
|
||||||
set => SetCategory(DeviceCategory.Monitor, value);
|
_categories.Add(category);
|
||||||
}
|
else if (!value)
|
||||||
|
_categories.Remove(category);
|
||||||
|
|
||||||
public bool HasCaseCategory
|
this.RaisePropertyChanged($"Has{category}Category");
|
||||||
{
|
|
||||||
get => GetCategory(DeviceCategory.Case);
|
|
||||||
set => SetCategory(DeviceCategory.Case, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool HasRoomCategory
|
|
||||||
{
|
|
||||||
get => GetCategory(DeviceCategory.Room);
|
|
||||||
set => SetCategory(DeviceCategory.Room, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool HasPeripheralsCategory
|
|
||||||
{
|
|
||||||
get => GetCategory(DeviceCategory.Peripherals);
|
|
||||||
set => SetCategory(DeviceCategory.Peripherals, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool RequiresManualSetup => !Device.DeviceProvider.CanDetectPhysicalLayout || !Device.DeviceProvider.CanDetectLogicalLayout;
|
|
||||||
|
|
||||||
public void ApplyScaling()
|
|
||||||
{
|
|
||||||
Device.RedScale = RedScale / 100f;
|
|
||||||
Device.GreenScale = GreenScale / 100f;
|
|
||||||
Device.BlueScale = BlueScale / 100f;
|
|
||||||
|
|
||||||
_rgbService.FlushLeds = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ClearCustomLayout()
|
|
||||||
{
|
|
||||||
Device.CustomLayoutPath = null;
|
|
||||||
_notificationService.CreateNotification()
|
|
||||||
.WithMessage("Cleared imported layout.")
|
|
||||||
.WithSeverity(NotificationSeverity.Informational);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task BrowseCustomLayout()
|
|
||||||
{
|
|
||||||
string[]? files = await _windowService.CreateOpenFileDialog()
|
|
||||||
.WithTitle("Select device layout file")
|
|
||||||
.HavingFilter(f => f.WithName("Layout files").WithExtension("xml"))
|
|
||||||
.ShowAsync();
|
|
||||||
|
|
||||||
if (files?.Length > 0)
|
|
||||||
{
|
|
||||||
Device.CustomLayoutPath = files[0];
|
|
||||||
_notificationService.CreateNotification()
|
|
||||||
.WithTitle("Imported layout")
|
|
||||||
.WithMessage($"File loaded from {files[0]}")
|
|
||||||
.WithSeverity(NotificationSeverity.Informational);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RestartSetup()
|
public async Task RestartSetup()
|
||||||
@ -211,12 +197,12 @@ public class DevicePropertiesTabViewModel : ActivatableViewModelBase
|
|||||||
_rgbService.ApplyBestDeviceLayout(Device);
|
_rgbService.ApplyBestDeviceLayout(Device);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Apply()
|
private void Apply()
|
||||||
{
|
{
|
||||||
// TODO: Validation
|
// TODO: Validation
|
||||||
|
|
||||||
_coreService.ProfileRenderingDisabled = true;
|
_coreService.ProfileRenderingDisabled = true;
|
||||||
await Task.Delay(100);
|
Thread.Sleep(100);
|
||||||
|
|
||||||
Device.X = X;
|
Device.X = X;
|
||||||
Device.Y = Y;
|
Device.Y = Y;
|
||||||
@ -234,40 +220,28 @@ public class DevicePropertiesTabViewModel : ActivatableViewModelBase
|
|||||||
_coreService.ProfileRenderingDisabled = false;
|
_coreService.ProfileRenderingDisabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Reset()
|
public void ApplyScaling()
|
||||||
{
|
{
|
||||||
HasDeskCategory = Device.Categories.Contains(DeviceCategory.Desk);
|
Device.RedScale = RedScale / 100f;
|
||||||
HasMonitorCategory = Device.Categories.Contains(DeviceCategory.Monitor);
|
Device.GreenScale = GreenScale / 100f;
|
||||||
HasCaseCategory = Device.Categories.Contains(DeviceCategory.Case);
|
Device.BlueScale = BlueScale / 100f;
|
||||||
HasRoomCategory = Device.Categories.Contains(DeviceCategory.Room);
|
|
||||||
HasPeripheralsCategory = Device.Categories.Contains(DeviceCategory.Peripherals);
|
|
||||||
|
|
||||||
|
_rgbService.FlushLeds = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetScaling()
|
||||||
|
{
|
||||||
RedScale = _initialRedScale * 100;
|
RedScale = _initialRedScale * 100;
|
||||||
GreenScale = _initialGreenScale * 100;
|
GreenScale = _initialGreenScale * 100;
|
||||||
BlueScale = _initialBlueScale * 100;
|
BlueScale = _initialBlueScale * 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool GetCategory(DeviceCategory category)
|
|
||||||
{
|
|
||||||
return _categories.Contains(category);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetCategory(DeviceCategory category, bool value)
|
|
||||||
{
|
|
||||||
if (value && !_categories.Contains(category))
|
|
||||||
_categories.Add(category);
|
|
||||||
else if (!value)
|
|
||||||
_categories.Remove(category);
|
|
||||||
|
|
||||||
this.RaisePropertyChanged($"Has{category}Category");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnFrameRendering(object? sender, FrameRenderingEventArgs e)
|
private void OnFrameRendering(object? sender, FrameRenderingEventArgs e)
|
||||||
{
|
{
|
||||||
if (!_displayOnDevices)
|
if (!DisplayOnDevices)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
using SKPaint overlayPaint = new() {Color = CurrentColor};
|
using SKPaint overlayPaint = new() { Color = CurrentColor };
|
||||||
e.Canvas.DrawRect(0, 0, e.Canvas.LocalClipBounds.Width, e.Canvas.LocalClipBounds.Height, overlayPaint);
|
e.Canvas.DrawRect(0, 0, e.Canvas.LocalClipBounds.Width, e.Canvas.LocalClipBounds.Height, overlayPaint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1,88 +0,0 @@
|
|||||||
<UserControl xmlns="https://github.com/avaloniaui"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
|
||||||
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
|
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
|
||||||
x:Class="Artemis.UI.Screens.Device.DeviceInfoTabView"
|
|
||||||
x:DataType="device:DeviceInfoTabViewModel">
|
|
||||||
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
|
||||||
<Grid RowDefinitions="Auto,*" ColumnDefinitions="*,*" Margin="-5">
|
|
||||||
<!-- First row -->
|
|
||||||
<Border Classes="card" Grid.Column="0" Grid.Row="0" Margin="5">
|
|
||||||
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Top">
|
|
||||||
<TextBlock FontWeight="Bold">Device name</TextBlock>
|
|
||||||
<TextBlock TextWrapping="Wrap" Text="{CompiledBinding Device.RgbDevice.DeviceInfo.DeviceName}" />
|
|
||||||
<Border Classes="card-separator" />
|
|
||||||
|
|
||||||
<TextBlock FontWeight="Bold">Manufacturer</TextBlock>
|
|
||||||
<TextBlock TextWrapping="Wrap" Text="{CompiledBinding Device.RgbDevice.DeviceInfo.Manufacturer}" />
|
|
||||||
<Border Classes="card-separator" />
|
|
||||||
|
|
||||||
|
|
||||||
<TextBlock FontWeight="Bold">Device type</TextBlock>
|
|
||||||
<TextBlock TextWrapping="Wrap" Text="{CompiledBinding Device.DeviceType}" />
|
|
||||||
<Border Classes="card-separator" IsVisible="{CompiledBinding IsKeyboard}" />
|
|
||||||
|
|
||||||
<StackPanel IsVisible="{CompiledBinding IsKeyboard}">
|
|
||||||
<TextBlock FontWeight="Bold">Physical layout</TextBlock>
|
|
||||||
<TextBlock TextWrapping="Wrap" Text="{CompiledBinding Device.PhysicalLayout}" />
|
|
||||||
</StackPanel>
|
|
||||||
</StackPanel>
|
|
||||||
</Border>
|
|
||||||
|
|
||||||
<Border Classes="card" Grid.Row="0" Grid.Column="1" Margin="5">
|
|
||||||
<StackPanel VerticalAlignment="Top">
|
|
||||||
<TextBlock FontWeight="Bold">Size (1px = 1mm)</TextBlock>
|
|
||||||
<TextBlock TextWrapping="Wrap" Text="{CompiledBinding Device.RgbDevice.Size}" />
|
|
||||||
<Border Classes="card-separator" />
|
|
||||||
|
|
||||||
<TextBlock FontWeight="Bold">Location (1px = 1mm)</TextBlock>
|
|
||||||
<TextBlock TextWrapping="Wrap" Text="{CompiledBinding Device.RgbDevice.Location}" />
|
|
||||||
<Border Classes="card-separator" />
|
|
||||||
|
|
||||||
<TextBlock FontWeight="Bold">Rotation (degrees)</TextBlock>
|
|
||||||
<TextBlock TextWrapping="Wrap" Text="{CompiledBinding Device.RgbDevice.Rotation.Degrees}" />
|
|
||||||
<Border Classes="card-separator" IsVisible="{CompiledBinding IsKeyboard}" />
|
|
||||||
|
|
||||||
<StackPanel IsVisible="{CompiledBinding IsKeyboard}">
|
|
||||||
<TextBlock FontWeight="Bold">Logical layout</TextBlock>
|
|
||||||
<TextBlock TextWrapping="Wrap" Text="{CompiledBinding Device.LogicalLayout}" />
|
|
||||||
</StackPanel>
|
|
||||||
</StackPanel>
|
|
||||||
</Border>
|
|
||||||
|
|
||||||
<!-- Second row -->
|
|
||||||
<Border Classes="card" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2" Margin="5">
|
|
||||||
<StackPanel>
|
|
||||||
<Grid ColumnDefinitions="*,Auto">
|
|
||||||
<TextBlock FontWeight="Bold">Default layout file path</TextBlock>
|
|
||||||
<Button Grid.Column="1"
|
|
||||||
Classes="icon-button"
|
|
||||||
ToolTip.Tip="Copy path to clipboard"
|
|
||||||
Click="LayoutPathButton_OnClick">
|
|
||||||
<avalonia:MaterialIcon Kind="ContentCopy" Width="18" Height="18" />
|
|
||||||
</Button>
|
|
||||||
</Grid>
|
|
||||||
<TextBlock
|
|
||||||
TextWrapping="Wrap"
|
|
||||||
Text="{CompiledBinding DefaultLayoutPath}" />
|
|
||||||
<Border Classes="card-separator" />
|
|
||||||
|
|
||||||
<Grid ColumnDefinitions="*,Auto">
|
|
||||||
<TextBlock FontWeight="Bold">Image file path</TextBlock>
|
|
||||||
<Button Grid.Column="1"
|
|
||||||
Classes="icon-button"
|
|
||||||
ToolTip.Tip="Copy path to clipboard"
|
|
||||||
Click="ImagePathButton_OnClick">
|
|
||||||
<avalonia:MaterialIcon Kind="ContentCopy" Width="18" Height="18" />
|
|
||||||
</Button>
|
|
||||||
</Grid>
|
|
||||||
<TextBlock TextWrapping="Wrap" Text="{CompiledBinding Device.Layout.Image.LocalPath}" />
|
|
||||||
</StackPanel>
|
|
||||||
</Border>
|
|
||||||
</Grid>
|
|
||||||
</ScrollViewer>
|
|
||||||
|
|
||||||
</UserControl>
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
using System.Threading.Tasks;
|
|
||||||
using Artemis.Core;
|
|
||||||
using Artemis.UI.Shared;
|
|
||||||
using Artemis.UI.Shared.Services;
|
|
||||||
using Avalonia;
|
|
||||||
using Avalonia.Controls;
|
|
||||||
using RGB.NET.Core;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Device;
|
|
||||||
|
|
||||||
public class DeviceInfoTabViewModel : ActivatableViewModelBase
|
|
||||||
{
|
|
||||||
private readonly INotificationService _notificationService;
|
|
||||||
|
|
||||||
public DeviceInfoTabViewModel(ArtemisDevice device, INotificationService notificationService)
|
|
||||||
{
|
|
||||||
_notificationService = notificationService;
|
|
||||||
|
|
||||||
Device = device;
|
|
||||||
DisplayName = "Info";
|
|
||||||
|
|
||||||
DefaultLayoutPath = Device.DeviceProvider.LoadLayout(Device).FilePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsKeyboard => Device.DeviceType == RGBDeviceType.Keyboard;
|
|
||||||
public ArtemisDevice Device { get; }
|
|
||||||
|
|
||||||
public string DefaultLayoutPath { get; }
|
|
||||||
}
|
|
||||||
89
src/Artemis.UI/Screens/Device/Tabs/DeviceLayoutTabView.axaml
Normal file
89
src/Artemis.UI/Screens/Device/Tabs/DeviceLayoutTabView.axaml
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
|
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="800"
|
||||||
|
x:Class="Artemis.UI.Screens.Device.DeviceLayoutTabView"
|
||||||
|
x:DataType="device:DeviceLayoutTabViewModel">
|
||||||
|
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
||||||
|
<Border Classes="card" Margin="5">
|
||||||
|
<Grid RowDefinitions="*,Auto">
|
||||||
|
<StackPanel Grid.Row="0">
|
||||||
|
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
|
||||||
|
<StackPanel Grid.Row="0" Grid.Column="0">
|
||||||
|
<TextBlock Text="Default layout file path" />
|
||||||
|
<TextBlock Classes="subtitle" FontSize="12" TextWrapping="Wrap" Text="{CompiledBinding DefaultLayoutPath}" />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||||
|
<Button
|
||||||
|
Classes="icon-button"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
ToolTip.Tip="Copy layout file path to clipboard"
|
||||||
|
Click="LayoutPathButton_OnClick">
|
||||||
|
<avalonia:MaterialIcon Kind="ContentCopy" Width="18" Height="18" />
|
||||||
|
</Button>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
<Border Classes="card-separator" />
|
||||||
|
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
|
||||||
|
<StackPanel Grid.Row="1" Grid.Column="0">
|
||||||
|
<TextBlock Text="Image file path" />
|
||||||
|
<TextBlock Classes="subtitle" FontSize="12" TextWrapping="Wrap" Text="{CompiledBinding Device.Layout.Image.LocalPath}" />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Grid.Row="1" Grid.Column="1" VerticalAlignment="Center">
|
||||||
|
<Button
|
||||||
|
Classes="icon-button"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
ToolTip.Tip="Copy image file path to clipboard"
|
||||||
|
Click="ImagePathButton_OnClick">
|
||||||
|
<avalonia:MaterialIcon Kind="ContentCopy" Width="18" Height="18" />
|
||||||
|
</Button>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
<Border Classes="card-separator" />
|
||||||
|
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
|
||||||
|
<StackPanel Grid.Row="1" Grid.Column="0">
|
||||||
|
<TextBlock Text="Disable default layout" />
|
||||||
|
<TextBlock Classes="subtitle" FontSize="12" Text="With this checked, Artemis will not load a layout for this device unless you specifically provide one." />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Grid.Row="1" Grid.Column="1" VerticalAlignment="Center">
|
||||||
|
<CheckBox HorizontalAlignment="Right" Margin="0,0,-10,0" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
<Border Classes="card-separator" />
|
||||||
|
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
|
||||||
|
<StackPanel Grid.Row="1" Grid.Column="0">
|
||||||
|
<TextBlock Text="Custom layout path" />
|
||||||
|
<TextBlock Classes="subtitle" FontSize="12" Text="{CompiledBinding CustomLayoutPath}" />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Orientation="Horizontal">
|
||||||
|
<Button Content="Clear" Command="{CompiledBinding ClearCustomLayout}" IsEnabled="{CompiledBinding HasCustomLayout}" />
|
||||||
|
<!-- 5 pixels of margin between the buttons -->
|
||||||
|
<Button Margin="5,0,0,0" Content="Browse" Command="{CompiledBinding BrowseCustomLayout}" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
<Border Classes="card-separator" />
|
||||||
|
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
|
||||||
|
<StackPanel Grid.Row="1" Grid.Column="0">
|
||||||
|
<TextBlock Text="Export current layout" />
|
||||||
|
<TextBlock Classes="subtitle" FontSize="12" Text="If there is a layout used, export that. Otherwise, export the LEDs present." />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Orientation="Horizontal">
|
||||||
|
<Button HorizontalAlignment="Right" Content="Export" Command="{CompiledBinding ExportLayout}" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
<controls:HyperlinkButton
|
||||||
|
Grid.Row="1"
|
||||||
|
Content="Learn more about layouts on the wiki"
|
||||||
|
NavigateUri="https://wiki.artemis-rgb.com/en/guides/developer/layouts?mtm_campaign=artemis&mtm_kwd=device-properties"
|
||||||
|
Margin="0 20"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
VerticalAlignment="Bottom" />
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</ScrollViewer>
|
||||||
|
</UserControl>
|
||||||
@ -1,13 +1,15 @@
|
|||||||
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Input;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Device;
|
namespace Artemis.UI.Screens.Device;
|
||||||
|
|
||||||
public partial class DeviceInfoTabView : ReactiveUserControl<DeviceInfoTabViewModel>
|
public partial class DeviceLayoutTabView : ReactiveUserControl<DeviceLayoutTabViewModel>
|
||||||
{
|
{
|
||||||
public DeviceInfoTabView()
|
public DeviceLayoutTabView()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
@ -15,10 +17,12 @@ public partial class DeviceInfoTabView : ReactiveUserControl<DeviceInfoTabViewMo
|
|||||||
private void LayoutPathButton_OnClick(object? sender, RoutedEventArgs e)
|
private void LayoutPathButton_OnClick(object? sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
TopLevel.GetTopLevel(this).Clipboard.SetTextAsync(ViewModel.DefaultLayoutPath);
|
TopLevel.GetTopLevel(this).Clipboard.SetTextAsync(ViewModel.DefaultLayoutPath);
|
||||||
|
ViewModel.ShowCopiedNotification();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ImagePathButton_OnClick(object? sender, RoutedEventArgs e)
|
private void ImagePathButton_OnClick(object? sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
TopLevel.GetTopLevel(this).Clipboard.SetTextAsync(ViewModel.Device.Layout.Image.LocalPath);
|
TopLevel.GetTopLevel(this).Clipboard.SetTextAsync(ViewModel.Device.Layout.Image.LocalPath);
|
||||||
|
ViewModel.ShowCopiedNotification();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
151
src/Artemis.UI/Screens/Device/Tabs/DeviceLayoutTabViewModel.cs
Normal file
151
src/Artemis.UI/Screens/Device/Tabs/DeviceLayoutTabViewModel.cs
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reactive.Disposables;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
using Artemis.Core;
|
||||||
|
using Artemis.Core.Services;
|
||||||
|
using Artemis.UI.Shared;
|
||||||
|
using Artemis.UI.Shared.Services;
|
||||||
|
using Artemis.UI.Shared.Services.Builders;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using ReactiveUI;
|
||||||
|
using RGB.NET.Layout;
|
||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Device;
|
||||||
|
|
||||||
|
public class DeviceLayoutTabViewModel : ActivatableViewModelBase
|
||||||
|
{
|
||||||
|
private readonly IWindowService _windowService;
|
||||||
|
private readonly INotificationService _notificationService;
|
||||||
|
|
||||||
|
public DeviceLayoutTabViewModel(
|
||||||
|
IWindowService windowService,
|
||||||
|
INotificationService notificationService,
|
||||||
|
ArtemisDevice device)
|
||||||
|
{
|
||||||
|
_windowService = windowService;
|
||||||
|
_notificationService = notificationService;
|
||||||
|
|
||||||
|
Device = device;
|
||||||
|
DisplayName = "Layout";
|
||||||
|
DefaultLayoutPath = Device.DeviceProvider.LoadLayout(Device).FilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArtemisDevice Device { get; }
|
||||||
|
|
||||||
|
public string DefaultLayoutPath { get; }
|
||||||
|
|
||||||
|
public string CustomLayoutPath => Device.CustomLayoutPath ?? "None";
|
||||||
|
|
||||||
|
public bool HasCustomLayout => Device.CustomLayoutPath != null;
|
||||||
|
|
||||||
|
private void RaiseCustomLayoutChanged()
|
||||||
|
{
|
||||||
|
this.RaisePropertyChanged(nameof(CustomLayoutPath));
|
||||||
|
this.RaisePropertyChanged(nameof(HasCustomLayout));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearCustomLayout()
|
||||||
|
{
|
||||||
|
Device.CustomLayoutPath = null;
|
||||||
|
_notificationService.CreateNotification()
|
||||||
|
.WithMessage("Cleared imported layout.")
|
||||||
|
.WithSeverity(NotificationSeverity.Informational);
|
||||||
|
|
||||||
|
RaiseCustomLayoutChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task BrowseCustomLayout()
|
||||||
|
{
|
||||||
|
string[]? files = await _windowService.CreateOpenFileDialog()
|
||||||
|
.WithTitle("Select device layout file")
|
||||||
|
.HavingFilter(f => f.WithName("Layout files").WithExtension("xml"))
|
||||||
|
.ShowAsync();
|
||||||
|
|
||||||
|
if (files?.Length > 0)
|
||||||
|
{
|
||||||
|
Device.CustomLayoutPath = files[0];
|
||||||
|
_notificationService.CreateNotification()
|
||||||
|
.WithTitle("Imported layout")
|
||||||
|
.WithMessage($"File loaded from {files[0]}")
|
||||||
|
.WithSeverity(NotificationSeverity.Informational);
|
||||||
|
}
|
||||||
|
|
||||||
|
RaiseCustomLayoutChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ExportLayout()
|
||||||
|
{
|
||||||
|
string fileName = Device.DeviceProvider.GetDeviceLayoutName(Device);
|
||||||
|
string layoutDir = Constants.LayoutsFolder;
|
||||||
|
string filePath = Path.Combine(
|
||||||
|
layoutDir,
|
||||||
|
Device.RgbDevice.DeviceInfo.Manufacturer,
|
||||||
|
Device.DeviceType.ToString(),
|
||||||
|
fileName
|
||||||
|
);
|
||||||
|
if (!Directory.Exists(filePath))
|
||||||
|
Directory.CreateDirectory(filePath);
|
||||||
|
|
||||||
|
string? result = await _windowService.CreateSaveFileDialog()
|
||||||
|
.HavingFilter(f => f.WithExtension("xml").WithName("Artemis layout"))
|
||||||
|
.WithDirectory(filePath)
|
||||||
|
.WithInitialFileName(fileName)
|
||||||
|
.ShowAsync();
|
||||||
|
|
||||||
|
if (result == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ArtemisLayout? layout = Device.Layout;
|
||||||
|
if (layout?.IsValid == true)
|
||||||
|
{
|
||||||
|
string path = layout.FilePath;
|
||||||
|
File.Copy(path, result, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<LedLayout> ledLayouts = Device.Leds.Select(x => new LedLayout()
|
||||||
|
{
|
||||||
|
Id = x.RgbLed.Id.ToString(),
|
||||||
|
DescriptiveX = x.Rectangle.Left.ToString(),
|
||||||
|
DescriptiveY = x.Rectangle.Top.ToString(),
|
||||||
|
DescriptiveWidth = $"{x.Rectangle.Width}mm",
|
||||||
|
DescriptiveHeight = $"{x.Rectangle.Height}mm",
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
DeviceLayout emptyLayout = new()
|
||||||
|
{
|
||||||
|
Author = "Artemis",
|
||||||
|
Type = Device.DeviceType,
|
||||||
|
Vendor = Device.RgbDevice.DeviceInfo.Manufacturer,
|
||||||
|
Model = Device.RgbDevice.DeviceInfo.Model,
|
||||||
|
Width = Device.Rectangle.Width,
|
||||||
|
Height = Device.Rectangle.Height,
|
||||||
|
InternalLeds = ledLayouts,
|
||||||
|
};
|
||||||
|
|
||||||
|
XmlSerializer serializer = new(typeof(DeviceLayout));
|
||||||
|
await using StreamWriter writer = new(result);
|
||||||
|
serializer.Serialize(writer, emptyLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
_notificationService.CreateNotification()
|
||||||
|
.WithMessage("Layout exported")
|
||||||
|
.WithTimeout(TimeSpan.FromSeconds(5))
|
||||||
|
.WithSeverity(NotificationSeverity.Success)
|
||||||
|
.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowCopiedNotification()
|
||||||
|
{
|
||||||
|
_notificationService.CreateNotification()
|
||||||
|
.WithTitle("Copied!")
|
||||||
|
.WithSeverity(NotificationSeverity.Informational)
|
||||||
|
.Show();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,204 +0,0 @@
|
|||||||
<UserControl xmlns="https://github.com/avaloniaui"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
|
||||||
xmlns:converters="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared"
|
|
||||||
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
|
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="1200"
|
|
||||||
x:Class="Artemis.UI.Screens.Device.DevicePropertiesTabView"
|
|
||||||
x:DataType="device:DevicePropertiesTabViewModel">
|
|
||||||
<UserControl.Resources>
|
|
||||||
<converters:SKColorToColorConverter x:Key="SKColorToColorConverter" />
|
|
||||||
</UserControl.Resources>
|
|
||||||
|
|
||||||
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
|
||||||
<!-- Body -->
|
|
||||||
<Grid RowDefinitions="*,Auto">
|
|
||||||
<StackPanel Grid.Row="0">
|
|
||||||
<!-- Layout -->
|
|
||||||
<TextBlock Classes="h4">
|
|
||||||
Categories
|
|
||||||
</TextBlock>
|
|
||||||
<TextBlock TextWrapping="Wrap">
|
|
||||||
Artemis uses categories to determine where the layers of imported profiles are applied to.
|
|
||||||
</TextBlock>
|
|
||||||
<TextBlock TextWrapping="Wrap">
|
|
||||||
You can hover over a category for a more detailed description.
|
|
||||||
</TextBlock>
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<CheckBox IsChecked="{CompiledBinding HasDeskCategory}"
|
|
||||||
ToolTip.Tip="A device acting as desk ornamentation such as a LED strip"
|
|
||||||
Content="Desk" />
|
|
||||||
<CheckBox IsChecked="{CompiledBinding HasMonitorCategory}"
|
|
||||||
ToolTip.Tip="A device attached to the monitor such as ambilight LEDs"
|
|
||||||
Content="Monitor" />
|
|
||||||
<CheckBox ToolTip.Tip="A device inside your computer case"
|
|
||||||
IsChecked="{CompiledBinding HasCaseCategory}"
|
|
||||||
Content="Case" />
|
|
||||||
<CheckBox IsChecked="{CompiledBinding HasRoomCategory}"
|
|
||||||
ToolTip.Tip="A device elsewhere in the room"
|
|
||||||
Content="Room" />
|
|
||||||
<CheckBox IsChecked="{CompiledBinding HasPeripheralsCategory}"
|
|
||||||
ToolTip.Tip="A peripheral such as a mouse or keyboard"
|
|
||||||
Content="Peripheral" />
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<Grid Margin="0 25" ColumnDefinitions="*,40,*">
|
|
||||||
<Grid Grid.Column="0" ColumnDefinitions="*,Auto,Auto" RowDefinitions="*,*,*,*,*">
|
|
||||||
<TextBlock Grid.Row="0" Grid.ColumnSpan="3" Classes="h4">
|
|
||||||
Surface properties
|
|
||||||
</TextBlock>
|
|
||||||
|
|
||||||
<TextBlock Grid.Row="1" Grid.Column="0" VerticalAlignment="Center">X-coordinate</TextBlock>
|
|
||||||
<NumericUpDown Grid.Row="1"
|
|
||||||
Grid.Column="1"
|
|
||||||
Margin="10 0"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Value="{CompiledBinding X}" />
|
|
||||||
<TextBlock Grid.Row="1" Grid.Column="2" VerticalAlignment="Center">mm</TextBlock>
|
|
||||||
|
|
||||||
<TextBlock Grid.Row="2" Grid.Column="0" VerticalAlignment="Center">Y-coordinate</TextBlock>
|
|
||||||
<NumericUpDown Grid.Row="2"
|
|
||||||
Grid.Column="1"
|
|
||||||
Margin="10 0"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Value="{CompiledBinding Y}" />
|
|
||||||
<TextBlock Grid.Row="2" Grid.Column="2" VerticalAlignment="Center">mm</TextBlock>
|
|
||||||
|
|
||||||
<TextBlock Grid.Row="3" Grid.Column="0" VerticalAlignment="Center">Scale</TextBlock>
|
|
||||||
<NumericUpDown Grid.Row="3"
|
|
||||||
Grid.Column="1"
|
|
||||||
Margin="10 0"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Increment="0.1"
|
|
||||||
FormatString="F1"
|
|
||||||
Value="{CompiledBinding Scale}" />
|
|
||||||
<TextBlock Grid.Row="3" Grid.Column="2" VerticalAlignment="Center">times</TextBlock>
|
|
||||||
|
|
||||||
<TextBlock Grid.Row="4" Grid.Column="0" VerticalAlignment="Center">Rotation</TextBlock>
|
|
||||||
<NumericUpDown Grid.Row="4"
|
|
||||||
Grid.Column="1"
|
|
||||||
Margin="10 0"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Value="{CompiledBinding Rotation}" />
|
|
||||||
<TextBlock Grid.Row="4" Grid.Column="2" VerticalAlignment="Center">deg</TextBlock>
|
|
||||||
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<Rectangle Grid.Column="1" VerticalAlignment="Stretch" Width="1" Fill="{DynamicResource ButtonBorderBrush}" Margin="0 0 0 5" />
|
|
||||||
|
|
||||||
<StackPanel Grid.Column="2">
|
|
||||||
<TextBlock Classes="h4">
|
|
||||||
Color calibration
|
|
||||||
</TextBlock>
|
|
||||||
|
|
||||||
<TextBlock TextWrapping="Wrap">
|
|
||||||
Use the sliders below to adjust the colors of your device so that it matches your other devices.
|
|
||||||
</TextBlock>
|
|
||||||
|
|
||||||
<Grid ColumnDefinitions="Auto,*,Auto" RowDefinitions="*,*,*,*">
|
|
||||||
<Label Grid.Row="0" Grid.Column="0" Content="R" VerticalAlignment="Center" />
|
|
||||||
<Slider Grid.Row="0" Grid.Column="1" Minimum="0" Maximum="200" Value="{CompiledBinding RedScale}" Margin="10 0" VerticalAlignment="Center" />
|
|
||||||
<NumericUpDown Grid.Row="0"
|
|
||||||
Grid.Column="2"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Width="65"
|
|
||||||
Value="{CompiledBinding RedScale}"
|
|
||||||
ShowButtonSpinner="False"
|
|
||||||
FormatString="{}{0:0.0}"
|
|
||||||
Minimum="0"
|
|
||||||
Maximum="200"
|
|
||||||
ClipValueToMinMax="True" />
|
|
||||||
|
|
||||||
<Label Grid.Row="1" Grid.Column="0" Content="G" VerticalAlignment="Center" />
|
|
||||||
<Slider Grid.Row="1" Grid.Column="1" Minimum="0" Maximum="200" Value="{CompiledBinding GreenScale}" Margin="10 0" VerticalAlignment="Center" />
|
|
||||||
<NumericUpDown Grid.Row="1"
|
|
||||||
Grid.Column="2"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Width="65"
|
|
||||||
Value="{CompiledBinding GreenScale}"
|
|
||||||
ShowButtonSpinner="False"
|
|
||||||
FormatString="{}{0:0.0}"
|
|
||||||
Minimum="0"
|
|
||||||
Maximum="200"
|
|
||||||
ClipValueToMinMax="True" />
|
|
||||||
|
|
||||||
<Label Grid.Row="2" Grid.Column="0" Content="B" VerticalAlignment="Center" />
|
|
||||||
<Slider Grid.Row="2" Grid.Column="1" Minimum="0" Maximum="200" Value="{CompiledBinding BlueScale}" Margin="10 0" Ticks="100" VerticalAlignment="Center" />
|
|
||||||
<NumericUpDown Grid.Row="2"
|
|
||||||
Grid.Column="2"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Width="65"
|
|
||||||
Value="{CompiledBinding BlueScale}"
|
|
||||||
ShowButtonSpinner="False"
|
|
||||||
FormatString="{}{0:0.0}"
|
|
||||||
Minimum="0"
|
|
||||||
Maximum="200"
|
|
||||||
ClipValueToMinMax="True" />
|
|
||||||
|
|
||||||
<CheckBox Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" IsChecked="{CompiledBinding DisplayOnDevices}" Content="Show preview" VerticalAlignment="Center" />
|
|
||||||
<controls:ColorPickerButton Grid.Row="3"
|
|
||||||
Grid.Column="2"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
HorizontalAlignment="Right"
|
|
||||||
Color="{CompiledBinding CurrentColor, Converter={StaticResource SKColorToColorConverter}}"
|
|
||||||
ShowAcceptDismissButtons="False" />
|
|
||||||
</Grid>
|
|
||||||
</StackPanel>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<!-- Layout -->
|
|
||||||
<TextBlock Classes="h4">
|
|
||||||
Layout
|
|
||||||
</TextBlock>
|
|
||||||
<TextBlock TextWrapping="Wrap">
|
|
||||||
The device layout is used to determine the position of LEDs and to create the visual representation of the device you see on the left side of this window.
|
|
||||||
</TextBlock>
|
|
||||||
|
|
||||||
<CheckBox Margin="0 0 0 5" IsChecked="{CompiledBinding Device.DisableDefaultLayout}">
|
|
||||||
<CheckBox.Content>
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<TextBlock>Don't load default layout</TextBlock>
|
|
||||||
<avalonia:MaterialIcon Kind="HelpCircle"
|
|
||||||
Margin="5 0"
|
|
||||||
ToolTip.Tip="With this enabled Artemis will not load a layout for this device unless you specifically provide one." />
|
|
||||||
</StackPanel>
|
|
||||||
</CheckBox.Content>
|
|
||||||
</CheckBox>
|
|
||||||
|
|
||||||
<Grid>
|
|
||||||
<TextBox Text="{CompiledBinding Device.CustomLayoutPath}"
|
|
||||||
Watermark="Custom layout path"
|
|
||||||
UseFloatingWatermark="True"
|
|
||||||
IsReadOnly="True"
|
|
||||||
PointerReleased="InputElement_OnPointerReleased"
|
|
||||||
Padding="10 5 36 6" />
|
|
||||||
<Button Classes="AppBarButton" HorizontalAlignment="Right" Command="{CompiledBinding ClearCustomLayout}" Padding="6" Margin="5 0">
|
|
||||||
<avalonia:MaterialIcon Kind="CloseCircle" />
|
|
||||||
</Button>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<controls:HyperlinkButton NavigateUri="https://wiki.artemis-rgb.com/en/guides/developer/layouts" Margin="0 20" HorizontalAlignment="Right">
|
|
||||||
Learn more about layouts on the wiki
|
|
||||||
</controls:HyperlinkButton>
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<!-- Buttons -->
|
|
||||||
<Grid Grid.Row="1" ColumnDefinitions="Auto,*">
|
|
||||||
<Button Grid.Column="0"
|
|
||||||
IsVisible="{CompiledBinding RequiresManualSetup}"
|
|
||||||
Command="{CompiledBinding RestartSetup}"
|
|
||||||
ToolTip.Tip="Restart device setup, allowing you to select a new physical and logical layout">
|
|
||||||
Restart setup
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
|
|
||||||
<Button IsCancel="True" Command="{CompiledBinding Reset}" Margin="0 0 5 0">Reset</Button>
|
|
||||||
<Button Classes="accent" IsDefault="True" Command="{CompiledBinding Apply}">Apply</Button>
|
|
||||||
</StackPanel>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</ScrollViewer>
|
|
||||||
</UserControl>
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
using Avalonia.Input;
|
|
||||||
using Avalonia.Markup.Xaml;
|
|
||||||
using Avalonia.ReactiveUI;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Device;
|
|
||||||
|
|
||||||
public partial class DevicePropertiesTabView : ReactiveUserControl<DevicePropertiesTabViewModel>
|
|
||||||
{
|
|
||||||
public DevicePropertiesTabView()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void InputElement_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
|
|
||||||
{
|
|
||||||
ViewModel?.BrowseCustomLayout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -43,7 +43,7 @@
|
|||||||
Under Settings > Plugins you can find your currently installed plugins, these default plugins are created by Artemis developers. We're also keeping track of a list of third-party plugins on our wiki.
|
Under Settings > Plugins you can find your currently installed plugins, these default plugins are created by Artemis developers. We're also keeping track of a list of third-party plugins on our wiki.
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<controls:HyperlinkButton Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="0" NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/plugins" HorizontalAlignment="Right">
|
<controls:HyperlinkButton Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="0" NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/plugins?mtm_campaign=artemis&mtm_kwd=home" HorizontalAlignment="Right">
|
||||||
<controls:HyperlinkButton.ContextMenu>
|
<controls:HyperlinkButton.ContextMenu>
|
||||||
<ContextMenu>
|
<ContextMenu>
|
||||||
<MenuItem Header="Test"></MenuItem>
|
<MenuItem Header="Test"></MenuItem>
|
||||||
@ -75,7 +75,7 @@
|
|||||||
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">GitHub</TextBlock>
|
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">GitHub</TextBlock>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
<controls:HyperlinkButton Grid.Row="0" HorizontalAlignment="Right" NavigateUri="https://artemis-rgb.com">
|
<controls:HyperlinkButton Grid.Row="0" HorizontalAlignment="Right" NavigateUri="https://artemis-rgb.com?mtm_campaign=artemis&mtm_kwd=home">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<avalonia:MaterialIcon Kind="Web" />
|
<avalonia:MaterialIcon Kind="Web" />
|
||||||
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Website</TextBlock>
|
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Website</TextBlock>
|
||||||
@ -110,7 +110,7 @@
|
|||||||
<controls:HyperlinkButton Grid.Row="1"
|
<controls:HyperlinkButton Grid.Row="1"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
NavigateUri="https://wiki.artemis-rgb.com/en/donating">
|
NavigateUri="https://wiki.artemis-rgb.com/en/donating?mtm_campaign=artemis&mtm_kwd=home">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<avalonia:MaterialIcon Kind="Gift" />
|
<avalonia:MaterialIcon Kind="Gift" />
|
||||||
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Donate</TextBlock>
|
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Donate</TextBlock>
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.ProfileEditor.MenuBar.MenuBarView"
|
x:Class="Artemis.UI.Screens.ProfileEditor.MenuBar.MenuBarView"
|
||||||
x:DataType="menuBar:MenuBarViewModel">
|
x:DataType="menuBar:MenuBarViewModel">
|
||||||
<Menu VerticalAlignment="Top" MenuClosed="MenuBase_OnMenuClosed">
|
<Menu VerticalAlignment="Top" Closed="MenuBase_OnMenuClosed">
|
||||||
<MenuItem Header="_File">
|
<MenuItem Header="_File">
|
||||||
<MenuItem Header="New">
|
<MenuItem Header="New">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
@ -164,44 +164,44 @@
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Header="_Help">
|
<MenuItem Header="_Help">
|
||||||
<MenuItem Header="Artemis Wiki" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/">
|
<MenuItem Header="Artemis Wiki" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/?mtm_campaign=artemis&mtm_kwd=profile-editor">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
<avalonia:MaterialIcon Kind="BookEdit" />
|
<avalonia:MaterialIcon Kind="BookEdit" />
|
||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<Separator />
|
<Separator />
|
||||||
<MenuItem Header="Editor" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/en/guides/user/profiles">
|
<MenuItem Header="Editor" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/en/guides/user/profiles?mtm_campaign=artemis&mtm_kwd=profile-editor">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
<avalonia:MaterialIcon Kind="Edit" />
|
<avalonia:MaterialIcon Kind="Edit" />
|
||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Header="Layers" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/layers">
|
<MenuItem Header="Layers" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/layers?mtm_campaign=artemis&mtm_kwd=profile-editor">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
<avalonia:MaterialIcon Kind="Layers" />
|
<avalonia:MaterialIcon Kind="Layers" />
|
||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Header="Display Conditions" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/conditions">
|
<MenuItem Header="Display Conditions" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/conditions?mtm_campaign=artemis&mtm_kwd=profile-editor">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
<avalonia:MaterialIcon Kind="NotEqual" />
|
<avalonia:MaterialIcon Kind="NotEqual" />
|
||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Header="Timeline" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/timeline">
|
<MenuItem Header="Timeline" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/timeline?mtm_campaign=artemis&mtm_kwd=profile-editor">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
<avalonia:MaterialIcon Kind="Stopwatch" />
|
<avalonia:MaterialIcon Kind="Stopwatch" />
|
||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Header="Data Bindings" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/data-bindings">
|
<MenuItem Header="Data Bindings" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/data-bindings?mtm_campaign=artemis&mtm_kwd=profile-editor">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
<avalonia:MaterialIcon Kind="VectorLink" />
|
<avalonia:MaterialIcon Kind="VectorLink" />
|
||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Header="Scripting" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/scripting">
|
<MenuItem Header="Scripting" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/scripting?mtm_campaign=artemis&mtm_kwd=profile-editor">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
<avalonia:MaterialIcon Kind="CodeJson" />
|
<avalonia:MaterialIcon Kind="CodeJson" />
|
||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<Separator />
|
<Separator />
|
||||||
<MenuItem Header="Report a Bug" Command="{CompiledBinding OpenUri}" CommandParameter="https://github.com/Artemis-RGB/Artemis/issues">
|
<MenuItem Header="Report a Bug" Command="{CompiledBinding OpenUri}" CommandParameter="https://github.com/Artemis-RGB/Artemis/issues?mtm_campaign=artemis&mtm_kwd=profile-editor">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
<avalonia:MaterialIcon Kind="Github" />
|
<avalonia:MaterialIcon Kind="Github" />
|
||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
|
|||||||
@ -25,7 +25,7 @@
|
|||||||
<controls:HyperlinkButton Grid.Row="0"
|
<controls:HyperlinkButton Grid.Row="0"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
VerticalAlignment="Top"
|
VerticalAlignment="Top"
|
||||||
NavigateUri="https://wiki.artemis-rgb.com/guides/user/profiles/layers/adaption-hints">
|
NavigateUri="https://wiki.artemis-rgb.com/guides/user/profiles/layers/adaption-hints?mtm_campaign=artemis&mtm_kwd=profile-editor">
|
||||||
Learn more about adaption hints
|
Learn more about adaption hints
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
|
|
||||||
|
|||||||
@ -43,7 +43,7 @@
|
|||||||
When you enable data bindings you can no longer use keyframes or normal values for this property.
|
When you enable data bindings you can no longer use keyframes or normal values for this property.
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
<controls:HyperlinkButton HorizontalAlignment="Center"
|
<controls:HyperlinkButton HorizontalAlignment="Center"
|
||||||
NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/profiles/data-bindings"
|
NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/profiles/data-bindings?mtm_campaign=artemis&mtm_kwd=profile-editor"
|
||||||
Margin="0 10">
|
Margin="0 10">
|
||||||
Learn more
|
Learn more
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
|
|||||||
@ -63,7 +63,12 @@ public partial class VisualEditorView : ReactiveUserControl<VisualEditorViewMode
|
|||||||
private void UpdateZoomBorderBackground()
|
private void UpdateZoomBorderBackground()
|
||||||
{
|
{
|
||||||
if (ZoomBorder.Background is VisualBrush visualBrush)
|
if (ZoomBorder.Background is VisualBrush visualBrush)
|
||||||
|
{
|
||||||
visualBrush.DestinationRect = new RelativeRect(ZoomBorder.OffsetX * -1, ZoomBorder.OffsetY * -1, 20, 20, RelativeUnit.Absolute);
|
visualBrush.DestinationRect = new RelativeRect(ZoomBorder.OffsetX * -1, ZoomBorder.OffsetY * -1, 20, 20, RelativeUnit.Absolute);
|
||||||
|
// Workaround
|
||||||
|
// This fixes an issue where the container is not invalidated, which leaves behind a 'smear' since Avalonia 11 rc1, check if still required later
|
||||||
|
ZoomBorder.InvalidateVisual();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -24,13 +24,13 @@
|
|||||||
</TextBlock>
|
</TextBlock>
|
||||||
|
|
||||||
<StackPanel Grid.Row="0" Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Bottom" Orientation="Horizontal">
|
<StackPanel Grid.Row="0" Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Bottom" Orientation="Horizontal">
|
||||||
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View website" NavigateUri="https://artemis-rgb.com">
|
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View website" NavigateUri="https://artemis-rgb.com?mtm_campaign=artemis&mtm_kwd=about">
|
||||||
<avalonia:MaterialIcon Kind="Web" />
|
<avalonia:MaterialIcon Kind="Web" />
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View GitHub repository" NavigateUri="https://github.com/Artemis-RGB/Artemis">
|
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View GitHub repository" NavigateUri="https://github.com/Artemis-RGB/Artemis">
|
||||||
<avalonia:MaterialIcon Kind="Github" />
|
<avalonia:MaterialIcon Kind="Github" />
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View Wiki" NavigateUri="https://wiki.artemis-rgb.com">
|
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View Wiki" NavigateUri="https://wiki.artemis-rgb.com?mtm_campaign=artemis&mtm_kwd=about">
|
||||||
<avalonia:MaterialIcon Kind="BookOpenOutline" />
|
<avalonia:MaterialIcon Kind="BookOpenOutline" />
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
<TextBox Classes="clearButton" Text="{CompiledBinding SearchPluginInput}" Watermark="Search plugins" Margin="0 0 10 0" />
|
<TextBox Classes="clearButton" Text="{CompiledBinding SearchPluginInput}" Watermark="Search plugins" Margin="0 0 10 0" />
|
||||||
|
|
||||||
<StackPanel Spacing="5" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Right" Orientation="Horizontal">
|
<StackPanel Spacing="5" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Right" Orientation="Horizontal">
|
||||||
<controls:HyperlinkButton VerticalAlignment="Top" NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/plugins">
|
<controls:HyperlinkButton VerticalAlignment="Top" NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/plugins?mtm_campaign=artemis&mtm_kwd=plugins">
|
||||||
Get more plugins
|
Get more plugins
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
<Button Classes="accent" Command="{CompiledBinding ImportPlugin}">Import plugin</Button>
|
<Button Classes="accent" Command="{CompiledBinding ImportPlugin}">Import plugin</Button>
|
||||||
|
|||||||
@ -28,7 +28,7 @@
|
|||||||
TextWrapping="Wrap"
|
TextWrapping="Wrap"
|
||||||
Text="{CompiledBinding Channel, StringFormat='Found no releases for the \'{0}\' channel.'}">
|
Text="{CompiledBinding Channel, StringFormat='Found no releases for the \'{0}\' channel.'}">
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
<controls:HyperlinkButton NavigateUri="https://wiki.artemis-rgb.com/en/channels"
|
<controls:HyperlinkButton NavigateUri="https://wiki.artemis-rgb.com/en/channels?mtm_campaign=artemis&mtm_kwd=releases"
|
||||||
HorizontalAlignment="Center">
|
HorizontalAlignment="Center">
|
||||||
Learn more about channels on the wiki
|
Learn more about channels on the wiki
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
|
|||||||
@ -47,7 +47,7 @@
|
|||||||
ToolTip.Tip="View website"
|
ToolTip.Tip="View website"
|
||||||
ToolTip.Placement="Top"
|
ToolTip.Placement="Top"
|
||||||
ToolTip.VerticalOffset="-5"
|
ToolTip.VerticalOffset="-5"
|
||||||
NavigateUri="https://artemis-rgb.com">
|
NavigateUri="https://artemis-rgb.com?mtm_campaign=artemis&mtm_kwd=sidebar">
|
||||||
<avalonia:MaterialIcon Kind="Web" Width="20" Height="20" />
|
<avalonia:MaterialIcon Kind="Web" Width="20" Height="20" />
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
<controls:HyperlinkButton Classes="icon-button"
|
<controls:HyperlinkButton Classes="icon-button"
|
||||||
@ -65,7 +65,7 @@
|
|||||||
ToolTip.Tip="View Wiki"
|
ToolTip.Tip="View Wiki"
|
||||||
ToolTip.Placement="Top"
|
ToolTip.Placement="Top"
|
||||||
ToolTip.VerticalOffset="-5"
|
ToolTip.VerticalOffset="-5"
|
||||||
NavigateUri="https://wiki.artemis-rgb.com">
|
NavigateUri="https://wiki.artemis-rgb.com?mtm_campaign=artemis&mtm_kwd=sidebar">
|
||||||
<avalonia:MaterialIcon Kind="BookOpenOutline" Width="20" Height="20" />
|
<avalonia:MaterialIcon Kind="BookOpenOutline" Width="20" Height="20" />
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
<controls:HyperlinkButton Classes="icon-button"
|
<controls:HyperlinkButton Classes="icon-button"
|
||||||
@ -83,7 +83,7 @@
|
|||||||
ToolTip.Tip="View donation options"
|
ToolTip.Tip="View donation options"
|
||||||
ToolTip.Placement="Top"
|
ToolTip.Placement="Top"
|
||||||
ToolTip.VerticalOffset="-5"
|
ToolTip.VerticalOffset="-5"
|
||||||
NavigateUri="https://wiki.artemis-rgb.com/en/donating">
|
NavigateUri="https://wiki.artemis-rgb.com/en/donating?mtm_campaign=artemis&mtm_kwd=sidebar">
|
||||||
<avalonia:MaterialIcon Kind="Gift" Width="20" Height="20" />
|
<avalonia:MaterialIcon Kind="Gift" Width="20" Height="20" />
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
</WrapPanel>
|
</WrapPanel>
|
||||||
|
|||||||
@ -33,10 +33,10 @@
|
|||||||
<TextBlock Classes="link-name">Discord</TextBlock>
|
<TextBlock Classes="link-name">Discord</TextBlock>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Grid.Column="1">
|
<StackPanel Grid.Column="1">
|
||||||
<controls:HyperlinkButton NavigateUri="https://wiki.artemis-rgb.com/">
|
<controls:HyperlinkButton NavigateUri="https://wiki.artemis-rgb.com/?mtm_campaign=artemis&mtm_kwd=wizard">
|
||||||
https://wiki.artemis-rgb.com/
|
https://wiki.artemis-rgb.com/
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
<controls:HyperlinkButton NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/introduction">
|
<controls:HyperlinkButton NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/introduction?mtm_campaign=artemis&mtm_kwd=wizard">
|
||||||
https://wiki.artemis-rgb.com/en/guides/user/introduction
|
https://wiki.artemis-rgb.com/en/guides/user/introduction
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
<controls:HyperlinkButton NavigateUri="https://github.com/Artemis-RGB/Artemis">
|
<controls:HyperlinkButton NavigateUri="https://github.com/Artemis-RGB/Artemis">
|
||||||
|
|||||||
@ -16,13 +16,13 @@
|
|||||||
</TextBlock>
|
</TextBlock>
|
||||||
|
|
||||||
<StackPanel Grid.Row="0" Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Bottom" Orientation="Horizontal">
|
<StackPanel Grid.Row="0" Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Bottom" Orientation="Horizontal">
|
||||||
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View website" NavigateUri="https://artemis-rgb.com">
|
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View website" NavigateUri="https://artemis-rgb.com?mtm_campaign=artemis&mtm_kwd=wizard">
|
||||||
<avalonia:MaterialIcon Kind="Web" />
|
<avalonia:MaterialIcon Kind="Web" />
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View GitHub repository" NavigateUri="https://github.com/Artemis-RGB/Artemis">
|
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View GitHub repository" NavigateUri="https://github.com/Artemis-RGB/Artemis">
|
||||||
<avalonia:MaterialIcon Kind="Github" />
|
<avalonia:MaterialIcon Kind="Github" />
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View Wiki" NavigateUri="https://wiki.artemis-rgb.com">
|
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View Wiki" NavigateUri="https://wiki.artemis-rgb.com?mtm_campaign=artemis&mtm_kwd=wizard">
|
||||||
<avalonia:MaterialIcon Kind="BookOpenOutline" />
|
<avalonia:MaterialIcon Kind="BookOpenOutline" />
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@ -110,14 +110,14 @@
|
|||||||
</shared:SelectionRectangle.Background>
|
</shared:SelectionRectangle.Background>
|
||||||
</shared:SelectionRectangle>
|
</shared:SelectionRectangle>
|
||||||
|
|
||||||
<Border Name="SurfaceBounds"
|
<Rectangle Name="SurfaceBounds"
|
||||||
VerticalAlignment="Top"
|
VerticalAlignment="Top"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
Width="{Binding MaxTextureSize}"
|
Width="{Binding MaxTextureSize}"
|
||||||
Height="{Binding MaxTextureSize}"
|
Height="{Binding MaxTextureSize}"
|
||||||
BorderThickness="2"
|
StrokeThickness="2"
|
||||||
BorderBrush="{DynamicResource SystemAccentColorLight1}"
|
Stroke="{DynamicResource SystemAccentColorLight1}"
|
||||||
BorderDashArray="6,2"
|
StrokeDashArray="6,2"
|
||||||
Opacity="0.5" />
|
Opacity="0.5" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</paz:ZoomBorder>
|
</paz:ZoomBorder>
|
||||||
|
|||||||
@ -5,7 +5,6 @@ using Avalonia;
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.PanAndZoom;
|
using Avalonia.Controls.PanAndZoom;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Markup.Xaml;
|
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
@ -30,7 +29,7 @@ public partial class SurfaceEditorView : ReactiveUserControl<SurfaceEditorViewMo
|
|||||||
private void ZoomBorder_OnZoomChanged(object sender, ZoomChangedEventArgs e)
|
private void ZoomBorder_OnZoomChanged(object sender, ZoomChangedEventArgs e)
|
||||||
{
|
{
|
||||||
UpdateZoomBorderBackground();
|
UpdateZoomBorderBackground();
|
||||||
SurfaceBounds.BorderThickness = new Thickness(2 / ContainerZoomBorder.ZoomX);
|
SurfaceBounds.StrokeThickness = 2 / ContainerZoomBorder.ZoomX;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SelectionRectangle_OnSelectionUpdated(object? sender, SelectionRectangleEventArgs e)
|
private void SelectionRectangle_OnSelectionUpdated(object? sender, SelectionRectangleEventArgs e)
|
||||||
@ -49,6 +48,11 @@ public partial class SurfaceEditorView : ReactiveUserControl<SurfaceEditorViewMo
|
|||||||
private void UpdateZoomBorderBackground()
|
private void UpdateZoomBorderBackground()
|
||||||
{
|
{
|
||||||
if (ContainerZoomBorder.Background is VisualBrush visualBrush)
|
if (ContainerZoomBorder.Background is VisualBrush visualBrush)
|
||||||
|
{
|
||||||
visualBrush.DestinationRect = new RelativeRect(ContainerZoomBorder.OffsetX * -1, ContainerZoomBorder.OffsetY * -1, 20, 20, RelativeUnit.Absolute);
|
visualBrush.DestinationRect = new RelativeRect(ContainerZoomBorder.OffsetX * -1, ContainerZoomBorder.OffsetY * -1, 20, 20, RelativeUnit.Absolute);
|
||||||
|
// Workaround
|
||||||
|
// This fixes an issue where the container is not invalidated, which leaves behind a 'smear' since Avalonia 11 rc1, check if still required later
|
||||||
|
ContainerZoomBorder.InvalidateVisual();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,38 +116,38 @@
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Header="_Help">
|
<MenuItem Header="_Help">
|
||||||
<MenuItem Header="Artemis Wiki" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/">
|
<MenuItem Header="Artemis Wiki" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/?mtm_campaign=artemis&mtm_kwd=script-editor">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
<avalonia:MaterialIcon Kind="BookEdit" />
|
<avalonia:MaterialIcon Kind="BookEdit" />
|
||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<Separator />
|
<Separator />
|
||||||
<MenuItem Header="Editor" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/en/guides/user/profiles">
|
<MenuItem Header="Editor" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/en/guides/user/profiles?mtm_campaign=artemis&mtm_kwd=script-editor">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
<avalonia:MaterialIcon Kind="Edit" />
|
<avalonia:MaterialIcon Kind="Edit" />
|
||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Header="Layers" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/layers">
|
<MenuItem Header="Layers" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/layers?mtm_campaign=artemis&mtm_kwd=script-editor">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
<avalonia:MaterialIcon Kind="Layers" />
|
<avalonia:MaterialIcon Kind="Layers" />
|
||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Header="Display Conditions" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/conditions">
|
<MenuItem Header="Display Conditions" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/conditions?mtm_campaign=artemis&mtm_kwd=script-editor">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
<avalonia:MaterialIcon Kind="NotEqual" />
|
<avalonia:MaterialIcon Kind="NotEqual" />
|
||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Header="Timeline" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/timeline">
|
<MenuItem Header="Timeline" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/timeline?mtm_campaign=artemis&mtm_kwd=script-editor">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
<avalonia:MaterialIcon Kind="Stopwatch" />
|
<avalonia:MaterialIcon Kind="Stopwatch" />
|
||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Header="Data Bindings" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/data-bindings">
|
<MenuItem Header="Data Bindings" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/data-bindings?mtm_campaign=artemis&mtm_kwd=script-editor">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
<avalonia:MaterialIcon Kind="VectorLink" />
|
<avalonia:MaterialIcon Kind="VectorLink" />
|
||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Header="Scripting" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/scripting">
|
<MenuItem Header="Scripting" Command="{CompiledBinding OpenUri}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/scripting?mtm_campaign=artemis&mtm_kwd=script-editor">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
<avalonia:MaterialIcon Kind="CodeJson" />
|
<avalonia:MaterialIcon Kind="CodeJson" />
|
||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
@ -173,7 +173,7 @@
|
|||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
VerticalAlignment="Top"
|
VerticalAlignment="Top"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/profiles/nodes">
|
NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/profiles/nodes?mtm_campaign=artemis&mtm_kwd=script-editor">
|
||||||
Learn more about visual scripts
|
Learn more about visual scripts
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
|
|
||||||
|
|||||||
@ -3,32 +3,30 @@ using Avalonia;
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
using Avalonia.Rendering;
|
using Avalonia.Threading;
|
||||||
using Avalonia.VisualTree;
|
using Avalonia.VisualTree;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.VisualScripting.Pins;
|
namespace Artemis.UI.Screens.VisualScripting.Pins;
|
||||||
|
|
||||||
public class PinView : ReactiveUserControl<PinViewModel>
|
public class PinView : ReactiveUserControl<PinViewModel>
|
||||||
{
|
{
|
||||||
private Canvas? _container;
|
private readonly DispatcherTimer _updateTimer;
|
||||||
private bool _dragging;
|
private bool _dragging;
|
||||||
|
private Canvas? _container;
|
||||||
private Border? _pinPoint;
|
private Border? _pinPoint;
|
||||||
private PinViewRenderLoopTaks _renderLoopTask;
|
|
||||||
|
public PinView()
|
||||||
|
{
|
||||||
|
_updateTimer = new DispatcherTimer(TimeSpan.FromMilliseconds(16), DispatcherPriority.Render, UpdatePosition);
|
||||||
|
}
|
||||||
|
|
||||||
protected void InitializePin(Border pinPoint)
|
protected void InitializePin(Border pinPoint)
|
||||||
{
|
{
|
||||||
_pinPoint = pinPoint;
|
_pinPoint = pinPoint;
|
||||||
_pinPoint.PointerMoved += PinPointOnPointerMoved;
|
_pinPoint.PointerMoved += PinPointOnPointerMoved;
|
||||||
_pinPoint.PointerReleased += PinPointOnPointerReleased;
|
_pinPoint.PointerReleased += PinPointOnPointerReleased;
|
||||||
_pinPoint.PropertyChanged += PinPointOnPropertyChanged;
|
|
||||||
_renderLoopTask = new PinViewRenderLoopTaks(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PinPointOnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
Console.WriteLine(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PinPointOnPointerMoved(object? sender, PointerEventArgs e)
|
private void PinPointOnPointerMoved(object? sender, PointerEventArgs e)
|
||||||
{
|
{
|
||||||
if (ViewModel == null || _container == null || _pinPoint == null)
|
if (ViewModel == null || _container == null || _pinPoint == null)
|
||||||
@ -74,19 +72,17 @@ public class PinView : ReactiveUserControl<PinViewModel>
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnAttachedToVisualTree(e);
|
|
||||||
_container = this.FindAncestorOfType<Canvas>();
|
_container = this.FindAncestorOfType<Canvas>();
|
||||||
AvaloniaLocator.Current.GetRequiredService<IRenderLoop>().Add(_renderLoopTask);
|
_updateTimer.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnDetachedFromVisualTree(e);
|
_updateTimer.Stop();
|
||||||
AvaloniaLocator.Current.GetRequiredService<IRenderLoop>().Remove(_renderLoopTask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdatePosition()
|
public void UpdatePosition(object? sender, EventArgs eventArgs)
|
||||||
{
|
{
|
||||||
if (_container == null || _pinPoint == null || ViewModel == null)
|
if (_container == null || _pinPoint == null || ViewModel == null)
|
||||||
return;
|
return;
|
||||||
@ -97,25 +93,4 @@ public class PinView : ReactiveUserControl<PinViewModel>
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
|
||||||
|
|
||||||
public class PinViewRenderLoopTaks : IRenderLoopTask
|
|
||||||
{
|
|
||||||
private readonly PinView _pinView;
|
|
||||||
|
|
||||||
public PinViewRenderLoopTaks(PinView pinView)
|
|
||||||
{
|
|
||||||
_pinView = pinView;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Update(TimeSpan time)
|
|
||||||
{
|
|
||||||
_pinView.UpdatePosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Render()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool NeedsUpdate => true;
|
|
||||||
}
|
}
|
||||||
@ -8,9 +8,9 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Avalonia" Version="11.0.0-preview8" />
|
<PackageReference Include="Avalonia" Version="11.0.0-rc1.1" />
|
||||||
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-preview8" />
|
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-rc1.1" />
|
||||||
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.0.0-preview8" />
|
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.0.0-rc1.1" />
|
||||||
<PackageReference Include="DryIoc.dll" Version="5.4.0" />
|
<PackageReference Include="DryIoc.dll" Version="5.4.0" />
|
||||||
<PackageReference Include="NoStringEvaluating" Version="2.5.2" />
|
<PackageReference Include="NoStringEvaluating" Version="2.5.2" />
|
||||||
<PackageReference Include="ReactiveUI" Version="18.4.26" />
|
<PackageReference Include="ReactiveUI" Version="18.4.26" />
|
||||||
|
|||||||
@ -5,7 +5,7 @@ using NoStringEvaluating.Models.FormulaChecker;
|
|||||||
|
|
||||||
namespace Artemis.VisualScripting.Nodes.Mathematics;
|
namespace Artemis.VisualScripting.Nodes.Mathematics;
|
||||||
|
|
||||||
[Node("Math Expression", "Outputs the result of a math expression.", "Mathematics", "https://wiki.artemis-rgb.com/en/guides/user/profiles/nodes/mathematics/math-expression", InputType = typeof(Numeric), OutputType = typeof(Numeric))]
|
[Node("Math Expression", "Outputs the result of a math expression.", "Mathematics", "https://wiki.artemis-rgb.com/en/guides/user/profiles/nodes/mathematics/math-expression?mtm_campaign=artemis&mtm_kwd=node-help", InputType = typeof(Numeric), OutputType = typeof(Numeric))]
|
||||||
public class MathExpressionNode : Node<string, MathExpressionNodeCustomViewModel>
|
public class MathExpressionNode : Node<string, MathExpressionNodeCustomViewModel>
|
||||||
{
|
{
|
||||||
private readonly IFormulaChecker _checker;
|
private readonly IFormulaChecker _checker;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user