diff --git a/AIStudio.Wpf.DiagramApp/AIStudio.Wpf.DiagramApp_gpbabrim_wpftmp.csproj b/AIStudio.Wpf.DiagramApp/AIStudio.Wpf.DiagramApp_gpbabrim_wpftmp.csproj
new file mode 100644
index 0000000..b68d647
--- /dev/null
+++ b/AIStudio.Wpf.DiagramApp/AIStudio.Wpf.DiagramApp_gpbabrim_wpftmp.csproj
@@ -0,0 +1,1058 @@
+
+
+ AIStudio.Wpf.DiagramApp
+ obj\Debug\
+ obj\
+ F:\aistudio.-wpf.-diagram\AIStudio.Wpf.DiagramApp\obj\
+ <_TargetAssemblyProjectName>AIStudio.Wpf.DiagramApp
+
+
+
+ WinExe
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+
+ 8.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AIStudio.Wpf.DiagramApp/ViewModels/MindViewModel.cs b/AIStudio.Wpf.DiagramApp/ViewModels/MindViewModel.cs
index 1279cbb..054a19e 100644
--- a/AIStudio.Wpf.DiagramApp/ViewModels/MindViewModel.cs
+++ b/AIStudio.Wpf.DiagramApp/ViewModels/MindViewModel.cs
@@ -29,7 +29,8 @@ namespace AIStudio.Wpf.Flowchart
{
base.InitDiagramViewModel();
- DiagramViewModel.GridCellSize = new Size(100, 100);
+ DiagramViewModel.GridCellSize = new Size(100, 100);
+ DiagramViewModel.ShowGrid= false;
_service.DrawModeViewModel.LineDrawMode = DrawMode.ConnectingLineSmooth;
DiagramViewModel.AllowDrop = false;
}
@@ -38,35 +39,32 @@ namespace AIStudio.Wpf.Flowchart
{
base.Init();
- MindLevel1Node level1node = new MindLevel1Node() { Text = "思维导图" };
+ MindNode level1node = new MindNode(DiagramViewModel, Mind.NodeLevel.Level1) { Text = "思维导图" };
DiagramViewModel.DirectAddItemCommand.Execute(level1node);
DiagramViewModel.CenterMoveCommand.Execute(level1node);
- MindLevel2Node level2node1_1 = new MindLevel2Node() { Text = "分支主题1" };
- DiagramViewModel.DirectAddItemCommand.Execute(level2node1_1);
- level1node.Children.Add(level2node1_1);
+ MindNode level2node1_1 = new MindNode(DiagramViewModel, Mind.NodeLevel.Level2) { Text = "分支主题1" };
+ level1node.AddChild(level2node1_1);
- MindLevel3Node level3node1_1_1 = new MindLevel3Node() { Text = "分支主题1_1" };
- DiagramViewModel.DirectAddItemCommand.Execute(level3node1_1_1);
- level2node1_1.Children.Add(level3node1_1_1);
+ MindNode level3node1_1_1 = new MindNode(DiagramViewModel, Mind.NodeLevel.Level3) { Text = "分支主题1_1" };
+ level2node1_1.AddChild(level3node1_1_1);
- MindLevel3Node level3node1_1_2 = new MindLevel3Node() { Text = "分支主题1_2" };
- DiagramViewModel.DirectAddItemCommand.Execute(level3node1_1_2);
- level2node1_1.Children.Add(level3node1_1_2);
+ MindNode level3node1_1_2 = new MindNode(DiagramViewModel, Mind.NodeLevel.Level3) { Text = "分支主题1_2" };
+ level2node1_1.AddChild(level3node1_1_2);
- MindLevel3Node level3node1_1_3 = new MindLevel3Node() { Text = "分支主题1_3" };
- DiagramViewModel.DirectAddItemCommand.Execute(level3node1_1_3);
- level2node1_1.Children.Add(level3node1_1_3);
+ MindNode level3node1_1_3 = new MindNode(DiagramViewModel, Mind.NodeLevel.Level3) { Text = "分支主题1_3" };
+ level2node1_1.AddChild(level3node1_1_3);
- MindLevel2Node level2node1_2 = new MindLevel2Node() { Text = "分支主题2" };
- DiagramViewModel.DirectAddItemCommand.Execute(level2node1_2);
- level1node.Children.Add(level2node1_2);
+ MindNode level2node1_2 = new MindNode(DiagramViewModel, Mind.NodeLevel.Level2) { Text = "分支主题2" };
+ level1node.AddChild(level2node1_2);
+ MindNode level2node1_3 = new MindNode(DiagramViewModel, Mind.NodeLevel.Level2) { Text = "分支主题3" };
+ level1node.AddChild(level2node1_3);
- DiagramViewModel.ClearSelectedItemsCommand.Execute(null);
-
+ DiagramViewModel.ClearSelectedItemsCommand.Execute(null);
level1node.LayoutUpdated();
+
}
public override void Dispose()
diff --git a/AIStudio.Wpf.DiagramDesigner/Converters/IntToBoolConverter.cs b/AIStudio.Wpf.DiagramDesigner/Converters/IntToBoolConverter.cs
index 5ff50ac..9c85874 100644
--- a/AIStudio.Wpf.DiagramDesigner/Converters/IntToBoolConverter.cs
+++ b/AIStudio.Wpf.DiagramDesigner/Converters/IntToBoolConverter.cs
@@ -1,24 +1,25 @@
using System;
+using System.Windows;
using System.Windows.Data;
namespace AIStudio.Wpf.DiagramDesigner.Converters
{
- public class IntToBoolConverter : IValueConverter
+ public class IntToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
- if (object.Equals(value, 0d))
- return false;
+ if (value == null || object.Equals(value, 0))
+ return Visibility.Collapsed;
else
- return true;
+ return Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
- if (object.Equals(value, false))
- return 0d;
+ if (object.Equals(value, Visibility.Collapsed))
+ return 0;
else
- return 1d;
+ return 1;
}
}
}
diff --git a/AIStudio.Wpf.DiagramDesigner/Converters/IntToVisibilityConverter.cs b/AIStudio.Wpf.DiagramDesigner/Converters/IntToVisibilityConverter.cs
new file mode 100644
index 0000000..5ff50ac
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner/Converters/IntToVisibilityConverter.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Windows.Data;
+
+namespace AIStudio.Wpf.DiagramDesigner.Converters
+{
+ public class IntToBoolConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ if (object.Equals(value, 0d))
+ return false;
+ else
+ return true;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ if (object.Equals(value, false))
+ return 0d;
+ else
+ return 1d;
+ }
+ }
+}
diff --git a/AIStudio.Wpf.DiagramDesigner/Geometrys/SizeBase.cs b/AIStudio.Wpf.DiagramDesigner/Geometrys/SizeBase.cs
index 3b07922..63a2bec 100644
--- a/AIStudio.Wpf.DiagramDesigner/Geometrys/SizeBase.cs
+++ b/AIStudio.Wpf.DiagramDesigner/Geometrys/SizeBase.cs
@@ -76,6 +76,8 @@ namespace AIStudio.Wpf.DiagramDesigner.Geometrys
public SizeBase Add(double value) => new SizeBase(Width + value, Height + value);
+ public SizeBase Add(double width, double height) => new SizeBase(Width + width, Height + height);
+
//public bool Equals(Size size) => size != null && Width == size.Width && Height == size.Height;
//public override string ToString() => $"Size(width={Width}, height={Height})";
diff --git a/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.Smooth.cs b/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.Smooth.cs
index 6211a04..7dd2c7e 100644
--- a/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.Smooth.cs
+++ b/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.Smooth.cs
@@ -6,7 +6,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{
public static partial class PathGenerators
{
- private const double _margin = 125;
+
public static PathGeneratorResult Smooth(IDiagramViewModel _, ConnectionViewModel link, PointBase[] route, PointBase source, PointBase target)
{
@@ -74,17 +74,39 @@ namespace AIStudio.Wpf.DiagramDesigner
if (sourceOrientation == ConnectorOrientation.None)//按照线条的四象限来处理。
{
var slope = (route[1].Y - route[0].Y) / (route[1].X - route[0].X);
+ if (Math.Abs(slope) < link.SmoothAutoSlope)
+ {
+ if (route[1].X > route[0].X)
+ {
+ sourceOrientation = ConnectorOrientation.Right;
+ }
+ else
+ {
+ sourceOrientation = ConnectorOrientation.Left;
+ }
+ }
+ else
+ {
+ if (route[1].Y > route[0].Y)//Y轴方向是反的
+ {
+ sourceOrientation = ConnectorOrientation.Bottom;
+ }
+ else
+ {
+ sourceOrientation = ConnectorOrientation.Top;
+ }
+ }
}
- var curvePointA = GetCurvePoint(route[0].X, route[0].Y, cX, cY, sourceOrientation);
- var curvePointB = GetCurvePoint(route[1].X, route[1].Y, cX, cY, link.SinkConnectorInfo?.Orientation);
+ var curvePointA = GetCurvePoint(route[0].X, route[0].Y, cX, cY, link.SmoothMargin, sourceOrientation);
+ var curvePointB = GetCurvePoint(route[1].X, route[1].Y, cX, cY, link.SmoothMargin, link.SinkConnectorInfo?.Orientation);
return new[] { route[0], curvePointA, curvePointB, route[1] };
}
}
- private static PointBase GetCurvePoint(double pX, double pY, double cX, double cY, ConnectorOrientation? alignment)
+ private static PointBase GetCurvePoint(double pX, double pY, double cX, double cY, double smoothMargin, ConnectorOrientation? alignment)
{
- var margin = Math.Min(_margin, Math.Pow(Math.Pow(pX - cX, 2) + Math.Pow(pY - cY, 2), .5));
+ var margin = Math.Min(smoothMargin, Math.Pow(Math.Pow(pX - cX, 2) + Math.Pow(pY - cY, 2), .5));
switch (alignment)
{
case ConnectorOrientation.Top: return new PointBase(pX, Math.Min(pY - margin, cY));
diff --git a/AIStudio.Wpf.DiagramDesigner/UserControls/DiagramControl.xaml b/AIStudio.Wpf.DiagramDesigner/UserControls/DiagramControl.xaml
index abc6a2f..0c40cf4 100644
--- a/AIStudio.Wpf.DiagramDesigner/UserControls/DiagramControl.xaml
+++ b/AIStudio.Wpf.DiagramDesigner/UserControls/DiagramControl.xaml
@@ -301,13 +301,15 @@
+ Value="{Binding EnabledForSelection}" />
+ Value="{Binding EnabledForConnection}" />
+
+ Value="{Binding ItemHeight}" />
@@ -351,7 +353,7 @@
VerticalAlignment="Stretch"
Content="{TemplateBinding Content}" />
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
\ No newline at end of file
diff --git a/AIStudio.Wpf.Mind/ViewModels/MindNode.cs b/AIStudio.Wpf.Mind/ViewModels/MindNode.cs
index 05f2d20..a2c1847 100644
--- a/AIStudio.Wpf.Mind/ViewModels/MindNode.cs
+++ b/AIStudio.Wpf.Mind/ViewModels/MindNode.cs
@@ -1,9 +1,13 @@
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.ComponentModel;
+using System.IO;
using System.Linq;
using System.Text;
+using System.Windows.Media;
using AIStudio.Wpf.DiagramDesigner;
+using AIStudio.Wpf.DiagramDesigner.Algorithms;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
using AIStudio.Wpf.DiagramDesigner.Models;
@@ -13,12 +17,12 @@ namespace AIStudio.Wpf.Mind.ViewModels
{
public MindNode(NodeLevel nodeLevel) : this(null, nodeLevel)
{
-
}
public MindNode(IDiagramViewModel root, NodeLevel nodeLevel) : base(root)
{
NodeLevel = nodeLevel;
+ LevelInit(true);
}
public MindNode(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
@@ -29,6 +33,90 @@ namespace AIStudio.Wpf.Mind.ViewModels
{
}
+ protected override void Init(IDiagramViewModel root)
+ {
+ base.Init(root);
+
+ EnabledForConnection = false;
+
+ AddChildCommand = new SimpleCommand(Command_Enable, ExecuteAddChildCommand);
+ AddParentCommand = new SimpleCommand(Level_Enable, ExecuteAddParentCommand);
+ AddPeerCommand = new SimpleCommand(Level_Enable, ExecuteAddPeerCommand);
+ DeleteCommand = new SimpleCommand(Command_Enable, ExecuteDeleteCommand);
+ MoveForwardCommand = new SimpleCommand(Command_Enable, ExecuteMoveForwardCommand);
+ MoveBackCommand = new SimpleCommand(Command_Enable, ExecuteMoveBackCommand);
+ BuildMenuOptions();
+
+ this.PropertyChanged += this.Item_PropertyChanged;
+ }
+
+ private void LevelInit(bool init =false)
+ {
+ switch (NodeLevel)
+ {
+ case NodeLevel.Level1:
+ {
+ ItemWidth = 110;
+ ItemHeight = 40;
+ this.ClearConnectors();
+ var port = new FullyCreatedConnectorInfo(Root, this, ConnectorOrientation.None, true) { XRatio = 0.5, YRatio = 0.5 };
+ this.AddConnector(port);
+ IsInnerConnector = true;
+
+ ColorViewModel.FillColor.Color = Color.FromRgb(0x73, 0xa1, 0xbf);
+ ColorViewModel.LineColor.Color = Color.FromRgb(0x73, 0xa1, 0xbf);
+ FontViewModel.FontColor = Colors.White;
+ FontViewModel.FontSize = 15;
+ Spacing = new SizeBase(50, 15);
+ ShapeViewModel.SinkMarker.PathStyle = ArrowPathStyle.Circle;
+ ShapeViewModel.SinkMarker.SizeStyle = ArrowSizeStyle.VerySmall;
+
+ break;
+ }
+ case NodeLevel.Level2:
+ {
+ ItemWidth = 80;
+ ItemHeight = 25;
+ this.ClearConnectors();
+ var port1 = new FullyCreatedConnectorInfo(Root, this, ConnectorOrientation.Left, true) { XRatio = 0, YRatio = 0.5 };
+ this.AddConnector(port1);
+ var port2 = new FullyCreatedConnectorInfo(Root, this, ConnectorOrientation.Right, true) { XRatio = 1, YRatio = 0.5 };
+ this.AddConnector(port2);
+ IsInnerConnector = true;
+
+ ColorViewModel.LineColor.Color = Color.FromRgb(0x73, 0xa1, 0xbf);
+ ShapeViewModel.SinkMarker.PathStyle = ArrowPathStyle.None;
+ ShapeViewModel.SinkMarker.SizeStyle = ArrowSizeStyle.VerySmall;
+ break;
+ }
+ case NodeLevel.Level3:
+ {
+ ItemWidth = 80;
+ ItemHeight = 25;
+ this.ClearConnectors();
+ var port1 = new FullyCreatedConnectorInfo(Root, this, ConnectorOrientation.Left, true) { XRatio = 0, YRatio = 1 };
+ this.AddConnector(port1);
+ var port2 = new FullyCreatedConnectorInfo(Root, this, ConnectorOrientation.Right, true) { XRatio = 1, YRatio = 1 };
+ this.AddConnector(port2);
+ IsInnerConnector = true;
+
+ ColorViewModel.LineColor.Color = Color.FromRgb(0x73, 0xa1, 0xbf);
+ ShapeViewModel.SinkMarker.PathStyle = ArrowPathStyle.None;
+ ShapeViewModel.SinkMarker.SizeStyle = ArrowSizeStyle.VerySmall;
+ break;
+ }
+ }
+ }
+
+
+
+ private bool Level_Enable(object obj)
+ {
+ if (Command_Enable(obj) == false) return false;
+
+ return NodeLevel != NodeLevel.Level1;
+ }
+
[Browsable(false)]
public NodeLevel NodeLevel
{
@@ -48,10 +136,28 @@ namespace AIStudio.Wpf.Mind.ViewModels
}
}
- public double Spacing
+ private bool _isExpanded = true;
+ public bool IsExpanded
+ {
+ get
+ {
+ return _isExpanded;
+ }
+ set
+ {
+ SetProperty(ref _isExpanded, value);
+ }
+ }
+
+ public bool LayoutUpdating
{
get; set;
- } = 20;
+ }
+
+ public SizeBase Spacing
+ {
+ get; set;
+ } = new SizeBase(15, 15);
public List Children
{
@@ -62,170 +168,357 @@ namespace AIStudio.Wpf.Mind.ViewModels
{
get
{
- return this.Size.Add(Spacing * 2);
+ return this.Size.Add(Spacing.Width * 2, Spacing.Height * 2);
}
}
public SizeBase DesiredSize
{
- get;set;
+ get; set;
}
- public SizeBase MeasureOverride()
+ public PointBase DesiredPosition
{
- var sizewithSpacing = SizeWithSpacing;
- if (Children?.Count > 0)
+ get; set;
+ }
+
+ public PointBase Offset
+ {
+ get; set;
+ }
+
+ public SimpleCommand AddParentCommand
+ {
+ get; private set;
+ }
+
+ public SimpleCommand AddChildCommand
+ {
+ get; private set;
+ }
+
+ public SimpleCommand AddPeerCommand
+ {
+ get; private set;
+ }
+
+ public SimpleCommand DeleteCommand
+ {
+ get; private set;
+ }
+
+ public SimpleCommand MoveForwardCommand
+ {
+ get; private set;
+ }
+
+ public SimpleCommand MoveBackCommand
+ {
+ get; private set;
+ }
+
+ private void BuildMenuOptions()
+ {
+ menuOptions = new ObservableCollection();
+ CinchMenuItem menuItem = new CinchMenuItem();
+ menuItem.Text = "下级";
+ menuItem.Command = AddChildCommand;
+ menuOptions.Add(menuItem);
+ menuItem = new CinchMenuItem();
+ menuItem.Text = "同级";
+ menuItem.Command = AddPeerCommand;
+ menuOptions.Add(menuItem);
+ //menuItem = new CinchMenuItem();
+ //menuItem.Text = "上级";
+ //menuItem.Command = AddParentCommand;
+ //menuOptions.Add(menuItem);
+ menuItem = new CinchMenuItem();
+ menuItem.Text = "前移";
+ menuItem.Command = MoveForwardCommand;
+ menuOptions.Add(menuItem);
+ menuItem = new CinchMenuItem();
+ menuItem.Text = "后移";
+ menuItem.Command = MoveBackCommand;
+ menuOptions.Add(menuItem);
+ menuItem = new CinchMenuItem();
+ menuItem.Text = "删除";
+ menuItem.Command = DeleteCommand;
+ menuOptions.Add(menuItem);
+ }
+
+ public void ExecuteAddChildCommand(object obj)
+ {
+ if (obj is MindNode node)
{
- var childrensizes = Children.Select(p => p.MeasureOverride()).ToArray();
- sizewithSpacing = new SizeBase(sizewithSpacing.Width + childrensizes.Max(p => p.Width), Math.Max(sizewithSpacing.Height, childrensizes.Sum(p => p.Height)));
}
- DesiredSize = sizewithSpacing;
- return DesiredSize;
+ else
+ {
+ if (NodeLevel == NodeLevel.Level1)
+ node = new MindNode(Root, NodeLevel.Level2) { Text = "分支主题" };
+ else
+ node = new MindNode(Root, NodeLevel.Level3) { Text = "分支主题" };
+ }
+ AddChild(node);
+
+ LayoutUpdated();
+ }
+
+ public void ExecuteAddParentCommand(object obj)
+ {
+ if (Parent is MindNode parent)
+ {
+ if (obj is MindNode node)
+ {
+ }
+ else
+ {
+ if (NodeLevel == NodeLevel.Level1)
+ {
+ return;
+ }
+ else if (NodeLevel == NodeLevel.Level2)
+ node = new MindNode(Root, NodeLevel.Level2) { Text = "分支主题" };
+ else
+ node = new MindNode(Root, NodeLevel.Level3) { Text = "分支主题" };
+ }
+
+ parent.RemoveChild(this);
+ int index = parent.Children.IndexOf(this);
+ parent.AddChild(node, index + 1);
+ node.AddChild(this);
+
+ LayoutUpdated();
+ }
+ }
+
+ public void ExecuteAddPeerCommand(object obj)
+ {
+ if (Parent is MindNode parent)
+ {
+ if (obj is MindNode node)
+ {
+ }
+ else
+ {
+ if (NodeLevel == NodeLevel.Level1)
+ {
+ return;
+ }
+ else if (NodeLevel == NodeLevel.Level2)
+ node = new MindNode(Root, NodeLevel.Level2) { Text = "分支主题" };
+ else
+ node = new MindNode(Root, NodeLevel.Level3) { Text = "分支主题" };
+ }
+ int index = parent.Children.IndexOf(this);
+ parent.AddChild(node, index + 1);
+
+ LayoutUpdated();
+ }
+ }
+
+ private void ExecuteMoveBackCommand(object obj)
+ {
+ if (Parent is MindNode parent)
+ {
+ int index = parent.Children.IndexOf(this);
+ if (index < parent.Children.Count - 1)
+ {
+ parent.RemoveChild(this);
+ parent.AddChild(this, index + 1);
+ LayoutUpdated();
+ }
+ }
+ }
+
+ private void ExecuteMoveForwardCommand(object obj)
+ {
+ if (Parent is MindNode parent)
+ {
+ int index = parent.Children.IndexOf(this);
+ if (index > 0)
+ {
+ parent.RemoveChild(this);
+ parent.AddChild(this, index - 1);
+ LayoutUpdated();
+ }
+ }
+ }
+
+ private void ExecuteDeleteCommand(object obj)
+ {
+ if (Parent is MindNode parent)
+ {
+ parent.RemoveChild(this);
+ LayoutUpdated();
+ }
+ }
+
+ public void AddChild(MindNode item, int index = -1)
+ {
+ if (index >= 0)
+ {
+ this.Children.Insert(index, item);
+ }
+ else
+ {
+ this.Children.Add(item);
+ }
+ item.Parent = this;
+ //item.ParentId = this.Id;
+ Root?.DirectAddItemCommand.Execute(item);
+
+ ConnectionViewModel connector = new ConnectionViewModel(Root, this.Connectors.FirstOrDefault(), item.Connectors.FirstOrDefault());
+ connector.ColorViewModel.LineColor = this.ColorViewModel.LineColor;
+ connector.SmoothMargin = 20;
+ connector.SmoothAutoSlope = 0.2;
+ connector.ShapeViewModel.SinkMarker.PathStyle = this.ShapeViewModel.SinkMarker.PathStyle;
+ connector.ShapeViewModel.SinkMarker.SizeStyle = this.ShapeViewModel.SinkMarker.SizeStyle;
+
+ Root?.DirectAddItemCommand.Execute(connector);
+
+ Root?.BringForwardCommand.Execute(new DesignerItemViewModelBase[] { item });
+
+ Root?.ClearSelectedItemsCommand.Execute(new SelectableDesignerItemViewModelBase[] { connector });
+ }
+
+ public void RemoveChild(MindNode item)
+ {
+ item.PropertyChanged -= Item_PropertyChanged;
+
+ this.Children.Remove(item);
+
+ var connectors = Root?.Items.OfType().Where(p => p.SinkConnectorInfoFully?.DataItem == item).ToList();
+
+ Root?.DirectRemoveItemCommand.Execute(item);
+ Root?.DirectRemoveItemCommand.Execute(connectors);
+ if (item.Children?.Count > 0)
+ {
+ foreach (var child in item.Children.ToList())
+ {
+ item.RemoveChild(child);
+ }
+ }
+ }
+
+ public MindNode GetLevel1Node()
+ {
+ var node = this;
+ while (node.Parent is MindNode mindNode)
+ {
+ node = mindNode;
+ }
+ return node;
+ }
+
+ private void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ switch (e.PropertyName)
+ {
+ case nameof(IsExpanded):
+ GetLevel1Node()?.LayoutUpdated();
+ break;
+ case nameof(NodeLevel):
+ LevelInit();
+ break;
+ case nameof(Left):
+ {
+
+ if (e is ValuePropertyChangedEventArgs valuePropertyChangedEventArgs)
+ {
+ if (NodeLevel == NodeLevel.Level1)
+ {
+ LayoutUpdated();
+ }
+ else
+ {
+ UpdateOffsetX((double)valuePropertyChangedEventArgs.OldValue, (double)valuePropertyChangedEventArgs.NewValue);
+ LayoutUpdated();
+ }
+ }
+ break;
+ }
+ case nameof(Top):
+ {
+ if (e is ValuePropertyChangedEventArgs valuePropertyChangedEventArgs)
+ {
+ if (NodeLevel == NodeLevel.Level1)
+ {
+ LayoutUpdated();
+ }
+ else
+ {
+ UpdateOffsetY((double)valuePropertyChangedEventArgs.OldValue, (double)valuePropertyChangedEventArgs.NewValue);
+ LayoutUpdated();
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ public void UpdateOffsetX(double oldvalue, double newvalue)
+ {
+ if (GetLevel1Node()?.LayoutUpdating == true) return;
+
+ Offset += new VectorBase(newvalue - oldvalue, 0);
+ }
+
+ public void UpdateOffsetY(double oldvalue, double newvalue)
+ {
+ if (GetLevel1Node()?.LayoutUpdating == true) return;
+
+ Offset += new VectorBase(0, newvalue - oldvalue);
}
public void LayoutUpdated()
{
- var size = MeasureOverride();
- ArrangeOverride(size);
+ GetLevel1Node()?.Level1LayoutUpdated();
}
- public void ArrangeOverride(SizeBase sizeBase)
+ protected void Level1LayoutUpdated()
{
- double left = MiddlePosition.X + ItemWidth / 2 + Spacing;
- double top = MiddlePosition.Y - sizeBase.Height / 2;
+ LayoutUpdating = true;
+ var size = MeasureOverride();
+ ArrangeOverride();
+
+ Root.BringToFrontCommand.Execute(new SelectableDesignerItemViewModelBase[] { this });
+ Root?.ReconnectLinksToClosestPorts();
+
+ LayoutUpdating = false;
+ }
+
+ protected SizeBase MeasureOverride(bool isExpanded = true)
+ {
+ var sizewithSpacing = SizeWithSpacing;
+ if (Children?.Count > 0)
+ {
+ var childrensizes = Children.Select(p => p.MeasureOverride(IsExpanded && isExpanded)).ToArray();
+ sizewithSpacing = new SizeBase(sizewithSpacing.Width + childrensizes.Max(p => p.Width), Math.Max(sizewithSpacing.Height, childrensizes.Sum(p => p.Height)));
+ }
+ DesiredSize = isExpanded ? sizewithSpacing : new SizeBase(0, 0);
+ Visible = isExpanded;
+ var connectors = Root?.Items.OfType().Where(p => p.SinkConnectorInfoFully?.DataItem == this).ToList();
+ connectors?.ForEach(p => p.Visible = Visible);
+ return DesiredSize;
+ }
+
+ protected void ArrangeOverride()
+ {
+ double left = MiddlePosition.X + ItemWidth / 2 + Spacing.Width;
+ double top = MiddlePosition.Y - DesiredSize.Height / 2;
if (Children?.Count > 0)
{
foreach (var child in Children)
{
- child.Left = left + Spacing;
- child.Top = top + child.DesiredSize.Height / 2 - child.ItemHeight;
+
+ child.Left = left + child.Spacing.Width + child.Offset.X;
+ child.Top = top + child.DesiredSize.Height / 2 - child.ItemHeight / 2 + child.Offset.Y;
+ child.DesiredPosition = child.Position;
top += child.DesiredSize.Height;
- child.ArrangeOverride(child.DesiredSize);
+ child.ArrangeOverride();
}
}
}
}
-
- public class MindLevel1Node : MindNode
- {
- public MindLevel1Node() : this(null)
- {
-
- }
-
- public MindLevel1Node(IDiagramViewModel root) : base(root, NodeLevel.Level1)
- {
-
- }
-
- public MindLevel1Node(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
- {
-
- }
-
- public MindLevel1Node(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
- {
-
- }
- protected override void Init(IDiagramViewModel root)
- {
- base.Init(root);
-
- ItemWidth = 80;
- ItemHeight = 40;
- this.ClearConnectors();
- var port = new FullyCreatedConnectorInfo(root, this, ConnectorOrientation.None, true) { XRatio = 0.5, YRatio = 0.5 };
- this.AddConnector(port);
- IsInnerConnector = true;
- }
-
- public RectangleBase Rectangle
- {
- get; set;
- }
-
- }
-
- public class MindLevel2Node : MindNode
- {
- public MindLevel2Node() : this(null)
- {
-
- }
-
- public MindLevel2Node(IDiagramViewModel root) : base(root, NodeLevel.Level2)
- {
-
- }
-
- public MindLevel2Node(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
- {
-
- }
-
- public MindLevel2Node(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
- {
-
- }
-
- protected override void Init(IDiagramViewModel root)
- {
- base.Init(root);
-
- ItemWidth = 80;
- ItemHeight = 40;
- this.ClearConnectors();
- var port1 = new FullyCreatedConnectorInfo(root, this, ConnectorOrientation.None, true) { XRatio = 0, YRatio = 0.5 };
- this.AddConnector(port1);
- var port2 = new FullyCreatedConnectorInfo(root, this, ConnectorOrientation.None, true) { XRatio = 1, YRatio = 0.5 };
- this.AddConnector(port2);
- IsInnerConnector = true;
- }
-
- public PointBase Offset
- {
- get; set;
- }
- }
-
- public class MindLevel3Node : MindNode
- {
- public MindLevel3Node() : this(null)
- {
-
- }
-
- public MindLevel3Node(IDiagramViewModel root) : base(root, NodeLevel.Level2)
- {
-
- }
-
- public MindLevel3Node(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
- {
-
- }
-
- public MindLevel3Node(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
- {
-
- }
- protected override void Init(IDiagramViewModel root)
- {
- base.Init(root);
-
- ItemWidth = 80;
- ItemHeight = 40;
- this.ClearConnectors();
- var port1 = new FullyCreatedConnectorInfo(root, this, ConnectorOrientation.None, true) { XRatio = 0, YRatio = 1 };
- this.AddConnector(port1);
- var port2 = new FullyCreatedConnectorInfo(root, this, ConnectorOrientation.None, true) { XRatio = 1, YRatio = 1 };
- this.AddConnector(port2);
- IsInnerConnector = true;
- }
- public PointBase Offset
- {
- get; set;
- }
- }
}