Skip to content

Commit 444f05a

Browse files
authored
Merge pull request #53 from TruePadawan/add-undo-redo-buttons
Add undo redo buttons
2 parents 3cd09ed + 9d8ee64 commit 444f05a

File tree

7 files changed

+82
-2
lines changed

7 files changed

+82
-2
lines changed

Scribble/Assets/redo-disabled.png

336 Bytes
Loading

Scribble/Assets/redo.png

296 Bytes
Loading

Scribble/Assets/undo-disabled.png

338 Bytes
Loading

Scribble/Assets/undo.png

286 Bytes
Loading

Scribble/ViewModels/MainViewModel.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,15 @@ public partial class MainViewModel : ViewModelBase
2929
public static int CanvasWidth => 10000;
3030
public static int CanvasHeight => 10000;
3131

32+
public event Action? RequestInvalidateSelection;
33+
public event Action<int>? UndoStackChanged;
34+
public event Action<int>? RedoStackChanged;
35+
3236
[ObservableProperty] private Color _backgroundColor;
3337
public ScaleTransform ScaleTransform { get; }
3438
[ObservableProperty] private List<Stroke> _canvasStrokes = [];
3539
private readonly HashSet<Guid> _deletedActions = [];
3640
public Dictionary<Guid, List<Guid>> SelectionTargets { get; private set; } = [];
37-
public event Action? RequestInvalidateSelection;
3841
public Queue<Event> CanvasEvents { get; private set; } = [];
3942

4043
private readonly CollaborativeDrawingService _collaborativeDrawingService;
@@ -134,6 +137,9 @@ private void TrackAction(Guid actionId)
134137
{
135138
_undoStack.Push(actionId);
136139
_redoStack.Clear();
140+
141+
UndoStackChanged?.Invoke(_undoStack.Count);
142+
RedoStackChanged?.Invoke(_redoStack.Count);
137143
}
138144

139145
public void Undo()
@@ -148,8 +154,11 @@ public void Undo()
148154
}
149155
}
150156

157+
UndoStackChanged?.Invoke(_undoStack.Count);
158+
151159
_redoStack.Push(actionId);
152160
ApplyEvent(new UndoEvent(Guid.NewGuid(), actionId), isLocalEvent: true);
161+
RedoStackChanged?.Invoke(_redoStack.Count);
153162
}
154163

155164
public void Redo()
@@ -164,8 +173,11 @@ public void Redo()
164173
}
165174
}
166175

176+
RedoStackChanged?.Invoke(_redoStack.Count);
177+
167178
_undoStack.Push(actionId);
168179
ApplyEvent(new RedoEvent(Guid.NewGuid(), actionId), isLocalEvent: true);
180+
UndoStackChanged?.Invoke(_undoStack.Count);
169181
}
170182

171183
public void ApplyEvent(Event @event, bool isLocalEvent = true)

Scribble/Views/MainView.axaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,5 +408,20 @@
408408
</StackPanel>
409409
</Border>
410410
</Panel>
411+
412+
<!-- Undo/Redo Buttons -->
413+
<Border CornerRadius="16"
414+
HorizontalAlignment="Left"
415+
VerticalAlignment="Bottom"
416+
Margin="8,0,0,12">
417+
<StackPanel Orientation="Horizontal">
418+
<Button ToolTip.Tip="Undo - Ctrl+Z" Name="UndoButton" Command="{Binding Undo}" IsEnabled="False">
419+
<Image Source="avares://Scribble/Assets/undo-disabled.png" Margin="4" Width="15" Height="15" />
420+
</Button>
421+
<Button ToolTip.Tip="Redo - Ctrl+Shift+Z" Name="RedoButton" Command="{Binding Redo}" IsEnabled="False">
422+
<Image Source="avares://Scribble/Assets/redo-disabled.png" Margin="4" Width="15" Height="15" />
423+
</Button>
424+
</StackPanel>
425+
</Border>
411426
</Panel>
412427
</UserControl>

Scribble/Views/MainView.axaml.cs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ public partial class MainView : UserControl
4343
private MainViewModel? _viewModel;
4444
private readonly Selection _selection;
4545
private readonly ToolOptionsValues _toolOptionsValues;
46+
private readonly Image _undoDisabledIcon;
47+
private readonly Image _undoEnabledIcon;
48+
private readonly Image _redoDisabledIcon;
49+
private readonly Image _redoEnabledIcon;
4650

