diff --git a/src/Artemis.UI.Shared/Behaviors/ScrollParentWhenAtMax.cs b/src/Artemis.UI.Shared/Behaviors/ScrollParentWhenAtMax.cs
index 2cde2a73c..b0493fc20 100644
--- a/src/Artemis.UI.Shared/Behaviors/ScrollParentWhenAtMax.cs
+++ b/src/Artemis.UI.Shared/Behaviors/ScrollParentWhenAtMax.cs
@@ -6,14 +6,19 @@ using Microsoft.Xaml.Behaviors;
namespace Artemis.UI.Shared
{
+ ///
+ /// A behavior that makes a scroll viewer bubble up its events if it is at its scroll limit
+ ///
public class ScrollParentWhenAtMax : Behavior
{
+ ///
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.PreviewMouseWheel += PreviewMouseWheel;
}
+ ///
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(AssociatedObject);
+ ScrollViewer? scrollViewer = GetVisualChild(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(DependencyObject parent) where T : Visual
+ private static T? GetVisualChild(DependencyObject parent) where T : Visual
{
- T child = default;
+ T? child = default;
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
diff --git a/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs b/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs
index e833d3479..cf8a17afe 100644
--- a/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs
+++ b/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs
@@ -38,8 +38,8 @@ namespace Artemis.UI.Shared
private readonly DrawingGroup _backingStore;
private readonly List _deviceVisualizerLeds;
private readonly DispatcherTimer _timer;
- private BitmapImage _deviceImage;
- private ArtemisDevice _oldDevice;
+ private BitmapImage? _deviceImage;
+ private ArtemisDevice? _oldDevice;
///
/// Creates a new instance of the class
@@ -60,7 +60,7 @@ namespace Artemis.UI.Shared
///
/// Gets or sets the device to visualize
///
- public ArtemisDevice Device
+ public ArtemisDevice? Device
{
get => (ArtemisDevice) GetValue(DeviceProperty);
set => SetValue(DeviceProperty, value);
@@ -78,16 +78,32 @@ namespace Artemis.UI.Shared
///
/// Gets or sets a list of LEDs to highlight
///
- public IEnumerable HighlightedLeds
+ public IEnumerable? HighlightedLeds
{
get => (IEnumerable) GetValue(HighlightedLedsProperty);
set => SetValue(HighlightedLedsProperty, value);
}
+ ///
+ /// Releases the unmanaged resources used by the object and optionally releases the managed resources.
+ ///
+ ///
+ /// to release both managed and unmanaged resources;
+ /// to release only unmanaged resources.
+ ///
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ _timer.Stop();
+ }
+ }
+
///
public void Dispose()
{
- _timer.Stop();
+ Dispose(true);
+ GC.SuppressFinalize(this);
}
///
@@ -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();
diff --git a/src/Artemis.UI.Shared/Converters/NullToVisibilityConverter.cs b/src/Artemis.UI.Shared/Converters/NullToVisibilityConverter.cs
index 0ff1e40e3..dd70fbac2 100644
--- a/src/Artemis.UI.Shared/Converters/NullToVisibilityConverter.cs
+++ b/src/Artemis.UI.Shared/Converters/NullToVisibilityConverter.cs
@@ -5,9 +5,13 @@ using System.Windows.Data;
namespace Artemis.UI.Shared
{
+ ///
+ /// Converts to
+ ///
public class NullToVisibilityConverter : IValueConverter
{
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ ///
+ 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)
+ ///
+ public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/DataModelDisplayViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/DataModelDisplayViewModel.cs
index 2d09153ef..623ed8a17 100644
--- a/src/Artemis.UI.Shared/DataModelVisualization/DataModelDisplayViewModel.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/DataModelDisplayViewModel.cs
@@ -3,10 +3,17 @@ using Stylet;
namespace Artemis.UI.Shared
{
+ ///
+ /// Represents a display view model
+ ///
+ /// The type of the data model
public abstract class DataModelDisplayViewModel : DataModelDisplayViewModel
{
private T _displayValue;
+ ///
+ /// Gets or sets value that the view model must display
+ ///
public T DisplayValue
{
get => _displayValue;
@@ -19,11 +26,15 @@ namespace Artemis.UI.Shared
internal override object InternalGuard => null;
+ ///
public override void UpdateValue(object model)
{
DisplayValue = model is T value ? value : default;
}
+ ///
+ /// Occurs when the display value is updated
+ ///
protected virtual void OnDisplayValueUpdated()
{
}
@@ -50,6 +61,10 @@ namespace Artemis.UI.Shared
///
internal abstract object InternalGuard { get; }
+ ///
+ /// Updates the display value
+ ///
+ /// The value to set
public abstract void UpdateValue(object model);
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/DataModelInputViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/DataModelInputViewModel.cs
index 30a24989e..97f5e5fa7 100644
--- a/src/Artemis.UI.Shared/DataModelVisualization/DataModelInputViewModel.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/DataModelInputViewModel.cs
@@ -9,25 +9,41 @@ using Stylet;
namespace Artemis.UI.Shared
{
+ ///
+ /// Represents a input view model
+ ///
+ /// The type of the data model
public abstract class DataModelInputViewModel : DataModelInputViewModel
{
private bool _closed;
private T _inputValue;
+ ///
+ /// Creates a new instance of the class
+ ///
+ /// The description of the property this input VM is representing
+ /// The initial value to set the input value to
protected DataModelInputViewModel(DataModelPropertyAttribute targetDescription, T initialValue)
{
TargetDescription = targetDescription;
InputValue = initialValue;
}
+ ///
+ /// Gets or sets the value shown in the input
+ ///
public T InputValue
{
get => _inputValue;
set => SetAndNotify(ref _inputValue, value);
}
+ ///
+ /// Gets the description of the property this input VM is representing
+ ///
public DataModelPropertyAttribute TargetDescription { get; }
- internal override object InternalGuard { get; } = null;
+
+ internal override object InternalGuard { get; } = new object();
///
public sealed override void Submit()
@@ -74,23 +90,6 @@ namespace Artemis.UI.Shared
///
internal IReadOnlyCollection 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; }
-
///
/// Submits the input value and removes this view model.
/// This is called automatically when the user presses enter or clicks outside the view
@@ -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; }
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelDynamicView.xaml.cs b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelDynamicView.xaml.cs
index 8a45bde5d..a487bdfea 100644
--- a/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelDynamicView.xaml.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelDynamicView.xaml.cs
@@ -8,6 +8,9 @@ namespace Artemis.UI.Shared.Input
///
public partial class DataModelDynamicView : UserControl
{
+ ///
+ /// Creates a new instance of the class
+ ///
public DataModelDynamicView()
{
InitializeComponent();
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelStaticViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelStaticViewModel.cs
index 490b126c9..5b632f1ce 100644
--- a/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelStaticViewModel.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelStaticViewModel.cs
@@ -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
}
}
+ ///
+ /// Gets or sets the brush to use for the input button
+ ///
public SolidColorBrush ButtonBrush
{
get => _buttonBrush;
@@ -52,32 +55,50 @@ namespace Artemis.UI.Shared.Input
}
}
+ ///
+ /// Gets the brush to use for the switch button
+ ///
public SolidColorBrush SwitchButtonBrush => new SolidColorBrush(ButtonBrush.Color.Darken());
+ ///
+ /// Gets the view model used to display the value
+ ///
public DataModelDisplayViewModel DisplayViewModel
{
get => _displayViewModel;
- set => SetAndNotify(ref _displayViewModel, value);
+ private set => SetAndNotify(ref _displayViewModel, value);
}
+ ///
+ /// Gets the view model used to edit the value
+ ///
public DataModelInputViewModel InputViewModel
{
get => _inputViewModel;
private set => SetAndNotify(ref _inputViewModel, value);
}
+ ///
+ /// Gets the type of the target property
+ ///
public Type TargetType
{
get => _targetType;
private set => SetAndNotify(ref _targetType, value);
}
+ ///
+ /// Gets the description of the target property
+ ///
public DataModelPropertyAttribute TargetDescription
{
get => _targetDescription;
set => SetAndNotify(ref _targetDescription, value);
}
+ ///
+ /// Gets or sets the value of the target
+ ///
public object Value
{
get => _value;
@@ -88,24 +109,36 @@ namespace Artemis.UI.Shared.Input
}
}
+ ///
+ /// Gets or sets the placeholder text when no value is entered
+ ///
public string Placeholder
{
get => _placeholder;
set => SetAndNotify(ref _placeholder, value);
}
+ ///
+ /// Gets or sets the enabled state of the input
+ ///
public bool IsEnabled
{
get => _isEnabled;
private set => SetAndNotify(ref _isEnabled, value);
}
+ ///
+ /// Gets or sets whether the switch button should be displayed
+ ///
public bool DisplaySwitchButton
{
get => _displaySwitchButton;
set => SetAndNotify(ref _displaySwitchButton, value);
}
+ ///
+ /// Activates the input view model
+ ///
public void ActivateInputViewModel()
{
InputViewModel = _dataModelUIService.GetDataModelInputViewModel(
@@ -116,6 +149,10 @@ namespace Artemis.UI.Shared.Input
);
}
+ ///
+ /// Updates the target type
+ ///
+ /// The new target type
public void UpdateTargetType(Type target)
{
TargetType = target;
@@ -135,6 +172,9 @@ namespace Artemis.UI.Shared.Input
ApplyFreeInput(TargetType.GetDefault(), true);
}
+ ///
+ /// Requests switching the input type to dynamic
+ ///
public void SwitchToDynamic()
{
InputViewModel?.Cancel();
@@ -154,17 +194,33 @@ namespace Artemis.UI.Shared.Input
#region IDisposable
+ ///
+ /// Releases the unmanaged resources used by the object and optionally releases the managed resources.
+ ///
+ ///
+ /// to release both managed and unmanaged resources;
+ /// to release only unmanaged resources.
+ ///
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ if (_rootView != null)
+ {
+ _rootView.MouseUp -= RootViewOnMouseUp;
+ _rootView.KeyUp -= RootViewOnKeyUp;
+ }
+ }
+
+ ///
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 ValueUpdated;
- public event EventHandler SwitchToDynamicRequested;
+ ///
+ /// Occurs when the value of the property has been updated
+ ///
+ public event EventHandler? ValueUpdated;
+ ///
+ /// Occurs when a switch to dynamic input has been requested
+ ///
+ public event EventHandler? SwitchToDynamicRequested;
+
+ ///
+ /// Invokes the event
+ ///
+ ///
protected virtual void OnValueUpdated(DataModelInputStaticEventArgs e)
{
ValueUpdated?.Invoke(this, e);
}
+ ///
+ /// Invokes the event
+ ///
protected virtual void OnSwitchToDynamicRequested()
{
SwitchToDynamicRequested?.Invoke(this, EventArgs.Empty);