diff --git a/NodeGraph.NET6/Controls/CanvasMouseEventArgs.cs b/NodeGraph.NET6/Controls/CanvasMouseEventArgs.cs
index 6115406..5db1c21 100644
--- a/NodeGraph.NET6/Controls/CanvasMouseEventArgs.cs
+++ b/NodeGraph.NET6/Controls/CanvasMouseEventArgs.cs
@@ -1,10 +1,5 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
-using System.Windows.Input;
namespace NodeGraph.NET6.Controls
{
diff --git a/NodeGraph.NET6/Controls/DefaultNode.cs b/NodeGraph.NET6/Controls/DefaultNode.cs
index 6225ce7..3ffa9cb 100644
--- a/NodeGraph.NET6/Controls/DefaultNode.cs
+++ b/NodeGraph.NET6/Controls/DefaultNode.cs
@@ -1,21 +1,10 @@
using System;
using System.Collections;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
-using System.Windows.Controls.Primitives;
-using System.Windows.Data;
-using System.Windows.Documents;
using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Navigation;
-using System.Windows.Shapes;
namespace NodeGraph.NET6.Controls
{
diff --git a/NodeGraph.NET6/Controls/GridCanvas.cs b/NodeGraph.NET6/Controls/GridCanvas.cs
index 2afd1be..7a2fbf1 100644
--- a/NodeGraph.NET6/Controls/GridCanvas.cs
+++ b/NodeGraph.NET6/Controls/GridCanvas.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
diff --git a/NodeGraph.NET6/Controls/GroupNode.cs b/NodeGraph.NET6/Controls/GroupNode.cs
index f27355e..047bd66 100644
--- a/NodeGraph.NET6/Controls/GroupNode.cs
+++ b/NodeGraph.NET6/Controls/GroupNode.cs
@@ -1,11 +1,7 @@
using System;
-using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
-using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
diff --git a/NodeGraph.NET6/Controls/ICanvasObject.cs b/NodeGraph.NET6/Controls/ICanvasObject.cs
index f676444..8da7831 100644
--- a/NodeGraph.NET6/Controls/ICanvasObject.cs
+++ b/NodeGraph.NET6/Controls/ICanvasObject.cs
@@ -1,10 +1,5 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
-using System.Windows.Controls;
namespace NodeGraph.NET6.Controls
{
diff --git a/NodeGraph.NET6/Controls/ISelectableObject.cs b/NodeGraph.NET6/Controls/ISelectableObject.cs
index 287f98d..c530aa0 100644
--- a/NodeGraph.NET6/Controls/ISelectableObject.cs
+++ b/NodeGraph.NET6/Controls/ISelectableObject.cs
@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
+using System.Windows;
namespace NodeGraph.NET6.Controls
{
diff --git a/NodeGraph.NET6/Controls/NodeBase.cs b/NodeGraph.NET6/Controls/NodeBase.cs
index 0deb561..5a7734f 100644
--- a/NodeGraph.NET6/Controls/NodeBase.cs
+++ b/NodeGraph.NET6/Controls/NodeBase.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
diff --git a/NodeGraph.NET6/Controls/NodeConnector.cs b/NodeGraph.NET6/Controls/NodeConnector.cs
index bb904de..de8fac5 100644
--- a/NodeGraph.NET6/Controls/NodeConnector.cs
+++ b/NodeGraph.NET6/Controls/NodeConnector.cs
@@ -1,11 +1,7 @@
-using Livet;
-using Livet.EventListeners;
-using System;
+using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
diff --git a/NodeGraph.NET6/Controls/NodeGraph.xaml b/NodeGraph.NET6/Controls/NodeGraph.xaml
index bda13f2..e94a906 100644
--- a/NodeGraph.NET6/Controls/NodeGraph.xaml
+++ b/NodeGraph.NET6/Controls/NodeGraph.xaml
@@ -1,7 +1,6 @@
diff --git a/NodeGraph.NET6/Controls/NodeInput.cs b/NodeGraph.NET6/Controls/NodeInput.cs
index 2c7af73..7ed4aa3 100644
--- a/NodeGraph.NET6/Controls/NodeInput.cs
+++ b/NodeGraph.NET6/Controls/NodeInput.cs
@@ -1,16 +1,6 @@
-using Livet;
-using Livet.EventListeners;
-using NodeGraph.NET6.Utilities;
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using NodeGraph.NET6.Utilities;
using System.Windows;
using System.Windows.Controls;
-using System.Windows.Controls.Primitives;
-using System.Windows.Media;
namespace NodeGraph.NET6.Controls
{
diff --git a/NodeGraph.NET6/Controls/NodeLink.cs b/NodeGraph.NET6/Controls/NodeLink.cs
index 45991cf..b81e26b 100644
--- a/NodeGraph.NET6/Controls/NodeLink.cs
+++ b/NodeGraph.NET6/Controls/NodeLink.cs
@@ -1,14 +1,9 @@
using NodeGraph.NET6.Extensions;
using System;
-using System.Collections.Generic;
using System.Data;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
-using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
diff --git a/NodeGraph.NET6/Controls/NodeOuput.cs b/NodeGraph.NET6/Controls/NodeOuput.cs
index 0e3466f..48cb23d 100644
--- a/NodeGraph.NET6/Controls/NodeOuput.cs
+++ b/NodeGraph.NET6/Controls/NodeOuput.cs
@@ -1,13 +1,6 @@
using NodeGraph.NET6.Utilities;
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
-using System.Windows.Controls.Primitives;
namespace NodeGraph.NET6.Controls
{
diff --git a/NodeGraph.NET6/Controls/RangeSelector.cs b/NodeGraph.NET6/Controls/RangeSelector.cs
index d34ea10..20cbe26 100644
--- a/NodeGraph.NET6/Controls/RangeSelector.cs
+++ b/NodeGraph.NET6/Controls/RangeSelector.cs
@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
+using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
diff --git a/NodeGraph.NET6/Controls/Ruler.cs b/NodeGraph.NET6/Controls/Ruler.cs
index fc27199..1624f16 100644
--- a/NodeGraph.NET6/Controls/Ruler.cs
+++ b/NodeGraph.NET6/Controls/Ruler.cs
@@ -1,9 +1,5 @@
using System;
-using System.Collections.Generic;
using System.Globalization;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
diff --git a/NodeGraph.NET6/Controls/StaticDefinition.cs b/NodeGraph.NET6/Controls/StaticDefinition.cs
index 9d0cc8a..e985d88 100644
--- a/NodeGraph.NET6/Controls/StaticDefinition.cs
+++ b/NodeGraph.NET6/Controls/StaticDefinition.cs
@@ -1,10 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace NodeGraph.NET6.Controls
+namespace NodeGraph.NET6.Controls
{
public static class ControlSize
{
diff --git a/NodeGraph.NET6/Converters/InverseBooleanToVisibilityConverter.cs b/NodeGraph.NET6/Converters/InverseBooleanToVisibilityConverter.cs
index 4edd083..147e866 100644
--- a/NodeGraph.NET6/Converters/InverseBooleanToVisibilityConverter.cs
+++ b/NodeGraph.NET6/Converters/InverseBooleanToVisibilityConverter.cs
@@ -1,9 +1,5 @@
using System;
-using System.Collections.Generic;
using System.Globalization;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
diff --git a/NodeGraph.NET6/Extensions/PointExtension.cs b/NodeGraph.NET6/Extensions/PointExtension.cs
index 26f40dc..172066c 100644
--- a/NodeGraph.NET6/Extensions/PointExtension.cs
+++ b/NodeGraph.NET6/Extensions/PointExtension.cs
@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
+using System.Windows;
namespace NodeGraph.NET6.Extensions
{
diff --git a/NodeGraph.NET6/Extensions/VectorExtension.cs b/NodeGraph.NET6/Extensions/VectorExtension.cs
index ac6a5d9..bac356c 100644
--- a/NodeGraph.NET6/Extensions/VectorExtension.cs
+++ b/NodeGraph.NET6/Extensions/VectorExtension.cs
@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
+using System.Windows;
namespace NodeGraph.NET6.Extensions
{
diff --git a/NodeGraph.NET6/Operation/BeginMoveNodesOperationEventArgs.cs b/NodeGraph.NET6/Operation/BeginMoveNodesOperationEventArgs.cs
index dd3ecda..141b610 100644
--- a/NodeGraph.NET6/Operation/BeginMoveNodesOperationEventArgs.cs
+++ b/NodeGraph.NET6/Operation/BeginMoveNodesOperationEventArgs.cs
@@ -1,14 +1,10 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace NodeGraph.NET6.Operation
{
public class BeginMoveNodesOperationEventArgs : EventArgs
{
- public Guid[] NodeGuids { get; } = null;
+ public Guid[] NodeGuids { get; } = null!;
public BeginMoveNodesOperationEventArgs(Guid[] nodeGuids)
{
diff --git a/NodeGraph.NET6/Operation/ConnectOperationEventArgs.cs b/NodeGraph.NET6/Operation/ConnectOperationEventArgs.cs
index 191d42e..3144e3e 100644
--- a/NodeGraph.NET6/Operation/ConnectOperationEventArgs.cs
+++ b/NodeGraph.NET6/Operation/ConnectOperationEventArgs.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace NodeGraph.NET6.Operation
{
diff --git a/NodeGraph.NET6/Operation/ConnectedLinkOperationEventArgs.cs b/NodeGraph.NET6/Operation/ConnectedLinkOperationEventArgs.cs
index 26a2bee..ffc38c8 100644
--- a/NodeGraph.NET6/Operation/ConnectedLinkOperationEventArgs.cs
+++ b/NodeGraph.NET6/Operation/ConnectedLinkOperationEventArgs.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace NodeGraph.NET6.Operation
{
diff --git a/NodeGraph.NET6/Operation/DisconnectOperationEventArgs.cs b/NodeGraph.NET6/Operation/DisconnectOperationEventArgs.cs
index 1f7c8a8..787d672 100644
--- a/NodeGraph.NET6/Operation/DisconnectOperationEventArgs.cs
+++ b/NodeGraph.NET6/Operation/DisconnectOperationEventArgs.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace NodeGraph.NET6.Operation
{
diff --git a/NodeGraph.NET6/Operation/DisconnectedLinkOperationEventArgs.cs b/NodeGraph.NET6/Operation/DisconnectedLinkOperationEventArgs.cs
index 87a9d77..5d36ff1 100644
--- a/NodeGraph.NET6/Operation/DisconnectedLinkOperationEventArgs.cs
+++ b/NodeGraph.NET6/Operation/DisconnectedLinkOperationEventArgs.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace NodeGraph.NET6.Operation
{
diff --git a/NodeGraph.NET6/Operation/EndMoveNodesOperationEventArgs.cs b/NodeGraph.NET6/Operation/EndMoveNodesOperationEventArgs.cs
index 25e4892..e66c80b 100644
--- a/NodeGraph.NET6/Operation/EndMoveNodesOperationEventArgs.cs
+++ b/NodeGraph.NET6/Operation/EndMoveNodesOperationEventArgs.cs
@@ -1,9 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
namespace NodeGraph.NET6.Operation
{
diff --git a/NodeGraph.NET6/Operation/MovedNodesOperationEventArgs.cs b/NodeGraph.NET6/Operation/MovedNodesOperationEventArgs.cs
index 58be98a..9c7561d 100644
--- a/NodeGraph.NET6/Operation/MovedNodesOperationEventArgs.cs
+++ b/NodeGraph.NET6/Operation/MovedNodesOperationEventArgs.cs
@@ -1,9 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
namespace NodeGraph.NET6.Operation
{
diff --git a/NodeGraph.NET6/Operation/PreviewConnectLinkOperationEventArgs.cs b/NodeGraph.NET6/Operation/PreviewConnectLinkOperationEventArgs.cs
index d6e7572..eb212ef 100644
--- a/NodeGraph.NET6/Operation/PreviewConnectLinkOperationEventArgs.cs
+++ b/NodeGraph.NET6/Operation/PreviewConnectLinkOperationEventArgs.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace NodeGraph.NET6.Operation
{
diff --git a/NodeGraph.NET6/Operation/PreviewConnectOperationEventArgs.cs b/NodeGraph.NET6/Operation/PreviewConnectOperationEventArgs.cs
index 23eecb8..869bfd4 100644
--- a/NodeGraph.NET6/Operation/PreviewConnectOperationEventArgs.cs
+++ b/NodeGraph.NET6/Operation/PreviewConnectOperationEventArgs.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace NodeGraph.NET6.Operation
{
diff --git a/NodeGraph.NET6/Operation/StartMoveNodesOperationEventArgs.cs b/NodeGraph.NET6/Operation/StartMoveNodesOperationEventArgs.cs
index 4588452..64471b8 100644
--- a/NodeGraph.NET6/Operation/StartMoveNodesOperationEventArgs.cs
+++ b/NodeGraph.NET6/Operation/StartMoveNodesOperationEventArgs.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace NodeGraph.NET6.Operation
{
diff --git a/NodeGraph.NET6/OperationEventArgs/BeginMoveNodesOperationEventArgs.cs b/NodeGraph.NET6/OperationEventArgs/BeginMoveNodesOperationEventArgs.cs
index 2fbf6e4..3de5c6f 100644
--- a/NodeGraph.NET6/OperationEventArgs/BeginMoveNodesOperationEventArgs.cs
+++ b/NodeGraph.NET6/OperationEventArgs/BeginMoveNodesOperationEventArgs.cs
@@ -1,14 +1,10 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace NodeGraph.NET6.OperationEventArgs
{
public class BeginMoveNodesOperationEventArgs : EventArgs
{
- public Guid[] NodeGuids { get; } = null;
+ public Guid[] NodeGuids { get; } = null!;
public BeginMoveNodesOperationEventArgs(Guid[] nodeGuids)
{
diff --git a/NodeGraph.NET6/OperationEventArgs/ConnectedLinkOperationEventArgs.cs b/NodeGraph.NET6/OperationEventArgs/ConnectedLinkOperationEventArgs.cs
index e09ea11..7860c3b 100644
--- a/NodeGraph.NET6/OperationEventArgs/ConnectedLinkOperationEventArgs.cs
+++ b/NodeGraph.NET6/OperationEventArgs/ConnectedLinkOperationEventArgs.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace NodeGraph.NET6.OperationEventArgs
{
diff --git a/NodeGraph.NET6/OperationEventArgs/DisconnectedLinkOperationEventArgs.cs b/NodeGraph.NET6/OperationEventArgs/DisconnectedLinkOperationEventArgs.cs
index add273d..2a6f011 100644
--- a/NodeGraph.NET6/OperationEventArgs/DisconnectedLinkOperationEventArgs.cs
+++ b/NodeGraph.NET6/OperationEventArgs/DisconnectedLinkOperationEventArgs.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace NodeGraph.NET6.OperationEventArgs
{
diff --git a/NodeGraph.NET6/OperationEventArgs/EndMoveNodesOperationEventArgs.cs b/NodeGraph.NET6/OperationEventArgs/EndMoveNodesOperationEventArgs.cs
index 4280500..4940c49 100644
--- a/NodeGraph.NET6/OperationEventArgs/EndMoveNodesOperationEventArgs.cs
+++ b/NodeGraph.NET6/OperationEventArgs/EndMoveNodesOperationEventArgs.cs
@@ -1,15 +1,10 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
namespace NodeGraph.NET6.OperationEventArgs
{
public class EndMoveNodesOperationEventArgs : EventArgs
{
- public Guid[] NodeGuids { get; } = null;
+ public Guid[] NodeGuids { get; } = null!;
public EndMoveNodesOperationEventArgs(Guid[] nodeGuids)
{
diff --git a/NodeGraph.NET6/OperationEventArgs/PreviewConnectLinkOperationEventArgs.cs b/NodeGraph.NET6/OperationEventArgs/PreviewConnectLinkOperationEventArgs.cs
index 11a9c5f..f915214 100644
--- a/NodeGraph.NET6/OperationEventArgs/PreviewConnectLinkOperationEventArgs.cs
+++ b/NodeGraph.NET6/OperationEventArgs/PreviewConnectLinkOperationEventArgs.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace NodeGraph.NET6.OperationEventArgs
{
diff --git a/NodeGraph.NET6/Properties/Resources.Designer.cs b/NodeGraph.NET6/Properties/Resources.Designer.cs
index c56ea3a..592c30a 100644
--- a/NodeGraph.NET6/Properties/Resources.Designer.cs
+++ b/NodeGraph.NET6/Properties/Resources.Designer.cs
@@ -8,7 +8,7 @@
//
//------------------------------------------------------------------------------
-namespace NodeGraph.Properties
+namespace NodeGraph.NET6.Properties
{
diff --git a/NodeGraph.NET6/Properties/Settings.Designer.cs b/NodeGraph.NET6/Properties/Settings.Designer.cs
index b01c872..2c78dcd 100644
--- a/NodeGraph.NET6/Properties/Settings.Designer.cs
+++ b/NodeGraph.NET6/Properties/Settings.Designer.cs
@@ -8,7 +8,7 @@
//
//------------------------------------------------------------------------------
-namespace NodeGraph.Properties
+namespace NodeGraph.NET6.Properties
{
diff --git a/NodeGraph.NET6/ResourceDictionary.xaml b/NodeGraph.NET6/ResourceDictionary.xaml
index 758b1b5..1c3389b 100644
--- a/NodeGraph.NET6/ResourceDictionary.xaml
+++ b/NodeGraph.NET6/ResourceDictionary.xaml
@@ -1,6 +1,4 @@
-
+
diff --git a/NodeGraph.NET6/Utilities/ResourceInstance.cs b/NodeGraph.NET6/Utilities/ResourceInstance.cs
index 1224539..0b6a85e 100644
--- a/NodeGraph.NET6/Utilities/ResourceInstance.cs
+++ b/NodeGraph.NET6/Utilities/ResourceInstance.cs
@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
+using System.Windows;
using System.Windows.Threading;
namespace NodeGraph.NET6.Utilities
@@ -14,12 +9,12 @@ public T Get(string resourceName)
{
if (_Resource == null)
{
- _Resource = Application.Current.TryFindResource(resourceName) as T;
+ _Resource = (Application.Current.TryFindResource(resourceName) as T)!;
}
- return _Resource;
+ return _Resource!;
}
- T _Resource = null;
+ T _Resource = null!;
}
}
diff --git a/NodeGraph.NET6/packages.config b/NodeGraph.NET6/packages.config
deleted file mode 100644
index 1c85274..0000000
--- a/NodeGraph.NET6/packages.config
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/NodeGraph.NET7/Controls/CanvasMouseEventArgs.cs b/NodeGraph.NET7/Controls/CanvasMouseEventArgs.cs
new file mode 100644
index 0000000..9bf8533
--- /dev/null
+++ b/NodeGraph.NET7/Controls/CanvasMouseEventArgs.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Windows;
+
+namespace NodeGraph.NET7.Controls
+{
+ public class CanvasMouseEventArgs : EventArgs
+ {
+ // This position has taken scale and offset into account.
+ public Point TransformedPosition { get; }
+
+ public CanvasMouseEventArgs(Point transformedPosition)
+ {
+ TransformedPosition = transformedPosition;
+ }
+ }
+}
diff --git a/NodeGraph.NET7/Controls/DefaultNode.cs b/NodeGraph.NET7/Controls/DefaultNode.cs
new file mode 100644
index 0000000..8d7ba72
--- /dev/null
+++ b/NodeGraph.NET7/Controls/DefaultNode.cs
@@ -0,0 +1,262 @@
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+
+namespace NodeGraph.NET7.Controls
+{
+ public class DefaultNode : NodeBase
+ {
+ public DataTemplate HeaderContentTemplate
+ {
+ get => (DataTemplate)GetValue(HeaderContentTemplateProperty);
+ set => SetValue(HeaderContentTemplateProperty, value);
+ }
+ public static readonly DependencyProperty HeaderContentTemplateProperty = DependencyProperty.Register(
+ nameof(HeaderContentTemplate),
+ typeof(DataTemplate),
+ typeof(DefaultNode),
+ new FrameworkPropertyMetadata(null));
+
+ public Thickness ContentMargin
+ {
+ get => (Thickness)GetValue(ContentMarginProperty);
+ set => SetValue(ContentMarginProperty, value);
+ }
+ public static readonly DependencyProperty ContentMarginProperty = DependencyProperty.Register(
+ nameof(ContentMargin),
+ typeof(Thickness),
+ typeof(DefaultNode),
+ new FrameworkPropertyMetadata(new Thickness(4, 0, 4, 0), FrameworkPropertyMetadataOptions.AffectsArrange));
+
+ public VerticalAlignment InputLayout
+ {
+ get => (VerticalAlignment)GetValue(InputLayoutProperty);
+ set => SetValue(InputLayoutProperty, value);
+ }
+ public static readonly DependencyProperty InputLayoutProperty = DependencyProperty.Register(
+ nameof(InputLayout),
+ typeof(VerticalAlignment),
+ typeof(DefaultNode),
+ new FrameworkPropertyMetadata(VerticalAlignment.Top));
+
+ public Thickness InputMargin
+ {
+ get => (Thickness)GetValue(InputMarginProperty);
+ set => SetValue(InputMarginProperty, value);
+ }
+ public static readonly DependencyProperty InputMarginProperty = DependencyProperty.Register(
+ nameof(InputMargin),
+ typeof(Thickness),
+ typeof(DefaultNode),
+ new FrameworkPropertyMetadata(new Thickness(2.0)));
+
+ public IEnumerable Inputs
+ {
+ get => (IEnumerable)GetValue(InputsProperty);
+ set => SetValue(InputsProperty, value);
+ }
+ public static readonly DependencyProperty InputsProperty = DependencyProperty.Register(
+ nameof(Inputs),
+ typeof(IEnumerable),
+ typeof(DefaultNode),
+ new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsArrange, InputsPropertyChanged));
+
+ public Style InputStyle
+ {
+ get => (Style)GetValue(InputStyleProperty);
+ set => SetValue(InputStyleProperty, value);
+ }
+ public static readonly DependencyProperty InputStyleProperty = DependencyProperty.Register(
+ nameof(InputStyle),
+ typeof(Style),
+ typeof(DefaultNode),
+ new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
+
+ public VerticalAlignment OutputLayout
+ {
+ get => (VerticalAlignment)GetValue(OutputLayoutProperty);
+ set => SetValue(OutputLayoutProperty, value);
+ }
+ public static readonly DependencyProperty OutputLayoutProperty = DependencyProperty.Register(
+ nameof(OutputLayout),
+ typeof(VerticalAlignment),
+ typeof(DefaultNode),
+ new FrameworkPropertyMetadata(VerticalAlignment.Top));
+
+ public Thickness OutputMargin
+ {
+ get => (Thickness)GetValue(OutputMarginProperty);
+ set => SetValue(OutputMarginProperty, value);
+ }
+ public static readonly DependencyProperty OutputMarginProperty = DependencyProperty.Register(
+ nameof(OutputMargin),
+ typeof(Thickness),
+ typeof(DefaultNode),
+ new FrameworkPropertyMetadata(new Thickness(2.0)));
+
+ public IEnumerable Outputs
+ {
+ get => (IEnumerable)GetValue(OutputsProperty);
+ set => SetValue(OutputsProperty, value);
+ }
+ public static readonly DependencyProperty OutputsProperty = DependencyProperty.Register(
+ nameof(Outputs),
+ typeof(IEnumerable),
+ typeof(DefaultNode),
+ new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsArrange, OutputsPropertyChanged));
+
+ public Style OutputStyle
+ {
+ get => (Style)GetValue(OutputStyleProperty);
+ set => SetValue(OutputStyleProperty, value);
+ }
+ public static readonly DependencyProperty OutputStyleProperty = DependencyProperty.Register(
+ nameof(OutputStyle),
+ typeof(Style),
+ typeof(DefaultNode),
+ new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
+
+ public ICommand SizeChangedCommand
+ {
+ get => (ICommand)GetValue(SizeChangedCommandProperty);
+ set => SetValue(SizeChangedCommandProperty, value);
+ }
+ public static readonly DependencyProperty SizeChangedCommandProperty = DependencyProperty.Register(
+ nameof(SizeChangedCommand),
+ typeof(ICommand),
+ typeof(DefaultNode),
+ new FrameworkPropertyMetadata(null));
+
+ NodeInput _NodeInput = null;
+ NodeOutput _NodeOutput = null;
+
+ ColumnDefinition _NodeInputGridColumnDefinition;
+ ColumnDefinition _NodeContentTemplateGridColumnDefinition;
+ ColumnDefinition _NodeOutputGridColumnDefinition;
+
+ static void OutputsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var node = d as DefaultNode;
+
+ if (e.OldValue is INotifyCollectionChanged oldCollection)
+ {
+ oldCollection.CollectionChanged -= node.OutputCollectionChanged;
+ }
+ if (e.NewValue is INotifyCollectionChanged newCollection)
+ {
+ newCollection.CollectionChanged += node.OutputCollectionChanged;
+ }
+ }
+
+ static void InputsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var node = d as DefaultNode;
+
+ if (e.OldValue != null && e.OldValue is INotifyCollectionChanged oldCollection)
+ {
+ oldCollection.CollectionChanged -= node.InputCollectionChanged;
+ }
+ if (e.NewValue != null && e.NewValue is INotifyCollectionChanged newCollection)
+ {
+ newCollection.CollectionChanged += node.InputCollectionChanged;
+ }
+ }
+
+ static DefaultNode()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(DefaultNode), new FrameworkPropertyMetadata(typeof(DefaultNode)));
+ }
+
+ internal DefaultNode(Canvas canvas, Point offset, double scale) : base(canvas, offset)
+ {
+ SizeChanged += Node_SizeChanged;
+ }
+
+ public override void OnApplyTemplate()
+ {
+ _NodeInput = (NodeInput)GetTemplateChild("__NodeInput__");
+ _NodeInput.ApplyTemplate();
+
+ _NodeOutput = (NodeOutput)GetTemplateChild("__NodeOutput__");
+ _NodeOutput.ApplyTemplate();
+
+ _NodeInputGridColumnDefinition = (ColumnDefinition)GetTemplateChild("__NodeInputGridColumnDefinition__");
+ _NodeContentTemplateGridColumnDefinition = (ColumnDefinition)GetTemplateChild("__NodeContentTemplateGridColumnDefinition__");
+ _NodeOutputGridColumnDefinition = (ColumnDefinition)GetTemplateChild("__NodeOutputGridColumnDefinition__");
+ }
+
+ internal void Initialize()
+ {
+ _NodeInput.Initialize();
+ _NodeOutput.Initialize();
+ }
+
+ internal NodeLink[] EnumrateConnectedNodeLinks()
+ {
+ var inputNodeLinks = _NodeInput.EnumerateConnectedNodeLinks();
+ var outputNodeLinks = _NodeOutput.EnumerateConnectedNodeLinks();
+
+ return inputNodeLinks.Concat(outputNodeLinks).ToArray();
+ }
+
+ public NodeConnectorContent FindNodeConnectorContent(Guid guid)
+ {
+ var input = _NodeInput.FindNodeConnector(guid);
+ if (input != null)
+ {
+ return input;
+ }
+
+ return _NodeOutput.FindNodeConnector(guid);
+ }
+
+ protected override void OnDisposing()
+ {
+ _NodeInput.Dispose();
+ _NodeOutput.Dispose();
+ SizeChanged -= Node_SizeChanged;
+ }
+
+ protected override void OnUpdateTranslation()
+ {
+ _NodeInput.UpdateLinkPosition(Canvas);
+ _NodeOutput.UpdateLinkPosition(Canvas);
+ }
+
+ protected override void OnMouseMove(MouseEventArgs e)
+ {
+ base.OnMouseMove(e);
+ }
+
+ protected override void OnMouseUp(MouseButtonEventArgs e)
+ {
+ base.OnMouseUp(e);
+ }
+
+ void Node_SizeChanged(object sender, SizeChangedEventArgs e)
+ {
+ _NodeInput.UpdateLinkPosition(Canvas);
+ _NodeOutput.UpdateLinkPosition(Canvas);
+
+ // Collapse input/output controls if not placement input/output connectors.
+ _NodeInputGridColumnDefinition.Width = _NodeInput.HasItems ? new GridLength(1.0f, GridUnitType.Star) : new GridLength(0);
+ _NodeOutputGridColumnDefinition.Width = _NodeOutput.HasItems ? new GridLength(1.0f, GridUnitType.Star) : new GridLength(0);
+
+ SizeChangedCommand?.Execute(e.NewSize);
+ }
+
+ void OutputCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ // Implement if need anything.
+ }
+
+ void InputCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ // Implement if need anything.
+ }
+ }
+}
diff --git a/NodeGraph.NET7/Controls/DefaultNode.xaml b/NodeGraph.NET7/Controls/DefaultNode.xaml
new file mode 100644
index 0000000..8a911e7
--- /dev/null
+++ b/NodeGraph.NET7/Controls/DefaultNode.xaml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NodeGraph.NET7/Controls/GridCanvas.cs b/NodeGraph.NET7/Controls/GridCanvas.cs
new file mode 100644
index 0000000..7091934
--- /dev/null
+++ b/NodeGraph.NET7/Controls/GridCanvas.cs
@@ -0,0 +1,204 @@
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace NodeGraph.NET7.Controls
+{
+ ///
+ /// Infinity grid rendering canvas.
+ ///
+ public class GridCanvas : Canvas
+ {
+ public Point Offset
+ {
+ get => (Point)GetValue(OffsetProperty);
+ set => SetValue(OffsetProperty, value);
+ }
+ public static readonly DependencyProperty OffsetProperty =
+ DependencyProperty.Register(nameof(Offset), typeof(Point), typeof(GridCanvas), new FrameworkPropertyMetadata(new Point(0, 0), OffsetPropertyChanged));
+
+ public double Scale
+ {
+ get => (double)GetValue(ScaleProperty);
+ set => SetValue(ScaleProperty, value);
+ }
+ public static readonly DependencyProperty ScaleProperty =
+ DependencyProperty.Register(nameof(Scale), typeof(double), typeof(GridCanvas), new FrameworkPropertyMetadata(1.0, ScalePropertyChanged));
+
+ public double Spacing
+ {
+ get => (double)GetValue(SpacingProperty);
+ set => SetValue(SpacingProperty, value);
+ }
+ public static readonly DependencyProperty SpacingProperty =
+ DependencyProperty.Register(nameof(Spacing), typeof(double), typeof(GridCanvas), new FrameworkPropertyMetadata(128.0));
+
+ public int SubDivisionCount
+ {
+ get => (int)GetValue(SubDivisionCountProperty);
+ set => SetValue(SubDivisionCountProperty, value);
+ }
+ public static readonly DependencyProperty SubDivisionCountProperty =
+ DependencyProperty.Register(nameof(SubDivisionCount), typeof(int), typeof(GridCanvas), new FrameworkPropertyMetadata(3));
+
+ public Brush GridMainBrush
+ {
+ get => (Brush)GetValue(GridMainBrushProperty);
+ set => SetValue(GridMainBrushProperty, value);
+ }
+ public static readonly DependencyProperty GridMainBrushProperty =
+ DependencyProperty.Register(nameof(GridMainBrush), typeof(Brush), typeof(GridCanvas), new FrameworkPropertyMetadata(new SolidColorBrush(Color.FromRgb(80, 80, 80)), GridMainBrushPropertyChanged));
+
+ public Brush GridSubBrush
+ {
+ get => (Brush)GetValue(GridSubBrushProperty);
+ set => SetValue(GridSubBrushProperty, value);
+ }
+ public static readonly DependencyProperty GridSubBrushProperty =
+ DependencyProperty.Register(nameof(GridSubBrush), typeof(Brush), typeof(GridCanvas), new FrameworkPropertyMetadata(new SolidColorBrush(Color.FromRgb(64, 64, 64)), GridSubBrushPropertyChanged));
+
+ public double GridMainThickness
+ {
+ get => (double)GetValue(GridMainThicknessProperty);
+ set => SetValue(GridMainThicknessProperty, value);
+ }
+ public static readonly DependencyProperty GridMainThicknessProperty =
+ DependencyProperty.Register(nameof(GridMainThickness), typeof(double), typeof(GridCanvas), new FrameworkPropertyMetadata(1.0, GridMainThicknessPropertyChanged));
+
+ public double GridSubThickness
+ {
+ get => (double)GetValue(GridSubThicknessProperty);
+ set => SetValue(GridSubThicknessProperty, value);
+ }
+ public static readonly DependencyProperty GridSubThicknessProperty =
+ DependencyProperty.Register(nameof(GridSubThickness), typeof(double), typeof(GridCanvas), new FrameworkPropertyMetadata(1.0, GridSubThicknessPropertyChanged));
+
+ Pen _GridMainPen = null;
+ Pen _GridSubPen = null;
+ ScaleTransform _Scale = new ScaleTransform(1.0, 1.0);
+
+ static void OffsetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ (d as GridCanvas).InvalidateVisual();
+ }
+
+ static void ScalePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var canvas = d as GridCanvas;
+ canvas.UpdateScale();
+ canvas.InvalidateVisual();
+ }
+
+ static void GridMainBrushPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ (d as GridCanvas).UpdateMainGridPen();
+ }
+
+ static void GridSubBrushPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ (d as GridCanvas).UpdateMainGridPen();
+ }
+
+ static void GridMainThicknessPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ (d as GridCanvas).UpdateSubGridPen();
+ }
+
+ static void GridSubThicknessPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ (d as GridCanvas).UpdateSubGridPen();
+ }
+
+ static GridCanvas()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(GridCanvas), new FrameworkPropertyMetadata(typeof(GridCanvas)));
+ }
+
+ public GridCanvas()
+ {
+ var transfromGroup = new TransformGroup();
+ transfromGroup.Children.Add(_Scale);
+ RenderTransform = transfromGroup;
+
+ UpdateMainGridPen();
+ UpdateSubGridPen();
+ }
+
+ protected override void OnRender(DrawingContext dc)
+ {
+ base.OnRender(dc);
+
+ // render grid only visual area.
+ int subGridCount = SubDivisionCount + 1;
+ double subGridSpace = Spacing / subGridCount;
+ double subGridOffset = subGridSpace * subGridCount;
+
+ double MinHorizonOnCanvas = -ActualWidth * Math.Max(0.0, 1.0 - Scale) * 1.0 / Scale * 0.5;
+ double MaxHorizonOnCanvas = +ActualWidth * (1 + Math.Max(0.0, 1.0 - Scale) * 1.0 / Scale * 0.5);
+
+ double MinVerticalOnCanvas = -ActualHeight * Math.Max(0.0, 1.0 - Scale) * 1.0 / Scale * 0.5;
+ double MaxVerticalOnCanvas = +ActualHeight * (1 + Math.Max(0.0, 1.0 - Scale) * 1.0 / Scale * 0.5);
+
+ double invScale = 1.0 / Scale;
+
+ int hCount = (int)(ActualHeight * invScale / Spacing + Math.Ceiling(Scale));
+ int initHIndex = (int)(Math.Max(0, ActualHeight * invScale - ActualHeight) / Spacing);
+
+ int vCount = (int)(ActualWidth * invScale / Spacing + Math.Ceiling(Scale)) + 2;
+ int initVIndex = (int)(Math.Max(0, ActualWidth * invScale - ActualWidth) / Spacing);
+
+ // sub horizon
+ for (int i = -initHIndex; i < hCount; ++i)
+ {
+ for (int sub = 0; sub < subGridCount; ++sub)
+ {
+ double hSub = sub * subGridSpace + i * subGridOffset + Offset.Y % subGridSpace;
+ dc.DrawLine(_GridSubPen, new Point(MinHorizonOnCanvas, hSub), new Point(MaxHorizonOnCanvas, hSub));
+ }
+ }
+
+ // sub vertical
+ for (int i = -initVIndex; i < vCount; ++i)
+ {
+ for (uint sub = 0; sub < subGridCount; ++sub)
+ {
+ double vSub = sub * subGridSpace + i * subGridOffset + Offset.X % subGridSpace;
+ dc.DrawLine(_GridSubPen, new Point(vSub, MinVerticalOnCanvas), new Point(vSub, MaxVerticalOnCanvas));
+ }
+ }
+
+ // main horizontal
+ for (int i = -initHIndex; i < hCount; ++i)
+ {
+ double h = i * Spacing + Offset.Y % Spacing;
+ dc.DrawLine(_GridMainPen, new Point(MinHorizonOnCanvas, h), new Point(MaxHorizonOnCanvas, h));
+ }
+
+ // main vertical
+ for (int i = -initVIndex; i < vCount; ++i)
+ {
+ double v = i * Spacing + Offset.X % Spacing;
+ dc.DrawLine(_GridMainPen, new Point(v, MinVerticalOnCanvas), new Point(v, MaxVerticalOnCanvas));
+ }
+ }
+
+ void UpdateMainGridPen()
+ {
+ _GridMainPen = new Pen(GridMainBrush, GridMainThickness);
+ _GridMainPen.Freeze();
+ }
+
+ void UpdateSubGridPen()
+ {
+ _GridSubPen = new Pen(GridSubBrush, GridSubThickness);
+ _GridSubPen.Freeze();
+ }
+
+ void UpdateScale()
+ {
+ _Scale.ScaleX = Scale;
+ _Scale.ScaleY = Scale;
+ }
+ }
+}
diff --git a/NodeGraph.NET7/Controls/GroupNode.cs b/NodeGraph.NET7/Controls/GroupNode.cs
new file mode 100644
index 0000000..a8e579c
--- /dev/null
+++ b/NodeGraph.NET7/Controls/GroupNode.cs
@@ -0,0 +1,536 @@
+using System;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows.Media;
+
+namespace NodeGraph.NET7.Controls
+{
+ enum DragResizeType
+ {
+ None,
+ LeftTop,
+ RightTop,
+ LeftBottom,
+ RightBottom,
+ Top,
+ Bottom,
+ Left,
+ Right,
+ }
+
+ public class GroupNode : NodeBase
+ {
+ public DataTemplate HeaderContentTemplate
+ {
+ get => (DataTemplate)GetValue(HeaderContentTemplateProperty);
+ set => SetValue(HeaderContentTemplateProperty, value);
+ }
+ public static readonly DependencyProperty HeaderContentTemplateProperty = DependencyProperty.Register(
+ nameof(HeaderContentTemplate),
+ typeof(DataTemplate),
+ typeof(GroupNode),
+ new FrameworkPropertyMetadata(null));
+
+ ///
+ /// This property is set only where script.
+ /// Do not use at UI code.
+ ///
+ public Point InterlockPosition
+ {
+ get => (Point)GetValue(InterlockPositionProperty);
+ set => SetValue(InterlockPositionProperty, value);
+ }
+ public static readonly DependencyProperty InterlockPositionProperty = DependencyProperty.Register(
+ nameof(InterlockPosition),
+ typeof(Point),
+ typeof(GroupNode),
+ new FrameworkPropertyMetadata(new Point(0, 0), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, InterlockPositionPropertyChanged));
+
+ public double BorderSize
+ {
+ get => (double)GetValue(BorderSizeProperty);
+ set => SetValue(BorderSizeProperty, value);
+ }
+ public static readonly DependencyProperty BorderSizeProperty = DependencyProperty.Register(
+ nameof(BorderSize),
+ typeof(double),
+ typeof(GroupNode),
+ new FrameworkPropertyMetadata(4.0));
+
+ public Point InnerPosition
+ {
+ get => (Point)GetValue(InnerPositionProperty);
+ set => SetValue(InnerPositionProperty, value);
+ }
+ public static readonly DependencyProperty InnerPositionProperty = DependencyProperty.Register(
+ nameof(InnerPosition),
+ typeof(Point),
+ typeof(GroupNode),
+ new FrameworkPropertyMetadata(new Point(0, 0), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, InnerPositionPropertyChanged));
+
+ public double InnerWidth
+ {
+ get => (double)GetValue(InnerWidthProperty);
+ set => SetValue(InnerWidthProperty, value);
+ }
+ public static readonly DependencyProperty InnerWidthProperty = DependencyProperty.Register(
+ nameof(InnerWidth),
+ typeof(double),
+ typeof(GroupNode),
+ new FrameworkPropertyMetadata(100.0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, InnerWidthPropertyChanged));
+
+ public double InnerHeight
+ {
+ get => (double)GetValue(InnerHeightProperty);
+ set => SetValue(InnerHeightProperty, value);
+ }
+ public static readonly DependencyProperty InnerHeightProperty = DependencyProperty.Register(
+ nameof(InnerHeight),
+ typeof(double),
+ typeof(GroupNode),
+ new FrameworkPropertyMetadata(100.0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, InnerHeightPropertyChanged));
+
+ public SolidColorBrush InnerColor
+ {
+ get => (SolidColorBrush)GetValue(InnerColorProperty);
+ set => SetValue(InnerColorProperty, value);
+ }
+ public static readonly DependencyProperty InnerColorProperty = DependencyProperty.Register(
+ nameof(InnerColor),
+ typeof(SolidColorBrush),
+ typeof(GroupNode),
+ new FrameworkPropertyMetadata(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0))));
+
+ public string Comment
+ {
+ get => (string)GetValue(CommentProperty);
+ set => SetValue(CommentProperty, value);
+ }
+ public static readonly DependencyProperty CommentProperty = DependencyProperty.Register(
+ nameof(Comment),
+ typeof(string),
+ typeof(GroupNode),
+ new FrameworkPropertyMetadata(string.Empty));
+
+ public double CommentSize
+ {
+ get => (double)GetValue(CommentSizeProperty);
+ set => SetValue(CommentSizeProperty, value);
+ }
+ public static readonly DependencyProperty CommentSizeProperty = DependencyProperty.Register(
+ nameof(CommentSize),
+ typeof(double),
+ typeof(GroupNode),
+ new FrameworkPropertyMetadata(12.0));
+
+ public SolidColorBrush CommentForeground
+ {
+ get => (SolidColorBrush)GetValue(CommentForegroundProperty);
+ set => SetValue(CommentForegroundProperty, value);
+ }
+ public static readonly DependencyProperty CommentForegroundProperty = DependencyProperty.Register(
+ nameof(CommentForeground),
+ typeof(SolidColorBrush),
+ typeof(GroupNode),
+ new FrameworkPropertyMetadata(new SolidColorBrush(Color.FromArgb(64, 255, 255, 255))));
+
+ public Thickness CommentMargin
+ {
+ get => (Thickness)GetValue(CommentMarginProperty);
+ set => SetValue(CommentMarginProperty, value);
+ }
+ public static readonly DependencyProperty CommentMarginProperty = DependencyProperty.Register(
+ nameof(CommentMargin),
+ typeof(Thickness),
+ typeof(GroupNode),
+ new FrameworkPropertyMetadata(new Thickness(8)));
+
+ public ICommand SizeChangedCommand
+ {
+ get => GetValue(SizeChangedCommandProperty) as ICommand;
+ set => SetValue(SizeChangedCommandProperty, value);
+ }
+ public static readonly DependencyProperty SizeChangedCommandProperty = DependencyProperty.Register(
+ nameof(SizeChangedCommand),
+ typeof(ICommand),
+ typeof(GroupNode),
+ new FrameworkPropertyMetadata(null));
+
+ public bool IsDraggingToResize { get; private set; } = false;
+
+ bool _IsInside = false;
+ bool _InternalPositionUpdating = false;
+
+ Rect _CapturedNodeRect;
+ DragResizeType _IsDraggingToResizeType = DragResizeType.None;
+ Border _GroupNodeHeader = null;
+
+ static GroupNode()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(GroupNode), new FrameworkPropertyMetadata(typeof(GroupNode)));
+ }
+
+ internal GroupNode(Canvas canvas, Point offset, double scale) : base(canvas, offset)
+ {
+ SizeChanged += Group_SizeChanged;
+ }
+
+ internal void Initialize()
+ {
+ // Implement if anything.
+ }
+
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ _GroupNodeHeader = (Border)GetTemplateChild("__GroupNodeHeader__");
+ _GroupNodeHeader.SizeChanged += GroupNodeHeader_SizeChanged;
+ }
+
+ internal void ExpandSize(Rect rect)
+ {
+ var oldPosition = Position;
+ var maxX = Math.Max(oldPosition.X + Width, rect.Right + BorderSize);
+ var maxY = Math.Max(oldPosition.Y + Height, rect.Bottom + BorderSize);
+
+ var x = rect.X - BorderSize;
+ var y = rect.Y - _GroupNodeHeader.ActualHeight - BorderSize;
+ UpdatePosition(Math.Min(x, Position.X), Math.Min(y, Position.Y));
+
+ var w = rect.Width + BorderSize * 2;
+ var h = rect.Height + BorderSize * 2 + _GroupNodeHeader.ActualHeight;
+ Width = Math.Max(w, maxX - Position.X);
+ Height = Math.Max(h, maxY - Position.Y);
+
+ UpdateInnerSize();
+ UpdateInnerPosition();
+ }
+
+ internal void CaptureToResizeDragging()
+ {
+ if (_IsDraggingToResizeType != DragResizeType.None)
+ {
+ IsDraggingToResize = true;
+ _CapturedNodeRect = new Rect(Position, new Size(ActualWidth, ActualHeight));
+ }
+ }
+
+ internal void ReleaseToResizeDragging()
+ {
+ IsDraggingToResize = false;
+ }
+
+ internal void Resize(in Point pos)
+ {
+ switch (_IsDraggingToResizeType)
+ {
+ case DragResizeType.LeftTop:
+ {
+ var x = _CapturedNodeRect.Right - pos.X > MinHeight ? pos.X : Position.X;
+ var y = _CapturedNodeRect.Bottom - pos.Y > MinHeight ? pos.Y : Position.Y;
+ Position = new Point(x, y);
+ Width = Math.Max(MinWidth, _CapturedNodeRect.Right - Position.X);
+ Height = Math.Max(MinWidth, _CapturedNodeRect.Bottom - Position.Y);
+ }
+ Mouse.SetCursor(Cursors.SizeNWSE);
+ break;
+ case DragResizeType.RightTop:
+ {
+ var h = _CapturedNodeRect.Bottom - pos.Y;
+ if (h > MinHeight)
+ {
+ Position = new Point(Position.X, pos.Y);
+ Height = Math.Max(MinHeight, h);
+ }
+ }
+ Width = Math.Max(MinWidth, pos.X - _CapturedNodeRect.X);
+ Mouse.SetCursor(Cursors.SizeNESW);
+ break;
+ case DragResizeType.LeftBottom:
+ {
+ var w = _CapturedNodeRect.Right - pos.X;
+ if (w > MinWidth)
+ {
+ Position = new Point(pos.X, Position.Y);
+ Width = Math.Max(MinWidth, w);
+ }
+ }
+ Height = Math.Max(MinHeight, pos.Y - _CapturedNodeRect.Y);
+ Mouse.SetCursor(Cursors.SizeNESW);
+ break;
+ case DragResizeType.RightBottom:
+ Width = Math.Max(MinWidth, pos.X - _CapturedNodeRect.X);
+ Height = Math.Max(MinHeight, pos.Y - _CapturedNodeRect.Y);
+ Mouse.SetCursor(Cursors.SizeNWSE);
+ break;
+ case DragResizeType.Top:
+ {
+ var h = _CapturedNodeRect.Bottom - pos.Y;
+ if (h > MinHeight)
+ {
+ Position = new Point(Position.X, pos.Y);
+ Height = Math.Max(MinHeight, h);
+ }
+ }
+ Mouse.SetCursor(Cursors.SizeNS);
+ break;
+ case DragResizeType.Bottom:
+ Height = Math.Max(MinHeight, pos.Y - _CapturedNodeRect.Y);
+ Mouse.SetCursor(Cursors.SizeNS);
+ break;
+ case DragResizeType.Left:
+ {
+ var w = _CapturedNodeRect.Right - pos.X;
+ if (w > MinWidth)
+ {
+ Position = new Point(pos.X, Position.Y);
+ Width = Math.Max(MinWidth, w);
+ }
+ }
+ Mouse.SetCursor(Cursors.SizeWE);
+ break;
+ case DragResizeType.Right:
+ Width = Math.Max(MinWidth, pos.X - _CapturedNodeRect.X);
+ Mouse.SetCursor(Cursors.SizeWE);
+ break;
+ }
+
+ UpdateInnerPosition();
+ }
+
+ internal void ChangeInnerColor(bool inside)
+ {
+ if (_IsInside != inside)
+ {
+ _IsInside = inside;
+ InnerColor = inside ? new SolidColorBrush(Color.FromArgb(128, 0, 255, 0)) : Brushes.Transparent;
+ }
+ }
+
+ internal bool IsInsideCompletely(in Rect rect)
+ {
+ return InnerPosition.X <= rect.X && rect.Right <= InnerPosition.X + InnerWidth
+ && InnerPosition.Y <= rect.Y && rect.Bottom <= InnerPosition.Y + InnerHeight;
+ }
+
+ internal bool IsInsideCompletely(Point pos)
+ {
+ return InnerPosition.X <= pos.X && pos.X <= InnerPosition.X + InnerWidth
+ && InnerPosition.Y <= pos.Y && pos.Y <= InnerPosition.Y + InnerHeight;
+ }
+
+ internal Rect GetInnerBoundingBox()
+ {
+ return new Rect(InnerPosition, new Size(InnerWidth, InnerHeight));
+ }
+
+ protected override void OnUpdateTranslation()
+ {
+ _InternalPositionUpdating = true;
+
+ InterlockPosition = Position;
+ UpdateInnerPosition();
+
+ _InternalPositionUpdating = false;
+ }
+
+ protected override void OnDisposing()
+ {
+ SizeChanged -= Group_SizeChanged;
+ _GroupNodeHeader.SizeChanged -= GroupNodeHeader_SizeChanged;
+ }
+
+ protected override void OnMouseEnter(MouseEventArgs e)
+ {
+ base.OnMouseEnter(e);
+ if (IsDraggingToResize == false)
+ {
+ UpdateMouseCursor(e);
+ }
+ }
+
+ protected override void OnMouseMove(MouseEventArgs e)
+ {
+ base.OnMouseMove(e);
+ if (IsDraggingToResize == false)
+ {
+ UpdateMouseCursor(e);
+ }
+ }
+
+ void UpdateMouseCursor(MouseEventArgs e)
+ {
+ var pos = e.GetPosition(this);
+ if (pos.X < BorderSize)
+ {
+ // left
+
+ // cursor is inside left vertical border.
+ if (pos.Y < BorderSize)
+ {
+ // top
+ _IsDraggingToResizeType = DragResizeType.LeftTop;
+ Mouse.SetCursor(Cursors.SizeNWSE);
+ }
+ else if (pos.Y > ActualHeight - BorderSize)
+ {
+ // bottom
+ _IsDraggingToResizeType = DragResizeType.LeftBottom;
+ Mouse.SetCursor(Cursors.SizeNESW);
+ }
+ else
+ {
+ // left
+ _IsDraggingToResizeType = DragResizeType.Left;
+ Mouse.SetCursor(Cursors.SizeWE);
+ }
+ }
+ else if (pos.X > ActualWidth - BorderSize)
+ {
+ // right
+
+ // cursor is inside right vertical border.
+ if (pos.Y < BorderSize)
+ {
+ // top
+ _IsDraggingToResizeType = DragResizeType.RightTop;
+ Mouse.SetCursor(Cursors.SizeNESW);
+ }
+ else if (pos.Y > ActualHeight - BorderSize)
+ {
+ // bottom
+ _IsDraggingToResizeType = DragResizeType.RightBottom;
+ Mouse.SetCursor(Cursors.SizeNWSE);
+ }
+ else
+ {
+ // right
+ _IsDraggingToResizeType = DragResizeType.Right;
+ Mouse.SetCursor(Cursors.SizeWE);
+ }
+ }
+ else
+ {
+ // middle
+ if (pos.Y < BorderSize)
+ {
+ _IsDraggingToResizeType = DragResizeType.Top;
+ Mouse.SetCursor(Cursors.SizeNS);
+ }
+ else if (pos.Y > ActualHeight - BorderSize)
+ {
+ _IsDraggingToResizeType = DragResizeType.Bottom;
+ Mouse.SetCursor(Cursors.SizeNS);
+ }
+ else
+ {
+ _IsDraggingToResizeType = DragResizeType.None;
+ }
+ }
+ }
+
+ void Group_SizeChanged(object sender, SizeChangedEventArgs e)
+ {
+ UpdateInnerSize();
+ UpdateInnerPosition();
+ SizeChangedCommand?.Execute(e.NewSize);
+ }
+
+ void GroupNodeHeader_SizeChanged(object sender, SizeChangedEventArgs e)
+ {
+ UpdateInnerSize();
+ UpdateInnerPosition();
+
+ Width = InnerWidth + BorderSize * 2;
+ Height = InnerHeight + _GroupNodeHeader.ActualHeight + BorderSize * 2;
+ UpdateLayout();
+ }
+
+ void UpdateInnerSize()
+ {
+ InnerWidth = Width - BorderSize * 2;
+ InnerHeight = Height - BorderSize * 2 - _GroupNodeHeader.ActualHeight;
+
+ // for notifying Width/Height immediately.
+ UpdateLayout();
+ }
+
+ void UpdateWidthFromInnerWidth()
+ {
+ Width = InnerWidth + BorderSize * 2;
+
+ // for notifying InnerWidth/InnerHeight immediately.
+ UpdateLayout();
+ }
+
+ void UpdateHeightFromInnerHeight()
+ {
+ Height = InnerHeight + _GroupNodeHeader.ActualHeight + BorderSize * 2;
+
+ // for notifying InnerWidth/InnerHeight immediately.
+ UpdateLayout();
+ }
+
+ void UpdateInnerPosition()
+ {
+ var diff_x = BorderSize;
+ var diff_y = _GroupNodeHeader.ActualHeight + BorderSize;
+ InnerPosition = new Point(Position.X + diff_x, Position.Y + diff_y);
+
+ // for notifying Position immediately.
+ UpdateLayout();
+ }
+
+ static void InterlockPositionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var groupNode = d as GroupNode;
+ if (groupNode._InternalPositionUpdating)
+ {
+ return;
+ }
+
+ var move = groupNode.InterlockPosition - groupNode.Position;
+
+ var otherNodes = groupNode.Canvas.Children.OfType().Where(arg => arg != groupNode).ToArray();
+ foreach (var node in otherNodes)
+ {
+ if (groupNode.IsInsideCompletely(node.GetBoundingBox()))
+ {
+ node.Position = node.Position + move;
+ }
+ }
+
+ groupNode.Position = groupNode.InterlockPosition;
+ }
+
+ static void InnerPositionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var groupNode = d as GroupNode;
+ if (groupNode._InternalPositionUpdating)
+ {
+ return;
+ }
+
+ var x = groupNode.InnerPosition.X - groupNode.BorderSize;
+ var y = groupNode.InnerPosition.Y - (groupNode._GroupNodeHeader.ActualHeight + groupNode.BorderSize);
+ groupNode.UpdatePosition(x, y);
+ }
+
+ static void InnerWidthPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var groupNode = d as GroupNode;
+
+ groupNode.UpdateWidthFromInnerWidth();
+ }
+
+ static void InnerHeightPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var groupNode = d as GroupNode;
+
+ groupNode.UpdateHeightFromInnerHeight();
+ }
+ }
+}
diff --git a/NodeGraph.NET7/Controls/GroupNode.xaml b/NodeGraph.NET7/Controls/GroupNode.xaml
new file mode 100644
index 0000000..afc7ee8
--- /dev/null
+++ b/NodeGraph.NET7/Controls/GroupNode.xaml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NodeGraph.NET7/Controls/ICanvasObject.cs b/NodeGraph.NET7/Controls/ICanvasObject.cs
new file mode 100644
index 0000000..80e9852
--- /dev/null
+++ b/NodeGraph.NET7/Controls/ICanvasObject.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Windows;
+
+namespace NodeGraph.NET7.Controls
+{
+ public interface ICanvasObject : IDisposable
+ {
+ Guid Guid { get; set; }
+ void UpdateOffset(Point offset);
+ }
+}
diff --git a/NodeGraph.NET7/Controls/ISelectableObject.cs b/NodeGraph.NET7/Controls/ISelectableObject.cs
new file mode 100644
index 0000000..b053e26
--- /dev/null
+++ b/NodeGraph.NET7/Controls/ISelectableObject.cs
@@ -0,0 +1,13 @@
+using System.Windows;
+
+namespace NodeGraph.NET7.Controls
+{
+ internal interface ISelectableObject
+ {
+ bool IsSelected { get; set; }
+ object DataContext { get; set; }
+
+ bool Contains(Rect rect);
+ bool IntersectsWith(Rect rect);
+ }
+}
diff --git a/NodeGraph.NET7/Controls/NodeBase.cs b/NodeGraph.NET7/Controls/NodeBase.cs
new file mode 100644
index 0000000..4f42e2b
--- /dev/null
+++ b/NodeGraph.NET7/Controls/NodeBase.cs
@@ -0,0 +1,155 @@
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Media;
+
+namespace NodeGraph.NET7.Controls
+{
+ public abstract class NodeBase : ContentControl, ICanvasObject, ISelectableObject, IDisposable
+ {
+ public Guid Guid
+ {
+ get => (Guid)GetValue(GuidProperty);
+ set => SetValue(GuidProperty, value);
+ }
+ public static readonly DependencyProperty GuidProperty = DependencyProperty.Register(
+ nameof(Guid),
+ typeof(Guid),
+ typeof(NodeBase),
+ new PropertyMetadata(Guid.NewGuid()));
+
+ public bool IsSelected
+ {
+ get => (bool)GetValue(IsSelectedProperty);
+ set => UpdateSelectedState(value);
+ }
+ public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register(
+ nameof(IsSelected),
+ typeof(bool),
+ typeof(NodeBase),
+ new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, IsSelectedPropertyChanged));
+
+ public Point Position
+ {
+ get => (Point)GetValue(PositionProperty);
+ set => SetValue(PositionProperty, value);
+ }
+ public static readonly DependencyProperty PositionProperty = DependencyProperty.Register(
+ nameof(Position),
+ typeof(Point),
+ typeof(NodeBase),
+ new FrameworkPropertyMetadata(new Point(0, 0), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, PositionPropertyChanged));
+
+ public Point DragStartPosition { get; private set; } = new Point(0, 0);
+
+ internal EventHandler BeginSelectionChanged { get; set; } = null;
+ internal EventHandler EndSelectionChanged { get; set; } = null;
+
+ protected Canvas Canvas { get; } = null;
+ protected Point Offset { get; private set; } = new Point(0, 0);
+ protected TranslateTransform Translate { get; private set; } = new TranslateTransform(0, 0);
+
+
+ internal NodeBase(Canvas canvas, Point offset)
+ {
+ Canvas = canvas;
+ Offset = offset;
+
+ Translate.X = Position.X + Offset.X;
+ Translate.Y = Position.Y + Offset.Y;
+
+ var transformGroup = new TransformGroup();
+ transformGroup.Children.Add(Translate);
+
+ RenderTransform = transformGroup;
+ }
+
+ internal Rect GetBoundingBox()
+ {
+ return new Rect(Position.X, Position.Y, ActualWidth, ActualHeight);
+ }
+
+ internal void CaptureDragStartPosition()
+ {
+ DragStartPosition = Position;
+ }
+
+ internal void UpdatePosition(double x, double y)
+ {
+ Position = new Point(x, y);
+
+ UpdateTranslation();
+ }
+
+ public void UpdateOffset(Point offset)
+ {
+ Offset = offset;
+
+ UpdateTranslation();
+
+ InvalidateVisual();
+ }
+
+ public bool Contains(Rect rect)
+ {
+ return rect.Contains(GetBoundingBox());
+ }
+
+ public bool IntersectsWith(Rect rect)
+ {
+ return GetBoundingBox().IntersectsWith(rect);
+ }
+
+ public void Dispose()
+ {
+ // You need to clear Style.
+ // Because implemented on style for binding.
+ Style = null;
+
+ // Clear binding for subscribing source changed event from old control.
+ // throw exception about visual tree ancestor different if you not clear binding.
+ BindingOperations.ClearAllBindings(this);
+
+ // Clear binding myself first.
+ // Because children throw exception about visual tree ancestor different when my Style to be null.
+ OnDisposing();
+ }
+
+ void UpdateSelectedState(bool value)
+ {
+ SetValue(IsSelectedProperty, value);
+ Panel.SetZIndex(this, value ? 1 : 0);
+ }
+
+ void UpdateTranslation()
+ {
+ Translate.X = Position.X + Offset.X;
+ Translate.Y = Position.Y + Offset.Y;
+
+ OnUpdateTranslation();
+ }
+
+ static void IsSelectedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var node = (NodeBase)d;
+
+ node.BeginSelectionChanged?.Invoke(node, EventArgs.Empty);
+
+ if (node.Focusable)
+ {
+ node.Focus();
+ }
+
+ node.EndSelectionChanged?.Invoke(node, EventArgs.Empty);
+ }
+
+ static void PositionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ (d as NodeBase).UpdateTranslation();
+ }
+
+ protected abstract void OnDisposing();
+ protected abstract void OnUpdateTranslation();
+ }
+}
diff --git a/NodeGraph.NET7/Controls/NodeConnector.cs b/NodeGraph.NET7/Controls/NodeConnector.cs
new file mode 100644
index 0000000..6179788
--- /dev/null
+++ b/NodeGraph.NET7/Controls/NodeConnector.cs
@@ -0,0 +1,378 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Data;
+using System.Windows.Media;
+
+namespace NodeGraph.NET7.Controls
+{
+ public abstract class NodeConnectorContent : ContentControl, IDisposable
+ {
+ public Guid Guid
+ {
+ get => (Guid)GetValue(GuidProperty);
+ set => SetValue(GuidProperty, value);
+ }
+ public static readonly DependencyProperty GuidProperty = DependencyProperty.Register(
+ nameof(Guid),
+ typeof(Guid),
+ typeof(NodeConnectorContent),
+ new PropertyMetadata(Guid.Empty));
+
+ public int ConnectedCount
+ {
+ get => (int)GetValue(ConnectedCountProperty);
+ private set => SetValue(ConnectedCountPropertyKey, value);
+ }
+ public static readonly DependencyPropertyKey ConnectedCountPropertyKey = DependencyProperty.RegisterReadOnly(
+ nameof(ConnectedCount),
+ typeof(int),
+ typeof(NodeConnectorContent),
+ new PropertyMetadata(0));
+
+ public static readonly DependencyProperty ConnectedCountProperty = ConnectedCountPropertyKey.DependencyProperty;
+
+ public bool IsConnected
+ {
+ get => (bool)GetValue(IsConnectedProperty);
+ private set => SetValue(IsConnectedPropertyKey, value);
+ }
+ public static readonly DependencyPropertyKey IsConnectedPropertyKey = DependencyProperty.RegisterReadOnly(
+ nameof(IsConnected),
+ typeof(bool),
+ typeof(NodeConnectorContent),
+ new PropertyMetadata(false));
+
+ public static readonly DependencyProperty IsConnectedProperty = IsConnectedPropertyKey.DependencyProperty;
+
+ public Brush Stroke
+ {
+ get => (Brush)GetValue(StrokeProperty);
+ set => SetValue(StrokeProperty, value);
+ }
+ public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register(
+ nameof(Stroke),
+ typeof(Brush),
+ typeof(NodeConnectorContent),
+ new FrameworkPropertyMetadata(Brushes.Blue));
+
+ public double StrokeThickness
+ {
+ get => (double)GetValue(StrokeThicknessProperty);
+ set => SetValue(StrokeThicknessProperty, value);
+ }
+ public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register(
+ nameof(StrokeThickness),
+ typeof(double),
+ typeof(NodeConnectorContent),
+ new FrameworkPropertyMetadata(1.0));
+
+ public Brush Fill
+ {
+ get => (Brush)GetValue(FillProperty);
+ set => SetValue(FillProperty, value);
+ }
+ public static readonly DependencyProperty FillProperty = DependencyProperty.Register(
+ nameof(Fill),
+ typeof(Brush),
+ typeof(NodeConnectorContent),
+ new FrameworkPropertyMetadata(Brushes.Gray));
+
+ public bool CanConnect
+ {
+ get => (bool)GetValue(CanConnectProperty);
+ set => SetValue(CanConnectProperty, value);
+ }
+ public static readonly DependencyProperty CanConnectProperty = DependencyProperty.Register(
+ nameof(CanConnect),
+ typeof(bool),
+ typeof(NodeConnectorContent),
+ new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsRender));
+
+ public Point Position
+ {
+ get => _Position;
+ set => UpdatePosition(value);
+ }
+
+ public DefaultNode Node { get; private set; } = null;
+
+ ///
+ /// connecting node links.
+ ///
+ public IEnumerable NodeLinks => _NodeLinks;
+ List _NodeLinks = new List();
+
+ protected abstract FrameworkElement ConnectorControl { get; }
+
+ Point _Position = new Point();
+ TranslateTransform _Translate = new TranslateTransform();
+
+ static public bool CanConnectEachOther(NodeConnectorContent start, NodeConnectorContent toEnd)
+ {
+ return start.CanConnectTo(toEnd) && toEnd.CanConnectTo(start);
+ }
+
+ public NodeConnectorContent()
+ {
+ var transfromGroup = new TransformGroup();
+ transfromGroup.Children.Add(_Translate);
+ RenderTransform = transfromGroup;
+ }
+
+ public void Initialize()
+ {
+ var parent = VisualTreeHelper.GetParent(this);
+ while (parent.GetType() != typeof(DefaultNode))
+ {
+ parent = VisualTreeHelper.GetParent(parent);
+ }
+
+ Node = parent as DefaultNode;
+ }
+
+ public void Dispose()
+ {
+ // You need to clear Style.
+ // Because implemented on style for binding.
+ Style = null;
+
+ // Clear binding for subscribing source changed event from old control.
+ // throw exception about visual tree ancestor different if you not clear binding.
+ BindingOperations.ClearAllBindings(this);
+
+ var nodeLinks = _NodeLinks.ToArray();
+
+ // it must instance to nodeLinks because change node link collection in NodeLink Dispose.
+ foreach (var nodeLink in nodeLinks)
+ {
+ nodeLink.Dispose();
+ }
+ }
+
+ public void Connect(NodeLink nodeLink)
+ {
+ _NodeLinks.Add(nodeLink);
+ ConnectedCount = _NodeLinks.Count;
+ IsConnected = ConnectedCount > 0;
+ }
+
+ public void Disconnect(NodeLink nodeLink)
+ {
+ _NodeLinks.Remove(nodeLink);
+ ConnectedCount = _NodeLinks.Count;
+ IsConnected = ConnectedCount > 0;
+ }
+
+ public Point GetContentPosition(Canvas canvas, double xScaleOffset = 0.5, double yScaleOffset = 0.5)
+ {
+ // it will be shifted Control position if not called UpdateLayout().
+ ConnectorControl.UpdateLayout();
+ var transformer = ConnectorControl.TransformToVisual(canvas);
+
+ var x = ConnectorControl.ActualWidth * xScaleOffset;
+ var y = ConnectorControl.ActualHeight * yScaleOffset;
+ return transformer.Transform(new Point(x, y));
+ }
+
+ public abstract void UpdateLinkPosition(Canvas canvas);
+ public abstract bool CanConnectTo(NodeConnectorContent connector);
+
+ void UpdatePosition(Point pos)
+ {
+ _Position = pos;
+ _Translate.X = _Position.X;
+ _Translate.Y = _Position.Y;
+
+ InvalidateVisual();
+ }
+ }
+
+ public abstract class NodeConnector : MultiSelector, IDisposable where T : NodeConnectorContent, new()
+ {
+ public Thickness ConnectorMargin
+ {
+ get => (Thickness)GetValue(ConnectorMarginProperty);
+ set => SetValue(ConnectorMarginProperty, value);
+ }
+ public static readonly DependencyProperty ConnectorMarginProperty = DependencyProperty.Register(
+ nameof(ConnectorMargin),
+ typeof(Thickness),
+ typeof(NodeConnector),
+ new FrameworkPropertyMetadata(new Thickness(2.0), ConnectorMarginPropertyChanged));
+
+ ///
+ /// must implement connector canvas name.
+ ///
+ protected abstract string ConnectorCanvasName { get; }
+
+ ///
+ /// must implement connector content template.
+ ///
+ protected abstract ControlTemplate NodeConnectorContentTemplate { get; }
+
+ ///
+ /// must implement connector content style.
+ ///
+ protected abstract Style NodeConnectorContentBaseStyle { get; }
+
+ Canvas _Canvas = null;
+
+
+ static void ConnectorMarginPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ (d as NodeConnector).UpdateConnectorsLayout();
+ }
+
+ public void Initialize()
+ {
+ foreach (var connector in _Canvas.Children.OfType())
+ {
+ // ItemContainerStyle is still null during applying template, so need to apply at initialize.(ApplyTemplate later)
+ connector.Style = ItemContainerStyle;
+ connector.Initialize();
+ }
+ }
+
+ public void Dispose()
+ {
+ // You need to clear Style.
+ // Because implemented on style for binding.
+ Style = null;
+
+ // Clear binding for subscribing source changed event from old control.
+ // throw exception about visual tree ancestor different if you not clear binding.
+ BindingOperations.ClearAllBindings(this);
+
+ var connectors = _Canvas.Children.OfType().ToArray();
+
+ foreach (var connector in connectors)
+ {
+ connector.Dispose();
+ }
+ }
+
+ public NodeLink[] EnumerateConnectedNodeLinks()
+ {
+ var connectors = _Canvas.Children.OfType().ToArray();
+ return connectors.SelectMany(arg => arg.NodeLinks).ToArray();
+ }
+
+ public T FindNodeConnector(Guid guid)
+ {
+ var connectors = _Canvas.Children.OfType().ToArray();
+ return connectors.FirstOrDefault(arg => arg.Guid == guid);
+ }
+
+ public void UpdateLinkPosition(Canvas canvas)
+ {
+ if (_Canvas == null)
+ {
+ return;
+ }
+
+ foreach (var connector in _Canvas.Children.OfType())
+ {
+ connector.UpdateLinkPosition(canvas);
+ }
+ }
+
+ public void UpdateConnectorsLayout()
+ {
+ if (_Canvas == null)
+ {
+ return;
+ }
+
+ ReplaceConnectElements(0);
+
+ var connectorContents = _Canvas.Children.OfType();
+
+ if (connectorContents.Count() > 0)
+ {
+ var numElement = connectorContents.Count();
+ Width = connectorContents.Max(arg => arg.ActualWidth);
+ Height = connectorContents.Sum(arg => arg.ActualHeight) + numElement * (ConnectorMargin.Top + ConnectorMargin.Bottom) + numElement; // last adding numElement is 1px border each other.
+ }
+ }
+
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ _Canvas = GetTemplateChild(ConnectorCanvasName) as Canvas;
+ }
+
+ protected override void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
+ {
+ base.OnItemsSourceChanged(oldValue, newValue);
+
+ if (oldValue != null)
+ {
+ RemoveConnectorFromCanvas(oldValue.OfType
diff --git a/NodeGraph.NET7/Controls/NodeInput.cs b/NodeGraph.NET7/Controls/NodeInput.cs
new file mode 100644
index 0000000..eb85635
--- /dev/null
+++ b/NodeGraph.NET7/Controls/NodeInput.cs
@@ -0,0 +1,91 @@
+using NodeGraph.NET7.Utilities;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace NodeGraph.NET7.Controls
+{
+ public class NodeInputContent : NodeConnectorContent
+ {
+ public bool AllowToConnectMultiple
+ {
+ get => (bool)GetValue(AllowToConnectMultipleProperty);
+ set => SetValue(AllowToConnectMultipleProperty, value);
+ }
+ public static readonly DependencyProperty AllowToConnectMultipleProperty = DependencyProperty.Register(
+ nameof(AllowToConnectMultiple),
+ typeof(bool),
+ typeof(NodeInputContent),
+ new PropertyMetadata(false));
+
+ public static bool AllowToOverrideConnection { get; set; } = false;
+
+ protected override FrameworkElement ConnectorControl => _ConnectorControl;
+ FrameworkElement _ConnectorControl = null;
+
+
+ static NodeInputContent()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(NodeInputContent), new FrameworkPropertyMetadata(typeof(NodeInputContent)));
+ }
+
+ public override void OnApplyTemplate()
+ {
+ _ConnectorControl = GetTemplateChild("__InputConnector__") as FrameworkElement;
+
+ base.OnApplyTemplate();
+ }
+
+ public override void UpdateLinkPosition(Canvas canvas)
+ {
+ var transformer = _ConnectorControl.TransformToVisual(canvas);
+ var posOnCanvas = transformer.Transform(new Point(0, _ConnectorControl.ActualHeight * 0.5));
+
+ foreach (var nodeLink in NodeLinks)
+ {
+ nodeLink.UpdateInputEdge(posOnCanvas.X, posOnCanvas.Y);
+ }
+ }
+
+ public override bool CanConnectTo(NodeConnectorContent connector)
+ {
+ if (AllowToOverrideConnection == false && ConnectedCount > 0 && AllowToConnectMultiple == false)
+ {
+ // already connected to other node link.
+ return false;
+ }
+ if ((CanConnect && connector is NodeOutputContent && Node != connector.Node) == false)
+ {
+ return false;
+ }
+
+ // check for circulation connecting.
+ var nodeLinks = connector.Node.EnumrateConnectedNodeLinks();
+ foreach (var nodeLink in nodeLinks)
+ {
+ if (nodeLink.Output?.Node == Node)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ public class NodeInput : NodeConnector
+ {
+ protected override string ConnectorCanvasName => "__NodeInputCanvas__";
+
+ protected override ControlTemplate NodeConnectorContentTemplate => _NodeInputTemplate.Get("__NodeInputContentTemplate__");
+ ResourceInstance _NodeInputTemplate = new ResourceInstance();
+
+ protected override Style NodeConnectorContentBaseStyle => _NodeConnectorContentBaseStyle.Get("__NodeInputBaseStyle__");
+ ResourceInstance
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NodeGraph.NET7/Controls/NodeLink.cs b/NodeGraph.NET7/Controls/NodeLink.cs
new file mode 100644
index 0000000..06daaeb
--- /dev/null
+++ b/NodeGraph.NET7/Controls/NodeLink.cs
@@ -0,0 +1,422 @@
+using NodeGraph.NET7.Extensions;
+using System;
+using System.Data;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Media;
+using System.Windows.Shapes;
+
+namespace NodeGraph.NET7.Controls
+{
+ public enum NodeLinkType
+ {
+ Line,
+ Curve
+ }
+
+ public class NodeLink : Shape, ICanvasObject, ISelectableObject
+ {
+ public Guid Guid
+ {
+ get => (Guid)GetValue(GuidProperty);
+ set => SetValue(GuidProperty, value);
+ }
+ public static readonly DependencyProperty GuidProperty = DependencyProperty.Register(
+ nameof(Guid),
+ typeof(Guid),
+ typeof(NodeLink),
+ new FrameworkPropertyMetadata(Guid.NewGuid()));
+
+ public Guid InputConnectorGuid
+ {
+ get => (Guid)GetValue(InputConnectorGuidProperty);
+ set => SetValue(InputConnectorGuidProperty, value);
+ }
+ public static readonly DependencyProperty InputConnectorGuidProperty = DependencyProperty.Register(
+ nameof(InputConnectorGuid),
+ typeof(Guid),
+ typeof(NodeLink),
+ new FrameworkPropertyMetadata(Guid.NewGuid()));
+
+ public Guid OutputConnectorGuid
+ {
+ get => (Guid)GetValue(OutputConnectorGuidProperty);
+ set => SetValue(OutputConnectorGuidProperty, value);
+ }
+ public static readonly DependencyProperty OutputConnectorGuidProperty = DependencyProperty.Register(
+ nameof(OutputConnectorGuid),
+ typeof(Guid),
+ typeof(NodeLink),
+ new FrameworkPropertyMetadata(Guid.NewGuid()));
+
+ public double LinkSize
+ {
+ get => (double)GetValue(LinkSizeProperty);
+ set => SetValue(LinkSizeProperty, value);
+ }
+ public static readonly DependencyProperty LinkSizeProperty =
+ DependencyProperty.Register(nameof(LinkSize), typeof(double), typeof(NodeLink), new FrameworkPropertyMetadata(2.0));
+
+ public double DashOffset
+ {
+ get => (double)GetValue(DashOffsetProperty);
+ set => SetValue(DashOffsetProperty, value);
+ }
+ public static readonly DependencyProperty DashOffsetProperty =
+ DependencyProperty.Register(nameof(DashOffset), typeof(double), typeof(NodeLink), new FrameworkPropertyMetadata(0.0, DashOffsetPropertyChanged));
+
+ public NodeLinkType LinkType
+ {
+ get => (NodeLinkType)GetValue(LinkTypeProperty);
+ set => SetValue(LinkTypeProperty, value);
+ }
+ public static readonly DependencyProperty LinkTypeProperty =
+ DependencyProperty.Register(nameof(LinkType), typeof(NodeLinkType), typeof(NodeLink), new FrameworkPropertyMetadata(NodeLinkType.Curve, LinkTypePropertyChanged));
+
+ public bool IsLocked
+ {
+ get => (bool)GetValue(IsLockedProperty);
+ set => SetValue(IsLockedProperty, value);
+ }
+ public static readonly DependencyProperty IsLockedProperty =
+ DependencyProperty.Register(nameof(IsLocked), typeof(bool), typeof(NodeLink), new FrameworkPropertyMetadata(false));
+
+ public bool IsSelected
+ {
+ get => (bool)GetValue(IsSelectedProperty);
+ set => SetValue(IsSelectedProperty, value);
+ }
+ public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register(
+ nameof(IsSelected), typeof(bool), typeof(NodeLink), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
+
+ static void DashOffsetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var nodeLink = (NodeLink)d;
+ nodeLink.InvalidateVisual();
+ }
+
+ static void LinkTypePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var nodeLink = (NodeLink)d;
+ nodeLink.InvalidateVisual();
+ }
+
+ public bool IsConnecting => Input != null && Output != null;
+
+ public NodeInputContent Input { get; private set; } = null;
+ public NodeOutputContent Output { get; private set; } = null;
+
+ public NodeConnectorContent StartConnector { get; private set; } = null;
+ public NodeConnectorContent ToEndConnector { get; private set; } = null;
+
+ protected override Geometry DefiningGeometry => StreamGeometry;
+
+ double EndPointX => _EndPoint.X / _Scale;
+ double EndPointY => _EndPoint.Y / _Scale;
+ Point _EndPoint = new Point(0, 0);
+
+ double StartPointX => _StartPoint.X / _Scale;
+ double StartPointY => _StartPoint.Y / _Scale;
+ Point _StartPoint = new Point(0, 0);
+
+ Canvas Canvas { get; } = null;
+
+ double _Scale = 1.0f;
+ Point _Offset = new Point(0, 0);
+ Point _RestoreEndPoint = new Point();
+
+ readonly StreamGeometry StreamGeometry = new StreamGeometry();
+
+ static NodeLink()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(NodeLink), new FrameworkPropertyMetadata(typeof(NodeLink)));
+ }
+
+ internal NodeLink(Canvas canvas, double scale, Point offset)
+ {
+ // constructed from view model or other constructors.
+ Canvas = canvas;
+
+ IsHitTestVisible = false; // no need to hit until connected
+
+ _Scale = scale;
+ _Offset = offset;
+
+ var transformGroup = new TransformGroup();
+ transformGroup.Children.Add(new ScaleTransform() { ScaleX = scale, ScaleY = scale });
+ RenderTransform = transformGroup;
+ RenderTransformOrigin = new Point(0.5, 0.5);
+
+ Panel.SetZIndex(this, -1);
+ }
+
+ internal NodeLink(NodeConnectorContent connector, double x, double y, Canvas canvas, double scale, Point offset) : this(x, y, canvas, scale, offset)
+ {
+ // constructed from view for previewing node link.
+ switch (connector)
+ {
+ case NodeInputContent input:
+ Input = input;
+ StartConnector = input;
+ break;
+ case NodeOutputContent output:
+ Output = output;
+ StartConnector = output;
+ break;
+ default:
+ throw new InvalidCastException($"Cannot cast this connector. {connector}");
+ }
+ }
+
+ NodeLink(double x, double y, Canvas canvas, double scale, Point offset) : this(canvas, scale, offset)
+ {
+ // create from view for preview reconnecting link.
+ var point = new Point(x, y);
+ _StartPoint = point;
+ _EndPoint = point;
+ }
+
+ public bool Contains(Rect rect)
+ {
+ var test = Rect.Offset(RenderedGeometry.Bounds, -_Offset.X, -_Offset.Y);
+ return rect.Contains(test);
+ }
+
+ public bool IntersectsWith(Rect rect)
+ {
+ var test = Rect.Offset(RenderedGeometry.Bounds, -_Offset.X, -_Offset.Y);
+ return rect.IntersectsWith(test);
+ }
+
+ internal NodeLink CreateGhost()
+ {
+ var ghost = new NodeLink(Canvas, _Scale, _Offset);
+ ghost.DataContext = null; // ghost link cannot binding connector properties. so you have to bind null to DataContext.(otherwise, occur binding errors)
+ ghost._StartPoint = _StartPoint;
+ ghost._EndPoint = _EndPoint;
+ ghost.IsHitTestVisible = false;
+ ghost.Fill = new SolidColorBrush(Color.FromArgb(128, 128, 128, 128));
+
+ return ghost;
+ }
+
+ internal void Validate()
+ {
+ if (Guid == Guid.Empty || InputConnectorGuid == Guid.Empty || OutputConnectorGuid == Guid.Empty)
+ {
+ throw new DataException("Does not assigned guid");
+ }
+ }
+
+ public void Dispose()
+ {
+ // You need to clear Style.
+ // Because implemented on style for binding.
+ Style = null;
+
+ // Clear binding for subscribing source changed event from old control.
+ // throw exception about visual tree ancestor different if you not clear binding.
+ BindingOperations.ClearAllBindings(this);
+
+ Input?.Disconnect(this);
+ Input = null;
+ Output?.Disconnect(this);
+ Output = null;
+ }
+
+ internal void Connect(NodeInputContent input, NodeOutputContent output)
+ {
+ Input?.Disconnect(this);
+ Output?.Disconnect(this);
+
+ Input = input;
+ Output = output;
+
+ StartConnector = Output;
+ ToEndConnector = Input;
+
+ IsHitTestVisible = true;
+
+ UpdateConnectPosition();
+
+ InvalidateVisual();
+ }
+
+ public void UpdateOffset(Point offset)
+ {
+ _Offset = offset;
+
+ UpdateConnectPosition();
+
+ InvalidateVisual();
+ }
+
+ internal void UpdateEdgePoint(double x, double y)
+ {
+ if (Input == null)
+ {
+ // first connected output to input.
+ _EndPoint = new Point(x, y);
+ }
+ else if (Output == null)
+ {
+ // first connected input to output.
+ _StartPoint = new Point(x, y);
+ }
+ else
+ {
+ // reconnected point.
+ _EndPoint = new Point(x, y);
+ }
+
+ InvalidateVisual();
+ }
+
+ internal void ReleaseEndPoint()
+ {
+ IsHitTestVisible = false;
+ _RestoreEndPoint = _EndPoint;
+ }
+
+ internal void RestoreEndPoint()
+ {
+ IsHitTestVisible = true;
+ UpdateEdgePoint(_RestoreEndPoint.X, _RestoreEndPoint.Y);
+ }
+
+ internal void UpdateInputEdge(double x, double y)
+ {
+ _EndPoint = new Point(x, y);
+ InvalidateVisual();
+ }
+
+ internal void UpdateOutputEdge(double x, double y)
+ {
+ _StartPoint = new Point(x, y);
+ InvalidateVisual();
+ }
+
+ protected override void OnRender(DrawingContext drawingContext)
+ {
+ switch (LinkType)
+ {
+ case NodeLinkType.Line:
+ DrawLine(drawingContext);
+ break;
+ case NodeLinkType.Curve:
+ DrawCurve(drawingContext);
+ break;
+ }
+ }
+
+ void UpdateConnectPosition()
+ {
+ _EndPoint = Input.GetContentPosition(Canvas, 0, 0.5);
+ _StartPoint = Output.GetContentPosition(Canvas, 0.5, 0.5);
+ }
+
+ void DrawLine(DrawingContext drawingContext)
+ {
+ var start = new Point(StartPointX, StartPointY);
+ var end = new Point(EndPointX, EndPointY);
+
+ double linkSize = LinkSize * (1.0f / _Scale);
+
+ // collision
+ if (IsHitTestVisible)
+ {
+ var hitVisiblePen = new Pen(Brushes.Transparent, linkSize + StrokeThickness);
+ hitVisiblePen.Freeze();
+ drawingContext.DrawLine(hitVisiblePen, start, end);
+ }
+
+ // actually visual
+ var visualPen = new Pen(Fill, linkSize);
+ if (IsMouseOver)
+ {
+ visualPen.DashStyle = new DashStyle(new double[] { 2 }, DashOffset);
+ }
+ visualPen.Freeze();
+
+ drawingContext.DrawLine(visualPen, start, end);
+
+ // arrow
+ var vEnd = new Vector(EndPointX, EndPointY);
+ var vStart = new Vector(StartPointX, StartPointY);
+ var degree = Vector.AngleBetween(vStart - vEnd, vStart);
+
+ if (IsConnecting == false)
+ {
+ return;
+ }
+
+ var segment = vStart - vEnd;
+ segment.Normalize();
+
+ Matrix rotMat = new Matrix();
+ {
+ rotMat.Rotate(30);
+
+ var arrow = Vector.Multiply(segment, rotMat);
+ drawingContext.DrawLine(visualPen, end, arrow * 12 + end);
+ }
+ {
+ rotMat.Rotate(-60);
+
+ var arrow = Vector.Multiply(segment, rotMat);
+ drawingContext.DrawLine(visualPen, end, arrow * 12 + end);
+ }
+ }
+
+ void DrawCurve(DrawingContext drawingContext)
+ {
+ var start = new Point(StartPointX, StartPointY);
+ var end = new Point(EndPointX, EndPointY);
+
+ Point c0 = new Point();
+ Point c1 = new Point();
+ double power = 100;
+
+ var pen = new Pen(Brushes.Green, 2);
+
+ var axis = new Vector(1, 0);
+ var startToEnd = (end.ToVector() - start.ToVector()).NormalizeTo();
+
+ var k = 1 - Math.Pow(Math.Max(0, axis.DotProduct(startToEnd)), 10.0);
+ var bias = start.X > end.X ? Math.Abs(start.X - end.X) * 0.25 : 0;
+
+ c0 = new Point(+(power + bias) * k + start.X, start.Y);
+ c1 = new Point(-(power + bias) * k + end.X, end.Y);
+
+ StreamGeometry.Clear();
+
+ using (var context = StreamGeometry.Open())
+ {
+ context.BeginFigure(start, true, false);
+ context.BezierTo(c0, c1, end, true, false);
+ }
+
+ double linkSize = LinkSize * (1.0f / _Scale);
+
+ // collision
+ if (IsHitTestVisible)
+ {
+ var hitVisiblePen = new Pen(Brushes.Transparent, linkSize + StrokeThickness);
+ hitVisiblePen.Freeze();
+ drawingContext.DrawGeometry(null, hitVisiblePen, StreamGeometry);
+ }
+
+ // actually visual
+ var visualPen = new Pen(Fill, linkSize);
+ if (IsMouseOver)
+ {
+ visualPen.DashStyle = new DashStyle(new double[] { 2 }, DashOffset);
+ }
+
+ visualPen.Freeze();
+
+ drawingContext.DrawGeometry(null, visualPen, StreamGeometry);
+ }
+ }
+}
diff --git a/NodeGraph.NET7/Controls/NodeLink.xaml b/NodeGraph.NET7/Controls/NodeLink.xaml
new file mode 100644
index 0000000..5eaf9ae
--- /dev/null
+++ b/NodeGraph.NET7/Controls/NodeLink.xaml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NodeGraph.NET7/Controls/NodeOuput.cs b/NodeGraph.NET7/Controls/NodeOuput.cs
new file mode 100644
index 0000000..eeb880a
--- /dev/null
+++ b/NodeGraph.NET7/Controls/NodeOuput.cs
@@ -0,0 +1,72 @@
+using NodeGraph.NET7.Utilities;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace NodeGraph.NET7.Controls
+{
+ public class NodeOutputContent : NodeConnectorContent
+ {
+ protected override FrameworkElement ConnectorControl => _ConnectorControl;
+ FrameworkElement _ConnectorControl = null;
+
+ static NodeOutputContent()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(NodeOutputContent), new FrameworkPropertyMetadata(typeof(NodeOutputContent)));
+ }
+
+ public override void OnApplyTemplate()
+ {
+ _ConnectorControl = GetTemplateChild("__OutputConnector__") as FrameworkElement;
+
+ base.OnApplyTemplate();
+ }
+
+ public override void UpdateLinkPosition(Canvas canvas)
+ {
+ var transformer = ConnectorControl.TransformToVisual(canvas);
+ var posOnCanvas = transformer.Transform(new Point(ConnectorControl.ActualWidth * 0.5, ConnectorControl.ActualHeight * 0.5));
+
+ foreach (var nodeLink in NodeLinks)
+ {
+ nodeLink.UpdateOutputEdge(posOnCanvas.X, posOnCanvas.Y);
+ }
+ }
+
+ public override bool CanConnectTo(NodeConnectorContent connector)
+ {
+ if ((CanConnect && connector is NodeInputContent && Node != connector.Node) == false)
+ {
+ return false;
+ }
+
+ // check for circulation connecting.
+ var nodeLinks = connector.Node.EnumrateConnectedNodeLinks();
+ foreach (var nodeLink in nodeLinks)
+ {
+ if (nodeLink.Input?.Node == Node)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ public class NodeOutput : NodeConnector
+ {
+ protected override string ConnectorCanvasName => "__NodeOutputCanvas__";
+
+ protected override ControlTemplate NodeConnectorContentTemplate => _NodeOutputTemplate.Get("__NodeOutputContentTemplate__");
+
+ protected override Style NodeConnectorContentBaseStyle => _NodeConnectorContentBaseStyle.Get("__NodeOutputBaseStyle__");
+ ResourceInstance
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NodeGraph.NET7/Controls/RangeSelector.cs b/NodeGraph.NET7/Controls/RangeSelector.cs
new file mode 100644
index 0000000..055e640
--- /dev/null
+++ b/NodeGraph.NET7/Controls/RangeSelector.cs
@@ -0,0 +1,56 @@
+using System.Windows;
+using System.Windows.Media;
+using System.Windows.Shapes;
+
+namespace NodeGraph.NET7.Controls
+{
+ public class RangeSelector : Shape
+ {
+ public Rect RangeRect
+ {
+ get => (Rect)GetValue(RangeRectProperty);
+ set => SetValue(RangeRectProperty, value);
+ }
+ public static readonly DependencyProperty RangeRectProperty = DependencyProperty.Register(
+ nameof(RangeRect),
+ typeof(Rect),
+ typeof(RangeSelector),
+ new FrameworkPropertyMetadata(new Rect(), FrameworkPropertyMetadataOptions.AffectsRender));
+
+ public bool IsIntersects
+ {
+ get => (bool)GetValue(IsIntersectsProperty);
+ set => SetValue(IsIntersectsProperty, value);
+ }
+ public static readonly DependencyProperty IsIntersectsProperty = DependencyProperty.Register(
+ nameof(IsIntersects),
+ typeof(bool),
+ typeof(RangeSelector),
+ new FrameworkPropertyMetadata(false));
+
+ protected override Geometry DefiningGeometry => Geometry.Empty;
+
+ Pen _StrokePen = null;
+
+ static RangeSelector()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(RangeSelector), new FrameworkPropertyMetadata(typeof(RangeSelector)));
+ }
+
+ public void Reset(Point pos)
+ {
+ RangeRect = new Rect(pos, Size.Empty);
+ IsIntersects = false;
+ }
+
+ protected override void OnRender(DrawingContext drawingContext)
+ {
+ base.OnRender(drawingContext);
+
+ _StrokePen = new Pen(Stroke, StrokeThickness);
+ _StrokePen.Freeze();
+
+ drawingContext.DrawRectangle(Fill, _StrokePen, RangeRect);
+ }
+ }
+}
diff --git a/NodeGraph.NET7/Controls/RangeSelector.xaml b/NodeGraph.NET7/Controls/RangeSelector.xaml
new file mode 100644
index 0000000..05a2e1e
--- /dev/null
+++ b/NodeGraph.NET7/Controls/RangeSelector.xaml
@@ -0,0 +1,17 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/NodeGraph.NET7/Controls/Ruler.cs b/NodeGraph.NET7/Controls/Ruler.cs
new file mode 100644
index 0000000..1fd32be
--- /dev/null
+++ b/NodeGraph.NET7/Controls/Ruler.cs
@@ -0,0 +1,143 @@
+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace NodeGraph.NET7.Controls
+{
+ internal class Ruler : ContentControl
+ {
+ public double Scale
+ {
+ get => (double)GetValue(ScaleProperty);
+ set => SetValue(ScaleProperty, value);
+ }
+ public static readonly DependencyProperty ScaleProperty =
+ DependencyProperty.Register(nameof(Scale), typeof(double), typeof(Ruler), new FrameworkPropertyMetadata(1.0, FrameworkPropertyMetadataOptions.AffectsRender));
+
+ public Point Offset
+ {
+ get => (Point)GetValue(OffsetProperty);
+ set => SetValue(OffsetProperty, value);
+ }
+ public static readonly DependencyProperty OffsetProperty =
+ DependencyProperty.Register(nameof(Offset), typeof(Point), typeof(Ruler), new FrameworkPropertyMetadata(new Point(0, 0), FrameworkPropertyMetadataOptions.AffectsRender));
+
+ public Brush Color
+ {
+ get => (Brush)GetValue(ColorProperty);
+ set => SetValue(ColorProperty, value);
+ }
+ public static readonly DependencyProperty ColorProperty =
+ DependencyProperty.Register(nameof(Color), typeof(Brush), typeof(Ruler), new FrameworkPropertyMetadata(Brushes.Black, ColorPropertyChanged));
+
+ public Orientation Orientation
+ {
+ get => (Orientation)GetValue(OrientationProperty);
+ set => SetValue(OrientationProperty, value);
+ }
+ public static readonly DependencyProperty OrientationProperty =
+ DependencyProperty.Register(nameof(Orientation), typeof(Orientation), typeof(Ruler), new FrameworkPropertyMetadata(Orientation.Horizontal));
+
+ Pen _Pen = null;
+ static Typeface Typeface = new Typeface("Verdana");
+ static double LineOffset = 3;
+ static double LineLength = 5 + LineOffset;
+ static double LineDistance = 100;
+ static double SubLineOffset = 1;
+ static double SubLineLength = 5 + SubLineOffset;
+ static double SubLineDistance = LineDistance / 10;
+
+ static void ColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ (d as Ruler).UpdatePen();
+ }
+
+ static Ruler()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(Ruler), new FrameworkPropertyMetadata(typeof(Ruler)));
+ }
+
+ public Ruler()
+ {
+
+ }
+
+ protected override void OnRender(DrawingContext drawingContext)
+ {
+ base.OnRender(drawingContext);
+
+ if (_Pen == null)
+ {
+ UpdatePen();
+ }
+
+ switch (Orientation)
+ {
+ case Orientation.Horizontal:
+ OnRenderHorizontal(drawingContext);
+ break;
+ case Orientation.Vertical:
+ OnRenderVertical(drawingContext);
+ break;
+ }
+ }
+
+ void OnRenderHorizontal(DrawingContext dc)
+ {
+ double s = Math.Max(Scale, 1);
+ double numScale = Math.Max(1.0 / Scale, 1);
+
+ int init = (int)(-Offset.X / LineDistance) - 1;
+ int count = (int)((-Offset.X + ActualWidth) / LineDistance) + 1;
+ for (int i = init; i < count; ++i)
+ {
+ double num = i * LineDistance;
+ double x = (num + Offset.X) * s;
+ dc.DrawLine(_Pen, new Point(x, LineOffset), new Point(x, LineLength));
+
+ for (int j = 1; j < 10; ++j)
+ {
+ double sub_x = x + j * SubLineDistance * s;
+ dc.DrawLine(_Pen, new Point(sub_x, SubLineOffset), new Point(sub_x, SubLineLength));
+ }
+
+ int numText = (int)(num * numScale);
+ var text = new FormattedText($"{numText}", CultureInfo.CurrentCulture, FlowDirection.LeftToRight, Typeface, 8, Color, 1.0);
+ dc.DrawText(text, new Point(x - text.Width * 0.5, LineLength));
+ }
+ }
+
+ void OnRenderVertical(DrawingContext dc)
+ {
+ double s = Math.Max(Scale, 1);
+ double numScale = Math.Max(1.0 / Scale, 1);
+
+ int init = (int)(-Offset.Y / LineDistance) - 1;
+ int count = (int)((-Offset.Y + ActualHeight) / LineDistance) + 1;
+ for (int i = init; i < count; ++i)
+ {
+ double num = i * LineDistance;
+ double y = (num + Offset.Y) * s;
+ dc.DrawLine(_Pen, new Point(LineOffset, y), new Point(LineLength, y));
+
+ for (int j = 1; j < 10; ++j)
+ {
+ double sub_y = y + j * SubLineDistance * s;
+ dc.DrawLine(_Pen, new Point(SubLineOffset, sub_y), new Point(SubLineLength, sub_y));
+ }
+
+ int numText = (int)(num * numScale);
+ var text = new FormattedText($"{numText}", CultureInfo.CurrentCulture, FlowDirection.LeftToRight, Typeface, 8, Color, 1.0);
+ dc.DrawText(text, new Point(LineLength + LineOffset, y - text.Height * 0.5));
+ }
+ }
+
+ void UpdatePen()
+ {
+ _Pen = new Pen(Color, 1);
+ _Pen.Freeze();
+ }
+ }
+}
diff --git a/NodeGraph.NET7/Controls/StaticDefinition.cs b/NodeGraph.NET7/Controls/StaticDefinition.cs
new file mode 100644
index 0000000..1304997
--- /dev/null
+++ b/NodeGraph.NET7/Controls/StaticDefinition.cs
@@ -0,0 +1,15 @@
+namespace NodeGraph.NET7.Controls
+{
+ public static class ControlSize
+ {
+ public const double ConnectorSize = 13;
+ }
+
+ public static class GroupNodeDefault
+ {
+ public const double Width = 500;
+ public const double Height = 300;
+ public const double MinWidth = 50;
+ public const double MinHeight = 50;
+ }
+}
diff --git a/NodeGraph.NET7/Converters/InverseBooleanToVisibilityConverter.cs b/NodeGraph.NET7/Converters/InverseBooleanToVisibilityConverter.cs
new file mode 100644
index 0000000..22b5fb5
--- /dev/null
+++ b/NodeGraph.NET7/Converters/InverseBooleanToVisibilityConverter.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace NodeGraph.NET7.Converters
+{
+ public class InverseBooleanToVisibilityConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var boolValue = (bool)value;
+ return boolValue ? Visibility.Collapsed : Visibility.Visible;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var visibility = (Visibility)value;
+ return visibility == Visibility.Visible ? false : true;
+ }
+ }
+}
diff --git a/NodeGraph.NET7/Extensions/PointExtension.cs b/NodeGraph.NET7/Extensions/PointExtension.cs
new file mode 100644
index 0000000..6bb0ddb
--- /dev/null
+++ b/NodeGraph.NET7/Extensions/PointExtension.cs
@@ -0,0 +1,22 @@
+using System.Windows;
+
+namespace NodeGraph.NET7.Extensions
+{
+ public static class PointExtension
+ {
+ public static Point Add(this Point a, Point b)
+ {
+ return new Point(a.X + b.X, a.Y + b.Y);
+ }
+
+ public static Point Sub(this Point a, Point b)
+ {
+ return new Point(a.X - b.X, a.Y - b.Y);
+ }
+
+ public static Vector ToVector(this Point me)
+ {
+ return new Vector(me.X, me.Y);
+ }
+ }
+}
diff --git a/NodeGraph.NET7/Extensions/VectorExtension.cs b/NodeGraph.NET7/Extensions/VectorExtension.cs
new file mode 100644
index 0000000..258d9c4
--- /dev/null
+++ b/NodeGraph.NET7/Extensions/VectorExtension.cs
@@ -0,0 +1,20 @@
+using System.Windows;
+
+namespace NodeGraph.NET7.Extensions
+{
+ public static class VectorExtension
+ {
+ public static double DotProduct(this Vector a, Vector b)
+ {
+ return a.X * b.X + a.Y * b.Y;
+ }
+
+ public static Vector NormalizeTo(this Vector v)
+ {
+ var temp = v;
+ temp.Normalize();
+
+ return temp;
+ }
+ }
+}
diff --git a/NodeGraph.NET7/NodeGraph.NET7.csproj b/NodeGraph.NET7/NodeGraph.NET7.csproj
new file mode 100644
index 0000000..2d1227e
--- /dev/null
+++ b/NodeGraph.NET7/NodeGraph.NET7.csproj
@@ -0,0 +1,29 @@
+
+
+
+ net7.0-windows
+ enable
+ true
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Settings.settings
+
+
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
diff --git a/NodeGraph.NET7/Operation/BeginMoveNodesOperationEventArgs.cs b/NodeGraph.NET7/Operation/BeginMoveNodesOperationEventArgs.cs
new file mode 100644
index 0000000..181e632
--- /dev/null
+++ b/NodeGraph.NET7/Operation/BeginMoveNodesOperationEventArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace NodeGraph.NET7.Operation
+{
+ public class BeginMoveNodesOperationEventArgs : EventArgs
+ {
+ public Guid[] NodeGuids { get; } = null!;
+
+ public BeginMoveNodesOperationEventArgs(Guid[] nodeGuids)
+ {
+ NodeGuids = nodeGuids;
+ }
+ }
+}
diff --git a/NodeGraph.NET7/Operation/ConnectOperationEventArgs.cs b/NodeGraph.NET7/Operation/ConnectOperationEventArgs.cs
new file mode 100644
index 0000000..d0e596a
--- /dev/null
+++ b/NodeGraph.NET7/Operation/ConnectOperationEventArgs.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace NodeGraph.NET7.Operation
+{
+ public class ConnectedOperationEventArgs : EventArgs
+ {
+ public Guid InputNodeGuid { get; } = Guid.Empty;
+ public Guid InputConnectorGuid { get; } = Guid.Empty;
+ public Guid OutputNodeGuid { get; } = Guid.Empty;
+ public Guid OutputConnectorGuid { get; } = Guid.Empty;
+
+ public ConnectedOperationEventArgs(
+ Guid inputNodeGuid,
+ Guid inputConnectorGuid,
+ Guid outputNodeGuid,
+ Guid outputConnectorGuid)
+ {
+ InputNodeGuid = inputNodeGuid;
+ InputConnectorGuid = inputConnectorGuid;
+ OutputNodeGuid = outputNodeGuid;
+ OutputConnectorGuid = outputConnectorGuid;
+ }
+ }
+}
diff --git a/NodeGraph.NET7/Operation/ConnectedLinkOperationEventArgs.cs b/NodeGraph.NET7/Operation/ConnectedLinkOperationEventArgs.cs
new file mode 100644
index 0000000..c2a58cb
--- /dev/null
+++ b/NodeGraph.NET7/Operation/ConnectedLinkOperationEventArgs.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace NodeGraph.NET7.Operation
+{
+ public class ConnectedLinkOperationEventArgs : EventArgs
+ {
+ public Guid OutputConnectorGuid { get; } = Guid.Empty;
+ public Guid OutputConnectorNodeGuid { get; } = Guid.Empty;
+ public Guid InputConnectorGuid { get; } = Guid.Empty;
+ public Guid InputConnectorNodeGuid { get; } = Guid.Empty;
+
+ public ConnectedLinkOperationEventArgs(
+ Guid outputConnectorGuid,
+ Guid outputConnectorNodeGuid,
+ Guid inputConnectorGuid,
+ Guid inputConnectorNodeGuid)
+ {
+ InputConnectorGuid = inputConnectorGuid;
+ InputConnectorNodeGuid = inputConnectorNodeGuid;
+ OutputConnectorGuid = outputConnectorGuid;
+ OutputConnectorNodeGuid = outputConnectorNodeGuid;
+ }
+ }
+}
diff --git a/NodeGraph.NET7/Operation/DisconnectOperationEventArgs.cs b/NodeGraph.NET7/Operation/DisconnectOperationEventArgs.cs
new file mode 100644
index 0000000..35dfc6a
--- /dev/null
+++ b/NodeGraph.NET7/Operation/DisconnectOperationEventArgs.cs
@@ -0,0 +1,27 @@
+using System;
+
+namespace NodeGraph.NET7.Operation
+{
+ public class DisconnectedOperationEventArgs : EventArgs
+ {
+ public Guid NodeLinkGuid { get; } = Guid.Empty;
+ public Guid OutputConnectorGuid { get; } = Guid.Empty;
+ public Guid OutputConnectorNodeGuid { get; } = Guid.Empty;
+ public Guid InputConnectorGuid { get; } = Guid.Empty;
+ public Guid InputConnectorNodeGuid { get; } = Guid.Empty;
+
+ public DisconnectedOperationEventArgs(
+ Guid nodeLinkGuid,
+ Guid outputConnectorGuid,
+ Guid outputConnectorNodeGuid,
+ Guid inputConnectorGuid,
+ Guid inputConnectorNodeGuid)
+ {
+ NodeLinkGuid = nodeLinkGuid;
+ OutputConnectorGuid = outputConnectorGuid;
+ OutputConnectorNodeGuid = outputConnectorNodeGuid;
+ InputConnectorGuid = inputConnectorGuid;
+ InputConnectorNodeGuid = inputConnectorNodeGuid;
+ }
+ }
+}
diff --git a/NodeGraph.NET7/Operation/DisconnectedLinkOperationEventArgs.cs b/NodeGraph.NET7/Operation/DisconnectedLinkOperationEventArgs.cs
new file mode 100644
index 0000000..9a13426
--- /dev/null
+++ b/NodeGraph.NET7/Operation/DisconnectedLinkOperationEventArgs.cs
@@ -0,0 +1,27 @@
+using System;
+
+namespace NodeGraph.NET7.Operation
+{
+ public class DisconnectedLinkOperationEventArgs : EventArgs
+ {
+ public Guid NodeLinkGuid { get; } = Guid.Empty;
+ public Guid OutputConnectorGuid { get; } = Guid.Empty;
+ public Guid OutputConnectorNodeGuid { get; } = Guid.Empty;
+ public Guid InputConnectorGuid { get; } = Guid.Empty;
+ public Guid InputConnectorNodeGuid { get; } = Guid.Empty;
+
+ public DisconnectedLinkOperationEventArgs(
+ Guid nodeLinkGuid,
+ Guid outputConnectorGuid,
+ Guid outputConnectorNodeGuid,
+ Guid inputConnectorGuid,
+ Guid inputConnectorNodeGuid)
+ {
+ NodeLinkGuid = nodeLinkGuid;
+ InputConnectorNodeGuid = inputConnectorNodeGuid;
+ InputConnectorGuid = inputConnectorGuid;
+ OutputConnectorNodeGuid = outputConnectorNodeGuid;
+ OutputConnectorGuid = outputConnectorGuid;
+ }
+ }
+}
diff --git a/NodeGraph.NET7/Operation/EndMoveNodesOperationEventArgs.cs b/NodeGraph.NET7/Operation/EndMoveNodesOperationEventArgs.cs
new file mode 100644
index 0000000..46e2e8d
--- /dev/null
+++ b/NodeGraph.NET7/Operation/EndMoveNodesOperationEventArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace NodeGraph.NET7.Operation
+{
+ public class EndMoveNodesOperationEventArgs : EventArgs
+ {
+ public Guid[] NodeGuids { get; } = null;
+
+ public EndMoveNodesOperationEventArgs(Guid[] nodeGuids)
+ {
+ NodeGuids = nodeGuids;
+ }
+ }
+}
diff --git a/NodeGraph.NET7/Operation/MovedNodesOperationEventArgs.cs b/NodeGraph.NET7/Operation/MovedNodesOperationEventArgs.cs
new file mode 100644
index 0000000..1b226a4
--- /dev/null
+++ b/NodeGraph.NET7/Operation/MovedNodesOperationEventArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace NodeGraph.NET7.Operation
+{
+ public class NodesMovedOperationEventArgs : EventArgs
+ {
+ public Guid[] NodeGuids { get; } = null;
+
+ public NodesMovedOperationEventArgs(Guid[] nodeGuids)
+ {
+ NodeGuids = nodeGuids;
+ }
+ }
+}
diff --git a/NodeGraph.NET7/Operation/PreviewConnectLinkOperationEventArgs.cs b/NodeGraph.NET7/Operation/PreviewConnectLinkOperationEventArgs.cs
new file mode 100644
index 0000000..b132bc0
--- /dev/null
+++ b/NodeGraph.NET7/Operation/PreviewConnectLinkOperationEventArgs.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace NodeGraph.NET7.Operation
+{
+ public class PreviewConnectLinkOperationEventArgs
+ {
+ public bool CanConnect { get; set; } = true;
+
+ public Guid ConnectStartNodeGuid { get; } = Guid.Empty;
+ public Guid ConnectStartConnectorGuid { get; } = Guid.Empty;
+ public Guid ConnectToEndNodeGuid { get; } = Guid.Empty;
+ public Guid ConnectToEndConnectorGuid { get; } = Guid.Empty;
+
+ public PreviewConnectLinkOperationEventArgs(
+ Guid connectStartNodeGuid,
+ Guid connectStartConnectorGuid,
+ Guid connectToEndNodeGuid,
+ Guid connectToEndConnectorGuid)
+ {
+ ConnectStartNodeGuid = connectStartNodeGuid;
+ ConnectStartConnectorGuid = connectStartConnectorGuid;
+ ConnectToEndNodeGuid = connectToEndNodeGuid;
+ ConnectToEndConnectorGuid = connectToEndConnectorGuid;
+ }
+ }
+}
diff --git a/NodeGraph.NET7/Operation/PreviewConnectOperationEventArgs.cs b/NodeGraph.NET7/Operation/PreviewConnectOperationEventArgs.cs
new file mode 100644
index 0000000..0934d46
--- /dev/null
+++ b/NodeGraph.NET7/Operation/PreviewConnectOperationEventArgs.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace NodeGraph.NET7.Operation
+{
+ public class PreviewConnectOperationEventArgs
+ {
+ public bool CanConnect { get; set; } = true;
+
+ public Guid ConnectStartNodeGuid { get; } = Guid.Empty;
+ public Guid ConnectStartConnectorGuid { get; } = Guid.Empty;
+ public Guid ConnectToEndNodeGuid { get; } = Guid.Empty;
+ public Guid ConnectToEndConnectorGuid { get; } = Guid.Empty;
+
+ public PreviewConnectOperationEventArgs(
+ Guid connectStartNodeGuid,
+ Guid connectStartConnectorGuid,
+ Guid connectToEndNodeGuid,
+ Guid connectToEndConnectorGuid)
+ {
+ ConnectStartNodeGuid = connectStartNodeGuid;
+ ConnectStartConnectorGuid = connectStartConnectorGuid;
+ ConnectToEndNodeGuid = connectToEndNodeGuid;
+ ConnectToEndConnectorGuid = connectToEndConnectorGuid;
+ }
+ }
+}
diff --git a/NodeGraph.NET7/Operation/StartMoveNodesOperationEventArgs.cs b/NodeGraph.NET7/Operation/StartMoveNodesOperationEventArgs.cs
new file mode 100644
index 0000000..fedf5f4
--- /dev/null
+++ b/NodeGraph.NET7/Operation/StartMoveNodesOperationEventArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace NodeGraph.NET7.Operation
+{
+ public class StartMoveNodesOperationEventArgs : EventArgs
+ {
+ public Guid[] NodeGuids { get; } = null;
+
+ public StartMoveNodesOperationEventArgs(Guid[] nodeGuids)
+ {
+ NodeGuids = nodeGuids;
+ }
+ }
+}
diff --git a/NodeGraph.NET7/OperationEventArgs/BeginMoveNodesOperationEventArgs.cs b/NodeGraph.NET7/OperationEventArgs/BeginMoveNodesOperationEventArgs.cs
new file mode 100644
index 0000000..e2522f8
--- /dev/null
+++ b/NodeGraph.NET7/OperationEventArgs/BeginMoveNodesOperationEventArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace NodeGraph.NET7.OperationEventArgs
+{
+ public class BeginMoveNodesOperationEventArgs : EventArgs
+ {
+ public Guid[] NodeGuids { get; } = null!;
+
+ public BeginMoveNodesOperationEventArgs(Guid[] nodeGuids)
+ {
+ NodeGuids = nodeGuids;
+ }
+ }
+}
diff --git a/NodeGraph.NET7/OperationEventArgs/ConnectedLinkOperationEventArgs.cs b/NodeGraph.NET7/OperationEventArgs/ConnectedLinkOperationEventArgs.cs
new file mode 100644
index 0000000..94a2b38
--- /dev/null
+++ b/NodeGraph.NET7/OperationEventArgs/ConnectedLinkOperationEventArgs.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace NodeGraph.NET7.OperationEventArgs
+{
+ public class ConnectedLinkOperationEventArgs : EventArgs
+ {
+ public Guid OutputConnectorGuid { get; } = Guid.Empty;
+ public Guid OutputConnectorNodeGuid { get; } = Guid.Empty;
+ public Guid InputConnectorGuid { get; } = Guid.Empty;
+ public Guid InputConnectorNodeGuid { get; } = Guid.Empty;
+
+ public ConnectedLinkOperationEventArgs(
+ Guid outputConnectorGuid,
+ Guid outputConnectorNodeGuid,
+ Guid inputConnectorGuid,
+ Guid inputConnectorNodeGuid)
+ {
+ InputConnectorGuid = inputConnectorGuid;
+ InputConnectorNodeGuid = inputConnectorNodeGuid;
+ OutputConnectorGuid = outputConnectorGuid;
+ OutputConnectorNodeGuid = outputConnectorNodeGuid;
+ }
+ }
+}
diff --git a/NodeGraph.NET7/OperationEventArgs/DisconnectedLinkOperationEventArgs.cs b/NodeGraph.NET7/OperationEventArgs/DisconnectedLinkOperationEventArgs.cs
new file mode 100644
index 0000000..f4ba280
--- /dev/null
+++ b/NodeGraph.NET7/OperationEventArgs/DisconnectedLinkOperationEventArgs.cs
@@ -0,0 +1,27 @@
+using System;
+
+namespace NodeGraph.NET7.OperationEventArgs
+{
+ public class DisconnectedLinkOperationEventArgs : EventArgs
+ {
+ public Guid NodeLinkGuid { get; } = Guid.Empty;
+ public Guid OutputConnectorGuid { get; } = Guid.Empty;
+ public Guid OutputConnectorNodeGuid { get; } = Guid.Empty;
+ public Guid InputConnectorGuid { get; } = Guid.Empty;
+ public Guid InputConnectorNodeGuid { get; } = Guid.Empty;
+
+ public DisconnectedLinkOperationEventArgs(
+ Guid nodeLinkGuid,
+ Guid outputConnectorGuid,
+ Guid outputConnectorNodeGuid,
+ Guid inputConnectorGuid,
+ Guid inputConnectorNodeGuid)
+ {
+ NodeLinkGuid = nodeLinkGuid;
+ InputConnectorNodeGuid = inputConnectorNodeGuid;
+ InputConnectorGuid = inputConnectorGuid;
+ OutputConnectorNodeGuid = outputConnectorNodeGuid;
+ OutputConnectorGuid = outputConnectorGuid;
+ }
+ }
+}
diff --git a/NodeGraph.NET7/OperationEventArgs/EndMoveNodesOperationEventArgs.cs b/NodeGraph.NET7/OperationEventArgs/EndMoveNodesOperationEventArgs.cs
new file mode 100644
index 0000000..7d9c048
--- /dev/null
+++ b/NodeGraph.NET7/OperationEventArgs/EndMoveNodesOperationEventArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace NodeGraph.NET7.OperationEventArgs
+{
+ public class EndMoveNodesOperationEventArgs : EventArgs
+ {
+ public Guid[] NodeGuids { get; } = null!;
+
+ public EndMoveNodesOperationEventArgs(Guid[] nodeGuids)
+ {
+ NodeGuids = nodeGuids;
+ }
+ }
+}
diff --git a/NodeGraph.NET7/OperationEventArgs/PreviewConnectLinkOperationEventArgs.cs b/NodeGraph.NET7/OperationEventArgs/PreviewConnectLinkOperationEventArgs.cs
new file mode 100644
index 0000000..2f507ee
--- /dev/null
+++ b/NodeGraph.NET7/OperationEventArgs/PreviewConnectLinkOperationEventArgs.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace NodeGraph.NET7.OperationEventArgs
+{
+ public class PreviewConnectLinkOperationEventArgs
+ {
+ public bool CanConnect { get; set; } = true;
+
+ public Guid ConnectStartNodeGuid { get; } = Guid.Empty;
+ public Guid ConnectStartConnectorGuid { get; } = Guid.Empty;
+ public Guid ConnectToEndNodeGuid { get; } = Guid.Empty;
+ public Guid ConnectToEndConnectorGuid { get; } = Guid.Empty;
+
+ public PreviewConnectLinkOperationEventArgs(
+ Guid connectStartNodeGuid,
+ Guid connectStartConnectorGuid,
+ Guid connectToEndNodeGuid,
+ Guid connectToEndConnectorGuid)
+ {
+ ConnectStartNodeGuid = connectStartNodeGuid;
+ ConnectStartConnectorGuid = connectStartConnectorGuid;
+ ConnectToEndNodeGuid = connectToEndNodeGuid;
+ ConnectToEndConnectorGuid = connectToEndConnectorGuid;
+ }
+ }
+}
diff --git a/NodeGraph.NET7/Properties/Resources.Designer.cs b/NodeGraph.NET7/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..dd5135e
--- /dev/null
+++ b/NodeGraph.NET7/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+//
+// このコードはツールによって生成されました。
+// ランタイム バージョン:4.0.30319.42000
+//
+// このファイルへの変更は、正しくない動作の原因になったり、
+// コードが再生成されるときに失われたりします。
+//
+//------------------------------------------------------------------------------
+
+namespace NodeGraph.NET7.Properties
+{
+
+
+ ///
+ /// ローカライズされた文字列などを検索するための、厳密に型指定されたリソース クラスです。
+ ///
+ // このクラスは StronglyTypedResourceBuilder クラスによって ResGen
+ // または Visual Studio のようなツールを使用して自動生成されました。
+ // メンバーを追加または削除するには、.ResX ファイルを編集して、/str オプションと共に
+ // ResGen を実行し直すか、または VS プロジェクトをリビルドします。
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ ///
+ /// このクラスで使用されるキャッシュされた ResourceManager インスタンスを返します。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NodeGraph.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// すべてについて、現在のスレッドの CurrentUICulture プロパティをオーバーライドします
+ /// 現在のスレッドの CurrentUICulture プロパティをオーバーライドします。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/NodeGraph.NET7/Properties/Resources.resx b/NodeGraph.NET7/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/NodeGraph.NET7/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/NodeGraph.NET7/Properties/Settings.Designer.cs b/NodeGraph.NET7/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..a1b5c97
--- /dev/null
+++ b/NodeGraph.NET7/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace NodeGraph.NET7.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.5.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/NodeGraph.NET7/Properties/Settings.settings b/NodeGraph.NET7/Properties/Settings.settings
new file mode 100644
index 0000000..033d7a5
--- /dev/null
+++ b/NodeGraph.NET7/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NodeGraph.NET7/ResourceDictionary.xaml b/NodeGraph.NET7/ResourceDictionary.xaml
new file mode 100644
index 0000000..9c52d20
--- /dev/null
+++ b/NodeGraph.NET7/ResourceDictionary.xaml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NodeGraph.NET7/Utilities/ResourceInstance.cs b/NodeGraph.NET7/Utilities/ResourceInstance.cs
new file mode 100644
index 0000000..edb6448
--- /dev/null
+++ b/NodeGraph.NET7/Utilities/ResourceInstance.cs
@@ -0,0 +1,20 @@
+using System.Windows;
+using System.Windows.Threading;
+
+namespace NodeGraph.NET7.Utilities
+{
+ public class ResourceInstance where T : DispatcherObject
+ {
+ public T Get(string resourceName)
+ {
+ if (_Resource == null)
+ {
+ _Resource = (Application.Current.TryFindResource(resourceName) as T)!;
+ }
+
+ return _Resource!;
+ }
+
+ T _Resource = null!;
+ }
+}
diff --git a/NodeGraph.PreviewTest.NET6/App.config b/NodeGraph.PreviewTest.NET6/App.config
deleted file mode 100644
index 56efbc7..0000000
--- a/NodeGraph.PreviewTest.NET6/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/NodeGraph.PreviewTest.NET6/App.xaml b/NodeGraph.PreviewTest.NET6/App.xaml
index b9db7fa..2b62348 100644
--- a/NodeGraph.PreviewTest.NET6/App.xaml
+++ b/NodeGraph.PreviewTest.NET6/App.xaml
@@ -1,7 +1,6 @@
diff --git a/NodeGraph.PreviewTest.NET6/App.xaml.cs b/NodeGraph.PreviewTest.NET6/App.xaml.cs
index 18f3466..867d14e 100644
--- a/NodeGraph.PreviewTest.NET6/App.xaml.cs
+++ b/NodeGraph.PreviewTest.NET6/App.xaml.cs
@@ -1,10 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Configuration;
-using System.Data;
-using System.Linq;
-using System.Threading.Tasks;
-using System.Windows;
+using System.Windows;
namespace NodeGraph.PreviewTest
{
diff --git a/NodeGraph.PreviewTest.NET6/MainWindow.xaml b/NodeGraph.PreviewTest.NET6/MainWindow.xaml
deleted file mode 100644
index 8515e4a..0000000
--- a/NodeGraph.PreviewTest.NET6/MainWindow.xaml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
diff --git a/NodeGraph.PreviewTest.NET6/MainWindow.xaml.cs b/NodeGraph.PreviewTest.NET6/MainWindow.xaml.cs
deleted file mode 100644
index 9bc0b30..0000000
--- a/NodeGraph.PreviewTest.NET6/MainWindow.xaml.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Navigation;
-using System.Windows.Shapes;
-
-namespace NodeGraph.PreviewTest.NET6
-{
- ///
- /// Interaction logic for MainWindow.xaml
- ///
- public partial class MainWindow : Window
- {
- public MainWindow()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/NodeGraph.PreviewTest.NET6/NodeGraph.PreviewTest.NET6.csproj b/NodeGraph.PreviewTest.NET6/NodeGraph.PreviewTest.NET6.csproj
index e83fae3..de35f03 100644
--- a/NodeGraph.PreviewTest.NET6/NodeGraph.PreviewTest.NET6.csproj
+++ b/NodeGraph.PreviewTest.NET6/NodeGraph.PreviewTest.NET6.csproj
@@ -7,11 +7,6 @@
true
-
-
-
-
-
diff --git a/NodeGraph.PreviewTest.NET6/Utilities/ViewModelCommandHandler.cs b/NodeGraph.PreviewTest.NET6/Utilities/ViewModelCommandHandler.cs
index af339e6..1ef9822 100644
--- a/NodeGraph.PreviewTest.NET6/Utilities/ViewModelCommandHandler.cs
+++ b/NodeGraph.PreviewTest.NET6/Utilities/ViewModelCommandHandler.cs
@@ -1,16 +1,11 @@
using Livet.Commands;
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Input;
-namespace NodeGraph.Utilities
+namespace NodeGraph.PreviewTest.NET6.Utilities
{
public class ViewModelCommandHandler
{
- public ViewModelCommand Get(Action execute, Func canExecute = null)
+ public ViewModelCommand Get(Action execute, Func canExecute = null!)
{
if (_Command == null)
{
@@ -20,14 +15,14 @@ public ViewModelCommand Get(Action execute, Func canExecute = null)
return _Command;
}
- ViewModelCommand _Command;
+ ViewModelCommand? _Command;
}
public class ViewModelCommandHandler
{
- public ListenerCommand Get(Action execute, Func canExecute = null)
+ public ListenerCommand Get(Action execute, Func canExecute = null!)
{
- if(_Command == null)
+ if (_Command == null)
{
_Command = new ListenerCommand(execute);
}
@@ -35,6 +30,6 @@ public ListenerCommand Get(Action execute, Func canExecute = null)
return _Command;
}
- ListenerCommand _Command;
+ ListenerCommand? _Command;
}
}
diff --git a/NodeGraph.PreviewTest.NET6/ViewModels/MainWindowViewModel.cs b/NodeGraph.PreviewTest.NET6/ViewModels/MainWindowViewModel.cs
index 619a683..49a3d94 100644
--- a/NodeGraph.PreviewTest.NET6/ViewModels/MainWindowViewModel.cs
+++ b/NodeGraph.PreviewTest.NET6/ViewModels/MainWindowViewModel.cs
@@ -1,18 +1,15 @@
using Livet;
using Livet.Commands;
using NodeGraph.NET6.Operation;
-using NodeGraph.PreviewTest.ViewModels;
-using NodeGraph.Utilities;
+using NodeGraph.PreviewTest.NET6.Utilities;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
-namespace NodeGraph.PreviewTest.ViewModels
+namespace NodeGraph.PreviewTest.NET6.ViewModels
{
public enum GroupIntersectType
{
diff --git a/NodeGraph.PreviewTest.NET6/ViewModels/NodeConnectorViewModel.cs b/NodeGraph.PreviewTest.NET6/ViewModels/NodeConnectorViewModel.cs
index ae59661..ac9926a 100644
--- a/NodeGraph.PreviewTest.NET6/ViewModels/NodeConnectorViewModel.cs
+++ b/NodeGraph.PreviewTest.NET6/ViewModels/NodeConnectorViewModel.cs
@@ -1,20 +1,16 @@
using Livet;
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-namespace NodeGraph.PreviewTest.ViewModels
+namespace NodeGraph.PreviewTest.NET6.ViewModels
{
- public interface NodeConnectorViewModel
+ public interface INodeConnectorViewModel
{
Guid Guid { get; set; }
string Label { get; set; }
bool IsEnable { get; set; }
}
- public class NodeInputViewModel : ViewModel, NodeConnectorViewModel
+ public class NodeInputViewModel : ViewModel, INodeConnectorViewModel
{
public Guid Guid
{
@@ -51,7 +47,7 @@ public NodeInputViewModel(string label, bool allowToConnectMultiple)
}
}
- public class NodeOutputViewModel : ViewModel, NodeConnectorViewModel
+ public class NodeOutputViewModel : ViewModel, INodeConnectorViewModel
{
public Guid Guid
{
diff --git a/NodeGraph.PreviewTest.NET6/ViewModels/NodeLinkViewModel.cs b/NodeGraph.PreviewTest.NET6/ViewModels/NodeLinkViewModel.cs
index 038957e..63727fc 100644
--- a/NodeGraph.PreviewTest.NET6/ViewModels/NodeLinkViewModel.cs
+++ b/NodeGraph.PreviewTest.NET6/ViewModels/NodeLinkViewModel.cs
@@ -1,11 +1,7 @@
using Livet;
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-namespace NodeGraph.PreviewTest.ViewModels
+namespace NodeGraph.PreviewTest.NET6.ViewModels
{
public class NodeLinkViewModel : ViewModel
{
diff --git a/NodeGraph.PreviewTest.NET6/ViewModels/NodeViewModel.cs b/NodeGraph.PreviewTest.NET6/ViewModels/NodeViewModel.cs
index f4cbffa..efa0af7 100644
--- a/NodeGraph.PreviewTest.NET6/ViewModels/NodeViewModel.cs
+++ b/NodeGraph.PreviewTest.NET6/ViewModels/NodeViewModel.cs
@@ -1,15 +1,13 @@
using Livet;
-using NodeGraph.Utilities;
+using NodeGraph.PreviewTest.NET6.Utilities;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
-namespace NodeGraph.PreviewTest.ViewModels
+namespace NodeGraph.PreviewTest.NET6.ViewModels
{
public interface INodeViewModel
{
@@ -130,10 +128,10 @@ public bool IsSelected
public ICommand SizeChangedCommand => _SizeChangedCommand.Get(SizeChanged);
ViewModelCommandHandler _SizeChangedCommand = new ViewModelCommandHandler();
- public abstract IEnumerable Inputs { get; }
- public abstract IEnumerable Outputs { get; }
+ public abstract IEnumerable Inputs { get; }
+ public abstract IEnumerable Outputs { get; }
- public abstract NodeConnectorViewModel FindConnector(Guid guid);
+ public abstract INodeConnectorViewModel FindConnector(Guid guid);
void SizeChanged(Size newSize)
{
@@ -158,10 +156,10 @@ public string Body
}
string _Body = string.Empty;
- public override IEnumerable Inputs => _Inputs;
+ public override IEnumerable Inputs => _Inputs;
readonly ObservableCollection _Inputs = new ObservableCollection();
- public override IEnumerable Outputs => _Outputs;
+ public override IEnumerable Outputs => _Outputs;
readonly ObservableCollection _Outputs = new ObservableCollection();
public Test1DefaultNodeViewModel()
@@ -171,7 +169,7 @@ public Test1DefaultNodeViewModel()
if (i % 2 == 0)
{
var label = $"Input{i}";
- if(i > 1)
+ if (i > 1)
{
label += " Allow to connect multiple";
}
@@ -189,7 +187,7 @@ public Test1DefaultNodeViewModel()
}
}
- public override NodeConnectorViewModel FindConnector(Guid guid)
+ public override INodeConnectorViewModel FindConnector(Guid guid)
{
var input = Inputs.FirstOrDefault(arg => arg.Guid == guid);
if (input != null)
@@ -218,10 +216,10 @@ public string Body
}
string _Body = string.Empty;
- public override IEnumerable Inputs => _Inputs;
+ public override IEnumerable Inputs => _Inputs;
readonly ObservableCollection _Inputs = new ObservableCollection();
- public override IEnumerable Outputs => _Outputs;
+ public override IEnumerable Outputs => _Outputs;
readonly ObservableCollection _Outputs = new ObservableCollection();
public Test2DefaultNodeViewModel()
@@ -242,7 +240,7 @@ public Test2DefaultNodeViewModel()
}
}
- public override NodeConnectorViewModel FindConnector(Guid guid)
+ public override INodeConnectorViewModel FindConnector(Guid guid)
{
var input = Inputs.FirstOrDefault(arg => arg.Guid == guid);
if (input != null)
@@ -271,10 +269,10 @@ public string Body
}
string _Body = string.Empty;
- public override IEnumerable Inputs => _Inputs;
+ public override IEnumerable Inputs => _Inputs;
readonly ObservableCollection _Inputs = new ObservableCollection();
- public override IEnumerable Outputs => _Outputs;
+ public override IEnumerable Outputs => _Outputs;
readonly ObservableCollection _Outputs = new ObservableCollection();
public Test3DefaultNodeViewModel()
@@ -285,7 +283,7 @@ public Test3DefaultNodeViewModel()
}
}
- public override NodeConnectorViewModel FindConnector(Guid guid)
+ public override INodeConnectorViewModel FindConnector(Guid guid)
{
return Outputs.FirstOrDefault(arg => arg.Guid == guid);
}
@@ -307,10 +305,10 @@ public string Body
}
string _Body = string.Empty;
- public override IEnumerable Inputs => _Inputs;
+ public override IEnumerable Inputs => _Inputs;
readonly ObservableCollection _Inputs = new ObservableCollection();
- public override IEnumerable Outputs => _Outputs;
+ public override IEnumerable Outputs => _Outputs;
readonly ObservableCollection _Outputs = new ObservableCollection();
public Test4DefaultNodeViewModel()
@@ -326,7 +324,7 @@ public Test4DefaultNodeViewModel()
}
}
- public override NodeConnectorViewModel FindConnector(Guid guid)
+ public override INodeConnectorViewModel FindConnector(Guid guid)
{
return Inputs.FirstOrDefault(arg => arg.Guid == guid);
}
diff --git a/NodeGraph.PreviewTest.NET6/Views/MainWindow.xaml b/NodeGraph.PreviewTest.NET6/Views/MainWindow.xaml
index d8456f4..242fda8 100644
--- a/NodeGraph.PreviewTest.NET6/Views/MainWindow.xaml
+++ b/NodeGraph.PreviewTest.NET6/Views/MainWindow.xaml
@@ -4,9 +4,9 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:vm="clr-namespace:NodeGraph.PreviewTest.ViewModels"
+ xmlns:vm="clr-namespace:NodeGraph.PreviewTest.NET6.ViewModels"
xmlns:ctrl="clr-namespace:NodeGraph.NET6.Controls;assembly=NodeGraph.NET6"
- xmlns:local="clr-namespace:NodeGraph.PreviewTest"
+
mc:Ignorable="d"
Title="NodeGraph - prototype" Height="600" Width="1000">
diff --git a/NodeGraph.PreviewTest.NET6/Views/MainWindow.xaml.cs b/NodeGraph.PreviewTest.NET6/Views/MainWindow.xaml.cs
index d1ec78b..bc479fc 100644
--- a/NodeGraph.PreviewTest.NET6/Views/MainWindow.xaml.cs
+++ b/NodeGraph.PreviewTest.NET6/Views/MainWindow.xaml.cs
@@ -1,17 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Navigation;
-using System.Windows.Shapes;
+using System.Windows;
namespace NodeGraph.PreviewTest.Views
{
diff --git a/NodeGraph.PreviewTest.NET7/App.xaml b/NodeGraph.PreviewTest.NET7/App.xaml
new file mode 100644
index 0000000..62c333e
--- /dev/null
+++ b/NodeGraph.PreviewTest.NET7/App.xaml
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/NodeGraph.PreviewTest.NET7/App.xaml.cs b/NodeGraph.PreviewTest.NET7/App.xaml.cs
new file mode 100644
index 0000000..867d14e
--- /dev/null
+++ b/NodeGraph.PreviewTest.NET7/App.xaml.cs
@@ -0,0 +1,11 @@
+using System.Windows;
+
+namespace NodeGraph.PreviewTest
+{
+ ///
+ /// App.xaml の相互作用ロジック
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/NodeGraph.PreviewTest.NET7/AssemblyInfo.cs b/NodeGraph.PreviewTest.NET7/AssemblyInfo.cs
new file mode 100644
index 0000000..8b5504e
--- /dev/null
+++ b/NodeGraph.PreviewTest.NET7/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+using System.Windows;
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
diff --git a/NodeGraph.PreviewTest.NET7/NodeGraph.PreviewTest.NET7.csproj b/NodeGraph.PreviewTest.NET7/NodeGraph.PreviewTest.NET7.csproj
new file mode 100644
index 0000000..91eaa67
--- /dev/null
+++ b/NodeGraph.PreviewTest.NET7/NodeGraph.PreviewTest.NET7.csproj
@@ -0,0 +1,14 @@
+
+
+
+ WinExe
+ net7.0-windows
+ enable
+ true
+
+
+
+
+
+
+
diff --git a/NodeGraph.PreviewTest.NET7/Properties/Resources.Designer.cs b/NodeGraph.PreviewTest.NET7/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..e82203c
--- /dev/null
+++ b/NodeGraph.PreviewTest.NET7/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+//
+// このコードはツールによって生成されました。
+// ランタイム バージョン:4.0.30319.42000
+//
+// このファイルへの変更は、以下の状況下で不正な動作の原因になったり、
+// コードが再生成されるときに損失したりします
+//
+//------------------------------------------------------------------------------
+
+namespace NodeGraph.PreviewTest.NET7.Properties
+{
+
+
+ ///
+ /// ローカライズされた文字列などを検索するための、厳密に型指定されたリソース クラスです。
+ ///
+ // このクラスは StronglyTypedResourceBuilder クラスによって ResGen
+ // または Visual Studio のようなツールを使用して自動生成されました。
+ // メンバーを追加または削除するには、.ResX ファイルを編集して、/str オプションと共に
+ // ResGen を実行し直すか、または VS プロジェクトをリビルドします。
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ ///
+ /// このクラスで使用されるキャッシュされた ResourceManager インスタンスを返します。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NodeGraph.PreviewTest.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// すべてについて、現在のスレッドの CurrentUICulture プロパティをオーバーライドします
+ /// 現在のスレッドの CurrentUICulture プロパティをオーバーライドします。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/NodeGraph.PreviewTest.NET7/Properties/Resources.resx b/NodeGraph.PreviewTest.NET7/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/NodeGraph.PreviewTest.NET7/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/NodeGraph.PreviewTest.NET7/Properties/Settings.Designer.cs b/NodeGraph.PreviewTest.NET7/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..35b992e
--- /dev/null
+++ b/NodeGraph.PreviewTest.NET7/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace NodeGraph.PreviewTest.NET7.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/NodeGraph.PreviewTest.NET7/Properties/Settings.settings b/NodeGraph.PreviewTest.NET7/Properties/Settings.settings
new file mode 100644
index 0000000..033d7a5
--- /dev/null
+++ b/NodeGraph.PreviewTest.NET7/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NodeGraph.PreviewTest.NET7/Utilities/ViewModelCommandHandler.cs b/NodeGraph.PreviewTest.NET7/Utilities/ViewModelCommandHandler.cs
new file mode 100644
index 0000000..1570e28
--- /dev/null
+++ b/NodeGraph.PreviewTest.NET7/Utilities/ViewModelCommandHandler.cs
@@ -0,0 +1,35 @@
+using Livet.Commands;
+using System;
+
+namespace NodeGraph.PreviewTest.NET7.Utilities
+{
+ public class ViewModelCommandHandler
+ {
+ public ViewModelCommand Get(Action execute, Func canExecute = null!)
+ {
+ if (_Command == null)
+ {
+ _Command = new ViewModelCommand(execute, canExecute);
+ }
+
+ return _Command;
+ }
+
+ ViewModelCommand? _Command;
+ }
+
+ public class ViewModelCommandHandler
+ {
+ public ListenerCommand Get(Action execute, Func canExecute = null!)
+ {
+ if (_Command == null)
+ {
+ _Command = new ListenerCommand(execute);
+ }
+
+ return _Command;
+ }
+
+ ListenerCommand? _Command;
+ }
+}
diff --git a/NodeGraph.PreviewTest.NET7/ViewModels/MainWindowViewModel.cs b/NodeGraph.PreviewTest.NET7/ViewModels/MainWindowViewModel.cs
new file mode 100644
index 0000000..76d3374
--- /dev/null
+++ b/NodeGraph.PreviewTest.NET7/ViewModels/MainWindowViewModel.cs
@@ -0,0 +1,288 @@
+using Livet;
+using Livet.Commands;
+using NodeGraph.NET7.Operation;
+using NodeGraph.PreviewTest.NET7.Utilities;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Windows;
+
+namespace NodeGraph.PreviewTest.NET7.ViewModels
+{
+ public enum GroupIntersectType
+ {
+ CursorPointVMDefine,
+ BoundingBoxVMDefine,
+ }
+
+ public enum RangeSelectionMode
+ {
+ ContainVMDefine,
+ IntersectVMDefine,
+ }
+
+ public class MainWindowViewModel : ViewModel
+ {
+ public double Scale
+ {
+ get => _Scale;
+ set => RaisePropertyChangedIfSet(ref _Scale, value);
+ }
+ double _Scale = 1.0f;
+
+ public ViewModelCommand AddNodeCommand => _AddNodeCommand.Get(AddNode);
+ ViewModelCommandHandler _AddNodeCommand = new ViewModelCommandHandler();
+
+ public ViewModelCommand AddGroupNodeCommand => _AddGroupNodeCommand.Get(AddGroupNode);
+ ViewModelCommandHandler _AddGroupNodeCommand = new ViewModelCommandHandler();
+
+ public ViewModelCommand RemoveNodesCommand => _RemoveNodesCommand.Get(RemoveNodes);
+ ViewModelCommandHandler _RemoveNodesCommand = new ViewModelCommandHandler();
+
+ public ListenerCommand PreviewConnectLinkCommand => _PreviewConnectLinkCommand.Get(PreviewConnect);
+ ViewModelCommandHandler _PreviewConnectLinkCommand = new ViewModelCommandHandler();
+
+ public ListenerCommand ConnectedLinkCommand => _ConnectedLinkCommand.Get(Connected);
+ ViewModelCommandHandler _ConnectedLinkCommand = new ViewModelCommandHandler();
+
+ public ListenerCommand DisconnectedLinkCommand => _DisconnectedLinkCommand.Get(Disconnected);
+ ViewModelCommandHandler _DisconnectedLinkCommand = new ViewModelCommandHandler();
+
+ public ListenerCommand EndMoveNodesCommand => _EndMoveNodesCommand.Get(NodesMoved);
+ ViewModelCommandHandler _EndMoveNodesCommand = new ViewModelCommandHandler();
+
+ public ListenerCommand SelectionChangedCommand => _SelectionChangedCommand.Get(SelectionChanged);
+ ViewModelCommandHandler _SelectionChangedCommand = new ViewModelCommandHandler();
+
+ public ViewModelCommand AddTestNodeLinkCommand => _AddTestNodeLinkCommand.Get(AddTestNodeLink);
+ ViewModelCommandHandler _AddTestNodeLinkCommand = new ViewModelCommandHandler();
+
+ public ViewModelCommand MoveTestNodesCommand => _MoveTestNodesCommand.Get(MoveTestNodes);
+ ViewModelCommandHandler _MoveTestNodesCommand = new ViewModelCommandHandler();
+
+ public ViewModelCommand ClearNodesCommand => _ClearNodesCommand.Get(ClearNodes);
+ ViewModelCommandHandler _ClearNodesCommand = new ViewModelCommandHandler();
+
+ public ViewModelCommand ClearNodeLinksCommand => _ClearNodeLinksCommand.Get(ClearNodeLinks);
+ ViewModelCommandHandler _ClearNodeLinksCommand = new ViewModelCommandHandler();
+
+ public ViewModelCommand MoveGroupNodeCommand => _MoveGroupNodeCommand.Get(MoveGroupNode);
+ ViewModelCommandHandler _MoveGroupNodeCommand = new ViewModelCommandHandler();
+
+ public ViewModelCommand ChangeGroupInnerSizeCommand => _ChangeGroupInnerSizeCommand.Get(ChangeGroupInnerSize);
+ ViewModelCommandHandler _ChangeGroupInnerSizeCommand = new ViewModelCommandHandler();
+
+ public ViewModelCommand ChangeGroupInnerPositionCommand => _ChangeGroupInnerPositionCommand.Get(ChangeGroupInnerPosition);
+ ViewModelCommandHandler _ChangeGroupInnerPositionCommand = new ViewModelCommandHandler();
+
+ public ViewModelCommand ResetScaleCommand => _ResetScaleCommand.Get(ResetScale);
+ ViewModelCommandHandler _ResetScaleCommand = new ViewModelCommandHandler();
+
+ public IEnumerable NodeViewModels => _NodeViewModels;
+ ObservableCollection _NodeViewModels = new ObservableCollection();
+
+ public IEnumerable NodeLinkViewModels => _NodeLinkViewModels;
+ ObservableCollection _NodeLinkViewModels = new ObservableCollection();
+
+ public IEnumerable GroupNodeViewModels => _GroupNodeViewModels;
+ ObservableCollection _GroupNodeViewModels = new ObservableCollection();
+
+ public GroupIntersectType[] GroupIntersectTypes { get; } = Enum.GetValues(typeof(GroupIntersectType)).OfType().ToArray();
+ public RangeSelectionMode[] RangeSelectionModes { get; } = Enum.GetValues(typeof(RangeSelectionMode)).OfType().ToArray();
+
+ public GroupIntersectType SelectedGroupIntersectType
+ {
+ get => _SelectedGroupIntersectType;
+ set => RaisePropertyChangedIfSet(ref _SelectedGroupIntersectType, value);
+ }
+ GroupIntersectType _SelectedGroupIntersectType;
+
+ public RangeSelectionMode SelectedRangeSelectionMode
+ {
+ get => _SelectedRangeSelectionMode;
+ set => RaisePropertyChangedIfSet(ref _SelectedRangeSelectionMode, value);
+ }
+ RangeSelectionMode _SelectedRangeSelectionMode = RangeSelectionMode.ContainVMDefine;
+
+ public bool IsLockedAllNodeLinks
+ {
+ get => _IsLockedAllNodeLinks;
+ set => UpdateIsLockedAllNodeLinksProperty(value);
+ }
+ bool _IsLockedAllNodeLinks = false;
+
+ public bool IsEnableAllNodeConnectors
+ {
+ get => _IsEnableAllNodeConnectors;
+ set => UpdateIsEnableAllNodeConnectorsProperty(value);
+ }
+ bool _IsEnableAllNodeConnectors = true;
+
+ public bool AllowToOverrideConnection
+ {
+ get => _AllowToOverrideConnection;
+ set => RaisePropertyChangedIfSet(ref _AllowToOverrideConnection, value);
+ }
+ bool _AllowToOverrideConnection = true;
+
+ public bool ClipToBounds
+ {
+ get => _ClipToBounds;
+ set => RaisePropertyChangedIfSet(ref _ClipToBounds, value);
+ }
+ bool _ClipToBounds = true;
+
+ public MainWindowViewModel()
+ {
+ _GroupNodeViewModels.Add(new GroupNodeViewModel() { Name = "Group1" });
+ _NodeViewModels.Add(new Test1DefaultNodeViewModel() { Name = "Node1", Body = "Content1", Position = new Point(0, 100) });
+ _NodeViewModels.Add(new Test1DefaultNodeViewModel() { Name = "Node2", Body = "Content2", Position = new Point(100, 200) });
+ _NodeViewModels.Add(new Test1DefaultNodeViewModel() { Name = "Node3", Body = "Content3", Position = new Point(200, 300) });
+ _NodeViewModels.Add(new Test3DefaultNodeViewModel() { Name = "Node4", Body = "OutputsOnlyNode", Position = new Point(500, 100) });
+ _NodeViewModels.Add(new Test4DefaultNodeViewModel() { Name = "Node5", Body = "InputsOnlyNode", Position = new Point(600, 200) });
+ }
+
+ void AddNode()
+ {
+ _NodeViewModels.Add(new Test2DefaultNodeViewModel() { Name = "NewNode", Body = "NewContent" });
+ }
+
+ void AddGroupNode()
+ {
+ _GroupNodeViewModels.Add(new GroupNodeViewModel() { Name = "NewGroupNode" });
+ }
+
+ void RemoveNodes()
+ {
+ var removeNodes = _NodeViewModels.Where(arg => arg.IsSelected).ToArray();
+ foreach (var removeNode in removeNodes)
+ {
+ _NodeViewModels.Remove(removeNode);
+
+ var removeNodeLink = NodeLinkViewModels.FirstOrDefault(arg => arg.InputConnectorNodeGuid == removeNode.Guid || arg.OutputConnectorNodeGuid == removeNode.Guid);
+ _NodeLinkViewModels.Remove(removeNodeLink);
+ }
+ }
+
+ void ClearNodes()
+ {
+ _NodeLinkViewModels.Clear();
+ _NodeViewModels.Clear();
+ }
+
+ void ClearNodeLinks()
+ {
+ _NodeLinkViewModels.Clear();
+ }
+
+ void MoveGroupNode()
+ {
+ _GroupNodeViewModels[0].InterlockPosition = new Point(0, 0);
+ }
+
+ void ChangeGroupInnerSize()
+ {
+ _GroupNodeViewModels[0].InnerWidth = 300;
+ _GroupNodeViewModels[0].InnerHeight = 300;
+ }
+
+ void ChangeGroupInnerPosition()
+ {
+ _GroupNodeViewModels[0].InnerPosition = new Point(0, 0);
+ }
+
+ void ResetScale()
+ {
+ Scale = 1.0f;
+ }
+
+ void UpdateIsLockedAllNodeLinksProperty(bool value)
+ {
+ _IsLockedAllNodeLinks = !_IsLockedAllNodeLinks;
+
+ foreach (var nodeLink in _NodeLinkViewModels)
+ {
+ nodeLink.IsLocked = _IsLockedAllNodeLinks;
+ }
+
+ RaisePropertyChanged(nameof(IsLockedAllNodeLinks));
+ }
+
+ void UpdateIsEnableAllNodeConnectorsProperty(bool value)
+ {
+ _IsEnableAllNodeConnectors = !_IsEnableAllNodeConnectors;
+
+ foreach (var node in _NodeViewModels)
+ {
+ foreach (var input in node.Inputs)
+ {
+ input.IsEnable = _IsEnableAllNodeConnectors;
+ }
+ foreach (var output in node.Outputs)
+ {
+ output.IsEnable = _IsEnableAllNodeConnectors;
+ }
+ }
+
+ RaisePropertyChanged(nameof(IsEnableAllNodeConnectors));
+ }
+
+ void PreviewConnect(PreviewConnectLinkOperationEventArgs args)
+ {
+ var inputNode = NodeViewModels.First(arg => arg.Guid == args.ConnectToEndNodeGuid);
+ var inputConnector = inputNode.FindConnector(args.ConnectToEndConnectorGuid);
+ args.CanConnect = inputConnector.Label == "Limited Input" == false;
+ }
+
+ void Connected(ConnectedLinkOperationEventArgs param)
+ {
+ var nodeLink = new NodeLinkViewModel()
+ {
+ OutputConnectorGuid = param.OutputConnectorGuid,
+ OutputConnectorNodeGuid = param.OutputConnectorNodeGuid,
+ InputConnectorGuid = param.InputConnectorGuid,
+ InputConnectorNodeGuid = param.InputConnectorNodeGuid,
+ IsLocked = IsLockedAllNodeLinks,
+ };
+ _NodeLinkViewModels.Add(nodeLink);
+ }
+
+ void Disconnected(DisconnectedLinkOperationEventArgs param)
+ {
+ var nodeLink = _NodeLinkViewModels.First(arg => arg.Guid == param.NodeLinkGuid);
+ _NodeLinkViewModels.Remove(nodeLink);
+ }
+
+ void NodesMoved(EndMoveNodesOperationEventArgs param)
+ {
+
+ }
+
+ void SelectionChanged(IList list)
+ {
+
+ }
+
+ void AddTestNodeLink()
+ {
+ if (_NodeViewModels.Count < 2)
+ {
+ return;
+ }
+ var nodeLink = new NodeLinkViewModel();
+ nodeLink.OutputConnectorGuid = _NodeViewModels[0].Outputs.ElementAt(0).Guid;
+ nodeLink.InputConnectorGuid = _NodeViewModels[1].Inputs.ElementAt(0).Guid;
+ _NodeLinkViewModels.Add(nodeLink);
+ }
+
+ void MoveTestNodes()
+ {
+ if (_NodeLinkViewModels.Count > 0)
+ {
+ _NodeViewModels[0].Position = new Point(0, 0);
+ }
+ }
+ }
+}
diff --git a/NodeGraph.PreviewTest.NET7/ViewModels/NodeConnectorViewModel.cs b/NodeGraph.PreviewTest.NET7/ViewModels/NodeConnectorViewModel.cs
new file mode 100644
index 0000000..d7f7fa1
--- /dev/null
+++ b/NodeGraph.PreviewTest.NET7/ViewModels/NodeConnectorViewModel.cs
@@ -0,0 +1,78 @@
+using Livet;
+using System;
+
+namespace NodeGraph.PreviewTest.NET7.ViewModels
+{
+ public interface INodeConnectorViewModel
+ {
+ Guid Guid { get; set; }
+ string Label { get; set; }
+ bool IsEnable { get; set; }
+ }
+
+ public class NodeInputViewModel : ViewModel, INodeConnectorViewModel
+ {
+ public Guid Guid
+ {
+ get => _Guid;
+ set => RaisePropertyChangedIfSet(ref _Guid, value);
+ }
+ Guid _Guid = Guid.NewGuid();
+
+ public string Label
+ {
+ get => _Label;
+ set => RaisePropertyChangedIfSet(ref _Label, value);
+ }
+ string _Label = string.Empty;
+
+ public bool IsEnable
+ {
+ get => _IsEnable;
+ set => RaisePropertyChangedIfSet(ref _IsEnable, value);
+ }
+ bool _IsEnable = true;
+
+ public bool AllowToConnectMultiple
+ {
+ get => _AllowToConnectMultiple;
+ set => RaisePropertyChangedIfSet(ref _AllowToConnectMultiple, value);
+ }
+ bool _AllowToConnectMultiple = false;
+
+ public NodeInputViewModel(string label, bool allowToConnectMultiple)
+ {
+ Label = label;
+ AllowToConnectMultiple = allowToConnectMultiple;
+ }
+ }
+
+ public class NodeOutputViewModel : ViewModel, INodeConnectorViewModel
+ {
+ public Guid Guid
+ {
+ get => _Guid;
+ set => RaisePropertyChangedIfSet(ref _Guid, value);
+ }
+ Guid _Guid = Guid.NewGuid();
+
+ public string Label
+ {
+ get => _Label;
+ set => RaisePropertyChangedIfSet(ref _Label, value);
+ }
+ string _Label = string.Empty;
+
+ public bool IsEnable
+ {
+ get => _IsEnable;
+ set => RaisePropertyChangedIfSet(ref _IsEnable, value);
+ }
+ bool _IsEnable = true;
+
+ public NodeOutputViewModel(string label)
+ {
+ Label = label;
+ }
+ }
+}
diff --git a/NodeGraph.PreviewTest.NET7/ViewModels/NodeLinkViewModel.cs b/NodeGraph.PreviewTest.NET7/ViewModels/NodeLinkViewModel.cs
new file mode 100644
index 0000000..8643386
--- /dev/null
+++ b/NodeGraph.PreviewTest.NET7/ViewModels/NodeLinkViewModel.cs
@@ -0,0 +1,57 @@
+using Livet;
+using System;
+
+namespace NodeGraph.PreviewTest.NET7.ViewModels
+{
+ public class NodeLinkViewModel : ViewModel
+ {
+ public Guid Guid
+ {
+ get => _Guid;
+ set => RaisePropertyChangedIfSet(ref _Guid, value);
+ }
+ Guid _Guid = Guid.NewGuid();
+
+ public Guid InputConnectorGuid
+ {
+ get => _InputConnectorGuid;
+ set => RaisePropertyChangedIfSet(ref _InputConnectorGuid, value);
+ }
+ Guid _InputConnectorGuid = Guid.NewGuid();
+
+ public Guid OutputConnectorGuid
+ {
+ get => _OutputConnectorGuid;
+ set => RaisePropertyChangedIfSet(ref _OutputConnectorGuid, value);
+ }
+ Guid _OutputConnectorGuid = Guid.NewGuid();
+
+ public Guid InputConnectorNodeGuid
+ {
+ get => _InputNodeGuid;
+ set => RaisePropertyChangedIfSet(ref _InputNodeGuid, value);
+ }
+ Guid _InputNodeGuid = Guid.NewGuid();
+
+ public Guid OutputConnectorNodeGuid
+ {
+ get => _OutputNodeGuid;
+ set => RaisePropertyChangedIfSet(ref _OutputNodeGuid, value);
+ }
+ Guid _OutputNodeGuid = Guid.NewGuid();
+
+ public bool IsLocked
+ {
+ get => _IsLocked;
+ set => RaisePropertyChangedIfSet(ref _IsLocked, value);
+ }
+ bool _IsLocked = false;
+
+ public bool IsSelected
+ {
+ get => _IsSelected;
+ set => RaisePropertyChangedIfSet(ref _IsSelected, value);
+ }
+ bool _IsSelected = false;
+ }
+}
diff --git a/NodeGraph.PreviewTest.NET7/ViewModels/NodeViewModel.cs b/NodeGraph.PreviewTest.NET7/ViewModels/NodeViewModel.cs
new file mode 100644
index 0000000..252dbc6
--- /dev/null
+++ b/NodeGraph.PreviewTest.NET7/ViewModels/NodeViewModel.cs
@@ -0,0 +1,332 @@
+using Livet;
+using NodeGraph.PreviewTest.NET7.Utilities;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Windows;
+using System.Windows.Input;
+
+namespace NodeGraph.PreviewTest.NET7.ViewModels
+{
+ public interface INodeViewModel
+ {
+ Guid Guid { get; set; }
+ Point Position { get; set; }
+ bool IsSelected { get; set; }
+ }
+
+ public class GroupNodeViewModel : ViewModel, INodeViewModel
+ {
+ public Guid Guid
+ {
+ get => _Guid;
+ set => RaisePropertyChangedIfSet(ref _Guid, value);
+ }
+ Guid _Guid = Guid.NewGuid();
+
+ public string Name
+ {
+ get => _Name;
+ set => RaisePropertyChangedIfSet(ref _Name, value);
+ }
+ string _Name = string.Empty;
+
+ public Point Position
+ {
+ get => _Position;
+ set => RaisePropertyChangedIfSet(ref _Position, value, nameof(Comment));
+ }
+ Point _Position = new Point(0, 0);
+
+ public Point InterlockPosition
+ {
+ get => _InterlockPosition;
+ set => RaisePropertyChangedIfSet(ref _InterlockPosition, value);
+ }
+ Point _InterlockPosition = new Point(0, 0);
+
+ public Point InnerPosition
+ {
+ get => _InnerPosition;
+ set => RaisePropertyChangedIfSet(ref _InnerPosition, value, nameof(Comment));
+ }
+ Point _InnerPosition = new Point(0, 0);
+
+ public double InnerWidth
+ {
+ get => _InnerWidth;
+ set => RaisePropertyChangedIfSet(ref _InnerWidth, value, nameof(Comment));
+ }
+ double _InnerWidth = 100;
+
+ public double InnerHeight
+ {
+ get => _InnerHeight;
+ set => RaisePropertyChangedIfSet(ref _InnerHeight, value, nameof(Comment));
+ }
+ double _InnerHeight = 100;
+
+ public string Comment
+ {
+ get => $"InnerWidth = {InnerWidth:F2}, InnerHeight = {InnerHeight:F2},\n Position = {Position:F2}, InnerPosition = {InnerPosition:F2}";
+ }
+
+ public bool IsSelected
+ {
+ get => _IsSelected;
+ set => RaisePropertyChangedIfSet(ref _IsSelected, value);
+ }
+ bool _IsSelected = false;
+
+ public ICommand SizeChangedCommand => _SizeChangedCommand.Get(SizeChanged);
+ ViewModelCommandHandler _SizeChangedCommand = new ViewModelCommandHandler();
+
+ void SizeChanged(Size newSize)
+ {
+
+ }
+ }
+
+ public abstract class DefaultNodeViewModel : ViewModel, INodeViewModel
+ {
+ public double Width
+ {
+ get => _Width;
+ set => RaisePropertyChangedIfSet(ref _Width, value);
+ }
+ double _Width = 0;
+
+ public double Height
+ {
+ get => _Height;
+ set => RaisePropertyChangedIfSet(ref _Height, value);
+ }
+ double _Height = 0;
+
+ public Guid Guid
+ {
+ get => _Guid;
+ set => RaisePropertyChangedIfSet(ref _Guid, value);
+ }
+ Guid _Guid = Guid.NewGuid();
+
+ public Point Position
+ {
+ get => _Position;
+ set => RaisePropertyChangedIfSet(ref _Position, value);
+ }
+ Point _Position = new Point(0, 0);
+
+ public bool IsSelected
+ {
+ get => _IsSelected;
+ set => RaisePropertyChangedIfSet(ref _IsSelected, value);
+ }
+ bool _IsSelected = false;
+
+ public ICommand SizeChangedCommand => _SizeChangedCommand.Get(SizeChanged);
+ ViewModelCommandHandler _SizeChangedCommand = new ViewModelCommandHandler();
+
+ public abstract IEnumerable Inputs { get; }
+ public abstract IEnumerable Outputs { get; }
+
+ public abstract INodeConnectorViewModel FindConnector(Guid guid);
+
+ void SizeChanged(Size newSize)
+ {
+ Width = newSize.Width;
+ Height = newSize.Height;
+ }
+ }
+
+ public class Test1DefaultNodeViewModel : DefaultNodeViewModel
+ {
+ public string Name
+ {
+ get => _Name;
+ set => RaisePropertyChangedIfSet(ref _Name, value);
+ }
+ string _Name = string.Empty;
+
+ public string Body
+ {
+ get => _Body;
+ set => RaisePropertyChangedIfSet(ref _Body, value);
+ }
+ string _Body = string.Empty;
+
+ public override IEnumerable Inputs => _Inputs;
+ readonly ObservableCollection _Inputs = new ObservableCollection();
+
+ public override IEnumerable Outputs => _Outputs;
+ readonly ObservableCollection _Outputs = new ObservableCollection();
+
+ public Test1DefaultNodeViewModel()
+ {
+ for (int i = 0; i < 4; ++i)
+ {
+ if (i % 2 == 0)
+ {
+ var label = $"Input{i}";
+ if (i > 1)
+ {
+ label += " Allow to connect multiple";
+ }
+ _Inputs.Add(new NodeInputViewModel(label, i > 1));
+ }
+ else
+ {
+ _Inputs.Add(new NodeInputViewModel($"Limited Input", false));
+ }
+ }
+
+ for (int i = 0; i < 5; ++i)
+ {
+ _Outputs.Add(new NodeOutputViewModel($"Output{i}"));
+ }
+ }
+
+ public override INodeConnectorViewModel FindConnector(Guid guid)
+ {
+ var input = Inputs.FirstOrDefault(arg => arg.Guid == guid);
+ if (input != null)
+ {
+ return input;
+ }
+
+ var output = Outputs.FirstOrDefault(arg => arg.Guid == guid);
+ return output;
+ }
+ }
+
+ public class Test2DefaultNodeViewModel : DefaultNodeViewModel
+ {
+ public string Name
+ {
+ get => _Name;
+ set => RaisePropertyChangedIfSet(ref _Name, value);
+ }
+ string _Name = string.Empty;
+
+ public string Body
+ {
+ get => _Body;
+ set => RaisePropertyChangedIfSet(ref _Body, value);
+ }
+ string _Body = string.Empty;
+
+ public override IEnumerable Inputs => _Inputs;
+ readonly ObservableCollection _Inputs = new ObservableCollection();
+
+ public override IEnumerable Outputs => _Outputs;
+ readonly ObservableCollection _Outputs = new ObservableCollection();
+
+ public Test2DefaultNodeViewModel()
+ {
+ for (int i = 0; i < 5; ++i)
+ {
+ var label = $"Input{i}";
+ if (i > 2)
+ {
+ label += " Allow to connect multiple";
+ }
+ _Inputs.Add(new NodeInputViewModel(label, i > 2));
+ }
+
+ for (int i = 0; i < 2; ++i)
+ {
+ _Outputs.Add(new NodeOutputViewModel($"Output{i}"));
+ }
+ }
+
+ public override INodeConnectorViewModel FindConnector(Guid guid)
+ {
+ var input = Inputs.FirstOrDefault(arg => arg.Guid == guid);
+ if (input != null)
+ {
+ return input;
+ }
+
+ var output = Outputs.FirstOrDefault(arg => arg.Guid == guid);
+ return output;
+ }
+ }
+
+ public class Test3DefaultNodeViewModel : DefaultNodeViewModel
+ {
+ public string Name
+ {
+ get => _Name;
+ set => RaisePropertyChangedIfSet(ref _Name, value);
+ }
+ string _Name = string.Empty;
+
+ public string Body
+ {
+ get => _Body;
+ set => RaisePropertyChangedIfSet(ref _Body, value);
+ }
+ string _Body = string.Empty;
+
+ public override IEnumerable Inputs => _Inputs;
+ readonly ObservableCollection _Inputs = new ObservableCollection();
+
+ public override IEnumerable Outputs => _Outputs;
+ readonly ObservableCollection _Outputs = new ObservableCollection();
+
+ public Test3DefaultNodeViewModel()
+ {
+ for (int i = 0; i < 2; ++i)
+ {
+ _Outputs.Add(new NodeOutputViewModel($"Output{i}"));
+ }
+ }
+
+ public override INodeConnectorViewModel FindConnector(Guid guid)
+ {
+ return Outputs.FirstOrDefault(arg => arg.Guid == guid);
+ }
+ }
+
+ public class Test4DefaultNodeViewModel : DefaultNodeViewModel
+ {
+ public string Name
+ {
+ get => _Name;
+ set => RaisePropertyChangedIfSet(ref _Name, value);
+ }
+ string _Name = string.Empty;
+
+ public string Body
+ {
+ get => _Body;
+ set => RaisePropertyChangedIfSet(ref _Body, value);
+ }
+ string _Body = string.Empty;
+
+ public override IEnumerable Inputs => _Inputs;
+ readonly ObservableCollection _Inputs = new ObservableCollection();
+
+ public override IEnumerable Outputs => _Outputs;
+ readonly ObservableCollection _Outputs = new ObservableCollection();
+
+ public Test4DefaultNodeViewModel()
+ {
+ for (int i = 0; i < 5; ++i)
+ {
+ var label = $"Input{i}";
+ if (i > 2)
+ {
+ label += " Allow to connect multiple";
+ }
+ _Inputs.Add(new NodeInputViewModel(label, i > 2));
+ }
+ }
+
+ public override INodeConnectorViewModel FindConnector(Guid guid)
+ {
+ return Inputs.FirstOrDefault(arg => arg.Guid == guid);
+ }
+ }
+}
diff --git a/NodeGraph.PreviewTest.NET7/Views/MainWindow.xaml b/NodeGraph.PreviewTest.NET7/Views/MainWindow.xaml
new file mode 100644
index 0000000..8afce66
--- /dev/null
+++ b/NodeGraph.PreviewTest.NET7/Views/MainWindow.xaml
@@ -0,0 +1,183 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NodeGraph.PreviewTest.NET7/Views/MainWindow.xaml.cs b/NodeGraph.PreviewTest.NET7/Views/MainWindow.xaml.cs
new file mode 100644
index 0000000..bc479fc
--- /dev/null
+++ b/NodeGraph.PreviewTest.NET7/Views/MainWindow.xaml.cs
@@ -0,0 +1,15 @@
+using System.Windows;
+
+namespace NodeGraph.PreviewTest.Views
+{
+ ///
+ /// MainWindow.xaml の相互作用ロジック
+ ///
+ public partial class MainWindow : Window
+ {
+ public MainWindow()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/NodeGraph.PreviewTest/App.xaml.cs b/NodeGraph.PreviewTest/App.xaml.cs
index 18f3466..867d14e 100644
--- a/NodeGraph.PreviewTest/App.xaml.cs
+++ b/NodeGraph.PreviewTest/App.xaml.cs
@@ -1,10 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Configuration;
-using System.Data;
-using System.Linq;
-using System.Threading.Tasks;
-using System.Windows;
+using System.Windows;
namespace NodeGraph.PreviewTest
{
diff --git a/NodeGraph.PreviewTest/Properties/AssemblyInfo.cs b/NodeGraph.PreviewTest/Properties/AssemblyInfo.cs
index 65da9ef..e69a266 100644
--- a/NodeGraph.PreviewTest/Properties/AssemblyInfo.cs
+++ b/NodeGraph.PreviewTest/Properties/AssemblyInfo.cs
@@ -1,6 +1,4 @@
using System.Reflection;
-using System.Resources;
-using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
diff --git a/NodeGraph.PreviewTest/Utilities/ViewModelCommandHandler.cs b/NodeGraph.PreviewTest/Utilities/ViewModelCommandHandler.cs
index af339e6..d0771a4 100644
--- a/NodeGraph.PreviewTest/Utilities/ViewModelCommandHandler.cs
+++ b/NodeGraph.PreviewTest/Utilities/ViewModelCommandHandler.cs
@@ -1,10 +1,5 @@
using Livet.Commands;
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Input;
namespace NodeGraph.Utilities
{
diff --git a/NodeGraph.PreviewTest/ViewModels/MainWindowViewModel.cs b/NodeGraph.PreviewTest/ViewModels/MainWindowViewModel.cs
index 2fbf978..80f9c91 100644
--- a/NodeGraph.PreviewTest/ViewModels/MainWindowViewModel.cs
+++ b/NodeGraph.PreviewTest/ViewModels/MainWindowViewModel.cs
@@ -1,15 +1,12 @@
using Livet;
using Livet.Commands;
using NodeGraph.Operation;
-using NodeGraph.PreviewTest.ViewModels;
using NodeGraph.Utilities;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
namespace NodeGraph.PreviewTest.ViewModels
diff --git a/NodeGraph.PreviewTest/ViewModels/NodeConnectorViewModel.cs b/NodeGraph.PreviewTest/ViewModels/NodeConnectorViewModel.cs
index ae59661..31e4f20 100644
--- a/NodeGraph.PreviewTest/ViewModels/NodeConnectorViewModel.cs
+++ b/NodeGraph.PreviewTest/ViewModels/NodeConnectorViewModel.cs
@@ -1,20 +1,16 @@
using Livet;
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace NodeGraph.PreviewTest.ViewModels
{
- public interface NodeConnectorViewModel
+ public interface INodeConnectorViewModel
{
Guid Guid { get; set; }
string Label { get; set; }
bool IsEnable { get; set; }
}
- public class NodeInputViewModel : ViewModel, NodeConnectorViewModel
+ public class NodeInputViewModel : ViewModel, INodeConnectorViewModel
{
public Guid Guid
{
@@ -51,7 +47,7 @@ public NodeInputViewModel(string label, bool allowToConnectMultiple)
}
}
- public class NodeOutputViewModel : ViewModel, NodeConnectorViewModel
+ public class NodeOutputViewModel : ViewModel, INodeConnectorViewModel
{
public Guid Guid
{
diff --git a/NodeGraph.PreviewTest/ViewModels/NodeLinkViewModel.cs b/NodeGraph.PreviewTest/ViewModels/NodeLinkViewModel.cs
index 038957e..d92a1ad 100644
--- a/NodeGraph.PreviewTest/ViewModels/NodeLinkViewModel.cs
+++ b/NodeGraph.PreviewTest/ViewModels/NodeLinkViewModel.cs
@@ -1,9 +1,5 @@
using Livet;
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace NodeGraph.PreviewTest.ViewModels
{
diff --git a/NodeGraph.PreviewTest/ViewModels/NodeViewModel.cs b/NodeGraph.PreviewTest/ViewModels/NodeViewModel.cs
index f4cbffa..3b75ac2 100644
--- a/NodeGraph.PreviewTest/ViewModels/NodeViewModel.cs
+++ b/NodeGraph.PreviewTest/ViewModels/NodeViewModel.cs
@@ -4,8 +4,6 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
@@ -130,10 +128,10 @@ public bool IsSelected
public ICommand SizeChangedCommand => _SizeChangedCommand.Get(SizeChanged);
ViewModelCommandHandler _SizeChangedCommand = new ViewModelCommandHandler();
- public abstract IEnumerable Inputs { get; }
- public abstract IEnumerable Outputs { get; }
+ public abstract IEnumerable Inputs { get; }
+ public abstract IEnumerable Outputs { get; }
- public abstract NodeConnectorViewModel FindConnector(Guid guid);
+ public abstract INodeConnectorViewModel FindConnector(Guid guid);
void SizeChanged(Size newSize)
{
@@ -158,10 +156,10 @@ public string Body
}
string _Body = string.Empty;
- public override IEnumerable Inputs => _Inputs;
+ public override IEnumerable Inputs => _Inputs;
readonly ObservableCollection _Inputs = new ObservableCollection();
- public override IEnumerable Outputs => _Outputs;
+ public override IEnumerable Outputs => _Outputs;
readonly ObservableCollection _Outputs = new ObservableCollection();
public Test1DefaultNodeViewModel()
@@ -189,7 +187,7 @@ public Test1DefaultNodeViewModel()
}
}
- public override NodeConnectorViewModel FindConnector(Guid guid)
+ public override INodeConnectorViewModel FindConnector(Guid guid)
{
var input = Inputs.FirstOrDefault(arg => arg.Guid == guid);
if (input != null)
@@ -218,10 +216,10 @@ public string Body
}
string _Body = string.Empty;
- public override IEnumerable Inputs => _Inputs;
+ public override IEnumerable Inputs => _Inputs;
readonly ObservableCollection _Inputs = new ObservableCollection();
- public override IEnumerable Outputs => _Outputs;
+ public override IEnumerable Outputs => _Outputs;
readonly ObservableCollection _Outputs = new ObservableCollection();
public Test2DefaultNodeViewModel()
@@ -242,7 +240,7 @@ public Test2DefaultNodeViewModel()
}
}
- public override NodeConnectorViewModel FindConnector(Guid guid)
+ public override INodeConnectorViewModel FindConnector(Guid guid)
{
var input = Inputs.FirstOrDefault(arg => arg.Guid == guid);
if (input != null)
@@ -271,10 +269,10 @@ public string Body
}
string _Body = string.Empty;
- public override IEnumerable Inputs => _Inputs;
+ public override IEnumerable Inputs => _Inputs;
readonly ObservableCollection _Inputs = new ObservableCollection();
- public override IEnumerable Outputs => _Outputs;
+ public override IEnumerable Outputs => _Outputs;
readonly ObservableCollection _Outputs = new ObservableCollection();
public Test3DefaultNodeViewModel()
@@ -285,7 +283,7 @@ public Test3DefaultNodeViewModel()
}
}
- public override NodeConnectorViewModel FindConnector(Guid guid)
+ public override INodeConnectorViewModel FindConnector(Guid guid)
{
return Outputs.FirstOrDefault(arg => arg.Guid == guid);
}
@@ -307,10 +305,10 @@ public string Body
}
string _Body = string.Empty;
- public override IEnumerable Inputs => _Inputs;
+ public override IEnumerable Inputs => _Inputs;
readonly ObservableCollection _Inputs = new ObservableCollection();
- public override IEnumerable Outputs => _Outputs;
+ public override IEnumerable Outputs => _Outputs;
readonly ObservableCollection _Outputs = new ObservableCollection();
public Test4DefaultNodeViewModel()
@@ -326,7 +324,7 @@ public Test4DefaultNodeViewModel()
}
}
- public override NodeConnectorViewModel FindConnector(Guid guid)
+ public override INodeConnectorViewModel FindConnector(Guid guid)
{
return Inputs.FirstOrDefault(arg => arg.Guid == guid);
}
diff --git a/NodeGraph.PreviewTest/Views/MainWindow.xaml.cs b/NodeGraph.PreviewTest/Views/MainWindow.xaml.cs
index d1ec78b..bc479fc 100644
--- a/NodeGraph.PreviewTest/Views/MainWindow.xaml.cs
+++ b/NodeGraph.PreviewTest/Views/MainWindow.xaml.cs
@@ -1,17 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Navigation;
-using System.Windows.Shapes;
+using System.Windows;
namespace NodeGraph.PreviewTest.Views
{
diff --git a/NodeGraph.sln b/NodeGraph.sln
index 5ceaec3..620622e 100644
--- a/NodeGraph.sln
+++ b/NodeGraph.sln
@@ -7,9 +7,13 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NodeGraph.PreviewTest", "No
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NodeGraph", "NodeGraph\NodeGraph.csproj", "{2E2AB11C-015D-40F2-97F6-0E0768FC7069}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NodeGraph.PreviewTest.NET6", "NodeGraph.PreviewTest.NET6\NodeGraph.PreviewTest.NET6.csproj", "{43BBA8F8-A4A3-42CB-855F-917395E9F99C}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NodeGraph.PreviewTest.NET6", "NodeGraph.PreviewTest.NET6\NodeGraph.PreviewTest.NET6.csproj", "{43BBA8F8-A4A3-42CB-855F-917395E9F99C}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NodeGraph.NET6", "NodeGraph.NET6\NodeGraph.NET6.csproj", "{8E201488-F251-4352-9953-3FB06F2D0654}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NodeGraph.NET6", "NodeGraph.NET6\NodeGraph.NET6.csproj", "{8E201488-F251-4352-9953-3FB06F2D0654}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NodeGraph.NET7", "NodeGraph.NET7\NodeGraph.NET7.csproj", "{6F0C31AD-3CEC-4851-A93D-D8BF3AE7B119}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NodeGraph.PreviewTest.NET7", "NodeGraph.PreviewTest.NET7\NodeGraph.PreviewTest.NET7.csproj", "{605A68A2-9EE9-4E28-A3E1-0DEED8BF153F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -33,6 +37,14 @@ Global
{8E201488-F251-4352-9953-3FB06F2D0654}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8E201488-F251-4352-9953-3FB06F2D0654}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8E201488-F251-4352-9953-3FB06F2D0654}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6F0C31AD-3CEC-4851-A93D-D8BF3AE7B119}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6F0C31AD-3CEC-4851-A93D-D8BF3AE7B119}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6F0C31AD-3CEC-4851-A93D-D8BF3AE7B119}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6F0C31AD-3CEC-4851-A93D-D8BF3AE7B119}.Release|Any CPU.Build.0 = Release|Any CPU
+ {605A68A2-9EE9-4E28-A3E1-0DEED8BF153F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {605A68A2-9EE9-4E28-A3E1-0DEED8BF153F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {605A68A2-9EE9-4E28-A3E1-0DEED8BF153F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {605A68A2-9EE9-4E28-A3E1-0DEED8BF153F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/NodeGraph/Controls/CanvasMouseEventArgs.cs b/NodeGraph/Controls/CanvasMouseEventArgs.cs
index d0eb410..ab872a0 100644
--- a/NodeGraph/Controls/CanvasMouseEventArgs.cs
+++ b/NodeGraph/Controls/CanvasMouseEventArgs.cs
@@ -1,10 +1,5 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
-using System.Windows.Input;
namespace NodeGraph.Controls
{
diff --git a/NodeGraph/Controls/DefaultNode.cs b/NodeGraph/Controls/DefaultNode.cs
index 1e63083..6b5d27c 100644
--- a/NodeGraph/Controls/DefaultNode.cs
+++ b/NodeGraph/Controls/DefaultNode.cs
@@ -1,21 +1,10 @@
using System;
using System.Collections;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
-using System.Windows.Controls.Primitives;
-using System.Windows.Data;
-using System.Windows.Documents;
using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Navigation;
-using System.Windows.Shapes;
namespace NodeGraph.Controls
{
diff --git a/NodeGraph/Controls/GridCanvas.cs b/NodeGraph/Controls/GridCanvas.cs
index 29ca056..4c41a4a 100644
--- a/NodeGraph/Controls/GridCanvas.cs
+++ b/NodeGraph/Controls/GridCanvas.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
diff --git a/NodeGraph/Controls/GroupNode.cs b/NodeGraph/Controls/GroupNode.cs
index 1132805..fb86655 100644
--- a/NodeGraph/Controls/GroupNode.cs
+++ b/NodeGraph/Controls/GroupNode.cs
@@ -1,11 +1,7 @@
using System;
-using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
-using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
diff --git a/NodeGraph/Controls/ICanvasObject.cs b/NodeGraph/Controls/ICanvasObject.cs
index b1f56b7..e387115 100644
--- a/NodeGraph/Controls/ICanvasObject.cs
+++ b/NodeGraph/Controls/ICanvasObject.cs
@@ -1,10 +1,5 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
-using System.Windows.Controls;
namespace NodeGraph.Controls
{
diff --git a/NodeGraph/Controls/ISelectableObject.cs b/NodeGraph/Controls/ISelectableObject.cs
index 47903cd..f86b571 100644
--- a/NodeGraph/Controls/ISelectableObject.cs
+++ b/NodeGraph/Controls/ISelectableObject.cs
@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
+using System.Windows;
namespace NodeGraph.Controls
{
diff --git a/NodeGraph/Controls/NodeBase.cs b/NodeGraph/Controls/NodeBase.cs
index 757e4e7..7fdbfc8 100644
--- a/NodeGraph/Controls/NodeBase.cs
+++ b/NodeGraph/Controls/NodeBase.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
diff --git a/NodeGraph/Controls/NodeConnector.cs b/NodeGraph/Controls/NodeConnector.cs
index 9196a30..cbdb4cd 100644
--- a/NodeGraph/Controls/NodeConnector.cs
+++ b/NodeGraph/Controls/NodeConnector.cs
@@ -1,11 +1,7 @@
-using Livet;
-using Livet.EventListeners;
-using System;
+using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
diff --git a/NodeGraph/Controls/NodeInput.cs b/NodeGraph/Controls/NodeInput.cs
index 8f3c900..d02f5e4 100644
--- a/NodeGraph/Controls/NodeInput.cs
+++ b/NodeGraph/Controls/NodeInput.cs
@@ -1,16 +1,6 @@
-using Livet;
-using Livet.EventListeners;
-using NodeGraph.Utilities;
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using NodeGraph.Utilities;
using System.Windows;
using System.Windows.Controls;
-using System.Windows.Controls.Primitives;
-using System.Windows.Media;
namespace NodeGraph.Controls
{
diff --git a/NodeGraph/Controls/NodeLink.cs b/NodeGraph/Controls/NodeLink.cs
index 9334b9f..ba0b40d 100644
--- a/NodeGraph/Controls/NodeLink.cs
+++ b/NodeGraph/Controls/NodeLink.cs
@@ -1,14 +1,9 @@
using NodeGraph.Extensions;
using System;
-using System.Collections.Generic;
using System.Data;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
-using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
diff --git a/NodeGraph/Controls/NodeOuput.cs b/NodeGraph/Controls/NodeOuput.cs
index 225a49b..4e1d5ed 100644
--- a/NodeGraph/Controls/NodeOuput.cs
+++ b/NodeGraph/Controls/NodeOuput.cs
@@ -1,13 +1,6 @@
using NodeGraph.Utilities;
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
-using System.Windows.Controls.Primitives;
namespace NodeGraph.Controls
{
diff --git a/NodeGraph/Controls/RangeSelector.cs b/NodeGraph/Controls/RangeSelector.cs
index 6e6b7b4..758e492 100644
--- a/NodeGraph/Controls/RangeSelector.cs
+++ b/NodeGraph/Controls/RangeSelector.cs
@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
+using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
diff --git a/NodeGraph/Controls/Ruler.cs b/NodeGraph/Controls/Ruler.cs
index 8fb6080..8baef38 100644
--- a/NodeGraph/Controls/Ruler.cs
+++ b/NodeGraph/Controls/Ruler.cs
@@ -1,9 +1,5 @@
using System;
-using System.Collections.Generic;
using System.Globalization;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
diff --git a/NodeGraph/Controls/StaticDefinition.cs b/NodeGraph/Controls/StaticDefinition.cs
index e321a64..7c4b5d1 100644
--- a/NodeGraph/Controls/StaticDefinition.cs
+++ b/NodeGraph/Controls/StaticDefinition.cs
@@ -1,10 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace NodeGraph.Controls
+namespace NodeGraph.Controls
{
public static class ControlSize
{
diff --git a/NodeGraph/Converters/InverseBooleanToVisibilityConverter.cs b/NodeGraph/Converters/InverseBooleanToVisibilityConverter.cs
index e6ce920..dd00cd1 100644
--- a/NodeGraph/Converters/InverseBooleanToVisibilityConverter.cs
+++ b/NodeGraph/Converters/InverseBooleanToVisibilityConverter.cs
@@ -1,9 +1,5 @@
using System;
-using System.Collections.Generic;
using System.Globalization;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
diff --git a/NodeGraph/Extensions/PointExtension.cs b/NodeGraph/Extensions/PointExtension.cs
index e480b8d..bb43d51 100644
--- a/NodeGraph/Extensions/PointExtension.cs
+++ b/NodeGraph/Extensions/PointExtension.cs
@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
+using System.Windows;
namespace NodeGraph.Extensions
{
diff --git a/NodeGraph/Extensions/VectorExtension.cs b/NodeGraph/Extensions/VectorExtension.cs
index af9b8d6..e388a93 100644
--- a/NodeGraph/Extensions/VectorExtension.cs
+++ b/NodeGraph/Extensions/VectorExtension.cs
@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
+using System.Windows;
namespace NodeGraph.Extensions
{
diff --git a/NodeGraph/Operation/BeginMoveNodesOperationEventArgs.cs b/NodeGraph/Operation/BeginMoveNodesOperationEventArgs.cs
index 581370d..ce26255 100644
--- a/NodeGraph/Operation/BeginMoveNodesOperationEventArgs.cs
+++ b/NodeGraph/Operation/BeginMoveNodesOperationEventArgs.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace NodeGraph.Operation
{
diff --git a/NodeGraph/Operation/ConnectedLinkOperationEventArgs.cs b/NodeGraph/Operation/ConnectedLinkOperationEventArgs.cs
index e997096..cb618c7 100644
--- a/NodeGraph/Operation/ConnectedLinkOperationEventArgs.cs
+++ b/NodeGraph/Operation/ConnectedLinkOperationEventArgs.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace NodeGraph.Operation
{
diff --git a/NodeGraph/Operation/DisconnectedLinkOperationEventArgs.cs b/NodeGraph/Operation/DisconnectedLinkOperationEventArgs.cs
index eab0386..84afe55 100644
--- a/NodeGraph/Operation/DisconnectedLinkOperationEventArgs.cs
+++ b/NodeGraph/Operation/DisconnectedLinkOperationEventArgs.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace NodeGraph.Operation
{
diff --git a/NodeGraph/Operation/EndMoveNodesOperationEventArgs.cs b/NodeGraph/Operation/EndMoveNodesOperationEventArgs.cs
index aecf4b3..a59e432 100644
--- a/NodeGraph/Operation/EndMoveNodesOperationEventArgs.cs
+++ b/NodeGraph/Operation/EndMoveNodesOperationEventArgs.cs
@@ -1,9 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
namespace NodeGraph.Operation
{
diff --git a/NodeGraph/Operation/PreviewConnectLinkOperationEventArgs.cs b/NodeGraph/Operation/PreviewConnectLinkOperationEventArgs.cs
index 4e6663d..1a3444e 100644
--- a/NodeGraph/Operation/PreviewConnectLinkOperationEventArgs.cs
+++ b/NodeGraph/Operation/PreviewConnectLinkOperationEventArgs.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace NodeGraph.Operation
{
diff --git a/NodeGraph/Properties/AssemblyInfo.cs b/NodeGraph/Properties/AssemblyInfo.cs
index 1a14702..41aa910 100644
--- a/NodeGraph/Properties/AssemblyInfo.cs
+++ b/NodeGraph/Properties/AssemblyInfo.cs
@@ -1,6 +1,4 @@
using System.Reflection;
-using System.Resources;
-using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
diff --git a/NodeGraph/Utilities/ResourceInstance.cs b/NodeGraph/Utilities/ResourceInstance.cs
index d6a6eda..2c7ac55 100644
--- a/NodeGraph/Utilities/ResourceInstance.cs
+++ b/NodeGraph/Utilities/ResourceInstance.cs
@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
+using System.Windows;
using System.Windows.Threading;
namespace NodeGraph.Utilities