Files
aistudio-wpf-diagram/AIStudio.Wpf.DiagramDesigner/ViewModels/BlockViewModel/BlockDesignerItemViewModelHelper.cs

338 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Documents;
namespace AIStudio.Wpf.DiagramDesigner
{
public static partial class BlockDesignerItemViewModelHelper
{
/// <summary>
/// type=0最近且没有依附=1
/// </summary>
/// <param name="blockDesignerItemViewModel"></param>
/// <param name="type"></param>
/// <returns></returns>
public static Tuple<FullyCreatedConnectorInfo, FullyCreatedConnectorInfo> FindNearPortToAttachTo(this IDiagramViewModel diagramViewModel, BlockDesignerItemTempLink blockDesignerItemTempLink)
{
if (blockDesignerItemTempLink == null || blockDesignerItemTempLink.LinkList == null || blockDesignerItemTempLink.LinkList.Count == 0)
return new Tuple<FullyCreatedConnectorInfo, FullyCreatedConnectorInfo>(null, null);
List<BlockDesignerItemViewModel> items = diagramViewModel.Items.OfType<BlockDesignerItemViewModel>().Where(p => !blockDesignerItemTempLink.LinkList.Contains(p)).ToList();
return diagramViewModel.FindNearPortToAttachTo(items, blockDesignerItemTempLink);
}
public static Tuple<FullyCreatedConnectorInfo, FullyCreatedConnectorInfo> FindNearPortToAttachTo(this IDiagramViewModel diagramViewModel, List<BlockDesignerItemViewModel> items, BlockDesignerItemTempLink blockDesignerItemTempLink)
{
if (blockDesignerItemTempLink == null || blockDesignerItemTempLink.LinkList == null || blockDesignerItemTempLink.LinkList.Count == 0)
return new Tuple<FullyCreatedConnectorInfo, FullyCreatedConnectorInfo>(null, null);
FullyCreatedConnectorInfo parent = null;
FullyCreatedConnectorInfo next = null;
foreach (var port2 in blockDesignerItemTempLink.Connectors.OfType<BlockConnectorInfo>())
{
bool success = false;
foreach (var item in items)
{
foreach (var port in item.Connectors.OfType<BlockConnectorInfo>())
{
//已经被连接的不允许在顶部吸附了
if ((port.Orientation == ConnectorOrientation.Top || port.Orientation == ConnectorOrientation.Left) && port.DataItem.LinkNode.Previous != null)
{
continue;
}
//parent
if (parent == null)
{
if ((port.Orientation == ConnectorOrientation.Right && port2.Orientation == ConnectorOrientation.Left)
|| (port.Orientation == ConnectorOrientation.Bottom && port2.Orientation == ConnectorOrientation.Top))
{
var dis = port.DistanceTo(port2);
//Debug.WriteLine($"{port.DataItem.Name}-{port2.DataItem.Name}:{dis}");
if (dis < diagramViewModel.DiagramOption.SnappingOption.BlockSnappingRadius)
{
port.DataItem.ShowConnectors = true;
if (port.CanAttachTo(port2) == true)
{
diagramViewModel.AddAttachTo(port, true);
parent = port;
success = true;
break;
}
else
{
diagramViewModel.AddAttachTo(port, false);
}
}
}
}
//next
if (next == null)
{
if ((port.Orientation == ConnectorOrientation.Left && port2.Orientation == ConnectorOrientation.Right)
|| (port.Orientation == ConnectorOrientation.Top && port2.Orientation == ConnectorOrientation.Bottom))
{
var dis = port.DistanceTo(port2);
//Debug.WriteLine($"{port.DataItem.Name}-{port2.DataItem.Name}:{dis}");
if (dis < diagramViewModel.DiagramOption.SnappingOption.BlockSnappingRadius)
{
port.DataItem.ShowConnectors = true;
if (port.CanAttachTo(port2) == true)
{
diagramViewModel.AddAttachTo(port, true);
next = port;
success = true;
break;
}
else
{
diagramViewModel.AddAttachTo(port, false);
}
}
}
}
}
if (success)
{
break;
}
}
if (success)
{
break;
}
}
return new Tuple<FullyCreatedConnectorInfo, FullyCreatedConnectorInfo>(parent, next);
}
public static BlockItemsContainerInfo FindNearContainerToAttachTo(this IDiagramViewModel diagramViewModel, BlockDesignerItemTempLink blockDesignerItemTempLink)
{
if (blockDesignerItemTempLink == null || blockDesignerItemTempLink.LinkList == null || blockDesignerItemTempLink.LinkList.Count == 0)
return null;
List<BlockDesignerItemViewModel> items;
items = diagramViewModel.Items.OfType<BlockDesignerItemViewModel>().Where(p => !blockDesignerItemTempLink.LinkList.Contains(p)).ToList();
foreach (var container in items.SelectMany(n => n.Containers))
{
if (container.GetBounds().IntersectsWith(blockDesignerItemTempLink.GetBounds())) //如果两个位置相交
{
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.LinkList.FirstOrDefault()) == true)
{
innerport.DataItem.ShowConnectors = true;
if (innerport.OnlyOneChild || innerport.Children.Count == 0)
{
diagramViewModel.AddAttachTo(innerport, true);
}
else
{
diagramViewModel.FindNearPortToAttachTo(innerport.Children.ToList(), blockDesignerItemTempLink);
}
return innerport;
}
//else
//{
// innerport.DisableAttachTo = true;
// return null;
//}
}
else
{
if (container.CanAttachTo(blockDesignerItemTempLink.LinkList.FirstOrDefault()) == true)
{
container.DataItem.ShowConnectors = true;
if (container.OnlyOneChild || container.Children.Count == 0)
{
diagramViewModel.AddAttachTo(container, true);
}
else
{
diagramViewModel.FindNearPortToAttachTo(container.Children.ToList(), blockDesignerItemTempLink);
}
return container;
}
//else
//{
// port.DisableAttachTo = true;
// return null;
//}
}
}
}
return null;
}
#region Block拖拽预览-
public static void PreviewNearBlock(this IBlockDiagramViewModel diagramViewModel, List<BlockDesignerItemViewModel> blocks)
{
if (diagramViewModel == null)
return;
if (blocks.Any())
{
diagramViewModel.ClearAttachTo();
var links = BlockDesignerItemTempLink.Build(blocks);
blocks.ToList().ForEach(p => {
if (p.ZIndex != int.MaxValue)
{
p.SetOldValue(p.ZIndex, "ZIndex");
}
p.ZIndex = int.MaxValue;
});
foreach (BlockDesignerItemTempLink item in links)
{
var container = diagramViewModel.FindNearContainerToAttachTo(item);
if (container != null)
{
continue;
}
diagramViewModel.FindNearPortToAttachTo(item);
}
}
}
public static void FinishNearBlock(this IBlockDiagramViewModel diagramViewModel, List<BlockDesignerItemViewModel> blocks)
{
if (diagramViewModel == null)
return;
if (blocks.Any())
{
var links = BlockDesignerItemTempLink.Build(blocks);
blocks.ToList().ForEach(p => {
if (p.HasOldValue("ZIndex"))
{
p.ZIndex = p.GetOldValue<int>("ZIndex");
}
});
foreach (BlockDesignerItemTempLink item in links)
{
var container = diagramViewModel.FindNearContainerToAttachTo(item);
if (container != null)
{
int index = 0;
var child = container.Children.FirstOrDefault(p => p.Connectors.Any(q => q.BeAttachTo == true));
if (child != null)
{
index = container.Children.IndexOf(child);
if (child.RightConnector?.BeAttachTo == true || child.BottomConnector?.BeAttachTo == true)
{
index++;
}
}
diagramViewModel.InsertChildCommand.Execute(new BlockContainerPara() { Item = container.DataItem, Child = item.LinkList.FirstOrDefault(), Container = container, Index = index });
continue;
}
var portTuple = diagramViewModel.FindNearPortToAttachTo(item);
var portParent = portTuple.Item1;
var portNext = portTuple.Item2;
if (portParent != null)
{
diagramViewModel.AddNextCommand.Execute(new BlockNextPara() { Item = portParent.DataItem as BlockDesignerItemViewModel, Next = item.LinkList.FirstOrDefault() });
portParent.BeAttachTo = false;
portParent.DisableAttachTo = false;
}
else if (portNext != null)
{
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.LinkList.FirstOrDefault().LinkNode.Previous != null)
{
diagramViewModel.RemoveNextCommand.Execute(new BlockNextPara() { Item = item.LinkList.FirstOrDefault().LinkNode.Previous.Value, Next = item.LinkList.FirstOrDefault().LinkNode.Value });
}
}
}
diagramViewModel.ClearAttachTo();
}
}
#endregion
}
public static class LinkedListExtensions
{
public static void InsertRange(this LinkedList<BlockDesignerItemViewModel> source, LinkedListNode<BlockDesignerItemViewModel> node, IEnumerable<BlockDesignerItemViewModel> 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<BlockDesignerItemViewModel> source, IEnumerable<BlockDesignerItemViewModel> 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<BlockDesignerItemViewModel> source, IEnumerable<BlockDesignerItemViewModel> 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;
}
}
}
}