Skip to content

Commit edd3ff8

Browse files
authored
Add selecting methods to NodifyEditor (#156)
* Add selecting methods to NodifyEditor
1 parent 9f55f4c commit edd3ff8

File tree

8 files changed

+597
-514
lines changed

8 files changed

+597
-514
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
> - Made the setter of NodifyEditor.IsPanning private
77
> - Renamed StartCutting to BeginCutting in NodifyEditor
88
> - Renamed PushItems to UpdatePushedArea and StartPushingItems to BeginPushingItems in NodifyEditor
9+
> - Renamed UnselectAllConnection to UnselectAllConnections in NodifyEditor
910
> - Features:
1011
> - Added BeginPanning, UpdatePanning, EndPanning, CancelPanning and AllowPanningCancellation to NodifyEditor
1112
> - Added UpdateCuttingLine to NodifyEditor
13+
> - Added BeginSelecting, UpdateSelection, EndSelecting, CancelSelecting and AllowSelectionCancellation to NodifyEditor
1214
> - Bugfixes:
1315
1416
#### **Version 6.6.0**

Nodify/EditorStates/EditorCuttingState.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace Nodify
44
{
55
public class EditorCuttingState : EditorState
66
{
7-
public bool Canceled { get; set; } = CuttingLine.AllowCuttingCancellation;
7+
private bool Canceled { get; set; } = CuttingLine.AllowCuttingCancellation;
88

99
public EditorCuttingState(NodifyEditor editor) : base(editor)
1010
{

Nodify/EditorStates/EditorDefaultState.cs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System.Windows;
22
using System.Windows.Input;
3-
using static Nodify.SelectionHelper;
43

54
namespace Nodify
65
{
@@ -32,23 +31,22 @@ public EditorDefaultState(NodifyEditor editor) : base(editor)
3231
public override void HandleMouseDown(MouseButtonEventArgs e)
3332
{
3433
EditorGestures.NodifyEditorGestures gestures = EditorGestures.Mappings.Editor;
35-
if (gestures.Cutting.Matches(e.Source, e))
34+
if (Editor.CanSelectMultipleItems && gestures.Selection.Select.Matches(e.Source, e))
3635
{
37-
PushState(new EditorCuttingState(Editor));
36+
SelectionType selectionType = SelectionHelper.GetSelectionType(e);
37+
PushState(new EditorSelectingState(Editor, selectionType));
3838
}
39-
else if (gestures.PushItems.Matches(e.Source, e))
39+
else if (!Editor.DisablePanning && gestures.Pan.Matches(e.Source, e))
4040
{
41-
PushState(new EditorPushingItemsState(Editor));
41+
PushState(new EditorPanningState(Editor));
4242
}
43-
else if (gestures.Selection.Select.Matches(e.Source, e))
43+
else if (gestures.Cutting.Matches(e.Source, e))
4444
{
45-
SelectionType selectionType = GetSelectionType(e);
46-
var selecting = new EditorSelectingState(Editor, selectionType);
47-
PushState(selecting);
45+
PushState(new EditorCuttingState(Editor));
4846
}
49-
else if (!Editor.DisablePanning && gestures.Pan.Matches(e.Source, e))
47+
else if (gestures.PushItems.Matches(e.Source, e))
5048
{
51-
PushState(new EditorPanningState(Editor));
49+
PushState(new EditorPushingItemsState(Editor));
5250
}
5351
}
5452

Nodify/EditorStates/EditorPushingItemsState.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public class EditorPushingItemsState : EditorState
1010
private Point _prevPosition;
1111
private const int _minDragDistance = 10;
1212

13-
public bool Canceled { get; set; } = NodifyEditor.AllowPushItemsCancellation;
13+
private bool Canceled { get; set; } = NodifyEditor.AllowPushItemsCancellation;
1414

1515
public EditorPushingItemsState(NodifyEditor editor) : base(editor)
1616
{

Nodify/EditorStates/EditorSelectingState.cs

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,46 @@
11
using System.Windows.Input;
2-
using static Nodify.SelectionHelper;
32

43
namespace Nodify
54
{
65
/// <summary>The selecting state of the editor.</summary>
76
public class EditorSelectingState : EditorState
87
{
98
private readonly SelectionType _type;
10-
private bool _canceled;
11-
12-
/// <summary>The selection helper.</summary>
13-
protected SelectionHelper Selection { get; }
9+
private bool Canceled { get; set; } = NodifyEditor.AllowSelectionCancellation;
1410

1511
/// <summary>Constructs an instance of the <see cref="EditorSelectingState"/> state.</summary>
1612
/// <param name="editor">The owner of the state.</param>
1713
/// <param name="type">The selection strategy.</param>
1814
public EditorSelectingState(NodifyEditor editor, SelectionType type) : base(editor)
1915
{
20-
Selection = new SelectionHelper(editor);
2116
_type = type;
2217
}
2318

2419
/// <inheritdoc />
2520
public override void Enter(EditorState? from)
2621
{
27-
Editor.UnselectAllConnection();
22+
Canceled = false;
2823

29-
_canceled = false;
30-
Selection.Start(Editor.MouseLocation, _type);
24+
Editor.BeginSelecting(Editor.MouseLocation, _type);
3125
}
3226

3327
/// <inheritdoc />
3428
public override void Exit()
3529
{
36-
if (_canceled)
30+
// TODO: This is not canceled on LostMouseCapture (add OnLostMouseCapture/OnCancel callback?)
31+
if (Canceled)
3732
{
38-
Selection.Abort();
33+
Editor.CancelSelecting();
3934
}
4035
else
4136
{
42-
Selection.End();
37+
Editor.EndSelecting();
4338
}
4439
}
4540

4641
/// <inheritdoc />
47-
public override void HandleMouseMove(MouseEventArgs e)
48-
=> Selection.Update(Editor.MouseLocation);
42+
public override void HandleMouseMove(MouseEventArgs e)
43+
=> Editor.UpdateSelection(Editor.MouseLocation);
4944

5045
/// <inheritdoc />
5146
public override void HandleMouseDown(MouseButtonEventArgs e)
@@ -60,12 +55,15 @@ public override void HandleMouseDown(MouseButtonEventArgs e)
6055
public override void HandleMouseUp(MouseButtonEventArgs e)
6156
{
6257
EditorGestures.SelectionGestures gestures = EditorGestures.Mappings.Editor.Selection;
63-
64-
bool canCancel = gestures.Cancel.Matches(e.Source, e);
65-
bool canComplete = gestures.Select.Matches(e.Source, e);
66-
if (canCancel || canComplete)
58+
if(gestures.Select.Matches(e.Source, e))
6759
{
68-
_canceled = !canComplete && canCancel;
60+
PopState();
61+
}
62+
else if(NodifyEditor.AllowSelectionCancellation && gestures.Cancel.Matches(e.Source, e))
63+
{
64+
Canceled = true;
65+
e.Handled = true; // prevents opening context menu
66+
6967
PopState();
7068
}
7169
}
@@ -76,9 +74,10 @@ public override void HandleAutoPanning(MouseEventArgs e)
7674

7775
public override void HandleKeyUp(KeyEventArgs e)
7876
{
79-
if (EditorGestures.Mappings.Editor.Selection.Cancel.Matches(e.Source, e))
77+
EditorGestures.SelectionGestures gestures = EditorGestures.Mappings.Editor.Selection;
78+
if (NodifyEditor.AllowSelectionCancellation && gestures.Cancel.Matches(e.Source, e))
8079
{
81-
_canceled = true;
80+
Canceled = true;
8281
PopState();
8382
}
8483
}

Nodify/Helpers/SelectionHelper.cs

Lines changed: 44 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,81 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Linq;
34
using System.Windows;
4-
using System.Windows.Controls;
55
using System.Windows.Input;
66

77
namespace Nodify
88
{
99
/// <summary>
10-
/// Helps with selecting <see cref="ItemContainer"/>s and updating the <see cref="NodifyEditor.SelectedArea"/> and <see cref="NodifyEditor.IsSelecting"/> properties.
10+
/// Helps with selecting <see cref="ItemContainer"/>s.
1111
/// </summary>
12-
public sealed class SelectionHelper
12+
internal sealed class SelectionHelper
1313
{
14-
private readonly NodifyEditor _host;
1514
private Point _startLocation;
15+
private Point _endLocation;
1616
private SelectionType _selectionType;
1717
private bool _isRealtime;
18-
private IReadOnlyList<ItemContainer> _initialSelection = new List<ItemContainer>();
19-
20-
/// <summary>Constructs a new instance of a <see cref="SelectionHelper"/>.</summary>
21-
/// <param name="host">The editor to select items from.</param>
22-
public SelectionHelper(NodifyEditor host)
23-
=> _host = host;
24-
25-
/// <summary>Available selection logic.</summary>
26-
public enum SelectionType
27-
{
28-
/// <summary>Replaces the old selection.</summary>
29-
Replace,
30-
/// <summary>Removes items from existing selection.</summary>
31-
Remove,
32-
/// <summary>Adds items to the current selection.</summary>
33-
Append,
34-
/// <summary>Inverts the selection.</summary>
35-
Invert
36-
}
18+
private IReadOnlyCollection<ItemContainer> _items = Array.Empty<ItemContainer>();
19+
private IReadOnlyList<ItemContainer> _initialSelection = Array.Empty<ItemContainer>();
20+
private Rect _selectedArea;
3721

3822
/// <summary>Attempts to start a new selection.</summary>
23+
/// <param name="containers">The containers that can be part of the selection.</param>
3924
/// <param name="location">The location inside the graph.</param>
4025
/// <param name="selectionType">The type of selection.</param>
4126
/// <remarks>Will not do anything if selection is in progress.</remarks>
42-
public void Start(Point location, SelectionType selectionType)
27+
public Rect Start(IEnumerable<ItemContainer> containers, Point location, SelectionType selectionType, bool realtime)
4328
{
44-
if (!_host.IsSelecting)
45-
{
46-
_selectionType = selectionType;
47-
_initialSelection = _host.SelectedContainers;
29+
_items = containers.Where(x => x.IsSelectable).ToList();
30+
_initialSelection = containers.Where(x => x.IsSelected).ToList();
4831

49-
_isRealtime = _host.EnableRealtimeSelection;
50-
_startLocation = location;
32+
_selectionType = selectionType;
5133

52-
_host.SelectedArea = new Rect();
53-
_host.IsSelecting = true;
54-
}
34+
_isRealtime = realtime;
35+
_startLocation = location;
36+
_endLocation = location;
37+
38+
_selectedArea = new Rect();
39+
return _selectedArea;
5540
}
5641

5742
/// <summary>Update the end location for the selection.</summary>
5843
/// <param name="endLocation">An absolute location.</param>
59-
public void Update(Point endLocation)
44+
public Rect Update(Point endLocation)
6045
{
61-
double left = endLocation.X < _startLocation.X ? endLocation.X : _startLocation.X;
62-
double top = endLocation.Y < _startLocation.Y ? endLocation.Y : _startLocation.Y;
63-
double width = Math.Abs(endLocation.X - _startLocation.X);
64-
double height = Math.Abs(endLocation.Y - _startLocation.Y);
46+
_endLocation = endLocation;
47+
48+
double left = _endLocation.X < _startLocation.X ? _endLocation.X : _startLocation.X;
49+
double top = _endLocation.Y < _startLocation.Y ? _endLocation.Y : _startLocation.Y;
50+
double width = Math.Abs(_endLocation.X - _startLocation.X);
51+
double height = Math.Abs(_endLocation.Y - _startLocation.Y);
6552

66-
_host.SelectedArea = new Rect(left, top, width, height);
53+
_selectedArea = new Rect(left, top, width, height);
6754

6855
if (_isRealtime)
6956
{
70-
PreviewSelection(_host.SelectedArea);
57+
PreviewSelection(_selectedArea);
7158
}
59+
60+
return _selectedArea;
7261
}
7362

74-
/// <summary>Commits the current selection to the editor.</summary>
75-
public void End()
63+
/// <summary>Increase the selected area by the specified amount.</summary>
64+
public Rect Update(Vector amount)
7665
{
77-
if (_host.IsSelecting)
78-
{
79-
PreviewSelection(_host.SelectedArea);
66+
_endLocation += amount;
8067

81-
_host.ApplyPreviewingSelection();
82-
_host.IsSelecting = false;
83-
}
68+
return Update(_endLocation);
8469
}
8570

86-
/// <summary>Aborts the current selection.</summary>
87-
public void Abort()
71+
/// <summary>Commits the current selection to the editor.</summary>
72+
public Rect End()
8873
{
89-
if (_host.IsSelecting)
90-
{
91-
_host.ClearPreviewingSelection();
92-
_host.IsSelecting = false;
93-
}
74+
PreviewSelection(_selectedArea);
75+
_items = Array.Empty<ItemContainer>();
76+
_initialSelection = Array.Empty<ItemContainer>();
77+
78+
return _selectedArea;
9479
}
9580

9681
private void PreviewSelection(Rect area)
@@ -128,10 +113,8 @@ private void PreviewSelection(Rect area)
128113

129114
private void PreviewUnselectAll()
130115
{
131-
ItemCollection items = _host.Items;
132-
for (var i = 0; i < items.Count; i++)
116+
foreach (var container in _items)
133117
{
134-
var container = (ItemContainer)_host.ItemContainerGenerator.ContainerFromIndex(i);
135118
container.IsPreviewingSelection = false;
136119
}
137120
}
@@ -145,10 +128,8 @@ private void PreviewSelectArea(Rect area, bool append = false, bool fit = false)
145128

146129
if (area.X != 0 || area.Y != 0 || area.Width > 0 || area.Height > 0)
147130
{
148-
ItemCollection items = _host.Items;
149-
for (var i = 0; i < items.Count; i++)
131+
foreach (var container in _items)
150132
{
151-
var container = (ItemContainer)_host.ItemContainerGenerator.ContainerFromIndex(i);
152133
if (container.IsSelectableInArea(area, fit))
153134
{
154135
container.IsPreviewingSelection = true;
@@ -159,10 +140,8 @@ private void PreviewSelectArea(Rect area, bool append = false, bool fit = false)
159140

160141
private void PreviewUnselectArea(Rect area, bool fit = false)
161142
{
162-
ItemCollection items = _host.Items;
163-
for (var i = 0; i < items.Count; i++)
143+
foreach (var container in _items)
164144
{
165-
var container = (ItemContainer)_host.ItemContainerGenerator.ContainerFromIndex(i);
166145
if (container.IsSelectableInArea(area, fit))
167146
{
168147
container.IsPreviewingSelection = false;
@@ -180,10 +159,8 @@ private static void PreviewSelectContainers(IReadOnlyList<ItemContainer> contain
180159

181160
private void PreviewInvertSelection(Rect area, bool fit = false)
182161
{
183-
ItemCollection items = _host.Items;
184-
for (var i = 0; i < items.Count; i++)
162+
foreach (var container in _items)
185163
{
186-
var container = (ItemContainer)_host.ItemContainerGenerator.ContainerFromIndex(i);
187164
if (container.IsSelectableInArea(area, fit))
188165
{
189166
container.IsPreviewingSelection = !container.IsPreviewingSelection;

0 commit comments

Comments
 (0)