diff --git a/AIStudio.Wpf.DiagramApp/AIStudio.Wpf.DiagramApp.csproj b/AIStudio.Wpf.DiagramApp/AIStudio.Wpf.DiagramApp.csproj
index e1a927f..a1bb605 100644
--- a/AIStudio.Wpf.DiagramApp/AIStudio.Wpf.DiagramApp.csproj
+++ b/AIStudio.Wpf.DiagramApp/AIStudio.Wpf.DiagramApp.csproj
@@ -231,9 +231,6 @@
-
- PreserveNewest
-
PreserveNewest
@@ -877,6 +874,10 @@
PreserveNewest
+
+
+
+
8.0
diff --git a/AIStudio.Wpf.DiagramApp/DesignItems/Customs/1.json b/AIStudio.Wpf.DiagramApp/DesignItems/Customs/1.json
deleted file mode 100644
index 75e975d..0000000
--- a/AIStudio.Wpf.DiagramApp/DesignItems/Customs/1.json
+++ /dev/null
@@ -1,102 +0,0 @@
-{
- "Title": null,
- "DiagramType": 0,
- "DiagramItems": [
- {
- "Name": null,
- "DiagramType": 0,
- "DesignerItems": [
- ],
- "PersistDesignerItems": [
- ],
- "SettingsDesignerItems": [
- ],
- "PathDesignerItems": [
- {
- "Left": 132.80000000000007,
- "Top": 101.26000022888184,
- "ScaleX": 1,
- "ScaleY": 1,
- "Margin": 0.0,
- "ItemWidth": 65.0,
- "ItemHeight": 65.0,
- "Icon": "M 0,0 H 60 V 40 C 30,30 30,50 0,40 Z",
- "ItemTypeName": "AIStudio.Wpf.DiagramDesigner.Additionals.Extensions.ViewModels.PathItemViewModel",
- "Id": "da395032-ad9e-4dab-a035-f59bed5cb4c4",
- "ZIndex": 0,
- "IsGroup": false,
- "ParentId": "00000000-0000-0000-0000-000000000000",
- "Text": "欢迎来到AIStudio画板",
- "ColorItem": {
- "LineColor": {
- "BrushType": 1,
- "Color": "#FF808080",
- "GradientStop": null,
- "Offset": null,
- "Image": null,
- "SubType": 0,
- "StartPoint": "0,0",
- "EndPoint": "0,0",
- "Opacity": 1.0,
- "LinearOrientation": 0,
- "RadialOrientation": 0,
- "Angle": 0
- },
- "FillColor": {
- "BrushType": 1,
- "Color": "#FFFFA500",
- "GradientStop": null,
- "Offset": null,
- "Image": null,
- "SubType": 0,
- "StartPoint": "0,0",
- "EndPoint": "0,0",
- "Opacity": 1.0,
- "LinearOrientation": 0,
- "RadialOrientation": 0,
- "Angle": 0
- },
- "ShadowColor": "#00FFFFFF",
- "LineWidth": 1.0,
- "LeftArrowPathStyle": 0,
- "RightArrowPathStyle": 1,
- "LeftArrowSizeStyle": 10,
- "RightArrowSizeStyle": 10
- },
- "FontItem": {
- "FontWeight": "Normal",
- "FontStyle": "Normal",
- "FontStretch": "Normal",
- "Underline": false,
- "Strikethrough": false,
- "OverLine": false,
- "FontColor": "#FF000000",
- "FontFamily": "Arial",
- "FontSize": 11.0,
- "FontObject": "Arial, 11pt",
- "TextEffectColor": "#00FFFFFF",
- "HighlightColor": "#00FFFFFF",
- "FontCase": 0,
- "HorizontalAlignment": 1,
- "VerticalAlignment": 1,
- "LineHeight": 0.0
- }
- }
- ],
- "MediaDesignerItems": [
- ],
- "ImageDesignerItems": [
- ],
- "TextDesignerItems": [
- ],
- "LogicalGateItems": [
- ],
- "FlowNodeDesignerItems": [
- ],
- "ConnectionIds": [
- ],
- "Connections": [
- ]
- }
- ]
-}
\ No newline at end of file
diff --git a/AIStudio.Wpf.DiagramApp/ViewModels/DiagramsViewModel.cs b/AIStudio.Wpf.DiagramApp/ViewModels/DiagramsViewModel.cs
index d46b6e5..705fd32 100644
--- a/AIStudio.Wpf.DiagramApp/ViewModels/DiagramsViewModel.cs
+++ b/AIStudio.Wpf.DiagramApp/ViewModels/DiagramsViewModel.cs
@@ -436,6 +436,17 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
}
}
+ public void SetSharp(IShapeViewModel shapeViewModel, string propertyName)
+ {
+ foreach (var item in DiagramViewModel.SelectedItems)
+ {
+ if (item.ShapeViewModel != shapeViewModel)
+ {
+ CopyHelper.CopyPropertyValue(shapeViewModel, item.ShapeViewModel, propertyName);
+ }
+ }
+ }
+
public void SetQuickItem(IQuickThemeViewModel quickThemeViewModel, string propertyName)
{
if (propertyName == nameof(QuickTheme) && quickThemeViewModel.QuickTheme != null)
diff --git a/AIStudio.Wpf.DiagramApp/ViewModels/MainWindowViewModel.cs b/AIStudio.Wpf.DiagramApp/ViewModels/MainWindowViewModel.cs
index 2ce1657..5038ee2 100644
--- a/AIStudio.Wpf.DiagramApp/ViewModels/MainWindowViewModel.cs
+++ b/AIStudio.Wpf.DiagramApp/ViewModels/MainWindowViewModel.cs
@@ -140,6 +140,13 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
return _service.ColorViewModel;
}
}
+ public IShapeViewModel ShapeViewModel
+ {
+ get
+ {
+ return _service.ShapeViewModel;
+ }
+ }
public IQuickThemeViewModel QuickThemeViewModel
{
get
@@ -677,6 +684,7 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
if (e.PropertyName == nameof(DrawModeViewModel)
|| e.PropertyName == nameof(FontViewModel)
|| e.PropertyName == nameof(ColorViewModel)
+ || e.PropertyName == nameof(ShapeViewModel)
|| e.PropertyName == nameof(QuickThemeViewModel)
|| e.PropertyName == nameof(LockObjectViewModel)
|| e.PropertyName == nameof(SelectedItem))
@@ -692,6 +700,9 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
if (sender is IColorViewModel)
DiagramsViewModel.SetColor(sender as IColorViewModel, e.PropertyName);
+ if (sender is IShapeViewModel)
+ DiagramsViewModel.SetSharp(sender as IShapeViewModel, e.PropertyName);
+
if (sender is IQuickThemeViewModel)
DiagramsViewModel.SetQuickItem(sender as IQuickThemeViewModel, e.PropertyName);
diff --git a/AIStudio.Wpf.DiagramApp/Views/MainWindow.xaml b/AIStudio.Wpf.DiagramApp/Views/MainWindow.xaml
index 4305720..f3827c3 100644
--- a/AIStudio.Wpf.DiagramApp/Views/MainWindow.xaml
+++ b/AIStudio.Wpf.DiagramApp/Views/MainWindow.xaml
@@ -1141,7 +1141,7 @@
-
+
@@ -1167,8 +1167,8 @@
-
-
+
+
@@ -1205,14 +1205,14 @@
-
+
-
+
diff --git a/AIStudio.Wpf.DiagramDesigner.Demo/AIStudio.Wpf.DiagramDesigner.Demo.csproj b/AIStudio.Wpf.DiagramDesigner.Demo/AIStudio.Wpf.DiagramDesigner.Demo.csproj
index 0144991..ade4264 100644
--- a/AIStudio.Wpf.DiagramDesigner.Demo/AIStudio.Wpf.DiagramDesigner.Demo.csproj
+++ b/AIStudio.Wpf.DiagramDesigner.Demo/AIStudio.Wpf.DiagramDesigner.Demo.csproj
@@ -11,7 +11,7 @@
-
+
diff --git a/AIStudio.Wpf.DiagramDesigner.Demo/ViewModels/Links/LabelsViewModel.cs b/AIStudio.Wpf.DiagramDesigner.Demo/ViewModels/Links/LabelsViewModel.cs
new file mode 100644
index 0000000..9dead39
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner.Demo/ViewModels/Links/LabelsViewModel.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows;
+
+namespace AIStudio.Wpf.DiagramDesigner.Demo.ViewModels
+{
+ class LabelsViewModel : BaseViewModel
+ {
+ public LabelsViewModel()
+ {
+ Title = "Link Labels";
+ Info = "Labels help you show more information through out a link. You can specify a distance or an offset." +
+ "The content of the labels is still limited because of Blazor's poor SVG support.";
+
+ _service.ColorViewModel.FillColor.Color = System.Windows.Media.Colors.Orange;
+
+ DiagramViewModel = new DiagramViewModel();
+ DiagramViewModel.PageSizeType = PageSizeType.Custom;
+ DiagramViewModel.PageSize = new Size(double.NaN, double.NaN);
+
+ DefaultDesignerItemViewModel node1 = new DefaultDesignerItemViewModel() { Left = 50, Top = 50 };
+ DiagramViewModel.DirectAddItemCommand.Execute(node1);
+
+ DefaultDesignerItemViewModel node2 = new DefaultDesignerItemViewModel() { Left = 400, Top = 50 };
+ DiagramViewModel.DirectAddItemCommand.Execute(node2);
+
+ ConnectionViewModel connector1 = new ConnectionViewModel(node1.RightConnector, node2.LeftConnector);
+ connector1.AddLabel("Content");
+ DiagramViewModel.DirectAddItemCommand.Execute(connector1);
+
+ node1 = new DefaultDesignerItemViewModel() { Left = 50, Top = 160, Text = "1" };
+ DiagramViewModel.DirectAddItemCommand.Execute(node1);
+
+ node2 = new DefaultDesignerItemViewModel() { Left = 400, Top = 160, Text = "2" };
+ DiagramViewModel.DirectAddItemCommand.Execute(node2);
+
+ connector1 = new ConnectionViewModel(node1.RightConnector, node2.LeftConnector);
+ connector1.AddLabel("0.25", 0.3);
+ connector1.AddLabel("0.75", 0.7);
+ DiagramViewModel.DirectAddItemCommand.Execute(connector1);
+
+ node1 = new DefaultDesignerItemViewModel() { Left = 50, Top = 270, Text = "1" };
+ DiagramViewModel.DirectAddItemCommand.Execute(node1);
+
+ node2 = new DefaultDesignerItemViewModel() { Left = 400, Top = 270, Text = "2" };
+ DiagramViewModel.DirectAddItemCommand.Execute(node2);
+
+ connector1 = new ConnectionViewModel(node1.RightConnector, node2.LeftConnector);
+ connector1.AddLabel("50", 50);
+ connector1.AddLabel("-50", -50);
+ DiagramViewModel.DirectAddItemCommand.Execute(connector1);
+
+ node1 = new DefaultDesignerItemViewModel() { Left = 50, Top = 380, Text = "1" };
+ DiagramViewModel.DirectAddItemCommand.Execute(node1);
+
+ node2 = new DefaultDesignerItemViewModel() { Left = 400, Top = 380, Text = "2" };
+ DiagramViewModel.DirectAddItemCommand.Execute(node2);
+
+ connector1 = new ConnectionViewModel(node1.RightConnector, node2.LeftConnector);
+ connector1.AddLabel("(0,-20)", 50, new Point(0, -20));
+ connector1.AddLabel("(0,20)", -50, new Point(0, 20));
+ DiagramViewModel.DirectAddItemCommand.Execute(connector1);
+ }
+ }
+}
diff --git a/AIStudio.Wpf.DiagramDesigner.Demo/ViewModels/Links/MarkersViewModel.cs b/AIStudio.Wpf.DiagramDesigner.Demo/ViewModels/Links/MarkersViewModel.cs
new file mode 100644
index 0000000..df7e37a
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner.Demo/ViewModels/Links/MarkersViewModel.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows;
+
+namespace AIStudio.Wpf.DiagramDesigner.Demo.ViewModels
+{
+ class MarkersViewModel : BaseViewModel
+ {
+ public MarkersViewModel()
+ {
+ Title = "Link Markers";
+ Info = "Markers are SVG Paths that you can put at the beginning or at the end of your links.";
+
+ _service.ColorViewModel.FillColor.Color = System.Windows.Media.Colors.Orange;
+
+ DiagramViewModel = new DiagramViewModel();
+ DiagramViewModel.PageSizeType = PageSizeType.Custom;
+ DiagramViewModel.PageSize = new Size(double.NaN, double.NaN);
+
+ DefaultDesignerItemViewModel node1 = new DefaultDesignerItemViewModel() { Left = 50, Top = 50, Text = "1" };
+ DiagramViewModel.DirectAddItemCommand.Execute(node1);
+
+ DefaultDesignerItemViewModel node2 = new DefaultDesignerItemViewModel() { Left = 400, Top = 50, Text = "2" };
+ DiagramViewModel.DirectAddItemCommand.Execute(node2);
+
+ ConnectionViewModel connector1 = new ConnectionViewModel(node1.RightConnector, node2.LeftConnector);
+ connector1.ShapeViewModel.SourceMarker = LinkMarker.Arrow;
+ connector1.ShapeViewModel.SinkMarker = LinkMarker.Arrow;
+ connector1.AddLabel("Arrow");
+ DiagramViewModel.DirectAddItemCommand.Execute(connector1);
+
+ node1 = new DefaultDesignerItemViewModel() { Left = 50, Top = 160, Text = "1" };
+ DiagramViewModel.DirectAddItemCommand.Execute(node1);
+
+ node2 = new DefaultDesignerItemViewModel() { Left = 400, Top = 160, Text = "2" };
+ DiagramViewModel.DirectAddItemCommand.Execute(node2);
+
+ connector1 = new ConnectionViewModel(node1.RightConnector, node2.LeftConnector);
+ connector1.ShapeViewModel.SourceMarker = LinkMarker.Circle;
+ connector1.ShapeViewModel.SinkMarker = LinkMarker.Circle;
+ connector1.AddLabel("Circle");
+ DiagramViewModel.DirectAddItemCommand.Execute(connector1);
+
+ node1 = new DefaultDesignerItemViewModel() { Left = 50, Top = 270, Text = "1" };
+ DiagramViewModel.DirectAddItemCommand.Execute(node1);
+
+ node2 = new DefaultDesignerItemViewModel() { Left = 400, Top = 270, Text = "2" };
+ DiagramViewModel.DirectAddItemCommand.Execute(node2);
+
+ connector1 = new ConnectionViewModel(node1.RightConnector, node2.LeftConnector);
+ connector1.ShapeViewModel.SourceMarker = LinkMarker.Square;
+ connector1.ShapeViewModel.SinkMarker = LinkMarker.Square;
+ connector1.AddLabel("Square");
+ DiagramViewModel.DirectAddItemCommand.Execute(connector1);
+
+ }
+ }
+}
diff --git a/AIStudio.Wpf.DiagramDesigner.Demo/ViewModels/ReconnectLinksToClosestPortsViewModel.cs b/AIStudio.Wpf.DiagramDesigner.Demo/ViewModels/ReconnectLinksToClosestPortsViewModel.cs
new file mode 100644
index 0000000..ffffc8d
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner.Demo/ViewModels/ReconnectLinksToClosestPortsViewModel.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows;
+using AIStudio.Wpf.DiagramDesigner.Algorithms;
+
+namespace AIStudio.Wpf.DiagramDesigner.Demo.ViewModels
+{
+ class ReconnectLinksToClosestPortsViewModel : BaseViewModel
+ {
+ public ReconnectLinksToClosestPortsViewModel()
+ {
+ Title = "Reconnect links";
+ Info = "An example of reconnecting links to the closest ports.";
+
+ _service.ColorViewModel.FillColor.Color = System.Windows.Media.Colors.Orange;
+
+ DiagramViewModel = new DiagramViewModel();
+ DiagramViewModel.PageSizeType = PageSizeType.Custom;
+ DiagramViewModel.PageSize = new Size(double.NaN, double.NaN);
+
+ DefaultDesignerItemViewModel node1 = new DefaultDesignerItemViewModel() { Left = 50, Top = 50, Text = "1" };
+ DiagramViewModel.DirectAddItemCommand.Execute(node1);
+
+ DefaultDesignerItemViewModel node2 = new DefaultDesignerItemViewModel() { Left = 300, Top = 300, Text = "2" };
+ DiagramViewModel.DirectAddItemCommand.Execute(node2);
+
+ DefaultDesignerItemViewModel node3 = new DefaultDesignerItemViewModel() { Left = 300, Top = 50, Text = "3" };
+ DiagramViewModel.DirectAddItemCommand.Execute(node3);
+
+ ConnectionViewModel connector1 = new ConnectionViewModel(node1.RightConnector, node2.LeftConnector, DrawMode.ConnectingLineSmooth, RouterMode.RouterNormal);
+ DiagramViewModel.DirectAddItemCommand.Execute(connector1);
+
+ ConnectionViewModel connector2 = new ConnectionViewModel(node2.RightConnector, node3.RightConnector, DrawMode.ConnectingLineStraight, RouterMode.RouterOrthogonal);
+ DiagramViewModel.DirectAddItemCommand.Execute(connector2);
+
+ ReconnectLinksCommand = new SimpleCommand(ReconnectLinks);
+ }
+
+ public SimpleCommand ReconnectLinksCommand
+ {
+ get; private set;
+ }
+
+ protected void ReconnectLinks(object para) => DiagramViewModel.ReconnectLinksToClosestPorts();
+ }
+}
diff --git a/AIStudio.Wpf.DiagramDesigner.Demo/ViewModels/ZoomViewModel.cs b/AIStudio.Wpf.DiagramDesigner.Demo/ViewModels/ZoomViewModel.cs
new file mode 100644
index 0000000..d5854bb
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner.Demo/ViewModels/ZoomViewModel.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows;
+
+namespace AIStudio.Wpf.DiagramDesigner.Demo.ViewModels
+{
+ class ZoomViewModel : BaseViewModel
+ {
+ public ZoomViewModel()
+ {
+ Title = "Zoom";
+ Info = "Drag the upper-right scroll bar to make the canvas larger and smaller.";
+
+ _service.ColorViewModel.FillColor.Color = System.Windows.Media.Colors.Orange;
+
+ DiagramViewModel = new DiagramViewModel();
+ DiagramViewModel.PageSizeType = PageSizeType.Custom;
+ DiagramViewModel.PageSize = new Size(double.NaN, double.NaN);
+
+ DefaultDesignerItemViewModel node1 = new DefaultDesignerItemViewModel() { Left = 50, Top = 50, Text = "1" };
+ DiagramViewModel.DirectAddItemCommand.Execute(node1);
+
+ DefaultDesignerItemViewModel node2 = new DefaultDesignerItemViewModel() { Left = 300, Top = 300, Text = "2" };
+ DiagramViewModel.DirectAddItemCommand.Execute(node2);
+
+ DefaultDesignerItemViewModel node3 = new DefaultDesignerItemViewModel() { Left = 300, Top = 50, Text = "3" };
+ DiagramViewModel.DirectAddItemCommand.Execute(node3);
+
+ ConnectionViewModel connector1 = new ConnectionViewModel(node1.RightConnector, node2.LeftConnector, DrawMode.ConnectingLineSmooth, RouterMode.RouterNormal);
+ DiagramViewModel.DirectAddItemCommand.Execute(connector1);
+
+ ConnectionViewModel connector2 = new ConnectionViewModel(node2.RightConnector, node3.RightConnector, DrawMode.ConnectingLineStraight, RouterMode.RouterOrthogonal);
+ DiagramViewModel.DirectAddItemCommand.Execute(connector2);
+
+ }
+ }
+}
diff --git a/AIStudio.Wpf.DiagramDesigner.Demo/Views/Animations/ReconnectLinksToClosestPortsView.xaml b/AIStudio.Wpf.DiagramDesigner.Demo/Views/Animations/ReconnectLinksToClosestPortsView.xaml
new file mode 100644
index 0000000..fb0fbdb
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner.Demo/Views/Animations/ReconnectLinksToClosestPortsView.xaml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
diff --git a/AIStudio.Wpf.DiagramDesigner.Demo/Views/Animations/ReconnectLinksToClosestPortsView.xaml.cs b/AIStudio.Wpf.DiagramDesigner.Demo/Views/Animations/ReconnectLinksToClosestPortsView.xaml.cs
new file mode 100644
index 0000000..e702b48
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner.Demo/Views/Animations/ReconnectLinksToClosestPortsView.xaml.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+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 AIStudio.Wpf.DiagramDesigner.Demo.Views
+{
+ ///
+ /// ReconnectLinksToClosestPortsView.xaml 的交互逻辑
+ ///
+ public partial class ReconnectLinksToClosestPortsView : UserControl
+ {
+ public ReconnectLinksToClosestPortsView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/AIStudio.Wpf.DiagramDesigner.Demo/Views/Links/LabelsView.xaml b/AIStudio.Wpf.DiagramDesigner.Demo/Views/Links/LabelsView.xaml
new file mode 100644
index 0000000..e12ee71
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner.Demo/Views/Links/LabelsView.xaml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
diff --git a/AIStudio.Wpf.DiagramDesigner.Demo/Views/Links/LabelsView.xaml.cs b/AIStudio.Wpf.DiagramDesigner.Demo/Views/Links/LabelsView.xaml.cs
new file mode 100644
index 0000000..3ff0493
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner.Demo/Views/Links/LabelsView.xaml.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+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 AIStudio.Wpf.DiagramDesigner.Demo.Views
+{
+ ///
+ /// LabelsView.xaml 的交互逻辑
+ ///
+ public partial class LabelsView : UserControl
+ {
+ public LabelsView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/AIStudio.Wpf.DiagramDesigner.Demo/Views/Links/MarkersView.xaml b/AIStudio.Wpf.DiagramDesigner.Demo/Views/Links/MarkersView.xaml
new file mode 100644
index 0000000..6c7a1c9
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner.Demo/Views/Links/MarkersView.xaml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
diff --git a/AIStudio.Wpf.DiagramDesigner.Demo/Views/Links/MarkersView.xaml.cs b/AIStudio.Wpf.DiagramDesigner.Demo/Views/Links/MarkersView.xaml.cs
new file mode 100644
index 0000000..da3ac7c
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner.Demo/Views/Links/MarkersView.xaml.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+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 AIStudio.Wpf.DiagramDesigner.Demo.Views
+{
+ ///
+ /// MarkersView.xaml 的交互逻辑
+ ///
+ public partial class MarkersView : UserControl
+ {
+ public MarkersView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/AIStudio.Wpf.DiagramDesigner.Demo/Views/ZoomView.xaml b/AIStudio.Wpf.DiagramDesigner.Demo/Views/ZoomView.xaml
new file mode 100644
index 0000000..5eb9bb3
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner.Demo/Views/ZoomView.xaml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/AIStudio.Wpf.DiagramDesigner.Demo/Views/ZoomView.xaml.cs b/AIStudio.Wpf.DiagramDesigner.Demo/Views/ZoomView.xaml.cs
new file mode 100644
index 0000000..c7b99ca
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner.Demo/Views/ZoomView.xaml.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+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 AIStudio.Wpf.DiagramDesigner.Demo.Views
+{
+ ///
+ /// ZoomView.xaml 的交互逻辑
+ ///
+ public partial class ZoomView : UserControl
+ {
+ public ZoomView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/AIStudio.Wpf.DiagramDesigner/Algorithms/LinksReconnectionAlgorithms.cs b/AIStudio.Wpf.DiagramDesigner/Algorithms/LinksReconnectionAlgorithms.cs
new file mode 100644
index 0000000..972cab1
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner/Algorithms/LinksReconnectionAlgorithms.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace AIStudio.Wpf.DiagramDesigner.Algorithms
+{
+ public static class LinksReconnectionAlgorithms
+ {
+ public static void ReconnectLinksToClosestPorts(this IDiagramViewModel diagram)
+ {
+ // Only refresh ports once
+ //var portsToRefresh = new HashSet();
+
+ foreach (var link in diagram.Items.OfType())
+ {
+ if (link.IsFullConnection == false)
+ continue;
+
+ var sourcePorts = link.SourceConnectorInfo.DataItem.Connectors;
+ var targetPorts = link.SinkConnectorInfoFully.DataItem.Connectors;
+
+ // Find the ports with minimal distance
+ var minDistance = double.MaxValue;
+ var minSourcePort = link.SourceConnectorInfo;
+ var minTargetPort = link.SinkConnectorInfoFully;
+ foreach (var sourcePort in sourcePorts)
+ {
+ foreach (var targetPort in targetPorts)
+ {
+ var distance = sourcePort.Position.DistanceTo(targetPort.Position);
+ if (distance < minDistance)
+ {
+ minDistance = distance;
+ minSourcePort = sourcePort;
+ minTargetPort = targetPort;
+ }
+ }
+ }
+
+ // Reconnect
+ if (link.SourceConnectorInfo != minSourcePort)
+ {
+ //portsToRefresh.Add(link.SourceConnectorInfo);
+ //portsToRefresh.Add(minSourcePort);
+ link.SetSourcePort(minSourcePort);
+ }
+
+ if (link.SinkConnectorInfo != minTargetPort)
+ {
+ //portsToRefresh.Add(link.SinkConnectorInfoFully);
+ //portsToRefresh.Add(minTargetPort);
+ link.SetSinkPort(minTargetPort);
+ }
+ }
+
+ //foreach (var port in portsToRefresh)
+ // port.Refresh();
+ }
+ }
+}
diff --git a/AIStudio.Wpf.DiagramDesigner/Enums/ArrowPathStyle.cs b/AIStudio.Wpf.DiagramDesigner/Enums/ArrowPathStyle.cs
index ace6f8f..338056f 100644
--- a/AIStudio.Wpf.DiagramDesigner/Enums/ArrowPathStyle.cs
+++ b/AIStudio.Wpf.DiagramDesigner/Enums/ArrowPathStyle.cs
@@ -9,7 +9,6 @@ namespace AIStudio.Wpf.DiagramDesigner
None,
Arrow,
Circle,
- Square,
-
+ Square,
}
}
diff --git a/AIStudio.Wpf.DiagramDesigner/Helpers/CopyHelper.cs b/AIStudio.Wpf.DiagramDesigner/Helpers/CopyHelper.cs
index d99f67c..5cd1b0c 100644
--- a/AIStudio.Wpf.DiagramDesigner/Helpers/CopyHelper.cs
+++ b/AIStudio.Wpf.DiagramDesigner/Helpers/CopyHelper.cs
@@ -160,6 +160,22 @@ namespace AIStudio.Wpf.DiagramDesigner
return d;
}
+ public static ShapeViewModel Mapper(IShapeViewModel s)
+ {
+ var d = CopyHelper.Mapper(s);
+ d.SourceMarker = CopyHelper.Mapper(s.SourceMarker);
+ d.SinkMarker = CopyHelper.Mapper(s.SinkMarker);
+ return d;
+ }
+
+ public static T Mapper(IShapeViewModel s) where T : IShapeViewModel
+ {
+ var d = CopyHelper.Mapper(s);
+ d.SourceMarker = CopyHelper.Mapper(s.SourceMarker);
+ d.SinkMarker = CopyHelper.Mapper(s.SinkMarker);
+ return d;
+ }
+
public static void CopyPropertyValue(IColorViewModel s, IColorViewModel d, string propertyName = null)
{
if (propertyName == "LineColor")
diff --git a/AIStudio.Wpf.DiagramDesigner/Models/Serializables/SelectableItemBase.cs b/AIStudio.Wpf.DiagramDesigner/Models/Serializables/SelectableItemBase.cs
index 36bcf65..18afd9c 100644
--- a/AIStudio.Wpf.DiagramDesigner/Models/Serializables/SelectableItemBase.cs
+++ b/AIStudio.Wpf.DiagramDesigner/Models/Serializables/SelectableItemBase.cs
@@ -34,6 +34,7 @@ namespace AIStudio.Wpf.DiagramDesigner
ColorItem = CopyHelper.Mapper(viewmodel.ColorViewModel);
FontItem = CopyHelper.Mapper(viewmodel.FontViewModel);
+ SharpItem = CopyHelper.Mapper(viewmodel.ShapeViewModel);
}
[XmlAttribute]
@@ -76,9 +77,16 @@ namespace AIStudio.Wpf.DiagramDesigner
public FontItem FontItem
{
get; set;
- }
+ }
+
+ [XmlElement]
+ public SharpItem SharpItem
+ {
+ get; set;
+ }
}
+ [XmlInclude(typeof(ColorItem))]
public class ColorItem : IColorViewModel
{
[XmlIgnore]
@@ -149,46 +157,54 @@ namespace AIStudio.Wpf.DiagramDesigner
}
[XmlAttribute]
- public ArrowPathStyle LeftArrowPathStyle
+ public LineDashStyle LineDashStyle
{
get; set;
}
- [XmlAttribute]
- public ArrowPathStyle RightArrowPathStyle
- {
- get; set;
- }
+ public event PropertyChangedEventHandler PropertyChanged;
+ }
- [XmlAttribute]
- public ArrowSizeStyle LeftArrowSizeStyle
- {
- get; set;
- }
-
- [XmlAttribute]
- public ArrowSizeStyle RightArrowSizeStyle
+ [XmlInclude(typeof(SharpItem))]
+ public class SharpItem : IShapeViewModel
+ {
+ [XmlIgnore]
+ public ILinkMarker SourceMarker
{
get; set;
}
[JsonIgnore]
- [XmlIgnore]
- public double LeftArrowSize
+ [XmlElement("SourceMarker")]
+ public LinkMarkerItem XmlSourceMarker
{
get
{
- throw new NotImplementedException();
+ return SourceMarker as LinkMarkerItem;
+ }
+ set
+ {
+ SourceMarker = value;
}
}
- [JsonIgnore]
[XmlIgnore]
- public double RightArrowSize
+ public ILinkMarker SinkMarker
+ {
+ get; set;
+ }
+
+ [JsonIgnore]
+ [XmlElement("SinkMarker")]
+ public LinkMarkerItem XmlSinkMarker
{
get
{
- throw new NotImplementedException();
+ return SinkMarker as LinkMarkerItem;
+ }
+ set
+ {
+ SinkMarker = value;
}
}
@@ -734,4 +750,30 @@ namespace AIStudio.Wpf.DiagramDesigner
}
+ public class LinkMarkerItem : ILinkMarker
+ {
+ [XmlAttribute]
+ public string Path
+ {
+ get; set;
+ }
+
+ [XmlAttribute]
+ public double Width
+ {
+ get; set;
+ }
+
+ [XmlAttribute]
+ public ArrowPathStyle PathStyle
+ {
+ get; set;
+ }
+
+ public ArrowSizeStyle SizeStyle
+ {
+ get; set;
+ }
+ }
+
}
diff --git a/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.Boundary.cs b/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.Boundary.cs
index 853fc5b..c50741d 100644
--- a/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.Boundary.cs
+++ b/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.Boundary.cs
@@ -16,8 +16,8 @@ namespace AIStudio.Wpf.DiagramDesigner
route = GetRouteWithMiddlePoints(_, link, route);
- double sourceAngle = SourceMarkerAdjustement(route, link.ColorViewModel.LeftArrowSize);
- double targetAngle = TargetMarkerAdjustement(route, link.ColorViewModel.RightArrowSize);
+ double sourceAngle = SourceMarkerAdjustement(route, link.GetSourceMarkerWidth());
+ double targetAngle = TargetMarkerAdjustement(route, link.GetSinkMarkerWidth());
DoShift(route, link);
diff --git a/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.Corner.cs b/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.Corner.cs
index c7bb742..01f6b00 100644
--- a/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.Corner.cs
+++ b/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.Corner.cs
@@ -19,8 +19,8 @@ namespace AIStudio.Wpf.DiagramDesigner
else
route = GetRouteWithPartConnectionLine(_, link, route);
- double sourceAngle = SourceMarkerAdjustement(route, link.ColorViewModel.LeftArrowSize);
- double targetAngle = TargetMarkerAdjustement(route, link.ColorViewModel.RightArrowSize);
+ double sourceAngle = SourceMarkerAdjustement(route, link.GetSourceMarkerWidth());
+ double targetAngle = TargetMarkerAdjustement(route, link.GetSinkMarkerWidth());
DoShift(route, link);
diff --git a/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.Smooth.cs b/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.Smooth.cs
index 2cee246..cd389d3 100644
--- a/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.Smooth.cs
+++ b/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.Smooth.cs
@@ -17,8 +17,8 @@ namespace AIStudio.Wpf.DiagramDesigner
route = GetRouteWithCurvePoints(link, route);
- double sourceAngle = SourceMarkerAdjustement(route, link.ColorViewModel.LeftArrowSize);
- double targetAngle = TargetMarkerAdjustement(route, link.ColorViewModel.RightArrowSize);
+ double sourceAngle = SourceMarkerAdjustement(route, link.GetSourceMarkerWidth());
+ double targetAngle = TargetMarkerAdjustement(route, link.GetSinkMarkerWidth());
DoShift(route, link);
@@ -28,8 +28,8 @@ namespace AIStudio.Wpf.DiagramDesigner
private static PathGeneratorResult CurveThroughPoints(PointBase[] route, ConnectionViewModel link)
{
- double sourceAngle = SourceMarkerAdjustement(route, link.ColorViewModel.LeftArrowSize);
- double targetAngle = TargetMarkerAdjustement(route, link.ColorViewModel.RightArrowSize);
+ double sourceAngle = SourceMarkerAdjustement(route, link.GetSourceMarkerWidth());
+ double targetAngle = TargetMarkerAdjustement(route, link.GetSinkMarkerWidth());
BezierSpline.GetCurveControlPoints(route, out var firstControlPoints, out var secondControlPoints);
diff --git a/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.Straight.cs b/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.Straight.cs
index 6b10cb4..7f70428 100644
--- a/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.Straight.cs
+++ b/AIStudio.Wpf.DiagramDesigner/PathGenerators/PathGenerators.Straight.cs
@@ -9,8 +9,8 @@ namespace AIStudio.Wpf.DiagramDesigner
{
route = ConcatRouteAndSourceAndTarget(route, source, target);
- double sourceAngle = SourceMarkerAdjustement(route, link.ColorViewModel.LeftArrowSize);
- double targetAngle = TargetMarkerAdjustement(route, link.ColorViewModel.RightArrowSize);
+ double sourceAngle = SourceMarkerAdjustement(route, link.GetSourceMarkerWidth());
+ double targetAngle = TargetMarkerAdjustement(route, link.GetSinkMarkerWidth());
DoShift(route, link);
diff --git a/AIStudio.Wpf.DiagramDesigner/UserControls/LineControl.xaml b/AIStudio.Wpf.DiagramDesigner/UserControls/LineControl.xaml
index 913e28a..b8d39a5 100644
--- a/AIStudio.Wpf.DiagramDesigner/UserControls/LineControl.xaml
+++ b/AIStudio.Wpf.DiagramDesigner/UserControls/LineControl.xaml
@@ -44,10 +44,10 @@
- /// Simple service interface
- ///
- public interface IDiagramServiceProvider : INotifyPropertyChanged
- {
- IColorViewModel ColorViewModel { get; }
- IFontViewModel FontViewModel { get; }
- IDrawModeViewModel DrawModeViewModel { get; }
- IQuickThemeViewModel QuickThemeViewModel { get; }
- ILockObjectViewModel LockObjectViewModel { get; }
- SelectableDesignerItemViewModelBase SelectedItem { get; set; }
- IColorViewModel CopyDefaultColorViewModel();
- IFontViewModel CopyDefaultFontViewModel();
- }
-
-
///
/// Simple service locator
///
@@ -28,7 +12,9 @@ namespace AIStudio.Wpf.DiagramDesigner
{
ColorViewModel = new ColorViewModel();
FontViewModel = new FontViewModel();
+ ShapeViewModel = new ShapeViewModel();
LockObjectViewModel = new LockObjectViewModel();
+
_drawModeViewModel = new DrawModeViewModel();
_quickThemeViewModel = new QuickThemeViewModel();
@@ -37,6 +23,7 @@ namespace AIStudio.Wpf.DiagramDesigner
SetOldValue(ColorViewModel, nameof(ColorViewModel));
SetOldValue(FontViewModel, nameof(FontViewModel));
+ SetOldValue(ShapeViewModel, nameof(ShapeViewModel));
SetOldValue(LockObjectViewModel, nameof(LockObjectViewModel));
}
@@ -57,6 +44,12 @@ namespace AIStudio.Wpf.DiagramDesigner
return CopyHelper.Mapper(viewModel);
}
+ public IShapeViewModel CopyDefaultShapeViewModel()
+ {
+ var viewModel = GetOldValue(nameof(ShapeViewModel));
+ return CopyHelper.Mapper(viewModel);
+ }
+
private IColorViewModel _colorViewModel;
public IColorViewModel ColorViewModel
{
@@ -76,7 +69,7 @@ namespace AIStudio.Wpf.DiagramDesigner
_colorViewModel.PropertyChanged += ViewModel_PropertyChanged;
}
}
- }
+ }
private IFontViewModel _fontViewModel;
public IFontViewModel FontViewModel
@@ -99,6 +92,27 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
+ private IShapeViewModel _linkMarkerViewModel;
+ public IShapeViewModel ShapeViewModel
+ {
+ get
+ {
+ return _linkMarkerViewModel;
+ }
+ set
+ {
+ if (_linkMarkerViewModel != null)
+ {
+ _linkMarkerViewModel.PropertyChanged -= ViewModel_PropertyChanged;
+ }
+ SetProperty(ref _linkMarkerViewModel, value);
+ if (_linkMarkerViewModel != null)
+ {
+ _linkMarkerViewModel.PropertyChanged += ViewModel_PropertyChanged;
+ }
+ }
+ }
+
private DrawModeViewModel _drawModeViewModel;
public IDrawModeViewModel DrawModeViewModel
{
@@ -151,12 +165,14 @@ namespace AIStudio.Wpf.DiagramDesigner
{
ColorViewModel = GetOldValue(nameof(ColorViewModel));
FontViewModel = GetOldValue(nameof(FontViewModel));
+ ShapeViewModel = GetOldValue(nameof(ShapeViewModel));
LockObjectViewModel = GetOldValue(nameof(LockObjectViewModel));
}
else
{
ColorViewModel = _selectedItem.ColorViewModel;
FontViewModel = _selectedItem.FontViewModel;
+ ShapeViewModel = _selectedItem.ShapeViewModel;
LockObjectViewModel = _selectedItem.LockObjectViewModel;
}
}
@@ -168,8 +184,6 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
-
-
///
/// Simple service locator helper
///
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/IColorViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/Interface/IColorViewModel.cs
similarity index 60%
rename from AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/IColorViewModel.cs
rename to AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/Interface/IColorViewModel.cs
index b83645c..5404069 100644
--- a/AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/IColorViewModel.cs
+++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/Interface/IColorViewModel.cs
@@ -25,33 +25,10 @@ namespace AIStudio.Wpf.DiagramDesigner
{
get; set;
}
- ArrowPathStyle LeftArrowPathStyle
+ LineDashStyle LineDashStyle
{
get; set;
}
- ArrowPathStyle RightArrowPathStyle
- {
- get; set;
- }
- ArrowSizeStyle LeftArrowSizeStyle
- {
- get; set;
- }
- ArrowSizeStyle RightArrowSizeStyle
- {
- get; set;
- }
-
- double LeftArrowSize
- {
- get;
- }
-
- double RightArrowSize
- {
- get;
- }
-
event PropertyChangedEventHandler PropertyChanged;
}
}
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/Interface/IDiagramServiceProvider.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/Interface/IDiagramServiceProvider.cs
new file mode 100644
index 0000000..6e363f9
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/Interface/IDiagramServiceProvider.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Text;
+
+namespace AIStudio.Wpf.DiagramDesigner
+{
+ ///
+ /// Simple service interface
+ ///
+ public interface IDiagramServiceProvider : INotifyPropertyChanged
+ {
+ IColorViewModel ColorViewModel
+ {
+ get;
+ }
+ IFontViewModel FontViewModel
+ {
+ get;
+ }
+ IShapeViewModel ShapeViewModel
+ {
+ get;
+ }
+ IDrawModeViewModel DrawModeViewModel
+ {
+ get;
+ }
+ IQuickThemeViewModel QuickThemeViewModel
+ {
+ get;
+ }
+ ILockObjectViewModel LockObjectViewModel
+ {
+ get;
+ }
+ SelectableDesignerItemViewModelBase SelectedItem
+ {
+ get; set;
+ }
+ IColorViewModel CopyDefaultColorViewModel();
+ IFontViewModel CopyDefaultFontViewModel();
+ IShapeViewModel CopyDefaultShapeViewModel();
+ }
+}
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/IDrawModeViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/Interface/IDrawModeViewModel.cs
similarity index 100%
rename from AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/IDrawModeViewModel.cs
rename to AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/Interface/IDrawModeViewModel.cs
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/IFontViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/Interface/IFontViewModel.cs
similarity index 100%
rename from AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/IFontViewModel.cs
rename to AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/Interface/IFontViewModel.cs
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/ILockObjectViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/Interface/ILockObjectViewModel.cs
similarity index 100%
rename from AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/ILockObjectViewModel.cs
rename to AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/Interface/ILockObjectViewModel.cs
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/IQuickThemeViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/Interface/IQuickThemeViewModel.cs
similarity index 100%
rename from AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/IQuickThemeViewModel.cs
rename to AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/Interface/IQuickThemeViewModel.cs
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/Interface/IShapeViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/Interface/IShapeViewModel.cs
new file mode 100644
index 0000000..98a31b3
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/Interface/IShapeViewModel.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Text;
+
+namespace AIStudio.Wpf.DiagramDesigner
+{
+ public interface IShapeViewModel
+ {
+ ILinkMarker SourceMarker
+ {
+ get; set;
+ }
+
+ ILinkMarker SinkMarker
+ {
+ get; set;
+ }
+
+ event PropertyChangedEventHandler PropertyChanged;
+ }
+
+
+}
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/ShapeViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/ShapeViewModel.cs
new file mode 100644
index 0000000..0d4b227
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/AdditionViewModel/ShapeViewModel.cs
@@ -0,0 +1,201 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace AIStudio.Wpf.DiagramDesigner
+{
+ public class ShapeViewModel : BindableBase, IShapeViewModel
+ {
+ private ILinkMarker _sourceMarker = LinkMarker.None;
+ public ILinkMarker SourceMarker
+ {
+ get
+ {
+ return _sourceMarker;
+ }
+ set
+ {
+ if (_sourceMarker != value)
+ {
+ if (_sourceMarker != null && _sourceMarker is LinkMarker _linkMarker1)
+ {
+ _linkMarker1.PropertyChanged -= ShapeViewModel_PropertyChanged;
+ }
+ SetProperty(ref _sourceMarker, value);
+ if (_sourceMarker != null && _sourceMarker is LinkMarker _linkMarker2)
+ {
+ _linkMarker2.PropertyChanged += ShapeViewModel_PropertyChanged;
+ }
+ }
+ else
+ {
+ RaisePropertyChanged(nameof(SourceMarker));
+ }
+ }
+ }
+
+ private ILinkMarker _sinkMarker = LinkMarker.Arrow;
+ public ILinkMarker SinkMarker
+ {
+ get
+ {
+ return _sinkMarker;
+ }
+ set
+ {
+ if (_sinkMarker != value)
+ {
+ if (_sinkMarker != null && _sinkMarker is LinkMarker _linkMarker1)
+ {
+ _linkMarker1.PropertyChanged -= ShapeViewModel_PropertyChanged;
+ }
+ SetProperty(ref _sinkMarker, value);
+ if (_sinkMarker != null && _sinkMarker is LinkMarker _linkMarker2)
+ {
+ _linkMarker2.PropertyChanged += ShapeViewModel_PropertyChanged;
+ }
+ }
+ else
+ {
+ RaisePropertyChanged(nameof(SinkMarker));
+ }
+ }
+ }
+
+ private void ShapeViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
+ {
+ if (sender == SourceMarker)
+ {
+ RaisePropertyChanged(nameof(SourceMarker));
+ }
+ else if (sender == SinkMarker)
+ {
+ RaisePropertyChanged(nameof(SinkMarker));
+ }
+ }
+ }
+
+ public class LinkMarker : BindableBase, ILinkMarker
+ {
+ public static LinkMarker None { get; } = new LinkMarker("", 10, ArrowPathStyle.None, ArrowSizeStyle.Middle);
+ public static LinkMarker Arrow { get; } = new LinkMarker("M 0 -5 10 0 0 5 z", 10, ArrowPathStyle.Arrow, ArrowSizeStyle.Middle);
+ public static LinkMarker Circle { get; } = new LinkMarker("M 0, 0 a 5,5 0 1,0 10,0 a 5,5 0 1,0 -10,0", 10, ArrowPathStyle.Circle, ArrowSizeStyle.Middle);
+ public static LinkMarker Square { get; } = new LinkMarker("M 0 -5 10 -5 10 5 0 5 z", 10, ArrowPathStyle.Square, ArrowSizeStyle.Middle);
+
+ public static readonly Dictionary ArrowDictionary = new Dictionary()
+ {
+ { ArrowPathStyle.None, None.Path },
+ { ArrowPathStyle.Arrow, Arrow.Path },
+ { ArrowPathStyle.Circle, Circle.Path },
+ { ArrowPathStyle.Square, Square.Path },
+ };
+
+ public LinkMarker()
+ {
+
+ }
+
+ public LinkMarker(string path, double width, ArrowPathStyle arrowPathStyle, ArrowSizeStyle arrowSizeStyle)
+ {
+ Path = path;
+ Width = width;
+ _pathStyle = arrowPathStyle;
+ _sizeStyle = arrowSizeStyle;
+ }
+
+ private string _path;
+ public string Path
+ {
+ get
+ {
+ return _path;
+ }
+ set
+ {
+ SetProperty(ref _path, value);
+ }
+ }
+
+ private double _witdh;
+ public double Width
+ {
+ get
+ {
+ return _witdh;
+ }
+ set
+ {
+ SetProperty(ref _witdh, value);
+ }
+ }
+
+ private ArrowPathStyle _pathStyle = ArrowPathStyle.None;
+ public ArrowPathStyle PathStyle
+ {
+ get
+ {
+ return _pathStyle;
+ }
+ set
+ {
+ if (SetProperty(ref _pathStyle, value))
+ {
+ if (ArrowDictionary.ContainsKey(_pathStyle))
+ {
+ Path = ArrowDictionary[_pathStyle];
+ }
+ }
+ }
+ }
+
+ private ArrowSizeStyle _sizeStyle = ArrowSizeStyle.Middle;
+ public ArrowSizeStyle SizeStyle
+ {
+ get
+ {
+ return _sizeStyle;
+ }
+ set
+ {
+ if (SetProperty(ref _sizeStyle, value))
+ {
+ Width = (double)_sizeStyle;
+ }
+ }
+ }
+
+ public static LinkMarker NewArrow(double width, double height)
+ => new LinkMarker(FormattableString.Invariant($"M 0 -{height / 2} {width} 0 0 {height / 2}"), width, ArrowPathStyle.Arrow, (ArrowSizeStyle)width);
+
+ public static LinkMarker NewCircle(double r)
+ => new LinkMarker(FormattableString.Invariant($"M 0, 0 a {r},{r} 0 1,0 {r * 2},0 a {r},{r} 0 1,0 -{r * 2},0"), r * 2, ArrowPathStyle.Circle, (ArrowSizeStyle)(r * 2));
+
+ public static LinkMarker NewRectangle(double width, double height)
+ => new LinkMarker(FormattableString.Invariant($"M 0 -{height / 2} {width} -{height / 2} {width} {height / 2} 0 {height / 2} z"), width, ArrowPathStyle.Square, (ArrowSizeStyle)width);
+
+ public static LinkMarker NewSquare(double size) => NewRectangle(size, size);
+ }
+
+ public interface ILinkMarker
+ {
+ string Path
+ {
+ get; set;
+ }
+
+ double Width
+ {
+ get; set;
+ }
+
+ ArrowPathStyle PathStyle
+ {
+ get; set;
+ }
+
+ ArrowSizeStyle SizeStyle
+ {
+ get; set;
+ }
+ }
+}
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/ConnectionViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/ConnectionViewModel.cs
index e7e4342..76137f5 100644
--- a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/ConnectionViewModel.cs
+++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/ConnectionViewModel.cs
@@ -53,17 +53,14 @@ namespace AIStudio.Wpf.DiagramDesigner
protected virtual void Init(FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo)
{
this.Root = sourceConnectorInfo.DataItem.Root;
-
- if (Root != null && Root.ColorViewModel != null)
- {
- this.ColorViewModel = CopyHelper.Mapper(Root.ColorViewModel);
- }
+
this.ColorViewModel.FillColor.Color = Colors.Red;
if (sinkConnectorInfo is FullyCreatedConnectorInfo sink && sink.DataItem.ShowArrow == false)
{
- this.ColorViewModel.RightArrowPathStyle = ArrowPathStyle.None;
+ this.ShapeViewModel.SinkMarker = LinkMarker.None;
}
- ColorViewModel.PropertyChanged += ConnectorViewModel_PropertyChanged;
+ this.ColorViewModel.PropertyChanged += ConnectorViewModel_PropertyChanged;
+ this.ShapeViewModel.PropertyChanged += ConnectorViewModel_PropertyChanged;
this.PropertyChanged += ConnectorViewModel_PropertyChanged;
var routetype = GlobalType.AllTypes.Where(p => typeof(IRouter).IsAssignableFrom(p)).FirstOrDefault(p => p.Name == RouterMode);
@@ -76,7 +73,7 @@ namespace AIStudio.Wpf.DiagramDesigner
this.SinkConnectorInfo = sinkConnectorInfo;
DeleteConnectionCommand = new SimpleCommand(Command_Enable, DeleteConnection);
AddVertexCommand = new SimpleCommand(Command_Enable, AddVertex);
- AddLabelCommand = new SimpleCommand(Command_Enable, AddLabel);
+ AddLabelCommand = new SimpleCommand(Command_Enable, para => AddLabel());
}
protected override void LoadDesignerItemViewModel(IDiagramViewModel root, SelectableItemBase designerbase)
@@ -452,12 +449,10 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
- else if (sender is ColorViewModel)
+ else if (sender is ShapeViewModel)
{
- if (e.PropertyName == nameof(ColorViewModel.LeftArrowPathStyle) ||
- e.PropertyName == nameof(ColorViewModel.LeftArrowSizeStyle) ||
- e.PropertyName == nameof(ColorViewModel.RightArrowPathStyle) ||
- e.PropertyName == nameof(ColorViewModel.RightArrowSizeStyle))
+ if (e.PropertyName == nameof(ShapeViewModel.SourceMarker) ||
+ e.PropertyName == nameof(ShapeViewModel.SinkMarker))
{
UpdatePathGeneratorResult();
}
@@ -536,22 +531,22 @@ namespace AIStudio.Wpf.DiagramDesigner
{
case ConnectorOrientation.Left:
{
- StartPoint = new PointBase(PathGeneratorResult.SourceMarkerPosition.X, PathGeneratorResult.SourceMarkerPosition.Y - ColorViewModel.LeftArrowSize / 2);
+ StartPoint = new PointBase(PathGeneratorResult.SourceMarkerPosition.X, PathGeneratorResult.SourceMarkerPosition.Y - GetSourceMarkerWidth() / 2);
break;
}
case ConnectorOrientation.Top:
{
- StartPoint = new PointBase(PathGeneratorResult.SourceMarkerPosition.X - ColorViewModel.LeftArrowSize / 2, PathGeneratorResult.SourceMarkerPosition.Y);
+ StartPoint = new PointBase(PathGeneratorResult.SourceMarkerPosition.X - GetSourceMarkerWidth() / 2, PathGeneratorResult.SourceMarkerPosition.Y);
break;
}
case ConnectorOrientation.Right:
{
- StartPoint = new PointBase(PathGeneratorResult.SourceMarkerPosition.X - ColorViewModel.LeftArrowSize, PathGeneratorResult.SourceMarkerPosition.Y - ColorViewModel.LeftArrowSize / 2);
+ StartPoint = new PointBase(PathGeneratorResult.SourceMarkerPosition.X - GetSourceMarkerWidth(), PathGeneratorResult.SourceMarkerPosition.Y - GetSourceMarkerWidth() / 2);
break;
}
case ConnectorOrientation.Bottom:
{
- StartPoint = new PointBase(PathGeneratorResult.SourceMarkerPosition.X - ColorViewModel.LeftArrowSize / 2, PathGeneratorResult.SourceMarkerPosition.Y - ColorViewModel.LeftArrowSize);
+ StartPoint = new PointBase(PathGeneratorResult.SourceMarkerPosition.X - GetSourceMarkerWidth() / 2, PathGeneratorResult.SourceMarkerPosition.Y - GetSourceMarkerWidth());
break;
}
default:
@@ -566,23 +561,23 @@ namespace AIStudio.Wpf.DiagramDesigner
{
case ConnectorOrientation.Left:
{
- EndPoint = new PointBase(PathGeneratorResult.TargetMarkerPosition.X, PathGeneratorResult.TargetMarkerPosition.Y - ColorViewModel.RightArrowSize / 2);
+ EndPoint = new PointBase(PathGeneratorResult.TargetMarkerPosition.X, PathGeneratorResult.TargetMarkerPosition.Y - GetSinkMarkerWidth() / 2);
break;
}
case ConnectorOrientation.Top:
{
- EndPoint = new PointBase(PathGeneratorResult.TargetMarkerPosition.X - ColorViewModel.RightArrowSize / 2, PathGeneratorResult.TargetMarkerPosition.Y);
+ EndPoint = new PointBase(PathGeneratorResult.TargetMarkerPosition.X - GetSinkMarkerWidth() / 2, PathGeneratorResult.TargetMarkerPosition.Y);
break;
}
case ConnectorOrientation.Right:
{
- EndPoint = new PointBase(PathGeneratorResult.TargetMarkerPosition.X - ColorViewModel.RightArrowSize, PathGeneratorResult.TargetMarkerPosition.Y - ColorViewModel.RightArrowSize / 2);
+ EndPoint = new PointBase(PathGeneratorResult.TargetMarkerPosition.X - GetSinkMarkerWidth(), PathGeneratorResult.TargetMarkerPosition.Y - GetSinkMarkerWidth() / 2);
break;
}
case ConnectorOrientation.Bottom:
{
- EndPoint = new PointBase(PathGeneratorResult.TargetMarkerPosition.X - ColorViewModel.RightArrowSize / 2, PathGeneratorResult.TargetMarkerPosition.Y - ColorViewModel.RightArrowSize);
+ EndPoint = new PointBase(PathGeneratorResult.TargetMarkerPosition.X - GetSinkMarkerWidth() / 2, PathGeneratorResult.TargetMarkerPosition.Y - GetSinkMarkerWidth());
break;
}
default:
@@ -686,6 +681,34 @@ namespace AIStudio.Wpf.DiagramDesigner
return minPoint;
}
+ public void SetSourcePort(FullyCreatedConnectorInfo port)
+ {
+ SourceConnectorInfo = port;
+ }
+
+ public void SetSinkPort(FullyCreatedConnectorInfo port)
+ {
+ SinkConnectorInfo = port;
+ }
+
+ public double GetSourceMarkerWidth()
+ {
+ if (string.IsNullOrEmpty(ShapeViewModel.SourceMarker.Path))
+ {
+ return 0;
+ }
+ return ShapeViewModel.SourceMarker.Width;
+ }
+
+ public double GetSinkMarkerWidth()
+ {
+ if (string.IsNullOrEmpty(ShapeViewModel.SinkMarker.Path))
+ {
+ return 0;
+ }
+ return ShapeViewModel.SinkMarker.Width;
+ }
+
#region 双击添加
private void AddVertex(object parameter)
{
@@ -708,9 +731,9 @@ namespace AIStudio.Wpf.DiagramDesigner
AddLabel();
}
- public void AddLabel(object text = null)
+ public void AddLabel(string text = null, double? distance = null, PointBase? offset = null)
{
- var label = new ConnectorLabelModel(this, text?.ToString());
+ var label = new ConnectorLabelModel(this, text?.ToString(), distance, offset);
label.PropertyChanged += new WeakINPCEventHandler(ConnectorViewModel_PropertyChanged).Handler;
label.IsSelected = true;
Labels.Add(label);
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/Connector/ConnectorLabelModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/Connector/ConnectorLabelModel.cs
index 281c3ea..038d644 100644
--- a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/Connector/ConnectorLabelModel.cs
+++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/Connector/ConnectorLabelModel.cs
@@ -35,6 +35,9 @@ namespace AIStudio.Wpf.DiagramDesigner
{
base.Init();
+ ConnectorWidth = 30;
+ ConnectorHeight = 30;
+
DeleteLabelCommand = new SimpleCommand(Command_Enable, DeleteLabel);
}
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModel.cs
index 3ac6ed9..e3fceeb 100644
--- a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModel.cs
+++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModel.cs
@@ -67,6 +67,16 @@ namespace AIStudio.Wpf.DiagramDesigner
get; set;
}
+ public IFontViewModel FontViewModel
+ {
+ get; set;
+ }
+
+ public IShapeViewModel ShapeViewModel
+ {
+ get; set;
+ }
+
private PageSizeType _pageSizeType = PageSizeType.A4;
public PageSizeType PageSizeType
{
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/SelectableViewModelBase.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/SelectableViewModelBase.cs
index d61c81f..41e8f22 100644
--- a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/SelectableViewModelBase.cs
+++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/SelectableViewModelBase.cs
@@ -62,8 +62,32 @@ namespace AIStudio.Wpf.DiagramDesigner
protected virtual void Init()
{
- ColorViewModel = _service.CopyDefaultColorViewModel();
- FontViewModel = _service.CopyDefaultFontViewModel();
+ if (Root?.ColorViewModel != null)
+ {
+ this.ColorViewModel = CopyHelper.Mapper(Root.ColorViewModel);
+ }
+ else
+ {
+ this.ColorViewModel = _service.CopyDefaultColorViewModel();
+ }
+
+ if (Root?.FontViewModel != null)
+ {
+ this.FontViewModel = CopyHelper.Mapper(Root.FontViewModel);
+ }
+ else
+ {
+ this.FontViewModel = _service.CopyDefaultFontViewModel();
+ }
+
+ if (Root?.ShapeViewModel != null)
+ {
+ this.ShapeViewModel = CopyHelper.Mapper(Root.ShapeViewModel);
+ }
+ else
+ {
+ this.ShapeViewModel = _service.CopyDefaultShapeViewModel();
+ }
LockObjectViewModel = new LockObjectViewModel();
}
@@ -80,6 +104,7 @@ namespace AIStudio.Wpf.DiagramDesigner
ColorViewModel = CopyHelper.Mapper(designerbase.ColorItem);
FontViewModel = CopyHelper.Mapper(designerbase.FontItem);
+ ShapeViewModel = CopyHelper.Mapper(designerbase.SharpItem);
}
public IDiagramViewModel Root
@@ -220,6 +245,19 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
+ private IShapeViewModel _shapeViewModel;
+ public IShapeViewModel ShapeViewModel
+ {
+ get
+ {
+ return _shapeViewModel;
+ }
+ set
+ {
+ SetProperty(ref _shapeViewModel, value);
+ }
+ }
+
public ILockObjectViewModel LockObjectViewModel
{
get; set;
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/IDiagramViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/IDiagramViewModel.cs
index 8f9dd2c..fc613a9 100644
--- a/AIStudio.Wpf.DiagramDesigner/ViewModels/IDiagramViewModel.cs
+++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/IDiagramViewModel.cs
@@ -258,6 +258,14 @@ namespace AIStudio.Wpf.DiagramDesigner
{
get; set;
}
+ IFontViewModel FontViewModel
+ {
+ get; set;
+ }
+ IShapeViewModel ShapeViewModel
+ {
+ get; set;
+ }
#endregion
//用于wpf大小与物理像素之间转换
double ScreenScale