Replace EveryValueChanged with ReactiveProperty

This commit is contained in:
Matt Parker
2025-12-05 20:55:03 +10:00
parent 275e822b77
commit b562c4c129
3 changed files with 22 additions and 20 deletions

View File

@@ -1,4 +1,5 @@
using SharpIDE.Application.Features.Analysis; using R3;
using SharpIDE.Application.Features.Analysis;
using SharpIDE.Application.Features.SolutionDiscovery; using SharpIDE.Application.Features.SolutionDiscovery;
namespace SharpIDE.Application.Features.NavigationHistory; namespace SharpIDE.Application.Features.NavigationHistory;
@@ -9,12 +10,12 @@ public class IdeNavigationHistoryService
// Using LinkedList for back stack to efficiently remove oldest entries // Using LinkedList for back stack to efficiently remove oldest entries
private readonly LinkedList<IdeNavigationLocation> _backStack = new(); private readonly LinkedList<IdeNavigationLocation> _backStack = new();
private IdeNavigationLocation? _current;
private readonly Stack<IdeNavigationLocation> _forwardStack = new(); private readonly Stack<IdeNavigationLocation> _forwardStack = new();
public bool CanGoBack => _backStack.Count > 0; public bool CanGoBack => _backStack.Count > 0;
public bool CanGoForward => _forwardStack.Count > 0; public bool CanGoForward => _forwardStack.Count > 0;
public IdeNavigationLocation? Current => _current; public ReactiveProperty<IdeNavigationLocation?> Current { get; private set; } = new(null);
public bool EnableRecording { get; set; } = false; public bool EnableRecording { get; set; } = false;
public void StartRecording() => EnableRecording = true; public void StartRecording() => EnableRecording = true;
@@ -23,40 +24,40 @@ public class IdeNavigationHistoryService
{ {
if (EnableRecording is false) return; if (EnableRecording is false) return;
var location = new IdeNavigationLocation(file, linePosition); var location = new IdeNavigationLocation(file, linePosition);
if (location == _current) if (location == Current.Value)
{ {
// perhaps we filter out our forward and back navigations like this? // perhaps we filter out our forward and back navigations like this?
return; return;
} }
if (_current is not null) if (Current.Value is not null)
{ {
_backStack.AddLast(_current); _backStack.AddLast(Current.Value);
if (_backStack.Count > MaxHistorySize) _backStack.RemoveFirst(); if (_backStack.Count > MaxHistorySize) _backStack.RemoveFirst();
} }
_current = location; Current.Value = location;
_forwardStack.Clear(); _forwardStack.Clear();
} }
public void GoBack() public void GoBack()
{ {
if (!CanGoBack) throw new InvalidOperationException("Cannot go back, no history available."); if (!CanGoBack) throw new InvalidOperationException("Cannot go back, no history available.");
if (_current is not null) if (Current.Value is not null)
{ {
_forwardStack.Push(_current); _forwardStack.Push(Current.Value);
} }
_current = _backStack.Last(); Current.Value = _backStack.Last();
_backStack.RemoveLast(); _backStack.RemoveLast();
} }
public void GoForward() public void GoForward()
{ {
if (!CanGoForward) throw new InvalidOperationException("Cannot go forward, no history available."); if (!CanGoForward) throw new InvalidOperationException("Cannot go forward, no history available.");
if (_current is not null) if (Current.Value is not null)
{ {
_backStack.AddLast(_current); _backStack.AddLast(Current.Value);
} }
_current = _forwardStack.Pop(); Current.Value = _forwardStack.Pop();
} }
} }

View File

@@ -376,7 +376,7 @@ public partial class SharpIdeCodeEdit : CodeEdit
if (@event is InputEventMouseButton { Pressed: true } mouseEvent) if (@event is InputEventMouseButton { Pressed: true } mouseEvent)
{ {
var (col, line) = GetLineColumnAtPos((Vector2I)mouseEvent.Position); var (col, line) = GetLineColumnAtPos((Vector2I)mouseEvent.Position);
var current = _navigationHistoryService.Current; var current = _navigationHistoryService.Current.Value;
if (current!.File != _currentFile) throw new InvalidOperationException("Current navigation history file does not match the focused code editor file."); if (current!.File != _currentFile) throw new InvalidOperationException("Current navigation history file does not match the focused code editor file.");
if (current.LinePosition.Line != line) // Only record a new navigation if the line has changed if (current.LinePosition.Line != line) // Only record a new navigation if the line has changed
{ {

View File

@@ -17,26 +17,27 @@ public partial class ForwardBackwardButtonContainer : HBoxContainer
_forwardButton = GetNode<Button>("ForwardButton"); _forwardButton = GetNode<Button>("ForwardButton");
_backwardButton.Pressed += OnBackwardButtonPressed; _backwardButton.Pressed += OnBackwardButtonPressed;
_forwardButton.Pressed += OnForwardButtonPressed; _forwardButton.Pressed += OnForwardButtonPressed;
Observable.EveryValueChanged(_navigationHistoryService, navigationHistoryService => navigationHistoryService.Current) _navigationHistoryService.Current.SubscribeOnThreadPool().SubscribeAwait(async (s, ct) =>
.Where(s => s is not null) {
.Subscribe(s => await this.InvokeAsync(() =>
{ {
_backwardButton.Disabled = !_navigationHistoryService.CanGoBack; _backwardButton.Disabled = !_navigationHistoryService.CanGoBack;
_forwardButton.Disabled = !_navigationHistoryService.CanGoForward; _forwardButton.Disabled = !_navigationHistoryService.CanGoForward;
}).AddTo(this); });
}).AddTo(this);
} }
private void OnBackwardButtonPressed() private void OnBackwardButtonPressed()
{ {
_navigationHistoryService.GoBack(); _navigationHistoryService.GoBack();
var current = _navigationHistoryService.Current; var current = _navigationHistoryService.Current.Value;
GodotGlobalEvents.Instance.FileExternallySelected.InvokeParallelFireAndForget(current!.File, current.LinePosition); GodotGlobalEvents.Instance.FileExternallySelected.InvokeParallelFireAndForget(current!.File, current.LinePosition);
} }
private void OnForwardButtonPressed() private void OnForwardButtonPressed()
{ {
_navigationHistoryService.GoForward(); _navigationHistoryService.GoForward();
var current = _navigationHistoryService.Current; var current = _navigationHistoryService.Current.Value;
GodotGlobalEvents.Instance.FileExternallySelected.InvokeParallelFireAndForget(current!.File, current.LinePosition); GodotGlobalEvents.Instance.FileExternallySelected.InvokeParallelFireAndForget(current!.File, current.LinePosition);
} }
} }