mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Transform tool - WIP commit
This commit is contained in:
parent
c36110e79d
commit
12e91b8c81
@ -22,7 +22,7 @@ namespace Artemis.UI.Shared.DataModelVisualization
|
||||
set
|
||||
{
|
||||
if (Equals(value, _displayValue)) return;
|
||||
this.RaiseAndSetIfChanged(ref _displayValue, value);
|
||||
RaiseAndSetIfChanged(ref _displayValue, value);
|
||||
OnDisplayValueUpdated();
|
||||
}
|
||||
}
|
||||
@ -56,7 +56,7 @@ namespace Artemis.UI.Shared.DataModelVisualization
|
||||
public DataModelPropertyAttribute? PropertyDescription
|
||||
{
|
||||
get => _propertyDescription;
|
||||
internal set => this.RaiseAndSetIfChanged(ref _propertyDescription, value);
|
||||
internal set => RaiseAndSetIfChanged(ref _propertyDescription, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -28,7 +28,7 @@ namespace Artemis.UI.Shared.DefaultTypes.DataModel.Display
|
||||
public string Display
|
||||
{
|
||||
get => _display;
|
||||
set => this.RaiseAndSetIfChanged(ref _display, value);
|
||||
set => RaiseAndSetIfChanged(ref _display, value);
|
||||
}
|
||||
|
||||
protected override void OnDisplayValueUpdated()
|
||||
|
||||
109
src/Avalonia/Artemis.UI.Shared/Extensions/LayerExtensions.cs
Normal file
109
src/Avalonia/Artemis.UI.Shared/Extensions/LayerExtensions.cs
Normal file
@ -0,0 +1,109 @@
|
||||
using System.Linq;
|
||||
using Artemis.Core;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.UI.Shared.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Provides utilities when working with layers in UI elements.
|
||||
/// </summary>
|
||||
public static class LayerExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the layer's bounds in real coordinates.
|
||||
/// </summary>
|
||||
public static SKRect GetLayerBounds(this Layer layer)
|
||||
{
|
||||
return new SKRect(
|
||||
layer.Leds.Min(l => l.RgbLed.AbsoluteBoundary.Location.X),
|
||||
layer.Leds.Min(l => l.RgbLed.AbsoluteBoundary.Location.Y),
|
||||
layer.Leds.Max(l => l.RgbLed.AbsoluteBoundary.Location.X + l.RgbLed.AbsoluteBoundary.Size.Width),
|
||||
layer.Leds.Max(l => l.RgbLed.AbsoluteBoundary.Location.Y + l.RgbLed.AbsoluteBoundary.Size.Height)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the layer's anchor in real coordinates.
|
||||
/// </summary>
|
||||
public static SKPoint GetLayerAnchorPosition(this Layer layer, SKPoint? positionOverride = null)
|
||||
{
|
||||
SKRect layerBounds = GetLayerBounds(layer);
|
||||
SKPoint positionProperty = layer.Transform.Position.CurrentValue;
|
||||
if (positionOverride != null)
|
||||
positionProperty = positionOverride.Value;
|
||||
|
||||
// Start at the center of the shape
|
||||
SKPoint position = new(layerBounds.MidX, layerBounds.MidY);
|
||||
|
||||
// Apply translation
|
||||
position.X += positionProperty.X * layerBounds.Width;
|
||||
position.Y += positionProperty.Y * layerBounds.Height;
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an absolute and scaled rectangular path for the given layer in real coordinates.
|
||||
/// </summary>
|
||||
public static SKPath GetLayerPath(this Layer layer, bool includeTranslation, bool includeScale, bool includeRotation, SKPoint? anchorOverride = null)
|
||||
{
|
||||
SKRect layerBounds = GetLayerBounds(layer);
|
||||
|
||||
// Apply transformation like done by the core during layer rendering (same differences apply as in GetLayerTransformGroup)
|
||||
SKPoint anchorPosition = GetLayerAnchorPosition(layer);
|
||||
if (anchorOverride != null)
|
||||
anchorPosition = anchorOverride.Value;
|
||||
|
||||
SKPoint anchorProperty = layer.Transform.AnchorPoint.CurrentValue;
|
||||
|
||||
// Translation originates from the unscaled center of the shape and is tied to the anchor
|
||||
float x = anchorPosition.X - layerBounds.MidX - anchorProperty.X * layerBounds.Width;
|
||||
float y = anchorPosition.Y - layerBounds.MidY - anchorProperty.Y * layerBounds.Height;
|
||||
|
||||
SKPath path = new();
|
||||
path.AddRect(layerBounds);
|
||||
if (includeTranslation)
|
||||
path.Transform(SKMatrix.CreateTranslation(x, y));
|
||||
if (includeScale)
|
||||
path.Transform(SKMatrix.CreateScale(layer.Transform.Scale.CurrentValue.Width / 100f, layer.Transform.Scale.CurrentValue.Height / 100f, anchorPosition.X, anchorPosition.Y));
|
||||
if (includeRotation)
|
||||
path.Transform(SKMatrix.CreateRotationDegrees(layer.Transform.Rotation.CurrentValue, anchorPosition.X, anchorPosition.Y));
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new point normalized to 0.0-1.0
|
||||
/// </summary>
|
||||
public static SKPoint GetScaledPoint(this Layer layer, SKPoint point, bool absolute)
|
||||
{
|
||||
SKRect bounds = GetLayerBounds(layer);
|
||||
if (absolute)
|
||||
return new SKPoint(
|
||||
100 / bounds.Width * (point.X - bounds.Left) / 100,
|
||||
100 / bounds.Height * (point.Y - bounds.Top) / 100
|
||||
);
|
||||
|
||||
return new SKPoint(
|
||||
100 / bounds.Width * point.X / 100,
|
||||
100 / bounds.Height * point.Y / 100
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the offset from the given point to the top-left of the layer
|
||||
/// </summary>
|
||||
public static SKPoint GetDragOffset(this Layer layer, SKPoint dragStart)
|
||||
{
|
||||
// Figure out what the top left will be if the shape moves to the current cursor position
|
||||
SKPoint scaledDragStart = GetScaledPoint(layer, dragStart, true);
|
||||
SKPoint tempAnchor = GetLayerAnchorPosition(layer, scaledDragStart);
|
||||
SKPoint tempTopLeft = GetLayerPath(layer, true, true, true, tempAnchor)[0];
|
||||
|
||||
// Get the shape's position
|
||||
SKPoint topLeft = GetLayerPath(layer, true, true, true)[0];
|
||||
|
||||
// The difference between the two is the offset
|
||||
return topLeft - tempTopLeft;
|
||||
}
|
||||
}
|
||||
@ -42,7 +42,7 @@ namespace Artemis.UI.Shared.ScriptingProviders
|
||||
public Script? Script
|
||||
{
|
||||
get => _script;
|
||||
internal set => this.RaiseAndSetIfChanged(ref _script, value);
|
||||
internal set => RaiseAndSetIfChanged(ref _script, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@ -78,7 +78,7 @@ public abstract class ToolViewModel : ActivatableViewModelBase, IToolViewModel
|
||||
public bool IsSelected
|
||||
{
|
||||
get => _isSelected;
|
||||
set => this.RaiseAndSetIfChanged(ref _isSelected, value);
|
||||
set => RaiseAndSetIfChanged(ref _isSelected, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@ -1,118 +1,142 @@
|
||||
using System;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Artemis.UI.Shared.Events;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using JetBrains.Annotations;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Validation.Helpers;
|
||||
|
||||
namespace Artemis.UI.Shared
|
||||
namespace Artemis.UI.Shared;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the base class for Artemis view models
|
||||
/// </summary>
|
||||
public abstract class ContentDialogViewModelBase : ReactiveValidationObject, IActivatableViewModel, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the base class for Artemis view models
|
||||
/// Gets the content dialog that hosts the view model
|
||||
/// </summary>
|
||||
public abstract class ContentDialogViewModelBase : ReactiveValidationObject, IActivatableViewModel, IDisposable
|
||||
public ContentDialog? ContentDialog { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Releases the unmanaged resources used by the object and optionally releases the managed resources.
|
||||
/// </summary>
|
||||
/// <param name="disposing">
|
||||
/// <see langword="true" /> to release both managed and unmanaged resources;
|
||||
/// <see langword="false" /> to release only unmanaged resources.
|
||||
/// </param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the content dialog that hosts the view model
|
||||
/// </summary>
|
||||
public ContentDialog? ContentDialog { get; internal set; }
|
||||
}
|
||||
|
||||
#region Implementation of IActivatableViewModel
|
||||
#region Implementation of IActivatableViewModel
|
||||
|
||||
/// <inheritdoc />
|
||||
public ViewModelActivator Activator { get; } = new();
|
||||
/// <inheritdoc />
|
||||
public ViewModelActivator Activator { get; } = new();
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region IDisposable
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases the unmanaged resources used by the object and optionally releases the managed resources.
|
||||
/// </summary>
|
||||
/// <param name="disposing">
|
||||
/// <see langword="true" /> to release both managed and unmanaged resources;
|
||||
/// <see langword="false" /> to release only unmanaged resources.
|
||||
/// </param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Represents the base class for Artemis view models
|
||||
/// </summary>
|
||||
public abstract class ViewModelValidationBase : ReactiveValidationObject
|
||||
{
|
||||
private string? _displayName;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the display name of the view model
|
||||
/// </summary>
|
||||
public string? DisplayName
|
||||
{
|
||||
get => _displayName;
|
||||
set => this.RaiseAndSetIfChanged(ref _displayName, value);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
/// <summary>
|
||||
/// Represents the base class for Artemis view models
|
||||
/// </summary>
|
||||
public abstract class ViewModelBase : ReactiveObject
|
||||
{
|
||||
private string? _displayName;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the display name of the view model
|
||||
/// </summary>
|
||||
public string? DisplayName
|
||||
{
|
||||
get => _displayName;
|
||||
set => RaiseAndSetIfChanged(ref _displayName, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the base class for Artemis view models
|
||||
/// RaiseAndSetIfChanged fully implements a Setter for a read-write property on a ReactiveObject, using
|
||||
/// CallerMemberName to raise the notification and the ref to the backing field to set the property.
|
||||
/// </summary>
|
||||
public abstract class ViewModelValidationBase : ReactiveValidationObject
|
||||
/// <typeparam name="TRet">The type of the return value.</typeparam>
|
||||
/// <param name="backingField">A Reference to the backing field for this property.</param>
|
||||
/// <param name="newValue">The new value.</param>
|
||||
/// <param name="propertyName">
|
||||
/// The name of the property, usually automatically provided through the CallerMemberName
|
||||
/// attribute.
|
||||
/// </param>
|
||||
/// <returns>The newly set value, normally discarded.</returns>
|
||||
[NotifyPropertyChangedInvocator]
|
||||
public TRet RaiseAndSetIfChanged<TRet>(ref TRet backingField, TRet newValue, [CallerMemberName] string? propertyName = null)
|
||||
{
|
||||
private string? _displayName;
|
||||
if (propertyName is null)
|
||||
throw new ArgumentNullException(nameof(propertyName));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the display name of the view model
|
||||
/// </summary>
|
||||
public string? DisplayName
|
||||
{
|
||||
get => _displayName;
|
||||
set => this.RaiseAndSetIfChanged(ref _displayName, value);
|
||||
}
|
||||
if (EqualityComparer<TRet>.Default.Equals(backingField, newValue))
|
||||
return newValue;
|
||||
|
||||
this.RaisePropertyChanging(propertyName);
|
||||
backingField = newValue;
|
||||
this.RaisePropertyChanged(propertyName);
|
||||
return newValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the base class for Artemis view models that are interested in the activated event
|
||||
/// </summary>
|
||||
public abstract class ActivatableViewModelBase : ViewModelBase, IActivatableViewModel
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public ViewModelActivator Activator { get; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the base class for Artemis view models used to drive dialogs
|
||||
/// </summary>
|
||||
public abstract class DialogViewModelBase<TResult> : ActivatableViewModelBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Closes the dialog with the given <paramref name="result" />
|
||||
/// </summary>
|
||||
/// <param name="result">The result of the dialog</param>
|
||||
public void Close(TResult result)
|
||||
{
|
||||
CloseRequested?.Invoke(this, new DialogClosedEventArgs<TResult>(result));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the base class for Artemis view models
|
||||
/// Closes the dialog without a result
|
||||
/// </summary>
|
||||
public abstract class ViewModelBase : ReactiveObject
|
||||
public void Cancel()
|
||||
{
|
||||
private string? _displayName;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the display name of the view model
|
||||
/// </summary>
|
||||
public string? DisplayName
|
||||
{
|
||||
get => _displayName;
|
||||
set => this.RaiseAndSetIfChanged(ref _displayName, value);
|
||||
}
|
||||
CancelRequested?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the base class for Artemis view models that are interested in the activated event
|
||||
/// </summary>
|
||||
public abstract class ActivatableViewModelBase : ViewModelBase, IActivatableViewModel
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public ViewModelActivator Activator { get; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the base class for Artemis view models used to drive dialogs
|
||||
/// </summary>
|
||||
public abstract class DialogViewModelBase<TResult> : ActivatableViewModelBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Closes the dialog with the given <paramref name="result" />
|
||||
/// </summary>
|
||||
/// <param name="result">The result of the dialog</param>
|
||||
public void Close(TResult result)
|
||||
{
|
||||
CloseRequested?.Invoke(this, new DialogClosedEventArgs<TResult>(result));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes the dialog without a result
|
||||
/// </summary>
|
||||
public void Cancel()
|
||||
{
|
||||
CancelRequested?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
internal event EventHandler<DialogClosedEventArgs<TResult>>? CloseRequested;
|
||||
internal event EventHandler? CancelRequested;
|
||||
}
|
||||
internal event EventHandler<DialogClosedEventArgs<TResult>>? CloseRequested;
|
||||
internal event EventHandler? CancelRequested;
|
||||
}
|
||||
@ -38,7 +38,7 @@ namespace Artemis.UI.Screens.Debugger
|
||||
public NavigationViewItem? SelectedItem
|
||||
{
|
||||
get => _selectedItem;
|
||||
set => this.RaiseAndSetIfChanged(ref _selectedItem, value);
|
||||
set => RaiseAndSetIfChanged(ref _selectedItem, value);
|
||||
}
|
||||
|
||||
private void NavigateToSelectedItem(NavigationViewItem item)
|
||||
|
||||
@ -59,13 +59,13 @@ namespace Artemis.UI.Screens.Debugger.DataModel
|
||||
public DataModelPropertiesViewModel? MainDataModel
|
||||
{
|
||||
get => _mainDataModel;
|
||||
set => this.RaiseAndSetIfChanged(ref _mainDataModel, value);
|
||||
set => RaiseAndSetIfChanged(ref _mainDataModel, value);
|
||||
}
|
||||
|
||||
public string? PropertySearch
|
||||
{
|
||||
get => _propertySearch;
|
||||
set => this.RaiseAndSetIfChanged(ref _propertySearch, value);
|
||||
set => RaiseAndSetIfChanged(ref _propertySearch, value);
|
||||
}
|
||||
|
||||
public bool SlowUpdates
|
||||
@ -73,7 +73,7 @@ namespace Artemis.UI.Screens.Debugger.DataModel
|
||||
get => _slowUpdates;
|
||||
set
|
||||
{
|
||||
this.RaiseAndSetIfChanged(ref _slowUpdates, value);
|
||||
RaiseAndSetIfChanged(ref _slowUpdates, value);
|
||||
_updateTimer.Interval = _slowUpdates ? 500 : 25;
|
||||
}
|
||||
}
|
||||
@ -85,7 +85,7 @@ namespace Artemis.UI.Screens.Debugger.DataModel
|
||||
get => _selectedModule;
|
||||
set
|
||||
{
|
||||
this.RaiseAndSetIfChanged(ref _selectedModule, value);
|
||||
RaiseAndSetIfChanged(ref _selectedModule, value);
|
||||
GetDataModel();
|
||||
}
|
||||
}
|
||||
@ -95,7 +95,7 @@ namespace Artemis.UI.Screens.Debugger.DataModel
|
||||
get => _isModuleFilterEnabled;
|
||||
set
|
||||
{
|
||||
this.RaiseAndSetIfChanged(ref _isModuleFilterEnabled, value);
|
||||
RaiseAndSetIfChanged(ref _isModuleFilterEnabled, value);
|
||||
|
||||
if (!IsModuleFilterEnabled)
|
||||
SelectedModule = null;
|
||||
|
||||
@ -22,31 +22,31 @@ namespace Artemis.UI.Screens.Debugger.Performance
|
||||
public string? Last
|
||||
{
|
||||
get => _last;
|
||||
set => this.RaiseAndSetIfChanged(ref _last, value);
|
||||
set => RaiseAndSetIfChanged(ref _last, value);
|
||||
}
|
||||
|
||||
public string? Average
|
||||
{
|
||||
get => _average;
|
||||
set => this.RaiseAndSetIfChanged(ref _average, value);
|
||||
set => RaiseAndSetIfChanged(ref _average, value);
|
||||
}
|
||||
|
||||
public string? Min
|
||||
{
|
||||
get => _min;
|
||||
set => this.RaiseAndSetIfChanged(ref _min, value);
|
||||
set => RaiseAndSetIfChanged(ref _min, value);
|
||||
}
|
||||
|
||||
public string? Max
|
||||
{
|
||||
get => _max;
|
||||
set => this.RaiseAndSetIfChanged(ref _max, value);
|
||||
set => RaiseAndSetIfChanged(ref _max, value);
|
||||
}
|
||||
|
||||
public string? Percentile
|
||||
{
|
||||
get => _percentile;
|
||||
set => this.RaiseAndSetIfChanged(ref _percentile, value);
|
||||
set => RaiseAndSetIfChanged(ref _percentile, value);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
|
||||
@ -66,25 +66,25 @@ namespace Artemis.UI.Screens.Debugger.Performance
|
||||
public double CurrentFps
|
||||
{
|
||||
get => _currentFps;
|
||||
set => this.RaiseAndSetIfChanged(ref _currentFps, value);
|
||||
set => RaiseAndSetIfChanged(ref _currentFps, value);
|
||||
}
|
||||
|
||||
public int RenderWidth
|
||||
{
|
||||
get => _renderWidth;
|
||||
set => this.RaiseAndSetIfChanged(ref _renderWidth, value);
|
||||
set => RaiseAndSetIfChanged(ref _renderWidth, value);
|
||||
}
|
||||
|
||||
public int RenderHeight
|
||||
{
|
||||
get => _renderHeight;
|
||||
set => this.RaiseAndSetIfChanged(ref _renderHeight, value);
|
||||
set => RaiseAndSetIfChanged(ref _renderHeight, value);
|
||||
}
|
||||
|
||||
public string? Renderer
|
||||
{
|
||||
get => _renderer;
|
||||
set => this.RaiseAndSetIfChanged(ref _renderer, value);
|
||||
set => RaiseAndSetIfChanged(ref _renderer, value);
|
||||
}
|
||||
|
||||
private void HandleActivation()
|
||||
|
||||
@ -35,31 +35,31 @@ namespace Artemis.UI.Screens.Debugger.Render
|
||||
public Bitmap? CurrentFrame
|
||||
{
|
||||
get => _currentFrame;
|
||||
set => this.RaiseAndSetIfChanged(ref _currentFrame, value);
|
||||
set => RaiseAndSetIfChanged(ref _currentFrame, value);
|
||||
}
|
||||
|
||||
public double CurrentFps
|
||||
{
|
||||
get => _currentFps;
|
||||
set => this.RaiseAndSetIfChanged(ref _currentFps, value);
|
||||
set => RaiseAndSetIfChanged(ref _currentFps, value);
|
||||
}
|
||||
|
||||
public int RenderWidth
|
||||
{
|
||||
get => _renderWidth;
|
||||
set => this.RaiseAndSetIfChanged(ref _renderWidth, value);
|
||||
set => RaiseAndSetIfChanged(ref _renderWidth, value);
|
||||
}
|
||||
|
||||
public int RenderHeight
|
||||
{
|
||||
get => _renderHeight;
|
||||
set => this.RaiseAndSetIfChanged(ref _renderHeight, value);
|
||||
set => RaiseAndSetIfChanged(ref _renderHeight, value);
|
||||
}
|
||||
|
||||
public string? Renderer
|
||||
{
|
||||
get => _renderer;
|
||||
set => this.RaiseAndSetIfChanged(ref _renderer, value);
|
||||
set => RaiseAndSetIfChanged(ref _renderer, value);
|
||||
}
|
||||
|
||||
private void HandleActivation()
|
||||
|
||||
@ -57,7 +57,7 @@ namespace Artemis.UI.Screens.Device
|
||||
public bool TogglingDevice
|
||||
{
|
||||
get => _togglingDevice;
|
||||
set => this.RaiseAndSetIfChanged(ref _togglingDevice, value);
|
||||
set => RaiseAndSetIfChanged(ref _togglingDevice, value);
|
||||
}
|
||||
|
||||
public void IdentifyDevice()
|
||||
|
||||
@ -60,7 +60,7 @@ namespace Artemis.UI.Screens.Device
|
||||
get => _isSelected;
|
||||
set
|
||||
{
|
||||
if (!this.RaiseAndSetIfChanged(ref _isSelected, value))
|
||||
if (!RaiseAndSetIfChanged(ref _isSelected, value))
|
||||
return;
|
||||
Apply();
|
||||
}
|
||||
|
||||
@ -84,55 +84,55 @@ namespace Artemis.UI.Screens.Device
|
||||
public int X
|
||||
{
|
||||
get => _x;
|
||||
set => this.RaiseAndSetIfChanged(ref _x, value);
|
||||
set => RaiseAndSetIfChanged(ref _x, value);
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get => _y;
|
||||
set => this.RaiseAndSetIfChanged(ref _y, value);
|
||||
set => RaiseAndSetIfChanged(ref _y, value);
|
||||
}
|
||||
|
||||
public float Scale
|
||||
{
|
||||
get => _scale;
|
||||
set => this.RaiseAndSetIfChanged(ref _scale, value);
|
||||
set => RaiseAndSetIfChanged(ref _scale, value);
|
||||
}
|
||||
|
||||
public int Rotation
|
||||
{
|
||||
get => _rotation;
|
||||
set => this.RaiseAndSetIfChanged(ref _rotation, value);
|
||||
set => RaiseAndSetIfChanged(ref _rotation, value);
|
||||
}
|
||||
|
||||
public float RedScale
|
||||
{
|
||||
get => _redScale;
|
||||
set => this.RaiseAndSetIfChanged(ref _redScale, value);
|
||||
set => RaiseAndSetIfChanged(ref _redScale, value);
|
||||
}
|
||||
|
||||
public float GreenScale
|
||||
{
|
||||
get => _greenScale;
|
||||
set => this.RaiseAndSetIfChanged(ref _greenScale, value);
|
||||
set => RaiseAndSetIfChanged(ref _greenScale, value);
|
||||
}
|
||||
|
||||
public float BlueScale
|
||||
{
|
||||
get => _blueScale;
|
||||
set => this.RaiseAndSetIfChanged(ref _blueScale, value);
|
||||
set => RaiseAndSetIfChanged(ref _blueScale, value);
|
||||
}
|
||||
|
||||
public SKColor CurrentColor
|
||||
{
|
||||
get => _currentColor;
|
||||
set => this.RaiseAndSetIfChanged(ref _currentColor, value);
|
||||
set => RaiseAndSetIfChanged(ref _currentColor, value);
|
||||
}
|
||||
|
||||
public bool DisplayOnDevices
|
||||
{
|
||||
get => _displayOnDevices;
|
||||
set => this.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.
|
||||
|
||||
@ -37,7 +37,7 @@ namespace Artemis.UI.Screens.Device
|
||||
public ArtemisLed? SelectedLed
|
||||
{
|
||||
get => _selectedLed;
|
||||
set => this.RaiseAndSetIfChanged(ref _selectedLed, value);
|
||||
set => RaiseAndSetIfChanged(ref _selectedLed, value);
|
||||
}
|
||||
|
||||
public ObservableCollection<(ArtemisLed, ArtemisLed)> InputMappings { get; }
|
||||
|
||||
@ -47,37 +47,37 @@ namespace Artemis.UI.Screens.Plugins
|
||||
public PluginPrerequisiteViewModel? ActivePrerequisite
|
||||
{
|
||||
get => _activePrerequisite;
|
||||
set => this.RaiseAndSetIfChanged(ref _activePrerequisite, value);
|
||||
set => RaiseAndSetIfChanged(ref _activePrerequisite, value);
|
||||
}
|
||||
|
||||
public bool ShowProgress
|
||||
{
|
||||
get => _showProgress;
|
||||
set => this.RaiseAndSetIfChanged(ref _showProgress, value);
|
||||
set => RaiseAndSetIfChanged(ref _showProgress, value);
|
||||
}
|
||||
|
||||
public bool ShowIntro
|
||||
{
|
||||
get => _showIntro;
|
||||
set => this.RaiseAndSetIfChanged(ref _showIntro, value);
|
||||
set => RaiseAndSetIfChanged(ref _showIntro, value);
|
||||
}
|
||||
|
||||
public bool ShowFailed
|
||||
{
|
||||
get => _showFailed;
|
||||
set => this.RaiseAndSetIfChanged(ref _showFailed, value);
|
||||
set => RaiseAndSetIfChanged(ref _showFailed, value);
|
||||
}
|
||||
|
||||
public bool ShowInstall
|
||||
{
|
||||
get => _showInstall;
|
||||
set => this.RaiseAndSetIfChanged(ref _showInstall, value);
|
||||
set => RaiseAndSetIfChanged(ref _showInstall, value);
|
||||
}
|
||||
|
||||
public bool CanInstall
|
||||
{
|
||||
get => _canInstall;
|
||||
set => this.RaiseAndSetIfChanged(ref _canInstall, value);
|
||||
set => RaiseAndSetIfChanged(ref _canInstall, value);
|
||||
}
|
||||
|
||||
public async Task Install()
|
||||
|
||||
@ -55,19 +55,19 @@ namespace Artemis.UI.Screens.Plugins
|
||||
public PluginPrerequisiteViewModel? ActivePrerequisite
|
||||
{
|
||||
get => _activePrerequisite;
|
||||
set => this.RaiseAndSetIfChanged(ref _activePrerequisite, value);
|
||||
set => RaiseAndSetIfChanged(ref _activePrerequisite, value);
|
||||
}
|
||||
|
||||
public bool CanUninstall
|
||||
{
|
||||
get => _canUninstall;
|
||||
set => this.RaiseAndSetIfChanged(ref _canUninstall, value);
|
||||
set => RaiseAndSetIfChanged(ref _canUninstall, value);
|
||||
}
|
||||
|
||||
public bool IsFinished
|
||||
{
|
||||
get => _isFinished;
|
||||
set => this.RaiseAndSetIfChanged(ref _isFinished, value);
|
||||
set => RaiseAndSetIfChanged(ref _isFinished, value);
|
||||
}
|
||||
|
||||
public async Task Uninstall()
|
||||
|
||||
@ -66,7 +66,7 @@ namespace Artemis.UI.Screens.Plugins
|
||||
public bool Enabling
|
||||
{
|
||||
get => _enabling;
|
||||
set => this.RaiseAndSetIfChanged(ref _enabling, value);
|
||||
set => RaiseAndSetIfChanged(ref _enabling, value);
|
||||
}
|
||||
|
||||
public bool IsEnabled
|
||||
|
||||
@ -50,7 +50,7 @@ namespace Artemis.UI.Screens.Plugins
|
||||
public PluginPrerequisiteActionViewModel? ActiveAction
|
||||
{
|
||||
get => _activeAction;
|
||||
set => this.RaiseAndSetIfChanged(ref _activeAction, value);
|
||||
set => RaiseAndSetIfChanged(ref _activeAction, value);
|
||||
}
|
||||
|
||||
public PluginPrerequisite PluginPrerequisite { get; }
|
||||
@ -58,19 +58,19 @@ namespace Artemis.UI.Screens.Plugins
|
||||
public bool Installing
|
||||
{
|
||||
get => _installing;
|
||||
set => this.RaiseAndSetIfChanged(ref _installing, value);
|
||||
set => RaiseAndSetIfChanged(ref _installing, value);
|
||||
}
|
||||
|
||||
public bool Uninstalling
|
||||
{
|
||||
get => _uninstalling;
|
||||
set => this.RaiseAndSetIfChanged(ref _uninstalling, value);
|
||||
set => RaiseAndSetIfChanged(ref _uninstalling, value);
|
||||
}
|
||||
|
||||
public bool IsMet
|
||||
{
|
||||
get => _isMet;
|
||||
set => this.RaiseAndSetIfChanged(ref _isMet, value);
|
||||
set => RaiseAndSetIfChanged(ref _isMet, value);
|
||||
}
|
||||
|
||||
public bool Busy => _busy.Value;
|
||||
|
||||
@ -78,13 +78,13 @@ namespace Artemis.UI.Screens.Plugins
|
||||
public Plugin Plugin
|
||||
{
|
||||
get => _plugin;
|
||||
set => this.RaiseAndSetIfChanged(ref _plugin, value);
|
||||
set => RaiseAndSetIfChanged(ref _plugin, value);
|
||||
}
|
||||
|
||||
public bool Enabling
|
||||
{
|
||||
get => _enabling;
|
||||
set => this.RaiseAndSetIfChanged(ref _enabling, value);
|
||||
set => RaiseAndSetIfChanged(ref _enabling, value);
|
||||
}
|
||||
|
||||
public string Type => Plugin.GetType().BaseType?.Name ?? Plugin.GetType().Name;
|
||||
@ -100,7 +100,7 @@ namespace Artemis.UI.Screens.Plugins
|
||||
get => _isSettingsPopupOpen;
|
||||
set
|
||||
{
|
||||
if (!this.RaiseAndSetIfChanged(ref _isSettingsPopupOpen, value)) return;
|
||||
if (!RaiseAndSetIfChanged(ref _isSettingsPopupOpen, value)) return;
|
||||
CheckPrerequisites();
|
||||
}
|
||||
}
|
||||
@ -108,13 +108,13 @@ namespace Artemis.UI.Screens.Plugins
|
||||
public bool CanInstallPrerequisites
|
||||
{
|
||||
get => _canInstallPrerequisites;
|
||||
set => this.RaiseAndSetIfChanged(ref _canInstallPrerequisites, value);
|
||||
set => RaiseAndSetIfChanged(ref _canInstallPrerequisites, value);
|
||||
}
|
||||
|
||||
public bool CanRemovePrerequisites
|
||||
{
|
||||
get => _canRemovePrerequisites;
|
||||
set => this.RaiseAndSetIfChanged(ref _canRemovePrerequisites, value);
|
||||
set => RaiseAndSetIfChanged(ref _canRemovePrerequisites, value);
|
||||
}
|
||||
|
||||
private void ExecuteOpenSettings()
|
||||
|
||||
@ -18,6 +18,6 @@ public class MenuBarViewModel : ActivatableViewModelBase
|
||||
public ProfileEditorHistory? History
|
||||
{
|
||||
get => _history;
|
||||
set => this.RaiseAndSetIfChanged(ref _history, value);
|
||||
set => RaiseAndSetIfChanged(ref _history, value);
|
||||
}
|
||||
}
|
||||
@ -50,19 +50,19 @@ public class PlaybackViewModel : ActivatableViewModelBase
|
||||
public bool Repeating
|
||||
{
|
||||
get => _repeating;
|
||||
set => this.RaiseAndSetIfChanged(ref _repeating, value);
|
||||
set => RaiseAndSetIfChanged(ref _repeating, value);
|
||||
}
|
||||
|
||||
public bool RepeatTimeline
|
||||
{
|
||||
get => _repeatTimeline;
|
||||
set => this.RaiseAndSetIfChanged(ref _repeatTimeline, value);
|
||||
set => RaiseAndSetIfChanged(ref _repeatTimeline, value);
|
||||
}
|
||||
|
||||
public bool RepeatSegment
|
||||
{
|
||||
get => _repeatSegment;
|
||||
set => this.RaiseAndSetIfChanged(ref _repeatSegment, value);
|
||||
set => RaiseAndSetIfChanged(ref _repeatSegment, value);
|
||||
}
|
||||
|
||||
public void PlayFromStart()
|
||||
|
||||
@ -48,7 +48,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
||||
public TreeItemViewModel? SelectedChild
|
||||
{
|
||||
get => _selectedChild;
|
||||
set => this.RaiseAndSetIfChanged(ref _selectedChild, value);
|
||||
set => RaiseAndSetIfChanged(ref _selectedChild, value);
|
||||
}
|
||||
|
||||
private void SelectCurrentProfileElement(RenderProfileElement? element)
|
||||
|
||||
@ -89,19 +89,19 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
||||
public ProfileElement? ProfileElement
|
||||
{
|
||||
get => _profileElement;
|
||||
set => this.RaiseAndSetIfChanged(ref _profileElement, value);
|
||||
set => RaiseAndSetIfChanged(ref _profileElement, value);
|
||||
}
|
||||
|
||||
public bool IsExpanded
|
||||
{
|
||||
get => _isExpanded;
|
||||
set => this.RaiseAndSetIfChanged(ref _isExpanded, value);
|
||||
set => RaiseAndSetIfChanged(ref _isExpanded, value);
|
||||
}
|
||||
|
||||
public bool Renaming
|
||||
{
|
||||
get => _renaming;
|
||||
set => this.RaiseAndSetIfChanged(ref _renaming, value);
|
||||
set => RaiseAndSetIfChanged(ref _renaming, value);
|
||||
}
|
||||
|
||||
public TreeItemViewModel? Parent { get; set; }
|
||||
@ -118,7 +118,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
||||
public string? RenameValue
|
||||
{
|
||||
get => _renameValue;
|
||||
set => this.RaiseAndSetIfChanged(ref _renameValue, value);
|
||||
set => RaiseAndSetIfChanged(ref _renameValue, value);
|
||||
}
|
||||
|
||||
public async Task ShowBrokenStateExceptions()
|
||||
|
||||
@ -64,19 +64,19 @@ public class PropertyGroupViewModel : ViewModelBase
|
||||
public bool IsVisible
|
||||
{
|
||||
get => _isVisible;
|
||||
set => this.RaiseAndSetIfChanged(ref _isVisible, value);
|
||||
set => RaiseAndSetIfChanged(ref _isVisible, value);
|
||||
}
|
||||
|
||||
public bool IsExpanded
|
||||
{
|
||||
get => _isExpanded;
|
||||
set => this.RaiseAndSetIfChanged(ref _isExpanded, value);
|
||||
set => RaiseAndSetIfChanged(ref _isExpanded, value);
|
||||
}
|
||||
|
||||
public bool HasChildren
|
||||
{
|
||||
get => _hasChildren;
|
||||
set => this.RaiseAndSetIfChanged(ref _hasChildren, value);
|
||||
set => RaiseAndSetIfChanged(ref _hasChildren, value);
|
||||
}
|
||||
|
||||
public List<ITimelineKeyframeViewModel> GetAllKeyframeViewModels(bool expandedOnly)
|
||||
|
||||
@ -30,18 +30,18 @@ public class PropertyViewModel : ViewModelBase
|
||||
public bool IsVisible
|
||||
{
|
||||
get => _isVisible;
|
||||
set => this.RaiseAndSetIfChanged(ref _isVisible, value);
|
||||
set => RaiseAndSetIfChanged(ref _isVisible, value);
|
||||
}
|
||||
|
||||
public bool IsHighlighted
|
||||
{
|
||||
get => _isHighlighted;
|
||||
set => this.RaiseAndSetIfChanged(ref _isHighlighted, value);
|
||||
set => RaiseAndSetIfChanged(ref _isHighlighted, value);
|
||||
}
|
||||
|
||||
public bool IsExpanded
|
||||
{
|
||||
get => _isExpanded;
|
||||
set => this.RaiseAndSetIfChanged(ref _isExpanded, value);
|
||||
set => RaiseAndSetIfChanged(ref _isExpanded, value);
|
||||
}
|
||||
}
|
||||
@ -47,13 +47,13 @@ public class TimelineKeyframeViewModel<T> : ActivatableViewModelBase, ITimelineK
|
||||
public double X
|
||||
{
|
||||
get => _x;
|
||||
set => this.RaiseAndSetIfChanged(ref _x, value);
|
||||
set => RaiseAndSetIfChanged(ref _x, value);
|
||||
}
|
||||
|
||||
public string Timestamp
|
||||
{
|
||||
get => _timestamp;
|
||||
set => this.RaiseAndSetIfChanged(ref _timestamp, value);
|
||||
set => RaiseAndSetIfChanged(ref _timestamp, value);
|
||||
}
|
||||
|
||||
public bool IsSelected => _isSelected?.Value ?? false;
|
||||
|
||||
@ -36,7 +36,7 @@ public class TimelineGroupViewModel : ActivatableViewModelBase
|
||||
public ObservableCollection<double>? KeyframePositions
|
||||
{
|
||||
get => _keyframePositions;
|
||||
set => this.RaiseAndSetIfChanged(ref _keyframePositions, value);
|
||||
set => RaiseAndSetIfChanged(ref _keyframePositions, value);
|
||||
}
|
||||
|
||||
private void UpdateKeyframePositions()
|
||||
|
||||
@ -52,12 +52,12 @@ public class StatusBarViewModel : ActivatableViewModelBase
|
||||
public string? StatusMessage
|
||||
{
|
||||
get => _statusMessage;
|
||||
set => this.RaiseAndSetIfChanged(ref _statusMessage, value);
|
||||
set => RaiseAndSetIfChanged(ref _statusMessage, value);
|
||||
}
|
||||
|
||||
public bool ShowStatusMessage
|
||||
{
|
||||
get => _showStatusMessage;
|
||||
set => this.RaiseAndSetIfChanged(ref _showStatusMessage, value);
|
||||
set => RaiseAndSetIfChanged(ref _showStatusMessage, value);
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,160 @@
|
||||
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:tools="clr-namespace:Artemis.UI.Screens.ProfileEditor.VisualEditor.Tools"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.VisualEditor.Tools.TransformToolView">
|
||||
Welcome to Avalonia!
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.VisualEditor.Tools.TransformToolView"
|
||||
x:DataType="tools:TransformToolViewModel">
|
||||
<UserControl.Styles>
|
||||
<Style Selector="Ellipse.rotation-handle">
|
||||
<Setter Property="Margin" Value="-15"></Setter>
|
||||
<Setter Property="Width" Value="30"></Setter>
|
||||
<Setter Property="Height" Value="30"></Setter>
|
||||
<Setter Property="Fill" Value="Green"></Setter>
|
||||
<Setter Property="Cursor" Value="Hand"></Setter>
|
||||
</Style>
|
||||
|
||||
<Style Selector="Ellipse.anchor-handle">
|
||||
<Setter Property="Margin" Value="-15"></Setter>
|
||||
<Setter Property="Width" Value="30"></Setter>
|
||||
<Setter Property="Height" Value="30"></Setter>
|
||||
<Setter Property="Fill" Value="Red"></Setter>
|
||||
<Setter Property="Cursor" Value="SizeAll"></Setter>
|
||||
</Style>
|
||||
|
||||
<Style Selector="Rectangle.resize-handle">
|
||||
<Setter Property="Margin" Value="-6"></Setter>
|
||||
<Setter Property="Width" Value="12"></Setter>
|
||||
<Setter Property="Height" Value="12"></Setter>
|
||||
<Setter Property="Fill" Value="Blue"></Setter>
|
||||
<Setter Property="Cursor" Value="Hand"></Setter>
|
||||
<Setter Property="RenderTransform">
|
||||
<Setter.Value>
|
||||
<RotateTransform Angle="{CompiledBinding InverseRotation}"></RotateTransform>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</UserControl.Styles>
|
||||
|
||||
<Canvas ClipToBounds="False" UseLayoutRounding="False">
|
||||
<Border Name="TransformationContainer"
|
||||
Width="{CompiledBinding ShapeBounds.Width}"
|
||||
Height="{CompiledBinding ShapeBounds.Height}"
|
||||
ClipToBounds="False"
|
||||
Canvas.Left="{CompiledBinding ShapeBounds.Left}"
|
||||
Canvas.Top="{CompiledBinding ShapeBounds.Top}"
|
||||
RenderTransformOrigin="{CompiledBinding RelativeAnchor}">
|
||||
<Border.RenderTransform>
|
||||
<RotateTransform Angle="{CompiledBinding Rotation}"></RotateTransform>
|
||||
</Border.RenderTransform>
|
||||
<Grid>
|
||||
<!-- Render these first so that they are always behind the actual shape -->
|
||||
<Ellipse Name="RotateTopLeft"
|
||||
VerticalAlignment="Top"
|
||||
HorizontalAlignment="Left"
|
||||
Classes="rotation-handle"
|
||||
PointerPressed="RotationOnPointerPressed"
|
||||
PointerReleased="RotationOnPointerReleased"
|
||||
PointerMoved="RotationOnPointerMoved" />
|
||||
<Ellipse Name="RotateTopRight"
|
||||
VerticalAlignment="Top"
|
||||
HorizontalAlignment="Right"
|
||||
Classes="rotation-handle"
|
||||
PointerPressed="RotationOnPointerPressed"
|
||||
PointerReleased="RotationOnPointerReleased"
|
||||
PointerMoved="RotationOnPointerMoved" />
|
||||
<Ellipse Name="RotateBottomRight"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Right"
|
||||
Classes="rotation-handle"
|
||||
PointerPressed="RotationOnPointerPressed"
|
||||
PointerReleased="RotationOnPointerReleased"
|
||||
PointerMoved="RotationOnPointerMoved" />
|
||||
<Ellipse Name="RotateBottomLeft"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left"
|
||||
Classes="rotation-handle"
|
||||
PointerPressed="RotationOnPointerPressed"
|
||||
PointerReleased="RotationOnPointerReleased"
|
||||
PointerMoved="RotationOnPointerMoved" />
|
||||
|
||||
<!-- Mutation points -->
|
||||
<Rectangle Name="ResizeTopCenter"
|
||||
VerticalAlignment="Top"
|
||||
HorizontalAlignment="Center"
|
||||
Classes="resize-handle"
|
||||
PointerPressed="ResizeOnPointerPressed"
|
||||
PointerReleased="ResizeOnPointerReleased"
|
||||
PointerMoved="ResizeOnPointerMoved">
|
||||
</Rectangle>
|
||||
<Rectangle Name="ResizeRightCenter"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right"
|
||||
Classes="resize-handle"
|
||||
PointerPressed="ResizeOnPointerPressed"
|
||||
PointerReleased="ResizeOnPointerReleased"
|
||||
PointerMoved="ResizeOnPointerMoved">
|
||||
</Rectangle>
|
||||
<Rectangle Name="ResizeBottomCenter"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Center"
|
||||
Classes="resize-handle"
|
||||
PointerPressed="ResizeOnPointerPressed"
|
||||
PointerReleased="ResizeOnPointerReleased"
|
||||
PointerMoved="ResizeOnPointerMoved">
|
||||
</Rectangle>
|
||||
<Rectangle Name="ResizeLeftCenter"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Left"
|
||||
Classes="resize-handle"
|
||||
PointerPressed="ResizeOnPointerPressed"
|
||||
PointerReleased="ResizeOnPointerReleased"
|
||||
PointerMoved="ResizeOnPointerMoved">
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle Name="ResizeTopLeft"
|
||||
Classes="resize-handle"
|
||||
VerticalAlignment="Top"
|
||||
HorizontalAlignment="Left"
|
||||
PointerPressed="ResizeOnPointerPressed"
|
||||
PointerReleased="ResizeOnPointerReleased"
|
||||
PointerMoved="ResizeOnPointerMoved">
|
||||
</Rectangle>
|
||||
<Rectangle Name="ResizeTopRight"
|
||||
VerticalAlignment="Top"
|
||||
HorizontalAlignment="Right"
|
||||
Classes="resize-handle"
|
||||
PointerPressed="ResizeOnPointerPressed"
|
||||
PointerReleased="ResizeOnPointerReleased"
|
||||
PointerMoved="ResizeOnPointerMoved">
|
||||
</Rectangle>
|
||||
<Rectangle Name="ResizeBottomRight"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Right"
|
||||
Classes="resize-handle"
|
||||
PointerPressed="ResizeOnPointerPressed"
|
||||
PointerReleased="ResizeOnPointerReleased"
|
||||
PointerMoved="ResizeOnPointerMoved">
|
||||
</Rectangle>
|
||||
<Rectangle Name="ResizeBottomLeft"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Left"
|
||||
Classes="resize-handle"
|
||||
PointerPressed="ResizeOnPointerPressed"
|
||||
PointerReleased="ResizeOnPointerReleased"
|
||||
PointerMoved="ResizeOnPointerMoved">
|
||||
</Rectangle>
|
||||
|
||||
<Canvas>
|
||||
<Ellipse Name="AnchorPoint"
|
||||
Canvas.Left="{CompiledBinding Anchor.X}"
|
||||
Canvas.Top="{CompiledBinding Anchor.Y}"
|
||||
Classes="anchor-handle"
|
||||
PointerPressed="MoveOnPointerPressed"
|
||||
PointerReleased="MoveOnPointerReleased"
|
||||
PointerMoved="MoveOnPointerMoved" />
|
||||
</Canvas>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Canvas>
|
||||
</UserControl>
|
||||
@ -1,10 +1,20 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.PanAndZoom;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.VisualEditor.Tools;
|
||||
|
||||
public class TransformToolView : ReactiveUserControl<TransformToolViewModel>
|
||||
{
|
||||
private ZoomBorder? _zoomBorder;
|
||||
private PointerPoint _dragOffset;
|
||||
|
||||
public TransformToolView()
|
||||
{
|
||||
InitializeComponent();
|
||||
@ -14,4 +24,138 @@ public class TransformToolView : ReactiveUserControl<TransformToolViewModel>
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
#region Zoom
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
|
||||
{
|
||||
_zoomBorder = (ZoomBorder?)this.GetLogicalAncestors().FirstOrDefault(l => l is ZoomBorder);
|
||||
if (_zoomBorder != null)
|
||||
_zoomBorder.PropertyChanged += ZoomBorderOnPropertyChanged;
|
||||
base.OnAttachedToLogicalTree(e);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
|
||||
{
|
||||
if (_zoomBorder != null)
|
||||
_zoomBorder.PropertyChanged -= ZoomBorderOnPropertyChanged;
|
||||
base.OnDetachedFromLogicalTree(e);
|
||||
}
|
||||
|
||||
private void ZoomBorderOnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.Property != ZoomBorder.ZoomXProperty || _zoomBorder == null)
|
||||
return;
|
||||
|
||||
// TODO
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rotation
|
||||
|
||||
private void RotationOnPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
IInputElement? element = (IInputElement?)sender;
|
||||
if (element == null || !e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
||||
return;
|
||||
|
||||
_dragOffset = e.GetCurrentPoint(_zoomBorder);
|
||||
|
||||
e.Pointer.Capture(element);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void RotationOnPointerReleased(object? sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
IInputElement? element = (IInputElement?)sender;
|
||||
if (element == null || e.Pointer.Captured != element || !e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
||||
return;
|
||||
|
||||
e.Pointer.Capture(null);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void RotationOnPointerMoved(object? sender, PointerEventArgs e)
|
||||
{
|
||||
IInputElement? element = (IInputElement?) sender;
|
||||
if (element == null || e.Pointer.Captured != element || !e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
||||
return;
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Movement
|
||||
|
||||
private void MoveOnPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
IInputElement? element = (IInputElement?)sender;
|
||||
if (element == null || !e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
||||
return;
|
||||
|
||||
_dragOffset = e.GetCurrentPoint(_zoomBorder);
|
||||
|
||||
e.Pointer.Capture(element);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void MoveOnPointerReleased(object? sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
IInputElement? element = (IInputElement?)sender;
|
||||
if (element == null || e.Pointer.Captured != element || !e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
||||
return;
|
||||
|
||||
e.Pointer.Capture(null);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void MoveOnPointerMoved(object? sender, PointerEventArgs e)
|
||||
{
|
||||
IInputElement? element = (IInputElement?)sender;
|
||||
if (element == null || e.Pointer.Captured != element || !e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
||||
return;
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Resizing
|
||||
|
||||
private void ResizeOnPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
IInputElement? element = (IInputElement?)sender;
|
||||
if (element == null || !e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
||||
return;
|
||||
|
||||
_dragOffset = e.GetCurrentPoint(_zoomBorder);
|
||||
|
||||
e.Pointer.Capture(element);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void ResizeOnPointerReleased(object? sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
IInputElement? element = (IInputElement?)sender;
|
||||
if (element == null || e.Pointer.Captured != element || !e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
||||
return;
|
||||
|
||||
e.Pointer.Capture(null);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void ResizeOnPointerMoved(object? sender, PointerEventArgs e)
|
||||
{
|
||||
IInputElement? element = (IInputElement?)sender;
|
||||
if (element == null || e.Pointer.Captured != element || !e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
||||
return;
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -1,21 +1,80 @@
|
||||
using System.Reactive.Linq;
|
||||
using System;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Shared.Extensions;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.Mixins;
|
||||
using Material.Icons;
|
||||
using ReactiveUI;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.VisualEditor.Tools;
|
||||
|
||||
public class TransformToolViewModel : ToolViewModel
|
||||
{
|
||||
private readonly ObservableAsPropertyHelper<bool>? _isEnabled;
|
||||
private readonly ObservableAsPropertyHelper<bool> _isEnabled;
|
||||
private RelativePoint _relativeAnchor;
|
||||
private double _inverseRotation;
|
||||
private ObservableAsPropertyHelper<Layer?>? _layer;
|
||||
private double _rotation;
|
||||
private Rect _shapeBounds;
|
||||
private Point _anchor;
|
||||
|
||||
/// <inheritdoc />
|
||||
public TransformToolViewModel(IProfileEditorService profileEditorService)
|
||||
{
|
||||
// Not disposed when deactivated but when really disposed
|
||||
_isEnabled = profileEditorService.ProfileElement.Select(p => p is Layer).ToProperty(this, vm => vm.IsEnabled);
|
||||
|
||||
this.WhenActivated(d =>
|
||||
{
|
||||
_layer = profileEditorService.ProfileElement.Select(p => p as Layer).ToProperty(this, vm => vm.Layer).DisposeWith(d);
|
||||
|
||||
this.WhenAnyValue(vm => vm.Layer)
|
||||
.Select(l => l != null
|
||||
? Observable.FromEventPattern(x => l.RenderPropertiesUpdated += x, x => l.RenderPropertiesUpdated -= x)
|
||||
: Observable.Never<EventPattern<object>>())
|
||||
.Switch()
|
||||
.Subscribe(_ => Update())
|
||||
.DisposeWith(d);
|
||||
this.WhenAnyValue(vm => vm.Layer)
|
||||
.Select(l => l != null
|
||||
? Observable.FromEventPattern<LayerPropertyEventArgs>(x => l.Transform.Position.CurrentValueSet += x, x => l.Transform.Position.CurrentValueSet -= x)
|
||||
: Observable.Never<EventPattern<LayerPropertyEventArgs>>())
|
||||
.Switch()
|
||||
.Subscribe(_ => Update())
|
||||
.DisposeWith(d);
|
||||
this.WhenAnyValue(vm => vm.Layer)
|
||||
.Select(l => l != null
|
||||
? Observable.FromEventPattern<LayerPropertyEventArgs>(x => l.Transform.Rotation.CurrentValueSet += x, x => l.Transform.Rotation.CurrentValueSet -= x)
|
||||
: Observable.Never<EventPattern<LayerPropertyEventArgs>>())
|
||||
.Switch()
|
||||
.Subscribe(_ => Update())
|
||||
.DisposeWith(d);
|
||||
this.WhenAnyValue(vm => vm.Layer)
|
||||
.Select(l => l != null
|
||||
? Observable.FromEventPattern<LayerPropertyEventArgs>(x => l.Transform.Scale.CurrentValueSet += x, x => l.Transform.Scale.CurrentValueSet -= x)
|
||||
: Observable.Never<EventPattern<LayerPropertyEventArgs>>())
|
||||
.Switch()
|
||||
.Subscribe(_ => Update())
|
||||
.DisposeWith(d);
|
||||
this.WhenAnyValue(vm => vm.Layer)
|
||||
.Select(l => l != null
|
||||
? Observable.FromEventPattern<LayerPropertyEventArgs>(x => l.Transform.AnchorPoint.CurrentValueSet += x, x => l.Transform.AnchorPoint.CurrentValueSet -= x)
|
||||
: Observable.Never<EventPattern<LayerPropertyEventArgs>>())
|
||||
.Switch()
|
||||
.Subscribe(_ => Update())
|
||||
.DisposeWith(d);
|
||||
|
||||
this.WhenAnyValue(vm => vm.Layer).Subscribe(_ => Update()).DisposeWith(d);
|
||||
profileEditorService.Time.Subscribe(_ => Update()).DisposeWith(d);
|
||||
});
|
||||
}
|
||||
|
||||
public Layer? Layer => _layer?.Value;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsEnabled => _isEnabled?.Value ?? false;
|
||||
|
||||
@ -34,6 +93,36 @@ public class TransformToolViewModel : ToolViewModel
|
||||
/// <inheritdoc />
|
||||
public override string ToolTip => "Transform the shape of the current layer";
|
||||
|
||||
public Rect ShapeBounds
|
||||
{
|
||||
get => _shapeBounds;
|
||||
set => RaiseAndSetIfChanged(ref _shapeBounds, value);
|
||||
}
|
||||
|
||||
public double Rotation
|
||||
{
|
||||
get => _rotation;
|
||||
set => RaiseAndSetIfChanged(ref _rotation, value);
|
||||
}
|
||||
|
||||
public double InverseRotation
|
||||
{
|
||||
get => _inverseRotation;
|
||||
set => RaiseAndSetIfChanged(ref _inverseRotation, value);
|
||||
}
|
||||
|
||||
public RelativePoint RelativeAnchor
|
||||
{
|
||||
get => _relativeAnchor;
|
||||
set => RaiseAndSetIfChanged(ref _relativeAnchor, value);
|
||||
}
|
||||
|
||||
public Point Anchor
|
||||
{
|
||||
get => _anchor;
|
||||
set => RaiseAndSetIfChanged(ref _anchor, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
@ -42,4 +131,37 @@ public class TransformToolViewModel : ToolViewModel
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Layer == null)
|
||||
return;
|
||||
|
||||
SKPath path = new();
|
||||
path.AddRect(Layer.GetLayerBounds());
|
||||
path.Transform(Layer.GetTransformMatrix(false, true, true, false));
|
||||
|
||||
ShapeBounds = path.Bounds.ToRect();
|
||||
Rotation = Layer.Transform.Rotation.CurrentValue;
|
||||
InverseRotation = Rotation * -1;
|
||||
|
||||
// The middle of the element is 0.5/0.5 in Avalonia, in Artemis it's 0.0/0.0 so compensate for that below
|
||||
SKPoint layerAnchor = Layer.Transform.AnchorPoint.CurrentValue;
|
||||
RelativeAnchor = new RelativePoint(layerAnchor.X + 0.5, layerAnchor.Y + 0.5, RelativeUnit.Relative);
|
||||
Anchor = new Point(ShapeBounds.Width * RelativeAnchor.Point.X, ShapeBounds.Height * RelativeAnchor.Point.Y);
|
||||
}
|
||||
|
||||
public enum ShapeControlPoint
|
||||
{
|
||||
TopLeft,
|
||||
TopRight,
|
||||
BottomRight,
|
||||
BottomLeft,
|
||||
TopCenter,
|
||||
RightCenter,
|
||||
BottomCenter,
|
||||
LeftCenter,
|
||||
LayerShape,
|
||||
Anchor
|
||||
}
|
||||
}
|
||||
@ -51,7 +51,7 @@ public class VisualEditorViewModel : ActivatableViewModelBase
|
||||
public ReadOnlyObservableCollection<IToolViewModel> Tools
|
||||
{
|
||||
get => _tools;
|
||||
set => this.RaiseAndSetIfChanged(ref _tools, value);
|
||||
set => RaiseAndSetIfChanged(ref _tools, value);
|
||||
}
|
||||
|
||||
private void CreateVisualizers(ProfileConfiguration? profileConfiguration)
|
||||
|
||||
@ -54,25 +54,25 @@ public class LayerShapeVisualizerViewModel : ActivatableViewModelBase, IVisualiz
|
||||
public Rect LayerBounds
|
||||
{
|
||||
get => _layerBounds;
|
||||
private set => this.RaiseAndSetIfChanged(ref _layerBounds, value);
|
||||
private set => RaiseAndSetIfChanged(ref _layerBounds, value);
|
||||
}
|
||||
|
||||
public double X
|
||||
{
|
||||
get => _x;
|
||||
set => this.RaiseAndSetIfChanged(ref _x, value);
|
||||
set => RaiseAndSetIfChanged(ref _x, value);
|
||||
}
|
||||
|
||||
public double Y
|
||||
{
|
||||
get => _y;
|
||||
set => this.RaiseAndSetIfChanged(ref _y, value);
|
||||
set => RaiseAndSetIfChanged(ref _y, value);
|
||||
}
|
||||
|
||||
public Geometry? ShapeGeometry
|
||||
{
|
||||
get => _shapeGeometry;
|
||||
set => this.RaiseAndSetIfChanged(ref _shapeGeometry, value);
|
||||
set => RaiseAndSetIfChanged(ref _shapeGeometry, value);
|
||||
}
|
||||
|
||||
public int Order => 2;
|
||||
|
||||
@ -40,19 +40,19 @@ public class LayerVisualizerViewModel : ActivatableViewModelBase, IVisualizerVie
|
||||
public Rect LayerBounds
|
||||
{
|
||||
get => _layerBounds;
|
||||
private set => this.RaiseAndSetIfChanged(ref _layerBounds, value);
|
||||
private set => RaiseAndSetIfChanged(ref _layerBounds, value);
|
||||
}
|
||||
|
||||
public double X
|
||||
{
|
||||
get => _x;
|
||||
set => this.RaiseAndSetIfChanged(ref _x, value);
|
||||
set => RaiseAndSetIfChanged(ref _x, value);
|
||||
}
|
||||
|
||||
public double Y
|
||||
{
|
||||
get => _y;
|
||||
set => this.RaiseAndSetIfChanged(ref _y, value);
|
||||
set => RaiseAndSetIfChanged(ref _y, value);
|
||||
}
|
||||
|
||||
public int Order => 1;
|
||||
|
||||
@ -70,7 +70,7 @@ namespace Artemis.UI.Screens.ProfileEditor
|
||||
public ReadOnlyObservableCollection<IToolViewModel> Tools
|
||||
{
|
||||
get => _tools;
|
||||
set => this.RaiseAndSetIfChanged(ref _tools, value);
|
||||
set => RaiseAndSetIfChanged(ref _tools, value);
|
||||
}
|
||||
|
||||
public ProfileConfiguration? ProfileConfiguration => _profileConfiguration?.Value;
|
||||
|
||||
@ -77,13 +77,13 @@ namespace Artemis.UI.Screens.Root
|
||||
public SidebarViewModel? SidebarViewModel
|
||||
{
|
||||
get => _sidebarViewModel;
|
||||
set => this.RaiseAndSetIfChanged(ref _sidebarViewModel, value);
|
||||
set => RaiseAndSetIfChanged(ref _sidebarViewModel, value);
|
||||
}
|
||||
|
||||
public ViewModelBase? TitleBarViewModel
|
||||
{
|
||||
get => _titleBarViewModel;
|
||||
set => this.RaiseAndSetIfChanged(ref _titleBarViewModel, value);
|
||||
set => RaiseAndSetIfChanged(ref _titleBarViewModel, value);
|
||||
}
|
||||
|
||||
private void CurrentMainWindowOnClosed(object? sender, EventArgs e)
|
||||
|
||||
@ -30,7 +30,7 @@ namespace Artemis.UI.Screens.Root
|
||||
public string Status
|
||||
{
|
||||
get => _status;
|
||||
set => this.RaiseAndSetIfChanged(ref _status, value);
|
||||
set => RaiseAndSetIfChanged(ref _status, value);
|
||||
}
|
||||
|
||||
private void OnPluginManagementServiceOnPluginManagementLoaded(object? sender, PluginEventArgs args)
|
||||
|
||||
@ -27,31 +27,31 @@ namespace Artemis.UI.Screens.Settings
|
||||
public string? Version
|
||||
{
|
||||
get => _version;
|
||||
set => this.RaiseAndSetIfChanged(ref _version, value);
|
||||
set => RaiseAndSetIfChanged(ref _version, value);
|
||||
}
|
||||
|
||||
public Bitmap? RobertProfileImage
|
||||
{
|
||||
get => _robertProfileImage;
|
||||
set => this.RaiseAndSetIfChanged(ref _robertProfileImage, value);
|
||||
set => RaiseAndSetIfChanged(ref _robertProfileImage, value);
|
||||
}
|
||||
|
||||
public Bitmap? DarthAffeProfileImage
|
||||
{
|
||||
get => _darthAffeProfileImage;
|
||||
set => this.RaiseAndSetIfChanged(ref _darthAffeProfileImage, value);
|
||||
set => RaiseAndSetIfChanged(ref _darthAffeProfileImage, value);
|
||||
}
|
||||
|
||||
public Bitmap? DrMeteorProfileImage
|
||||
{
|
||||
get => _drMeteorProfileImage;
|
||||
set => this.RaiseAndSetIfChanged(ref _drMeteorProfileImage, value);
|
||||
set => RaiseAndSetIfChanged(ref _drMeteorProfileImage, value);
|
||||
}
|
||||
|
||||
public Bitmap? KaiProfileImage
|
||||
{
|
||||
get => _kaiProfileImage;
|
||||
set => this.RaiseAndSetIfChanged(ref _kaiProfileImage, value);
|
||||
set => RaiseAndSetIfChanged(ref _kaiProfileImage, value);
|
||||
}
|
||||
|
||||
private async Task Activate()
|
||||
|
||||
@ -46,7 +46,7 @@ namespace Artemis.UI.Screens.Settings
|
||||
public string? SearchPluginInput
|
||||
{
|
||||
get => _searchPluginInput;
|
||||
set => this.RaiseAndSetIfChanged(ref _searchPluginInput, value);
|
||||
set => RaiseAndSetIfChanged(ref _searchPluginInput, value);
|
||||
}
|
||||
|
||||
public void OpenUrl(string url)
|
||||
|
||||
@ -64,31 +64,31 @@ namespace Artemis.UI.Screens.Sidebar
|
||||
public ProfileConfiguration ProfileConfiguration
|
||||
{
|
||||
get => _profileConfiguration;
|
||||
set => this.RaiseAndSetIfChanged(ref _profileConfiguration, value);
|
||||
set => RaiseAndSetIfChanged(ref _profileConfiguration, value);
|
||||
}
|
||||
|
||||
public string ProfileName
|
||||
{
|
||||
get => _profileName;
|
||||
set => this.RaiseAndSetIfChanged(ref _profileName, value);
|
||||
set => RaiseAndSetIfChanged(ref _profileName, value);
|
||||
}
|
||||
|
||||
public ProfileConfigurationHotkeyMode HotkeyMode
|
||||
{
|
||||
get => _hotkeyMode;
|
||||
set => this.RaiseAndSetIfChanged(ref _hotkeyMode, value);
|
||||
set => RaiseAndSetIfChanged(ref _hotkeyMode, value);
|
||||
}
|
||||
|
||||
public Hotkey? EnableHotkey
|
||||
{
|
||||
get => _enableHotkey;
|
||||
set => this.RaiseAndSetIfChanged(ref _enableHotkey, value);
|
||||
set => RaiseAndSetIfChanged(ref _enableHotkey, value);
|
||||
}
|
||||
|
||||
public Hotkey? DisableHotkey
|
||||
{
|
||||
get => _disableHotkey;
|
||||
set => this.RaiseAndSetIfChanged(ref _disableHotkey, value);
|
||||
set => RaiseAndSetIfChanged(ref _disableHotkey, value);
|
||||
}
|
||||
|
||||
public ObservableCollection<ProfileModuleViewModel> Modules { get; }
|
||||
@ -96,7 +96,7 @@ namespace Artemis.UI.Screens.Sidebar
|
||||
public ProfileModuleViewModel? SelectedModule
|
||||
{
|
||||
get => _selectedModule;
|
||||
set => this.RaiseAndSetIfChanged(ref _selectedModule, value);
|
||||
set => RaiseAndSetIfChanged(ref _selectedModule, value);
|
||||
}
|
||||
|
||||
public async Task Import()
|
||||
@ -183,31 +183,31 @@ namespace Artemis.UI.Screens.Sidebar
|
||||
public ProfileConfigurationIconType IconType
|
||||
{
|
||||
get => _iconType;
|
||||
set => this.RaiseAndSetIfChanged(ref _iconType, value);
|
||||
set => RaiseAndSetIfChanged(ref _iconType, value);
|
||||
}
|
||||
|
||||
public ObservableCollection<ProfileIconViewModel>? MaterialIcons
|
||||
{
|
||||
get => _materialIcons;
|
||||
set => this.RaiseAndSetIfChanged(ref _materialIcons, value);
|
||||
set => RaiseAndSetIfChanged(ref _materialIcons, value);
|
||||
}
|
||||
|
||||
public ProfileIconViewModel? SelectedMaterialIcon
|
||||
{
|
||||
get => _selectedMaterialIcon;
|
||||
set => this.RaiseAndSetIfChanged(ref _selectedMaterialIcon, value);
|
||||
set => RaiseAndSetIfChanged(ref _selectedMaterialIcon, value);
|
||||
}
|
||||
|
||||
public Bitmap? SelectedBitmapSource
|
||||
{
|
||||
get => _selectedBitmapSource;
|
||||
set => this.RaiseAndSetIfChanged(ref _selectedBitmapSource, value);
|
||||
set => RaiseAndSetIfChanged(ref _selectedBitmapSource, value);
|
||||
}
|
||||
|
||||
public SvgImage? SelectedSvgSource
|
||||
{
|
||||
get => _selectedSvgSource;
|
||||
set => this.RaiseAndSetIfChanged(ref _selectedSvgSource, value);
|
||||
set => RaiseAndSetIfChanged(ref _selectedSvgSource, value);
|
||||
}
|
||||
|
||||
private void LoadIcon()
|
||||
|
||||
@ -53,7 +53,7 @@ namespace Artemis.UI.Screens.Sidebar
|
||||
public SidebarProfileConfigurationViewModel? SelectedProfileConfiguration
|
||||
{
|
||||
get => _selectedProfileConfiguration;
|
||||
set => this.RaiseAndSetIfChanged(ref _selectedProfileConfiguration, value);
|
||||
set => RaiseAndSetIfChanged(ref _selectedProfileConfiguration, value);
|
||||
}
|
||||
|
||||
public bool ShowItems
|
||||
|
||||
@ -89,13 +89,13 @@ namespace Artemis.UI.Screens.Sidebar
|
||||
public ArtemisDevice? HeaderDevice
|
||||
{
|
||||
get => _headerDevice;
|
||||
set => this.RaiseAndSetIfChanged(ref _headerDevice, value);
|
||||
set => RaiseAndSetIfChanged(ref _headerDevice, value);
|
||||
}
|
||||
|
||||
public SidebarScreenViewModel? SelectedSidebarScreen
|
||||
{
|
||||
get => _selectedSidebarScreen;
|
||||
set => this.RaiseAndSetIfChanged(ref _selectedSidebarScreen, value);
|
||||
set => RaiseAndSetIfChanged(ref _selectedSidebarScreen, value);
|
||||
}
|
||||
|
||||
public SidebarCategoryViewModel AddProfileCategoryViewModel(ProfileCategory profileCategory)
|
||||
|
||||
@ -20,13 +20,13 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
public bool IsSelected
|
||||
{
|
||||
get => _isSelected;
|
||||
set => this.RaiseAndSetIfChanged(ref _isSelected, value);
|
||||
set => RaiseAndSetIfChanged(ref _isSelected, value);
|
||||
}
|
||||
|
||||
public SKColor Color
|
||||
{
|
||||
get => _color;
|
||||
set => this.RaiseAndSetIfChanged(ref _color, value);
|
||||
set => RaiseAndSetIfChanged(ref _color, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -53,7 +53,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
get => _selectionStatus;
|
||||
set
|
||||
{
|
||||
this.RaiseAndSetIfChanged(ref _selectionStatus, value);
|
||||
RaiseAndSetIfChanged(ref _selectionStatus, value);
|
||||
this.RaisePropertyChanged(nameof(Highlighted));
|
||||
}
|
||||
}
|
||||
@ -65,7 +65,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
public Cursor Cursor
|
||||
{
|
||||
get => _cursor;
|
||||
set => this.RaiseAndSetIfChanged(ref _cursor, value);
|
||||
set => RaiseAndSetIfChanged(ref _cursor, value);
|
||||
}
|
||||
|
||||
public void StartMouseDrag(Point mouseStartPosition)
|
||||
|
||||
@ -6,24 +6,26 @@
|
||||
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
||||
xmlns:controls1="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:attachedProperties="clr-namespace:Artemis.UI.Shared.AttachedProperties;assembly=Artemis.UI.Shared"
|
||||
xmlns:workshop="clr-namespace:Artemis.UI.Screens.Workshop"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.Workshop.WorkshopView">
|
||||
x:Class="Artemis.UI.Screens.Workshop.WorkshopView"
|
||||
x:DataType="workshop:WorkshopViewModel">
|
||||
<Border Classes="router-container">
|
||||
<StackPanel Margin="12">
|
||||
<TextBlock>Workshop!! :3</TextBlock>
|
||||
<Border Classes="card" Margin="0 12">
|
||||
<StackPanel Spacing="5">
|
||||
<TextBlock Classes="h4">Notification tests</TextBlock>
|
||||
<Button Command="{Binding ShowNotification}" CommandParameter="{x:Static builders:NotificationSeverity.Informational}">
|
||||
<Button Command="{CompiledBinding ShowNotification}" CommandParameter="{x:Static builders:NotificationSeverity.Informational}">
|
||||
Notification test (default)
|
||||
</Button>
|
||||
<Button Command="{Binding ShowNotification}" CommandParameter="{x:Static builders:NotificationSeverity.Warning}">
|
||||
<Button Command="{CompiledBinding ShowNotification}" CommandParameter="{x:Static builders:NotificationSeverity.Warning}">
|
||||
Notification test (warning)
|
||||
</Button>
|
||||
<Button Command="{Binding ShowNotification}" CommandParameter="{x:Static builders:NotificationSeverity.Error}">
|
||||
<Button Command="{CompiledBinding ShowNotification}" CommandParameter="{x:Static builders:NotificationSeverity.Error}">
|
||||
Notification test (error)
|
||||
</Button>
|
||||
<Button Command="{Binding ShowNotification}" CommandParameter="{x:Static builders:NotificationSeverity.Success}">
|
||||
<Button Command="{CompiledBinding ShowNotification}" CommandParameter="{x:Static builders:NotificationSeverity.Success}">
|
||||
Notification test (success)
|
||||
</Button>
|
||||
|
||||
@ -36,6 +38,13 @@
|
||||
<TextBox
|
||||
attachedProperties:TextBoxAssist.PrefixText="$"
|
||||
attachedProperties:TextBoxAssist.SuffixText="%"></TextBox>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Spacing="5">
|
||||
<Border Classes="card" Cursor="{CompiledBinding Cursor}">
|
||||
<TextBlock Text="{CompiledBinding SelectedCursor}"></TextBlock>
|
||||
</Border>
|
||||
<controls:EnumComboBox Value="{CompiledBinding SelectedCursor}"></controls:EnumComboBox>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using Artemis.UI.Shared.Services.Builders;
|
||||
using Artemis.UI.Shared.Services.Interfaces;
|
||||
using Avalonia.Input;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.Workshop
|
||||
@ -8,10 +10,13 @@ namespace Artemis.UI.Screens.Workshop
|
||||
public class WorkshopViewModel : MainScreenViewModel
|
||||
{
|
||||
private readonly INotificationService _notificationService;
|
||||
private StandardCursorType _selectedCursor;
|
||||
private readonly ObservableAsPropertyHelper<Cursor> _cursor;
|
||||
|
||||
public WorkshopViewModel(IScreen hostScreen, INotificationService notificationService) : base(hostScreen, "workshop")
|
||||
{
|
||||
_notificationService = notificationService;
|
||||
_cursor = this.WhenAnyValue(vm => vm.SelectedCursor).Select(c => new Cursor(c)).ToProperty(this, vm => vm.Cursor);
|
||||
|
||||
DisplayName = "Workshop";
|
||||
ShowNotification = ReactiveCommand.Create<NotificationSeverity>(ExecuteShowNotification);
|
||||
@ -19,6 +24,14 @@ namespace Artemis.UI.Screens.Workshop
|
||||
|
||||
public ReactiveCommand<NotificationSeverity, Unit> ShowNotification { get; set; }
|
||||
|
||||
public StandardCursorType SelectedCursor
|
||||
{
|
||||
get => _selectedCursor;
|
||||
set => RaiseAndSetIfChanged(ref _selectedCursor, value);
|
||||
}
|
||||
|
||||
public Cursor Cursor => _cursor.Value;
|
||||
|
||||
private void ExecuteShowNotification(NotificationSeverity severity)
|
||||
{
|
||||
_notificationService.CreateNotification().WithTitle("Test title").WithMessage("Test message").WithSeverity(severity).Show();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user