Skip to content

Commit d87a048

Browse files
authored
Merge pull request #180 from miroiu/feature/items-moved-event
Add ItemsMoved routed event to NodifyEditor to simplify undo-redo
2 parents ff589bd + 1b86343 commit d87a048

File tree

16 files changed

+145
-56
lines changed

16 files changed

+145
-56
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717
> - Moved AllowCuttingCancellation from CuttingLine to NodifyEditor
1818
> - Moved AllowDraggingCancellation from ItemContainer to NodifyEditor
1919
> - Moved EditorGestures under the Nodify.Interactivity namespace
20+
> - Moved Editor events under the Nodify.Events namespace
2021
> - Features:
2122
> - Added BeginPanning, UpdatePanning, EndPanning, CancelPanning and AllowPanningCancellation to NodifyEditor and Minimap
2223
> - Added MouseLocation, ZoomAtPosition and GetLocationInsideMinimap to Minimap
2324
> - Added UpdateCuttingLine to NodifyEditor
2425
> - Added Select, BeginSelecting, UpdateSelection, EndSelecting, CancelSelecting and AllowSelectionCancellation to NodifyEditor
2526
> - Added IsDragging, BeginDragging, UpdateDragging, EndDragging and CancelDragging to NodifyEditor
2627
> - Added AlignSelection and AlignContainers methods to NodifyEditor
28+
> - Added ItemsMoved routed event to NodifyEditor
2729
> - Added HasCustomContextMenu dependency property to NodifyEditor, ItemContainer, Connector and BaseConnection
2830
> - Added Select, BeginDragging, UpdateDragging, EndDragging and CancelDragging to ItemContainer
2931
> - Added PreserveSelectionOnRightClick configuration field to ItemContainer

Examples/Nodify.Playground/Editor/NodifyEditorView.xaml.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Windows.Controls;
1+
using Nodify.Events;
2+
using System.Windows.Controls;
23

34
namespace Nodify.Playground
45
{

Examples/Nodify.Shapes/Canvas/CanvasView.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
ItemsDragCompletedCommand="{Binding MoveShapesCompletedCommand}"
4747
RemoveConnectionCommand="{Binding RemoveConnectionCommand}"
4848
SelectionChanged="Editor_SelectionChanged"
49+
ItemsMoved="Editor_ItemsMoved"
4950
MouseDown="Editor_MouseDown"
5051
MouseMove="Editor_MouseMove"
5152
MouseUp="Editor_MouseUp"

Examples/Nodify.Shapes/Canvas/CanvasView.xaml.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Nodify.Shapes.Canvas.UndoRedo;
1+
using Nodify.Events;
2+
using Nodify.Shapes.Canvas.UndoRedo;
23
using System;
34
using System.Collections.Generic;
45
using System.Linq;
@@ -129,5 +130,17 @@ private void Editor_SelectionChanged(object sender, SelectionChangedEventArgs e)
129130
canvasVM.UndoRedo.Record(selectNodes);
130131
}
131132
}
133+
134+
private void Editor_ItemsMoved(object sender, ItemsMovedEventArgs e)
135+
{
136+
var shapes = e.Items.Cast<ShapeViewModel>().ToList();
137+
138+
var canvasVM = (CanvasViewModel)DataContext;
139+
using (canvasVM.UndoRedo.Batch("Move shapes"))
140+
{
141+
var moveShapes = new MoveShapesAction(shapes, e.Offset);
142+
canvasVM.UndoRedo.Record(moveShapes);
143+
}
144+
}
132145
}
133146
}

Examples/Nodify.Shapes/Canvas/CanvasViewModel.cs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,11 @@ public CanvasViewModel()
7474

7575
private void MoveShapesStartedHandler()
7676
{
77-
UndoRedo.ExecuteAction(new MoveShapesAction(this));
7877
ShapeToolbar.Hide();
7978
}
8079

8180
private void MoveShapesCompletedHandler()
8281
{
83-
if (UndoRedo.Current is MoveShapesAction movesShapes)
84-
{
85-
movesShapes.SaveLocations();
86-
}
87-
8882
ShapeToolbar.Show();
8983
}
9084

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,34 @@
11
using Nodify.UndoRedo;
22
using System.Collections.Generic;
3-
using System.Linq;
43
using System.Windows;
54

65
namespace Nodify.Shapes.Canvas.UndoRedo
76
{
87
public class MoveShapesAction : IAction
98
{
10-
private readonly IReadOnlyCollection<ShapeViewModel> _movedShapes;
11-
private readonly Dictionary<ShapeViewModel, Point> _initialLocations;
12-
private Dictionary<ShapeViewModel, Point>? _finalLocations;
13-
14-
public MoveShapesAction(CanvasViewModel canvas)
15-
{
16-
_movedShapes = canvas.SelectedShapes;
17-
_initialLocations = _movedShapes.ToDictionary(x => x, x => x.Location);
18-
}
9+
private readonly IReadOnlyCollection<ShapeViewModel> _shapes;
10+
private readonly Vector _offset;
1911

2012
public string? Label => "Move shapes";
2113

22-
public void Execute()
14+
public MoveShapesAction(IReadOnlyCollection<ShapeViewModel> shapes, Vector offset)
2315
{
24-
_finalLocations?.ForEach(x => x.Key.Location = x.Value);
16+
_shapes = shapes;
17+
_offset = offset;
2518
}
2619

20+
public void Execute()
21+
=> ApplyOffset(_offset);
22+
2723
public void Undo()
28-
{
29-
_initialLocations.ForEach(x => x.Key.Location = x.Value);
30-
}
24+
=> ApplyOffset(-_offset);
3125

32-
public void SaveLocations()
26+
private void ApplyOffset(Vector offset)
3327
{
34-
_finalLocations = _movedShapes.ToDictionary(x => x, x => x.Location);
28+
foreach (var shape in _shapes)
29+
{
30+
shape.Location += offset;
31+
}
3532
}
3633
}
3734
}

