From 4870a2fd0ed7a723a7c6d47ad58e8311520733b6 Mon Sep 17 00:00:00 2001 From: kwai Date: Mon, 19 Jun 2023 15:47:39 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=8F=E5=B0=8F=E6=95=B4=E7=90=86=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ViewModels/PageViewModel.cs | 23 +- .../Models/Serializables/DiagramItem.cs | 2 + .../BaseViewModel/DiagramViewModel.cs | 513 +----------------- .../BaseViewModel/DiagramViewModelHelper.cs | 452 ++++++++++++++- .../BlockDesignerItemViewModel.cs | 0 .../BlockViewModel/BlockDiagramViewModel.cs | 78 +++ .../ViewModels/IDiagramViewModel.cs | 11 +- 7 files changed, 539 insertions(+), 540 deletions(-) rename AIStudio.Wpf.DiagramDesigner/ViewModels/{DefaultViewModel => BlockViewModel}/BlockDesignerItemViewModel.cs (100%) create mode 100644 AIStudio.Wpf.DiagramDesigner/ViewModels/BlockViewModel/BlockDiagramViewModel.cs diff --git a/AIStudio.Wpf.DiagramApp/ViewModels/PageViewModel.cs b/AIStudio.Wpf.DiagramApp/ViewModels/PageViewModel.cs index 71d5659..e8ca2dc 100644 --- a/AIStudio.Wpf.DiagramApp/ViewModels/PageViewModel.cs +++ b/AIStudio.Wpf.DiagramApp/ViewModels/PageViewModel.cs @@ -392,16 +392,7 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels foreach (var diagramItem in diagramDocument.DiagramItems) { var viewModel = GetDiagramViewModel(diagramItem.Name, diagramItem.DiagramType, false); - viewModel.DiagramOption.LayoutOption.ShowGrid = diagramItem.ShowGrid; - viewModel.DiagramOption.LayoutOption.PhysicalGridCellSize = diagramItem.PhysicalGridCellSize; - viewModel.DiagramOption.LayoutOption.CellHorizontalAlignment = diagramItem.CellHorizontalAlignment; - viewModel.DiagramOption.LayoutOption.CellVerticalAlignment = diagramItem.CellVerticalAlignment; - viewModel.DiagramOption.LayoutOption.PageSizeOrientation = diagramItem.PageSizeOrientation; - viewModel.DiagramOption.LayoutOption.PhysicalPageSize = diagramItem.PhysicalPageSize; - viewModel.DiagramOption.LayoutOption.PageSizeType = diagramItem.PageSizeType; - viewModel.DiagramOption.LayoutOption.PhysicalGridMarginSize = diagramItem.PhysicalGridMarginSize; - viewModel.DiagramOption.LayoutOption.GridColor = diagramItem.GridColor; - viewModel.DiagramOption.LayoutOption.AllowDrop = diagramItem.AllowDrop; + viewModel.Init(diagramItem); foreach (var diagramItemData in diagramItem.DesignerItems) { @@ -430,8 +421,6 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels viewModel.Items.Add(connectionVM); } - viewModel.Thumbnail = diagramItem.Thumbnail.ToBrush((int)viewModel.DiagramOption.LayoutOption.PageSize.Width / 4, (int)viewModel.DiagramOption.LayoutOption.PageSize.Height / 4); - viewModels.Add(viewModel); } DiagramViewModels = new ObservableCollection(viewModels); @@ -473,7 +462,7 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels diagramItem.DesignerItems = selectedDesignerItems.Select(p => p.ToSerializableItem(ext)).Where(p => p != null).ToList(); diagramItem.Connections = selectedConnections.Select(p => p.ToSerializableItem(ext)).Where(p => p != null).ToList(); - diagramItem.Thumbnail = viewModel.Thumbnail.ToBase64String(); + diagramDocument.DiagramItems.Add(diagramItem); } @@ -511,7 +500,7 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels protected virtual DiagramViewModel GetDiagramViewModel(string name, DiagramType diagramType, bool initNew) { - return new DiagramViewModel() { Name = name ?? NewNameHelper.GetNewName(DiagramViewModels.Select(p => p.Name), "页-"), DiagramType = diagramType }; + return new BlockDiagramViewModel() { Name = name ?? NewNameHelper.GetNewName(DiagramViewModels.Select(p => p.Name), "页-"), DiagramType = diagramType }; } public void AddCopyPageExecuted(object para) @@ -526,10 +515,9 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels diagramItem.DesignerItems = selectedDesignerItems.Select(p => p.ToSerializableItem("json")).Where(p => p != null).ToList(); diagramItem.Connections = selectedConnections.Select(p => p.ToSerializableItem("json")).Where(p => p != null).ToList(); - diagramItem.Thumbnail = viewModel.Thumbnail.ToBase64String(); - viewModel = new DiagramViewModel(diagramItem); - viewModel.Name = NewNameHelper.GetNewName(DiagramViewModels.Select(p => p.Name), "页-"); + viewModel = GetDiagramViewModel(NewNameHelper.GetNewName(DiagramViewModels.Select(p => p.Name), "页-"), diagramItem.DiagramType, false); + viewModel.Init(diagramItem); foreach (var diagramItemData in diagramItem.DesignerItems) { @@ -556,7 +544,6 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels connectionVM.Id = Guid.NewGuid(); viewModel.Items.Add(connectionVM); } - viewModel.Thumbnail = diagramItem.Thumbnail.ToBrush((int)viewModel.DiagramOption.LayoutOption.PageSize.Width / 4, (int)viewModel.DiagramOption.LayoutOption.PageSize.Height / 4); DiagramViewModels.Add(viewModel); DiagramViewModel = viewModel; diff --git a/AIStudio.Wpf.DiagramDesigner/Models/Serializables/DiagramItem.cs b/AIStudio.Wpf.DiagramDesigner/Models/Serializables/DiagramItem.cs index 7dd754c..74105a5 100644 --- a/AIStudio.Wpf.DiagramDesigner/Models/Serializables/DiagramItem.cs +++ b/AIStudio.Wpf.DiagramDesigner/Models/Serializables/DiagramItem.cs @@ -31,6 +31,8 @@ namespace AIStudio.Wpf.DiagramDesigner PhysicalGridMarginSize = diagramView.DiagramOption.LayoutOption.PhysicalGridMarginSize; GridColor = diagramView.DiagramOption.LayoutOption.GridColor; AllowDrop = diagramView.DiagramOption.LayoutOption.AllowDrop; + + Thumbnail = diagramView.Thumbnail.ToBase64String(); } [XmlAttribute] diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModel.cs index f38ab81..ad6ec93 100644 --- a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModel.cs +++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModel.cs @@ -814,42 +814,6 @@ namespace AIStudio.Wpf.DiagramDesigner return this._replaceAllCommand ?? (this._replaceAllCommand = new SimpleCommand(ExecuteEnable, this.ExecutedSearchReplaceAllCommand)); } } - - private ICommand _addNextCommand; - public ICommand AddNextCommand - { - get - { - return this._addNextCommand ?? (this._addNextCommand = new SimpleCommand(ExecuteEnable, this.ExecutedAddNextCommand)); - } - } - - private ICommand _removeNextCommand; - public ICommand RemoveNextCommand - { - get - { - return this._removeNextCommand ?? (this._removeNextCommand = new SimpleCommand(ExecuteEnable, this.ExecutedRemoveNextCommand)); - } - } - - private ICommand _addChildCommand; - public ICommand AddChildCommand - { - get - { - return this._addChildCommand ?? (this._addChildCommand = new SimpleCommand(ExecuteEnable, this.ExecutedAddChildCommand)); - } - } - - private ICommand _removeChildCommand; - public ICommand RemoveChildCommand - { - get - { - return this._removeChildCommand ?? (this._removeChildCommand = new SimpleCommand(ExecuteEnable, this.ExecutedRemoveChildCommand)); - } - } #endregion #region ctor和初始化 @@ -863,7 +827,7 @@ namespace AIStudio.Wpf.DiagramDesigner BuildMenuOptions(); } - public DiagramViewModel(DiagramItem diagramItem) : this() + public void Init(DiagramItem diagramItem) { DiagramType = diagramItem.DiagramType; DiagramOption.LayoutOption.ShowGrid = diagramItem.ShowGrid; @@ -877,6 +841,7 @@ namespace AIStudio.Wpf.DiagramDesigner DiagramOption.LayoutOption.GridColor = diagramItem.GridColor; DiagramOption.LayoutOption.AllowDrop = diagramItem.AllowDrop; + Thumbnail = diagramItem.Thumbnail.ToBrush((int)DiagramOption.LayoutOption.PageSize.Width / 4, (int)DiagramOption.LayoutOption.PageSize.Height / 4); Init(true); } @@ -1557,30 +1522,6 @@ namespace AIStudio.Wpf.DiagramDesigner } #endregion - #region Block使用 - private void ExecutedAddNextCommand(object parameter) - { - if (parameter is Tuple blockTuple) - { - } - - } - - private void ExecutedRemoveNextCommand(object parameter) - { - - } - - private void ExecutedAddChildCommand(object parameter) - { - - } - private void ExecutedRemoveChildCommand(object parameter) - { - - } - #endregion - #region 布局 private void ExecuteAlignTopCommand(object parameter) { @@ -3040,456 +2981,6 @@ namespace AIStudio.Wpf.DiagramDesigner } #endregion - #region 自动依附节点 - public FullyCreatedConnectorInfo FindNearPortToAttachTo(ConnectionViewModel partialConnection, ConnectorVertexType connectorVertexType) - { - if (partialConnection == null) - return null; - - ClearNearPort(); - foreach (var port in Items.OfType().ToList().SelectMany(n => n.Connectors)) - { - if (connectorVertexType == ConnectorVertexType.Start) - { - if (partialConnection.SourceConnectorInfo.Position.DistanceTo(port.Position) < DiagramOption.SnappingOption.SnappingRadius) - { - if (partialConnection.SinkConnectorInfo?.CanAttachTo(port) == true) - { - port.DataItem.ShowConnectors = true; - port.BeAttachTo = true; - return port; - } - else - { - port.DataItem.ShowConnectors = true; - port.DisableAttachTo = true; - return null; - } - } - } - else if (connectorVertexType == ConnectorVertexType.End) - { - if (partialConnection.SinkConnectorInfo.Position.DistanceTo(port.Position) < DiagramOption.SnappingOption.SnappingRadius) - { - if (partialConnection.SourceConnectorInfo?.CanAttachTo(port) == true) - { - port.DataItem.ShowConnectors = true; - port.BeAttachTo = true; - return port; - } - else - { - port.DataItem.ShowConnectors = true; - port.DisableAttachTo = true; - return null; - } - } - } - } - - return null; - } - - public FullyCreatedConnectorInfo FindNearPortToAttachTo(ConnectionViewModel partialConnection) - { - if (partialConnection == null) - return null; - - ClearNearPort(); - foreach (var port in Items.OfType().ToList().SelectMany(n => n.Connectors)) - { - if (partialConnection.OnGoingPosition.DistanceTo(port.Position) < DiagramOption.SnappingOption.SnappingRadius) - { - port.DataItem.ShowConnectors = true; - if (partialConnection.SourceConnectorInfo?.CanAttachTo(port) == true) - { - port.BeAttachTo = true; - return port; - } - else - { - port.DisableAttachTo = true; - return null; - } - - } - } - - return null; - } - - /// - /// type=0最近且没有依附;=1 - /// - /// - /// - /// - public Tuple FindNearPortToAttachTo(BlockDesignerItemViewModel blockDesignerItemViewModel, bool isExist) - { - if (blockDesignerItemViewModel == null) - return new Tuple(null, null); - - List items; - if (isExist == false) - { - items = Items.OfType(). - Where(p => p != blockDesignerItemViewModel && p != blockDesignerItemViewModel.Parent && p != blockDesignerItemViewModel.Next) - .ToList(); - - } - else - { - items = Items.OfType(). - Where(p => p != blockDesignerItemViewModel) - .ToList(); - } - - FullyCreatedConnectorInfo parent = null; - FullyCreatedConnectorInfo next = null; - - foreach (var port in items.SelectMany(n => n.Connectors)) - { - foreach (var port2 in blockDesignerItemViewModel.Connectors) - { - //parent - if (parent == null) - { - if ((port.Orientation == ConnectorOrientation.Right && port2.Orientation == ConnectorOrientation.Left) - || (port.Orientation == ConnectorOrientation.Bottom && port2.Orientation == ConnectorOrientation.Top)) - { - - if (port.Position.DistanceTo(port2.Position) < DiagramOption.SnappingOption.SnappingRadius) - { - port.DataItem.ShowConnectors = true; - if (port2.CanAttachTo(port) == true) - { - port.BeAttachTo = true; - parent = port; - continue; - } - else - { - port.DisableAttachTo = true; - } - - } - } - } - - //next - if (next == null) - { - if ((port.Orientation == ConnectorOrientation.Left && port2.Orientation == ConnectorOrientation.Right) - || (port.Orientation == ConnectorOrientation.Top && port2.Orientation == ConnectorOrientation.Bottom)) - { - - if (port.Position.DistanceTo(port2.Position) < DiagramOption.SnappingOption.SnappingRadius) - { - port.DataItem.ShowConnectors = true; - if (port2.CanAttachTo(port) == true) - { - port.BeAttachTo = true; - next = port; - continue; - } - else - { - port.DisableAttachTo = true; - } - - } - } - } - } - } - - return new Tuple(parent, next); - } - - public BlockItemsContainerInfo 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.Containers)) - { - if (port.GetBounds().IntersectsWith(blockDesignerItemViewModel.GetBounds())) //如果两个位置相交 - { - var innerport = port.GetAllContainers(port.Children, false).Where(p => p.GetBounds().IntersectsWith(blockDesignerItemViewModel.GetBounds())).OrderByDescending(p => p.ContainerLevel).FirstOrDefault(); - if (innerport != null) - { - innerport.DataItem.ShowConnectors = true; - if (innerport.CanAttachTo(blockDesignerItemViewModel) == true) - { - innerport.BeAttachTo = true; - } - else - { - innerport.DisableAttachTo = true; - } - return innerport; - } - else - { - port.DataItem.ShowConnectors = true; - if (port.CanAttachTo(blockDesignerItemViewModel) == true) - { - port.BeAttachTo = true; - } - else - { - port.DisableAttachTo = true; - } - return port; - } - } - } - - return null; - } - - /// - /// type=0最近且没有依附;=1 - /// - /// - /// - /// - public Tuple FindNearPortToAttachTo(BlockDesignerItemTempLink blockDesignerItemTempLink, bool isExist) - { - if (blockDesignerItemTempLink == null || blockDesignerItemTempLink.Items == null || blockDesignerItemTempLink.Items.Count == 0) - return new Tuple(null, null); - - List items; - if (isExist == false) - { - items = Items.OfType().Where(p => !blockDesignerItemTempLink.Items.Contains(p)).ToList(); - } - else - { - items = Items.OfType().Where(p => !blockDesignerItemTempLink.Items.Contains(p)).ToList(); - } - - FullyCreatedConnectorInfo parent = null; - FullyCreatedConnectorInfo next = null; - - foreach (var port in items.SelectMany(n => n.Connectors).OfType()) - { - //已经被连接的不允许在顶部吸附了 - if ((port.Orientation == ConnectorOrientation.Top || port.Orientation == ConnectorOrientation.Left) && port.DataItem.Prev != null) - { - continue; - } - - foreach (var port2 in blockDesignerItemTempLink.Connectors) - { - //parent - if (parent == null) - { - if ((port.Orientation == ConnectorOrientation.Right && port2.Orientation == ConnectorOrientation.Left) - || (port.Orientation == ConnectorOrientation.Bottom && port2.Orientation == ConnectorOrientation.Top)) - { - - if (port.Position.DistanceTo(port2.Position) < DiagramOption.SnappingOption.SnappingRadius) - { - port.DataItem.ShowConnectors = true; - if (port2.CanAttachTo(port) == true) - { - port.BeAttachTo = true; - parent = port; - continue; - } - else - { - port.DisableAttachTo = true; - } - - } - } - } - - //next - if (next == null) - { - if ((port.Orientation == ConnectorOrientation.Left && port2.Orientation == ConnectorOrientation.Right) - || (port.Orientation == ConnectorOrientation.Top && port2.Orientation == ConnectorOrientation.Bottom)) - { - - if (port.Position.DistanceTo(port2.Position) < DiagramOption.SnappingOption.SnappingRadius) - { - port.DataItem.ShowConnectors = true; - if (port2.CanAttachTo(port) == true) - { - port.BeAttachTo = true; - next = port; - continue; - } - else - { - port.DisableAttachTo = true; - } - - } - } - } - } - } - - return new Tuple(parent, next); - } - - public BlockItemsContainerInfo FindNearContainerToAttachTo(BlockDesignerItemTempLink blockDesignerItemTempLink) - { - if (blockDesignerItemTempLink == null || blockDesignerItemTempLink.Items == null || blockDesignerItemTempLink.Items.Count == 0) - return null; - - List items; - - items = Items.OfType().Where(p => !blockDesignerItemTempLink.Items.Contains(p)).ToList(); - - foreach (var port in items.SelectMany(n => n.Containers)) - { - if (port.GetBounds().IntersectsWith(blockDesignerItemTempLink.GetBounds())) //如果两个位置相交 - { - var innerport = port.GetAllContainers(port.Children, false).Where(p => p.GetBounds().IntersectsWith(blockDesignerItemTempLink.GetBounds())).OrderByDescending(p => p.ContainerLevel).FirstOrDefault(); - if (innerport != null) - { - innerport.DataItem.ShowConnectors = true; - if (innerport.CanAttachTo(blockDesignerItemTempLink.Items.FirstOrDefault()) == true) - { - innerport.BeAttachTo = true; - return innerport; - } - //else - //{ - // innerport.DisableAttachTo = true; - // return null; - //} - - } - else - { - port.DataItem.ShowConnectors = true; - if (port.CanAttachTo(blockDesignerItemTempLink.Items.FirstOrDefault()) == true) - { - port.BeAttachTo = true; - return port; - } - //else - //{ - // port.DisableAttachTo = true; - // return null; - //} - } - } - } - - return null; - } - - public void ClearNearPort() - { - Items.OfType().ToList().SelectMany(n => n.Connectors).Where(p => p.BeAttachTo == true || p.DisableAttachTo == true).ToList() - .ForEach(p => { - p.DisableAttachTo = false; - p.BeAttachTo = false; - }); - } - - public void ClearNearContain() - { - Items.OfType().ToList().SelectMany(n => n.GetAllContainers()).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(); - var links = BlockDesignerItemTempLink.Build(blocks); - foreach (BlockDesignerItemTempLink item in links) - { - var container = FindNearContainerToAttachTo(item); - if (container != null) - { - continue; - } - FindNearPortToAttachTo(item, false); - } - } - } - - - - public void FinishNearBlock(List blocks) - { - if (blocks.Any()) - { - ClearNearPort(); - ClearNearContain(); - var links = BlockDesignerItemTempLink.Build(blocks); - - foreach (BlockDesignerItemTempLink item in links) - { - var container = FindNearContainerToAttachTo(item); - if (container != null) - { - container.DataItem.AddChild(item.Items.FirstOrDefault(), container);//待完善 - container.BeAttachTo = false; - container.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.Items.FirstOrDefault()); - portParent.BeAttachTo = false; - portParent.DisableAttachTo = false; - } - else - { - if (item.Items.FirstOrDefault().Parent != null) - { - (item.Items.FirstOrDefault().Parent as BlockDesignerItemViewModel).RemoveNext(); - } - } - - if (portNext != null) - { - item.Items.LastOrDefault().AddNext(portNext.DataItem as BlockDesignerItemViewModel); - portNext.BeAttachTo = false; - portNext.DisableAttachTo = false; - } - else - { - if (item.Items.LastOrDefault().Next != null) - { - item.Items.LastOrDefault().RemoveNext(); - } - } - } - } - } - - - #endregion - public override string ToString() { return $"{Name}-{DiagramType}"; diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModelHelper.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModelHelper.cs index 4ca1dd9..6a3523d 100644 --- a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModelHelper.cs +++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModelHelper.cs @@ -6,7 +6,7 @@ using AIStudio.Wpf.DiagramDesigner.Geometrys; namespace AIStudio.Wpf.DiagramDesigner { - public class DiagramViewModelHelper + public static class DiagramViewModelHelper { public static DesignerItemViewModelBase GetConnectorDataItem(IEnumerable items, Guid conectorDataItemId, Type connectorDataItemType) { @@ -37,5 +37,455 @@ namespace AIStudio.Wpf.DiagramDesigner { return GetBoundingRectangle(new DesignerItemViewModelBase[] { item }); } + + #region 自动依附节点 + public static FullyCreatedConnectorInfo FindNearPortToAttachTo(this IDiagramViewModel diagramViewModel, ConnectionViewModel partialConnection, ConnectorVertexType connectorVertexType) + { + if (partialConnection == null) + return null; + + diagramViewModel.ClearNearPort(); + foreach (var port in diagramViewModel.Items.OfType().ToList().SelectMany(n => n.Connectors)) + { + if (connectorVertexType == ConnectorVertexType.Start) + { + if (partialConnection.SourceConnectorInfo.Position.DistanceTo(port.Position) < diagramViewModel.DiagramOption.SnappingOption.SnappingRadius) + { + if (partialConnection.SinkConnectorInfo?.CanAttachTo(port) == true) + { + port.DataItem.ShowConnectors = true; + port.BeAttachTo = true; + return port; + } + else + { + port.DataItem.ShowConnectors = true; + port.DisableAttachTo = true; + return null; + } + } + } + else if (connectorVertexType == ConnectorVertexType.End) + { + if (partialConnection.SinkConnectorInfo.Position.DistanceTo(port.Position) < diagramViewModel.DiagramOption.SnappingOption.SnappingRadius) + { + if (partialConnection.SourceConnectorInfo?.CanAttachTo(port) == true) + { + port.DataItem.ShowConnectors = true; + port.BeAttachTo = true; + return port; + } + else + { + port.DataItem.ShowConnectors = true; + port.DisableAttachTo = true; + return null; + } + } + } + } + + return null; + } + + public static FullyCreatedConnectorInfo FindNearPortToAttachTo(this IDiagramViewModel diagramViewModel, ConnectionViewModel partialConnection) + { + if (partialConnection == null) + return null; + + diagramViewModel.ClearNearPort(); + foreach (var port in diagramViewModel.Items.OfType().ToList().SelectMany(n => n.Connectors)) + { + if (partialConnection.OnGoingPosition.DistanceTo(port.Position) < diagramViewModel.DiagramOption.SnappingOption.SnappingRadius) + { + port.DataItem.ShowConnectors = true; + if (partialConnection.SourceConnectorInfo?.CanAttachTo(port) == true) + { + port.BeAttachTo = true; + return port; + } + else + { + port.DisableAttachTo = true; + return null; + } + + } + } + + return null; + } + + /// + /// type=0最近且没有依附;=1 + /// + /// + /// + /// + public static Tuple FindNearPortToAttachTo(this IDiagramViewModel diagramViewModel, BlockDesignerItemViewModel blockDesignerItemViewModel, bool isExist) + { + if (blockDesignerItemViewModel == null) + return new Tuple(null, null); + + List items; + if (isExist == false) + { + items = diagramViewModel.Items.OfType(). + Where(p => p != blockDesignerItemViewModel && p != blockDesignerItemViewModel.Parent && p != blockDesignerItemViewModel.Next) + .ToList(); + + } + else + { + items = diagramViewModel.Items.OfType(). + Where(p => p != blockDesignerItemViewModel) + .ToList(); + } + + FullyCreatedConnectorInfo parent = null; + FullyCreatedConnectorInfo next = null; + + foreach (var port in items.SelectMany(n => n.Connectors)) + { + foreach (var port2 in blockDesignerItemViewModel.Connectors) + { + //parent + if (parent == null) + { + if ((port.Orientation == ConnectorOrientation.Right && port2.Orientation == ConnectorOrientation.Left) + || (port.Orientation == ConnectorOrientation.Bottom && port2.Orientation == ConnectorOrientation.Top)) + { + + if (port.Position.DistanceTo(port2.Position) < diagramViewModel.DiagramOption.SnappingOption.SnappingRadius) + { + port.DataItem.ShowConnectors = true; + if (port2.CanAttachTo(port) == true) + { + port.BeAttachTo = true; + parent = port; + continue; + } + else + { + port.DisableAttachTo = true; + } + + } + } + } + + //next + if (next == null) + { + if ((port.Orientation == ConnectorOrientation.Left && port2.Orientation == ConnectorOrientation.Right) + || (port.Orientation == ConnectorOrientation.Top && port2.Orientation == ConnectorOrientation.Bottom)) + { + + if (port.Position.DistanceTo(port2.Position) < diagramViewModel.DiagramOption.SnappingOption.SnappingRadius) + { + port.DataItem.ShowConnectors = true; + if (port2.CanAttachTo(port) == true) + { + port.BeAttachTo = true; + next = port; + continue; + } + else + { + port.DisableAttachTo = true; + } + + } + } + } + } + } + + return new Tuple(parent, next); + } + + public static BlockItemsContainerInfo FindNearContainerToAttachTo(this IDiagramViewModel diagramViewModel, BlockDesignerItemViewModel blockDesignerItemViewModel) + { + if (blockDesignerItemViewModel == null) + return null; + + List items; + + items = diagramViewModel.Items.OfType(). + Where(p => p != blockDesignerItemViewModel) + .ToList(); + + foreach (var port in items.SelectMany(n => n.Containers)) + { + if (port.GetBounds().IntersectsWith(blockDesignerItemViewModel.GetBounds())) //如果两个位置相交 + { + var innerport = port.GetAllContainers(port.Children, false).Where(p => p.GetBounds().IntersectsWith(blockDesignerItemViewModel.GetBounds())).OrderByDescending(p => p.ContainerLevel).FirstOrDefault(); + if (innerport != null) + { + innerport.DataItem.ShowConnectors = true; + if (innerport.CanAttachTo(blockDesignerItemViewModel) == true) + { + innerport.BeAttachTo = true; + } + else + { + innerport.DisableAttachTo = true; + } + return innerport; + } + else + { + port.DataItem.ShowConnectors = true; + if (port.CanAttachTo(blockDesignerItemViewModel) == true) + { + port.BeAttachTo = true; + } + else + { + port.DisableAttachTo = true; + } + return port; + } + } + } + + return null; + } + + /// + /// type=0最近且没有依附;=1 + /// + /// + /// + /// + public static Tuple FindNearPortToAttachTo(this IDiagramViewModel diagramViewModel, BlockDesignerItemTempLink blockDesignerItemTempLink, bool isExist) + { + if (blockDesignerItemTempLink == null || blockDesignerItemTempLink.Items == null || blockDesignerItemTempLink.Items.Count == 0) + return new Tuple(null, null); + + List items; + if (isExist == false) + { + items = diagramViewModel.Items.OfType().Where(p => !blockDesignerItemTempLink.Items.Contains(p)).ToList(); + } + else + { + items = diagramViewModel.Items.OfType().Where(p => !blockDesignerItemTempLink.Items.Contains(p)).ToList(); + } + + FullyCreatedConnectorInfo parent = null; + FullyCreatedConnectorInfo next = null; + + foreach (var port in items.SelectMany(n => n.Connectors).OfType()) + { + //已经被连接的不允许在顶部吸附了 + if ((port.Orientation == ConnectorOrientation.Top || port.Orientation == ConnectorOrientation.Left) && port.DataItem.Prev != null) + { + continue; + } + + foreach (var port2 in blockDesignerItemTempLink.Connectors) + { + //parent + if (parent == null) + { + if ((port.Orientation == ConnectorOrientation.Right && port2.Orientation == ConnectorOrientation.Left) + || (port.Orientation == ConnectorOrientation.Bottom && port2.Orientation == ConnectorOrientation.Top)) + { + + if (port.Position.DistanceTo(port2.Position) < diagramViewModel.DiagramOption.SnappingOption.SnappingRadius) + { + port.DataItem.ShowConnectors = true; + if (port2.CanAttachTo(port) == true) + { + port.BeAttachTo = true; + parent = port; + continue; + } + else + { + port.DisableAttachTo = true; + } + + } + } + } + + //next + if (next == null) + { + if ((port.Orientation == ConnectorOrientation.Left && port2.Orientation == ConnectorOrientation.Right) + || (port.Orientation == ConnectorOrientation.Top && port2.Orientation == ConnectorOrientation.Bottom)) + { + + if (port.Position.DistanceTo(port2.Position) < diagramViewModel.DiagramOption.SnappingOption.SnappingRadius) + { + port.DataItem.ShowConnectors = true; + if (port2.CanAttachTo(port) == true) + { + port.BeAttachTo = true; + next = port; + continue; + } + else + { + port.DisableAttachTo = true; + } + + } + } + } + } + } + + return new Tuple(parent, next); + } + + public static BlockItemsContainerInfo FindNearContainerToAttachTo(this IDiagramViewModel diagramViewModel, BlockDesignerItemTempLink blockDesignerItemTempLink) + { + if (blockDesignerItemTempLink == null || blockDesignerItemTempLink.Items == null || blockDesignerItemTempLink.Items.Count == 0) + return null; + + List items; + + items = diagramViewModel.Items.OfType().Where(p => !blockDesignerItemTempLink.Items.Contains(p)).ToList(); + + foreach (var port in items.SelectMany(n => n.Containers)) + { + if (port.GetBounds().IntersectsWith(blockDesignerItemTempLink.GetBounds())) //如果两个位置相交 + { + var innerport = port.GetAllContainers(port.Children, false).Where(p => p.GetBounds().IntersectsWith(blockDesignerItemTempLink.GetBounds())).OrderByDescending(p => p.ContainerLevel).FirstOrDefault(); + if (innerport != null) + { + innerport.DataItem.ShowConnectors = true; + if (innerport.CanAttachTo(blockDesignerItemTempLink.Items.FirstOrDefault()) == true) + { + innerport.BeAttachTo = true; + return innerport; + } + //else + //{ + // innerport.DisableAttachTo = true; + // return null; + //} + + } + else + { + port.DataItem.ShowConnectors = true; + if (port.CanAttachTo(blockDesignerItemTempLink.Items.FirstOrDefault()) == true) + { + port.BeAttachTo = true; + return port; + } + //else + //{ + // port.DisableAttachTo = true; + // return null; + //} + } + } + } + + return null; + } + + public static void ClearNearPort(this IDiagramViewModel diagramViewModel) + { + diagramViewModel.Items.OfType().ToList().SelectMany(n => n.Connectors).Where(p => p.BeAttachTo == true || p.DisableAttachTo == true).ToList() + .ForEach(p => { + p.DisableAttachTo = false; + p.BeAttachTo = false; + }); + } + + public static void ClearNearContain(this IDiagramViewModel diagramViewModel) + { + diagramViewModel.Items.OfType().ToList().SelectMany(n => n.GetAllContainers()).Where(p => p.BeAttachTo == true || p.DisableAttachTo == true).ToList() + .ForEach(p => { + p.DisableAttachTo = false; + p.BeAttachTo = false; + }); + } + #endregion + + #region Block拖拽预览-拖拽完成 + public static void PreviewNearBlock(this IDiagramViewModel diagramViewModel, List blocks) + { + if (blocks.Any()) + { + diagramViewModel.ClearNearPort(); + diagramViewModel.ClearNearContain(); + var links = BlockDesignerItemTempLink.Build(blocks); + foreach (BlockDesignerItemTempLink item in links) + { + var container = diagramViewModel.FindNearContainerToAttachTo(item); + if (container != null) + { + continue; + } + diagramViewModel.FindNearPortToAttachTo(item, false); + } + } + } + + + + public static void FinishNearBlock(this IDiagramViewModel diagramViewModel, List blocks) + { + if (blocks.Any()) + { + diagramViewModel.ClearNearPort(); + diagramViewModel.ClearNearContain(); + var links = BlockDesignerItemTempLink.Build(blocks); + + foreach (BlockDesignerItemTempLink item in links) + { + var container = diagramViewModel.FindNearContainerToAttachTo(item); + if (container != null) + { + container.DataItem.AddChild(item.Items.FirstOrDefault(), container);//待完善 + container.BeAttachTo = false; + container.DisableAttachTo = false; + continue; + } + + var portTuple = diagramViewModel.FindNearPortToAttachTo(item, true); + var portParent = portTuple.Item1; + var portNext = portTuple.Item2; + + if (portParent != null) + { + (portParent.DataItem as BlockDesignerItemViewModel).AddNext(item.Items.FirstOrDefault()); + portParent.BeAttachTo = false; + portParent.DisableAttachTo = false; + } + else + { + if (item.Items.FirstOrDefault().Parent != null) + { + (item.Items.FirstOrDefault().Parent as BlockDesignerItemViewModel).RemoveNext(); + } + } + + if (portNext != null) + { + item.Items.LastOrDefault().AddNext(portNext.DataItem as BlockDesignerItemViewModel); + portNext.BeAttachTo = false; + portNext.DisableAttachTo = false; + } + else + { + if (item.Items.LastOrDefault().Next != null) + { + item.Items.LastOrDefault().RemoveNext(); + } + } + } + } + } + + + #endregion } } diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/DefaultViewModel/BlockDesignerItemViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BlockViewModel/BlockDesignerItemViewModel.cs similarity index 100% rename from AIStudio.Wpf.DiagramDesigner/ViewModels/DefaultViewModel/BlockDesignerItemViewModel.cs rename to AIStudio.Wpf.DiagramDesigner/ViewModels/BlockViewModel/BlockDesignerItemViewModel.cs diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BlockViewModel/BlockDiagramViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BlockViewModel/BlockDiagramViewModel.cs new file mode 100644 index 0000000..c762243 --- /dev/null +++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BlockViewModel/BlockDiagramViewModel.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; + +namespace AIStudio.Wpf.DiagramDesigner +{ + public class BlockDiagramViewModel : DiagramViewModel + { + public BlockDiagramViewModel() + { + } + + #region + private ICommand _addNextCommand; + public ICommand AddNextCommand + { + get + { + return this._addNextCommand ?? (this._addNextCommand = new SimpleCommand(ExecuteEnable, this.ExecutedAddNextCommand)); + } + } + + private ICommand _removeNextCommand; + public ICommand RemoveNextCommand + { + get + { + return this._removeNextCommand ?? (this._removeNextCommand = new SimpleCommand(ExecuteEnable, this.ExecutedRemoveNextCommand)); + } + } + + private ICommand _addChildCommand; + public ICommand AddChildCommand + { + get + { + return this._addChildCommand ?? (this._addChildCommand = new SimpleCommand(ExecuteEnable, this.ExecutedAddChildCommand)); + } + } + + private ICommand _removeChildCommand; + public ICommand RemoveChildCommand + { + get + { + return this._removeChildCommand ?? (this._removeChildCommand = new SimpleCommand(ExecuteEnable, this.ExecutedRemoveChildCommand)); + } + } + #endregion + + #region Block使用 + private void ExecutedAddNextCommand(object parameter) + { + if (parameter is Tuple blockTuple) + { + } + + } + + private void ExecutedRemoveNextCommand(object parameter) + { + + } + + private void ExecutedAddChildCommand(object parameter) + { + + } + private void ExecutedRemoveChildCommand(object parameter) + { + + } + #endregion + } +} diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/IDiagramViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/IDiagramViewModel.cs index d8a60a7..2805bf7 100644 --- a/AIStudio.Wpf.DiagramDesigner/ViewModels/IDiagramViewModel.cs +++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/IDiagramViewModel.cs @@ -333,6 +333,7 @@ namespace AIStudio.Wpf.DiagramDesigner #endregion #region 方法 + void Init(DiagramItem diagramItem); void Init(bool initNew); void Add(object parameter, bool? isSelected = false); @@ -362,16 +363,6 @@ namespace AIStudio.Wpf.DiagramDesigner void LockAction(LockObject lockObject, string propertyName, List items); #endregion - #region 公共方法 - FullyCreatedConnectorInfo FindNearPortToAttachTo(ConnectionViewModel partialConnection, ConnectorVertexType connectorVertexType); - FullyCreatedConnectorInfo FindNearPortToAttachTo(ConnectionViewModel partialConnection); - Tuple FindNearPortToAttachTo(BlockDesignerItemTempLink blockDesignerItemViewModel, bool isExist); - BlockItemsContainerInfo FindNearContainerToAttachTo(BlockDesignerItemTempLink blockDesignerItemViewModel); - void ClearNearPort(); - void ClearNearContain(); - void PreviewNearBlock(List blocks); - void FinishNearBlock(List blocks); - #endregion event PropertyChangedEventHandler PropertyChanged; }