diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5d20dc2c..b6d48668 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,9 +6,11 @@
> - Made the setter of NodifyEditor.IsPanning private
> - Renamed StartCutting to BeginCutting in NodifyEditor
> - Renamed PushItems to UpdatePushedArea and StartPushingItems to BeginPushingItems in NodifyEditor
+> - Renamed UnselectAllConnection to UnselectAllConnections in NodifyEditor
> - Features:
> - Added BeginPanning, UpdatePanning, EndPanning, CancelPanning and AllowPanningCancellation to NodifyEditor
> - Added UpdateCuttingLine to NodifyEditor
+> - Added BeginSelecting, UpdateSelection, EndSelecting, CancelSelecting and AllowSelectionCancellation to NodifyEditor
> - Bugfixes:
#### **Version 6.6.0**
diff --git a/Nodify/EditorStates/EditorCuttingState.cs b/Nodify/EditorStates/EditorCuttingState.cs
index 2bef1545..b9d6261e 100644
--- a/Nodify/EditorStates/EditorCuttingState.cs
+++ b/Nodify/EditorStates/EditorCuttingState.cs
@@ -4,7 +4,7 @@ namespace Nodify
{
public class EditorCuttingState : EditorState
{
- public bool Canceled { get; set; } = CuttingLine.AllowCuttingCancellation;
+ private bool Canceled { get; set; } = CuttingLine.AllowCuttingCancellation;
public EditorCuttingState(NodifyEditor editor) : base(editor)
{
diff --git a/Nodify/EditorStates/EditorDefaultState.cs b/Nodify/EditorStates/EditorDefaultState.cs
index bc2b35e1..eba8eed1 100644
--- a/Nodify/EditorStates/EditorDefaultState.cs
+++ b/Nodify/EditorStates/EditorDefaultState.cs
@@ -1,6 +1,5 @@
using System.Windows;
using System.Windows.Input;
-using static Nodify.SelectionHelper;
namespace Nodify
{
@@ -32,23 +31,22 @@ public EditorDefaultState(NodifyEditor editor) : base(editor)
public override void HandleMouseDown(MouseButtonEventArgs e)
{
EditorGestures.NodifyEditorGestures gestures = EditorGestures.Mappings.Editor;
- if (gestures.Cutting.Matches(e.Source, e))
+ if (Editor.CanSelectMultipleItems && gestures.Selection.Select.Matches(e.Source, e))
{
- PushState(new EditorCuttingState(Editor));
+ SelectionType selectionType = SelectionHelper.GetSelectionType(e);
+ PushState(new EditorSelectingState(Editor, selectionType));
}
- else if (gestures.PushItems.Matches(e.Source, e))
+ else if (!Editor.DisablePanning && gestures.Pan.Matches(e.Source, e))
{
- PushState(new EditorPushingItemsState(Editor));
+ PushState(new EditorPanningState(Editor));
}
- else if (gestures.Selection.Select.Matches(e.Source, e))
+ else if (gestures.Cutting.Matches(e.Source, e))
{
- SelectionType selectionType = GetSelectionType(e);
- var selecting = new EditorSelectingState(Editor, selectionType);
- PushState(selecting);
+ PushState(new EditorCuttingState(Editor));
}
- else if (!Editor.DisablePanning && gestures.Pan.Matches(e.Source, e))
+ else if (gestures.PushItems.Matches(e.Source, e))
{
- PushState(new EditorPanningState(Editor));
+ PushState(new EditorPushingItemsState(Editor));
}
}
diff --git a/Nodify/EditorStates/EditorPushingItemsState.cs b/Nodify/EditorStates/EditorPushingItemsState.cs
index 99441115..fb69c3ea 100644
--- a/Nodify/EditorStates/EditorPushingItemsState.cs
+++ b/Nodify/EditorStates/EditorPushingItemsState.cs
@@ -10,7 +10,7 @@ public class EditorPushingItemsState : EditorState
private Point _prevPosition;
private const int _minDragDistance = 10;
- public bool Canceled { get; set; } = NodifyEditor.AllowPushItemsCancellation;
+ private bool Canceled { get; set; } = NodifyEditor.AllowPushItemsCancellation;
public EditorPushingItemsState(NodifyEditor editor) : base(editor)
{
diff --git a/Nodify/EditorStates/EditorSelectingState.cs b/Nodify/EditorStates/EditorSelectingState.cs
index dd878091..d1f8c54d 100644
--- a/Nodify/EditorStates/EditorSelectingState.cs
+++ b/Nodify/EditorStates/EditorSelectingState.cs
@@ -1,5 +1,4 @@
using System.Windows.Input;
-using static Nodify.SelectionHelper;
namespace Nodify
{
@@ -7,45 +6,41 @@ namespace Nodify
public class EditorSelectingState : EditorState
{
private readonly SelectionType _type;
- private bool _canceled;
-
- /// The selection helper.
- protected SelectionHelper Selection { get; }
+ private bool Canceled { get; set; } = NodifyEditor.AllowSelectionCancellation;
/// Constructs an instance of the state.
/// The owner of the state.
/// The selection strategy.
public EditorSelectingState(NodifyEditor editor, SelectionType type) : base(editor)
{
- Selection = new SelectionHelper(editor);
_type = type;
}
///
public override void Enter(EditorState? from)
{
- Editor.UnselectAllConnection();
+ Canceled = false;
- _canceled = false;
- Selection.Start(Editor.MouseLocation, _type);
+ Editor.BeginSelecting(Editor.MouseLocation, _type);
}
///
public override void Exit()
{
- if (_canceled)
+ // TODO: This is not canceled on LostMouseCapture (add OnLostMouseCapture/OnCancel callback?)
+ if (Canceled)
{
- Selection.Abort();
+ Editor.CancelSelecting();
}
else
{
- Selection.End();
+ Editor.EndSelecting();
}
}
///
- public override void HandleMouseMove(MouseEventArgs e)
- => Selection.Update(Editor.MouseLocation);
+ public override void HandleMouseMove(MouseEventArgs e)
+ => Editor.UpdateSelection(Editor.MouseLocation);
///
public override void HandleMouseDown(MouseButtonEventArgs e)
@@ -60,12 +55,15 @@ public override void HandleMouseDown(MouseButtonEventArgs e)
public override void HandleMouseUp(MouseButtonEventArgs e)
{
EditorGestures.SelectionGestures gestures = EditorGestures.Mappings.Editor.Selection;
-
- bool canCancel = gestures.Cancel.Matches(e.Source, e);
- bool canComplete = gestures.Select.Matches(e.Source, e);
- if (canCancel || canComplete)
+ if(gestures.Select.Matches(e.Source, e))
{
- _canceled = !canComplete && canCancel;
+ PopState();
+ }
+ else if(NodifyEditor.AllowSelectionCancellation && gestures.Cancel.Matches(e.Source, e))
+ {
+ Canceled = true;
+ e.Handled = true; // prevents opening context menu
+
PopState();
}
}
@@ -76,9 +74,10 @@ public override void HandleAutoPanning(MouseEventArgs e)
public override void HandleKeyUp(KeyEventArgs e)
{
- if (EditorGestures.Mappings.Editor.Selection.Cancel.Matches(e.Source, e))
+ EditorGestures.SelectionGestures gestures = EditorGestures.Mappings.Editor.Selection;
+ if (NodifyEditor.AllowSelectionCancellation && gestures.Cancel.Matches(e.Source, e))
{
- _canceled = true;
+ Canceled = true;
PopState();
}
}
diff --git a/Nodify/Helpers/SelectionHelper.cs b/Nodify/Helpers/SelectionHelper.cs
index 2f4869bd..699a90fd 100644
--- a/Nodify/Helpers/SelectionHelper.cs
+++ b/Nodify/Helpers/SelectionHelper.cs
@@ -1,96 +1,81 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Windows;
-using System.Windows.Controls;
using System.Windows.Input;
namespace Nodify
{
///
- /// Helps with selecting s and updating the and properties.
+ /// Helps with selecting s.
///
- public sealed class SelectionHelper
+ internal sealed class SelectionHelper
{
- private readonly NodifyEditor _host;
private Point _startLocation;
+ private Point _endLocation;
private SelectionType _selectionType;
private bool _isRealtime;
- private IReadOnlyList _initialSelection = new List();
-
- /// Constructs a new instance of a .
- /// The editor to select items from.
- public SelectionHelper(NodifyEditor host)
- => _host = host;
-
- /// Available selection logic.
- public enum SelectionType
- {
- /// Replaces the old selection.
- Replace,
- /// Removes items from existing selection.
- Remove,
- /// Adds items to the current selection.
- Append,
- /// Inverts the selection.
- Invert
- }
+ private IReadOnlyCollection _items = Array.Empty();
+ private IReadOnlyList _initialSelection = Array.Empty();
+ private Rect _selectedArea;
/// Attempts to start a new selection.
+ /// The containers that can be part of the selection.
/// The location inside the graph.
/// The type of selection.
/// Will not do anything if selection is in progress.
- public void Start(Point location, SelectionType selectionType)
+ public Rect Start(IEnumerable containers, Point location, SelectionType selectionType, bool realtime)
{
- if (!_host.IsSelecting)
- {
- _selectionType = selectionType;
- _initialSelection = _host.SelectedContainers;
+ _items = containers.Where(x => x.IsSelectable).ToList();
+ _initialSelection = containers.Where(x => x.IsSelected).ToList();
- _isRealtime = _host.EnableRealtimeSelection;
- _startLocation = location;
+ _selectionType = selectionType;
- _host.SelectedArea = new Rect();
- _host.IsSelecting = true;
- }
+ _isRealtime = realtime;
+ _startLocation = location;
+ _endLocation = location;
+
+ _selectedArea = new Rect();
+ return _selectedArea;
}
/// Update the end location for the selection.
/// An absolute location.
- public void Update(Point endLocation)
+ public Rect Update(Point endLocation)
{
- double left = endLocation.X < _startLocation.X ? endLocation.X : _startLocation.X;
- double top = endLocation.Y < _startLocation.Y ? endLocation.Y : _startLocation.Y;
- double width = Math.Abs(endLocation.X - _startLocation.X);
- double height = Math.Abs(endLocation.Y - _startLocation.Y);
+ _endLocation = endLocation;
+
+ double left = _endLocation.X < _startLocation.X ? _endLocation.X : _startLocation.X;
+ double top = _endLocation.Y < _startLocation.Y ? _endLocation.Y : _startLocation.Y;
+ double width = Math.Abs(_endLocation.X - _startLocation.X);
+ double height = Math.Abs(_endLocation.Y - _startLocation.Y);
- _host.SelectedArea = new Rect(left, top, width, height);
+ _selectedArea = new Rect(left, top, width, height);
if (_isRealtime)
{
- PreviewSelection(_host.SelectedArea);
+ PreviewSelection(_selectedArea);
}
+
+ return _selectedArea;
}
- /// Commits the current selection to the editor.
- public void End()
+ /// Increase the selected area by the specified amount.
+ public Rect Update(Vector amount)
{
- if (_host.IsSelecting)
- {
- PreviewSelection(_host.SelectedArea);
+ _endLocation += amount;
- _host.ApplyPreviewingSelection();
- _host.IsSelecting = false;
- }
+ return Update(_endLocation);
}
- /// Aborts the current selection.
- public void Abort()
+ /// Commits the current selection to the editor.
+ public Rect End()
{
- if (_host.IsSelecting)
- {
- _host.ClearPreviewingSelection();
- _host.IsSelecting = false;
- }
+ PreviewSelection(_selectedArea);
+ _items = Array.Empty();
+ _initialSelection = Array.Empty();
+
+ return _selectedArea;
}
private void PreviewSelection(Rect area)
@@ -128,10 +113,8 @@ private void PreviewSelection(Rect area)
private void PreviewUnselectAll()
{
- ItemCollection items = _host.Items;
- for (var i = 0; i < items.Count; i++)
+ foreach (var container in _items)
{
- var container = (ItemContainer)_host.ItemContainerGenerator.ContainerFromIndex(i);
container.IsPreviewingSelection = false;
}
}
@@ -145,10 +128,8 @@ private void PreviewSelectArea(Rect area, bool append = false, bool fit = false)
if (area.X != 0 || area.Y != 0 || area.Width > 0 || area.Height > 0)
{
- ItemCollection items = _host.Items;
- for (var i = 0; i < items.Count; i++)
+ foreach (var container in _items)
{
- var container = (ItemContainer)_host.ItemContainerGenerator.ContainerFromIndex(i);
if (container.IsSelectableInArea(area, fit))
{
container.IsPreviewingSelection = true;
@@ -159,10 +140,8 @@ private void PreviewSelectArea(Rect area, bool append = false, bool fit = false)
private void PreviewUnselectArea(Rect area, bool fit = false)
{
- ItemCollection items = _host.Items;
- for (var i = 0; i < items.Count; i++)
+ foreach (var container in _items)
{
- var container = (ItemContainer)_host.ItemContainerGenerator.ContainerFromIndex(i);
if (container.IsSelectableInArea(area, fit))
{
container.IsPreviewingSelection = false;
@@ -180,10 +159,8 @@ private static void PreviewSelectContainers(IReadOnlyList contain
private void PreviewInvertSelection(Rect area, bool fit = false)
{
- ItemCollection items = _host.Items;
- for (var i = 0; i < items.Count; i++)
+ foreach (var container in _items)
{
- var container = (ItemContainer)_host.ItemContainerGenerator.ContainerFromIndex(i);
if (container.IsSelectableInArea(area, fit))
{
container.IsPreviewingSelection = !container.IsPreviewingSelection;
diff --git a/Nodify/NodifyEditor.Selecting.cs b/Nodify/NodifyEditor.Selecting.cs
new file mode 100644
index 00000000..cac8376a
--- /dev/null
+++ b/Nodify/NodifyEditor.Selecting.cs
@@ -0,0 +1,517 @@
+using System.Diagnostics;
+using System.Windows.Controls.Primitives;
+using System.Windows.Controls;
+using System.Windows;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Collections.Generic;
+using System.Windows.Input;
+using System.Windows.Shapes;
+
+namespace Nodify
+{
+ /// Available selection logic.
+ public enum SelectionType
+ {
+ /// Replaces the old selection.
+ Replace,
+ /// Removes items from existing selection.
+ Remove,
+ /// Adds items to the current selection.
+ Append,
+ /// Inverts the selection.
+ Invert
+ }
+
+ [StyleTypedProperty(Property = nameof(SelectionRectangleStyle), StyleTargetType = typeof(Rectangle))]
+ public partial class NodifyEditor : MultiSelector
+ {
+ public static readonly DependencyProperty ItemsSelectStartedCommandProperty = DependencyProperty.Register(nameof(ItemsSelectStartedCommand), typeof(ICommand), typeof(NodifyEditor));
+ public static readonly DependencyProperty ItemsSelectCompletedCommandProperty = DependencyProperty.Register(nameof(ItemsSelectCompletedCommand), typeof(ICommand), typeof(NodifyEditor));
+
+ public static readonly DependencyProperty SelectionRectangleStyleProperty = DependencyProperty.Register(nameof(SelectionRectangleStyle), typeof(Style), typeof(NodifyEditor));
+
+ protected static readonly DependencyPropertyKey SelectedAreaPropertyKey = DependencyProperty.RegisterReadOnly(nameof(SelectedArea), typeof(Rect), typeof(NodifyEditor), new FrameworkPropertyMetadata(BoxValue.Rect));
+ public static readonly DependencyProperty SelectedAreaProperty = SelectedAreaPropertyKey.DependencyProperty;
+
+ protected static readonly DependencyPropertyKey IsSelectingPropertyKey = DependencyProperty.RegisterReadOnly(nameof(IsSelecting), typeof(bool), typeof(NodifyEditor), new FrameworkPropertyMetadata(BoxValue.False, OnIsSelectingChanged));
+ public static readonly DependencyProperty IsSelectingProperty = IsSelectingPropertyKey.DependencyProperty;
+
+ public static readonly DependencyProperty EnableRealtimeSelectionProperty = DependencyProperty.Register(nameof(EnableRealtimeSelection), typeof(bool), typeof(NodifyEditor), new FrameworkPropertyMetadata(BoxValue.False));
+ public static readonly DependencyProperty CanSelectMultipleConnectionsProperty = DependencyProperty.Register(nameof(CanSelectMultipleConnections), typeof(bool), typeof(NodifyEditor), new FrameworkPropertyMetadata(BoxValue.True));
+ public static readonly DependencyProperty CanSelectMultipleItemsProperty = DependencyProperty.Register(nameof(CanSelectMultipleItems), typeof(bool), typeof(NodifyEditor), new FrameworkPropertyMetadata(BoxValue.True, OnCanSelectMultipleItemsChanged, CoerceCanSelectMultipleItems));
+ public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register(nameof(SelectedItems), typeof(IList), typeof(NodifyEditor), new FrameworkPropertyMetadata(default(IList), OnSelectedItemsSourceChanged));
+ public static readonly DependencyProperty SelectedConnectionsProperty = DependencyProperty.Register(nameof(SelectedConnections), typeof(IList), typeof(NodifyEditor), new FrameworkPropertyMetadata(default(IList)));
+ public static readonly DependencyProperty SelectedConnectionProperty = DependencyProperty.Register(nameof(SelectedConnection), typeof(object), typeof(NodifyEditor), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
+
+ private static void OnCanSelectMultipleItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ => ((NodifyEditor)d).CanSelectMultipleItemsBase = (bool)e.NewValue;
+
+ private static object CoerceCanSelectMultipleItems(DependencyObject d, object baseValue)
+ => ((NodifyEditor)d).CanSelectMultipleItemsBase = (bool)baseValue;
+
+ private static void OnSelectedItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ => ((NodifyEditor)d).OnSelectedItemsSourceChanged((IList)e.OldValue, (IList)e.NewValue);
+
+ private static void OnIsSelectingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var editor = (NodifyEditor)d;
+ if ((bool)e.NewValue == true)
+ editor.OnItemsSelectStarted();
+ else
+ editor.OnItemsSelectCompleted();
+ }
+
+ private void OnItemsSelectCompleted()
+ {
+ if (ItemsSelectCompletedCommand?.CanExecute(DataContext) ?? false)
+ ItemsSelectCompletedCommand.Execute(DataContext);
+ }
+
+ private void OnItemsSelectStarted()
+ {
+ if (ItemsSelectStartedCommand?.CanExecute(DataContext) ?? false)
+ ItemsSelectStartedCommand.Execute(DataContext);
+ }
+
+ /// Invoked when a selection operation is started.
+ public ICommand? ItemsSelectStartedCommand
+ {
+ get => (ICommand?)GetValue(ItemsSelectStartedCommandProperty);
+ set => SetValue(ItemsSelectStartedCommandProperty, value);
+ }
+
+ /// Invoked when a selection operation is completed.
+ public ICommand? ItemsSelectCompletedCommand
+ {
+ get => (ICommand?)GetValue(ItemsSelectCompletedCommandProperty);
+ set => SetValue(ItemsSelectCompletedCommandProperty, value);
+ }
+
+ ///
+ /// Gets or sets whether multiple connections can be selected.
+ ///
+ public bool CanSelectMultipleConnections
+ {
+ get => (bool)GetValue(CanSelectMultipleConnectionsProperty);
+ set => SetValue(CanSelectMultipleConnectionsProperty, value);
+ }
+
+ ///
+ /// Gets or sets whether multiple s can be selected.
+ ///
+ public new bool CanSelectMultipleItems
+ {
+ get => (bool)GetValue(CanSelectMultipleItemsProperty);
+ set => SetValue(CanSelectMultipleItemsProperty, value);
+ }
+
+ private bool CanSelectMultipleItemsBase
+ {
+ get => base.CanSelectMultipleItems;
+ set => base.CanSelectMultipleItems = value;
+ }
+
+ ///
+ /// Enables selecting and deselecting items while the changes.
+ /// Disable for maximum performance when hundreds of items are generated.
+ ///
+ public bool EnableRealtimeSelection
+ {
+ get => (bool)GetValue(EnableRealtimeSelectionProperty);
+ set => SetValue(EnableRealtimeSelectionProperty, value);
+ }
+
+ ///
+ /// Gets or sets the selected connection.
+ ///
+ public object? SelectedConnection
+ {
+ get => GetValue(SelectedConnectionProperty);
+ set => SetValue(SelectedConnectionProperty, value);
+ }
+
+ ///
+ /// Gets or sets the selected connections in the .
+ ///
+ public IList? SelectedConnections
+ {
+ get => (IList?)GetValue(SelectedConnectionsProperty);
+ set => SetValue(SelectedConnectionsProperty, value);
+ }
+
+ ///
+ /// Gets or sets the selected items in the .
+ ///
+ public new IList? SelectedItems
+ {
+ get => (IList?)GetValue(SelectedItemsProperty);
+ set => SetValue(SelectedItemsProperty, value);
+ }
+
+ ///
+ /// Gets the currently selected area while is true.
+ ///
+ public Rect SelectedArea
+ {
+ get => (Rect)GetValue(SelectedAreaProperty);
+ private set => SetValue(SelectedAreaPropertyKey, value);
+ }
+
+ ///
+ /// Gets a value that indicates whether a selection operation is in progress.
+ ///
+ public bool IsSelecting
+ {
+ get => (bool)GetValue(IsSelectingProperty);
+ private set => SetValue(IsSelectingPropertyKey, value);
+ }
+
+ ///
+ /// Gets or sets the style to use for the selection rectangle.
+ ///
+ public Style SelectionRectangleStyle
+ {
+ get => (Style)GetValue(SelectionRectangleStyleProperty);
+ set => SetValue(SelectionRectangleStyleProperty, value);
+ }
+
+ ///
+ /// Gets a list of s that are selected.
+ ///
+ /// Cache the result before using it to avoid extra allocations.
+ protected internal IReadOnlyList SelectedContainers
+ {
+ get
+ {
+ IList selectedItems = base.SelectedItems;
+ var selectedContainers = new List(selectedItems.Count);
+
+ for (var i = 0; i < selectedItems.Count; i++)
+ {
+ var container = (ItemContainer)ItemContainerGenerator.ContainerFromItem(selectedItems[i]);
+ selectedContainers.Add(container);
+ }
+
+ return selectedContainers;
+ }
+ }
+
+ ///
+ /// Gets or sets whether cancelling a selection operation is allowed (see ).
+ ///
+ public static bool AllowSelectionCancellation { get; set; } = true;
+
+ /// The selection helper.
+ private readonly SelectionHelper _selection = new SelectionHelper();
+
+ #region Selection
+
+ internal void ApplyPreviewingSelection()
+ {
+ Debug.Assert(IsSelecting);
+
+ ItemCollection items = Items;
+ IList selected = base.SelectedItems;
+
+ BeginUpdateSelectedItems();
+ for (var i = 0; i < items.Count; i++)
+ {
+ var container = (ItemContainer)ItemContainerGenerator.ContainerFromIndex(i);
+ if (container.IsPreviewingSelection == true && container.IsSelectable)
+ {
+ selected.Add(items[i]);
+ }
+ else if (container.IsPreviewingSelection == false)
+ {
+ selected.Remove(items[i]);
+ }
+ container.IsPreviewingSelection = null;
+ }
+ EndUpdateSelectedItems();
+ }
+
+ internal void ClearPreviewingSelection()
+ {
+ Debug.Assert(IsSelecting);
+
+ ItemCollection items = Items;
+ for (var i = 0; i < items.Count; i++)
+ {
+ var container = (ItemContainer)ItemContainerGenerator.ContainerFromIndex(i);
+ container.IsPreviewingSelection = null;
+ }
+ }
+
+ ///
+ /// Inverts the s selection in the specified .
+ ///
+ /// The area to look for s.
+ /// True to check if the contains the .
False to check if intersects the .
+ public void InvertSelection(Rect area, bool fit = false)
+ {
+ ItemCollection items = Items;
+ IList selected = base.SelectedItems;
+
+ IsSelecting = true;
+ BeginUpdateSelectedItems();
+ for (var i = 0; i < items.Count; i++)
+ {
+ var container = (ItemContainer)ItemContainerGenerator.ContainerFromIndex(i);
+
+ if (container.IsSelectableInArea(area, fit))
+ {
+ object? item = items[i];
+ if (container.IsSelected)
+ {
+ selected.Remove(item);
+ }
+ else
+ {
+ selected.Add(item);
+ }
+ }
+ }
+ EndUpdateSelectedItems();
+ IsSelecting = false;
+ }
+
+ ///
+ /// Selects the s in the specified .
+ ///
+ /// The area to look for s.
+ /// If true, it will add to the existing selection.
+ /// True to check if the contains the .
False to check if intersects the .
+ public void SelectArea(Rect area, bool append = false, bool fit = false)
+ {
+ if (!append)
+ {
+ UnselectAll();
+ }
+
+ ItemCollection items = Items;
+ IList selected = base.SelectedItems;
+
+ IsSelecting = true;
+ BeginUpdateSelectedItems();
+ for (var i = 0; i < items.Count; i++)
+ {
+ var container = (ItemContainer)ItemContainerGenerator.ContainerFromIndex(i);
+ if (container.IsSelectableInArea(area, fit))
+ {
+ selected.Add(items[i]);
+ }
+ }
+ EndUpdateSelectedItems();
+ IsSelecting = false;
+ }
+
+ ///
+ /// Unselect the s in the specified .
+ ///
+ /// The area to look for s.
+ /// True to check if the contains the .
False to check if intersects the .
+ public void UnselectArea(Rect area, bool fit = false)
+ {
+ IList items = base.SelectedItems;
+
+ IsSelecting = true;
+ BeginUpdateSelectedItems();
+ for (var i = 0; i < items.Count; i++)
+ {
+ var container = (ItemContainer)ItemContainerGenerator.ContainerFromItem(items[i]);
+ if (container.IsSelectableInArea(area, fit))
+ {
+ items.Remove(items[i]);
+ }
+ }
+ EndUpdateSelectedItems();
+ IsSelecting = false;
+ }
+
+ ///
+ /// Unselect all .
+ ///
+ public void UnselectAllConnections()
+ {
+ if (ConnectionsHost is MultiSelector selector)
+ {
+ selector.UnselectAll();
+ }
+ }
+
+ ///
+ /// Select all .
+ ///
+ public void SelectAllConnections()
+ {
+ if (ConnectionsHost is MultiSelector selector)
+ {
+ selector.SelectAll();
+ }
+ }
+ ///
+ /// Initiates a selection operation from the specified location.
+ ///
+ /// This method has no effect if a selection operation is already in progress.
+ /// The starting point for the selection, in graph space coordinates.
+ /// The type of selection to perform. Defaults to .
+ public void BeginSelecting(Point location, SelectionType type = SelectionType.Replace)
+ {
+ if (IsSelecting)
+ {
+ return;
+ }
+
+ UnselectAllConnections();
+ SelectedArea = _selection.Start(ItemContainers, location, type, EnableRealtimeSelection);
+ IsSelecting = true;
+ }
+
+ ///
+ /// Expands or modifies the selection area by the specified amount.
+ ///
+ /// Rrepresents the change to apply to the selection area.
+ public void UpdateSelection(Vector amount)
+ {
+ Debug.Assert(IsSelecting);
+ SelectedArea = _selection.Update(amount);
+ }
+
+ ///
+ /// Expands or modifies the selection area to the specified location.
+ ///
+ /// The point, in graph space coordinates, to extend or adjust the selection area to.
+ public void UpdateSelection(Point location)
+ {
+ Debug.Assert(IsSelecting);
+ SelectedArea = _selection.Update(location);
+ }
+
+ ///
+ /// Completes the selection operation and applies any pending changes.
+ ///
+ /// This method has no effect if there's no selection operation in progress.
+ public void EndSelecting()
+ {
+ if (!IsSelecting)
+ {
+ return;
+ }
+
+ SelectedArea = _selection.End();
+ ApplyPreviewingSelection();
+ IsSelecting = false;
+ }
+
+ ///
+ /// Cancels the current selection operation and reverts any changes made during the selection process.
+ ///
+ /// This method has no effect if there's no selection operation in progress.
+ public void CancelSelecting()
+ {
+ if (!IsSelecting)
+ {
+ return;
+ }
+
+ ClearPreviewingSelection();
+ IsSelecting = false;
+ }
+
+ #endregion
+
+ #region Selection Handlers
+
+ private void OnSelectedItemsSourceChanged(IList oldValue, IList newValue)
+ {
+ if (oldValue is INotifyCollectionChanged oc)
+ {
+ oc.CollectionChanged -= OnSelectedItemsChanged;
+ }
+
+ if (newValue is INotifyCollectionChanged nc)
+ {
+ nc.CollectionChanged += OnSelectedItemsChanged;
+ }
+
+ IList selectedItems = base.SelectedItems;
+
+ BeginUpdateSelectedItems();
+ selectedItems.Clear();
+ if (newValue != null)
+ {
+ for (var i = 0; i < newValue.Count; i++)
+ {
+ selectedItems.Add(newValue[i]);
+ }
+ }
+ EndUpdateSelectedItems();
+ }
+
+ private void OnSelectedItemsChanged(object? sender, NotifyCollectionChangedEventArgs e)
+ {
+ if (!CanSelectMultipleItems)
+ return;
+
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Reset:
+ base.SelectedItems.Clear();
+ break;
+
+ case NotifyCollectionChangedAction.Add:
+ IList? newItems = e.NewItems;
+ if (newItems != null)
+ {
+ IList selectedItems = base.SelectedItems;
+ for (var i = 0; i < newItems.Count; i++)
+ {
+ selectedItems.Add(newItems[i]);
+ }
+ }
+ break;
+
+ case NotifyCollectionChangedAction.Remove:
+ IList? oldItems = e.OldItems;
+ if (oldItems != null)
+ {
+ IList selectedItems = base.SelectedItems;
+ for (var i = 0; i < oldItems.Count; i++)
+ {
+ selectedItems.Remove(oldItems[i]);
+ }
+ }
+ break;
+ }
+ }
+
+ ///
+ protected override void OnSelectionChanged(SelectionChangedEventArgs e)
+ {
+ base.OnSelectionChanged(e);
+
+ IList? selected = SelectedItems;
+ if (selected != null)
+ {
+ IList added = e.AddedItems;
+ for (var i = 0; i < added.Count; i++)
+ {
+ // Ensure no duplicates are added
+ if (!selected.Contains(added[i]))
+ {
+ selected.Add(added[i]);
+ }
+ }
+
+ IList removed = e.RemovedItems;
+ for (var i = 0; i < removed.Count; i++)
+ {
+ selected.Remove(removed[i]);
+ }
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/Nodify/NodifyEditor.cs b/Nodify/NodifyEditor.cs
index 1f1a7b87..6902532b 100644
--- a/Nodify/NodifyEditor.cs
+++ b/Nodify/NodifyEditor.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Collections.Specialized;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
@@ -9,7 +8,6 @@
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
-using System.Windows.Shapes;
namespace Nodify
{
@@ -20,10 +18,9 @@ namespace Nodify
[TemplatePart(Name = ElementConnectionsHost, Type = typeof(FrameworkElement))]
[StyleTypedProperty(Property = nameof(ItemContainerStyle), StyleTargetType = typeof(ItemContainer))]
[StyleTypedProperty(Property = nameof(DecoratorContainerStyle), StyleTargetType = typeof(DecoratorContainer))]
- [StyleTypedProperty(Property = nameof(SelectionRectangleStyle), StyleTargetType = typeof(Rectangle))]
[ContentProperty(nameof(Decorators))]
[DefaultProperty(nameof(Decorators))]
- public partial class NodifyEditor : MultiSelector
+ public partial class NodifyEditor
{
protected const string ElementItemsHost = "PART_ItemsHost";
protected const string ElementConnectionsHost = "PART_ConnectionsHost";
@@ -250,7 +247,6 @@ private void ApplyRenderingOptimizations()
public static readonly DependencyProperty ConnectionTemplateProperty = DependencyProperty.Register(nameof(ConnectionTemplate), typeof(DataTemplate), typeof(NodifyEditor));
public static readonly DependencyProperty DecoratorTemplateProperty = DependencyProperty.Register(nameof(DecoratorTemplate), typeof(DataTemplate), typeof(NodifyEditor));
public static readonly DependencyProperty PendingConnectionTemplateProperty = DependencyProperty.Register(nameof(PendingConnectionTemplate), typeof(DataTemplate), typeof(NodifyEditor));
- public static readonly DependencyProperty SelectionRectangleStyleProperty = DependencyProperty.Register(nameof(SelectionRectangleStyle), typeof(Style), typeof(NodifyEditor));
public static readonly DependencyProperty DecoratorContainerStyleProperty = DependencyProperty.Register(nameof(DecoratorContainerStyle), typeof(Style), typeof(NodifyEditor));
///
@@ -308,15 +304,6 @@ public DataTemplate PendingConnectionTemplate
set => SetValue(PendingConnectionTemplateProperty, value);
}
- ///
- /// Gets or sets the style to use for the selection rectangle.
- ///
- public Style SelectionRectangleStyle
- {
- get => (Style)GetValue(SelectionRectangleStyleProperty);
- set => SetValue(SelectionRectangleStyleProperty, value);
- }
-
///
/// Gets or sets the style to use for the .
///
@@ -330,54 +317,9 @@ public Style DecoratorContainerStyle
#region Readonly Dependency Properties
- protected static readonly DependencyPropertyKey SelectedAreaPropertyKey = DependencyProperty.RegisterReadOnly(nameof(SelectedArea), typeof(Rect), typeof(NodifyEditor), new FrameworkPropertyMetadata(BoxValue.Rect));
- public static readonly DependencyProperty SelectedAreaProperty = SelectedAreaPropertyKey.DependencyProperty;
-
- protected static readonly DependencyPropertyKey IsSelectingPropertyKey = DependencyProperty.RegisterReadOnly(nameof(IsSelecting), typeof(bool), typeof(NodifyEditor), new FrameworkPropertyMetadata(BoxValue.False, OnIsSelectingChanged));
- public static readonly DependencyProperty IsSelectingProperty = IsSelectingPropertyKey.DependencyProperty;
-
protected static readonly DependencyPropertyKey MouseLocationPropertyKey = DependencyProperty.RegisterReadOnly(nameof(MouseLocation), typeof(Point), typeof(NodifyEditor), new FrameworkPropertyMetadata(BoxValue.Point));
public static readonly DependencyProperty MouseLocationProperty = MouseLocationPropertyKey.DependencyProperty;
- private static void OnIsSelectingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var editor = (NodifyEditor)d;
- if ((bool)e.NewValue == true)
- editor.OnItemsSelectStarted();
- else
- editor.OnItemsSelectCompleted();
- }
-
- private void OnItemsSelectCompleted()
- {
- if (ItemsSelectCompletedCommand?.CanExecute(DataContext) ?? false)
- ItemsSelectCompletedCommand.Execute(DataContext);
- }
-
- private void OnItemsSelectStarted()
- {
- if (ItemsSelectStartedCommand?.CanExecute(DataContext) ?? false)
- ItemsSelectStartedCommand.Execute(DataContext);
- }
-
- ///
- /// Gets the currently selected area while is true.
- ///
- public Rect SelectedArea
- {
- get => (Rect)GetValue(SelectedAreaProperty);
- internal set => SetValue(SelectedAreaPropertyKey, value);
- }
-
- ///
- /// Gets a value that indicates whether a selection operation is in progress.
- ///
- public bool IsSelecting
- {
- get => (bool)GetValue(IsSelectingProperty);
- internal set => SetValue(IsSelectingPropertyKey, value);
- }
-
///
/// Gets the current mouse location in graph space coordinates (relative to the ).
///
@@ -392,25 +334,10 @@ public Point MouseLocation
#region Dependency Properties
public static readonly DependencyProperty ConnectionsProperty = DependencyProperty.Register(nameof(Connections), typeof(IEnumerable), typeof(NodifyEditor));
- public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register(nameof(SelectedItems), typeof(IList), typeof(NodifyEditor), new FrameworkPropertyMetadata(default(IList), OnSelectedItemsSourceChanged));
- public static readonly DependencyProperty SelectedConnectionsProperty = DependencyProperty.Register(nameof(SelectedConnections), typeof(IList), typeof(NodifyEditor), new FrameworkPropertyMetadata(default(IList)));
- public static readonly DependencyProperty SelectedConnectionProperty = DependencyProperty.Register(nameof(SelectedConnection), typeof(object), typeof(NodifyEditor), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public static readonly DependencyProperty PendingConnectionProperty = DependencyProperty.Register(nameof(PendingConnection), typeof(object), typeof(NodifyEditor));
public static readonly DependencyProperty GridCellSizeProperty = DependencyProperty.Register(nameof(GridCellSize), typeof(uint), typeof(NodifyEditor), new FrameworkPropertyMetadata(BoxValue.UInt1, OnGridCellSizeChanged, OnCoerceGridCellSize));
public static readonly DependencyProperty DisableZoomingProperty = DependencyProperty.Register(nameof(DisableZooming), typeof(bool), typeof(NodifyEditor), new FrameworkPropertyMetadata(BoxValue.False));
- public static readonly DependencyProperty EnableRealtimeSelectionProperty = DependencyProperty.Register(nameof(EnableRealtimeSelection), typeof(bool), typeof(NodifyEditor), new FrameworkPropertyMetadata(BoxValue.False));
public static readonly DependencyProperty DecoratorsProperty = DependencyProperty.Register(nameof(Decorators), typeof(IEnumerable), typeof(NodifyEditor));
- public static readonly DependencyProperty CanSelectMultipleConnectionsProperty = DependencyProperty.Register(nameof(CanSelectMultipleConnections), typeof(bool), typeof(NodifyEditor), new FrameworkPropertyMetadata(BoxValue.True));
- public static readonly DependencyProperty CanSelectMultipleItemsProperty = DependencyProperty.Register(nameof(CanSelectMultipleItems), typeof(bool), typeof(NodifyEditor), new FrameworkPropertyMetadata(BoxValue.True, OnCanSelectMultipleItemsChanged, CoerceCanSelectMultipleItems));
-
- private static void OnCanSelectMultipleItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- => ((NodifyEditor)d).CanSelectMultipleItemsBase = (bool)e.NewValue;
-
- private static object CoerceCanSelectMultipleItems(DependencyObject d, object baseValue)
- => ((NodifyEditor)d).CanSelectMultipleItemsBase = (bool)baseValue;
-
- private static void OnSelectedItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- => ((NodifyEditor)d).OnSelectedItemsSourceChanged((IList)e.OldValue, (IList)e.NewValue);
private static object OnCoerceGridCellSize(DependencyObject d, object value)
=> (uint)value > 0u ? value : BoxValue.UInt1;
@@ -453,33 +380,6 @@ public object PendingConnection
set => SetValue(PendingConnectionProperty, value);
}
- ///
- /// Gets or sets the selected connection.
- ///
- public object? SelectedConnection
- {
- get => GetValue(SelectedConnectionProperty);
- set => SetValue(SelectedConnectionProperty, value);
- }
-
- ///
- /// Gets or sets the selected connections in the .
- ///
- public IList? SelectedConnections
- {
- get => (IList?)GetValue(SelectedConnectionsProperty);
- set => SetValue(SelectedConnectionsProperty, value);
- }
-
- ///
- /// Gets or sets the selected items in the .
- ///
- public new IList? SelectedItems
- {
- get => (IList?)GetValue(SelectedItemsProperty);
- set => SetValue(SelectedItemsProperty, value);
- }
-
///
/// Gets or sets whether zooming should be disabled.
///
@@ -489,40 +389,6 @@ public bool DisableZooming
set => SetValue(DisableZoomingProperty, value);
}
- ///
- /// Enables selecting and deselecting items while the changes.
- /// Disable for maximum performance when hundreds of items are generated.
- ///
- public bool EnableRealtimeSelection
- {
- get => (bool)GetValue(EnableRealtimeSelectionProperty);
- set => SetValue(EnableRealtimeSelectionProperty, value);
- }
-
- ///
- /// Gets or sets whether multiple connections can be selected.
- ///
- public bool CanSelectMultipleConnections
- {
- get => (bool)GetValue(CanSelectMultipleConnectionsProperty);
- set => SetValue(CanSelectMultipleConnectionsProperty, value);
- }
-
- ///
- /// Gets or sets whether multiple s can be selected.
- ///
- public new bool CanSelectMultipleItems
- {
- get => (bool)GetValue(CanSelectMultipleItemsProperty);
- set => SetValue(CanSelectMultipleItemsProperty, value);
- }
-
- private bool CanSelectMultipleItemsBase
- {
- get => base.CanSelectMultipleItems;
- set => base.CanSelectMultipleItems = value;
- }
-
#endregion
#region Command Dependency Properties
@@ -533,8 +399,6 @@ private bool CanSelectMultipleItemsBase
public static readonly DependencyProperty RemoveConnectionCommandProperty = DependencyProperty.Register(nameof(RemoveConnectionCommand), typeof(ICommand), typeof(NodifyEditor));
public static readonly DependencyProperty ItemsDragStartedCommandProperty = DependencyProperty.Register(nameof(ItemsDragStartedCommand), typeof(ICommand), typeof(NodifyEditor));
public static readonly DependencyProperty ItemsDragCompletedCommandProperty = DependencyProperty.Register(nameof(ItemsDragCompletedCommand), typeof(ICommand), typeof(NodifyEditor));
- public static readonly DependencyProperty ItemsSelectStartedCommandProperty = DependencyProperty.Register(nameof(ItemsSelectStartedCommand), typeof(ICommand), typeof(NodifyEditor));
- public static readonly DependencyProperty ItemsSelectCompletedCommandProperty = DependencyProperty.Register(nameof(ItemsSelectCompletedCommand), typeof(ICommand), typeof(NodifyEditor));
///
/// Invoked when the is completed.
@@ -581,7 +445,7 @@ public ICommand? RemoveConnectionCommand
}
///
- /// Invoked when a drag operation starts for the .
+ /// Invoked when a drag operation starts for the , or when is set to true.
///
public ICommand? ItemsDragStartedCommand
{
@@ -590,7 +454,7 @@ public ICommand? ItemsDragStartedCommand
}
///
- /// Invoked when a drag operation is completed for the .
+ /// Invoked when a drag operation is completed for the , or when is set to false.
///
public ICommand? ItemsDragCompletedCommand
{
@@ -598,20 +462,6 @@ public ICommand? ItemsDragCompletedCommand
set => SetValue(ItemsDragCompletedCommandProperty, value);
}
- /// Invoked when a selection operation is started.
- public ICommand? ItemsSelectStartedCommand
- {
- get => (ICommand?)GetValue(ItemsSelectStartedCommandProperty);
- set => SetValue(ItemsSelectStartedCommandProperty, value);
- }
-
- /// Invoked when a selection operation is completed.
- public ICommand? ItemsSelectCompletedCommand
- {
- get => (ICommand?)GetValue(ItemsSelectCompletedCommandProperty);
- set => SetValue(ItemsSelectCompletedCommandProperty, value);
- }
-
#endregion
#region Fields
@@ -664,27 +514,6 @@ public ICommand? ItemsSelectCompletedCommand
private IDraggingStrategy? _draggingStrategy;
- ///
- /// Gets a list of s that are selected.
- ///
- /// Cache the result before using it to avoid extra allocations.
- protected internal IReadOnlyList SelectedContainers
- {
- get
- {
- IList selectedItems = base.SelectedItems;
- var selectedContainers = new List(selectedItems.Count);
-
- for (var i = 0; i < selectedItems.Count; i++)
- {
- var container = (ItemContainer)ItemContainerGenerator.ContainerFromItem(selectedItems[i]);
- selectedContainers.Add(container);
- }
-
- return selectedContainers;
- }
- }
-
///
/// Gets a list of all s.
///
@@ -1041,245 +870,6 @@ protected override void OnKeyDown(KeyEventArgs e)
#endregion
- #region Selection Handlers
-
- private void OnSelectedItemsSourceChanged(IList oldValue, IList newValue)
- {
- if (oldValue is INotifyCollectionChanged oc)
- {
- oc.CollectionChanged -= OnSelectedItemsChanged;
- }
-
- if (newValue is INotifyCollectionChanged nc)
- {
- nc.CollectionChanged += OnSelectedItemsChanged;
- }
-
- IList selectedItems = base.SelectedItems;
-
- BeginUpdateSelectedItems();
- selectedItems.Clear();
- if (newValue != null)
- {
- for (var i = 0; i < newValue.Count; i++)
- {
- selectedItems.Add(newValue[i]);
- }
- }
- EndUpdateSelectedItems();
- }
-
- private void OnSelectedItemsChanged(object? sender, NotifyCollectionChangedEventArgs e)
- {
- if (!CanSelectMultipleItems)
- return;
-
- switch (e.Action)
- {
- case NotifyCollectionChangedAction.Reset:
- base.SelectedItems.Clear();
- break;
-
- case NotifyCollectionChangedAction.Add:
- IList? newItems = e.NewItems;
- if (newItems != null)
- {
- IList selectedItems = base.SelectedItems;
- for (var i = 0; i < newItems.Count; i++)
- {
- selectedItems.Add(newItems[i]);
- }
- }
- break;
-
- case NotifyCollectionChangedAction.Remove:
- IList? oldItems = e.OldItems;
- if (oldItems != null)
- {
- IList selectedItems = base.SelectedItems;
- for (var i = 0; i < oldItems.Count; i++)
- {
- selectedItems.Remove(oldItems[i]);
- }
- }
- break;
- }
- }
-
- ///
- protected override void OnSelectionChanged(SelectionChangedEventArgs e)
- {
- base.OnSelectionChanged(e);
-
- IList? selected = SelectedItems;
- if (selected != null)
- {
- IList added = e.AddedItems;
- for (var i = 0; i < added.Count; i++)
- {
- // Ensure no duplicates are added
- if (!selected.Contains(added[i]))
- {
- selected.Add(added[i]);
- }
- }
-
- IList removed = e.RemovedItems;
- for (var i = 0; i < removed.Count; i++)
- {
- selected.Remove(removed[i]);
- }
- }
- }
-
- #endregion
-
- #region Selection
-
- internal void ApplyPreviewingSelection()
- {
- ItemCollection items = Items;
- IList selected = base.SelectedItems;
-
- IsSelecting = true;
- BeginUpdateSelectedItems();
- for (var i = 0; i < items.Count; i++)
- {
- var container = (ItemContainer)ItemContainerGenerator.ContainerFromIndex(i);
- if (container.IsPreviewingSelection == true && container.IsSelectable)
- {
- selected.Add(items[i]);
- }
- else if (container.IsPreviewingSelection == false)
- {
- selected.Remove(items[i]);
- }
- container.IsPreviewingSelection = null;
- }
- EndUpdateSelectedItems();
- IsSelecting = false;
- }
-
- internal void ClearPreviewingSelection()
- {
- ItemCollection items = Items;
- for (var i = 0; i < items.Count; i++)
- {
- var container = (ItemContainer)ItemContainerGenerator.ContainerFromIndex(i);
- container.IsPreviewingSelection = null;
- }
- }
-
- ///
- /// Inverts the s selection in the specified .
- ///
- /// The area to look for s.
- /// True to check if the contains the .
False to check if intersects the .
- public void InvertSelection(Rect area, bool fit = false)
- {
- ItemCollection items = Items;
- IList selected = base.SelectedItems;
-
- IsSelecting = true;
- BeginUpdateSelectedItems();
- for (var i = 0; i < items.Count; i++)
- {
- var container = (ItemContainer)ItemContainerGenerator.ContainerFromIndex(i);
-
- if (container.IsSelectableInArea(area, fit))
- {
- object? item = items[i];
- if (container.IsSelected)
- {
- selected.Remove(item);
- }
- else
- {
- selected.Add(item);
- }
- }
- }
- EndUpdateSelectedItems();
- IsSelecting = false;
- }
-
- ///
- /// Selects the s in the specified .
- ///
- /// The area to look for s.
- /// If true, it will add to the existing selection.
- /// True to check if the contains the .
False to check if intersects the .
- public void SelectArea(Rect area, bool append = false, bool fit = false)
- {
- if (!append)
- {
- UnselectAll();
- }
-
- ItemCollection items = Items;
- IList selected = base.SelectedItems;
-
- IsSelecting = true;
- BeginUpdateSelectedItems();
- for (var i = 0; i < items.Count; i++)
- {
- var container = (ItemContainer)ItemContainerGenerator.ContainerFromIndex(i);
- if (container.IsSelectableInArea(area, fit))
- {
- selected.Add(items[i]);
- }
- }
- EndUpdateSelectedItems();
- IsSelecting = false;
- }
-
- ///
- /// Unselect the s in the specified .
- ///
- /// The area to look for s.
- /// True to check if the contains the .
False to check if intersects the .
- public void UnselectArea(Rect area, bool fit = false)
- {
- IList items = base.SelectedItems;
-
- IsSelecting = true;
- BeginUpdateSelectedItems();
- for (var i = 0; i < items.Count; i++)
- {
- var container = (ItemContainer)ItemContainerGenerator.ContainerFromItem(items[i]);
- if (container.IsSelectableInArea(area, fit))
- {
- items.Remove(items[i]);
- }
- }
- EndUpdateSelectedItems();
- IsSelecting = false;
- }
-
- ///
- /// Unselect all .
- ///
- public void UnselectAllConnection()
- {
- if (ConnectionsHost is MultiSelector selector)
- {
- selector.UnselectAll();
- }
- }
-
- ///
- /// Select all .
- ///
- public void SelectAllConnections()
- {
- if (ConnectionsHost is MultiSelector selector)
- {
- selector.SelectAll();
- }
- }
-
- #endregion
-
#region Dragging
private void OnItemsDragDelta(object sender, DragDeltaEventArgs e)