Examples/Nodify.Shapes/Canvas/UndoRedo/ResizeShapesAction.cs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,21 @@ public class ResizeShapesAction : IAction
1010
private readonly IReadOnlyCollection<ShapeViewModel> _resizedShapes;
1111
private readonly Dictionary<ShapeViewModel, Size> _initialSizes;
1212
private Dictionary<ShapeViewModel, Size>? _finalSizes;
13-
14-
// Resizing could also move the shape
15-
private readonly MoveShapesAction _moveShapesAction;
13+
private readonly Dictionary<ShapeViewModel, Point> _initialLocations;
14+
private Dictionary<ShapeViewModel, Point>? _finalLocations;
1615

1716
public ResizeShapesAction(CanvasViewModel canvas)
1817
{
1918
_resizedShapes = canvas.SelectedShapes;
2019
_initialSizes = _resizedShapes.ToDictionary(x => x, x => new Size(x.Width, x.Height));
21-
22-
_moveShapesAction = new MoveShapesAction(canvas);
20+
_initialLocations = _resizedShapes.ToDictionary(x => x, x => x.Location);
2321
}
2422

2523
public string? Label => "Resize shapes";
2624

2725
public void Execute()
2826
{
29-
_moveShapesAction.Execute();
27+
_finalLocations?.ForEach(x => x.Key.Location = x.Value);
3028

3129
_finalSizes?.ForEach(x =>
3230
{
@@ -43,13 +41,12 @@ public void Undo()
4341
x.Key.Height = x.Value.Height;
4442
});
4543

46-
_moveShapesAction.Undo();
44+
_initialLocations.ForEach(x => x.Key.Location = x.Value);
4745
}
4846

4947
public void SaveSizes()
5048
{
51-
_moveShapesAction.SaveLocations();
52-
49+
_finalLocations = _resizedShapes.ToDictionary(x => x, x => x.Location);
5350
_finalSizes = _resizedShapes.ToDictionary(x => x, x => new Size(x.Width, x.Height));
5451
}
5552
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System.Windows;
2+
3+
namespace Nodify.Events
4+
{
5+
/// <summary>
6+
/// Delegate used to notify when an <see cref="ItemContainer"/> is previewing a new location.
7+
/// </summary>
8+
/// <param name="newLocation">The new location.</param>
9+
public delegate void PreviewLocationChanged(Point newLocation);
10+
}

Nodify/Containers/ItemContainer.cs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Nodify.Interactivity;
1+
using Nodify.Events;
2+
using Nodify.Interactivity;
23
using System.Windows;
34
using System.Windows.Controls;
45
using System.Windows.Controls.Primitives;
@@ -7,12 +8,6 @@
78

89
namespace Nodify
910
{
10-
/// <summary>
11-
/// Delegate used to notify when an <see cref="ItemContainer"/> is previewing a new location.
12-
/// </summary>
13-
/// <param name="newLocation">The new location.</param>
14-
public delegate void PreviewLocationChanged(Point newLocation);
15-
1611
/// <summary>
1712
/// The container for all the items generated by the <see cref="ItemsControl.ItemsSource"/> of the <see cref="NodifyEditor"/>.
1813
/// </summary>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Windows;
4+
5+
namespace Nodify.Events
6+
{
7+
/// <summary>
8+
/// Represents a method signature used to handle the <see cref="NodifyEditor.ItemsMovedEvent"/> routed event.
9+
/// </summary>
10+
/// <param name="sender">The source of the event.</param>
11+
/// <param name="e">The event data containing information about the moved items and their offset.</param>
12+
public delegate void ItemsMovedEventHandler(object sender, ItemsMovedEventArgs e);
13+
14+
/// <summary>
15+
/// Provides data for the <see cref="NodifyEditor.ItemsMovedEvent"/> routed event.
16+
/// </summary>
17+
public class ItemsMovedEventArgs : RoutedEventArgs
18+
{
19+
/// <summary>
20+
/// Initializes a new instance of the <see cref="ItemsMovedEventArgs"/> class with the specified moved items and offset.
21+
/// </summary>
22+
/// <param name="items">The collection of items that were moved.</param>
23+
/// <param name="offset">The vector representing the distance the items were moved.</param>
24+
public ItemsMovedEventArgs(IReadOnlyCollection<object> items, Vector offset)
25+
{
26+
Items = items;
27+
Offset = offset;
28+
}
29+
30+
/// <summary>
31+
/// Gets or sets the vector representing the distance the items were moved.
32+
/// </summary>
33+
public Vector Offset { get; set; }
34+
35+
/// <summary>
36+
/// Gets a collection of <see cref="FrameworkElement.DataContext"/>s of the <see cref="ItemContainer"/>s associated with this event.
37+
/// </summary>
38+
public IReadOnlyCollection<object> Items { get; }
39+
40+
protected override void InvokeEventHandler(Delegate genericHandler, object genericTarget)
41+
=> ((ItemsMovedEventHandler)genericHandler)(genericTarget, this);
42+
}
43+
}

0 commit comments

Comments
 (0)