From 9485ce6684c28f726c93e71e3daa3a0b63f0a782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=89=BE=E7=AB=B9?= Date: Sat, 12 Aug 2023 22:58:24 +0800 Subject: [PATCH] =?UTF-8?q?block=E4=BD=BF=E7=94=A8linklist=E9=87=8D?= =?UTF-8?q?=E5=86=99=EF=BC=8C=E6=8A=8A=E4=BB=A3=E7=A0=81=E5=A4=8D=E6=9D=82?= =?UTF-8?q?=E5=BA=A6=E9=99=8D=E4=BD=8E=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...udio.Wpf.DiagramApp_vlj5xwu5_wpftmp.csproj | 1039 +++++++++++++++++ AIStudio.Wpf.DiagramApp/Views/MainWindow.xaml | 3 + .../Common/BindableBase.cs | 5 + .../DesignerItemViewModelBase.cs | 27 +- .../ViewModels/BaseViewModel/DiagramOption.cs | 6 +- .../BaseViewModel/DiagramViewModel.cs | 7 +- .../BaseViewModel/SelectableViewModelBase.cs | 4 + .../BlockDesignerItemViewModel.cs | 355 +++--- .../BlockDesignerItemViewModelHelper.cs | 98 +- .../BlockViewModel/BlockDiagramViewModel.cs | 8 +- 10 files changed, 1339 insertions(+), 213 deletions(-) create mode 100644 AIStudio.Wpf.DiagramApp/AIStudio.Wpf.DiagramApp_vlj5xwu5_wpftmp.csproj diff --git a/AIStudio.Wpf.DiagramApp/AIStudio.Wpf.DiagramApp_vlj5xwu5_wpftmp.csproj b/AIStudio.Wpf.DiagramApp/AIStudio.Wpf.DiagramApp_vlj5xwu5_wpftmp.csproj new file mode 100644 index 0000000..18f5e13 --- /dev/null +++ b/AIStudio.Wpf.DiagramApp/AIStudio.Wpf.DiagramApp_vlj5xwu5_wpftmp.csproj @@ -0,0 +1,1039 @@ + + + AIStudio.Wpf.DiagramApp + obj\Debug\ + obj\ + F:\aistudio.-wpf.-diagram\AIStudio.Wpf.DiagramApp\obj\ + <_TargetAssemblyProjectName>AIStudio.Wpf.DiagramApp + + + + WinExe + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + 8.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AIStudio.Wpf.DiagramApp/Views/MainWindow.xaml b/AIStudio.Wpf.DiagramApp/Views/MainWindow.xaml index 2c6bc0f..19936cc 100644 --- a/AIStudio.Wpf.DiagramApp/Views/MainWindow.xaml +++ b/AIStudio.Wpf.DiagramApp/Views/MainWindow.xaml @@ -2861,6 +2861,9 @@ HorizontalAlignment="Right" > 形状ID: + + - diff --git a/AIStudio.Wpf.DiagramDesigner/Common/BindableBase.cs b/AIStudio.Wpf.DiagramDesigner/Common/BindableBase.cs index 83a04e4..1b13bc1 100644 --- a/AIStudio.Wpf.DiagramDesigner/Common/BindableBase.cs +++ b/AIStudio.Wpf.DiagramDesigner/Common/BindableBase.cs @@ -36,6 +36,11 @@ namespace AIStudio.Wpf.DiagramDesigner } } + public bool HasOldValue(string propertyName, string guid = null) + { + return _oldDic.ContainsKey(propertyName + guid ?? string.Empty); + } + public void ClearOldValue(string propertyName, string guid = null) { if (_oldDic.ContainsKey(propertyName + guid ?? string.Empty)) diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DesignerItemViewModelBase.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DesignerItemViewModelBase.cs index 103df89..c0e2f8e 100644 --- a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DesignerItemViewModelBase.cs +++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DesignerItemViewModelBase.cs @@ -369,15 +369,15 @@ namespace AIStudio.Wpf.DiagramDesigner } set { - if (Root?.DiagramOption?.LayoutOption?.BeyondBoundary > 0) + if (Root != null && BeyondBoundary > 0) { - if (value + GetItemWidth() < Root.DiagramOption.LayoutOption.BeyondBoundary) + if (value + GetItemWidth() < BeyondBoundary) { - value = Root.DiagramOption.LayoutOption.BeyondBoundary - GetItemWidth(); + value = BeyondBoundary - GetItemWidth(); } - else if (value > Root.DiagramOption.LayoutOption.PageSize.Width - Root.DiagramOption.LayoutOption.BeyondBoundary) + else if (value > Root.DiagramOption.LayoutOption.PageSize.Width - BeyondBoundary) { - value = Root.DiagramOption.LayoutOption.PageSize.Width - Root.DiagramOption.LayoutOption.BeyondBoundary; + value = Root.DiagramOption.LayoutOption.PageSize.Width - BeyondBoundary; } } SetProperty(ref _left, value); @@ -395,15 +395,15 @@ namespace AIStudio.Wpf.DiagramDesigner } set { - if (Root?.DiagramOption?.LayoutOption?.BeyondBoundary > 0) + if (Root != null && BeyondBoundary > 0) { - if (value + GetItemHeight() < Root.DiagramOption.LayoutOption.BeyondBoundary) + if (value + GetItemHeight() < BeyondBoundary) { - value = Root.DiagramOption.LayoutOption.BeyondBoundary - GetItemHeight(); + value = BeyondBoundary - GetItemHeight(); } - else if (value > Root.DiagramOption.LayoutOption.PageSize.Height - Root.DiagramOption.LayoutOption.BeyondBoundary) + else if (value > Root.DiagramOption.LayoutOption.PageSize.Height - BeyondBoundary) { - value = Root.DiagramOption.LayoutOption.PageSize.Height - Root.DiagramOption.LayoutOption.BeyondBoundary; + value = Root.DiagramOption.LayoutOption.PageSize.Height - BeyondBoundary; } } SetProperty(ref _top, value); @@ -603,6 +603,11 @@ namespace AIStudio.Wpf.DiagramDesigner } } + public double BeyondBoundary + { + get; set; + } = -1; + /// /// 连接点是否可以按偏移自定义 /// @@ -809,7 +814,7 @@ namespace AIStudio.Wpf.DiagramDesigner public override string ToString() { - return $"{Id}-{Name}-{Text}-({Left},{Top},{ItemWidth},{ItemHeight})"; + return $"{ParentId}-{Id}-{Name}-{Text}-({Left},{Top},{ItemWidth},{ItemHeight})"; } #endregion } diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramOption.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramOption.cs index 7153bba..c097c7d 100644 --- a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramOption.cs +++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramOption.cs @@ -370,11 +370,7 @@ namespace AIStudio.Wpf.DiagramDesigner { get; set; } = true; - - public double BeyondBoundary - { - get; set; - } = -1; + } public class SnappingOption diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModel.cs index 1cc18f0..cd4cfb4 100644 --- a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModel.cs +++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DiagramViewModel.cs @@ -1226,11 +1226,14 @@ namespace AIStudio.Wpf.DiagramDesigner item.Id = Guid.NewGuid(); } - var logical = item as LogicalGateItemViewModelBase; - if (logical != null) + if (item is LogicalGateItemViewModelBase logical) { logical.OrderNumber = Items.OfType().Count() + 1; } + //if (item is BlockDesignerItemViewModel block) + //{ + // block.Text = block.Text + item.ZIndex; + //} var designerItemViewModelBase = item as DesignerItemViewModelBase; if (designerItemViewModelBase != null) diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/SelectableViewModelBase.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/SelectableViewModelBase.cs index 5ff0997..f8fa8ad 100644 --- a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/SelectableViewModelBase.cs +++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/SelectableViewModelBase.cs @@ -287,6 +287,10 @@ namespace AIStudio.Wpf.DiagramDesigner } set { + if (value == int.MaxValue) + { + + } SetProperty(ref _zIndex, value); } } diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BlockViewModel/BlockDesignerItemViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BlockViewModel/BlockDesignerItemViewModel.cs index c9bbb91..599e44b 100644 --- a/AIStudio.Wpf.DiagramDesigner/ViewModels/BlockViewModel/BlockDesignerItemViewModel.cs +++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BlockViewModel/BlockDesignerItemViewModel.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; +using System.Windows.Documents; using AIStudio.Wpf.DiagramDesigner.Geometrys; using AIStudio.Wpf.DiagramDesigner.Models; using static System.Net.Mime.MediaTypeNames; @@ -41,7 +42,6 @@ namespace AIStudio.Wpf.DiagramDesigner ItemHeight = double.NaN; AddConnector(new BlockConnectorInfo(this.Root, this, ConnectorOrientation.Top)); AddConnector(new BlockConnectorInfo(this.Root, this, ConnectorOrientation.Bottom)); - } protected override void Init(IDiagramViewModel root, bool initNew) @@ -79,69 +79,147 @@ namespace AIStudio.Wpf.DiagramDesigner } } - public void AddNext(BlockDesignerItemViewModel next, bool first = true) + public void AddNext(BlockDesignerItemViewModel next, BlockDesignerItemViewModel first = null) { - if (this.Next == next) + if (LinkNode.Next?.Value == next) { - AlignNext(next); + AlignNext(LinkNode.Next); return; } - if (next.Prev != null) + var linkedList = LinkNode.List; + var nextlinkedList = next.LinkNode.List; + if (nextlinkedList == linkedList)//后面的拖到前面去了 { - next.Prev.RemoveNext(); - } - - var oldnext = RemoveNext(); - - next.Left = this.Left; - next.Top = this.Top + this.GetItemHeight(); - next.ParentId = this.Id; - next.Prev = this; - this.Next = next; - if (next.Next != null) - { - next.AlignNext(next.Next); - } - if (oldnext != null && first == true) - { - //if (this.GetItemHeight() > 0) - //{ - // GetLast().AddNext(oldnext, false); - //} - //else + if (first != null) { - System.Windows.Application.Current?.Dispatcher.BeginInvoke(new Action(async () => { - await Task.Delay(10); - GetLast().AddNext(oldnext, false); - })); + first.RemovePrevious(); } - + else + { + next.LinkNode.Previous?.Value.RemoveNext(); + } + nextlinkedList = next.LinkNode.List; } + linkedList.InsertRange(LinkNode, nextlinkedList); + nextlinkedList.Clear(); + + AlignNext(LinkNode.Next); } - public void AlignNext(BlockDesignerItemViewModel next) + public void AlignNext(LinkedListNode nextnode) { - if (next != null && this.Next == next) + if (nextnode != null && LinkNode.Next == nextnode) { - next.Left = this.Left; - next.Top = this.Top + this.GetItemHeight(); - if (next.Next != null) + nextnode.Value.Left = this.Left; + nextnode.Value.Top = this.Top + this.GetItemHeight(); + if (nextnode.Next != null) { - next.AlignNext(next.Next); + nextnode.Value.AlignNext(nextnode.Next); } } } - public BlockDesignerItemViewModel RemoveNext() + public List RemoveNext(bool allbreak = false) { - var next = this.Next; + List removes = new List(); + var next = LinkNode?.Next; if (next != null) { - next.ParentId = new Guid(); - next.Prev = null; - this.Next = null; - return next; + var linkedList = LinkNode.List; + + var list = linkedList.ToList(); + int index = list.IndexOf(next.Value); + //BlockDesignerItemViewModel[] array = new BlockDesignerItemViewModel[linkedList.Count]; + //linkedList.CopyTo(array, index); + + var nextlinkedList = new LinkedList(); + for (int i = list.Count - 1; i >= index; i--) + { + var nextnode = linkedList.Find(list[i]); + linkedList.Remove(nextnode); + + if (allbreak)//全部变成散落的 + { + list[i].ParentId = new Guid(); + } + else//后面的连接成一个链表 + { + list[i].LinkNode = nextlinkedList.AddFirst(list[i]); + } + + removes.Add(list[i]); + } + + if (nextlinkedList.First != null) + { + nextlinkedList.First.Value.ParentId = new Guid(); + } + } + + return removes; + } + + public List RemoveSelf(bool allbreak = false) + { + List removes = new List(); + var linkedList = LinkNode.List; + + var list = linkedList.ToList(); + int index = list.IndexOf(this); + + var nextlinkedList = new LinkedList(); + for (int i = list.Count - 1; i >= index; i--) + { + var nextnode = linkedList.Find(list[i]); + linkedList.Remove(nextnode); + + if (allbreak)//全部变成散落的 + { + list[i].ParentId = new Guid(); + } + else//后面的连接成一个链表 + { + list[i].LinkNode = nextlinkedList.AddFirst(list[i]); + } + + removes.Add(list[i]); + } + + if (nextlinkedList.First != null) + { + nextlinkedList.First.Value.ParentId = new Guid(); + } + + return removes; + } + + public BlockDesignerItemViewModel RemovePrevious(bool allbreak = false) + { + var previous = this.LinkNode.Previous; + if (previous != null) + { + var linkedList = LinkNode.List; + var previouslinkedList = new LinkedList(); + + var list = linkedList.ToList(); + int index = list.IndexOf(previous.Value); + for (int i = 0; i <= index; i++) + { + var previousnode = linkedList.Find(list[i]); + linkedList.Remove(previousnode); + if (allbreak)//全部变成散落的 + { + list[i].ParentId = new Guid(); + } + else//前面的连接成一个链表 + { + list[i].LinkNode = previouslinkedList.AddLast(list[i]); + } + } + + this.ParentId = new Guid(); + return previous.Value; } else { @@ -149,6 +227,7 @@ namespace AIStudio.Wpf.DiagramDesigner } } + public override void AddToSelection(bool selected, bool clearother) { if (clearother) @@ -180,48 +259,44 @@ namespace AIStudio.Wpf.DiagramDesigner this.RemoveChild(oldchildren, container); } Root.Items.Remove(child); - if (child.Prev != null) + if (child.LinkNode?.Previous != null) { - child.Prev.RemoveNext(); + child.LinkNode.Previous.Value.RemoveNext(); } - if (child.Next != null) + if (child.LinkNode?.Next != null) { - child.RemoveNext(); + child.LinkNode.Next.Value.RemovePrevious(); } container.InsertChild(child, index); } else { - var list = child.GetNexts(true); - list.Reverse(); - list.ForEach(p => { + var items = new List(); + var linkedList = child.LinkNode.List; + + if (child.LinkNode?.Previous != null) + { + items = child.LinkNode.Previous.Value.RemoveNext(true); + } + else + { + items = child.LinkNode.Value.RemoveSelf(true); + } + + items.ForEach(p => { Root.Items.Remove(p); - if (p.Prev != null) - { - p.Prev.RemoveNext(); - } - if (p.Next != null) - { - p.RemoveNext(); - } container.InsertChild(p, index); }); + } child.RemoveFromSelection(); this.GetRootContainItem.AddToSelection(true, true); - //if (this.GetItemHeight() > 0) - //{ - // AlignNext(this.Next); - //} - //else - { - System.Windows.Application.Current?.Dispatcher.BeginInvoke(new Action(async () => { - await Task.Delay(10); - AlignNext(this.Next); - })); - } + System.Windows.Application.Current?.Dispatcher.BeginInvoke(new Action(async () => { + await Task.Delay(10); + AlignNext(LinkNode?.Next); + })); } public virtual void RemoveChild(BlockDesignerItemViewModel child, BlockItemsContainerInfo container) @@ -236,17 +311,10 @@ namespace AIStudio.Wpf.DiagramDesigner this.RemoveFromSelection(); child.AddToSelection(true, true); - //if (this.GetItemHeight() > 0) - //{ - // AlignNext(this.Next); - //} - //else - { - System.Windows.Application.Current?.Dispatcher.BeginInvoke(new Action(async () => { - await Task.Delay(10); - AlignNext(this.Next); - })); - } + System.Windows.Application.Current?.Dispatcher.BeginInvoke(new Action(async () => { + await Task.Delay(10); + AlignNext(LinkNode?.Next); + })); } private bool _isExecuting; @@ -267,41 +335,40 @@ namespace AIStudio.Wpf.DiagramDesigner get; set; } - public int BlockLevel + public int LinkNodeLevel { get { - if (Prev == null) + if (LinkNode?.Previous == null) { return 0; } else { - return Prev.BlockLevel + 1; + return LinkNode.Previous.Value.LinkNodeLevel + 1; } } } - public BlockDesignerItemViewModel Prev + private LinkedListNode _linkNode; + public LinkedListNode LinkNode { get { - return Parent as BlockDesignerItemViewModel; + if (_linkNode == null || _linkNode.List == null) + { + var linklist = new LinkedList(); ; + _linkNode = linklist.AddFirst(this); + } + + return _linkNode; } set { - if (Parent != value) - { - Parent = value; - } + _linkNode = value; } } - public BlockDesignerItemViewModel Next - { - get; set; - } - public BlockItemsContainerInfo ParentContainer { get; set; @@ -336,48 +403,6 @@ namespace AIStudio.Wpf.DiagramDesigner } } - public BlockDesignerItemViewModel GetFirst() - { - var parent = this.Prev; - while (parent?.Prev != null) - { - parent = parent.Prev; - } - - return parent; - } - - public BlockDesignerItemViewModel GetLast() - { - var next = this; - while (next.Next != null) - { - next = next.Next; - } - - return next; - } - - public List GetNexts(bool self) - { - List blockDesignerItemViewModels = new List(); - if (self) - { - blockDesignerItemViewModels.Add(this); - } - var next = this; - while (next != null) - { - next = next.Next; - if (next != null) - { - blockDesignerItemViewModels.Add(next); - } - } - - return blockDesignerItemViewModels; - } - public void AddContainer(BlockItemsContainerInfo container) { Containers.Add(container); @@ -425,26 +450,26 @@ namespace AIStudio.Wpf.DiagramDesigner #region 执行 protected override async void ExecuteEditCommand(object param) { - await (this.GetFirst() ?? this).Execute(); + await this.LinkNode.List.First.Value.Execute(); } - public override async void PreviewExecuteEdit() + public override void PreviewExecuteEdit() { - var items = (this.GetFirst() ?? this).GetNexts(true); + var items = this.LinkNode.List.ToList(); items.ForEach(p => p.IsExecuting = true); } - public override async void ExitPreviewExecuteEdit() + public override void ExitPreviewExecuteEdit() { - var items = (this.GetFirst() ?? this).GetNexts(true); + var items = this.LinkNode.List.ToList(); items.ForEach(p => p.IsExecuting = false); } public async Task Execute() { - await BeforeExecute(); + await BeforeExecute(); await Executing(); await AfterExecute(); } @@ -465,8 +490,8 @@ namespace AIStudio.Wpf.DiagramDesigner if (IsExecuting) { IsExecuting = false; - if (Next != null) - await Next.Execute(); + if (LinkNode.Next != null) + await LinkNode.Next.Value.Execute(); } } @@ -548,14 +573,14 @@ namespace AIStudio.Wpf.DiagramDesigner #region 帮助 public class BlockDesignerItemTempLink { - public List Items + public LinkedList LinkList { get; set; - } = new List(); + } = new LinkedList(); public RectangleBase GetBounds() { - return Items.FirstOrDefault().GetBounds(); + return LinkList.FirstOrDefault().GetBounds(); } public List Connectors @@ -563,21 +588,21 @@ namespace AIStudio.Wpf.DiagramDesigner get { List connectors = new List(); - if (Items.FirstOrDefault().TopConnector != null) + if (LinkList.FirstOrDefault().TopConnector != null) { - connectors.Add(Items.FirstOrDefault().TopConnector); + connectors.Add(LinkList.FirstOrDefault().TopConnector); } - if (Items.FirstOrDefault().LeftConnector != null) + if (LinkList.FirstOrDefault().LeftConnector != null) { - connectors.Add(Items.FirstOrDefault().LeftConnector); + connectors.Add(LinkList.FirstOrDefault().LeftConnector); } - if (Items.LastOrDefault().BottomConnector != null) + if (LinkList.LastOrDefault().BottomConnector != null) { - connectors.Add(Items.LastOrDefault().BottomConnector); + connectors.Add(LinkList.LastOrDefault().BottomConnector); } - if (Items.LastOrDefault().RightConnector != null) + if (LinkList.LastOrDefault().RightConnector != null) { - connectors.Add(Items.LastOrDefault().RightConnector); + connectors.Add(LinkList.LastOrDefault().RightConnector); } return connectors; } @@ -586,23 +611,15 @@ namespace AIStudio.Wpf.DiagramDesigner public static List Build(List blocks) { List links = new List(); - foreach (var block in blocks.OrderBy(p => p.BlockLevel).ToList()) + + foreach (var blockgroup in blocks.GroupBy(p => p.LinkNode.List)) { - bool success = false; - foreach (var link in links) + var link = new BlockDesignerItemTempLink(); + foreach (var block in blockgroup.OrderBy(p => p.LinkNodeLevel)) { - if (link.Items.LastOrDefault() == block.Prev) - { - link.Items.Add(block); - success = true; - } - } - if (success == false) - { - BlockDesignerItemTempLink link = new BlockDesignerItemTempLink(); - link.Items.Add(block); - links.Add(link); + link.LinkList.AddLast(block); } + links.Add(link); } return links; } diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BlockViewModel/BlockDesignerItemViewModelHelper.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BlockViewModel/BlockDesignerItemViewModelHelper.cs index 7a488b9..6a12a1c 100644 --- a/AIStudio.Wpf.DiagramDesigner/ViewModels/BlockViewModel/BlockDesignerItemViewModelHelper.cs +++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BlockViewModel/BlockDesignerItemViewModelHelper.cs @@ -19,17 +19,17 @@ namespace AIStudio.Wpf.DiagramDesigner /// public static Tuple FindNearPortToAttachTo(this IDiagramViewModel diagramViewModel, BlockDesignerItemTempLink blockDesignerItemTempLink) { - if (blockDesignerItemTempLink == null || blockDesignerItemTempLink.Items == null || blockDesignerItemTempLink.Items.Count == 0) + if (blockDesignerItemTempLink == null || blockDesignerItemTempLink.LinkList == null || blockDesignerItemTempLink.LinkList.Count == 0) return new Tuple(null, null); - List items = diagramViewModel.Items.OfType().Where(p => !blockDesignerItemTempLink.Items.Contains(p)).ToList(); + List items = diagramViewModel.Items.OfType().Where(p => !blockDesignerItemTempLink.LinkList.Contains(p)).ToList(); return diagramViewModel.FindNearPortToAttachTo(items, blockDesignerItemTempLink); } public static Tuple FindNearPortToAttachTo(this IDiagramViewModel diagramViewModel, List items, BlockDesignerItemTempLink blockDesignerItemTempLink) { - if (blockDesignerItemTempLink == null || blockDesignerItemTempLink.Items == null || blockDesignerItemTempLink.Items.Count == 0) + if (blockDesignerItemTempLink == null || blockDesignerItemTempLink.LinkList == null || blockDesignerItemTempLink.LinkList.Count == 0) return new Tuple(null, null); FullyCreatedConnectorInfo parent = null; @@ -40,11 +40,11 @@ namespace AIStudio.Wpf.DiagramDesigner { bool success = false; foreach (var item in items) - { + { foreach (var port in item.Connectors.OfType()) { //已经被连接的不允许在顶部吸附了 - if ((port.Orientation == ConnectorOrientation.Top || port.Orientation == ConnectorOrientation.Left) && port.DataItem.Prev != null) + if ((port.Orientation == ConnectorOrientation.Top || port.Orientation == ConnectorOrientation.Left) && port.DataItem.LinkNode.Previous != null) { continue; } @@ -121,12 +121,12 @@ namespace AIStudio.Wpf.DiagramDesigner public static BlockItemsContainerInfo FindNearContainerToAttachTo(this IDiagramViewModel diagramViewModel, BlockDesignerItemTempLink blockDesignerItemTempLink) { - if (blockDesignerItemTempLink == null || blockDesignerItemTempLink.Items == null || blockDesignerItemTempLink.Items.Count == 0) + if (blockDesignerItemTempLink == null || blockDesignerItemTempLink.LinkList == null || blockDesignerItemTempLink.LinkList.Count == 0) return null; List items; - items = diagramViewModel.Items.OfType().Where(p => !blockDesignerItemTempLink.Items.Contains(p)).ToList(); + items = diagramViewModel.Items.OfType().Where(p => !blockDesignerItemTempLink.LinkList.Contains(p)).ToList(); foreach (var container in items.SelectMany(n => n.Containers)) { @@ -135,7 +135,7 @@ namespace AIStudio.Wpf.DiagramDesigner var innerport = container.GetAllContainers(container.Children, false).Where(p => p.GetBounds().IntersectsWith(blockDesignerItemTempLink.GetBounds())).OrderByDescending(p => p.ContainerLevel).FirstOrDefault(); if (innerport != null) { - if (innerport.CanAttachTo(blockDesignerItemTempLink.Items.FirstOrDefault()) == true) + if (innerport.CanAttachTo(blockDesignerItemTempLink.LinkList.FirstOrDefault()) == true) { innerport.DataItem.ShowConnectors = true; if (innerport.OnlyOneChild || innerport.Children.Count == 0) @@ -158,7 +158,7 @@ namespace AIStudio.Wpf.DiagramDesigner else { - if (container.CanAttachTo(blockDesignerItemTempLink.Items.FirstOrDefault()) == true) + if (container.CanAttachTo(blockDesignerItemTempLink.LinkList.FirstOrDefault()) == true) { container.DataItem.ShowConnectors = true; if (container.OnlyOneChild || container.Children.Count == 0) @@ -195,6 +195,10 @@ namespace AIStudio.Wpf.DiagramDesigner var links = BlockDesignerItemTempLink.Build(blocks); blocks.ToList().ForEach(p => { + if (p.ZIndex != int.MaxValue) + { + p.SetOldValue(p.ZIndex, "ZIndex"); + } p.ZIndex = int.MaxValue; }); @@ -222,7 +226,10 @@ namespace AIStudio.Wpf.DiagramDesigner var links = BlockDesignerItemTempLink.Build(blocks); blocks.ToList().ForEach(p => { - p.ZIndex = diagramViewModel.Items.Where(q => q.ZIndex != int.MaxValue).Any() ? diagramViewModel.Items.Where(q => q.ZIndex != int.MaxValue).Max(r => r.ZIndex) + 1 : 0; + if (p.HasOldValue("ZIndex")) + { + p.ZIndex = p.GetOldValue("ZIndex"); + } }); foreach (BlockDesignerItemTempLink item in links) @@ -240,7 +247,7 @@ namespace AIStudio.Wpf.DiagramDesigner index++; } } - diagramViewModel.InsertChildCommand.Execute(new BlockContainerPara() { Item = container.DataItem, Child = item.Items.FirstOrDefault(), Container = container, Index = index }); + diagramViewModel.InsertChildCommand.Execute(new BlockContainerPara() { Item = container.DataItem, Child = item.LinkList.FirstOrDefault(), Container = container, Index = index }); continue; } @@ -250,29 +257,21 @@ namespace AIStudio.Wpf.DiagramDesigner if (portParent != null) { - diagramViewModel.AddNextCommand.Execute(new BlockNextPara() { Item = portParent.DataItem as BlockDesignerItemViewModel, Next = item.Items.FirstOrDefault() }); + diagramViewModel.AddNextCommand.Execute(new BlockNextPara() { Item = portParent.DataItem as BlockDesignerItemViewModel, Next = item.LinkList.FirstOrDefault() }); portParent.BeAttachTo = false; portParent.DisableAttachTo = false; } - else + else if (portNext != null) { - if (item.Items.FirstOrDefault().Parent != null) - { - diagramViewModel.RemoveNextCommand.Execute(new BlockNextPara() { Item = item.Items.FirstOrDefault().Parent as BlockDesignerItemViewModel, Next = (item.Items.FirstOrDefault().Parent as BlockDesignerItemViewModel)?.Next }); - } - } - - if (portNext != null) - { - diagramViewModel.AddNextCommand.Execute(new BlockNextPara() { Item = item.Items.LastOrDefault(), Next = portNext.DataItem as BlockDesignerItemViewModel }); + diagramViewModel.AddNextCommand.Execute(new BlockNextPara() { First = item.LinkList.FirstOrDefault(), Item = item.LinkList.LastOrDefault(), Next = portNext.DataItem as BlockDesignerItemViewModel }); portNext.BeAttachTo = false; portNext.DisableAttachTo = false; } else { - if (item.Items.LastOrDefault().Next != null) + if (item.LinkList.FirstOrDefault().LinkNode.Previous != null) { - diagramViewModel.RemoveNextCommand.Execute(new BlockNextPara() { Item = item.Items.LastOrDefault(), Next = item.Items.LastOrDefault()?.Next }); + diagramViewModel.RemoveNextCommand.Execute(new BlockNextPara() { Item = item.LinkList.FirstOrDefault().LinkNode.Previous.Value, Next = item.LinkList.FirstOrDefault().LinkNode.Value }); } } } @@ -284,4 +283,55 @@ namespace AIStudio.Wpf.DiagramDesigner #endregion } + + public static class LinkedListExtensions + { + public static void InsertRange(this LinkedList source, LinkedListNode node, IEnumerable items) + { + if (node == null || items.Count() == 0) + { + return; + } + + BlockDesignerItemViewModel last = null; + foreach (var item in items) + { + item.LinkNode = source.AddAfter(node, item); + item.ParentId = item.LinkNode.Previous.Value.Id; + node = item.LinkNode; + + last = item; + } + + //把后面的接上 + var lastnode = source.Find(last); + if (lastnode.Next != null) + { + lastnode.Next.Value.ParentId = last.Id; + } + } + + public static void AppendRange(this LinkedList source, IEnumerable items) + { + foreach (var item in items) + { + item.LinkNode = source.AddLast(item); + item.ParentId = item.LinkNode.Previous?.Value.Id ?? new Guid(); + } + } + + public static void PrependRange(this LinkedList source, IEnumerable items) + { + var first = source.First; // If the list is empty, we can just append everything. + if (first is null) + { + AppendRange(source, items); return; + } // Otherwise, add each item in turn just before the original first item + foreach (var item in items) + { + item.LinkNode = source.AddBefore(first, item); + item.ParentId = item.LinkNode.Previous.Value.Id; + } + } + } } diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BlockViewModel/BlockDiagramViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BlockViewModel/BlockDiagramViewModel.cs index 391c17d..e963fb7 100644 --- a/AIStudio.Wpf.DiagramDesigner/ViewModels/BlockViewModel/BlockDiagramViewModel.cs +++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BlockViewModel/BlockDiagramViewModel.cs @@ -59,7 +59,7 @@ namespace AIStudio.Wpf.DiagramDesigner { DoCommandManager.DoNewCommand(this.ToString(), () => { - blockItemPara.Item.AddNext(blockItemPara.Next); + blockItemPara.Item.AddNext(blockItemPara.Next, blockItemPara.First); }, () => { blockItemPara.Item.RemoveNext(); @@ -76,7 +76,7 @@ namespace AIStudio.Wpf.DiagramDesigner blockItemPara.Item.RemoveNext(); }, () => { - blockItemPara.Item.AddNext(blockItemPara.Next); + blockItemPara.Item.AddNext(blockItemPara.Next, blockItemPara.First); }); } } @@ -113,6 +113,10 @@ namespace AIStudio.Wpf.DiagramDesigner public class BlockNextPara { + public BlockDesignerItemViewModel First + { + get; set; + } public BlockDesignerItemViewModel Item { get; set;