Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
479cf95
Refactor: Replace ReactiveUI with CommunityToolkit.Mvvm in `PrintOutp…
voytas Jun 14, 2025
c0564ef
Refactor: Replace ReactiveUI with CommunityToolkit.Mvvm in `TrainerVi…
voytas Jun 14, 2025
ae967eb
Refactor: Replace ReactiveUI with CommunityToolkit.Mvvm in `TapeViewM…
voytas Jun 14, 2025
5b7713c
Refactor: Replace ReactiveUI with CommunityToolkit.Mvvm in `StatusBar…
voytas Jun 14, 2025
4f30aac
Refactor: Replace ReactiveUI with CommunityToolkit.Mvvm in `TapeBlock…
voytas Jun 14, 2025
5ca09cf
Refactor: Replace ReactiveUI with CommunityToolkit.Mvvm in `RecentFil…
voytas Jun 14, 2025
1bc0278
Refactor: Replace ReactiveUI with CommunityToolkit.Mvvm in `SelectFil…
voytas Jun 14, 2025
ec7b022
Refactor: Replace `ReactiveWindow` with `Window` in `PrintOutputView`…
voytas Jun 14, 2025
c0188e3
Refactor: Replace ReactiveUI with CommunityToolkit.Mvvm in `Screensho…
voytas Jun 14, 2025
0f02409
Refactor: Replace ReactiveUI with CommunityToolkit.Mvvm across multip…
voytas Jun 15, 2025
fd7d4d0
Refactor: Replace `Interaction` with `WeakReferenceMessenger` in `Sho…
voytas Jun 15, 2025
d5bd321
Refactor: Replace `Interaction` with `WeakReferenceMessenger` for `Sh…
voytas Jun 15, 2025
d6748bc
Refactor: Replace `Interaction` with `WeakReferenceMessenger` for `Sh…
voytas Jun 15, 2025
3766a08
Refactor: Replace `Interaction` with `WeakReferenceMessenger` for `Sh…
voytas Jun 15, 2025
b917f92
Refactor: Replace remaining ReactiveUI usages in `PreferencesViewMode…
voytas Jun 15, 2025
92b2724
Refactor: Update parameter names in `WeakReferenceMessenger` registra…
voytas Jun 15, 2025
c12b8b9
Refactor: Replace `ReactiveUI` with `CommunityToolkit.Mvvm` in `TimeM…
voytas Jun 15, 2025
303744a
Refactor: Complete migration from `ReactiveUI` to `CommunityToolkit.M…
voytas Jun 15, 2025
5572fe2
Refactor: Clean up unused methods in `MainWindowViewModel`, replace h…
voytas Jun 15, 2025
c289aa0
Refactor: Replace property change handlers in `MainWindowViewModel` a…
voytas Jun 16, 2025
bde0b27
Refactor: Complete migration of `Spectron` and `Spectron.Debugger` fr…
voytas Jun 16, 2025
ed2fbb2
Refactor: Remove unused `System.Reactive.Linq` import from `MainWindo…
voytas Jun 16, 2025
1698b76
Refactor: Replace breakpoint subscription logic with `WeakReferenceMe…
voytas Jun 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions src/Spectron.Debugger/Controls/CodeList.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@ namespace OldBit.Spectron.Debugger.Controls;

public partial class CodeList : UserControl
{
public CodeList()
{
InitializeComponent();
}
public CodeList() => InitializeComponent();

private void ListBox_OnDoubleTapped(object? sender, TappedEventArgs e)
{
Expand All @@ -20,7 +17,7 @@ private void ListBox_OnDoubleTapped(object? sender, TappedEventArgs e)

if (control.DataContext is CodeLineViewModel codeLine)
{
codeLine.IsBreakpoint = !codeLine.IsBreakpoint;
codeLine.ToggleBreakpoint();
}
}
}
21 changes: 6 additions & 15 deletions src/Spectron.Debugger/Controls/HexViewerCell.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,15 @@
using ReactiveUI;
using CommunityToolkit.Mvvm.ComponentModel;

namespace OldBit.Spectron.Debugger.Controls;

public class HexViewerCell : ReactiveObject
public partial class HexViewerCell : ObservableObject
{
private bool _isSelected;
[ObservableProperty]
private byte _value;

public byte Value
{
get => _value;
set => this.RaiseAndSetIfChanged(ref _value, value);
}

public bool IsSelected
{
get => _isSelected;
set => this.RaiseAndSetIfChanged(ref _isSelected, value);
}
[ObservableProperty]
private bool _isSelected;

public int RowIndex { get; init; }
public int ColumnIndex { get; init; }
public int ColumnIndex { get;init; }
}
2 changes: 1 addition & 1 deletion src/Spectron.Debugger/Controls/Logging.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
</Grid>

<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Left">
<CheckBox Content="T-states" IsChecked="{Binding ShouldLockTicks}"/>
<CheckBox Content="T-states" IsChecked="{Binding ShouldLogTicks}"/>
</StackPanel>

<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Center">
Expand Down
4 changes: 2 additions & 2 deletions src/Spectron.Debugger/Logging/InstructionLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ internal sealed class InstructionLogger : IDisposable

internal bool IsEnabled { get; private set; }

internal bool ShouldLockTicks { get; set; } = true;
internal bool ShouldLogTicks { get; set; } = true;

internal InstructionLogger(string logFilePath, Emulator emulator)
{
Expand Down Expand Up @@ -56,7 +56,7 @@ private void CpuOnBeforeInstruction(BeforeInstructionEventArgs e)
instruction = instructions[0].ToString();
}

_textWriter.WriteLine(ShouldLockTicks ?
_textWriter.WriteLine(ShouldLogTicks ?
$"{ticks} {address:X4} {instruction}" :
$"{address:X4} {instruction}");
}
Expand Down
3 changes: 3 additions & 0 deletions src/Spectron.Debugger/Messages/BreakpointAddedMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace OldBit.Spectron.Debugger.Messages;

public record BreakpointAddedMessage(Word Address);
5 changes: 5 additions & 0 deletions src/Spectron.Debugger/Messages/BreakpointRemovedMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using OldBit.Spectron.Debugger.Breakpoints;

namespace OldBit.Spectron.Debugger.Messages;

public record BreakpointRemovedMessage(Register Register, Word Address);
5 changes: 5 additions & 0 deletions src/Spectron.Debugger/Messages/BreakpointUpdatedMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using OldBit.Spectron.Debugger.Breakpoints;

namespace OldBit.Spectron.Debugger.Messages;

public record BreakpointUpdatedMessage(Register Register, Word OldAddress, Word NewAddress);
3 changes: 3 additions & 0 deletions src/Spectron.Debugger/Messages/ResetEmulatorMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace OldBit.Spectron.Debugger.Messages;

public record ResetEmulatorMessage(bool HardReset = false);
5 changes: 5 additions & 0 deletions src/Spectron.Debugger/Messages/ToggleBreakpointMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using OldBit.Spectron.Debugger.Breakpoints;

namespace OldBit.Spectron.Debugger.Messages;

public record ToggleBreakpointMessage(Register Register, Word Address, bool IsEnabled);
2 changes: 1 addition & 1 deletion src/Spectron.Debugger/Spectron.Debugger.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
<PackageReference Include="Avalonia" Version="11.2.8" />
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.2.8" />
<PackageReference Include="Avalonia.Controls.ItemsRepeater" Version="11.1.5" />
<PackageReference Include="Avalonia.ReactiveUI" Version="11.2.8" />
<PackageReference Include="Avalonia.Xaml.Interactions" Version="11.2.7.1" />
<PackageReference Include="Avalonia.Xaml.Interactivity" Version="11.2.7.1" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="Material.Icons.Avalonia" Version="2.4.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.5" />
<PackageReference Include="OldBit.Z80Cpu.Spectron" Version="0.9.3-pre.12" />
Expand Down
65 changes: 45 additions & 20 deletions src/Spectron.Debugger/ViewModels/BreakpointListViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
using System.Collections;
using System.Collections.ObjectModel;
using System.Reactive;
using DynamicData;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using OldBit.Spectron.Debugger.Breakpoints;
using ReactiveUI;
using OldBit.Spectron.Debugger.Messages;

namespace OldBit.Spectron.Debugger.ViewModels;

public class BreakpointListViewModel : ReactiveObject
public partial class BreakpointListViewModel : ObservableObject,
IRecipient<ToggleBreakpointMessage>
{
private readonly BreakpointManager _breakpointManager;

public ObservableCollection<BreakpointViewModel> Breakpoints { get; } = [];

public ReactiveCommand<Unit, Unit> AddBreakpointCommand { get; private set; }
public ReactiveCommand<IList, Unit> RemoveBreakpointCommand { get; private set; }

public BreakpointListViewModel(DebuggerContext debuggerContext, BreakpointManager breakpointManager)
{
_breakpointManager = breakpointManager;
Expand All @@ -25,8 +24,19 @@ public BreakpointListViewModel(DebuggerContext debuggerContext, BreakpointManage
AddBreakpoint(breakpoint);
}

AddBreakpointCommand = ReactiveCommand.Create(() => AddBreakpoint(Register.PC, 0x1000));
RemoveBreakpointCommand = ReactiveCommand.Create<IList>(RemoveBreakpoints);
WeakReferenceMessenger.Default.RegisterAll(this);
}

[RelayCommand]
private void AddBreakpoint() => AddBreakpoint(Register.PC, 0x1000);

[RelayCommand]
private void RemoveBreakpoint(IList breakpoints)
{
foreach (var breakpoint in breakpoints.OfType<BreakpointViewModel>().ToList())
{
RemoveBreakpoint(breakpoint);
}
}

private void AddBreakpoint(Breakpoint breakpoint)
Expand All @@ -35,50 +45,65 @@ private void AddBreakpoint(Breakpoint breakpoint)

Breakpoints.Add(viewModel);
_breakpointManager.AddBreakpoint(breakpoint);

WeakReferenceMessenger.Default.Send(new BreakpointAddedMessage((Word)breakpoint.Value));
}

public void AddBreakpoint(Register register, Word value)
private void AddBreakpoint(Register register, Word value)
{
var breakpoint = new Breakpoint(register, value);

AddBreakpoint(breakpoint);
}

public void RemoveBreakpoint(Register register, Word value)
private void RemoveBreakpoint(Register register, Word value)
{
var breakpoint = Breakpoints.FirstOrDefault(x =>
x.Breakpoint.Value == value &&
x.Breakpoint.Register == register);

if (breakpoint != null)
{
_breakpointManager.RemoveBreakpoint(breakpoint.Breakpoint.Id);
Breakpoints.Remove(breakpoint);
RemoveBreakpoint(breakpoint);
}
}

private void RemoveBreakpoint(BreakpointViewModel breakpoint)
{
_breakpointManager.RemoveBreakpoint(breakpoint.Id);
Breakpoints.Remove(breakpoint);

WeakReferenceMessenger.Default.Send(new BreakpointRemovedMessage(breakpoint.Breakpoint.Register, (Word)breakpoint.Breakpoint.Value));
}

public void UpdateBreakpoint(BreakpointViewModel breakpoint)
{
if (!BreakpointParser.TryParseCondition(breakpoint.Condition, out var updated))
{
return;
}

var (newRegister, newAddress) = updated.Value;
var oldAddress = breakpoint.Breakpoint.Value;

_breakpointManager.UpdateBreakpoint(
breakpoint.Breakpoint.Id,
updated.Value.Register,
updated.Value.Address,
newRegister,
newAddress,
breakpoint.IsEnabled);

Breakpoints.Replace(breakpoint, breakpoint);
WeakReferenceMessenger.Default.Send(new BreakpointUpdatedMessage(newRegister, (Word)oldAddress, (Word)newAddress));
}

private void RemoveBreakpoints(IList breakpoints)
public void Receive(ToggleBreakpointMessage message)
{
foreach (var breakpoint in breakpoints.OfType<BreakpointViewModel>().ToList())
if (message.IsEnabled)
{
AddBreakpoint(message.Register, message.Address);
}
else
{
_breakpointManager.RemoveBreakpoint(breakpoint.Id);
Breakpoints.Remove(breakpoint);
RemoveBreakpoint(message.Register, message.Address);
}
}
}
25 changes: 9 additions & 16 deletions src/Spectron.Debugger/ViewModels/BreakpointViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
using System.ComponentModel.DataAnnotations;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using OldBit.Spectron.Debugger.Breakpoints;
using ReactiveUI;
using OldBit.Spectron.Debugger.Messages;

namespace OldBit.Spectron.Debugger.ViewModels;

public class BreakpointViewModel : ReactiveObject
public partial class BreakpointViewModel : ObservableValidator
{
[ObservableProperty]
[Required(ErrorMessage = "Condition is required.")]
[CustomValidation(typeof(BreakpointViewModel), nameof(ValidateCondition))]
private string _condition = string.Empty;

[ObservableProperty]
private bool _isEnabled;

public BreakpointViewModel(Breakpoint breakpoint)
Expand All @@ -29,18 +36,4 @@ public BreakpointViewModel(Breakpoint breakpoint)
public Guid Id => Breakpoint.Id;

public Breakpoint Breakpoint { get; }

[Required(ErrorMessage = "Condition is required.")]
[CustomValidation(typeof(BreakpointViewModel), nameof(ValidateCondition))]
public string Condition
{
get => _condition;
set => this.RaiseAndSetIfChanged(ref _condition, value);
}

public bool IsEnabled
{
get => _isEnabled;
set => this.RaiseAndSetIfChanged(ref _isEnabled, value);
}
}
Loading