diff --git a/AIStudio.Wpf.DiagramApp/App.xaml b/AIStudio.Wpf.DiagramApp/App.xaml
index 7e1527f..5142858 100644
--- a/AIStudio.Wpf.DiagramApp/App.xaml
+++ b/AIStudio.Wpf.DiagramApp/App.xaml
@@ -16,7 +16,8 @@
-
+
+
diff --git a/AIStudio.Wpf.DiagramApp/Models/CustomToolBoxData.cs b/AIStudio.Wpf.DiagramApp/Models/CustomToolBoxData.cs
index a8a8b0f..24d4637 100644
--- a/AIStudio.Wpf.DiagramApp/Models/CustomToolBoxData.cs
+++ b/AIStudio.Wpf.DiagramApp/Models/CustomToolBoxData.cs
@@ -14,7 +14,7 @@ namespace AIStudio.Wpf.DiagramApp.Models
{
public class PathToolBoxData : ToolBoxData
{
- public PathToolBoxData(string icon, Type type, double width = 32, double height = 32, Size? desiredSize = null, string description = null) : base(null, icon, type, width, height, desiredSize, description)
+ public PathToolBoxData(string icon, Type type, double width = 32, double height = 32, Size? desiredSize = null, Size? desiredMinSize = null, string description = null) : base(null, icon, type, width, height, desiredSize, desiredMinSize, description)
{
ColorViewModel.FillColor.Color = Colors.Orange;
}
@@ -23,7 +23,7 @@ namespace AIStudio.Wpf.DiagramApp.Models
public class TextToolBoxData : ToolBoxData
{
- public TextToolBoxData(string text, Type type, double width = 32, double height = 32, Size? desiredSize = null, string description = null) : base(text, null, type, width, height, desiredSize, description)
+ public TextToolBoxData(string text, Type type, double width = 32, double height = 32, Size? desiredSize = null, Size? desiredMinSize = null, string description = null) : base(text, null, type, width, height, desiredSize, desiredMinSize, description)
{
ColorViewModel.FillColor.Color = Colors.Orange;
}
@@ -32,7 +32,7 @@ namespace AIStudio.Wpf.DiagramApp.Models
public class EllipseTextToolBoxData : ToolBoxData
{
- public EllipseTextToolBoxData(string text, Type type, double width = 32, double height = 32, Size? desiredSize = null, string description = null) : base(text, null, type, width, height, desiredSize, description)
+ public EllipseTextToolBoxData(string text, Type type, double width = 32, double height = 32, Size? desiredSize = null, Size? desiredMinSize = null, string description = null) : base(text, null, type, width, height, desiredSize, desiredMinSize, description)
{
ColorViewModel.FillColor.Color = Colors.Orange;
}
@@ -41,7 +41,7 @@ namespace AIStudio.Wpf.DiagramApp.Models
public class ImageToolBoxData : ToolBoxData
{
- public ImageToolBoxData(string icon, Type type, double width = 32, double height = 32, Size? desiredSize = null, string description = null) : base(null, icon, type, width, height, desiredSize, description)
+ public ImageToolBoxData(string icon, Type type, double width = 32, double height = 32, Size? desiredSize = null, Size? desiredMinSize = null, string description = null) : base(null, icon, type, width, height, desiredSize, desiredMinSize, description)
{
}
@@ -57,7 +57,7 @@ namespace AIStudio.Wpf.DiagramApp.Models
{
get; set;
}
- public DesignerItemToolBoxData(DesignerItemBase designerItemBase, string filename, Type type, double width = 32, double height = 32, Size? desiredSize = null, string description = null) : base(null, null, type, width, height, desiredSize, description)
+ public DesignerItemToolBoxData(DesignerItemBase designerItemBase, string filename, Type type, double width = 32, double height = 32, Size? desiredSize = null, Size? desiredMinSize = null, string description = null) : base(null, null, type, width, height, desiredSize, desiredMinSize, description)
{
Addition = designerItemBase;
DesignerItemViewModel = Activator.CreateInstance(type, null, designerItemBase) as DesignerItemViewModelBase;
@@ -84,7 +84,7 @@ namespace AIStudio.Wpf.DiagramApp.Models
{
get; set;
}
- public MultipleDesignerItemToolBoxData(SerializableObject designerItemBase, string filename, double width = 32, double height = 32, Size? desiredSize = null, string description = null) : base(null, null, typeof(List), width, height, desiredSize, description)
+ public MultipleDesignerItemToolBoxData(SerializableObject designerItemBase, string filename, double width = 32, double height = 32, Size? desiredSize = null, Size? desiredMinSize = null, string description = null) : base(null, null, typeof(List), width, height, desiredSize, desiredMinSize, description)
{
SelectableDesignerItemViewModels = designerItemBase.ToObject();
@@ -111,7 +111,7 @@ namespace AIStudio.Wpf.DiagramApp.Models
public class SvgToolBoxData : ToolBoxData
{
- public SvgToolBoxData(string filename, Type type, double width = 32, double height = 32, Size? desiredSize = null, string description = null) : base(null, filename, type, width, height, desiredSize, description)
+ public SvgToolBoxData(string filename, Type type, double width = 32, double height = 32, Size? desiredSize = null, Size? desiredMinSize = null, string description = null) : base(null, filename, type, width, height, desiredSize, desiredMinSize, description)
{
ColorViewModel.FillColor.Color = Colors.Blue;
}
@@ -119,7 +119,7 @@ namespace AIStudio.Wpf.DiagramApp.Models
public class MediaToolBoxData : ToolBoxData
{
- public MediaToolBoxData(string icon, Type type, double width = 32, double height = 32, Size? desiredSize = null, string description = null) : base(icon, null, type, width, height, desiredSize, description)
+ public MediaToolBoxData(string icon, Type type, double width = 32, double height = 32, Size? desiredSize = null, Size? desiredMinSize = null, string description = null) : base(icon, null, type, width, height, desiredSize, desiredMinSize, description)
{
}
diff --git a/AIStudio.Wpf.DiagramApp/ViewModels/BlockViewModel.cs b/AIStudio.Wpf.DiagramApp/ViewModels/BlockViewModel.cs
new file mode 100644
index 0000000..21e1260
--- /dev/null
+++ b/AIStudio.Wpf.DiagramApp/ViewModels/BlockViewModel.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+//using AIStudio.Wpf.Block.ViewModels;
+using AIStudio.Wpf.DiagramApp.Models;
+using AIStudio.Wpf.DiagramDesigner;
+
+namespace AIStudio.Wpf.DiagramApp.ViewModels
+{
+ internal class BlockViewModel : PageViewModel
+ {
+ public BlockViewModel(string title, string status, DiagramType diagramType) : base(title, status, diagramType)
+ {
+
+ }
+ public BlockViewModel(string filename, DiagramDocument diagramDocument) : base(filename, diagramDocument)
+ {
+
+ }
+
+ protected override void InitDiagramViewModel()
+ {
+ base.InitDiagramViewModel();
+
+ DiagramViewModel.DiagramOption.LayoutOption.ShowGrid = false;
+ }
+
+ protected override void Init(bool initNew)
+ {
+ base.Init(initNew);
+
+ //StartBlockItemViewModel start = new StartBlockItemViewModel(DiagramViewModel) { Left = 28, Top = 28 };
+ //DiagramViewModel.Add(start);
+
+ //WaitTimeBlockItemViewModel waittime = new WaitTimeBlockItemViewModel(DiagramViewModel) { Left = 28, Top = 28 };
+ //DiagramViewModel.Add(waittime);
+
+ //AddBlockItemViewModel add = new AddBlockItemViewModel(DiagramViewModel) { Left = 28, Top = 28 };
+ //DiagramViewModel.Add(add);
+
+ //KeyboardPressBlockItemViewModel keyboardPress = new KeyboardPressBlockItemViewModel(DiagramViewModel) { Left = 28, Top = 28 };
+ //DiagramViewModel.Add(keyboardPress);
+ }
+ }
+}
diff --git a/AIStudio.Wpf.DiagramApp/ViewModels/MainWindowViewModel.cs b/AIStudio.Wpf.DiagramApp/ViewModels/MainWindowViewModel.cs
index 19d3573..a3b77a2 100644
--- a/AIStudio.Wpf.DiagramApp/ViewModels/MainWindowViewModel.cs
+++ b/AIStudio.Wpf.DiagramApp/ViewModels/MainWindowViewModel.cs
@@ -21,6 +21,7 @@ using AIStudio.Wpf.DiagramDesigner.ViewModels;
using AIStudio.Wpf.DiagramDesigner.ViewModels.BaseViewModel;
using AIStudio.Wpf.Mind;
using AIStudio.Wpf.Mind.Models;
+using ControlzEx.Controls;
namespace AIStudio.Wpf.DiagramApp.ViewModels
{
@@ -545,6 +546,10 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
{
flow = new DrawingViewModel(filename, diagram);
}
+ else if (diagram.DiagramType == DiagramType.Block)
+ {
+ flow = new BlockViewModel(filename, diagram);
+ }
else
{
flow = new PageViewModel(filename, diagram);
@@ -668,6 +673,10 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
{
PageViewModel = new DrawingViewModel(NewNameHelper.GetNewName(PageViewModels.Select(p => p.Title), "新建-"), "*", (DiagramType)Enum.Parse(typeof(DiagramType), type));
}
+ else if (type == DiagramType.Block.ToString())
+ {
+ PageViewModel = new BlockViewModel(NewNameHelper.GetNewName(PageViewModels.Select(p => p.Title), "新建-"), "*", (DiagramType)Enum.Parse(typeof(DiagramType), type));
+ }
else
{
PageViewModel = new PageViewModel(NewNameHelper.GetNewName(PageViewModels.Select(p => p.Title), "新建-"), "*", (DiagramType)Enum.Parse(typeof(DiagramType), type));
diff --git a/AIStudio.Wpf.DiagramApp/ViewModels/PageViewModel.cs b/AIStudio.Wpf.DiagramApp/ViewModels/PageViewModel.cs
index 5c3c94c..71d5659 100644
--- a/AIStudio.Wpf.DiagramApp/ViewModels/PageViewModel.cs
+++ b/AIStudio.Wpf.DiagramApp/ViewModels/PageViewModel.cs
@@ -20,6 +20,7 @@ using ZXing;
using AIStudio.Wpf.DiagramDesigner.Helpers;
using AIStudio.Wpf.DiagramDesigner.ViewModels;
using AIStudio.Wpf.DiagramDesigner.ViewModels.BaseViewModel;
+using System.Threading.Tasks;
namespace AIStudio.Wpf.DiagramApp.ViewModels
{
@@ -34,29 +35,48 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
}
}
+
public PageViewModel(string title, string status, DiagramType diagramType, string subType = null)
{
Title = title;
Status = status;
DiagramType = diagramType;
SubType = subType;
- Init(true);
+
}
public PageViewModel(string filename)
{
FileName = filename;
string ext = Path.GetExtension(filename);
- var diagramDocument = OpenFile(filename, ext);
- OpenFile(diagramDocument, ext);
+ DiagramDocument = OpenFile(filename, ext);
}
public PageViewModel(string filename, DiagramDocument diagramDocument)
{
FileName = filename;
- string ext = Path.GetExtension(filename);
- OpenFile(diagramDocument, ext);
+ DiagramDocument = diagramDocument;
}
+ DiagramDocument DiagramDocument;
+ public virtual void View_Loaded(object sender, EventArgs e)
+ {
+ //await Task.Run(() => {
+ //Application.Current.Dispatcher.Invoke(() => {
+ if (string.IsNullOrEmpty(FileName))
+ {
+ Init(true);
+ }
+ else
+ {
+ string ext = Path.GetExtension(FileName);
+ OpenFile(DiagramDocument, ext);
+ }
+ //});
+ //});
+
+ }
+
+
protected virtual void InitDiagramViewModel()
{
diff --git a/AIStudio.Wpf.DiagramApp/ViewModels/SFCViewModel.cs b/AIStudio.Wpf.DiagramApp/ViewModels/SFCViewModel.cs
index 77065c9..a700752 100644
--- a/AIStudio.Wpf.DiagramApp/ViewModels/SFCViewModel.cs
+++ b/AIStudio.Wpf.DiagramApp/ViewModels/SFCViewModel.cs
@@ -13,7 +13,7 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
{
public SFCViewModel(string title, string status, DiagramType diagramType) : base(title, status, diagramType)
{
- Init(true);
+
}
public SFCViewModel(string filename, DiagramDocument diagramDocument) : base(filename, diagramDocument)
diff --git a/AIStudio.Wpf.DiagramApp/ViewModels/ScriptViewModel.cs b/AIStudio.Wpf.DiagramApp/ViewModels/ScriptViewModel.cs
index 47f9189..d0bafdc 100644
--- a/AIStudio.Wpf.DiagramApp/ViewModels/ScriptViewModel.cs
+++ b/AIStudio.Wpf.DiagramApp/ViewModels/ScriptViewModel.cs
@@ -27,7 +27,7 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
public ScriptViewModel(string title, string status, DiagramType diagramType) : base(title, status, diagramType)
{
- Init(true);
+
}
public ScriptViewModel(string filename, DiagramDocument diagramDocument) : base(filename, diagramDocument)
@@ -61,8 +61,8 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
ConsoleLogViewModel logNode = new ConsoleLogViewModel(DiagramViewModel) { Name = "Log", Left = 150, Top = 420 };
DiagramViewModel.Add(logNode);
- IntScriptViewModel intLog = new IntScriptViewModel(DiagramViewModel) { Name = "Int", Left = 40, Top = 220 };
- DiagramViewModel.Add(intLog);
+ IntScriptViewModel intNode = new IntScriptViewModel(DiagramViewModel) { Name = "Int", Left = 40, Top = 220 };
+ DiagramViewModel.Add(intNode);
ColorBoxFactoryScriptViewModel factoryNode = new ColorBoxFactoryScriptViewModel(DiagramViewModel) { Name = "ColorBoxFactory", Left = 150, Top = 150 };
DiagramViewModel.Add(factoryNode);
@@ -111,7 +111,7 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
collectorNode7.Tag = new ColorBoxModel("紫色|六边形", "M 0,20 L 10,0 H 50 L 60,20 L 50,40 H10 Z", Colors.Purple);
DiagramViewModel.Add(collectorNode7);
- ConnectionViewModel int_factoryConnector = new ConnectionViewModel(DiagramViewModel, intLog.Output[0], factoryNode.Input[0], DrawMode.ConnectingLineSmooth, RouterMode.RouterNormal);
+ ConnectionViewModel int_factoryConnector = new ConnectionViewModel(DiagramViewModel, intNode.Output[0], factoryNode.Input[0], DrawMode.ConnectingLineSmooth, RouterMode.RouterNormal);
DiagramViewModel.Add(int_factoryConnector);
ConnectionViewModel bool_switchConnector = new ConnectionViewModel(DiagramViewModel, boolNode.Output[0], switchNode.Input[0], DrawMode.ConnectingLineSmooth, RouterMode.RouterNormal);
@@ -191,7 +191,9 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
{
item.Execute();
}
- readDataTimer.Start();
+
+ if (readDataTimer != null)
+ readDataTimer.Start();
}
public override void Dispose()
@@ -200,6 +202,7 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
readDataTimer.Stop();
readDataTimer.Dispose();
+ readDataTimer = null;
foreach (var item in DiagramViewModel.Items.OfType().OrderBy(p => p.OrderNumber).ToList())
{
diff --git a/AIStudio.Wpf.DiagramApp/ViewModels/ToolBoxViewModel.cs b/AIStudio.Wpf.DiagramApp/ViewModels/ToolBoxViewModel.cs
index d8d7bb8..6aab3aa 100644
--- a/AIStudio.Wpf.DiagramApp/ViewModels/ToolBoxViewModel.cs
+++ b/AIStudio.Wpf.DiagramApp/ViewModels/ToolBoxViewModel.cs
@@ -119,9 +119,16 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
List defaultToolBoxItems = new List();
defaultToolBoxItems.Add(new TextToolBoxData("", typeof(DefaultDesignerItemViewModel)));
- var blockitem = new TextToolBoxData("", typeof(BlockDesignerItemViewModel), 64, 32, new Size(130, 65));
+ var blockitem = new TextToolBoxData("Block", typeof(BlockDesignerItemViewModel), 64, 32, desiredMinSize: new Size(130, 65));
blockitem.ColorViewModel.FillColor.Color = Color.FromRgb(0x00, 0x2F, 0xA7);
defaultToolBoxItems.Add(blockitem);
+ var blockitem2 = new TextToolBoxData("Contain", typeof(BlockContainDesignerItemViewModel), 64, 32, desiredMinSize: new Size(130, 65));
+ blockitem2.ColorViewModel.FillColor.Color = Color.FromRgb(0x00, 0x2F, 0xA7);
+ defaultToolBoxItems.Add(blockitem2);
+ var blockitem3 = new TextToolBoxData("ContainList", typeof(BlockContainListDesignerItemViewModel), 64, 32, desiredMinSize: new Size(130, 65));
+ blockitem3.ColorViewModel.FillColor.Color = Color.FromRgb(0x00, 0x2F, 0xA7);
+ defaultToolBoxItems.Add(blockitem3);
+
ToolBoxCategory.Add(new ToolBoxCategory() { Header = "Default", ToolBoxItems = new ObservableCollection(defaultToolBoxItems), IsExpanded = true });
ToolBoxCategory.Add(new ToolBoxCategory() { Header = "Svg", ToolBoxItems = new ObservableCollection() });
diff --git a/AIStudio.Wpf.DiagramApp/Views/MainWindow.xaml b/AIStudio.Wpf.DiagramApp/Views/MainWindow.xaml
index 6338ccc..577ec0f 100644
--- a/AIStudio.Wpf.DiagramApp/Views/MainWindow.xaml
+++ b/AIStudio.Wpf.DiagramApp/Views/MainWindow.xaml
@@ -103,6 +103,9 @@
+
@@ -2651,70 +2654,76 @@
-
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
diff --git a/AIStudio.Wpf.DiagramDesigner.Additionals/AIStudio.Wpf.DiagramDesigner.Additionals_c3dwds1m_wpftmp.csproj b/AIStudio.Wpf.DiagramDesigner.Additionals/AIStudio.Wpf.DiagramDesigner.Additionals_c3dwds1m_wpftmp.csproj
new file mode 100644
index 0000000..4c693ab
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner.Additionals/AIStudio.Wpf.DiagramDesigner.Additionals_c3dwds1m_wpftmp.csproj
@@ -0,0 +1,309 @@
+
+
+ AIStudio.Wpf.DiagramDesigner.Additionals
+ obj\Debug\
+ obj\
+ F:\aistudio.-wpf.-diagram\AIStudio.Wpf.DiagramDesigner.Additionals\obj\
+ <_TargetAssemblyProjectName>AIStudio.Wpf.DiagramDesigner.Additionals
+
+
+
+ true
+ true
+ AIStudio.Wpf.Controls
+ akwkevin
+ https://gitee.com/akwkevin
+ A.png
+
+
+ 1.0.1
+ 一个Wpf的Diagram控件帮助库
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AIStudio.Wpf.DiagramDesigner.Additionals/AIStudio.Wpf.DiagramDesigner.Additionals_ltmcgkh5_wpftmp.csproj b/AIStudio.Wpf.DiagramDesigner.Additionals/AIStudio.Wpf.DiagramDesigner.Additionals_ltmcgkh5_wpftmp.csproj
new file mode 100644
index 0000000..a5374c7
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner.Additionals/AIStudio.Wpf.DiagramDesigner.Additionals_ltmcgkh5_wpftmp.csproj
@@ -0,0 +1,300 @@
+
+
+ AIStudio.Wpf.DiagramDesigner.Additionals
+ obj\Debug\
+ obj\
+ F:\aistudio.-wpf.-diagram\AIStudio.Wpf.DiagramDesigner.Additionals\obj\
+ <_TargetAssemblyProjectName>AIStudio.Wpf.DiagramDesigner.Additionals
+
+
+
+ true
+ true
+ AIStudio.Wpf.Controls
+ akwkevin
+ https://gitee.com/akwkevin
+ A.png
+
+
+ 1.0.1
+ 一个Wpf的Diagram控件帮助库
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AIStudio.Wpf.DiagramDesigner.Additionals/AIStudio.Wpf.DiagramDesigner.Additionals_uoedrdjs_wpftmp.csproj b/AIStudio.Wpf.DiagramDesigner.Additionals/AIStudio.Wpf.DiagramDesigner.Additionals_uoedrdjs_wpftmp.csproj
new file mode 100644
index 0000000..53e7f62
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner.Additionals/AIStudio.Wpf.DiagramDesigner.Additionals_uoedrdjs_wpftmp.csproj
@@ -0,0 +1,235 @@
+
+
+ AIStudio.Wpf.DiagramDesigner.Additionals
+ obj\Debug\
+ obj\
+ F:\aistudio.-wpf.-diagram\AIStudio.Wpf.DiagramDesigner.Additionals\obj\
+ <_TargetAssemblyProjectName>AIStudio.Wpf.DiagramDesigner.Additionals
+
+
+
+ true
+ true
+ AIStudio.Wpf.Controls
+ akwkevin
+ https://gitee.com/akwkevin
+ A.png
+
+
+ 1.0.1
+ 一个Wpf的Diagram控件帮助库
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AIStudio.Wpf.DiagramDesigner/AttachedProperties/DragAndDropProps.cs b/AIStudio.Wpf.DiagramDesigner/AttachedProperties/DragAndDropProps.cs
index 741dd5c..1cc3f43 100644
--- a/AIStudio.Wpf.DiagramDesigner/AttachedProperties/DragAndDropProps.cs
+++ b/AIStudio.Wpf.DiagramDesigner/AttachedProperties/DragAndDropProps.cs
@@ -77,7 +77,9 @@ namespace AIStudio.Wpf.DiagramDesigner
DragObject dataObject = new DragObject();
dataObject.ContentType = toolBoxData.Type;
dataObject.DesiredSize = toolBoxData.DesiredSize;
+ dataObject.DesiredMinSize = toolBoxData.DesiredMinSize;
dataObject.Icon = toolBoxData.Icon;
+ dataObject.Text = toolBoxData.Text;
dataObject.ColorViewModel = toolBoxData.ColorViewModel;
dataObject.DesignerItem = toolBoxData.Addition;
diff --git a/AIStudio.Wpf.DiagramDesigner/AttachedProperties/WidthAndHeightProps.cs b/AIStudio.Wpf.DiagramDesigner/AttachedProperties/WidthAndHeightProps.cs
new file mode 100644
index 0000000..debea6b
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner/AttachedProperties/WidthAndHeightProps.cs
@@ -0,0 +1,100 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace AIStudio.Wpf.DiagramDesigner
+{
+
+ public static class WidthAndHeightProps
+ {
+ public static readonly DependencyProperty ActiveProperty = DependencyProperty.RegisterAttached(
+ "Active",
+ typeof(bool),
+ typeof(WidthAndHeightProps),
+ new FrameworkPropertyMetadata(OnActiveChanged));
+
+ public static bool GetActive(FrameworkElement frameworkElement)
+ {
+ return (bool)frameworkElement.GetValue(ActiveProperty);
+ }
+
+ public static void SetActive(FrameworkElement frameworkElement, bool active)
+ {
+ frameworkElement.SetValue(ActiveProperty, active);
+ }
+
+ public static readonly DependencyProperty BoundActualWidthProperty = DependencyProperty.RegisterAttached(
+ "BoundActualWidth",
+ typeof(double),
+ typeof(WidthAndHeightProps));
+
+ public static double GetBoundActualWidth(FrameworkElement frameworkElement)
+ {
+ return (double)frameworkElement.GetValue(BoundActualWidthProperty);
+ }
+
+ public static void SetBoundActualWidth(FrameworkElement frameworkElement, double width)
+ {
+ frameworkElement.SetValue(BoundActualWidthProperty, width);
+ }
+
+ public static readonly DependencyProperty BoundActualHeightProperty = DependencyProperty.RegisterAttached(
+ "BoundActualHeight",
+ typeof(double),
+ typeof(WidthAndHeightProps));
+
+ public static double GetBoundActualHeight(FrameworkElement frameworkElement)
+ {
+ return (double)frameworkElement.GetValue(BoundActualHeightProperty);
+ }
+
+ public static void SetBoundActualHeight(FrameworkElement frameworkElement, double height)
+ {
+ frameworkElement.SetValue(BoundActualHeightProperty, height);
+ }
+
+ private static void OnActiveChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
+ {
+ if (!(dependencyObject is FrameworkElement frameworkElement))
+ {
+ return;
+ }
+
+ if ((bool)e.NewValue)
+ {
+ frameworkElement.SizeChanged -= OnFrameworkElementSizeChanged;
+ frameworkElement.SizeChanged += OnFrameworkElementSizeChanged;
+ frameworkElement.Loaded -= FrameworkElement_Loaded;
+ frameworkElement.Loaded += FrameworkElement_Loaded;
+
+ }
+ else
+ {
+ frameworkElement.SizeChanged -= OnFrameworkElementSizeChanged;
+ frameworkElement.Loaded -= FrameworkElement_Loaded;
+ }
+ }
+
+ private static void FrameworkElement_Loaded(object sender, RoutedEventArgs e)
+ {
+ UpdateObservedSizesForFrameworkElement(sender as FrameworkElement);
+ }
+
+ private static void OnFrameworkElementSizeChanged(object sender, SizeChangedEventArgs e)
+ {
+ if (sender is FrameworkElement frameworkElement)
+ {
+ UpdateObservedSizesForFrameworkElement(frameworkElement);
+ }
+ }
+
+ private static void UpdateObservedSizesForFrameworkElement(FrameworkElement frameworkElement)
+ {
+ frameworkElement.SetCurrentValue(BoundActualWidthProperty, frameworkElement.ActualWidth);
+ frameworkElement.SetCurrentValue(BoundActualHeightProperty, frameworkElement.ActualHeight);
+ }
+ }
+}
diff --git a/AIStudio.Wpf.DiagramDesigner/Controls/BlockConnector.cs b/AIStudio.Wpf.DiagramDesigner/Controls/BlockConnector.cs
new file mode 100644
index 0000000..639ce98
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner/Controls/BlockConnector.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+
+namespace AIStudio.Wpf.DiagramDesigner
+{
+ public class BlockConnector : ContentControl
+ {
+ public ConnectorOrientation Orientation { get; set; }
+
+ public ConnectorInfoBase Info
+ {
+ get
+ {
+ if (Content is ConnectorInfoBase connectorInfo)
+ return connectorInfo;
+
+ return this.DataContext as ConnectorInfoBase;
+ }
+ }
+
+ }
+
+ public class BlockBorder : Border
+ {
+ }
+
+}
diff --git a/AIStudio.Wpf.DiagramDesigner/Controls/DesignerCanvas.cs b/AIStudio.Wpf.DiagramDesigner/Controls/DesignerCanvas.cs
index 3e8bd85..40560cb 100644
--- a/AIStudio.Wpf.DiagramDesigner/Controls/DesignerCanvas.cs
+++ b/AIStudio.Wpf.DiagramDesigner/Controls/DesignerCanvas.cs
@@ -1,22 +1,14 @@
using System;
-using System.Collections.Generic;
-using System.IO;
+using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
-using System.Windows.Markup;
using System.Windows.Media;
-using System.Xml;
-using System.Linq;
-using System.Windows.Shapes;
using System.Windows.Resources;
-using System.Runtime.InteropServices;
-using Newtonsoft.Json;
using AIStudio.Wpf.DiagramDesigner.Models;
using AIStudio.Wpf.DiagramDesigner.ViewModels;
using AIStudio.Wpf.DiagramDesigner.ViewModels.BaseViewModel;
-using System.Diagnostics;
namespace AIStudio.Wpf.DiagramDesigner
{
@@ -37,7 +29,7 @@ namespace AIStudio.Wpf.DiagramDesigner
return DiagramServicesProvider.Instance.Provider;
}
}
- private ConnectionViewModel partialConnection;
+ private ConnectionViewModel _partialConnection;
private Point? rubberbandSelectionStartPoint = null;
@@ -63,10 +55,10 @@ namespace AIStudio.Wpf.DiagramDesigner
Point point = sourceDataItem.MiddlePosition;
- partialConnection = new ConnectionViewModel(_viewModel, sourceDataItem, new PartCreatedConnectorInfo(point.X, point.Y), LineDrawMode, RouterMode);
+ _partialConnection = new ConnectionViewModel(_viewModel, sourceDataItem, new PartCreatedConnectorInfo(point.X, point.Y), LineDrawMode, RouterMode);
- _viewModel.Add(partialConnection);
- partialConnection.ZIndex = -1;
+ _viewModel.Add(_partialConnection);
+ _partialConnection.ZIndex = -1;
}
}
}
@@ -91,6 +83,30 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
}
+
+ private ItemsContainer _sourceItemsContainer;
+ public ItemsContainer SourceItemsContainer
+ {
+ get
+ {
+ return _sourceItemsContainer;
+ }
+ set
+ {
+ if (_sourceItemsContainer != value)
+ {
+ _sourceItemsContainer = value;
+ if (_sourceItemsContainer != null)
+ {
+ ItemsContainerInfo sourceDataItem = _sourceItemsContainer.Info;
+
+ sourceDataItem.DataItem.RemoveChild(_sourceItemsContainer.DragObject);
+
+ EnterMove();
+ }
+ }
+ }
+ }
private DrawMode DrawMode
{
@@ -467,7 +483,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{
if (e.LeftButton == MouseButtonState.Pressed)
{
- partialConnection.SinkConnectorInfo = new PartCreatedConnectorInfo(currentPoint.X, currentPoint.Y);
+ _partialConnection.SinkConnectorInfo = new PartCreatedConnectorInfo(currentPoint.X, currentPoint.Y);
SinkConnector = HitTesting(currentPoint);
if (SinkConnector?.Info?.CanAttachTo(SourceConnector?.Info) == false)
@@ -477,14 +493,24 @@ namespace AIStudio.Wpf.DiagramDesigner
if (_viewModel.DiagramOption.SnappingOption.EnableSnapping)
{
- var nearPort = _viewModel.FindNearPortToAttachTo(partialConnection);
+ var nearPort = _viewModel.FindNearPortToAttachTo(_partialConnection);
if (nearPort != null)
{
- partialConnection.SinkConnectorInfo = nearPort;
+ _partialConnection.SinkConnectorInfo = nearPort;
}
}
}
}
+ else if (SourceItemsContainer != null)
+ {
+ if (e.LeftButton == MouseButtonState.Pressed)
+ {
+ SourceItemsContainer.DragObject.Left = currentPoint.X - SourceItemsContainer.DragOffset.X;
+ SourceItemsContainer.DragObject.Top = currentPoint.Y - SourceItemsContainer.DragOffset.Y;
+
+ _viewModel.PreviewNearBlock(new System.Collections.Generic.List { SourceItemsContainer.DragObject });
+ }
+ }
else
{
// if mouse button is not pressed we have no drag operation, ...
@@ -526,10 +552,10 @@ namespace AIStudio.Wpf.DiagramDesigner
{
ConnectorInfoBase sinkDataItem = SinkConnector.Info;
- _viewModel.Delete(partialConnection);
+ _viewModel.Delete(_partialConnection);
_viewModel.AddCommand.Execute(new ConnectionViewModel(_viewModel, sourceDataItem, sinkDataItem, LineDrawMode, RouterMode));
}
- else if (partialConnection.IsFullConnection)//自动连接模式
+ else if (_partialConnection.IsFullConnection)//自动连接模式
{
_viewModel.ClearNearPort();
}
@@ -538,19 +564,26 @@ namespace AIStudio.Wpf.DiagramDesigner
Point currentPoint = e.GetPosition(this);
ConnectorInfoBase sinkDataItem = new PartCreatedConnectorInfo(currentPoint.X, currentPoint.Y);
- _viewModel.Delete(partialConnection);
+ _viewModel.Delete(_partialConnection);
_viewModel.AddCommand.Execute(new ConnectionViewModel(_viewModel, sourceDataItem, sinkDataItem, LineDrawMode, RouterMode));
}
else
{
//Need to remove last item as we did not finish drawing the path
- _viewModel.Delete(partialConnection);
+ _viewModel.Delete(_partialConnection);
}
}
+ else if (SourceItemsContainer != null)
+ {
+ _viewModel.FinishNearBlock(new System.Collections.Generic.List { SourceItemsContainer.DragObject });
+ ExitCursor();
+ }
SourceConnector = null;
SinkConnector = null;
- partialConnection = null;
+ _partialConnection = null;
+
+ SourceItemsContainer = null;
_service.DrawModeViewModel.ResetDrawMode();
}
@@ -624,6 +657,36 @@ namespace AIStudio.Wpf.DiagramDesigner
return null;
}
+ protected override void OnDragOver(DragEventArgs e)
+ {
+ DragObject dragObject = e.Data.GetData(typeof(DragObject)) as DragObject;
+ if (dragObject != null && (dragObject.ContentType == typeof(BlockDesignerItemViewModel) || dragObject.ContentType.IsSubclassOf(typeof(BlockDesignerItemViewModel))))
+ {
+ var position = e.GetPosition(this);
+
+ BlockDesignerItemViewModel itemBase = Activator.CreateInstance(dragObject.ContentType) as BlockDesignerItemViewModel;
+ itemBase.Text = dragObject.Text;
+ itemBase.Icon = dragObject.Icon;
+ itemBase.ColorViewModel = CopyHelper.Mapper(dragObject.ColorViewModel);
+ if (dragObject.DesiredSize != null)
+ {
+ itemBase.ItemWidth = dragObject.DesiredSize.Value.Width;
+ itemBase.ItemHeight = dragObject.DesiredSize.Value.Height;
+ }
+ if (dragObject.DesiredMinSize != null)
+ {
+ itemBase.MinItemWidth = dragObject.DesiredMinSize.Value.Width;
+ itemBase.MinItemHeight = dragObject.DesiredMinSize.Value.Height;
+ }
+ itemBase.Left = Math.Max(0, position.X - itemBase.GetItemWidth() / 2);
+ itemBase.Top = Math.Max(0, position.Y - itemBase.GetItemHeight() / 2);
+
+ _viewModel.PreviewNearBlock(new System.Collections.Generic.List { itemBase });
+ }
+
+ base.OnDragOver(e);
+ }
+
protected override void OnDrop(DragEventArgs e)
{
base.OnDrop(e);
@@ -640,8 +703,8 @@ namespace AIStudio.Wpf.DiagramDesigner
var designerItems = serializableObject.ToObject();
var minleft = designerItems.OfType().Min(p => p.Left);
var mintop = designerItems.OfType().Min(p => p.Top);
- var maxright = designerItems.OfType().Max(p => p.Left + p.ItemWidth);
- var maxbottom = designerItems.OfType().Max(p => p.Top + p.ItemHeight);
+ var maxright = designerItems.OfType().Max(p => p.Left + p.GetItemWidth());
+ var maxbottom = designerItems.OfType().Max(p => p.Top + p.GetItemHeight());
var itemswidth = maxright - minleft;
var itemsheight = maxbottom - mintop;
@@ -662,6 +725,7 @@ namespace AIStudio.Wpf.DiagramDesigner
else
{
itemBase = Activator.CreateInstance(dragObject.ContentType) as DesignerItemViewModelBase;
+ itemBase.Text = dragObject.Text;
itemBase.Icon = dragObject.Icon;
itemBase.ColorViewModel = CopyHelper.Mapper(dragObject.ColorViewModel);
if (dragObject.DesiredSize != null)
@@ -669,28 +733,42 @@ namespace AIStudio.Wpf.DiagramDesigner
itemBase.ItemWidth = dragObject.DesiredSize.Value.Width;
itemBase.ItemHeight = dragObject.DesiredSize.Value.Height;
}
+ if (dragObject.DesiredMinSize != null)
+ {
+ itemBase.MinItemWidth = dragObject.DesiredMinSize.Value.Width;
+ itemBase.MinItemHeight = dragObject.DesiredMinSize.Value.Height;
+ }
+
}
- itemBase.Left = Math.Max(0, position.X - itemBase.ItemWidth / 2);
- itemBase.Top = Math.Max(0, position.Y - itemBase.ItemHeight / 2);
+ itemBase.Left = Math.Max(0, position.X - itemBase.GetItemWidth() / 2);
+ itemBase.Top = Math.Max(0, position.Y - itemBase.GetItemHeight() / 2);
_viewModel.AddCommand.Execute(itemBase);
+
+ if (itemBase is BlockDesignerItemViewModel block)
+ {
+ _viewModel.FinishNearBlock(new System.Collections.Generic.List { block });
+ }
}
}
- var dragFile = e.Data.GetData(DataFormats.FileDrop);
- if (dragFile != null && dragFile is string[] files)
+ else
{
- foreach (var file in files)
+ var dragFile = e.Data.GetData(DataFormats.FileDrop);
+ if (dragFile != null && dragFile is string[] files)
{
- _viewModel.ClearSelectedItems();
- Point position = e.GetPosition(this);
- ImageItemViewModel itemBase = new ImageItemViewModel();
- itemBase.Icon = file;
- itemBase.Suffix = System.IO.Path.GetExtension(itemBase.Icon).ToLower();
- itemBase.InitWidthAndHeight();
- itemBase.AutoSize();
+ foreach (var file in files)
+ {
+ _viewModel.ClearSelectedItems();
+ Point position = e.GetPosition(this);
+ ImageItemViewModel itemBase = new ImageItemViewModel();
+ itemBase.Icon = file;
+ itemBase.Suffix = System.IO.Path.GetExtension(itemBase.Icon).ToLower();
+ itemBase.InitWidthAndHeight();
+ itemBase.AutoSize();
- itemBase.Left = Math.Max(0, position.X - itemBase.ItemWidth / 2);
- itemBase.Top = Math.Max(0, position.Y - itemBase.ItemHeight / 2);
- _viewModel.AddCommand.Execute(itemBase);
+ itemBase.Left = Math.Max(0, position.X - itemBase.GetItemWidth() / 2);
+ itemBase.Top = Math.Max(0, position.Y - itemBase.GetItemHeight() / 2);
+ _viewModel.AddCommand.Execute(itemBase);
+ }
}
}
e.Handled = true;
diff --git a/AIStudio.Wpf.DiagramDesigner/Controls/DragThumb.cs b/AIStudio.Wpf.DiagramDesigner/Controls/DragThumb.cs
index a5a563c..e734321 100644
--- a/AIStudio.Wpf.DiagramDesigner/Controls/DragThumb.cs
+++ b/AIStudio.Wpf.DiagramDesigner/Controls/DragThumb.cs
@@ -21,10 +21,7 @@ namespace AIStudio.Wpf.DiagramDesigner.Controls
public IDiagramViewModel DiagramViewModel
{
- get
- {
- return (this.DataContext as SelectableDesignerItemViewModelBase)?.Root;
- }
+ get;set;
}
private List designerItems;
@@ -35,6 +32,7 @@ namespace AIStudio.Wpf.DiagramDesigner.Controls
drag = false;
SelectableDesignerItemViewModelBase designerItem = this.DataContext as SelectableDesignerItemViewModelBase;
+ DiagramViewModel = designerItem?.Root;
if (designerItem != null && designerItem.IsSelected)
{
@@ -99,47 +97,9 @@ namespace AIStudio.Wpf.DiagramDesigner.Controls
var blocks = designerItems.OfType().ToList();
if (blocks.Any())
{
- foreach (BlockDesignerItemViewModel item in blocks)
- {
- var portTuple = DiagramViewModel.FindNearPortToAttachTo(item, true);
- var portParent = portTuple.Item1;
- var portNext = portTuple.Item2;
-
- if (portParent != null)
- {
- (portParent.DataItem as BlockDesignerItemViewModel).AddNext(item);
- portParent.BeAttachTo = false;
- portParent.DisableAttachTo = false;
- }
- else
- {
- if (item.Parent != null)
- {
- (item.Parent as BlockDesignerItemViewModel).Next = null;
- item.Parent = null;
- item.ParentId = new Guid();
- }
- }
-
- if (portNext != null)
- {
- item.AddNext(portNext.DataItem as BlockDesignerItemViewModel);
- portNext.BeAttachTo = false;
- portNext.DisableAttachTo = false;
- }
- else
- {
- if (item.Next != null)
- {
- item.Next.Parent = null;
- item.Next.ParentId = new Guid();
- item.Next = null;
- }
- }
- }
- //-DiagramViewModel.ClearNearPort();
+ DiagramViewModel.FinishNearBlock(blocks);
}
-
+
Dictionary> infos =
designerItems.OfType().ToDictionary(p => p,
p => new Tuple(p.GetOldValue(nameof(p.TopLeft)), p.TopLeft));
@@ -207,14 +167,8 @@ namespace AIStudio.Wpf.DiagramDesigner.Controls
}
var blocks = designerItems.OfType().ToList();
- if (blocks.Any())
- {
- DiagramViewModel.ClearNearPort();
- foreach (BlockDesignerItemViewModel item in blocks)
- {
- DiagramViewModel.FindNearPortToAttachTo(item, false);
- }
- }
+ DiagramViewModel.PreviewNearBlock(blocks);
+
e.Handled = true;
}
}
diff --git a/AIStudio.Wpf.DiagramDesigner/Controls/ItemsContainer.cs b/AIStudio.Wpf.DiagramDesigner/Controls/ItemsContainer.cs
new file mode 100644
index 0000000..a2e4ac8
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner/Controls/ItemsContainer.cs
@@ -0,0 +1,200 @@
+using System;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows.Media;
+using AIStudio.Wpf.DiagramDesigner.Helpers;
+
+namespace AIStudio.Wpf.DiagramDesigner
+{
+ public class ItemsContainer : ContentControl
+ {
+ static ItemsContainer()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(ItemsContainer), new FrameworkPropertyMetadata(typeof(ItemsContainer)));
+ }
+
+ public static readonly DependencyProperty BorderProperty = DependencyProperty.Register(
+ nameof(Border), typeof(object), typeof(ItemsContainer), new PropertyMetadata(default(object)));
+
+ public object Border
+ {
+ get => GetValue(BorderProperty);
+ set => SetValue(BorderProperty, value);
+ }
+
+ public static readonly DependencyProperty BorderTemplateProperty = DependencyProperty.Register(
+ nameof(BorderTemplate), typeof(DataTemplate), typeof(ItemsContainer), new PropertyMetadata(default(DataTemplate)));
+
+ [Bindable(true), Category("Content")]
+ public DataTemplate BorderTemplate
+ {
+ get => (DataTemplate)GetValue(BorderTemplateProperty);
+ set => SetValue(BorderTemplateProperty, value);
+ }
+
+ public static readonly DependencyProperty BorderTemplateSelectorProperty = DependencyProperty.Register(
+ nameof(BorderTemplateSelector), typeof(DataTemplateSelector), typeof(ItemsContainer), new PropertyMetadata(default(DataTemplateSelector)));
+
+ [Bindable(true), Category("Content")]
+ public DataTemplateSelector BorderTemplateSelector
+ {
+ get => (DataTemplateSelector)GetValue(BorderTemplateSelectorProperty);
+ set => SetValue(BorderTemplateSelectorProperty, value);
+ }
+
+ public static readonly DependencyProperty BorderStringFormatProperty = DependencyProperty.Register(
+ nameof(BorderStringFormat), typeof(string), typeof(ItemsContainer), new PropertyMetadata(default(string)));
+
+ [Bindable(true), Category("Content")]
+ public string BorderStringFormat
+ {
+ get => (string)GetValue(BorderStringFormatProperty);
+ set => SetValue(BorderStringFormatProperty, value);
+ }
+
+
+ public static readonly DependencyProperty ParentPanelProperty =
+ DependencyProperty.Register(nameof(ParentPanel), typeof(FrameworkElement), typeof(ItemsContainer),
+ new FrameworkPropertyMetadata(null));
+
+ public FrameworkElement ParentPanel
+ {
+ get
+ {
+ return (FrameworkElement)GetValue(ParentPanelProperty);
+ }
+ set
+ {
+ SetValue(ParentPanelProperty, value);
+ }
+ }
+
+ public static readonly DependencyProperty GetOffSetFuncProperty =
+ DependencyProperty.Register(nameof(GetOffSetFunc),
+ typeof(Func),
+ typeof(ItemsContainer),
+ new FrameworkPropertyMetadata(null));
+ public Func GetOffSetFunc
+ {
+ get
+ {
+ return (Func)this.GetValue(GetOffSetFuncProperty);
+ }
+ set
+ {
+ this.SetValue(GetOffSetFuncProperty, value);
+ }
+ }
+
+ public Func GetOffSet
+ {
+ get
+ {
+ return new Func(() => this.TransformToAncestor(ParentPanel).Transform(new Point(0, 0)));
+ }
+ }
+
+ public ItemsContainerInfo Info
+ {
+ get
+ {
+ if (Border is ItemsContainerInfo itemsContainerInfo)
+ return itemsContainerInfo;
+
+ return this.DataContext as ItemsContainerInfo;
+ }
+ }
+
+ public BlockDesignerItemViewModel DragObject
+ {
+ get; private set;
+ }
+
+ public Point DragOffset
+ {
+ get; private set;
+ }
+
+ public ItemsContainer()
+ {
+
+ }
+
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ GetOffSetFunc = GetOffSet;
+ }
+
+ Point? firstPoint;
+ protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
+ {
+ base.OnMouseLeftButtonDown(e);
+ firstPoint = e.GetPosition(this);
+ }
+
+ protected override void OnMouseMove(MouseEventArgs e)
+ {
+ base.OnMouseMove(e);
+
+ if (firstPoint != null)
+ {
+ var currentPoint = e.GetPosition(this);
+ if (Math.Sqrt(Math.Pow(firstPoint.Value.X - currentPoint.X, 2) + Math.Pow(firstPoint.Value.Y - currentPoint.Y, 2)) > 5)
+ {
+ if (Info?.Children?.Count > 0)
+ {
+ var borders = VisualHelper.FindVisualChildren(this);
+ foreach (var border in borders)
+ {
+ var point = border.TransformToAncestor(this).Transform(new Point(0, 0));
+ var rect = new Rect(point.X, point.Y, border.ActualWidth, border.ActualHeight);
+ if (rect.Contains(currentPoint))
+ {
+ DragObject = border.DataContext as BlockDesignerItemViewModel;
+ DragOffset = new Point(currentPoint.X - point.X, currentPoint.Y - point.Y);
+ break;
+ }
+ }
+
+ if (DragObject != null)
+ {
+ DesignerCanvas canvas = GetDesignerCanvas(this);
+ if (canvas != null)
+ {
+ canvas.SourceItemsContainer = this;
+ }
+ }
+ }
+ firstPoint = null;
+ }
+ }
+ }
+ protected override void OnMouseUp(MouseButtonEventArgs e)
+ {
+ base.OnMouseUp(e);
+
+ firstPoint = null;
+ DragObject = null;
+ }
+
+ public ConnectorOrientation Orientation
+ {
+ get; set;
+ }
+
+ // iterate through visual tree to get parent DesignerCanvas
+ private DesignerCanvas GetDesignerCanvas(DependencyObject element)
+ {
+ while (element != null && !(element is DesignerCanvas))
+ element = VisualTreeHelper.GetParent(element);
+
+ return element as DesignerCanvas;
+ }
+
+ }
+}
diff --git a/AIStudio.Wpf.DiagramDesigner/Controls/ResizeThumb.cs b/AIStudio.Wpf.DiagramDesigner/Controls/ResizeThumb.cs
index dcae788..86d0158 100644
--- a/AIStudio.Wpf.DiagramDesigner/Controls/ResizeThumb.cs
+++ b/AIStudio.Wpf.DiagramDesigner/Controls/ResizeThumb.cs
@@ -95,13 +95,13 @@ namespace AIStudio.Wpf.DiagramDesigner.Controls
{
case VerticalAlignment.Bottom:
dragDeltaVertical = Math.Min(-e.VerticalChange, minDeltaVertical);
- scale = (item.ItemHeight - dragDeltaVertical) / item.ItemHeight;
+ scale = (item.GetItemHeight() - dragDeltaVertical) / item.GetItemHeight();
DragBottom(scale, item, DiagramViewModel.SelectionService);
break;
case VerticalAlignment.Top:
double top = item.Top;
dragDeltaVertical = Math.Min(Math.Max(-minTop, e.VerticalChange), minDeltaVertical);
- scale = (item.ItemHeight - dragDeltaVertical) / item.ItemHeight;
+ scale = (item.GetItemHeight() - dragDeltaVertical) / item.GetItemHeight();
DragTop(scale, item, DiagramViewModel.SelectionService);
break;
default:
@@ -113,12 +113,12 @@ namespace AIStudio.Wpf.DiagramDesigner.Controls
case HorizontalAlignment.Left:
double left = item.Left;
dragDeltaHorizontal = Math.Min(Math.Max(-minLeft, e.HorizontalChange), minDeltaHorizontal);
- scale = (item.ItemWidth - dragDeltaHorizontal) / item.ItemWidth;
+ scale = (item.GetItemWidth() - dragDeltaHorizontal) / item.GetItemWidth();
DragLeft(scale, item, DiagramViewModel.SelectionService);
break;
case HorizontalAlignment.Right:
dragDeltaHorizontal = Math.Min(-e.HorizontalChange, minDeltaHorizontal);
- scale = (item.ItemWidth - dragDeltaHorizontal) / item.ItemWidth;
+ scale = (item.GetItemWidth() - dragDeltaHorizontal) / item.GetItemWidth();
DragRight(scale, item, DiagramViewModel.SelectionService);
break;
default:
@@ -137,26 +137,26 @@ namespace AIStudio.Wpf.DiagramDesigner.Controls
{
IEnumerable groupItems = selectionService.GetGroupMembers(item, false).Cast();
- double groupLeft = item.Left + item.ItemWidth;
+ double groupLeft = item.Left + item.GetItemWidth();
foreach (DesignerItemViewModelBase groupItem in groupItems)
{
double groupItemLeft = groupItem.Left;
double delta = (groupLeft - groupItemLeft) * (scale - 1);
groupItem.Left = groupItemLeft - delta;
- groupItem.ItemWidth = groupItem.ItemWidth * scale;
+ groupItem.ItemWidth = groupItem.GetItemWidth() * scale;
}
}
private void DragTop(double scale, DesignerItemViewModelBase item, SelectionService selectionService)
{
IEnumerable groupItems = selectionService.GetGroupMembers(item, false).Cast();
- double groupBottom = item.Top + item.ItemHeight;
+ double groupBottom = item.Top + item.GetItemHeight();
foreach (DesignerItemViewModelBase groupItem in groupItems)
{
double groupItemTop = groupItem.Top;
double delta = (groupBottom - groupItemTop) * (scale - 1);
groupItem.Top = groupItemTop - delta;
- groupItem.ItemHeight = groupItem.ItemHeight * scale;
+ groupItem.ItemHeight = groupItem.GetItemHeight() * scale;
}
}
@@ -171,7 +171,7 @@ namespace AIStudio.Wpf.DiagramDesigner.Controls
double delta = (groupItemLeft - groupLeft) * (scale - 1);
groupItem.Left = groupItemLeft + delta;
- groupItem.ItemWidth = groupItem.ItemWidth * scale;
+ groupItem.ItemWidth = groupItem.GetItemWidth() * scale;
}
}
@@ -185,7 +185,7 @@ namespace AIStudio.Wpf.DiagramDesigner.Controls
double delta = (groupItemTop - groupTop) * (scale - 1);
groupItem.Top = groupItemTop + delta;
- groupItem.ItemHeight = groupItem.ItemHeight * scale;
+ groupItem.ItemHeight = groupItem.GetItemHeight() * scale;
}
}
diff --git a/AIStudio.Wpf.DiagramDesigner/Controls/RotateThumb.cs b/AIStudio.Wpf.DiagramDesigner/Controls/RotateThumb.cs
index 80ac038..25ae658 100644
--- a/AIStudio.Wpf.DiagramDesigner/Controls/RotateThumb.cs
+++ b/AIStudio.Wpf.DiagramDesigner/Controls/RotateThumb.cs
@@ -53,8 +53,8 @@ namespace AIStudio.Wpf.DiagramDesigner.Controls
if (this.designerCanvas != null)
{
this.centerPoint =
- new Point(this.designerItem.Left + this.designerItem.ItemWidth * 0.5,
- this.designerItem.Top + this.designerItem.ItemHeight * 0.5);
+ new Point(this.designerItem.Left + this.designerItem.GetItemHeight() * 0.5,
+ this.designerItem.Top + this.designerItem.GetItemHeight() * 0.5);
Point startPoint = Mouse.GetPosition(this.designerCanvas);
this.startVector = Point.Subtract(startPoint, this.centerPoint);
diff --git a/AIStudio.Wpf.DiagramDesigner/Enums/DiagramType.cs b/AIStudio.Wpf.DiagramDesigner/Enums/DiagramType.cs
index 443564d..dcf24e6 100644
--- a/AIStudio.Wpf.DiagramDesigner/Enums/DiagramType.cs
+++ b/AIStudio.Wpf.DiagramDesigner/Enums/DiagramType.cs
@@ -12,6 +12,7 @@ namespace AIStudio.Wpf.DiagramDesigner
SFC,
Mind,
Script,
- Drawing
+ Drawing,
+ Block
}
}
diff --git a/AIStudio.Wpf.DiagramDesigner/Geometrys/PointBase.cs b/AIStudio.Wpf.DiagramDesigner/Geometrys/PointBase.cs
index 2ac36aa..9e30444 100644
--- a/AIStudio.Wpf.DiagramDesigner/Geometrys/PointBase.cs
+++ b/AIStudio.Wpf.DiagramDesigner/Geometrys/PointBase.cs
@@ -16,6 +16,12 @@ namespace AIStudio.Wpf.DiagramDesigner.Geometrys
_y = y;
}
+ public PointBase(Point point)
+ {
+ _x = point.X;
+ _y = point.Y;
+ }
+
///
/// 中间X
///
diff --git a/AIStudio.Wpf.DiagramDesigner/Helpers/PointHelper.cs b/AIStudio.Wpf.DiagramDesigner/Helpers/PointHelper.cs
index c9645c3..ed84f96 100644
--- a/AIStudio.Wpf.DiagramDesigner/Helpers/PointHelper.cs
+++ b/AIStudio.Wpf.DiagramDesigner/Helpers/PointHelper.cs
@@ -17,8 +17,8 @@ namespace AIStudio.Wpf.DiagramDesigner
var connectorHeight = double.IsNaN(connector.ConnectorHeight) ? 0 : connector.ConnectorHeight;
var left = connector.DataItem.Left;
var top = connector.DataItem.Top;
- var itemWidth = connector.DataItem.ItemWidth;
- var itemHeight = connector.DataItem.ItemHeight;
+ var itemWidth = connector.DataItem.GetItemWidth();
+ var itemHeight = connector.DataItem.GetItemHeight();
if (connector.IsInnerPoint)
{
diff --git a/AIStudio.Wpf.DiagramDesigner/Models/DragObject.cs b/AIStudio.Wpf.DiagramDesigner/Models/DragObject.cs
index 712fbde..74720f2 100644
--- a/AIStudio.Wpf.DiagramDesigner/Models/DragObject.cs
+++ b/AIStudio.Wpf.DiagramDesigner/Models/DragObject.cs
@@ -9,10 +9,33 @@ namespace AIStudio.Wpf.DiagramDesigner
// Wraps info of the dragged object into a class
public class DragObject
{
- public Size? DesiredSize { get; set; }
- public Type ContentType { get; set; }
- public string Icon { get; set; }
- public IColorViewModel ColorViewModel { get; set; }
- public object DesignerItem { get; set; }
+ public Size? DesiredSize
+ {
+ get; set;
+ }
+ public Size? DesiredMinSize
+ {
+ get; set;
+ }
+ public Type ContentType
+ {
+ get; set;
+ }
+ public string Icon
+ {
+ get; set;
+ }
+ public string Text
+ {
+ get; set;
+ }
+ public IColorViewModel ColorViewModel
+ {
+ get; set;
+ }
+ public object DesignerItem
+ {
+ get; set;
+ }
}
}
diff --git a/AIStudio.Wpf.DiagramDesigner/Models/ToolBoxData.cs b/AIStudio.Wpf.DiagramDesigner/Models/ToolBoxData.cs
index 333a6e7..6fafc6c 100644
--- a/AIStudio.Wpf.DiagramDesigner/Models/ToolBoxData.cs
+++ b/AIStudio.Wpf.DiagramDesigner/Models/ToolBoxData.cs
@@ -36,6 +36,10 @@ namespace AIStudio.Wpf.DiagramDesigner
{
get; set;
}
+ public Size? DesiredMinSize
+ {
+ get; set;
+ }
public string Description
{
get; set;
@@ -46,7 +50,7 @@ namespace AIStudio.Wpf.DiagramDesigner
get; set;
}
- public ToolBoxData(string text, string icon, Type type, double width, double height, Size? desiredSize = null, string description = null)
+ public ToolBoxData(string text, string icon, Type type, double width, double height, Size? desiredSize = null, Size? desiredMinSize = null, string description = null)
{
this.Text = text;
this.Icon = icon;
@@ -54,6 +58,7 @@ namespace AIStudio.Wpf.DiagramDesigner
this.Width = width;
this.Height = height;
this.DesiredSize = desiredSize;
+ this.DesiredMinSize = desiredMinSize;
this.ColorViewModel = new ColorViewModel();
this.Description = description;
}
diff --git a/AIStudio.Wpf.DiagramDesigner/Themes/ConnectorItem.xaml b/AIStudio.Wpf.DiagramDesigner/Themes/ConnectorItem.xaml
index 6b5a4ac..aa0855b 100644
--- a/AIStudio.Wpf.DiagramDesigner/Themes/ConnectorItem.xaml
+++ b/AIStudio.Wpf.DiagramDesigner/Themes/ConnectorItem.xaml
@@ -5,7 +5,7 @@
-
+
@@ -70,7 +70,7 @@
-
+
@@ -115,7 +115,7 @@
-
+
@@ -158,6 +158,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AIStudio.Wpf.DiagramDesigner/Themes/DesignerItem.xaml b/AIStudio.Wpf.DiagramDesigner/Themes/DesignerItem.xaml
index c314b4e..fcd5ed0 100644
--- a/AIStudio.Wpf.DiagramDesigner/Themes/DesignerItem.xaml
+++ b/AIStudio.Wpf.DiagramDesigner/Themes/DesignerItem.xaml
@@ -12,6 +12,7 @@
+
@@ -98,14 +99,72 @@
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AIStudio.Wpf.DiagramDesigner/UserControls/ConnectorContainer.xaml.cs b/AIStudio.Wpf.DiagramDesigner/UserControls/ConnectorContainer.xaml.cs
index f1b76c3..e959e21 100644
--- a/AIStudio.Wpf.DiagramDesigner/UserControls/ConnectorContainer.xaml.cs
+++ b/AIStudio.Wpf.DiagramDesigner/UserControls/ConnectorContainer.xaml.cs
@@ -38,8 +38,8 @@ namespace AIStudio.Wpf.DiagramDesigner
var connector = ItemContainerGenerator.ContainerFromItem(item) as ContentPresenter;
if (connector != null)
{
- Canvas.SetLeft(connector, vm.DataItem.ItemWidth * vm.XRatio - vm.ConnectorWidth / 2);
- Canvas.SetTop(connector, vm.DataItem.ItemHeight * vm.YRatio - vm.ConnectorHeight / 2);
+ Canvas.SetLeft(connector, vm.DataItem.GetItemWidth() * vm.XRatio - vm.ConnectorWidth / 2);
+ Canvas.SetTop(connector, vm.DataItem.GetItemHeight() * vm.YRatio - vm.ConnectorHeight / 2);
}
}
diff --git a/AIStudio.Wpf.DiagramDesigner/UserControls/DiagramControl.xaml b/AIStudio.Wpf.DiagramDesigner/UserControls/DiagramControl.xaml
index c52ec44..9e22d2a 100644
--- a/AIStudio.Wpf.DiagramDesigner/UserControls/DiagramControl.xaml
+++ b/AIStudio.Wpf.DiagramDesigner/UserControls/DiagramControl.xaml
@@ -344,25 +344,25 @@
-
-
-
-
+
+
+
@@ -855,16 +861,13 @@
-
-
+
-
-
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/Container/ItemsContainerInfo.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/Container/ItemsContainerInfo.cs
new file mode 100644
index 0000000..8f87660
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/Container/ItemsContainerInfo.cs
@@ -0,0 +1,213 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Windows;
+using System.Windows.Media;
+using AIStudio.Wpf.DiagramDesigner.Geometrys;
+using AIStudio.Wpf.DiagramDesigner.Models;
+
+namespace AIStudio.Wpf.DiagramDesigner
+{
+ public class ItemsContainerInfo : SelectableViewModelBase
+ {
+ public ItemsContainerInfo(BlockDesignerItemViewModel dataItem) : this(null, dataItem)
+ {
+
+ }
+
+ public ItemsContainerInfo(IDiagramViewModel root, BlockDesignerItemViewModel dataItem) : base(root)
+ {
+ this.Parent = dataItem;
+ }
+
+ public ItemsContainerInfo(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
+ {
+
+ }
+
+ public ItemsContainerInfo(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
+ {
+
+ }
+
+ //public override SelectableItemBase GetSerializableObject()
+ //{
+ // return new ConnectorInfoItemBase(this);
+ //}
+
+ protected override void Init(IDiagramViewModel root, bool initNew)
+ {
+ base.Init(root, initNew);
+ }
+
+ protected override void InitNew()
+ {
+ ColorViewModel = new ColorViewModel()
+ {
+ LineWidth = 1,
+ LineColor = new ColorObject() { Color = Color.FromArgb(0xAA, 0x00, 0x00, 0x80) },
+ FillColor = new ColorObject() { Color = Colors.Transparent },
+ };
+ }
+
+ protected override void LoadDesignerItemViewModel(SelectableItemBase designerbase)
+ {
+ base.LoadDesignerItemViewModel(designerbase);
+
+ //if (designerbase is ConnectorInfoItemBase designer)
+ //{
+ // PhysicalConnectorWidth = designer.PhysicalConnectorWidth;
+ // PhysicalConnectorHeight = designer.PhysicalConnectorHeight;
+ // Orientation = designer.Orientation;
+ //}
+ }
+
+ #region 属性
+ private double _itemWidth = double.NaN;
+ public double ItemWidth
+ {
+ get
+ {
+ return _itemWidth;
+ }
+ set
+ {
+ if (value <= 0) return;
+ SetProperty(ref _itemWidth, value);
+ }
+ }
+
+ private double _itemHeight = double.NaN;
+ public double ItemHeight
+ {
+ get
+ {
+ return _itemHeight;
+ }
+ set
+ {
+ if (value <= 0) return;
+ SetProperty(ref _itemHeight, value);
+ }
+ }
+
+ private double _actualItemWidth;
+ public double ActualItemWidth
+ {
+ get
+ {
+ return _actualItemWidth;
+ }
+ set
+ {
+ SetProperty(ref _actualItemWidth, value);
+ }
+ }
+
+ private double _actualItemHeight;
+ public double ActualItemHeight
+ {
+ get
+ {
+ return _actualItemHeight;
+ }
+ set
+ {
+ SetProperty(ref _actualItemHeight, value);
+ }
+ }
+
+ //public PointBase Position
+ //{
+ // get
+ // {
+ // var offset = GetOffSetFunc?.Invoke() ?? new Point(0, 0);
+ // return new PointBase(DataItem.Left + offset.X, DataItem.Top + offset.Y);
+ // }
+ //}
+
+ //public PointBase MiddlePosition
+ //{
+ // get
+ // {
+ // return new PointBase(Position.X + GetItemWidth() / 2, Position.Y + GetItemHeight() / 2);
+ // }
+ //}
+
+ public RectangleBase GetBounds()
+ {
+ var offset = GetOffSetFunc?.Invoke() ?? new Point(0, 0);
+
+ return new RectangleBase(DataItem.Left + offset.X, DataItem.Top + offset.Y, GetItemWidth(), GetItemHeight());
+ }
+
+ public BlockDesignerItemViewModel DataItem
+ {
+ get
+ {
+ return Parent as BlockDesignerItemViewModel;
+ }
+ }
+
+ public ObservableCollection Children
+ {
+ get; set;
+ } = new ObservableCollection();
+
+
+ private Func _getOffSetFunc;
+ public Func GetOffSetFunc
+ {
+ get
+ {
+ return _getOffSetFunc;
+ }
+ set
+ {
+ SetProperty(ref _getOffSetFunc, value);
+ }
+ }
+
+ private bool _beAttachTo;
+ public bool BeAttachTo
+ {
+ get
+ {
+ return _beAttachTo;
+ }
+ set
+ {
+ SetProperty(ref _beAttachTo, value);
+ }
+ }
+
+ private bool _disableAttachTo;
+ public bool DisableAttachTo
+ {
+ get
+ {
+ return _disableAttachTo;
+ }
+ set
+ {
+ SetProperty(ref _disableAttachTo, value);
+ }
+ }
+
+ public virtual bool CanAttachTo(DesignerItemViewModelBase item)
+ => item != null && item != this.DataItem && !item.IsReadOnly && item is BlockDesignerItemViewModel;
+ #endregion
+
+ public double GetItemWidth()
+ {
+ return double.IsNaN(ItemWidth) ? ActualItemWidth : ItemWidth;
+ }
+
+ public double GetItemHeight()
+ {
+ return double.IsNaN(ItemHeight) ? ActualItemHeight : ItemHeight;
+ }
+ }
+}
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DesignerItemViewModelBase.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DesignerItemViewModelBase.cs
index 5637f32..02c4501 100644
--- a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DesignerItemViewModelBase.cs
+++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DesignerItemViewModelBase.cs
@@ -261,7 +261,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{
get
{
- return new SizeBase(ItemWidth, ItemHeight);
+ return new SizeBase(GetItemWidth(), GetItemHeight());
}
set
{
@@ -445,7 +445,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{
get
{
- return new Point(Left + ItemWidth, Top + ItemHeight);
+ return new Point(Left + GetItemWidth(), Top + GetItemHeight());
}
}
@@ -557,6 +557,32 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
+ private double _actualItemWidth;
+ public double ActualItemWidth
+ {
+ get
+ {
+ return _actualItemWidth;
+ }
+ set
+ {
+ SetProperty(ref _actualItemWidth, value);
+ }
+ }
+
+ private double _actualItemHeight;
+ public double ActualItemHeight
+ {
+ get
+ {
+ return _actualItemHeight;
+ }
+ set
+ {
+ SetProperty(ref _actualItemHeight, value);
+ }
+ }
+
///
/// 连接点是否可以按偏移自定义
///
@@ -637,9 +663,9 @@ namespace AIStudio.Wpf.DiagramDesigner
{
if (Root.DiagramOption.LayoutOption.CellHorizontalAlignment == CellHorizontalAlignment.Center)
{
- if (Root.DiagramOption.LayoutOption.GridCellSize.Width > this.ItemWidth)
+ if (Root.DiagramOption.LayoutOption.GridCellSize.Width > this.GetItemWidth())
{
- this.Left = (int)(this.Left / Root.DiagramOption.LayoutOption.GridCellSize.Width) * Root.DiagramOption.LayoutOption.GridCellSize.Width + Root.DiagramOption.LayoutOption.GridMarginSize.Width + (Root.DiagramOption.LayoutOption.GridCellSize.Width - this.ItemWidth) / 2;
+ this.Left = (int)(this.Left / Root.DiagramOption.LayoutOption.GridCellSize.Width) * Root.DiagramOption.LayoutOption.GridCellSize.Width + Root.DiagramOption.LayoutOption.GridMarginSize.Width + (Root.DiagramOption.LayoutOption.GridCellSize.Width - this.GetItemWidth()) / 2;
}
}
else if (Root.DiagramOption.LayoutOption.CellHorizontalAlignment == CellHorizontalAlignment.Left)
@@ -648,17 +674,17 @@ namespace AIStudio.Wpf.DiagramDesigner
}
else if (Root.DiagramOption.LayoutOption.CellHorizontalAlignment == CellHorizontalAlignment.Right)
{
- if (Root.DiagramOption.LayoutOption.GridCellSize.Width > this.ItemWidth)
+ if (Root.DiagramOption.LayoutOption.GridCellSize.Width > this.GetItemWidth())
{
- this.Left = (int)(this.Left / Root.DiagramOption.LayoutOption.GridCellSize.Width) * Root.DiagramOption.LayoutOption.GridCellSize.Width + Root.DiagramOption.LayoutOption.GridMarginSize.Width + (Root.DiagramOption.LayoutOption.GridCellSize.Width - this.ItemWidth);
+ this.Left = (int)(this.Left / Root.DiagramOption.LayoutOption.GridCellSize.Width) * Root.DiagramOption.LayoutOption.GridCellSize.Width + Root.DiagramOption.LayoutOption.GridMarginSize.Width + (Root.DiagramOption.LayoutOption.GridCellSize.Width - this.GetItemWidth());
}
}
if (Root.DiagramOption.LayoutOption.CellVerticalAlignment == CellVerticalAlignment.Center)
{
- if (Root.DiagramOption.LayoutOption.GridCellSize.Height > this.ItemHeight)
+ if (Root.DiagramOption.LayoutOption.GridCellSize.Height > this.GetItemHeight())
{
- this.Top = (int)(this.Top / Root.DiagramOption.LayoutOption.GridCellSize.Height) * Root.DiagramOption.LayoutOption.GridCellSize.Height + Root.DiagramOption.LayoutOption.GridMarginSize.Height + (Root.DiagramOption.LayoutOption.GridCellSize.Height - this.ItemHeight) / 2;
+ this.Top = (int)(this.Top / Root.DiagramOption.LayoutOption.GridCellSize.Height) * Root.DiagramOption.LayoutOption.GridCellSize.Height + Root.DiagramOption.LayoutOption.GridMarginSize.Height + (Root.DiagramOption.LayoutOption.GridCellSize.Height - this.GetItemHeight()) / 2;
}
}
else if (Root.DiagramOption.LayoutOption.CellVerticalAlignment == CellVerticalAlignment.Top)
@@ -667,9 +693,9 @@ namespace AIStudio.Wpf.DiagramDesigner
}
else if (Root.DiagramOption.LayoutOption.CellVerticalAlignment == CellVerticalAlignment.Bottom)
{
- if (Root.DiagramOption.LayoutOption.GridCellSize.Height > this.ItemHeight)
+ if (Root.DiagramOption.LayoutOption.GridCellSize.Height > this.GetItemHeight())
{
- this.Top = (int)(this.Top / Root.DiagramOption.LayoutOption.GridCellSize.Height) * Root.DiagramOption.LayoutOption.GridCellSize.Height + Root.DiagramOption.LayoutOption.GridMarginSize.Height + (Root.DiagramOption.LayoutOption.GridCellSize.Height - this.ItemHeight);
+ this.Top = (int)(this.Top / Root.DiagramOption.LayoutOption.GridCellSize.Height) * Root.DiagramOption.LayoutOption.GridCellSize.Height + Root.DiagramOption.LayoutOption.GridMarginSize.Height + (Root.DiagramOption.LayoutOption.GridCellSize.Height - this.GetItemHeight());
}
}
}
@@ -740,14 +766,24 @@ namespace AIStudio.Wpf.DiagramDesigner
var left = leftPort == null ? Position.X : Math.Min(Position.X, leftPort.Position.X);
var top = topPort == null ? Position.Y : Math.Min(Position.Y, topPort.Position.Y);
- var right = rightPort == null ? Position.X + ItemWidth :
- Math.Max(rightPort.Position.X + rightPort.ConnectorWidth, Position.X + ItemWidth);
+ var right = rightPort == null ? Position.X + GetItemWidth() :
+ Math.Max(rightPort.Position.X + rightPort.ConnectorWidth, Position.X + GetItemWidth());
var bottom = bottomPort == null ? Position.Y + ItemHeight :
- Math.Max(bottomPort.Position.Y + bottomPort.ConnectorHeight, Position.Y + ItemHeight);
+ Math.Max(bottomPort.Position.Y + bottomPort.ConnectorHeight, Position.Y + GetItemHeight());
return new RectangleBase(left, top, right, bottom, true);
}
+ public double GetItemWidth()
+ {
+ return double.IsNaN(ItemWidth) ? ActualItemWidth : ItemWidth;
+ }
+
+ public double GetItemHeight()
+ {
+ return double.IsNaN(ItemHeight) ? ActualItemHeight : ItemHeight;
+ }
+
public IShape GetShape() => ShapeDefiner(this);
public override string ToString()
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModel.cs
index 83f3d69..7a2bc4f 100644
--- a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModel.cs
+++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModel.cs
@@ -1449,7 +1449,7 @@ namespace AIStudio.Wpf.DiagramDesigner
return items;
}
- protected void ExecuteDeleteCommand(object parameter)
+ protected virtual void ExecuteDeleteCommand(object parameter)
{
var items = Delete(parameter, false);
if (items.Any())
@@ -1580,11 +1580,11 @@ namespace AIStudio.Wpf.DiagramDesigner
DoCommandManager.DoNewCommand(this.ToString(),
() => {
- double mid = selectedItems.Select(p => p.Top + p.ItemHeight / 2).Average();
+ double mid = selectedItems.Select(p => p.Top + p.GetItemHeight() / 2).Average();
foreach (DesignerItemViewModelBase item in selectedItems)
{
- item.Top = mid - item.ItemHeight / 2;
+ item.Top = mid - item.GetItemHeight() / 2;
}
},
() => {
@@ -1618,11 +1618,11 @@ namespace AIStudio.Wpf.DiagramDesigner
DoCommandManager.DoNewCommand(this.ToString(),
() => {
- double top = selectedItems.OrderBy(p => p.Top + p.ItemHeight).Select(p => p.Top + p.ItemHeight).LastOrDefault();
+ double top = selectedItems.OrderBy(p => p.Top + p.GetItemHeight()).Select(p => p.Top + p.GetItemHeight()).LastOrDefault();
foreach (DesignerItemViewModelBase item in selectedItems)
{
- item.Top = top - item.ItemHeight;
+ item.Top = top - item.GetItemHeight();
}
},
() => {
@@ -1694,11 +1694,11 @@ namespace AIStudio.Wpf.DiagramDesigner
DoCommandManager.DoNewCommand(this.ToString(),
() => {
- double mid = selectedItems.Select(p => p.Left + p.ItemWidth / 2).Average();
+ double mid = selectedItems.Select(p => p.Left + p.GetItemWidth() / 2).Average();
foreach (DesignerItemViewModelBase item in selectedItems)
{
- item.Left = mid - item.ItemWidth / 2;
+ item.Left = mid - item.GetItemWidth() / 2;
}
},
() => {
@@ -1732,11 +1732,11 @@ namespace AIStudio.Wpf.DiagramDesigner
DoCommandManager.DoNewCommand(this.ToString(),
() => {
- double right = selectedItems.OrderBy(p => p.Left + p.ItemWidth).Select(p => p.Left + p.ItemWidth).LastOrDefault();
+ double right = selectedItems.OrderBy(p => p.Left + p.GetItemWidth()).Select(p => p.Left + p.GetItemWidth()).LastOrDefault();
foreach (DesignerItemViewModelBase item in selectedItems)
{
- item.Left = right - item.ItemWidth;
+ item.Left = right - item.GetItemWidth();
}
},
() => {
@@ -1975,8 +1975,8 @@ namespace AIStudio.Wpf.DiagramDesigner
foreach (DesignerItemViewModelBase item in selectedItems)
{
left = Math.Min(left, item.Left);
- right = Math.Max(right, item.Left + item.ItemWidth);
- sumWidth += item.ItemWidth;
+ right = Math.Max(right, item.Left + item.GetItemWidth());
+ sumWidth += item.GetItemWidth();
}
double distance = Math.Max(0, (right - left - sumWidth) / (selectedItems.Count() - 1));
@@ -1989,7 +1989,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{
di.Left += delta;
}
- offset = offset + item.ItemWidth + distance;
+ offset = offset + item.GetItemWidth() + distance;
}
},
@@ -2030,8 +2030,8 @@ namespace AIStudio.Wpf.DiagramDesigner
foreach (DesignerItemViewModelBase item in selectedItems)
{
top = Math.Min(top, item.Top);
- bottom = Math.Max(bottom, item.Top + item.ItemHeight);
- sumHeight += item.ItemHeight;
+ bottom = Math.Max(bottom, item.Top + item.GetItemHeight());
+ sumHeight += item.GetItemHeight();
}
double distance = Math.Max(0, (bottom - top - sumHeight) / (selectedItems.Count() - 1));
@@ -2044,7 +2044,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{
di.Top += +delta;
}
- offset = offset + item.ItemHeight + distance;
+ offset = offset + item.GetItemHeight() + distance;
}
},
() => {
@@ -2264,8 +2264,8 @@ namespace AIStudio.Wpf.DiagramDesigner
() => {
foreach (var item in selectedItems)
{
- item.ItemWidth = selectedItems.FirstOrDefault().ItemWidth;
- item.ItemHeight = selectedItems.FirstOrDefault().ItemHeight;
+ item.ItemWidth = selectedItems.FirstOrDefault().GetItemWidth();
+ item.ItemHeight = selectedItems.FirstOrDefault().GetItemHeight();
}
},
() => {
@@ -2295,13 +2295,13 @@ namespace AIStudio.Wpf.DiagramDesigner
if (selectedItems.Count > 1)
{
- Dictionary infos = selectedItems.ToDictionary(p => p, p => p.ItemWidth);
+ Dictionary infos = selectedItems.ToDictionary(p => p, p => p.GetItemWidth());
DoCommandManager.DoNewCommand(this.ToString(),
() => {
foreach (var item in selectedItems)
{
- item.ItemWidth = selectedItems.FirstOrDefault().ItemWidth;
+ item.ItemWidth = selectedItems.FirstOrDefault().GetItemWidth();
}
},
() => {
@@ -2331,13 +2331,13 @@ namespace AIStudio.Wpf.DiagramDesigner
if (selectedItems.Count > 1)
{
- Dictionary infos = selectedItems.ToDictionary(p => p, p => p.ItemHeight);
+ Dictionary infos = selectedItems.ToDictionary(p => p, p => p.GetItemHeight());
DoCommandManager.DoNewCommand(this.ToString(),
() => {
foreach (var item in selectedItems)
{
- item.ItemHeight = selectedItems.FirstOrDefault().ItemHeight;
+ item.ItemHeight = selectedItems.FirstOrDefault().GetItemHeight();
}
},
() => {
@@ -3145,6 +3145,37 @@ namespace AIStudio.Wpf.DiagramDesigner
return new Tuple(parent, next);
}
+ public ItemsContainerInfo FindNearContainerToAttachTo(BlockDesignerItemViewModel blockDesignerItemViewModel)
+ {
+ if (blockDesignerItemViewModel == null)
+ return null;
+
+ List items;
+
+ items = Items.OfType().
+ Where(p => p != blockDesignerItemViewModel)
+ .ToList();
+
+ foreach (var port in items.SelectMany(n => n.Contains))
+ {
+ if (port.GetBounds().IntersectsWith(blockDesignerItemViewModel.GetBounds())) //如果两个位置相交
+ {
+ port.DataItem.ShowConnectors = true;
+ if (port.CanAttachTo(blockDesignerItemViewModel) == true)
+ {
+ port.BeAttachTo = true;
+ }
+ else
+ {
+ port.DisableAttachTo = true;
+ }
+ return port;
+ }
+ }
+
+ return null;
+ }
+
public void ClearNearPort()
{
Items.OfType().ToList().SelectMany(n => n.Connectors).Where(p => p.BeAttachTo == true || p.DisableAttachTo == true).ToList()
@@ -3152,6 +3183,91 @@ namespace AIStudio.Wpf.DiagramDesigner
p.DisableAttachTo = false;
p.BeAttachTo = false;
});
+
+
+ }
+
+ public void ClearNearContain()
+ {
+ Items.OfType().ToList().SelectMany(n => n.Contains).Where(p => p.BeAttachTo == true || p.DisableAttachTo == true).ToList()
+ .ForEach(p => {
+ p.DisableAttachTo = false;
+ p.BeAttachTo = false;
+ });
+ }
+ #endregion
+
+ #region Block拖拽预览-拖拽完成
+ public void PreviewNearBlock(List blocks)
+ {
+ if (blocks.Any())
+ {
+ ClearNearPort();
+ ClearNearContain();
+ foreach (BlockDesignerItemViewModel item in blocks)
+ {
+ var contain = FindNearContainerToAttachTo(item);
+ if (contain != null)
+ {
+ continue;
+ }
+ FindNearPortToAttachTo(item, false);
+ }
+ }
+ }
+
+
+
+ public void FinishNearBlock(List blocks)
+ {
+ if (blocks.Any())
+ {
+ ClearNearPort();
+ ClearNearContain();
+ foreach (BlockDesignerItemViewModel item in blocks)
+ {
+ var contain = FindNearContainerToAttachTo(item);
+ if (contain != null)
+ {
+ (contain.DataItem as BlockDesignerItemViewModel).AddChild(item);
+ contain.BeAttachTo = false;
+ contain.DisableAttachTo = false;
+ continue;
+ }
+
+ var portTuple = FindNearPortToAttachTo(item, true);
+ var portParent = portTuple.Item1;
+ var portNext = portTuple.Item2;
+
+ if (portParent != null)
+ {
+ (portParent.DataItem as BlockDesignerItemViewModel).AddNext(item);
+ portParent.BeAttachTo = false;
+ portParent.DisableAttachTo = false;
+ }
+ else
+ {
+ if (item.Parent != null)
+ {
+ (item.Parent as BlockDesignerItemViewModel).RemoveNext();
+ }
+ }
+
+ if (portNext != null)
+ {
+ item.AddNext(portNext.DataItem as BlockDesignerItemViewModel);
+ portNext.BeAttachTo = false;
+ portNext.DisableAttachTo = false;
+ }
+ else
+ {
+ if (item.Next != null)
+ {
+ item.RemoveNext();
+ }
+ }
+ }
+ }
}
#endregion
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModelHelper.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModelHelper.cs
index 671a529..4ca1dd9 100644
--- a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModelHelper.cs
+++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModelHelper.cs
@@ -26,8 +26,8 @@ namespace AIStudio.Wpf.DiagramDesigner
x1 = Math.Min(item.Left, x1);
y1 = Math.Min(item.Top, y1);
- x2 = Math.Max(item.Left + item.ItemWidth, x2);
- y2 = Math.Max(item.Top + item.ItemHeight, y2);
+ x2 = Math.Max(item.Left + item.GetItemWidth(), x2);
+ y2 = Math.Max(item.Top + item.GetItemHeight(), y2);
}
return new RectangleBase(new PointBase(x1, y1), new PointBase(x2, y2));
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/DefaultViewModel/BlockContainDesignerItemViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/DefaultViewModel/BlockContainDesignerItemViewModel.cs
new file mode 100644
index 0000000..49f05b5
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/DefaultViewModel/BlockContainDesignerItemViewModel.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using AIStudio.Wpf.DiagramDesigner.Models;
+
+namespace AIStudio.Wpf.DiagramDesigner
+{
+ public class BlockContainDesignerItemViewModel : BlockDesignerItemViewModel
+ {
+ public BlockContainDesignerItemViewModel()
+ {
+ }
+
+ public BlockContainDesignerItemViewModel(IDiagramViewModel root) : base(root)
+ {
+ }
+
+ public BlockContainDesignerItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
+ {
+ }
+
+ public BlockContainDesignerItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
+ {
+ }
+
+ protected override void InitNew()
+ {
+ base.InitNew();
+
+ Contains.Add(new ItemsContainerInfo(this.Root, this));
+ }
+
+ public override void AddChild(BlockDesignerItemViewModel child)
+ {
+ var oldchildren = FirstContain.Children.FirstOrDefault();
+ if (oldchildren != null)
+ {
+ this.RemoveChild(oldchildren);
+ }
+
+ Root.Items.Remove(child);
+ FirstContain.Children.Add(child);
+
+ base.AddChild(child);
+ }
+
+ public override void RemoveChild(BlockDesignerItemViewModel child)
+ {
+ Root.Items.Add(child);
+ FirstContain.Children.Remove(child);
+
+ this.RemoveFromSelection();
+ child.AddToSelection(true, false);
+
+ base.RemoveChild(child);
+ }
+ }
+}
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/DefaultViewModel/BlockContainListDesignerItemViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/DefaultViewModel/BlockContainListDesignerItemViewModel.cs
new file mode 100644
index 0000000..e0b9a7b
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/DefaultViewModel/BlockContainListDesignerItemViewModel.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using AIStudio.Wpf.DiagramDesigner.Models;
+
+namespace AIStudio.Wpf.DiagramDesigner
+{
+ public class BlockContainListDesignerItemViewModel : BlockDesignerItemViewModel
+ {
+ public BlockContainListDesignerItemViewModel()
+ {
+ }
+
+ public BlockContainListDesignerItemViewModel(IDiagramViewModel root) : base(root)
+ {
+ }
+
+ public BlockContainListDesignerItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
+ {
+ }
+
+ public BlockContainListDesignerItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
+ {
+ }
+
+ protected override void InitNew()
+ {
+ base.InitNew();
+
+ Contains.Add(new ItemsContainerInfo(this.Root, this));
+ }
+
+ public override void AddChild(BlockDesignerItemViewModel child)
+ {
+ Root.Items.Remove(child);
+ FirstContain.Children.Add(child);
+
+ base.AddChild(child);
+ }
+
+ public override void RemoveChild(BlockDesignerItemViewModel child)
+ {
+ Root.Items.Add(child);
+ FirstContain.Children.Remove(child);
+
+ base.RemoveChild(child);
+ }
+ }
+}
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/DefaultViewModel/BlockDesignerItemViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/DefaultViewModel/BlockDesignerItemViewModel.cs
index 86d2f2a..c203747 100644
--- a/AIStudio.Wpf.DiagramDesigner/ViewModels/DefaultViewModel/BlockDesignerItemViewModel.cs
+++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/DefaultViewModel/BlockDesignerItemViewModel.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -27,28 +28,57 @@ namespace AIStudio.Wpf.DiagramDesigner
protected override void InitNew()
{
+ ItemWidth = double.NaN;
+ ItemHeight = double.NaN;
AddConnector(new BlockConnectorInfo(this.Root, this, ConnectorOrientation.Top));
AddConnector(new BlockConnectorInfo(this.Root, this, ConnectorOrientation.Bottom));
+ IsReadOnlyText = true;
}
public BlockDesignerItemViewModel Next
{
- get;set;
+ get; set;
}
public void AddNext(BlockDesignerItemViewModel next)
{
+ this.ParentId = new Guid();
+ this.Parent = null;
next.Left = this.Left;
- next.Top = this.Top + this.ItemHeight;
+ next.Top = this.Top + this.GetItemHeight();
next.ParentId = this.Id;
next.Parent = this;
this.Next = next;
- if (next.Next != null)
+ //if (oldnext != null)
+ //{
+ // next.AddNext(oldnext);
+ //}
+ }
+
+ public void RemoveNext()
+ {
+ var next = this.Next;
+ if (next != null)
{
- next.AddNext(next.Next);
+ next.ParentId = new Guid();
+ next.Parent = null;
+ this.Next = null;
}
}
+ public BlockDesignerItemViewModel GetLastNext()
+ {
+ var next = this.Next;
+ if (next != null)
+ {
+ while (next.Next != null)
+ {
+ next = next.Next;
+ }
+ }
+ return next;
+ }
+
public override void AddToSelection(bool selected, bool clearother)
{
if (clearother)
@@ -64,5 +94,31 @@ namespace AIStudio.Wpf.DiagramDesigner
IsSelected = selected;
}
+
+
+ public virtual void AddChild(BlockDesignerItemViewModel child)
+ {
+ child.RemoveFromSelection();
+ this.AddToSelection(true, false);
+ }
+
+ public virtual void RemoveChild(BlockDesignerItemViewModel child)
+ {
+ this.RemoveFromSelection();
+ child.AddToSelection(true, false);
+ }
+
+ public ObservableCollection Contains
+ {
+ get; set;
+ } = new ObservableCollection();
+
+ public ItemsContainerInfo FirstContain
+ {
+ get
+ {
+ return Contains?.FirstOrDefault();
+ }
+ }
}
}
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/DefaultViewModel/GifImageItemViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/DefaultViewModel/GifImageItemViewModel.cs
index dad8b97..b3ab989 100644
--- a/AIStudio.Wpf.DiagramDesigner/ViewModels/DefaultViewModel/GifImageItemViewModel.cs
+++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/DefaultViewModel/GifImageItemViewModel.cs
@@ -115,8 +115,8 @@ namespace AIStudio.Wpf.DiagramDesigner
FullyCreatedConnectorInfo connector = new FullyCreatedConnectorInfo(this, ConnectorOrientation.None, true);
MouseButtonEventArgs mosueArg = ((EventToCommandArgs)parameter).EventArgs as MouseButtonEventArgs;
var position = mosueArg.GetPosition(((EventToCommandArgs)parameter).Sender as IInputElement);
- connector.XRatio = (position.X - connector.ConnectorWidth / 2) / connector.DataItem.ItemWidth;
- connector.YRatio = (position.Y - connector.ConnectorHeight / 2) / connector.DataItem.ItemHeight;
+ connector.XRatio = (position.X - connector.ConnectorWidth / 2) / connector.DataItem.GetItemWidth();
+ connector.YRatio = (position.Y - connector.ConnectorHeight / 2) / connector.DataItem.GetItemHeight();
AddConnector(connector);
}
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/IDiagramViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/IDiagramViewModel.cs
index ba861c1..68114cc 100644
--- a/AIStudio.Wpf.DiagramDesigner/ViewModels/IDiagramViewModel.cs
+++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/IDiagramViewModel.cs
@@ -366,7 +366,11 @@ namespace AIStudio.Wpf.DiagramDesigner
FullyCreatedConnectorInfo FindNearPortToAttachTo(ConnectionViewModel partialConnection, ConnectorVertexType connectorVertexType);
FullyCreatedConnectorInfo FindNearPortToAttachTo(ConnectionViewModel partialConnection);
Tuple FindNearPortToAttachTo(BlockDesignerItemViewModel blockDesignerItemViewModel, bool isExist);
+ ItemsContainerInfo FindNearContainerToAttachTo(BlockDesignerItemViewModel blockDesignerItemViewModel);
void ClearNearPort();
+ void ClearNearContain();
+ void PreviewNearBlock(List blocks);
+ void FinishNearBlock(List blocks);
#endregion
event PropertyChangedEventHandler PropertyChanged;
diff --git a/Extensions/AIStudio.Wpf.Block/A.png b/Extensions/AIStudio.Wpf.Block/A.png
new file mode 100644
index 0000000..b6949fa
Binary files /dev/null and b/Extensions/AIStudio.Wpf.Block/A.png differ
diff --git a/Extensions/AIStudio.Wpf.Block/AIStudio.Wpf.Block.csproj b/Extensions/AIStudio.Wpf.Block/AIStudio.Wpf.Block.csproj
new file mode 100644
index 0000000..8c745f5
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/AIStudio.Wpf.Block.csproj
@@ -0,0 +1,26 @@
+
+
+
+ true
+ AIStudio.Wpf.Controls
+ akwkevin
+ https://gitee.com/akwkevin
+ A.png
+
+
+ 1.0.7
+ 一个Wpf的流程图控件
+
+
+
+
+ True
+
+
+
+
+
+
+
+
+
diff --git a/Extensions/AIStudio.Wpf.Block/AIStudio.Wpf.Block_4a4h4ycz_wpftmp.csproj b/Extensions/AIStudio.Wpf.Block/AIStudio.Wpf.Block_4a4h4ycz_wpftmp.csproj
new file mode 100644
index 0000000..b366cc1
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/AIStudio.Wpf.Block_4a4h4ycz_wpftmp.csproj
@@ -0,0 +1,246 @@
+
+
+ AIStudio.Wpf.Block
+ obj\Debug\
+ obj\
+ F:\aistudio.-wpf.-diagram\Extensions\AIStudio.Wpf.Block\obj\
+ <_TargetAssemblyProjectName>AIStudio.Wpf.Block
+
+
+
+ true
+ AIStudio.Wpf.Controls
+ akwkevin
+ https://gitee.com/akwkevin
+ A.png
+
+
+ 1.0.7
+ 一个Wpf的流程图控件
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Extensions/AIStudio.Wpf.Block/AIStudio.Wpf.Block_attaon4q_wpftmp.csproj b/Extensions/AIStudio.Wpf.Block/AIStudio.Wpf.Block_attaon4q_wpftmp.csproj
new file mode 100644
index 0000000..98ee754
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/AIStudio.Wpf.Block_attaon4q_wpftmp.csproj
@@ -0,0 +1,244 @@
+
+
+ AIStudio.Wpf.Block
+ obj\Debug\
+ obj\
+ F:\aistudio.-wpf.-diagram\Extensions\AIStudio.Wpf.Block\obj\
+ <_TargetAssemblyProjectName>AIStudio.Wpf.Block
+
+
+
+ true
+ AIStudio.Wpf.Controls
+ akwkevin
+ https://gitee.com/akwkevin
+ A.png
+
+
+ 1.0.7
+ 一个Wpf的流程图控件
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Extensions/AIStudio.Wpf.Block/AIStudio.Wpf.Block_axsfel0m_wpftmp.csproj b/Extensions/AIStudio.Wpf.Block/AIStudio.Wpf.Block_axsfel0m_wpftmp.csproj
new file mode 100644
index 0000000..18a4093
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/AIStudio.Wpf.Block_axsfel0m_wpftmp.csproj
@@ -0,0 +1,177 @@
+
+
+ AIStudio.Wpf.Block
+ obj\Debug\
+ obj\
+ F:\aistudio.-wpf.-diagram\Extensions\AIStudio.Wpf.Block\obj\
+ <_TargetAssemblyProjectName>AIStudio.Wpf.Block
+
+
+
+ true
+ AIStudio.Wpf.Controls
+ akwkevin
+ https://gitee.com/akwkevin
+ A.png
+
+
+ 1.0.7
+ 一个Wpf的流程图控件
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Extensions/AIStudio.Wpf.Block/AIStudio.Wpf.Block_gkma3gbh_wpftmp.csproj b/Extensions/AIStudio.Wpf.Block/AIStudio.Wpf.Block_gkma3gbh_wpftmp.csproj
new file mode 100644
index 0000000..98ee754
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/AIStudio.Wpf.Block_gkma3gbh_wpftmp.csproj
@@ -0,0 +1,244 @@
+
+
+ AIStudio.Wpf.Block
+ obj\Debug\
+ obj\
+ F:\aistudio.-wpf.-diagram\Extensions\AIStudio.Wpf.Block\obj\
+ <_TargetAssemblyProjectName>AIStudio.Wpf.Block
+
+
+
+ true
+ AIStudio.Wpf.Controls
+ akwkevin
+ https://gitee.com/akwkevin
+ A.png
+
+
+ 1.0.7
+ 一个Wpf的流程图控件
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Extensions/AIStudio.Wpf.Block/AIStudio.Wpf.Block_ohjhbtlx_wpftmp.csproj b/Extensions/AIStudio.Wpf.Block/AIStudio.Wpf.Block_ohjhbtlx_wpftmp.csproj
new file mode 100644
index 0000000..98ee754
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/AIStudio.Wpf.Block_ohjhbtlx_wpftmp.csproj
@@ -0,0 +1,244 @@
+
+
+ AIStudio.Wpf.Block
+ obj\Debug\
+ obj\
+ F:\aistudio.-wpf.-diagram\Extensions\AIStudio.Wpf.Block\obj\
+ <_TargetAssemblyProjectName>AIStudio.Wpf.Block
+
+
+
+ true
+ AIStudio.Wpf.Controls
+ akwkevin
+ https://gitee.com/akwkevin
+ A.png
+
+
+ 1.0.7
+ 一个Wpf的流程图控件
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Extensions/AIStudio.Wpf.Block/Controls/BlockDecorator.cs b/Extensions/AIStudio.Wpf.Block/Controls/BlockDecorator.cs
new file mode 100644
index 0000000..df7b037
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/Controls/BlockDecorator.cs
@@ -0,0 +1,114 @@
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace AIStudio.Wpf.Block.Controls
+{
+ public class BlockDecorator : Decorator
+ {
+ #region 依赖属性
+ public static readonly DependencyProperty BackgroundProperty =
+ DependencyProperty.Register(nameof(Background), typeof(Brush), typeof(BlockDecorator)
+ , new PropertyMetadata(new SolidColorBrush(Color.FromRgb(255, 255, 255))));
+ ///
+ /// 背景色,默认值为#FFFFFF,白色
+ ///
+ public Brush Background
+ {
+ get
+ {
+ return (Brush)GetValue(BackgroundProperty);
+ }
+ set
+ {
+ SetValue(BackgroundProperty, value);
+ }
+ }
+
+ public static readonly DependencyProperty PaddingProperty =
+ DependencyProperty.Register(nameof(Padding), typeof(Thickness), typeof(BlockDecorator)
+ , new PropertyMetadata(new Thickness(0, 0, 0, 0)));
+ ///
+ /// 内边距
+ ///
+ public Thickness Padding
+ {
+ get
+ {
+ return (Thickness)GetValue(PaddingProperty);
+ }
+ set
+ {
+ SetValue(PaddingProperty, value);
+ }
+ }
+
+ public static readonly DependencyProperty BorderBrushProperty =
+ DependencyProperty.Register(nameof(BorderBrush), typeof(Brush), typeof(BlockDecorator)
+ , new PropertyMetadata(default(Brush)));
+ ///
+ /// 边框颜色
+ ///
+ public Brush BorderBrush
+ {
+ get
+ {
+ return (Brush)GetValue(BorderBrushProperty);
+ }
+ set
+ {
+ SetValue(BorderBrushProperty, value);
+ }
+ }
+
+ public static readonly DependencyProperty BorderThicknessProperty =
+ DependencyProperty.Register(nameof(BorderThickness), typeof(Thickness), typeof(BlockDecorator), new PropertyMetadata(new Thickness(0d)));
+ ///
+ /// 边框大小
+ ///
+ public Thickness BorderThickness
+ {
+ get
+ {
+ return (Thickness)GetValue(BorderThicknessProperty);
+ }
+ set
+ {
+ SetValue(BorderThicknessProperty, value);
+ }
+ }
+ #endregion
+
+ protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
+ {
+ Point hitPoint = hitTestParameters.HitPoint;
+
+ // 在此处实现自定义的命中测试逻辑
+ if (IsPointInsideCustomRegion(hitPoint))
+ {
+ return new PointHitTestResult(this, hitPoint);
+ }
+
+ return null; // 不命中
+ }
+
+ private bool IsPointInsideCustomRegion(Point point)
+ {
+ // 在此处检测点是否在自定义区域内
+ // 返回 true 表示命中,返回 false 表示不命中
+ return false;
+ }
+
+ protected Brush CreateFillBrush()
+ {
+ Brush result = null;
+
+ System.Windows.Media.GradientStopCollection gsc = new System.Windows.Media.GradientStopCollection();
+ gsc.Add(new System.Windows.Media.GradientStop(((SolidColorBrush)this.Background).Color, 0));
+ LinearGradientBrush backGroundBrush = new LinearGradientBrush(gsc, new Point(0, 0), new Point(0, 1));
+ result = backGroundBrush;
+
+ return result;
+ }
+ }
+}
diff --git a/Extensions/AIStudio.Wpf.Block/Controls/BlockPanel.cs b/Extensions/AIStudio.Wpf.Block/Controls/BlockPanel.cs
new file mode 100644
index 0000000..85049a9
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/Controls/BlockPanel.cs
@@ -0,0 +1,114 @@
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace AIStudio.Wpf.Block.Controls
+{
+ public class BlockPanel : Panel
+ {
+ #region 依赖属性
+ public static readonly DependencyProperty BackgroundProperty =
+ DependencyProperty.Register(nameof(Background), typeof(Brush), typeof(BlockPanel)
+ , new PropertyMetadata(new SolidColorBrush(Color.FromRgb(255, 255, 255))));
+ ///
+ /// 背景色,默认值为#FFFFFF,白色
+ ///
+ public Brush Background
+ {
+ get
+ {
+ return (Brush)GetValue(BackgroundProperty);
+ }
+ set
+ {
+ SetValue(BackgroundProperty, value);
+ }
+ }
+
+ public static readonly DependencyProperty PaddingProperty =
+ DependencyProperty.Register(nameof(Padding), typeof(Thickness), typeof(BlockPanel)
+ , new PropertyMetadata(new Thickness(0, 0, 0, 0)));
+ ///
+ /// 内边距
+ ///
+ public Thickness Padding
+ {
+ get
+ {
+ return (Thickness)GetValue(PaddingProperty);
+ }
+ set
+ {
+ SetValue(PaddingProperty, value);
+ }
+ }
+
+ public static readonly DependencyProperty BorderBrushProperty =
+ DependencyProperty.Register(nameof(BorderBrush), typeof(Brush), typeof(BlockPanel)
+ , new PropertyMetadata(default(Brush)));
+ ///
+ /// 边框颜色
+ ///
+ public Brush BorderBrush
+ {
+ get
+ {
+ return (Brush)GetValue(BorderBrushProperty);
+ }
+ set
+ {
+ SetValue(BorderBrushProperty, value);
+ }
+ }
+
+ public static readonly DependencyProperty BorderThicknessProperty =
+ DependencyProperty.Register(nameof(BorderThickness), typeof(Thickness), typeof(BlockPanel), new PropertyMetadata(new Thickness(0d)));
+ ///
+ /// 边框大小
+ ///
+ public Thickness BorderThickness
+ {
+ get
+ {
+ return (Thickness)GetValue(BorderThicknessProperty);
+ }
+ set
+ {
+ SetValue(BorderThicknessProperty, value);
+ }
+ }
+ #endregion
+
+ protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
+ {
+ Point hitPoint = hitTestParameters.HitPoint;
+
+ // 在此处实现自定义的命中测试逻辑
+ if (IsPointInsideCustomRegion(hitPoint))
+ {
+ return new PointHitTestResult(this, hitPoint);
+ }
+
+ return null; // 不命中
+ }
+
+ private bool IsPointInsideCustomRegion(Point point)
+ {
+ // 在此处检测点是否在自定义区域内
+ // 返回 true 表示命中,返回 false 表示不命中
+ return false;
+ }
+
+ protected Brush CreateFillBrush()
+ {
+ Brush result = null;
+
+ System.Windows.Media.GradientStopCollection gsc = new System.Windows.Media.GradientStopCollection();
+ gsc.Add(new System.Windows.Media.GradientStop(((SolidColorBrush)this.Background).Color, 0));
+ LinearGradientBrush backGroundBrush = new LinearGradientBrush(gsc, new Point(0, 0), new Point(0, 1));
+ result = backGroundBrush;
+
+ return result;
+ }
+ }
+}
diff --git a/Extensions/AIStudio.Wpf.Block/Controls/EndBlockBorder.cs b/Extensions/AIStudio.Wpf.Block/Controls/EndBlockBorder.cs
new file mode 100644
index 0000000..f61ab79
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/Controls/EndBlockBorder.cs
@@ -0,0 +1,144 @@
+using System;
+using System.Windows;
+using System.Windows.Media;
+
+namespace AIStudio.Wpf.Block.Controls
+{
+ public class EndBlockBorder : BlockDecorator
+ {
+ public EndBlockBorder()
+ {
+
+ }
+
+ #region 方法重写
+ public double Insideheight { get; set; } = 6;
+ public double Insidewidth { get; set; } = 21;
+ public double Insideoffset { get; set; } = 14;
+ public double Minwidth { get; set; } = 86;
+ public double Minheight { get; set; } = 34;
+ ///
+ /// 该方法用于测量整个控件的大小
+ ///
+ ///
+ /// 控件的大小
+ protected override Size MeasureOverride(Size constraint)
+ {
+ Thickness padding = this.Padding;
+
+ Size result = new Size();
+ if (Child != null)
+ {
+ //测量子控件的大小
+ Child.Measure(constraint);
+
+ result.Width = Math.Max(Minwidth, Child.DesiredSize.Width + padding.Left + padding.Right);
+ result.Height = Math.Max(Minheight, Child.DesiredSize.Height + padding.Top + padding.Bottom);
+ }
+ else
+ {
+ result.Width = Minwidth;
+ result.Height = Minheight;
+ }
+ return result;
+ }
+
+ ///
+ /// 设置子控件的大小与位置
+ ///
+ ///
+ ///
+ protected override Size ArrangeOverride(Size arrangeSize)
+ {
+ Thickness padding = this.Padding;
+ if (Child != null)
+ {
+ Child.Arrange(new Rect(new Point(padding.Left, padding.Top),
+ new Size(Math.Max(Minwidth - padding.Left - padding.Right, Child.DesiredSize.Width ), Math.Max(Minheight - padding.Top - padding.Bottom, Child.DesiredSize.Height))));
+ }
+ return arrangeSize;
+ }
+
+ ///
+ /// 绘制控件
+ ///
+ ///
+ protected override void OnRender(DrawingContext drawingContext)
+ {
+ Thickness padding = this.Padding;
+
+ Pen pen = new Pen();
+ pen.Brush = this.BorderBrush;
+ pen.Thickness = this.BorderThickness.Left;// NextForBlockBorder.RoundLayoutValue(BorderThickness.Left, DoubleUtil.DpiScaleX);
+
+ Geometry cg = CreateGeometry(Math.Max(Minwidth, Child?.DesiredSize.Width??0 + padding.Left + padding.Right), Math.Max(Minheight, Child?.DesiredSize.Height??0 + padding.Top + padding.Bottom));
+ Brush brush = CreateFillBrush();
+
+ GuidelineSet guideLines = new GuidelineSet();
+ drawingContext.PushGuidelineSet(guideLines);
+ drawingContext.DrawGeometry(brush, pen, cg);
+
+ }
+ #endregion
+
+ #region 私有方法
+ private Geometry CreateGeometry(double x, double y)
+ {
+ #region
+ PathFigure pf = new PathFigure();
+ pf.IsClosed = true;
+ pf.StartPoint = new Point(0, 2);
+
+ //第一横线
+ ArcSegment seg1 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(2, 0) };
+ pf.Segments.Add(seg1);
+
+ LineSegment seg2 = new LineSegment() { Point = new Point(Insideoffset, 0) };
+ pf.Segments.Add(seg2);
+
+ //第二in
+ QuadraticBezierSegment seg3 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + 1, 0), Point2 = new Point(Insideoffset + 2, 2) };
+ pf.Segments.Add(seg3);
+
+ QuadraticBezierSegment seg4 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + 4, 6), Point2 = new Point(Insideoffset + 5, 6) };
+ pf.Segments.Add(seg4);
+
+ LineSegment seg5 = new LineSegment() { Point = new Point(Insideoffset + Insidewidth - 5, 6) };
+ pf.Segments.Add(seg5);
+
+ QuadraticBezierSegment seg6 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + Insidewidth - 4, 6), Point2 = new Point(Insideoffset + Insidewidth - 2, 2) };
+ pf.Segments.Add(seg6);
+
+ QuadraticBezierSegment seg7 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + Insidewidth - 1, 0), Point2 = new Point(Insideoffset + Insidewidth, 0) };
+ pf.Segments.Add(seg7);
+
+ //第三横线
+ LineSegment seg8 = new LineSegment() { Point = new Point(x - 2, 0) };
+ pf.Segments.Add(seg8);
+
+ //第四竖线
+ ArcSegment seg9 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(x, 2) };
+ pf.Segments.Add(seg9);
+
+ LineSegment seg10 = new LineSegment() { Point = new Point(x, y - 2) };
+ pf.Segments.Add(seg10);
+
+ //第五横线
+ ArcSegment seg11 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(x - 2, y) };
+ pf.Segments.Add(seg11);
+
+ LineSegment seg12 = new LineSegment() { Point = new Point(2, y) };
+ pf.Segments.Add(seg12);
+
+ ArcSegment seg13 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(0, y - 2) };
+ pf.Segments.Add(seg13);
+
+ PathGeometry g1 = new PathGeometry();
+ g1.Figures.Add(pf);
+ #endregion
+
+ return g1;
+ }
+ #endregion
+ }
+}
diff --git a/Extensions/AIStudio.Wpf.Block/Controls/NextBlockBorder.cs b/Extensions/AIStudio.Wpf.Block/Controls/NextBlockBorder.cs
new file mode 100644
index 0000000..8552a4a
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/Controls/NextBlockBorder.cs
@@ -0,0 +1,164 @@
+using System;
+using System.Windows;
+using System.Windows.Media;
+
+namespace AIStudio.Wpf.Block.Controls
+{
+ public class NextBlockBorder : BlockDecorator
+ {
+ public NextBlockBorder()
+ {
+
+ }
+
+ #region 方法重写
+ public double Insideheight { get; set; } = 6;
+ public double Insidewidth { get; set; } = 21;
+ public double Insideoffset { get; set; } = 14;
+ public double Minwidth { get; set; } = 86;
+ public double Minheight { get; set; } = 34;
+ ///
+ /// 该方法用于测量整个控件的大小
+ ///
+ ///
+ /// 控件的大小
+ protected override Size MeasureOverride(Size constraint)
+ {
+ Thickness padding = this.Padding;
+
+ Size result = new Size();
+ if (Child != null)
+ {
+ //测量子控件的大小
+ Child.Measure(constraint);
+
+ result.Width = Math.Max(Minwidth, Child.DesiredSize.Width + padding.Left + padding.Right);
+ result.Height = Math.Max(Minheight, Child.DesiredSize.Height + padding.Top + padding.Bottom);
+ }
+ else
+ {
+ result.Width = Minwidth;
+ result.Height = Minheight;
+ }
+ return result;
+ }
+
+ ///
+ /// 设置子控件的大小与位置
+ ///
+ ///
+ ///
+ protected override Size ArrangeOverride(Size arrangeSize)
+ {
+ Thickness padding = this.Padding;
+ if (Child != null)
+ {
+ Child.Arrange(new Rect(new Point(padding.Left, padding.Top),
+ new Size(Math.Max(Minwidth - padding.Left - padding.Right, Child.DesiredSize.Width ), Math.Max(Minheight - padding.Top - padding.Bottom, Child.DesiredSize.Height))));
+ }
+ return arrangeSize;
+ }
+
+ ///
+ /// 绘制控件
+ ///
+ ///
+ protected override void OnRender(DrawingContext drawingContext)
+ {
+ Thickness padding = this.Padding;
+
+ Pen pen = new Pen();
+ pen.Brush = this.BorderBrush;
+ pen.Thickness = this.BorderThickness.Left;// NextForBlockBorder.RoundLayoutValue(BorderThickness.Left, DoubleUtil.DpiScaleX);
+
+ Geometry cg = CreateGeometry(Math.Max(Minwidth, Child?.DesiredSize.Width??0 + padding.Left + padding.Right), Math.Max(Minheight, Child?.DesiredSize.Height??0 + padding.Top + padding.Bottom));
+ Brush brush = CreateFillBrush();
+
+ GuidelineSet guideLines = new GuidelineSet();
+ drawingContext.PushGuidelineSet(guideLines);
+ drawingContext.DrawGeometry(brush, pen, cg);
+
+ }
+ #endregion
+
+ #region 私有方法
+ private Geometry CreateGeometry(double x, double y)
+ {
+ #region
+ PathFigure pf = new PathFigure();
+ pf.IsClosed = true;
+ pf.StartPoint = new Point(0, 2);
+
+ //第一横线
+ ArcSegment seg1 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(2, 0) };
+ pf.Segments.Add(seg1);
+
+ LineSegment seg2 = new LineSegment() { Point = new Point(Insideoffset, 0) };
+ pf.Segments.Add(seg2);
+
+ //第二in
+ QuadraticBezierSegment seg3 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + 1, 0), Point2 = new Point(Insideoffset + 2, 2) };
+ pf.Segments.Add(seg3);
+
+ QuadraticBezierSegment seg4 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + 4, 6), Point2 = new Point(Insideoffset + 5, 6) };
+ pf.Segments.Add(seg4);
+
+ LineSegment seg5 = new LineSegment() { Point = new Point(Insideoffset + Insidewidth - 5, 6) };
+ pf.Segments.Add(seg5);
+
+ QuadraticBezierSegment seg6 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + Insidewidth - 4, 6), Point2 = new Point(Insideoffset + Insidewidth - 2, 2) };
+ pf.Segments.Add(seg6);
+
+ QuadraticBezierSegment seg7 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + Insidewidth - 1, 0), Point2 = new Point(Insideoffset + Insidewidth, 0) };
+ pf.Segments.Add(seg7);
+
+ //第三横线
+ LineSegment seg8 = new LineSegment() { Point = new Point(x - 2, 0) };
+ pf.Segments.Add(seg8);
+
+ //第四竖线
+ ArcSegment seg9 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(x, 2) };
+ pf.Segments.Add(seg9);
+
+ LineSegment seg10 = new LineSegment() { Point = new Point(x, y - 2) };
+ pf.Segments.Add(seg10);
+
+ //第五横线
+ ArcSegment seg11 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(x - 2, y) };
+ pf.Segments.Add(seg11);
+
+ LineSegment seg12 = new LineSegment() { Point = new Point(Insideoffset + Insidewidth, y) };
+ pf.Segments.Add(seg12);
+
+ //第六in
+ QuadraticBezierSegment seg13 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + Insidewidth - 1, y), Point2 = new Point(Insideoffset + Insidewidth - 2, y + 2) };
+ pf.Segments.Add(seg13);
+
+ QuadraticBezierSegment seg14 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + Insidewidth - 4, y + Insideheight), Point2 = new Point(Insideoffset + Insidewidth - 5, y + Insideheight) };
+ pf.Segments.Add(seg14);
+
+ LineSegment seg15 = new LineSegment() { Point = new Point(Insideoffset + 5, y + Insideheight) };
+ pf.Segments.Add(seg15);
+
+ QuadraticBezierSegment seg16 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + 4, y + Insideheight), Point2 = new Point(Insideoffset + 2, y + 2) };
+ pf.Segments.Add(seg16);
+
+ QuadraticBezierSegment seg17 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + 1, y), Point2 = new Point(Insideoffset, y) };
+ pf.Segments.Add(seg17);
+
+ //第七横线
+ LineSegment seg18 = new LineSegment() { Point = new Point(2, y) };
+ pf.Segments.Add(seg18);
+
+ ArcSegment seg19 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(0, y - 2) };
+ pf.Segments.Add(seg19);
+
+ PathGeometry g1 = new PathGeometry();
+ g1.Figures.Add(pf);
+ #endregion
+
+ return g1;
+ }
+ #endregion
+ }
+}
diff --git a/Extensions/AIStudio.Wpf.Block/Controls/NextFor2BlockPanel.cs b/Extensions/AIStudio.Wpf.Block/Controls/NextFor2BlockPanel.cs
new file mode 100644
index 0000000..988c193
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/Controls/NextFor2BlockPanel.cs
@@ -0,0 +1,435 @@
+using System;
+using System.ComponentModel;
+using System.Data;
+using System.Runtime.InteropServices;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace AIStudio.Wpf.Block.Controls
+{
+
+ public class NextFor2BlockPanel : BlockPanel
+ {
+ public NextFor2BlockPanel()
+ {
+
+ }
+
+ #region 方法重写
+ private UIElement Header
+ {
+ get
+ {
+ return InternalChildren.Count >= 0 ? InternalChildren[0] : null;
+ }
+ }
+
+ private UIElement Content1
+ {
+ get
+ {
+ return InternalChildren.Count >= 1 ? InternalChildren[1] : null;
+ }
+ }
+
+ private UIElement Footer1
+ {
+ get
+ {
+ return InternalChildren.Count >= 2 ? InternalChildren[2] : null;
+ }
+ }
+
+ private UIElement Content2
+ {
+ get
+ {
+ return InternalChildren.Count >= 3 ? InternalChildren[3] : null;
+ }
+ }
+
+ private UIElement Footer2
+ {
+ get
+ {
+ return InternalChildren.Count >= 4 ? InternalChildren[4] : null;
+ }
+ }
+
+ public double Insideheight { get; set; } = 6;
+ public double Insidewidth { get; set; } = 21;
+ public double insideoffset { get; set; } = 14;
+ public double Leftpanelwidth { get; set; } = 10;
+ public double Minwidth { get; set; } = 109;
+ public double Minheaderheight { get; set; } = 34;
+ public double Mincontentheight { get; set; } = 16;
+ public double Minfooterheight { get; set; } = 26;
+
+
+ private double _width;
+ private double _headerheight;
+ private double _content1height;
+ private double _footer1height;
+ private double _content2height;
+ private double _footer2height;
+ ///
+ /// 该方法用于测量整个控件的大小
+ ///
+ ///
+ /// 控件的大小
+ protected override Size MeasureOverride(Size constraint)
+ {
+ Thickness padding = this.Padding;
+
+ _width = Minwidth;
+ if (Header != null)
+ {
+ //测量子控件的大小
+ Header.Measure(constraint);
+ _width = Math.Max(Minwidth, Header.DesiredSize.Width + padding.Left + padding.Right);
+ _headerheight = Math.Max(Minheaderheight, Header.DesiredSize.Height + padding.Top + padding.Bottom);
+ }
+ else
+ {
+ _headerheight = Minheaderheight;
+ }
+
+ if (Content1 != null)
+ {
+ //测量子控件的大小
+ Content1.Measure(constraint);
+ _width = Math.Max(Minwidth, Content1.DesiredSize.Width + padding.Left + padding.Right + Leftpanelwidth);
+ _content1height = Math.Max(Mincontentheight, Content1.DesiredSize.Height + padding.Top + padding.Bottom);
+ }
+ else
+ {
+ _content1height = Mincontentheight;
+ }
+
+ if (Footer1 != null)
+ {
+ //测量子控件的大小
+ Footer1.Measure(constraint);
+ _width = Math.Max(Minwidth, Footer1.DesiredSize.Width + padding.Left + padding.Right);
+ _footer1height = Math.Max(Minfooterheight, Footer1.DesiredSize.Height + padding.Top + padding.Bottom);
+ }
+ else
+ {
+ _footer1height = Minfooterheight;
+ }
+
+ if (Content2!= null)
+ {
+ //测量子控件的大小
+ Content2.Measure(constraint);
+ _width = Math.Max(Minwidth, Content2.DesiredSize.Width + padding.Left + padding.Right + Leftpanelwidth);
+ _content2height = Math.Max(Mincontentheight, Content2.DesiredSize.Height + padding.Top + padding.Bottom);
+ }
+ else
+ {
+ _content2height = Mincontentheight;
+ }
+
+ if (Footer2 != null)
+ {
+ //测量子控件的大小
+ Footer2.Measure(constraint);
+ _width = Math.Max(Minwidth, Footer2.DesiredSize.Width + padding.Left + padding.Right);
+ _footer2height = Math.Max(Minfooterheight, Footer2.DesiredSize.Height + padding.Top + padding.Bottom);
+ }
+ else
+ {
+ _footer2height = Minfooterheight;
+ }
+
+ return new Size(_width, _headerheight + _content1height + _footer1height + _content2height + _footer2height);
+ }
+
+ ///
+ /// 设置子控件的大小与位置
+ ///
+ ///
+ ///
+ protected override Size ArrangeOverride(Size arrangeSize)
+ {
+ Thickness padding = this.Padding;
+
+ if (Header != null)
+ {
+ Header.Arrange(new Rect(new Point(padding.Left, padding.Top), new Size(_width - padding.Left - padding.Right, _headerheight - padding.Top - padding.Bottom)));
+ }
+
+
+ if (Content1 != null)
+ {
+ Content1.Arrange(new Rect(new Point(padding.Left + Leftpanelwidth, padding.Top + _headerheight), new Size(_width - Leftpanelwidth - padding.Left - padding.Right, _content1height - padding.Top - padding.Bottom)));
+ }
+
+
+ if (Footer1 != null)
+ {
+ Footer1.Arrange(new Rect(new Point(padding.Left, padding.Top + _headerheight + _content1height), new Size(_width - padding.Left - padding.Right, _footer1height - padding.Top - padding.Bottom)));
+ }
+
+ if (Content2 != null)
+ {
+ Content2.Arrange(new Rect(new Point(padding.Left + Leftpanelwidth, padding.Top + _headerheight + _content1height + _footer1height), new Size(_width - Leftpanelwidth - padding.Left - padding.Right, _content2height - padding.Top - padding.Bottom)));
+ }
+
+
+ if (Footer2 != null)
+ {
+ Footer2.Arrange(new Rect(new Point(padding.Left, padding.Top + _headerheight + _content1height + _footer1height + _content2height), new Size(_width - padding.Left - padding.Right, _footer2height - padding.Top - padding.Bottom)));
+ }
+
+
+ return base.ArrangeOverride(arrangeSize);
+ }
+
+ ///
+ /// 绘制控件
+ ///
+ ///
+ protected override void OnRender(DrawingContext drawingContext)
+ {
+ Thickness padding = this.Padding;
+
+ Pen pen = new Pen();
+ pen.Brush = this.BorderBrush;
+ pen.Thickness = this.BorderThickness.Left;// NextForBlockBorder.RoundLayoutValue(BorderThickness.Left, DoubleUtil.DpiScaleX);
+
+ Geometry cg = CreateGeometry(_width, _headerheight, _content1height, _footer1height, _content2height, _footer2height);
+ Brush brush = CreateFillBrush();
+
+ GuidelineSet guideLines = new GuidelineSet();
+ drawingContext.PushGuidelineSet(guideLines);
+ drawingContext.DrawGeometry(brush, pen, cg);
+
+ base.OnRender(drawingContext);
+ }
+ #endregion
+
+ #region 私有方法
+ private Geometry CreateGeometry(double x, double y0, double y1, double y2, double y3, double y4)
+ {
+ #region
+ PathFigure pf = new PathFigure();
+ pf.IsClosed = true;
+ pf.StartPoint = new Point(0, 2);
+
+ //第一横线
+ ArcSegment seg1 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(2, 0) };
+ pf.Segments.Add(seg1);
+
+ LineSegment seg2 = new LineSegment() { Point = new Point(insideoffset, 0) };
+ pf.Segments.Add(seg2);
+
+ //第二in
+ QuadraticBezierSegment seg3 = new QuadraticBezierSegment() { Point1 = new Point(insideoffset + 1, 0), Point2 = new Point(insideoffset + 2, 2) };
+ pf.Segments.Add(seg3);
+
+ QuadraticBezierSegment seg4 = new QuadraticBezierSegment() { Point1 = new Point(insideoffset + 4, Insideheight), Point2 = new Point(insideoffset + 5, Insideheight) };
+ pf.Segments.Add(seg4);
+
+ LineSegment seg5 = new LineSegment() { Point = new Point(insideoffset + Insidewidth - 5, Insideheight) };
+ pf.Segments.Add(seg5);
+
+ QuadraticBezierSegment seg6 = new QuadraticBezierSegment() { Point1 = new Point(insideoffset + Insidewidth - 4, Insideheight), Point2 = new Point(insideoffset + Insidewidth - 2, 2) };
+ pf.Segments.Add(seg6);
+
+ QuadraticBezierSegment seg7 = new QuadraticBezierSegment() { Point1 = new Point(insideoffset + Insidewidth - 1, 0), Point2 = new Point(insideoffset + Insidewidth, 0) };
+ pf.Segments.Add(seg7);
+
+ //第三横线
+ LineSegment seg8 = new LineSegment() { Point = new Point(x - 2, 0) };
+ pf.Segments.Add(seg8);
+
+ //第四竖线
+ ArcSegment seg9 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(x, 2) };
+ pf.Segments.Add(seg9);
+
+ LineSegment seg10 = new LineSegment() { Point = new Point(x, y0 - 2) };
+ pf.Segments.Add(seg10);
+
+ //第五横线
+ ArcSegment seg11 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(x - 2, y0) };
+ pf.Segments.Add(seg11);
+
+ LineSegment seg12 = new LineSegment() { Point = new Point(Leftpanelwidth + insideoffset + Insidewidth, y0) };
+ pf.Segments.Add(seg12);
+
+ //第六in
+ QuadraticBezierSegment seg13 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + insideoffset + Insidewidth - 1, y0), Point2 = new Point(Leftpanelwidth + insideoffset + Insidewidth - 2, y0 + 2) };
+ pf.Segments.Add(seg13);
+
+ QuadraticBezierSegment seg14 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + insideoffset + Insidewidth - 4, y0 + Insideheight), Point2 = new Point(Leftpanelwidth + insideoffset + Insidewidth - 5, y0 + Insideheight) };
+ pf.Segments.Add(seg14);
+
+ LineSegment seg15 = new LineSegment() { Point = new Point(Leftpanelwidth + insideoffset + 5, y0 + Insideheight) };
+ pf.Segments.Add(seg15);
+
+ QuadraticBezierSegment seg16 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + insideoffset + 4, y0 + Insideheight), Point2 = new Point(Leftpanelwidth + insideoffset + 2, y0 + 2) };
+ pf.Segments.Add(seg16);
+
+ QuadraticBezierSegment seg17 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + insideoffset + 1, y0), Point2 = new Point(insideoffset, y0) };
+ pf.Segments.Add(seg17);
+
+ //第七横线
+ LineSegment seg18 = new LineSegment() { Point = new Point(Leftpanelwidth + 2, y0) };
+ pf.Segments.Add(seg18);
+
+ ArcSegment seg19 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Counterclockwise, Point = new Point(Leftpanelwidth, y0 + 2) };
+ pf.Segments.Add(seg19);
+
+ //第八竖线
+ LineSegment seg20 = new LineSegment() { Point = new Point(Leftpanelwidth, y0 + y1 - 2) };
+ pf.Segments.Add(seg20);
+
+ ArcSegment seg21 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Counterclockwise, Point = new Point(Leftpanelwidth + 2, y0 + y1) };
+ pf.Segments.Add(seg21);
+
+ //第九横线
+ LineSegment seg22 = new LineSegment() { Point = new Point(Leftpanelwidth + insideoffset, y0 + y1) };
+ pf.Segments.Add(seg22);
+
+ //第十in
+ QuadraticBezierSegment seg23 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + insideoffset + 1, y0 + y1), Point2 = new Point(Leftpanelwidth + insideoffset + 2, y0 + y1 + 2) };
+ pf.Segments.Add(seg23);
+
+ QuadraticBezierSegment seg24 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + insideoffset + 4, y0 + y1 + Insideheight), Point2 = new Point(Leftpanelwidth + insideoffset + 5, y0 + y1 + Insideheight) };
+ pf.Segments.Add(seg24);
+
+ LineSegment seg25 = new LineSegment() { Point = new Point(Leftpanelwidth + insideoffset + Insidewidth - 5, y0 + y1 + Insideheight) };
+ pf.Segments.Add(seg25);
+
+ QuadraticBezierSegment seg26 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + insideoffset + Insidewidth - 4, y0 + y1 + Insideheight), Point2 = new Point(Leftpanelwidth + insideoffset + Insidewidth - 2, y0 + y1 + 2) };
+ pf.Segments.Add(seg26);
+
+ QuadraticBezierSegment seg27 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + insideoffset + Insidewidth - 1, y0 + y1), Point2 = new Point(Leftpanelwidth + insideoffset + Insidewidth, y0 + y1) };
+ pf.Segments.Add(seg27);
+
+ //第十一横线
+ LineSegment seg28 = new LineSegment() { Point = new Point(x - 2, y0 + y1) };
+ pf.Segments.Add(seg28);
+
+ //第十二竖线
+ ArcSegment seg29 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(x, y0 + y1 + 2) };
+ pf.Segments.Add(seg29);
+
+ LineSegment seg30 = new LineSegment() { Point = new Point(x, y0 + y1 + y2 - 2) };
+ pf.Segments.Add(seg30);
+
+ //第十三横线
+ ArcSegment seg31 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(x - 2, y0 + y1 + y2) };
+ pf.Segments.Add(seg31);
+
+
+
+ LineSegment seg32 = new LineSegment() { Point = new Point(Leftpanelwidth + insideoffset + Insidewidth, y0 + y1 + y2) };
+ pf.Segments.Add(seg32);
+
+ //第十四in
+ QuadraticBezierSegment seg33 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + insideoffset + Insidewidth - 1, y0 + y1 + y2), Point2 = new Point(Leftpanelwidth + insideoffset + Insidewidth - 2, y0 + y1 + y2 + 2) };
+ pf.Segments.Add(seg33);
+
+ QuadraticBezierSegment seg34 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + insideoffset + Insidewidth - 4, y0 + y1 + y2 + Insideheight), Point2 = new Point(Leftpanelwidth + insideoffset + Insidewidth - 5, y0 + y1 + y2 + Insideheight) };
+ pf.Segments.Add(seg34);
+
+ LineSegment seg35 = new LineSegment() { Point = new Point(Leftpanelwidth + insideoffset + 5, y0 + y1 + y2 + Insideheight) };
+ pf.Segments.Add(seg35);
+
+ QuadraticBezierSegment seg36 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + insideoffset + 4, y0 + y1 + y2 + Insideheight), Point2 = new Point(Leftpanelwidth + insideoffset + 2, y0 + y1 + y2 + 2) };
+ pf.Segments.Add(seg36);
+
+ QuadraticBezierSegment seg37 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + insideoffset + 1, y0 + y1 + y2), Point2 = new Point(Leftpanelwidth + insideoffset, y0 + y1 + y2) };
+ pf.Segments.Add(seg37);
+
+ //第十五横线
+ LineSegment seg38 = new LineSegment() { Point = new Point(Leftpanelwidth + 2, y0 + y1 + y2) };
+ pf.Segments.Add(seg38);
+
+ ArcSegment seg39 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Counterclockwise, Point = new Point(Leftpanelwidth, y0 + y1 + y2 + 2) };
+ pf.Segments.Add(seg39);
+
+ //第十六竖向
+ LineSegment seg40 = new LineSegment() { Point = new Point(Leftpanelwidth, y0 + y1 + y2 + y3 - 2) };
+ pf.Segments.Add(seg40);
+
+ ArcSegment seg41 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Counterclockwise, Point = new Point(Leftpanelwidth + 2, y0 + y1 + y2 + y3) };
+ pf.Segments.Add(seg41);
+
+ //第十七横线
+ LineSegment seg42 = new LineSegment() { Point = new Point(Leftpanelwidth + insideoffset, y0 + y1 + y2 + y3) };
+ pf.Segments.Add(seg42);
+
+ //第十八in
+ QuadraticBezierSegment seg43 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + insideoffset + 1, y0 + y1 + y2 + y3), Point2 = new Point(Leftpanelwidth + insideoffset + 2, y0 + y1 + y2 + y3 + 2) };
+ pf.Segments.Add(seg43);
+
+ QuadraticBezierSegment seg44 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + insideoffset + 4, y0 + y1 + y2 + y3 + Insideheight), Point2 = new Point(Leftpanelwidth + insideoffset + 5, y0 + y1 + y2 + y3 + Insideheight) };
+ pf.Segments.Add(seg44);
+
+ LineSegment seg45 = new LineSegment() { Point = new Point(Leftpanelwidth + insideoffset + Insidewidth - 5, y0 + y1 + y2 + y3 + Insideheight) };
+ pf.Segments.Add(seg45);
+
+ QuadraticBezierSegment seg46 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + insideoffset + Insidewidth - 4, y0 + y1 + y2 + y3 + Insideheight), Point2 = new Point(Leftpanelwidth + insideoffset + Insidewidth - 2, y0 + y1 + y2 + y3 + 2) };
+ pf.Segments.Add(seg46);
+
+ QuadraticBezierSegment seg47 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + insideoffset + Insidewidth - 1, y0 + y1 + y2 + y3), Point2 = new Point(Leftpanelwidth + insideoffset + Insidewidth, y0 + y1 + y2 + y3) };
+ pf.Segments.Add(seg47);
+
+ //第十一横线
+ LineSegment seg48 = new LineSegment() { Point = new Point(x - 2, y0 + y1 + y2 + y3) };
+ pf.Segments.Add(seg48);
+
+ //第十二竖线
+ ArcSegment seg49 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(x, y0 + y1 + y2 + y3 + 2) };
+ pf.Segments.Add(seg49);
+
+ LineSegment seg50 = new LineSegment() { Point = new Point(x, y0 + y1 + y2 + y3 + y4 - 2) };
+ pf.Segments.Add(seg50);
+
+ //第十三横线
+ ArcSegment seg51 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(x - 2, y0 + y1 + y2 + y3 + y4) };
+ pf.Segments.Add(seg51);
+
+
+
+ LineSegment seg52 = new LineSegment() { Point = new Point(insideoffset + Insidewidth, y0 + y1 + y2 + y3 + y4) };
+ pf.Segments.Add(seg52);
+
+ //第十四in
+ QuadraticBezierSegment seg53 = new QuadraticBezierSegment() { Point1 = new Point(insideoffset + Insidewidth - 1, y0 + y1 + y2 + y3 + y4), Point2 = new Point(insideoffset + Insidewidth - 2, y0 + y1 + y2 + y3 + y4 + 2) };
+ pf.Segments.Add(seg53);
+
+ QuadraticBezierSegment seg54 = new QuadraticBezierSegment() { Point1 = new Point(insideoffset + Insidewidth - 4, y0 + y1 + y2 + y3 + y4 + Insideheight), Point2 = new Point(insideoffset + Insidewidth - 5, y0 + y1 + y2 + y3 + y4 + Insideheight) };
+ pf.Segments.Add(seg54);
+
+ LineSegment seg55 = new LineSegment() { Point = new Point(insideoffset + 5, y0 + y1 + y2 + y3 + y4 + Insideheight) };
+ pf.Segments.Add(seg55);
+
+ QuadraticBezierSegment seg56 = new QuadraticBezierSegment() { Point1 = new Point(insideoffset + 4, y0 + y1 + y2 + y3 + y4 + Insideheight), Point2 = new Point(insideoffset + 2, y0 + y1 + y2 + y3 + y4 + 2) };
+ pf.Segments.Add(seg56);
+
+ QuadraticBezierSegment seg57 = new QuadraticBezierSegment() { Point1 = new Point(insideoffset + 1, y0 + y1 + y2 + y3 + y4), Point2 = new Point(insideoffset, y0 + y1 + y2 + y3 + y4) };
+ pf.Segments.Add(seg57);
+
+ //第十五横线
+ LineSegment seg58 = new LineSegment() { Point = new Point(2, y0 + y1 + y2 + y3 + y4) };
+ pf.Segments.Add(seg58);
+
+ ArcSegment seg59 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Counterclockwise, Point = new Point(0, y0 + y1 + y2 + y3 + y4 - 2) };
+ pf.Segments.Add(seg59);
+
+
+ PathGeometry g1 = new PathGeometry();
+ g1.Figures.Add(pf);
+ #endregion
+
+ return g1;
+ }
+
+ #endregion
+ }
+}
diff --git a/Extensions/AIStudio.Wpf.Block/Controls/NextForBlockPanel.cs b/Extensions/AIStudio.Wpf.Block/Controls/NextForBlockPanel.cs
new file mode 100644
index 0000000..5880309
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/Controls/NextForBlockPanel.cs
@@ -0,0 +1,309 @@
+using System;
+using System.ComponentModel;
+using System.Data;
+using System.Runtime.InteropServices;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace AIStudio.Wpf.Block.Controls
+{
+
+ public class NextForBlockPanel : BlockPanel
+ {
+ public NextForBlockPanel()
+ {
+
+ }
+
+ #region 方法重写
+ private UIElement Header
+ {
+ get
+ {
+ return InternalChildren.Count >= 0 ? InternalChildren[0] : null;
+ }
+ }
+
+ private UIElement Content
+ {
+ get
+ {
+ return InternalChildren.Count >= 1 ? InternalChildren[1] : null;
+ }
+ }
+
+ private UIElement Footer
+ {
+ get
+ {
+ return InternalChildren.Count >= 2 ? InternalChildren[2] : null;
+ }
+ }
+
+ public double Insideheight { get; set; } = 6;
+ public double Insidewidth { get; set; } = 21;
+ public double Insideoffset { get; set; } = 14;
+ public double Leftpanelwidth { get; set; } = 10;
+ public double Minwidth { get; set; } = 109;
+ public double Minheaderheight { get; set; } = 34;
+ public double Mincontentheight { get; set; } = 16;
+ public double Minfooterheight { get; set; } = 26;
+
+
+ private double _width;
+ private double _headerheight;
+ private double _contentheight;
+ private double _footerheight;
+ ///
+ /// 该方法用于测量整个控件的大小
+ ///
+ ///
+ /// 控件的大小
+ protected override Size MeasureOverride(Size constraint)
+ {
+ Thickness padding = this.Padding;
+
+ _width = Minwidth;
+ if (Header != null)
+ {
+ //测量子控件的大小
+ Header.Measure(constraint);
+ _width = Math.Max(Minwidth, Header.DesiredSize.Width + padding.Left + padding.Right);
+ _headerheight = Math.Max(Minheaderheight, Header.DesiredSize.Height + padding.Top + padding.Bottom);
+ }
+ else
+ {
+ _headerheight = Minheaderheight;
+ }
+
+ if (Content != null)
+ {
+ //测量子控件的大小
+ Content.Measure(constraint);
+ _width = Math.Max(Minwidth, Content.DesiredSize.Width + padding.Left + padding.Right + Leftpanelwidth);
+ _contentheight = Math.Max(Mincontentheight, Content.DesiredSize.Height + padding.Top + padding.Bottom);
+ }
+ else
+ {
+ _contentheight = Mincontentheight;
+ }
+
+ if (Footer != null)
+ {
+ //测量子控件的大小
+ Footer.Measure(constraint);
+ _width = Math.Max(Minwidth, Footer.DesiredSize.Width + padding.Left + padding.Right);
+ _footerheight = Math.Max(Minfooterheight, Footer.DesiredSize.Height + padding.Top + padding.Bottom);
+ }
+ else
+ {
+ _footerheight = Minfooterheight;
+ }
+
+ return new Size(_width, _headerheight + _contentheight + _footerheight);
+ }
+
+ ///
+ /// 设置子控件的大小与位置
+ ///
+ ///
+ ///
+ protected override Size ArrangeOverride(Size arrangeSize)
+ {
+ Thickness padding = this.Padding;
+
+ if (Header != null)
+ {
+ Header.Arrange(new Rect(new Point(padding.Left, padding.Top), new Size(_width - padding.Left - padding.Right, _headerheight - padding.Top - padding.Bottom)));
+ }
+
+
+ if (Content != null)
+ {
+ Content.Arrange(new Rect(new Point(padding.Left + Leftpanelwidth, padding.Top + _headerheight), new Size(_width - Leftpanelwidth - padding.Left - padding.Right, _contentheight - padding.Top - padding.Bottom)));
+ }
+
+
+ if (Footer != null)
+ {
+ Footer.Arrange(new Rect(new Point(padding.Left, padding.Top + _headerheight + _contentheight), new Size(_width - padding.Left - padding.Right, _footerheight - padding.Top - padding.Bottom)));
+ }
+
+
+ return base.ArrangeOverride(arrangeSize);
+ }
+
+ ///
+ /// 绘制控件
+ ///
+ ///
+ protected override void OnRender(DrawingContext drawingContext)
+ {
+ Thickness padding = this.Padding;
+
+ Pen pen = new Pen();
+ pen.Brush = this.BorderBrush;
+ pen.Thickness = this.BorderThickness.Left;// NextForBlockBorder.RoundLayoutValue(BorderThickness.Left, DoubleUtil.DpiScaleX);
+
+ Geometry cg = CreateGeometry(_width, _headerheight, _contentheight, _footerheight);
+ Brush brush = CreateFillBrush();
+
+ GuidelineSet guideLines = new GuidelineSet();
+ drawingContext.PushGuidelineSet(guideLines);
+ drawingContext.DrawGeometry(brush, pen, cg);
+
+ base.OnRender(drawingContext);
+ }
+ #endregion
+
+ #region 私有方法
+ private Geometry CreateGeometry(double x, double y0, double y1, double y2)
+ {
+ #region
+ PathFigure pf = new PathFigure();
+ pf.IsClosed = true;
+ pf.StartPoint = new Point(0, 2);
+
+ //第一横线
+ ArcSegment seg1 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(2, 0) };
+ pf.Segments.Add(seg1);
+
+ LineSegment seg2 = new LineSegment() { Point = new Point(Insideoffset, 0) };
+ pf.Segments.Add(seg2);
+
+ //第二in
+ QuadraticBezierSegment seg3 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + 1, 0), Point2 = new Point(Insideoffset + 2, 2) };
+ pf.Segments.Add(seg3);
+
+ QuadraticBezierSegment seg4 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + 4, Insideheight), Point2 = new Point(Insideoffset + 5, Insideheight) };
+ pf.Segments.Add(seg4);
+
+ LineSegment seg5 = new LineSegment() { Point = new Point(Insideoffset + Insidewidth - 5, Insideheight) };
+ pf.Segments.Add(seg5);
+
+ QuadraticBezierSegment seg6 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + Insidewidth - 4, Insideheight), Point2 = new Point(Insideoffset + Insidewidth - 2, 2) };
+ pf.Segments.Add(seg6);
+
+ QuadraticBezierSegment seg7 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + Insidewidth - 1, 0), Point2 = new Point(Insideoffset + Insidewidth, 0) };
+ pf.Segments.Add(seg7);
+
+ //第三横线
+ LineSegment seg8 = new LineSegment() { Point = new Point(x - 2, 0) };
+ pf.Segments.Add(seg8);
+
+ //第四竖线
+ ArcSegment seg9 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(x, 2) };
+ pf.Segments.Add(seg9);
+
+ LineSegment seg10 = new LineSegment() { Point = new Point(x, y0 - 2) };
+ pf.Segments.Add(seg10);
+
+ //第五横线
+ ArcSegment seg11 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(x - 2, y0) };
+ pf.Segments.Add(seg11);
+
+ LineSegment seg12 = new LineSegment() { Point = new Point(Leftpanelwidth + Insideoffset + Insidewidth, y0) };
+ pf.Segments.Add(seg12);
+
+ //第六in
+ QuadraticBezierSegment seg13 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + Insideoffset + Insidewidth - 1, y0), Point2 = new Point(Leftpanelwidth + Insideoffset + Insidewidth - 2, y0 + 2) };
+ pf.Segments.Add(seg13);
+
+ QuadraticBezierSegment seg14 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + Insideoffset + Insidewidth - 4, y0 + Insideheight), Point2 = new Point(Leftpanelwidth + Insideoffset + Insidewidth - 5, y0 + Insideheight) };
+ pf.Segments.Add(seg14);
+
+ LineSegment seg15 = new LineSegment() { Point = new Point(Leftpanelwidth + Insideoffset + 5, y0 + Insideheight) };
+ pf.Segments.Add(seg15);
+
+ QuadraticBezierSegment seg16 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + Insideoffset + 4, y0 + Insideheight), Point2 = new Point(Leftpanelwidth + Insideoffset + 2, y0 + 2) };
+ pf.Segments.Add(seg16);
+
+ QuadraticBezierSegment seg17 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + Insideoffset + 1, y0), Point2 = new Point(Insideoffset, y0) };
+ pf.Segments.Add(seg17);
+
+ //第七横线
+ LineSegment seg18 = new LineSegment() { Point = new Point(Leftpanelwidth + 2, y0) };
+ pf.Segments.Add(seg18);
+
+ ArcSegment seg19 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Counterclockwise, Point = new Point(Leftpanelwidth, y0 + 2) };
+ pf.Segments.Add(seg19);
+
+ //第八竖线
+ LineSegment seg20 = new LineSegment() { Point = new Point(Leftpanelwidth, y0 + y1 - 2) };
+ pf.Segments.Add(seg20);
+
+ ArcSegment seg21 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Counterclockwise, Point = new Point(Leftpanelwidth + 2, y0 + y1) };
+ pf.Segments.Add(seg21);
+
+ //第九横线
+ LineSegment seg22 = new LineSegment() { Point = new Point(Leftpanelwidth + Insideoffset, y0 + y1) };
+ pf.Segments.Add(seg22);
+
+ //第十in
+ QuadraticBezierSegment seg23 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + Insideoffset + 1, y0 + y1), Point2 = new Point(Leftpanelwidth + Insideoffset + 2, y0 + y1 + 2) };
+ pf.Segments.Add(seg23);
+
+ QuadraticBezierSegment seg24 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + Insideoffset + 4, y0 + y1 + Insideheight), Point2 = new Point(Leftpanelwidth + Insideoffset + 5, y0 + y1 + Insideheight) };
+ pf.Segments.Add(seg24);
+
+ LineSegment seg25 = new LineSegment() { Point = new Point(Leftpanelwidth + Insideoffset + Insidewidth - 5, y0 + y1 + Insideheight) };
+ pf.Segments.Add(seg25);
+
+ QuadraticBezierSegment seg26 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + Insideoffset + Insidewidth - 4, y0 + y1 + Insideheight), Point2 = new Point(Leftpanelwidth + Insideoffset + Insidewidth - 2, y0 + y1 + 2) };
+ pf.Segments.Add(seg26);
+
+ QuadraticBezierSegment seg27 = new QuadraticBezierSegment() { Point1 = new Point(Leftpanelwidth + Insideoffset + Insidewidth - 1, y0 + y1), Point2 = new Point(Leftpanelwidth + Insideoffset + Insidewidth, y0 + y1) };
+ pf.Segments.Add(seg27);
+
+ //第十一横线
+ LineSegment seg28 = new LineSegment() { Point = new Point(x - 2, y0 + y1) };
+ pf.Segments.Add(seg28);
+
+ //第十二竖线
+ ArcSegment seg29 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(x, y0 + y1 + 2) };
+ pf.Segments.Add(seg29);
+
+ LineSegment seg30 = new LineSegment() { Point = new Point(x, y0 + y1 + y2 - 2) };
+ pf.Segments.Add(seg30);
+
+ //第十三横线
+ ArcSegment seg31 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(x - 2, y0 + y1 + y2) };
+ pf.Segments.Add(seg31);
+
+ LineSegment seg32 = new LineSegment() { Point = new Point(Insideoffset + Insidewidth, y0 + y1 + y2) };
+ pf.Segments.Add(seg32);
+
+ //第十四in
+ QuadraticBezierSegment seg33 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + Insidewidth - 1, y0 + y1 + y2), Point2 = new Point(Insideoffset + Insidewidth - 2, y0 + y1 + y2 + 2) };
+ pf.Segments.Add(seg33);
+
+ QuadraticBezierSegment seg34 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + Insidewidth - 4, y0 + y1 + y2 + Insideheight), Point2 = new Point(Insideoffset + Insidewidth - 5, y0 + y1 + y2 + Insideheight) };
+ pf.Segments.Add(seg34);
+
+ LineSegment seg35 = new LineSegment() { Point = new Point(Insideoffset + 5, y0 + y1 + y2 + Insideheight) };
+ pf.Segments.Add(seg35);
+
+ QuadraticBezierSegment seg36 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + 4, y0 + y1 + y2 + Insideheight), Point2 = new Point(Insideoffset + 2, y0 + y1 + y2 + 2) };
+ pf.Segments.Add(seg36);
+
+ QuadraticBezierSegment seg37 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + 1, y0 + y1 + y2), Point2 = new Point(Insideoffset, y0 + y1 + y2) };
+ pf.Segments.Add(seg37);
+
+ //第十五横线
+ LineSegment seg38 = new LineSegment() { Point = new Point(2, y0 + y1 + y2) };
+ pf.Segments.Add(seg38);
+
+ ArcSegment seg39 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(0, y0 + y1 + y2 - 2) };
+ pf.Segments.Add(seg39);
+
+ PathGeometry g1 = new PathGeometry();
+ g1.Figures.Add(pf);
+ #endregion
+
+ return g1;
+ }
+
+ #endregion
+ }
+}
diff --git a/Extensions/AIStudio.Wpf.Block/Controls/OperationBlockBorder.cs b/Extensions/AIStudio.Wpf.Block/Controls/OperationBlockBorder.cs
new file mode 100644
index 0000000..723afb1
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/Controls/OperationBlockBorder.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Windows;
+using System.Windows.Media;
+
+namespace AIStudio.Wpf.Block.Controls
+{
+ public class OperationBlockBorder : BlockDecorator
+ {
+ public OperationBlockBorder()
+ {
+
+ }
+
+ #region 方法重写
+ public double Minwidth { get; set; } = 100;
+ public double Minheight { get; set; } = 30;
+
+ ///
+ /// 该方法用于测量整个控件的大小
+ ///
+ ///
+ /// 控件的大小
+ protected override Size MeasureOverride(Size constraint)
+ {
+ Thickness padding = this.Padding;
+
+ Size result = new Size();
+ if (Child != null)
+ {
+ //测量子控件的大小
+ Child.Measure(constraint);
+
+ result.Width = Math.Max(Minwidth, Child.DesiredSize.Width + padding.Left + padding.Right);
+ result.Height = Math.Max(Minheight, Child.DesiredSize.Height + padding.Top + padding.Bottom);
+ }
+ else
+ {
+ result.Width = Minwidth;
+ result.Height = Minheight;
+ }
+ return result;
+ }
+
+ ///
+ /// 设置子控件的大小与位置
+ ///
+ ///
+ ///
+ protected override Size ArrangeOverride(Size arrangeSize)
+ {
+ Thickness padding = this.Padding;
+ if (Child != null)
+ {
+ Child.Arrange(new Rect(new Point(padding.Left, padding.Top),
+ new Size(Math.Max(Minwidth - padding.Left - padding.Right, Child.DesiredSize.Width), Math.Max(Minheight - padding.Top - padding.Bottom, Child.DesiredSize.Height))));
+ }
+ return arrangeSize;
+ }
+
+ ///
+ /// 绘制控件
+ ///
+ ///
+ protected override void OnRender(DrawingContext drawingContext)
+ {
+ Thickness padding = this.Padding;
+
+ Pen pen = new Pen();
+ pen.Brush = this.BorderBrush;
+ pen.Thickness = this.BorderThickness.Left;// NextForBlockBorder.RoundLayoutValue(BorderThickness.Left, DoubleUtil.DpiScaleX);
+
+ Geometry cg = CreateGeometry(Math.Max(Minwidth, Child?.DesiredSize.Width ?? 0 + padding.Left + padding.Right), Math.Max(Minheight, Child?.DesiredSize.Height ?? 0 + padding.Top + padding.Bottom));
+ Brush brush = CreateFillBrush();
+
+ GuidelineSet guideLines = new GuidelineSet();
+ drawingContext.PushGuidelineSet(guideLines);
+ drawingContext.DrawGeometry(brush, pen, cg);
+ }
+ #endregion
+
+ #region 私有方法
+ //按Element的大小计算
+ private Geometry CreateGeometry(double x, double y)
+ {
+ #region
+ PathFigure pf = new PathFigure();
+ pf.IsClosed = true;
+ pf.StartPoint = new Point(0, y/ 2 + 1);
+
+
+ LineSegment seg1 = new LineSegment() { Point = new Point(y / 2 + 1, 0) };
+ pf.Segments.Add(seg1);
+
+ LineSegment seg2 = new LineSegment() { Point = new Point(x - y / 2 - 1, 0) };
+ pf.Segments.Add(seg2);
+
+ LineSegment seg3 = new LineSegment() { Point = new Point(x, y / 2) };
+ pf.Segments.Add(seg3);
+
+ LineSegment seg4 = new LineSegment() { Point = new Point(x - y / 2 - 1, y) };
+ pf.Segments.Add(seg4);
+
+ LineSegment seg5 = new LineSegment() { Point = new Point(y / 2 + 1, y) };
+ pf.Segments.Add(seg5);
+
+ PathGeometry g1 = new PathGeometry();
+ g1.Figures.Add(pf);
+ #endregion
+
+ return g1;
+ }
+ #endregion
+ }
+}
diff --git a/Extensions/AIStudio.Wpf.Block/Controls/StartBlockBorder.cs b/Extensions/AIStudio.Wpf.Block/Controls/StartBlockBorder.cs
new file mode 100644
index 0000000..393646e
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/Controls/StartBlockBorder.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Windows;
+using System.Windows.Media;
+
+namespace AIStudio.Wpf.Block.Controls
+{
+ public class StartBlockBorder : BlockDecorator
+ {
+ public StartBlockBorder()
+ {
+
+ }
+
+ #region 方法重写
+ public double Outsideheight { get; set; } = 13;
+ public double Outsidewidth { get; set; } = 70;
+ public double Insideheight { get; set; } = 6;
+ public double Insidewidth { get; set; } = 21;
+ public double Insideoffset { get; set; } = 14;
+ public double Minwidth { get; set; } = 86;
+ public double Minheight { get; set; } = 47;
+
+ ///
+ /// 该方法用于测量整个控件的大小
+ ///
+ ///
+ /// 控件的大小
+ protected override Size MeasureOverride(Size constraint)
+ {
+ Thickness padding = this.Padding;
+
+ Size result = new Size();
+ if (Child != null)
+ {
+ //测量子控件的大小
+ Child.Measure(constraint);
+
+ result.Width = Math.Max(Minwidth, Child.DesiredSize.Width + padding.Left + padding.Right);
+ result.Height = Math.Max(Minheight, Child.DesiredSize.Height + padding.Top + padding.Bottom + Outsideheight);
+ }
+ else
+ {
+ result.Width = Minwidth;
+ result.Height = Minheight;
+ }
+ return result;
+ }
+
+ ///
+ /// 设置子控件的大小与位置
+ ///
+ ///
+ ///
+ protected override Size ArrangeOverride(Size arrangeSize)
+ {
+ Thickness padding = this.Padding;
+ if (Child != null)
+ {
+ Child.Arrange(new Rect(new Point(padding.Left, Outsideheight + padding.Top),
+ new Size(Math.Max(Minwidth - padding.Left - padding.Right, Child.DesiredSize.Width), Math.Max(Minheight - Outsideheight - padding.Top - padding.Bottom, Child.DesiredSize.Height ))));
+ }
+ return arrangeSize;
+ }
+
+ ///
+ /// 绘制控件
+ ///
+ ///
+ protected override void OnRender(DrawingContext drawingContext)
+ {
+ Thickness padding = this.Padding;
+
+ Pen pen = new Pen();
+ pen.Brush = this.BorderBrush;
+ pen.Thickness = this.BorderThickness.Left;// NextForBlockBorder.RoundLayoutValue(BorderThickness.Left, DoubleUtil.DpiScaleX);
+
+ Geometry cg = CreateGeometry(Math.Max(Minwidth, Child?.DesiredSize.Width ?? 0 + padding.Left + padding.Right), Math.Max(Minheight - Outsideheight, Child?.DesiredSize.Height ?? 0 + padding.Top + padding.Bottom));
+ Brush brush = CreateFillBrush();
+
+ GuidelineSet guideLines = new GuidelineSet();
+ drawingContext.PushGuidelineSet(guideLines);
+ drawingContext.DrawGeometry(brush, pen, cg);
+ }
+ #endregion
+
+ #region 私有方法
+ //按Element的大小计算
+ private Geometry CreateGeometry(double x, double y)
+ {
+ #region
+ PathFigure pf = new PathFigure();
+ pf.IsClosed = true;
+ pf.StartPoint = new Point(0, Outsideheight);
+
+ //第一横线
+ QuadraticBezierSegment seg1 = new QuadraticBezierSegment() { Point1 = new Point(Outsidewidth / 2, 3 - Outsideheight), Point2 = new Point(Outsidewidth, Outsideheight) };
+ pf.Segments.Add(seg1);
+
+ LineSegment seg2 = new LineSegment() { Point = new Point(x - 2, Outsideheight) };
+ pf.Segments.Add(seg2);
+
+ //第二竖线
+ ArcSegment seg3 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(x, Outsideheight + 2) };
+ pf.Segments.Add(seg3);
+
+ LineSegment seg4 = new LineSegment() { Point = new Point(x, Outsideheight + y - 2) };
+ pf.Segments.Add(seg4);
+
+ //第三横线
+ ArcSegment seg5 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(x - 2, Outsideheight + y) };
+ pf.Segments.Add(seg5);
+
+ LineSegment seg6 = new LineSegment() { Point = new Point(Insideoffset + Insidewidth, Outsideheight + y) };
+ pf.Segments.Add(seg6);
+
+ //第四in
+ QuadraticBezierSegment seg7 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + Insidewidth - 1, Outsideheight + y), Point2 = new Point(Insideoffset + Insidewidth - 2, Outsideheight + y + 2) };
+ pf.Segments.Add(seg7);
+
+ QuadraticBezierSegment seg8 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + Insidewidth - 4, Outsideheight + y + Insideheight), Point2 = new Point(Insideoffset + Insidewidth - 5, Outsideheight + y + Insideheight) };
+ pf.Segments.Add(seg8);
+
+ LineSegment seg9 = new LineSegment() { Point = new Point(Insideoffset + 5, Outsideheight + y + Insideheight) };
+ pf.Segments.Add(seg9);
+
+ QuadraticBezierSegment seg10 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + 4, Outsideheight + y + Insideheight), Point2 = new Point(Insideoffset + 2, Outsideheight + y + 2) };
+ pf.Segments.Add(seg10);
+
+ QuadraticBezierSegment seg11 = new QuadraticBezierSegment() { Point1 = new Point(Insideoffset + 1, Outsideheight + y), Point2 = new Point(Insideoffset, Outsideheight + y) };
+ pf.Segments.Add(seg11);
+
+ //第五横线
+ LineSegment seg12 = new LineSegment() { Point = new Point(2, Outsideheight + y) };
+ pf.Segments.Add(seg12);
+
+ ArcSegment seg13 = new ArcSegment() { Size = new Size(2, 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(0, Outsideheight + y - 2) };
+ pf.Segments.Add(seg13);
+
+ PathGeometry g1 = new PathGeometry();
+ g1.Figures.Add(pf);
+ #endregion
+
+ return g1;
+ }
+ #endregion
+ }
+}
diff --git a/Extensions/AIStudio.Wpf.Block/Controls/VariableBlockBorder.cs b/Extensions/AIStudio.Wpf.Block/Controls/VariableBlockBorder.cs
new file mode 100644
index 0000000..c4b6d2f
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/Controls/VariableBlockBorder.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Media;
+
+namespace AIStudio.Wpf.Block.Controls
+{
+ public class VariableBlockBorder : BlockDecorator
+ {
+ public VariableBlockBorder()
+ {
+
+ }
+
+ #region 方法重写
+ public double Minwidth { get; set; } = 64;
+ public double Minheight { get; set; } = 28;
+
+ ///
+ /// 该方法用于测量整个控件的大小
+ ///
+ ///
+ /// 控件的大小
+ protected override Size MeasureOverride(Size constraint)
+ {
+ Thickness padding = this.Padding;
+
+ Size result = new Size();
+ if (Child != null)
+ {
+ //测量子控件的大小
+ Child.Measure(constraint);
+
+ result.Width = Math.Max(Minwidth, Child.DesiredSize.Width + padding.Left + padding.Right);
+ result.Height = Math.Max(Minheight, Child.DesiredSize.Height + padding.Top + padding.Bottom);
+ }
+ else
+ {
+ result.Width = Minwidth;
+ result.Height = Minheight;
+ }
+ return result;
+ }
+
+ ///
+ /// 设置子控件的大小与位置
+ ///
+ ///
+ ///
+ protected override Size ArrangeOverride(Size arrangeSize)
+ {
+ Thickness padding = this.Padding;
+ if (Child != null)
+ {
+ Child.Arrange(new Rect(new Point(padding.Left, padding.Top),
+ new Size(Math.Max(Minwidth - padding.Left - padding.Right, Child.DesiredSize.Width), Math.Max(Minheight - padding.Top - padding.Bottom, Child.DesiredSize.Height))));
+ }
+ return arrangeSize;
+ }
+
+ ///
+ /// 绘制控件
+ ///
+ ///
+ protected override void OnRender(DrawingContext drawingContext)
+ {
+ Thickness padding = this.Padding;
+
+ Pen pen = new Pen();
+ pen.Brush = this.BorderBrush;
+ pen.Thickness = this.BorderThickness.Left;// NextForBlockBorder.RoundLayoutValue(BorderThickness.Left, DoubleUtil.DpiScaleX);
+
+ Geometry cg = CreateGeometry(Math.Max(Minwidth, Child?.DesiredSize.Width ?? 0 + padding.Left + padding.Right), Math.Max(Minheight, Child?.DesiredSize.Height ?? 0 + padding.Top + padding.Bottom));
+ Brush brush = CreateFillBrush();
+
+ GuidelineSet guideLines = new GuidelineSet();
+ drawingContext.PushGuidelineSet(guideLines);
+ drawingContext.DrawGeometry(brush, pen, cg);
+ }
+ #endregion
+
+ #region 私有方法
+ //按Element的大小计算
+ private Geometry CreateGeometry(double x, double y)
+ {
+ #region
+ PathFigure pf = new PathFigure();
+ pf.IsClosed = true;
+ pf.StartPoint = new Point(y / 2, 0);
+
+
+ LineSegment seg1 = new LineSegment() { Point = new Point(x - y / 2, 0) };
+ pf.Segments.Add(seg1);
+
+ ArcSegment seg2= new ArcSegment() { Size = new Size(y / 2, y / 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(x - y / 2, y) };
+ pf.Segments.Add(seg2);
+
+ LineSegment seg3 = new LineSegment() { Point = new Point(y / 2, y) };
+ pf.Segments.Add(seg3);
+
+ ArcSegment seg4 = new ArcSegment() { Size = new Size(y / 2, y / 2), SweepDirection = SweepDirection.Clockwise, Point = new Point(y / 2, 0) };
+ pf.Segments.Add(seg4);
+
+ PathGeometry g1 = new PathGeometry();
+ g1.Figures.Add(pf);
+ #endregion
+
+ return g1;
+ }
+ #endregion
+
+
+ }
+}
diff --git a/Extensions/AIStudio.Wpf.Block/Models/BlockType.cs b/Extensions/AIStudio.Wpf.Block/Models/BlockType.cs
new file mode 100644
index 0000000..617cf47
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/Models/BlockType.cs
@@ -0,0 +1,138 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AIStudio.Wpf.Block.Models
+{
+ public enum BlockType
+ {
+ //运动
+ [Description("移动")]
+ Move,
+ [Description("右转")]
+ TurnRight,
+ [Description("左转")]
+ TurnLeft,
+ [Description("移到")]
+ MoveTo,
+ [Description("移到坐标")]
+ MoveToPoint,
+ [Description("在几s内移到")]
+ TimeMoveTo,
+ [Description("在几s内移到坐标")]
+ TimeMoveToPoint,
+ [Description("面向方向")]
+ FaceTo,
+ [Description("面向鼠标")]
+ FaceToMouse,
+ [Description("将X坐标增加")]
+ PointXAdd,
+ [Description("将X坐标设为")]
+ PointXSet,
+ [Description("将Y坐标增加")]
+ PointYAdd,
+ [Description("将Y坐标设为")]
+ PointYSet,
+ [Description("碰到边缘就反弹")]
+ BorderBounce,
+ [Description("旋转方式")]
+ RotationMethod,
+ [Description("X坐标")]
+ PointX,
+ [Description("Y坐标")]
+ PointY,
+ [Description("方向")]
+ Direction,
+ //外观
+ //声音
+ //事件
+ [Description("当开始被点击")]
+ Start,
+ [Description("当键盘按下")]
+ KeyboardPress,
+ [Description("当角色被点击")]
+ WhenRoleClicked,
+ [Description("当背景切换")]
+ WhenBackgroundSwitch,
+ [Description("当大于")]
+ WhenGreaterThan,
+ [Description("当接收到")]
+ WhenReceivedMessage,
+ [Description("广播消息")]
+ BroadcastMessage,
+ [Description("广播消息并等待")]
+ BroadcastMessageAndWaiting,
+ [Description("等待1s")]
+ WaitTime,
+ [Description("循环执行")]
+ For,
+ [Description("一直执行")]
+ Always,
+ [Description("如果")]
+ If,
+ [Description("如果否则")]
+ IfElse,
+ [Description("等待条件")]
+ Wait,
+ [Description("重复执行直到")]
+ While,
+ [Description("停止")]
+ Stop,
+ [Description("克隆")]
+ Clone,
+ [Description("删除此克隆体")]
+ DeleteThisClone,
+ //侦测
+ //运算
+ [Description("加")]
+ Add,
+ [Description("减")]
+ Subtract,
+ [Description("乘")]
+ Multiply,
+ [Description("除")]
+ Division,
+ [Description("除")]
+ Random,
+ [Description("大于")]
+ GreaterThan,
+ [Description("小于")]
+ LessThan,
+ [Description("等于")]
+ EqualThan,
+ [Description("与")]
+ And,
+ [Description("或")]
+ Or,
+ [Description("不成立")]
+ Not,
+ [Description("字符串连接")]
+ StringAdd,
+ [Description("第几个字符")]
+ StringIndex,
+ [Description("字符数")]
+ StringLength,
+ [Description("包含")]
+ StringContain,
+ [Description("余数")]
+ Mod,
+ [Description("四舍五入")]
+ Round,
+ [Description("绝对值")]
+ Abs,
+ //变量
+ [Description("变量")]
+ Variable,
+ [Description("设为")]
+ SetValue,
+ [Description("增加")]
+ Increase,
+ [Description("显示变量")]
+ VariableVisable,
+ [Description("隐藏变量")]
+ VariableHidden,
+ }
+}
diff --git a/Extensions/AIStudio.Wpf.Block/Models/ConstParameter.cs b/Extensions/AIStudio.Wpf.Block/Models/ConstParameter.cs
new file mode 100644
index 0000000..440d0dd
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/Models/ConstParameter.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AIStudio.Wpf.Block.Models
+{
+ public class ConstParameter : IParameter
+ {
+ public double? Value
+ {
+ get;set;
+ }
+ }
+}
diff --git a/Extensions/AIStudio.Wpf.Block/Models/IParameter.cs b/Extensions/AIStudio.Wpf.Block/Models/IParameter.cs
new file mode 100644
index 0000000..bc51972
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/Models/IParameter.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AIStudio.Wpf.Block.Models
+{
+ public interface IParameter
+ {
+ //double Value
+ //{
+ // get;
+ //}
+ }
+}
diff --git a/Extensions/AIStudio.Wpf.Block/Models/VarParameter.cs b/Extensions/AIStudio.Wpf.Block/Models/VarParameter.cs
new file mode 100644
index 0000000..071af07
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/Models/VarParameter.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AIStudio.Wpf.Block.Models
+{
+ public class VarParameter : IParameter
+ {
+
+ }
+}
diff --git a/Extensions/AIStudio.Wpf.Block/Themes/BlockItemViewModel.xaml b/Extensions/AIStudio.Wpf.Block/Themes/BlockItemViewModel.xaml
new file mode 100644
index 0000000..33a35da
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/Themes/BlockItemViewModel.xaml
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Extensions/AIStudio.Wpf.Block/Themes/Brushes.xaml b/Extensions/AIStudio.Wpf.Block/Themes/Brushes.xaml
new file mode 100644
index 0000000..f9df8c8
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/Themes/Brushes.xaml
@@ -0,0 +1,30 @@
+
+
+ #ffbf00
+ #cc9900
+ White
+ #ffab19
+ #cf8b17
+ White
+ #59c059
+ #389438
+ White
+
+ #4cbf56
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Extensions/AIStudio.Wpf.Block/Themes/Geometries.xaml b/Extensions/AIStudio.Wpf.Block/Themes/Geometries.xaml
new file mode 100644
index 0000000..5ca17af
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/Themes/Geometries.xaml
@@ -0,0 +1,6 @@
+
+
+ M152.474 62.225c-26.856 0-56.286 21.748-56.286 48.663v802.451c0 26.798 28.773 48.653 55.579 48.653 26.789 0 56.286-21.857 56.286-48.663v-802.434c0-26.914-28.78-48.663-55.579-48.663zM730.146 129.011c-157.836 0-157.836-64.694-315.663-64.694-91.108 0-161.46 42.504-161.46 42.504l-0.658 484.313s71.010-42.446 162.119-42.446c157.827 0 157.827 64.694 315.663 64.694 98.74 0 197.923-51.845 197.923-51.845v-484.264s-99.183 51.737-197.923 51.737z
+
\ No newline at end of file
diff --git a/Extensions/AIStudio.Wpf.Block/ViewModels/ArithmeticModules/AddBlockItemViewModel.cs b/Extensions/AIStudio.Wpf.Block/ViewModels/ArithmeticModules/AddBlockItemViewModel.cs
new file mode 100644
index 0000000..30672f9
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/ViewModels/ArithmeticModules/AddBlockItemViewModel.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using AIStudio.Wpf.Block.Models;
+using AIStudio.Wpf.DiagramDesigner;
+using AIStudio.Wpf.DiagramDesigner.Models;
+
+namespace AIStudio.Wpf.Block.ViewModels
+{
+ public class AddBlockItemViewModel : BlockDesignerItemViewModel
+ {
+ public AddBlockItemViewModel()
+ {
+ }
+
+ public AddBlockItemViewModel(IDiagramViewModel root) : base(root)
+ {
+ }
+
+ public AddBlockItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
+ {
+ }
+
+ public AddBlockItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
+ {
+ }
+
+ protected override void InitNew()
+ {
+ ItemWidth = double.NaN;
+ ItemHeight = double.NaN;
+ Add1 = new ConstParameter();
+ Add2 = new ConstParameter();
+ }
+
+ private IParameter _add1;
+ public IParameter Add1
+ {
+ get
+ {
+ return _add1;
+ }
+ set
+ {
+ SetProperty(ref _add1, value);
+ }
+ }
+
+ private IParameter _add2;
+ public IParameter Add2
+ {
+ get
+ {
+ return _add2;
+ }
+ set
+ {
+ SetProperty(ref _add2, value);
+ }
+ }
+ }
+}
diff --git a/Extensions/AIStudio.Wpf.Block/ViewModels/ControlModules/ControlBlockItemViewModel.cs b/Extensions/AIStudio.Wpf.Block/ViewModels/ControlModules/ControlBlockItemViewModel.cs
new file mode 100644
index 0000000..30c86bd
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/ViewModels/ControlModules/ControlBlockItemViewModel.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using AIStudio.Wpf.DiagramDesigner;
+using AIStudio.Wpf.DiagramDesigner.Models;
+
+namespace AIStudio.Wpf.Block.ViewModels
+{
+ public class ControlBlockItemViewModel : BlockDesignerItemViewModel
+ {
+ public ControlBlockItemViewModel()
+ {
+ }
+
+ public ControlBlockItemViewModel(IDiagramViewModel root) : base(root)
+ {
+ }
+
+ public ControlBlockItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
+ {
+ }
+
+ public ControlBlockItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
+ {
+ }
+
+ protected override void InitNew()
+ {
+ ItemWidth = double.NaN;
+ ItemHeight = double.NaN;
+ AddConnector(new BlockConnectorInfo(this.Root, this, ConnectorOrientation.Bottom));
+ }
+ }
+}
diff --git a/Extensions/AIStudio.Wpf.Block/ViewModels/ControlModules/KeyboardPressBlockItemViewModel.cs b/Extensions/AIStudio.Wpf.Block/ViewModels/ControlModules/KeyboardPressBlockItemViewModel.cs
new file mode 100644
index 0000000..63114c4
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/ViewModels/ControlModules/KeyboardPressBlockItemViewModel.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using AIStudio.Wpf.DiagramDesigner;
+using AIStudio.Wpf.DiagramDesigner.Models;
+
+namespace AIStudio.Wpf.Block.ViewModels
+{
+ public class KeyboardPressBlockItemViewModel : ControlBlockItemViewModel
+ {
+ public KeyboardPressBlockItemViewModel()
+ {
+ }
+
+ public KeyboardPressBlockItemViewModel(IDiagramViewModel root) : base(root)
+ {
+ }
+
+ public KeyboardPressBlockItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
+ {
+ }
+
+ public KeyboardPressBlockItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
+ {
+ }
+
+ public List KeyItemsSource
+ {
+ get;set;
+ }
+
+ private string _key;
+ public string Key
+ {
+ get
+ {
+ return _key;
+ }
+ set
+ {
+ SetProperty(ref _key, value);
+ }
+ }
+ }
+}
diff --git a/Extensions/AIStudio.Wpf.Block/ViewModels/ControlModules/StartBlockItemViewModel.cs b/Extensions/AIStudio.Wpf.Block/ViewModels/ControlModules/StartBlockItemViewModel.cs
new file mode 100644
index 0000000..d5e3e1c
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/ViewModels/ControlModules/StartBlockItemViewModel.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using AIStudio.Wpf.DiagramDesigner;
+using AIStudio.Wpf.DiagramDesigner.Models;
+
+namespace AIStudio.Wpf.Block.ViewModels
+{
+ public class StartBlockItemViewModel : ControlBlockItemViewModel
+ {
+ public StartBlockItemViewModel()
+ {
+ }
+
+ public StartBlockItemViewModel(IDiagramViewModel root) : base(root)
+ {
+ }
+
+ public StartBlockItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
+ {
+ }
+
+ public StartBlockItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
+ {
+ }
+
+ }
+}
diff --git a/Extensions/AIStudio.Wpf.Block/ViewModels/EventModules/WaitTimeBlockItemViewModel.cs b/Extensions/AIStudio.Wpf.Block/ViewModels/EventModules/WaitTimeBlockItemViewModel.cs
new file mode 100644
index 0000000..e36318c
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/ViewModels/EventModules/WaitTimeBlockItemViewModel.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using AIStudio.Wpf.Block.Models;
+using AIStudio.Wpf.DiagramDesigner;
+using AIStudio.Wpf.DiagramDesigner.Models;
+
+namespace AIStudio.Wpf.Block.ViewModels
+{
+ public class WaitTimeBlockItemViewModel : BlockDesignerItemViewModel
+ {
+ public WaitTimeBlockItemViewModel()
+ {
+ }
+
+ public WaitTimeBlockItemViewModel(IDiagramViewModel root) : base(root)
+ {
+ }
+
+ public WaitTimeBlockItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
+ {
+ }
+
+ public WaitTimeBlockItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
+ {
+ }
+
+ protected override void InitNew()
+ {
+ ItemWidth = double.NaN;
+ ItemHeight = double.NaN;
+ Second = new ConstParameter();
+ }
+
+ private IParameter _second;
+ public IParameter Second
+ {
+ get
+ {
+ return _second;
+ }
+ set
+ {
+ SetProperty(ref _second, value);
+ }
+ }
+ }
+}
diff --git a/Extensions/AIStudio.Wpf.Block/ViewModels/VariableModules/VariableBlockItemViewModel.cs b/Extensions/AIStudio.Wpf.Block/ViewModels/VariableModules/VariableBlockItemViewModel.cs
new file mode 100644
index 0000000..ffe346c
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Block/ViewModels/VariableModules/VariableBlockItemViewModel.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using AIStudio.Wpf.Block.Models;
+using AIStudio.Wpf.DiagramDesigner;
+using AIStudio.Wpf.DiagramDesigner.Models;
+
+namespace AIStudio.Wpf.Block.ViewModels.VariableModules
+{
+ public class VariableBlockItemViewModel : BlockDesignerItemViewModel
+ {
+ public VariableBlockItemViewModel()
+ {
+ }
+
+ public VariableBlockItemViewModel(IDiagramViewModel root) : base(root)
+ {
+ }
+
+ public VariableBlockItemViewModel(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
+ {
+ }
+
+ public VariableBlockItemViewModel(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
+ {
+ }
+
+ protected override void InitNew()
+ {
+ ItemWidth = double.NaN;
+ ItemHeight = double.NaN;
+ Value = new VarParameter();
+ }
+
+ private IParameter _value;
+ public IParameter Value
+ {
+ get
+ {
+ return _value;
+ }
+ set
+ {
+ SetProperty(ref _value, value);
+ }
+ }
+ }
+}
diff --git a/Extensions/AIStudio.Wpf.SFC/AIStudio.Wpf.SFC_gn4tlqoy_wpftmp.csproj b/Extensions/AIStudio.Wpf.SFC/AIStudio.Wpf.SFC_gn4tlqoy_wpftmp.csproj
new file mode 100644
index 0000000..fa98620
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.SFC/AIStudio.Wpf.SFC_gn4tlqoy_wpftmp.csproj
@@ -0,0 +1,236 @@
+
+
+ AIStudio.Wpf.SFC
+ obj\Debug\
+ obj\
+ F:\aistudio.-wpf.-diagram\Extensions\AIStudio.Wpf.SFC\obj\
+ <_TargetAssemblyProjectName>AIStudio.Wpf.SFC
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Extensions/AIStudio.Wpf.SFC/AIStudio.Wpf.SFC_hjulhjj0_wpftmp.csproj b/Extensions/AIStudio.Wpf.SFC/AIStudio.Wpf.SFC_hjulhjj0_wpftmp.csproj
new file mode 100644
index 0000000..fa98620
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.SFC/AIStudio.Wpf.SFC_hjulhjj0_wpftmp.csproj
@@ -0,0 +1,236 @@
+
+
+ AIStudio.Wpf.SFC
+ obj\Debug\
+ obj\
+ F:\aistudio.-wpf.-diagram\Extensions\AIStudio.Wpf.SFC\obj\
+ <_TargetAssemblyProjectName>AIStudio.Wpf.SFC
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Extensions/AIStudio.Wpf.Script/AIStudio.Wpf.Script_5k10wu0u_wpftmp.csproj b/Extensions/AIStudio.Wpf.Script/AIStudio.Wpf.Script_5k10wu0u_wpftmp.csproj
new file mode 100644
index 0000000..59edb5e
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Script/AIStudio.Wpf.Script_5k10wu0u_wpftmp.csproj
@@ -0,0 +1,203 @@
+
+
+ AIStudio.Wpf.Script
+ obj\Debug\
+ obj\
+ F:\aistudio.-wpf.-diagram\Extensions\AIStudio.Wpf.Script\obj\
+ <_TargetAssemblyProjectName>AIStudio.Wpf.Script
+
+
+
+ true
+ AIStudio.Wpf.Controls
+ akwkevin
+ https://gitee.com/akwkevin
+ A.png
+
+
+ 1.0.6
+ 一个Wpf的脚本生成模块
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Extensions/AIStudio.Wpf.Script/AIStudio.Wpf.Script_a4fgwrgk_wpftmp.csproj b/Extensions/AIStudio.Wpf.Script/AIStudio.Wpf.Script_a4fgwrgk_wpftmp.csproj
new file mode 100644
index 0000000..abd163d
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Script/AIStudio.Wpf.Script_a4fgwrgk_wpftmp.csproj
@@ -0,0 +1,276 @@
+
+
+ AIStudio.Wpf.Script
+ obj\Debug\
+ obj\
+ F:\aistudio.-wpf.-diagram\Extensions\AIStudio.Wpf.Script\obj\
+ <_TargetAssemblyProjectName>AIStudio.Wpf.Script
+
+
+
+ true
+ AIStudio.Wpf.Controls
+ akwkevin
+ https://gitee.com/akwkevin
+ A.png
+
+
+ 1.0.6
+ 一个Wpf的脚本生成模块
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Extensions/AIStudio.Wpf.Script/AIStudio.Wpf.Script_l225ygvw_wpftmp.csproj b/Extensions/AIStudio.Wpf.Script/AIStudio.Wpf.Script_l225ygvw_wpftmp.csproj
new file mode 100644
index 0000000..abd163d
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Script/AIStudio.Wpf.Script_l225ygvw_wpftmp.csproj
@@ -0,0 +1,276 @@
+
+
+ AIStudio.Wpf.Script
+ obj\Debug\
+ obj\
+ F:\aistudio.-wpf.-diagram\Extensions\AIStudio.Wpf.Script\obj\
+ <_TargetAssemblyProjectName>AIStudio.Wpf.Script
+
+
+
+ true
+ AIStudio.Wpf.Controls
+ akwkevin
+ https://gitee.com/akwkevin
+ A.png
+
+
+ 1.0.6
+ 一个Wpf的脚本生成模块
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Extensions/AIStudio.Wpf.Script/AIStudio.Wpf.Script_vs4rptnz_wpftmp.csproj b/Extensions/AIStudio.Wpf.Script/AIStudio.Wpf.Script_vs4rptnz_wpftmp.csproj
new file mode 100644
index 0000000..186a2f4
--- /dev/null
+++ b/Extensions/AIStudio.Wpf.Script/AIStudio.Wpf.Script_vs4rptnz_wpftmp.csproj
@@ -0,0 +1,268 @@
+
+
+ AIStudio.Wpf.Script
+ obj\Debug\
+ obj\
+ F:\aistudio.-wpf.-diagram\Extensions\AIStudio.Wpf.Script\obj\
+ <_TargetAssemblyProjectName>AIStudio.Wpf.Script
+
+
+
+ true
+ AIStudio.Wpf.Controls
+ akwkevin
+ https://gitee.com/akwkevin
+ A.png
+
+
+ 1.0.6
+ 一个Wpf的脚本生成模块
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file