mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Shared UI - Added XML comments
This commit is contained in:
parent
69f02d83ac
commit
32e80c3d05
@ -6,14 +6,19 @@ using Microsoft.Xaml.Behaviors;
|
||||
|
||||
namespace Artemis.UI.Shared
|
||||
{
|
||||
/// <summary>
|
||||
/// A behavior that makes a scroll viewer bubble up its events if it is at its scroll limit
|
||||
/// </summary>
|
||||
public class ScrollParentWhenAtMax : Behavior<FrameworkElement>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
AssociatedObject.PreviewMouseWheel += PreviewMouseWheel;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnDetaching()
|
||||
{
|
||||
AssociatedObject.PreviewMouseWheel -= PreviewMouseWheel;
|
||||
@ -22,10 +27,12 @@ namespace Artemis.UI.Shared
|
||||
|
||||
private void PreviewMouseWheel(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
ScrollViewer scrollViewer = GetVisualChild<ScrollViewer>(AssociatedObject);
|
||||
ScrollViewer? scrollViewer = GetVisualChild<ScrollViewer>(AssociatedObject);
|
||||
if (scrollViewer == null)
|
||||
return;
|
||||
double scrollPos = scrollViewer.ContentVerticalOffset;
|
||||
if (scrollPos == scrollViewer.ScrollableHeight && e.Delta < 0
|
||||
|| scrollPos == 0 && e.Delta > 0)
|
||||
// ReSharper disable once CompareOfFloatsByEqualityOperator
|
||||
if (scrollPos == scrollViewer.ScrollableHeight && e.Delta < 0 || scrollPos == 0 && e.Delta > 0)
|
||||
{
|
||||
e.Handled = true;
|
||||
MouseWheelEventArgs e2 = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
|
||||
@ -34,9 +41,9 @@ namespace Artemis.UI.Shared
|
||||
}
|
||||
}
|
||||
|
||||
private static T GetVisualChild<T>(DependencyObject parent) where T : Visual
|
||||
private static T? GetVisualChild<T>(DependencyObject parent) where T : Visual
|
||||
{
|
||||
T child = default;
|
||||
T? child = default;
|
||||
|
||||
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
|
||||
for (int i = 0; i < numVisuals; i++)
|
||||
|
||||
@ -38,8 +38,8 @@ namespace Artemis.UI.Shared
|
||||
private readonly DrawingGroup _backingStore;
|
||||
private readonly List<DeviceVisualizerLed> _deviceVisualizerLeds;
|
||||
private readonly DispatcherTimer _timer;
|
||||
private BitmapImage _deviceImage;
|
||||
private ArtemisDevice _oldDevice;
|
||||
private BitmapImage? _deviceImage;
|
||||
private ArtemisDevice? _oldDevice;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="DeviceVisualizer" /> class
|
||||
@ -60,7 +60,7 @@ namespace Artemis.UI.Shared
|
||||
/// <summary>
|
||||
/// Gets or sets the device to visualize
|
||||
/// </summary>
|
||||
public ArtemisDevice Device
|
||||
public ArtemisDevice? Device
|
||||
{
|
||||
get => (ArtemisDevice) GetValue(DeviceProperty);
|
||||
set => SetValue(DeviceProperty, value);
|
||||
@ -78,16 +78,32 @@ namespace Artemis.UI.Shared
|
||||
/// <summary>
|
||||
/// Gets or sets a list of LEDs to highlight
|
||||
/// </summary>
|
||||
public IEnumerable<ArtemisLed> HighlightedLeds
|
||||
public IEnumerable<ArtemisLed>? HighlightedLeds
|
||||
{
|
||||
get => (IEnumerable<ArtemisLed>) GetValue(HighlightedLedsProperty);
|
||||
set => SetValue(HighlightedLedsProperty, value);
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_timer.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
_timer.Stop();
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -174,7 +190,8 @@ namespace Artemis.UI.Shared
|
||||
|
||||
if (_oldDevice != null)
|
||||
{
|
||||
Device.RgbDevice.PropertyChanged -= DevicePropertyChanged;
|
||||
if (Device != null)
|
||||
Device.RgbDevice.PropertyChanged -= DevicePropertyChanged;
|
||||
_oldDevice = null;
|
||||
}
|
||||
}
|
||||
@ -224,7 +241,7 @@ namespace Artemis.UI.Shared
|
||||
UpdateTransform();
|
||||
|
||||
// Load the device main image
|
||||
if (Device.RgbDevice?.DeviceInfo?.Image?.AbsolutePath != null && File.Exists(Device.RgbDevice.DeviceInfo.Image.AbsolutePath))
|
||||
if (Device.RgbDevice.DeviceInfo?.Image?.AbsolutePath != null && File.Exists(Device.RgbDevice.DeviceInfo.Image.AbsolutePath))
|
||||
_deviceImage = new BitmapImage(Device.RgbDevice.DeviceInfo.Image);
|
||||
|
||||
// Create all the LEDs
|
||||
@ -266,7 +283,7 @@ namespace Artemis.UI.Shared
|
||||
InvalidateMeasure();
|
||||
}
|
||||
|
||||
private void DevicePropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
private void DevicePropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(Device.RgbDevice.Scale) || e.PropertyName == nameof(Device.RgbDevice.Rotation))
|
||||
UpdateTransform();
|
||||
|
||||
@ -5,9 +5,13 @@ using System.Windows.Data;
|
||||
|
||||
namespace Artemis.UI.Shared
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts <see langword="null"/> to <see cref="Visibility"/>
|
||||
/// </summary>
|
||||
public class NullToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
/// <inheritdoc />
|
||||
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
Parameters direction;
|
||||
if (parameter == null)
|
||||
@ -23,7 +27,8 @@ namespace Artemis.UI.Shared
|
||||
return value == null ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
/// <inheritdoc />
|
||||
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@ -3,10 +3,17 @@ using Stylet;
|
||||
|
||||
namespace Artemis.UI.Shared
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a <see cref="DataModel" /> display view model
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the data model</typeparam>
|
||||
public abstract class DataModelDisplayViewModel<T> : DataModelDisplayViewModel
|
||||
{
|
||||
private T _displayValue;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets value that the view model must display
|
||||
/// </summary>
|
||||
public T DisplayValue
|
||||
{
|
||||
get => _displayValue;
|
||||
@ -19,11 +26,15 @@ namespace Artemis.UI.Shared
|
||||
|
||||
internal override object InternalGuard => null;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void UpdateValue(object model)
|
||||
{
|
||||
DisplayValue = model is T value ? value : default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the display value is updated
|
||||
/// </summary>
|
||||
protected virtual void OnDisplayValueUpdated()
|
||||
{
|
||||
}
|
||||
@ -50,6 +61,10 @@ namespace Artemis.UI.Shared
|
||||
/// </summary>
|
||||
internal abstract object InternalGuard { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Updates the display value
|
||||
/// </summary>
|
||||
/// <param name="model">The value to set</param>
|
||||
public abstract void UpdateValue(object model);
|
||||
}
|
||||
}
|
||||
@ -9,25 +9,41 @@ using Stylet;
|
||||
|
||||
namespace Artemis.UI.Shared
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a <see cref="DataModel" /> input view model
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the data model</typeparam>
|
||||
public abstract class DataModelInputViewModel<T> : DataModelInputViewModel
|
||||
{
|
||||
private bool _closed;
|
||||
private T _inputValue;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="DataModelInputViewModel{T}" /> class
|
||||
/// </summary>
|
||||
/// <param name="targetDescription">The description of the property this input VM is representing</param>
|
||||
/// <param name="initialValue">The initial value to set the input value to</param>
|
||||
protected DataModelInputViewModel(DataModelPropertyAttribute targetDescription, T initialValue)
|
||||
{
|
||||
TargetDescription = targetDescription;
|
||||
InputValue = initialValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value shown in the input
|
||||
/// </summary>
|
||||
public T InputValue
|
||||
{
|
||||
get => _inputValue;
|
||||
set => SetAndNotify(ref _inputValue, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description of the property this input VM is representing
|
||||
/// </summary>
|
||||
public DataModelPropertyAttribute TargetDescription { get; }
|
||||
internal override object InternalGuard { get; } = null;
|
||||
|
||||
internal override object InternalGuard { get; } = new object();
|
||||
|
||||
/// <inheritdoc />
|
||||
public sealed override void Submit()
|
||||
@ -74,23 +90,6 @@ namespace Artemis.UI.Shared
|
||||
/// </summary>
|
||||
internal IReadOnlyCollection<Type> CompatibleConversionTypes { get; set; }
|
||||
|
||||
public void AttachView(UIElement view)
|
||||
{
|
||||
if (View != null)
|
||||
throw new InvalidOperationException(string.Format("Tried to attach View {0} to ViewModel {1}, but it already has a view attached", view.GetType().Name, GetType().Name));
|
||||
|
||||
View = view;
|
||||
|
||||
// After the animation finishes attempt to focus the input field
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(50);
|
||||
await Execute.OnUIThreadAsync(() => View.MoveFocus(new TraversalRequest(FocusNavigationDirection.First)));
|
||||
});
|
||||
}
|
||||
|
||||
public UIElement View { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Submits the input value and removes this view model.
|
||||
/// <para>This is called automatically when the user presses enter or clicks outside the view</para>
|
||||
@ -116,5 +115,22 @@ namespace Artemis.UI.Shared
|
||||
protected virtual void OnCancel()
|
||||
{
|
||||
}
|
||||
|
||||
public void AttachView(UIElement view)
|
||||
{
|
||||
if (View != null)
|
||||
throw new InvalidOperationException(string.Format("Tried to attach View {0} to ViewModel {1}, but it already has a view attached", view.GetType().Name, GetType().Name));
|
||||
|
||||
View = view;
|
||||
|
||||
// After the animation finishes attempt to focus the input field
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(50);
|
||||
await Execute.OnUIThreadAsync(() => View.MoveFocus(new TraversalRequest(FocusNavigationDirection.First)));
|
||||
});
|
||||
}
|
||||
|
||||
public UIElement View { get; set; }
|
||||
}
|
||||
}
|
||||
@ -8,6 +8,9 @@ namespace Artemis.UI.Shared.Input
|
||||
/// </summary>
|
||||
public partial class DataModelDynamicView : UserControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="DataModelDynamicView" /> class
|
||||
/// </summary>
|
||||
public DataModelDynamicView()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
@ -16,6 +16,7 @@ namespace Artemis.UI.Shared.Input
|
||||
private readonly IDataModelUIService _dataModelUIService;
|
||||
private readonly Window _rootView;
|
||||
private SolidColorBrush _buttonBrush = new SolidColorBrush(Color.FromRgb(171, 71, 188));
|
||||
private bool _displaySwitchButton;
|
||||
private DataModelDisplayViewModel _displayViewModel;
|
||||
private DataModelInputViewModel _inputViewModel;
|
||||
private bool _isEnabled;
|
||||
@ -23,7 +24,6 @@ namespace Artemis.UI.Shared.Input
|
||||
private DataModelPropertyAttribute _targetDescription;
|
||||
private Type _targetType;
|
||||
private object _value;
|
||||
private bool _displaySwitchButton;
|
||||
|
||||
public DataModelStaticViewModel(Type targetType, DataModelPropertyAttribute targetDescription, IDataModelUIService dataModelUIService)
|
||||
{
|
||||
@ -42,6 +42,9 @@ namespace Artemis.UI.Shared.Input
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the brush to use for the input button
|
||||
/// </summary>
|
||||
public SolidColorBrush ButtonBrush
|
||||
{
|
||||
get => _buttonBrush;
|
||||
@ -52,32 +55,50 @@ namespace Artemis.UI.Shared.Input
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the brush to use for the switch button
|
||||
/// </summary>
|
||||
public SolidColorBrush SwitchButtonBrush => new SolidColorBrush(ButtonBrush.Color.Darken());
|
||||
|
||||
/// <summary>
|
||||
/// Gets the view model used to display the value
|
||||
/// </summary>
|
||||
public DataModelDisplayViewModel DisplayViewModel
|
||||
{
|
||||
get => _displayViewModel;
|
||||
set => SetAndNotify(ref _displayViewModel, value);
|
||||
private set => SetAndNotify(ref _displayViewModel, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the view model used to edit the value
|
||||
/// </summary>
|
||||
public DataModelInputViewModel InputViewModel
|
||||
{
|
||||
get => _inputViewModel;
|
||||
private set => SetAndNotify(ref _inputViewModel, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the target property
|
||||
/// </summary>
|
||||
public Type TargetType
|
||||
{
|
||||
get => _targetType;
|
||||
private set => SetAndNotify(ref _targetType, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description of the target property
|
||||
/// </summary>
|
||||
public DataModelPropertyAttribute TargetDescription
|
||||
{
|
||||
get => _targetDescription;
|
||||
set => SetAndNotify(ref _targetDescription, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the target
|
||||
/// </summary>
|
||||
public object Value
|
||||
{
|
||||
get => _value;
|
||||
@ -88,24 +109,36 @@ namespace Artemis.UI.Shared.Input
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the placeholder text when no value is entered
|
||||
/// </summary>
|
||||
public string Placeholder
|
||||
{
|
||||
get => _placeholder;
|
||||
set => SetAndNotify(ref _placeholder, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the enabled state of the input
|
||||
/// </summary>
|
||||
public bool IsEnabled
|
||||
{
|
||||
get => _isEnabled;
|
||||
private set => SetAndNotify(ref _isEnabled, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether the switch button should be displayed
|
||||
/// </summary>
|
||||
public bool DisplaySwitchButton
|
||||
{
|
||||
get => _displaySwitchButton;
|
||||
set => SetAndNotify(ref _displaySwitchButton, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activates the input view model
|
||||
/// </summary>
|
||||
public void ActivateInputViewModel()
|
||||
{
|
||||
InputViewModel = _dataModelUIService.GetDataModelInputViewModel(
|
||||
@ -116,6 +149,10 @@ namespace Artemis.UI.Shared.Input
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the target type
|
||||
/// </summary>
|
||||
/// <param name="target">The new target type</param>
|
||||
public void UpdateTargetType(Type target)
|
||||
{
|
||||
TargetType = target;
|
||||
@ -135,6 +172,9 @@ namespace Artemis.UI.Shared.Input
|
||||
ApplyFreeInput(TargetType.GetDefault(), true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Requests switching the input type to dynamic
|
||||
/// </summary>
|
||||
public void SwitchToDynamic()
|
||||
{
|
||||
InputViewModel?.Cancel();
|
||||
@ -154,17 +194,33 @@ namespace Artemis.UI.Shared.Input
|
||||
|
||||
#region IDisposable
|
||||
|
||||
/// <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)
|
||||
{
|
||||
if (disposing)
|
||||
if (_rootView != null)
|
||||
{
|
||||
_rootView.MouseUp -= RootViewOnMouseUp;
|
||||
_rootView.KeyUp -= RootViewOnKeyUp;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
if (_rootView != null)
|
||||
{
|
||||
_rootView.MouseUp -= RootViewOnMouseUp;
|
||||
_rootView.KeyUp -= RootViewOnKeyUp;
|
||||
}
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Event handlers
|
||||
|
||||
private void RootViewOnKeyUp(object sender, KeyEventArgs e)
|
||||
@ -191,14 +247,28 @@ namespace Artemis.UI.Shared.Input
|
||||
|
||||
#region Events
|
||||
|
||||
public event EventHandler<DataModelInputStaticEventArgs> ValueUpdated;
|
||||
public event EventHandler SwitchToDynamicRequested;
|
||||
/// <summary>
|
||||
/// Occurs when the value of the property has been updated
|
||||
/// </summary>
|
||||
public event EventHandler<DataModelInputStaticEventArgs>? ValueUpdated;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a switch to dynamic input has been requested
|
||||
/// </summary>
|
||||
public event EventHandler? SwitchToDynamicRequested;
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the <see cref="ValueUpdated" /> event
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
protected virtual void OnValueUpdated(DataModelInputStaticEventArgs e)
|
||||
{
|
||||
ValueUpdated?.Invoke(this, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the <see cref="SwitchToDynamicRequested" /> event
|
||||
/// </summary>
|
||||
protected virtual void OnSwitchToDynamicRequested()
|
||||
{
|
||||
SwitchToDynamicRequested?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user