From fa710777d7bf5c61cd8ca9fec0838f89167ada12 Mon Sep 17 00:00:00 2001 From: Robert Date: Sat, 20 May 2023 23:11:44 +0200 Subject: [PATCH] UI - Use Timer instead of DispatcherTimer where feasible --- .../Controls/DeviceVisualizer.cs | 2 +- .../Builders/OpenFileDialogBuilder.cs | 2 +- .../Panels/Playback/PlaybackViewModel.cs | 19 +++++++------- .../DataBinding/DataBindingViewModel.cs | 21 +++++++--------- .../ModuleActivationRequirementViewModel.cs | 17 +++++-------- .../NodeScriptWindowViewModel.cs | 25 ++++++++----------- .../DisplayValueNodeCustomViewModel.cs | 8 +++--- 7 files changed, 42 insertions(+), 52 deletions(-) diff --git a/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs b/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs index 3d8a3192e..111675973 100644 --- a/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs +++ b/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs @@ -34,7 +34,7 @@ public class DeviceVisualizer : Control /// public DeviceVisualizer() { - _timer = new DispatcherTimer(DispatcherPriority.Render) {Interval = TimeSpan.FromMilliseconds(1000.0 / UpdateFrameRate)}; + _timer = new DispatcherTimer(DispatcherPriority.Background) {Interval = TimeSpan.FromMilliseconds(1000.0 / UpdateFrameRate)}; _deviceVisualizerLeds = new List(); PointerReleased += OnPointerReleased; diff --git a/src/Artemis.UI.Shared/Services/Builders/OpenFileDialogBuilder.cs b/src/Artemis.UI.Shared/Services/Builders/OpenFileDialogBuilder.cs index 616b7977a..c9ef09d65 100644 --- a/src/Artemis.UI.Shared/Services/Builders/OpenFileDialogBuilder.cs +++ b/src/Artemis.UI.Shared/Services/Builders/OpenFileDialogBuilder.cs @@ -78,6 +78,6 @@ public class OpenFileDialogBuilder public async Task ShowAsync() { IReadOnlyList files = await _parent.StorageProvider.OpenFilePickerAsync(_options); - return files.Select(f => f.Path.LocalPath).ToArray(); + return files.Count == 0 ? null : files.Select(f => f.Path.LocalPath).ToArray(); } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Playback/PlaybackViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/Playback/PlaybackViewModel.cs index dc4390255..5e91ae70f 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/Playback/PlaybackViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Playback/PlaybackViewModel.cs @@ -2,11 +2,11 @@ using System.Reactive; using System.Reactive.Disposables; using System.Reactive.Linq; +using System.Timers; using Artemis.Core; using Artemis.Core.Services; using Artemis.UI.Shared; using Artemis.UI.Shared.Services.ProfileEditor; -using Avalonia.Threading; using ReactiveUI; namespace Artemis.UI.Screens.ProfileEditor.Playback; @@ -53,13 +53,17 @@ public class PlaybackViewModel : ActivatableViewModelBase _formattedCurrentTime = _profileEditorService.Time.Select(t => $"{Math.Floor(t.TotalSeconds):00}.{t.Milliseconds:000}").ToProperty(this, vm => vm.FormattedCurrentTime).DisposeWith(d); _playing = _profileEditorService.Playing.ToProperty(this, vm => vm.Playing).DisposeWith(d); _keyBindingsEnabled = Shared.UI.KeyBindingsEnabled.ToProperty(this, vm => vm.KeyBindingsEnabled).DisposeWith(d); - + + // Update timer + Timer updateTimer = new(TimeSpan.FromMilliseconds(60.0 / 1000)); + updateTimer.Elapsed += (_, _) => Update(); + updateTimer.DisposeWith(d); + _profileEditorService.Playing.Subscribe(_ => _lastUpdate = DateTime.Now).DisposeWith(d); + _profileEditorService.Playing.Subscribe(p => updateTimer.Enabled = p).DisposeWith(d); _lastUpdate = DateTime.MinValue; - DispatcherTimer updateTimer = new(TimeSpan.FromMilliseconds(60.0 / 1000), DispatcherPriority.Background, Update); - updateTimer.Start(); + Disposable.Create(() => { - updateTimer.Stop(); _settingsService.GetSetting("ProfileEditor.RepeatTimeline", true).Value = _repeating && _repeatTimeline; _settingsService.GetSetting("ProfileEditor.RepeatSegment", false).Value = _repeating && _repeatSegment; }).DisposeWith(d); @@ -206,13 +210,10 @@ public class PlaybackViewModel : ActivatableViewModelBase return TimeSpan.Zero; } - private void Update(object? sender, EventArgs e) + private void Update() { try { - if (!Playing) - return; - if (_lastUpdate == DateTime.MinValue) _lastUpdate = DateTime.Now; diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/DataBinding/DataBindingViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/DataBinding/DataBindingViewModel.cs index 672e50490..7435ac361 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/DataBinding/DataBindingViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/DataBinding/DataBindingViewModel.cs @@ -2,6 +2,7 @@ using System.Reactive.Disposables; using System.Reactive.Linq; using System.Threading.Tasks; +using System.Timers; using Artemis.Core; using Artemis.Core.Services; using Artemis.UI.DryIoc.Factories; @@ -50,20 +51,16 @@ public class DataBindingViewModel : ActivatableViewModelBase .DisposeWith(d); _profileEditorService.Playing.CombineLatest(_profileEditorService.SuspendedEditing).Subscribe(tuple => _playing = tuple.First || tuple.Second).DisposeWith(d); - DispatcherTimer updateTimer = new(TimeSpan.FromMilliseconds(25.0 / 1000), DispatcherPriority.Background, Update); - // TODO: Remove in favor of saving each time a node editor command is executed - DispatcherTimer saveTimer = new(TimeSpan.FromMinutes(2), DispatcherPriority.Normal, Save); + Timer updateTimer = new(TimeSpan.FromMilliseconds(25.0 / 1000)); + Timer saveTimer = new(TimeSpan.FromMinutes(2)); + updateTimer.Elapsed += (_, _) => Update(); + saveTimer.Elapsed += (_, _) => Save(); updateTimer.Start(); saveTimer.Start(); - Disposable.Create(() => - { - updateTimer.Stop(); - saveTimer.Stop(); - - _profileEditorService.SaveProfile(); - }).DisposeWith(d); + updateTimer.DisposeWith(d); + saveTimer.DisposeWith(d); }); } @@ -97,7 +94,7 @@ public class DataBindingViewModel : ActivatableViewModelBase } } - private void Update(object? sender, EventArgs e) + private void Update() { // If playing the data binding will already be updated, no need to do it here if (_playing || !_alwaysApplyDataBindings.Value) @@ -106,7 +103,7 @@ public class DataBindingViewModel : ActivatableViewModelBase LayerProperty?.UpdateDataBinding(); } - private void Save(object? sender, EventArgs e) + private void Save() { if (!_editorOpen) _profileEditorService.SaveProfile(); diff --git a/src/Artemis.UI/Screens/Sidebar/Dialogs/ModuleActivationRequirementViewModel.cs b/src/Artemis.UI/Screens/Sidebar/Dialogs/ModuleActivationRequirementViewModel.cs index 8a51d3810..c7844442c 100644 --- a/src/Artemis.UI/Screens/Sidebar/Dialogs/ModuleActivationRequirementViewModel.cs +++ b/src/Artemis.UI/Screens/Sidebar/Dialogs/ModuleActivationRequirementViewModel.cs @@ -1,8 +1,8 @@ using System; using System.Reactive.Disposables; +using System.Timers; using Artemis.Core.Modules; using Artemis.UI.Shared; -using Avalonia.Threading; using Humanizer; using ReactiveUI; @@ -13,7 +13,6 @@ public class ModuleActivationRequirementViewModel : ActivatableViewModelBase private readonly IModuleActivationRequirement _activationRequirement; private string _requirementDescription; private bool _requirementMet; - private DispatcherTimer? _updateTimer; public ModuleActivationRequirementViewModel(IModuleActivationRequirement activationRequirement) { @@ -23,14 +22,10 @@ public class ModuleActivationRequirementViewModel : ActivatableViewModelBase this.WhenActivated(d => { - _updateTimer = new DispatcherTimer(TimeSpan.FromMilliseconds(500), DispatcherPriority.Background, Update); - _updateTimer.Start(); - - Disposable.Create(() => - { - _updateTimer?.Stop(); - _updateTimer = null; - }).DisposeWith(d); + Timer updateTimer = new(TimeSpan.FromMilliseconds(500)); + updateTimer.Elapsed += (_, _) => Update(); + updateTimer.Start(); + updateTimer.DisposeWith(d); }); } @@ -48,7 +43,7 @@ public class ModuleActivationRequirementViewModel : ActivatableViewModelBase set => RaiseAndSetIfChanged(ref _requirementMet, value); } - private void Update(object? sender, EventArgs e) + private void Update() { RequirementDescription = _activationRequirement.GetUserFriendlyDescription(); RequirementMet = _activationRequirement.Evaluate(); diff --git a/src/Artemis.UI/Screens/VisualScripting/NodeScriptWindowViewModel.cs b/src/Artemis.UI/Screens/VisualScripting/NodeScriptWindowViewModel.cs index ba87decff..9383ccdec 100644 --- a/src/Artemis.UI/Screens/VisualScripting/NodeScriptWindowViewModel.cs +++ b/src/Artemis.UI/Screens/VisualScripting/NodeScriptWindowViewModel.cs @@ -5,6 +5,7 @@ using System.IO; using System.Reactive; using System.Reactive.Disposables; using System.Threading.Tasks; +using System.Timers; using Artemis.Core; using Artemis.Core.Services; using Artemis.UI.DryIoc.Factories; @@ -12,9 +13,7 @@ using Artemis.UI.Shared.Services; using Artemis.UI.Shared.Services.NodeEditor; using Artemis.UI.Shared.Services.NodeEditor.Commands; using Avalonia; -using Avalonia.Threading; using DynamicData; -using DynamicData.List; using ReactiveUI; namespace Artemis.UI.Screens.VisualScripting; @@ -66,19 +65,17 @@ public class NodeScriptWindowViewModel : NodeScriptWindowViewModelBase this.WhenActivated(d => { _keyBindingsEnabled = Shared.UI.KeyBindingsEnabled.ToProperty(this, vm => vm.KeyBindingsEnabled).DisposeWith(d); - - DispatcherTimer updateTimer = new(TimeSpan.FromMilliseconds(25.0 / 1000), DispatcherPriority.Background, Update); - // TODO: Remove in favor of saving each time a node editor command is executed - DispatcherTimer saveTimer = new(TimeSpan.FromMinutes(2), DispatcherPriority.Background, Save); + Timer updateTimer = new(TimeSpan.FromMilliseconds(25.0 / 1000)); + Timer saveTimer = new(TimeSpan.FromMinutes(2)); + + updateTimer.Elapsed += (_, _) => Update(); + saveTimer.Elapsed += (_, _) => Save(); updateTimer.Start(); saveTimer.Start(); - Disposable.Create(() => - { - updateTimer.Stop(); - saveTimer.Stop(); - }).DisposeWith(d); + updateTimer.DisposeWith(d); + saveTimer.DisposeWith(d); }); } @@ -93,7 +90,7 @@ public class NodeScriptWindowViewModel : NodeScriptWindowViewModelBase public ReactiveCommand Export { get; } public ReactiveCommand Import { get; } public bool KeyBindingsEnabled => _keyBindingsEnabled?.Value ?? false; - + public PluginSetting ShowDataModelValues => _settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false); public PluginSetting ShowFullPaths => _settingsService.GetSetting("ProfileEditor.ShowFullPaths", false); public PluginSetting AlwaysShowValues => _settingsService.GetSetting("ProfileEditor.AlwaysShowValues", true); @@ -176,13 +173,13 @@ public class NodeScriptWindowViewModel : NodeScriptWindowViewModelBase } } - private void Update(object? sender, EventArgs e) + private void Update() { if (!_pauseUpdate) NodeScript.Run(); } - private void Save(object? sender, EventArgs e) + private void Save() { if (NodeScript.Context is Profile profile) _profileService.SaveProfile(profile, true); diff --git a/src/Artemis.VisualScripting/Nodes/Static/Screens/DisplayValueNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/Static/Screens/DisplayValueNodeCustomViewModel.cs index f9e462de4..590a397fb 100644 --- a/src/Artemis.VisualScripting/Nodes/Static/Screens/DisplayValueNodeCustomViewModel.cs +++ b/src/Artemis.VisualScripting/Nodes/Static/Screens/DisplayValueNodeCustomViewModel.cs @@ -1,7 +1,6 @@ using System.Reactive.Disposables; using Artemis.Core; using Artemis.UI.Shared.VisualScripting; -using Avalonia.Threading; using ReactiveUI; namespace Artemis.VisualScripting.Nodes.Static.Screens; @@ -18,9 +17,10 @@ public class DisplayValueNodeCustomViewModel : CustomNodeViewModel // Because the DisplayValueNode has no output it never evaluates, manually do so here this.WhenActivated(d => { - DispatcherTimer updateTimer = new(TimeSpan.FromMilliseconds(25.0 / 1000), DispatcherPriority.Background, Update); + System.Timers.Timer updateTimer = new(TimeSpan.FromMilliseconds(25.0 / 1000)); + updateTimer.Elapsed += (_, _) => Update(); updateTimer.Start(); - Disposable.Create(() => updateTimer.Stop()).DisposeWith(d); + updateTimer.DisposeWith(d); }); } @@ -30,7 +30,7 @@ public class DisplayValueNodeCustomViewModel : CustomNodeViewModel private set => this.RaiseAndSetIfChanged(ref _currentValue, value); } - private void Update(object? sender, EventArgs e) + private void Update() { try {