4751
public MainView()
4852
{
@@ -56,13 +60,47 @@ public MainView()
5660
Bitmap.DecodeToWidth(AssetLoader.Open(new Uri("avares://Scribble/Assets/rotate.png")), 24);
5761
SelectionBorder.Cursor = new Cursor(moveIconBitmap, new PixelPoint(18, 18));
5862
SelectionRotationBtn.Cursor = new Cursor(rotateIconBitmap, new PixelPoint(12, 12));
63+
64+
_undoDisabledIcon = new Image
65+
{
66+
Source = new Bitmap(AssetLoader.Open(new Uri("avares://Scribble/Assets/undo-disabled.png"))),
67+
Width = 15,
68+
Height = 15,
69+
Margin = new Thickness(4)
70+
};
71+
72+
_undoEnabledIcon = new Image
73+
{
74+
Source = new Bitmap(AssetLoader.Open(new Uri("avares://Scribble/Assets/undo.png"))),
75+
Width = 15,
76+
Height = 15,
77+
Margin = new Thickness(4)
78+
};
79+
80+
_redoDisabledIcon = new Image
81+
{
82+
Source = new Bitmap(AssetLoader.Open(new Uri("avares://Scribble/Assets/redo-disabled.png"))),
83+
Width = 15,
84+
Height = 15,
85+
Margin = new Thickness(4)
86+
};
87+
88+
_redoEnabledIcon = new Image
89+
{
90+
Source = new Bitmap(AssetLoader.Open(new Uri("avares://Scribble/Assets/redo.png"))),
91+
Width = 15,
92+
Height = 15,
93+
Margin = new Thickness(4)
94+
};
5995
}
6096

6197
protected override void OnDataContextChanged(EventArgs e)
6298
{
6399
if (_viewModel != null)
64100
{
65101
_viewModel.RequestInvalidateSelection -= VisualizeSelection;
102+
_viewModel.UndoStackChanged -= UpdateUndoButton;
103+
_viewModel.RedoStackChanged -= UpdateRedoButton;
66104
}
67105

68106
base.OnDataContextChanged(e);
@@ -71,6 +109,8 @@ protected override void OnDataContextChanged(EventArgs e)
71109
{
72110
_viewModel = viewModel;
73111
_viewModel.RequestInvalidateSelection += VisualizeSelection;
112+
_viewModel.UndoStackChanged += UpdateUndoButton;
113+
_viewModel.RedoStackChanged += UpdateRedoButton;
74114

75115
Toolbar.Children.Clear();
76116

@@ -464,7 +504,8 @@ private void VisualizeSelection()
464504
{
465505
if (_viewModel == null) return;
466506

467-
var triggeringSelectionAction = _viewModel.CanvasEvents.Last() is EndSelectionEvent;
507+
var hasEvents = _viewModel.CanvasEvents.Count > 0;
508+
var triggeringSelectionAction = hasEvents && _viewModel.CanvasEvents.Last() is EndSelectionEvent;
468509
var allSelectedIds = _viewModel.SelectionTargets.Values.SelectMany(x => x).Distinct().ToList();
469510

470511
if (allSelectedIds.Count > 0)
@@ -1041,4 +1082,16 @@ private void AboutOption_OnClick(object? sender, RoutedEventArgs e)
10411082
AboutScribbleWindow.IsVisible = true;
10421083
AboutScribbleWindowOverlay.IsVisible = true;
10431084
}
1085+
1086+
private void UpdateUndoButton(int undoStackCount)
1087+
{
1088+
UndoButton.IsEnabled = undoStackCount > 0;
1089+
UndoButton.Content = undoStackCount > 0 ? _undoEnabledIcon : _undoDisabledIcon;
1090+
}
1091+
1092+
private void UpdateRedoButton(int redoStackCount)
1093+
{
1094+
RedoButton.IsEnabled = redoStackCount > 0;
1095+
RedoButton.Content = redoStackCount > 0 ? _redoEnabledIcon : _redoDisabledIcon;
1096+
}
10441097
}

0 commit comments

Comments
 (0)