Files
aistudio-wpf-diagram/AIStudio.Wpf.DiagramDesigner/ViewModels/BlockViewModel/BlockDesignerItemViewModelHelper.cs
艾竹 b476fd4eb5 block
2023-07-02 11:23:00 +08:00

288 lines
13 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.Items == null || blockDesignerItemTempLink.Items.Count == 0)
return new Tuple<FullyCreatedConnectorInfo, FullyCreatedConnectorInfo>(null, null);
List<BlockDesignerItemViewModel> items = diagramViewModel.Items.OfType<BlockDesignerItemViewModel>().Where(p => !blockDesignerItemTempLink.Items.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.Items == null || blockDesignerItemTempLink.Items.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.Prev != 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.Items == null || blockDesignerItemTempLink.Items.Count == 0)
return null;
List<BlockDesignerItemViewModel> items;
items = diagramViewModel.Items.OfType<BlockDesignerItemViewModel>().Where(p => !blockDesignerItemTempLink.Items.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.Items.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.Items.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 => {
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 => {
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;
});
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.Items.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.Items.FirstOrDefault() });
portParent.BeAttachTo = false;
portParent.DisableAttachTo = false;
}
else
{
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 });
portNext.BeAttachTo = false;
portNext.DisableAttachTo = false;
}
else
{
if (item.Items.LastOrDefault().Next != null)
{
diagramViewModel.RemoveNextCommand.Execute(new BlockNextPara() { Item = item.Items.LastOrDefault(), Next = item.Items.LastOrDefault()?.Next });
}
}
}
diagramViewModel.ClearAttachTo();
}
}
#endregion
}
}