mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-01-01 18:23:32 +00:00
UI - Further sidebar improvements and fixed titlebar
This commit is contained in:
parent
1784d2b8b5
commit
5d8a541624
@ -21,5 +21,8 @@
|
|||||||
<Reference Include="Material.Icons.Avalonia">
|
<Reference Include="Material.Icons.Avalonia">
|
||||||
<HintPath>..\..\..\..\Users\Robert\.nuget\packages\material.icons.avalonia\1.0.2\lib\netstandard2.0\Material.Icons.Avalonia.dll</HintPath>
|
<HintPath>..\..\..\..\Users\Robert\.nuget\packages\material.icons.avalonia\1.0.2\lib\netstandard2.0\Material.Icons.Avalonia.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="RGB.NET.Core">
|
||||||
|
<HintPath>..\..\..\RGB.NET\bin\net5.0\RGB.NET.Core.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -1,14 +1,17 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
|
using Artemis.UI.Avalonia.Shared.Events;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Input;
|
||||||
using Avalonia.LogicalTree;
|
using Avalonia.LogicalTree;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
|
using Avalonia.Media.Imaging;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
|
|
||||||
namespace Artemis.UI.Avalonia.Shared.Controls
|
namespace Artemis.UI.Avalonia.Shared.Controls
|
||||||
@ -18,6 +21,121 @@ namespace Artemis.UI.Avalonia.Shared.Controls
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class DeviceVisualizer : Control
|
public class DeviceVisualizer : Control
|
||||||
{
|
{
|
||||||
|
private readonly DispatcherTimer _timer;
|
||||||
|
private readonly List<DeviceVisualizerLed> _deviceVisualizerLeds;
|
||||||
|
|
||||||
|
private Bitmap? _deviceImage;
|
||||||
|
private List<DeviceVisualizerLed>? _dimmedLeds;
|
||||||
|
private List<DeviceVisualizerLed>? _highlightedLeds;
|
||||||
|
private ArtemisDevice? _oldDevice;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public DeviceVisualizer()
|
||||||
|
{
|
||||||
|
// Run an update timer at 25 fps
|
||||||
|
_timer = new DispatcherTimer(DispatcherPriority.Render) {Interval = TimeSpan.FromMilliseconds(40)};
|
||||||
|
_deviceVisualizerLeds = new List<DeviceVisualizerLed>();
|
||||||
|
|
||||||
|
PointerReleased += OnPointerReleased;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Render(DrawingContext drawingContext)
|
||||||
|
{
|
||||||
|
if (Device == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Determine the scale required to fit the desired size of the control
|
||||||
|
Rect measureSize = MeasureDevice();
|
||||||
|
double scale = Math.Min(Bounds.Width / measureSize.Width, Bounds.Height / measureSize.Height);
|
||||||
|
|
||||||
|
// Scale the visualization in the desired bounding box
|
||||||
|
if (Bounds.Width > 0 && Bounds.Height > 0)
|
||||||
|
drawingContext.PushPostTransform(Matrix.CreateScale(scale, scale));
|
||||||
|
|
||||||
|
// Apply device rotation
|
||||||
|
drawingContext.PushPostTransform(Matrix.CreateTranslation(0 - measureSize.Left, 0 - measureSize.Top));
|
||||||
|
drawingContext.PushPostTransform(Matrix.CreateRotation(Device.Rotation));
|
||||||
|
|
||||||
|
// Apply device scale
|
||||||
|
drawingContext.PushPostTransform(Matrix.CreateScale(Device.Scale, Device.Scale));
|
||||||
|
|
||||||
|
// Render device and LED images
|
||||||
|
if (_deviceImage != null)
|
||||||
|
drawingContext.DrawImage(_deviceImage, new Rect(0, 0, Device.RgbDevice.Size.Width, Device.RgbDevice.Size.Height));
|
||||||
|
|
||||||
|
foreach (DeviceVisualizerLed deviceVisualizerLed in _deviceVisualizerLeds)
|
||||||
|
deviceVisualizerLed.RenderImage(drawingContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when a LED of the device has been clicked
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler<LedClickedEventArgs>? LedClicked;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="LedClicked" /> event
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
protected virtual void OnLedClicked(LedClickedEventArgs e)
|
||||||
|
{
|
||||||
|
LedClicked?.Invoke(this, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Update()
|
||||||
|
{
|
||||||
|
InvalidateVisual();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateTransform()
|
||||||
|
{
|
||||||
|
InvalidateVisual();
|
||||||
|
InvalidateMeasure();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Rect MeasureDevice()
|
||||||
|
{
|
||||||
|
if (Device == null)
|
||||||
|
return Rect.Empty;
|
||||||
|
|
||||||
|
Rect deviceRect = new(0, 0, Device.RgbDevice.ActualSize.Width, Device.RgbDevice.ActualSize.Height);
|
||||||
|
Geometry geometry = new RectangleGeometry(deviceRect);
|
||||||
|
geometry.Transform = new RotateTransform(Device.Rotation);
|
||||||
|
|
||||||
|
return geometry.Bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TimerOnTick(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (ShowColors && IsVisible && Opacity > 0)
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPointerReleased(object? sender, PointerReleasedEventArgs e)
|
||||||
|
{
|
||||||
|
if (Device == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Point position = e.GetPosition(this);
|
||||||
|
double x = position.X / Bounds.Width;
|
||||||
|
double y = position.Y / Bounds.Height;
|
||||||
|
|
||||||
|
Point scaledPosition = new(x * Device.Rectangle.Width, y * Device.Rectangle.Height);
|
||||||
|
DeviceVisualizerLed? deviceVisualizerLed = _deviceVisualizerLeds.FirstOrDefault(l => l.HitTest(scaledPosition));
|
||||||
|
if (deviceVisualizerLed != null)
|
||||||
|
OnLedClicked(new LedClickedEventArgs(deviceVisualizerLed.Led.Device, deviceVisualizerLed.Led));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DevicePropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
Dispatcher.UIThread.Post(SetupForDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DeviceUpdated(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Dispatcher.UIThread.Post(SetupForDevice);
|
||||||
|
}
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -67,26 +185,6 @@ namespace Artemis.UI.Avalonia.Shared.Controls
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private readonly DispatcherTimer _timer;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public DeviceVisualizer()
|
|
||||||
{
|
|
||||||
// Run an update timer at 25 fps
|
|
||||||
_timer = new DispatcherTimer(DispatcherPriority.Render) {Interval = TimeSpan.FromMilliseconds(40)};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override void Render(DrawingContext context)
|
|
||||||
{
|
|
||||||
base.Render(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Update()
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Lifetime management
|
#region Lifetime management
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -105,14 +203,37 @@ namespace Artemis.UI.Avalonia.Shared.Controls
|
|||||||
base.OnDetachedFromLogicalTree(e);
|
base.OnDetachedFromLogicalTree(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
private void SetupForDevice()
|
||||||
|
|
||||||
#region Event handlers
|
|
||||||
|
|
||||||
private void TimerOnTick(object? sender, EventArgs e)
|
|
||||||
{
|
{
|
||||||
if (ShowColors && IsVisible && Opacity > 0)
|
_deviceImage = null;
|
||||||
Update();
|
_deviceVisualizerLeds.Clear();
|
||||||
|
_highlightedLeds = new List<DeviceVisualizerLed>();
|
||||||
|
_dimmedLeds = new List<DeviceVisualizerLed>();
|
||||||
|
|
||||||
|
if (Device == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_oldDevice != null)
|
||||||
|
{
|
||||||
|
Device.RgbDevice.PropertyChanged -= DevicePropertyChanged;
|
||||||
|
Device.DeviceUpdated -= DeviceUpdated;
|
||||||
|
}
|
||||||
|
|
||||||
|
_oldDevice = Device;
|
||||||
|
|
||||||
|
Device.RgbDevice.PropertyChanged += DevicePropertyChanged;
|
||||||
|
Device.DeviceUpdated += DeviceUpdated;
|
||||||
|
UpdateTransform();
|
||||||
|
|
||||||
|
// Load the device main image
|
||||||
|
if (Device.Layout?.Image != null && File.Exists(Device.Layout.Image.LocalPath))
|
||||||
|
_deviceImage = new Bitmap(Device.Layout.Image.AbsolutePath);
|
||||||
|
|
||||||
|
// Create all the LEDs
|
||||||
|
foreach (ArtemisLed artemisLed in Device.Leds)
|
||||||
|
_deviceVisualizerLeds.Add(new DeviceVisualizerLed(artemisLed));
|
||||||
|
|
||||||
|
InvalidateMeasure();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
159
src/Artemis.UI.Avalonia.Shared/Controls/DeviceVisualizerLed.cs
Normal file
159
src/Artemis.UI.Avalonia.Shared/Controls/DeviceVisualizerLed.cs
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using Artemis.Core;
|
||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Media;
|
||||||
|
using Avalonia.Media.Imaging;
|
||||||
|
using RGB.NET.Core;
|
||||||
|
using Color = Avalonia.Media.Color;
|
||||||
|
using Point = Avalonia.Point;
|
||||||
|
using SolidColorBrush = Avalonia.Media.SolidColorBrush;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Avalonia.Shared.Controls
|
||||||
|
{
|
||||||
|
internal class DeviceVisualizerLed
|
||||||
|
{
|
||||||
|
private const byte Dimmed = 100;
|
||||||
|
private const byte NonDimmed = 255;
|
||||||
|
|
||||||
|
public DeviceVisualizerLed(ArtemisLed led)
|
||||||
|
{
|
||||||
|
Led = led;
|
||||||
|
LedRect = new Rect(
|
||||||
|
Led.RgbLed.Location.X,
|
||||||
|
Led.RgbLed.Location.Y,
|
||||||
|
Led.RgbLed.Size.Width,
|
||||||
|
Led.RgbLed.Size.Height
|
||||||
|
);
|
||||||
|
|
||||||
|
if (Led.Layout?.Image != null && File.Exists(Led.Layout.Image.LocalPath))
|
||||||
|
LedImage = new Bitmap(Led.Layout.Image.AbsolutePath);
|
||||||
|
|
||||||
|
CreateLedGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArtemisLed Led { get; }
|
||||||
|
public Rect LedRect { get; set; }
|
||||||
|
public Bitmap? LedImage { get; set; }
|
||||||
|
public Geometry? DisplayGeometry { get; private set; }
|
||||||
|
|
||||||
|
public void RenderImage(DrawingContext drawingContext)
|
||||||
|
{
|
||||||
|
if (LedImage == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
drawingContext.DrawImage(LedImage, LedRect);
|
||||||
|
|
||||||
|
byte r = Led.RgbLed.Color.GetR();
|
||||||
|
byte g = Led.RgbLed.Color.GetG();
|
||||||
|
byte b = Led.RgbLed.Color.GetB();
|
||||||
|
SolidColorBrush fillBrush = new(new Color(100, r, g, b));
|
||||||
|
SolidColorBrush penBrush = new(new Color(255, r, g, b));
|
||||||
|
|
||||||
|
// Create transparent pixels covering the entire LedRect so the image size matched the LedRect size
|
||||||
|
// drawingContext.DrawRectangle(new SolidColorBrush(Colors.Transparent), new Pen(new SolidColorBrush(Colors.Transparent), 1), LedRect);
|
||||||
|
// Translate to the top-left of the LedRect
|
||||||
|
using DrawingContext.PushedState push = drawingContext.PushPostTransform(Matrix.CreateTranslation(LedRect.X, LedRect.Y));
|
||||||
|
// Render the LED geometry
|
||||||
|
drawingContext.DrawGeometry(fillBrush, new Pen(penBrush) {LineJoin = PenLineJoin.Round}, DisplayGeometry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HitTest(Point position)
|
||||||
|
{
|
||||||
|
if (DisplayGeometry == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Geometry translatedGeometry = DisplayGeometry.Clone();
|
||||||
|
translatedGeometry.Transform = new TranslateTransform(Led.RgbLed.Location.X, Led.RgbLed.Location.Y);
|
||||||
|
return translatedGeometry.FillContains(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateLedGeometry()
|
||||||
|
{
|
||||||
|
// The minimum required size for geometry to be created
|
||||||
|
if (Led.RgbLed.Size.Width < 2 || Led.RgbLed.Size.Height < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (Led.RgbLed.Shape)
|
||||||
|
{
|
||||||
|
case Shape.Custom:
|
||||||
|
if (Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keyboard || Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keypad)
|
||||||
|
CreateCustomGeometry(2.0);
|
||||||
|
else
|
||||||
|
CreateCustomGeometry(1.0);
|
||||||
|
break;
|
||||||
|
case Shape.Rectangle:
|
||||||
|
if (Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keyboard || Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keypad)
|
||||||
|
CreateKeyCapGeometry();
|
||||||
|
else
|
||||||
|
CreateRectangleGeometry();
|
||||||
|
break;
|
||||||
|
case Shape.Circle:
|
||||||
|
CreateCircleGeometry();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateRectangleGeometry()
|
||||||
|
{
|
||||||
|
DisplayGeometry = new RectangleGeometry(new Rect(0.5, 0.5, Led.RgbLed.Size.Width - 1, Led.RgbLed.Size.Height - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateCircleGeometry()
|
||||||
|
{
|
||||||
|
DisplayGeometry = new EllipseGeometry(new Rect(0.5, 0.5, Led.RgbLed.Size.Width - 1, Led.RgbLed.Size.Height - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateKeyCapGeometry()
|
||||||
|
{
|
||||||
|
PathGeometry path = PathGeometry.Parse($"M1,1" +
|
||||||
|
$"h{Led.RgbLed.Size.Width - 2} a10," +
|
||||||
|
$"10 0 0 1 10," +
|
||||||
|
$"10 v{Led.RgbLed.Size.Height - 2} a10," +
|
||||||
|
$"10 0 0 1 -10," +
|
||||||
|
$"10 h-{Led.RgbLed.Size.Width - 2} a10," +
|
||||||
|
$"10 0 0 1 -10," +
|
||||||
|
$"-10 v-{Led.RgbLed.Size.Height - 2} a10," +
|
||||||
|
$"10 0 0 1 10,-10 z");
|
||||||
|
DisplayGeometry = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateCustomGeometry(double deflateAmount)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
double width = Led.RgbLed.Size.Width - deflateAmount;
|
||||||
|
double height = Led.RgbLed.Size.Height - deflateAmount;
|
||||||
|
|
||||||
|
Geometry geometry = Geometry.Parse(Led.RgbLed.ShapeData);
|
||||||
|
geometry.Transform = new ScaleTransform(width, height);
|
||||||
|
geometry = geometry.Clone();
|
||||||
|
geometry.Transform = new TranslateTransform(deflateAmount / 2, deflateAmount / 2);
|
||||||
|
DisplayGeometry = geometry.Clone();
|
||||||
|
|
||||||
|
// TODO: Figure out wtf was going on here
|
||||||
|
// if (DisplayGeometry.Bounds.Width > width)
|
||||||
|
// {
|
||||||
|
// DisplayGeometry = Geometry.Combine(Geometry.Empty, DisplayGeometry, GeometryCombineMode.Union, new TransformGroup
|
||||||
|
// {
|
||||||
|
// Children = new TransformCollection {new ScaleTransform(width / DisplayGeometry.Bounds.Width, 1)}
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (DisplayGeometry.Bounds.Height > height)
|
||||||
|
// {
|
||||||
|
// DisplayGeometry = Geometry.Combine(Geometry.Empty, DisplayGeometry, GeometryCombineMode.Union, new TransformGroup
|
||||||
|
// {
|
||||||
|
// Children = new TransformCollection {new ScaleTransform(1, height / DisplayGeometry.Bounds.Height)}
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
CreateRectangleGeometry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using Artemis.Core;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Avalonia.Shared.Events
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides data about selection events raised by <see cref="DataModelDynamicViewModel" />
|
||||||
|
/// </summary>
|
||||||
|
public class DataModelInputDynamicEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
internal DataModelInputDynamicEventArgs(DataModelPath? dataModelPath)
|
||||||
|
{
|
||||||
|
DataModelPath = dataModelPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the data model path that was selected
|
||||||
|
/// </summary>
|
||||||
|
public DataModelPath? DataModelPath { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Avalonia.Shared.Events
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides data about submit events raised by <see cref="DataModelStaticViewModel" />
|
||||||
|
/// </summary>
|
||||||
|
public class DataModelInputStaticEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
internal DataModelInputStaticEventArgs(object? value)
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The value that was submitted
|
||||||
|
/// </summary>
|
||||||
|
public object? Value { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
27
src/Artemis.UI.Avalonia.Shared/Events/LedClickedEventArgs.cs
Normal file
27
src/Artemis.UI.Avalonia.Shared/Events/LedClickedEventArgs.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using Artemis.Core;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Avalonia.Shared.Events
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides data on LED click events raised by the device visualizer
|
||||||
|
/// </summary>
|
||||||
|
public class LedClickedEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
internal LedClickedEventArgs(ArtemisDevice device, ArtemisLed led)
|
||||||
|
{
|
||||||
|
Device = device;
|
||||||
|
Led = led;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The device that was clicked
|
||||||
|
/// </summary>
|
||||||
|
public ArtemisDevice Device { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The LED that was clicked
|
||||||
|
/// </summary>
|
||||||
|
public ArtemisLed Led { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
using System;
|
||||||
|
using Artemis.Core;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Avalonia.Shared.Events
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides data on profile related events raised by the profile editor
|
||||||
|
/// </summary>
|
||||||
|
public class ProfileConfigurationEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
internal ProfileConfigurationEventArgs(ProfileConfiguration? profileConfiguration)
|
||||||
|
{
|
||||||
|
ProfileConfiguration = profileConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal ProfileConfigurationEventArgs(ProfileConfiguration? profileConfiguration, ProfileConfiguration? previousProfileConfiguration)
|
||||||
|
{
|
||||||
|
ProfileConfiguration = profileConfiguration;
|
||||||
|
PreviousProfileConfiguration = previousProfileConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the profile the event was raised for
|
||||||
|
/// </summary>
|
||||||
|
public ProfileConfiguration? ProfileConfiguration { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If applicable, the previous active profile before the event was raised
|
||||||
|
/// </summary>
|
||||||
|
public ProfileConfiguration? PreviousProfileConfiguration { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
using System;
|
||||||
|
using Artemis.Core;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Avalonia.Shared.Events
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides data on profile element related events raised by the profile editor
|
||||||
|
/// </summary>
|
||||||
|
public class RenderProfileElementEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
internal RenderProfileElementEventArgs(RenderProfileElement? renderProfileElement)
|
||||||
|
{
|
||||||
|
RenderProfileElement = renderProfileElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal RenderProfileElementEventArgs(RenderProfileElement? renderProfileElement, RenderProfileElement? previousRenderProfileElement)
|
||||||
|
{
|
||||||
|
RenderProfileElement = renderProfileElement;
|
||||||
|
PreviousRenderProfileElement = previousRenderProfileElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the profile element the event was raised for
|
||||||
|
/// </summary>
|
||||||
|
public RenderProfileElement? RenderProfileElement { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If applicable, the previous active profile element before the event was raised
|
||||||
|
/// </summary>
|
||||||
|
public RenderProfileElement? PreviousRenderProfileElement { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -11,8 +11,13 @@
|
|||||||
|
|
||||||
<Application.Styles>
|
<Application.Styles>
|
||||||
<!-- Third party styles -->
|
<!-- Third party styles -->
|
||||||
<sty:FluentAvaloniaTheme CustomAccentColor="#4db6ac"/>
|
<sty:FluentAvaloniaTheme RequestedTheme="Dark" CustomAccentColor="#4db6ac"/>
|
||||||
<StyleInclude Source="avares://Material.Icons.Avalonia/App.xaml"></StyleInclude>
|
<StyleInclude Source="avares://Material.Icons.Avalonia/App.xaml"/>
|
||||||
|
|
||||||
|
<!-- Grab the window styling from Avalonia -->
|
||||||
|
<StyleInclude Source="avares://Avalonia.Themes.Fluent/Controls/Window.xaml" />
|
||||||
|
<StyleInclude Source="avares://Avalonia.Themes.Fluent/Controls/TitleBar.xaml" />
|
||||||
|
<StyleInclude Source="avares://Avalonia.Themes.Fluent/Controls/CaptionButtons.xaml" />
|
||||||
|
|
||||||
<!-- Global styles -->
|
<!-- Global styles -->
|
||||||
<StyleInclude Source="/Styles/Button.axaml"></StyleInclude>
|
<StyleInclude Source="/Styles/Button.axaml"></StyleInclude>
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
using Artemis.Core.Ninject;
|
using Artemis.Core.Ninject;
|
||||||
using Artemis.UI.Avalonia.Ninject;
|
using Artemis.UI.Avalonia.Ninject;
|
||||||
using Artemis.UI.Avalonia.Screens.Main.Views;
|
|
||||||
using Artemis.UI.Avalonia.Screens.Root.ViewModels;
|
using Artemis.UI.Avalonia.Screens.Root.ViewModels;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls.ApplicationLifetimes;
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
|
using FluentAvalonia.Styling;
|
||||||
using Ninject;
|
using Ninject;
|
||||||
using Splat.Ninject;
|
using Splat.Ninject;
|
||||||
|
|
||||||
@ -23,10 +23,13 @@ namespace Artemis.UI.Avalonia
|
|||||||
public override void OnFrameworkInitializationCompleted()
|
public override void OnFrameworkInitializationCompleted()
|
||||||
{
|
{
|
||||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||||
|
{
|
||||||
desktop.MainWindow = new MainWindow
|
desktop.MainWindow = new MainWindow
|
||||||
{
|
{
|
||||||
DataContext = _kernel.Get<RootViewModel>()
|
DataContext = _kernel.Get<RootViewModel>()
|
||||||
};
|
};
|
||||||
|
AvaloniaLocator.Current.GetService<FluentAvaloniaTheme>().ForceNativeTitleBarToTheme(desktop.MainWindow, "Dark");
|
||||||
|
}
|
||||||
|
|
||||||
base.OnFrameworkInitializationCompleted();
|
base.OnFrameworkInitializationCompleted();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,11 +4,11 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:reactiveUi="http://reactiveui.net"
|
xmlns:reactiveUi="http://reactiveui.net"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Avalonia.Screens.Main.Views.MainWindow"
|
x:Class="Artemis.UI.Avalonia.MainWindow"
|
||||||
Icon="/Assets/avalonia-logo.ico"
|
Icon="/Assets/avalonia-logo.ico"
|
||||||
Title="Artemis.UI.Avalonia"
|
Title="Artemis.UI.Avalonia"
|
||||||
|
ExtendClientAreaToDecorationsHint="True"
|
||||||
TransparencyLevelHint="AcrylicBlur"
|
TransparencyLevelHint="AcrylicBlur"
|
||||||
Background="Transparent"
|
Background="Transparent"
|
||||||
ExtendClientAreaToDecorationsHint="True"
|
|
||||||
Content="{Binding}">
|
Content="{Binding}">
|
||||||
</Window>
|
</Window>
|
||||||
@ -3,7 +3,7 @@ using Avalonia;
|
|||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Avalonia.Screens.Main.Views
|
namespace Artemis.UI.Avalonia
|
||||||
{
|
{
|
||||||
public partial class MainWindow : ReactiveWindow<RootViewModel>
|
public partial class MainWindow : ReactiveWindow<RootViewModel>
|
||||||
{
|
{
|
||||||
|
|||||||
@ -3,6 +3,7 @@ using Artemis.UI.Avalonia.Ninject.Factories;
|
|||||||
using Artemis.UI.Avalonia.Screens;
|
using Artemis.UI.Avalonia.Screens;
|
||||||
using Ninject.Extensions.Conventions;
|
using Ninject.Extensions.Conventions;
|
||||||
using Ninject.Modules;
|
using Ninject.Modules;
|
||||||
|
using Ninject.Planning.Bindings.Resolvers;
|
||||||
|
|
||||||
namespace Artemis.UI.Avalonia.Ninject
|
namespace Artemis.UI.Avalonia.Ninject
|
||||||
{
|
{
|
||||||
@ -13,6 +14,7 @@ namespace Artemis.UI.Avalonia.Ninject
|
|||||||
if (Kernel == null)
|
if (Kernel == null)
|
||||||
throw new ArgumentNullException("Kernel shouldn't be null here.");
|
throw new ArgumentNullException("Kernel shouldn't be null here.");
|
||||||
|
|
||||||
|
Kernel.Components.Add<IMissingBindingResolver, SelfBindingResolver>();
|
||||||
|
|
||||||
Kernel.Bind(x =>
|
Kernel.Bind(x =>
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
namespace Artemis.UI.Avalonia.Screens.Home.ViewModels
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Avalonia.Screens.Home.ViewModels
|
||||||
{
|
{
|
||||||
public class HomeViewModel : MainScreenViewModel
|
public class HomeViewModel : MainScreenViewModel
|
||||||
{
|
{
|
||||||
public HomeViewModel()
|
public HomeViewModel(IScreen hostScreens) : base(hostScreens, "home")
|
||||||
{
|
{
|
||||||
DisplayName = "Home";
|
DisplayName = "Home";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,19 @@
|
|||||||
namespace Artemis.UI.Avalonia.Screens
|
using ReactiveUI;
|
||||||
{
|
|
||||||
public class MainScreenViewModel : ViewModelBase
|
|
||||||
{
|
|
||||||
|
|
||||||
|
namespace Artemis.UI.Avalonia.Screens
|
||||||
|
{
|
||||||
|
public abstract class MainScreenViewModel : ViewModelBase, IRoutableViewModel
|
||||||
|
{
|
||||||
|
protected MainScreenViewModel(IScreen hostScreen, string urlPathSegment)
|
||||||
|
{
|
||||||
|
HostScreen = hostScreen;
|
||||||
|
UrlPathSegment = urlPathSegment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string UrlPathSegment { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IScreen HostScreen { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Reactive;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
@ -10,10 +11,12 @@ namespace Artemis.UI.Avalonia.Screens.Root.ViewModels
|
|||||||
|
|
||||||
public RootViewModel(ICoreService coreService, SidebarViewModel sidebarViewModel)
|
public RootViewModel(ICoreService coreService, SidebarViewModel sidebarViewModel)
|
||||||
{
|
{
|
||||||
|
Router = new RoutingState();
|
||||||
SidebarViewModel = sidebarViewModel;
|
SidebarViewModel = sidebarViewModel;
|
||||||
|
SidebarViewModel.Router = Router;
|
||||||
|
|
||||||
_coreService = coreService;
|
_coreService = coreService;
|
||||||
_coreService.Initialize();
|
_coreService.Initialize();
|
||||||
Console.WriteLine("test");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SidebarViewModel SidebarViewModel { get; }
|
public SidebarViewModel SidebarViewModel { get; }
|
||||||
@ -22,6 +25,6 @@ namespace Artemis.UI.Avalonia.Screens.Root.ViewModels
|
|||||||
public ViewModelActivator Activator { get; } = new();
|
public ViewModelActivator Activator { get; } = new();
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public RoutingState Router { get; } = new();
|
public RoutingState Router { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,5 +1,8 @@
|
|||||||
using Material.Icons;
|
using System;
|
||||||
|
using System.Reactive.Linq;
|
||||||
|
using Material.Icons;
|
||||||
using Ninject;
|
using Ninject;
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Avalonia.Screens.Root.ViewModels
|
namespace Artemis.UI.Avalonia.Screens.Root.ViewModels
|
||||||
{
|
{
|
||||||
@ -27,5 +30,10 @@ namespace Artemis.UI.Avalonia.Screens.Root.ViewModels
|
|||||||
public string DisplayName { get; }
|
public string DisplayName { get; }
|
||||||
|
|
||||||
public abstract MainScreenViewModel CreateInstance(IKernel kernel);
|
public abstract MainScreenViewModel CreateInstance(IKernel kernel);
|
||||||
|
|
||||||
|
public bool IsActive(IObservable<IRoutableViewModel?> routerCurrentViewModel)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -10,6 +10,7 @@ using Artemis.UI.Avalonia.Screens.Workshop.ViewModels;
|
|||||||
using Material.Icons;
|
using Material.Icons;
|
||||||
using Ninject;
|
using Ninject;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
using RGB.NET.Core;
|
||||||
|
|
||||||
namespace Artemis.UI.Avalonia.Screens.Root.ViewModels
|
namespace Artemis.UI.Avalonia.Screens.Root.ViewModels
|
||||||
{
|
{
|
||||||
@ -17,13 +18,18 @@ namespace Artemis.UI.Avalonia.Screens.Root.ViewModels
|
|||||||
{
|
{
|
||||||
private readonly IKernel _kernel;
|
private readonly IKernel _kernel;
|
||||||
private readonly IProfileService _profileService;
|
private readonly IProfileService _profileService;
|
||||||
|
private readonly IRgbService _rgbService;
|
||||||
private readonly ISidebarVmFactory _sidebarVmFactory;
|
private readonly ISidebarVmFactory _sidebarVmFactory;
|
||||||
private SidebarScreenViewModel _selectedSidebarScreen;
|
private ArtemisDevice? _headerDevice;
|
||||||
|
|
||||||
public SidebarViewModel(IKernel kernel, IProfileService profileService, ISidebarVmFactory sidebarVmFactory)
|
private SidebarScreenViewModel _selectedSidebarScreen;
|
||||||
|
private RoutingState _router;
|
||||||
|
|
||||||
|
public SidebarViewModel(IKernel kernel, IProfileService profileService, IRgbService rgbService, ISidebarVmFactory sidebarVmFactory)
|
||||||
{
|
{
|
||||||
_kernel = kernel;
|
_kernel = kernel;
|
||||||
_profileService = profileService;
|
_profileService = profileService;
|
||||||
|
_rgbService = rgbService;
|
||||||
_sidebarVmFactory = sidebarVmFactory;
|
_sidebarVmFactory = sidebarVmFactory;
|
||||||
|
|
||||||
SidebarScreens = new ObservableCollection<SidebarScreenViewModel>
|
SidebarScreens = new ObservableCollection<SidebarScreenViewModel>
|
||||||
@ -33,17 +39,43 @@ namespace Artemis.UI.Avalonia.Screens.Root.ViewModels
|
|||||||
new SidebarScreenViewModel<SurfaceEditorViewModel>(MaterialIconKind.Devices, "Surface Editor"),
|
new SidebarScreenViewModel<SurfaceEditorViewModel>(MaterialIconKind.Devices, "Surface Editor"),
|
||||||
new SidebarScreenViewModel<SettingsViewModel>(MaterialIconKind.Cog, "Settings")
|
new SidebarScreenViewModel<SettingsViewModel>(MaterialIconKind.Cog, "Settings")
|
||||||
};
|
};
|
||||||
SelectedSidebarScreen = SidebarScreens.First();
|
_selectedSidebarScreen = SidebarScreens.First();
|
||||||
|
|
||||||
UpdateProfileCategories();
|
UpdateProfileCategories();
|
||||||
|
UpdateHeaderDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObservableCollection<SidebarScreenViewModel> SidebarScreens { get; }
|
public ObservableCollection<SidebarScreenViewModel> SidebarScreens { get; }
|
||||||
public ObservableCollection<SidebarCategoryViewModel> SidebarCategories { get; } = new();
|
public ObservableCollection<SidebarCategoryViewModel> SidebarCategories { get; } = new();
|
||||||
|
|
||||||
|
public ArtemisDevice? HeaderDevice
|
||||||
|
{
|
||||||
|
get => _headerDevice;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _headerDevice, value);
|
||||||
|
}
|
||||||
|
|
||||||
public SidebarScreenViewModel SelectedSidebarScreen
|
public SidebarScreenViewModel SelectedSidebarScreen
|
||||||
{
|
{
|
||||||
get => _selectedSidebarScreen;
|
get => _selectedSidebarScreen;
|
||||||
set => this.RaiseAndSetIfChanged(ref _selectedSidebarScreen, value);
|
set
|
||||||
|
{
|
||||||
|
this.RaiseAndSetIfChanged(ref _selectedSidebarScreen, value);
|
||||||
|
// if (!SelectedSidebarScreen.IsActive(Router.CurrentViewModel))
|
||||||
|
// Router.Navigate.Execute(SelectedSidebarScreen.CreateInstance(_kernel)).Subscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public RoutingState Router
|
||||||
|
{
|
||||||
|
get => _router;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _router, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SidebarCategoryViewModel AddProfileCategoryViewModel(ProfileCategory profileCategory)
|
||||||
|
{
|
||||||
|
SidebarCategoryViewModel viewModel = _sidebarVmFactory.SidebarCategoryViewModel(profileCategory);
|
||||||
|
SidebarCategories.Add(viewModel);
|
||||||
|
return viewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateProfileCategories()
|
private void UpdateProfileCategories()
|
||||||
@ -53,11 +85,9 @@ namespace Artemis.UI.Avalonia.Screens.Root.ViewModels
|
|||||||
AddProfileCategoryViewModel(profileCategory);
|
AddProfileCategoryViewModel(profileCategory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SidebarCategoryViewModel AddProfileCategoryViewModel(ProfileCategory profileCategory)
|
private void UpdateHeaderDevice()
|
||||||
{
|
{
|
||||||
SidebarCategoryViewModel viewModel = _sidebarVmFactory.SidebarCategoryViewModel(profileCategory);
|
HeaderDevice = _rgbService.Devices.FirstOrDefault(d => d.DeviceType == RGBDeviceType.Keyboard && d.Layout is {IsValid: true});
|
||||||
SidebarCategories.Add(viewModel);
|
|
||||||
return viewModel;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,10 +1,10 @@
|
|||||||
<UserControl xmlns="https://github.com/avaloniaui"
|
<UserControl 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:reactiveUi="http://reactiveui.net"
|
xmlns:reactiveUi="http://reactiveui.net"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Avalonia.Screens.Root.Views.RootView">
|
x:Class="Artemis.UI.Avalonia.Screens.Root.Views.RootView">
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
@ -19,11 +19,10 @@
|
|||||||
TintOpacity="1"
|
TintOpacity="1"
|
||||||
MaterialOpacity="0.65" />
|
MaterialOpacity="0.65" />
|
||||||
</ExperimentalAcrylicBorder.Material>
|
</ExperimentalAcrylicBorder.Material>
|
||||||
<ContentControl Content="{Binding SidebarViewModel}"/>
|
<ContentControl Content="{Binding SidebarViewModel}" />
|
||||||
</ExperimentalAcrylicBorder>
|
</ExperimentalAcrylicBorder>
|
||||||
<Border Grid.Column="1" Background="Black">
|
|
||||||
<reactiveUi:RoutedViewHost Router="{Binding Router}" Margin="0 20 0 0" Padding="15" />
|
|
||||||
</Border>
|
|
||||||
|
|
||||||
|
<Border Grid.Column="1" Background="#101010" IsHitTestVisible="False" />
|
||||||
|
<reactiveUi:RoutedViewHost Grid.Column="1" Router="{Binding Router}" Margin="0 20 0 0" Padding="15" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -4,7 +4,9 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
xmlns:svg="clr-namespace:Avalonia.Svg.Skia;assembly=Avalonia.Svg.Skia"
|
||||||
|
xmlns:shared="clr-namespace:Artemis.UI.Avalonia.Shared.Controls;assembly=Artemis.UI.Avalonia.Shared"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="240" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Avalonia.Screens.Root.Views.SidebarView">
|
x:Class="Artemis.UI.Avalonia.Screens.Root.Views.SidebarView">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
@ -16,40 +18,41 @@
|
|||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<Grid Grid.Row="0" ClipToBounds="True">
|
<Grid Grid.Row="0" IsHitTestVisible="False">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<!-- <shared:DeviceVisualizer Grid.Column="0" -->
|
<Border Grid.Column="0"
|
||||||
<!-- Grid.ColumnSpan="2" -->
|
Grid.ColumnSpan="2">
|
||||||
<!-- Device="{Binding HeaderDevice}" -->
|
<shared:DeviceVisualizer Device="{Binding HeaderDevice}"
|
||||||
<!-- ShowColors="True" -->
|
ShowColors="True"
|
||||||
<!-- RenderTransformOrigin="0.5 0.5" -->
|
VerticalAlignment="Center"
|
||||||
<!-- VerticalAlignment="Center" -->
|
HorizontalAlignment="Center">
|
||||||
<!-- HorizontalAlignment="Center" -->
|
<shared:DeviceVisualizer.RenderTransform>
|
||||||
<!-- RenderOptions.BitmapScalingMode="HighQuality"> -->
|
<TransformGroup>
|
||||||
<!-- <shared:DeviceVisualizer.RenderTransform> -->
|
<RotateTransform Angle="20" />
|
||||||
<!-- <TransformGroup> -->
|
<ScaleTransform ScaleX="2" ScaleY="2" />
|
||||||
<!-- <RotateTransform Angle="20" /> -->
|
</TransformGroup>
|
||||||
<!-- <ScaleTransform ScaleX="2" ScaleY="2" /> -->
|
</shared:DeviceVisualizer.RenderTransform>
|
||||||
<!-- </TransformGroup> -->
|
</shared:DeviceVisualizer>
|
||||||
<!-- </shared:DeviceVisualizer.RenderTransform> -->
|
<Border.OpacityMask>
|
||||||
<!-- </shared:DeviceVisualizer> -->
|
<LinearGradientBrush StartPoint="0,0" EndPoint="0,60">
|
||||||
<Rectangle Grid.Column="0" Grid.ColumnSpan="2" Height="60" VerticalAlignment="Bottom">
|
<GradientStop Color="White" Offset="0"></GradientStop>
|
||||||
<Rectangle.Fill>
|
<GradientStop Color="Transparent" Offset="1"></GradientStop>
|
||||||
<LinearGradientBrush StartPoint="0,1" EndPoint="0,0">
|
|
||||||
<GradientStop Color="Black" Offset="0" />
|
|
||||||
<GradientStop Color="#00000000" Offset="1" />
|
|
||||||
</LinearGradientBrush>
|
</LinearGradientBrush>
|
||||||
</Rectangle.Fill>
|
</Border.OpacityMask>
|
||||||
</Rectangle>
|
</Border>
|
||||||
|
|
||||||
<Image Grid.Column="0" Source="{SvgImage /Assets/Images/Logo/bow.svg}" Height="35" Width="35" Margin="10" />
|
<Image Grid.Column="0" >
|
||||||
|
<Image.Source>
|
||||||
|
<svg:SvgImage Source="/Assets/Images/Logo/bow.svg" />
|
||||||
|
</Image.Source>
|
||||||
|
</Image>
|
||||||
<TextBlock Grid.Column="1"
|
<TextBlock Grid.Column="1"
|
||||||
|
FontSize="24"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
|
|
||||||
Foreground="{DynamicResource MaterialDesignDarkForeground}">
|
Foreground="{DynamicResource MaterialDesignDarkForeground}">
|
||||||
Artemis 2
|
Artemis 2
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
namespace Artemis.UI.Avalonia.Screens.Settings.ViewModels
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Avalonia.Screens.Settings.ViewModels
|
||||||
{
|
{
|
||||||
public class SettingsViewModel : MainScreenViewModel
|
public class SettingsViewModel : MainScreenViewModel
|
||||||
{
|
{
|
||||||
public SettingsViewModel()
|
public SettingsViewModel(IScreen hostScreens) : base(hostScreens, "settings")
|
||||||
{
|
{
|
||||||
DisplayName = "Settings";
|
DisplayName = "Settings";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
namespace Artemis.UI.Avalonia.Screens.SurfaceEditor.ViewModels
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Avalonia.Screens.SurfaceEditor.ViewModels
|
||||||
{
|
{
|
||||||
public class SurfaceEditorViewModel : MainScreenViewModel
|
public class SurfaceEditorViewModel : MainScreenViewModel
|
||||||
{
|
{
|
||||||
public SurfaceEditorViewModel()
|
public SurfaceEditorViewModel(IScreen hostScreens) : base(hostScreens, "surface-editor")
|
||||||
{
|
{
|
||||||
DisplayName = "Surface Editor";
|
DisplayName = "Surface Editor";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
namespace Artemis.UI.Avalonia.Screens.Workshop.ViewModels
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Avalonia.Screens.Workshop.ViewModels
|
||||||
{
|
{
|
||||||
public class WorkshopViewModel : MainScreenViewModel
|
public class WorkshopViewModel : MainScreenViewModel
|
||||||
{
|
{
|
||||||
public WorkshopViewModel()
|
public WorkshopViewModel(IScreen hostScreens) : base(hostScreens, "workshop")
|
||||||
{
|
{
|
||||||
DisplayName = "Workshop";
|
DisplayName = "Workshop";
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user