修改暂存一下

This commit is contained in:
艾竹
2023-01-12 23:02:53 +08:00
parent 5d7717cc2b
commit 6a4c31106a
58 changed files with 776 additions and 468 deletions

View File

@@ -4,13 +4,13 @@ using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;
using AIStudio.Wpf.DiagramDesigner.Geometry;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
namespace AIStudio.Wpf.DiagramDesigner
{
public abstract class ConnectorInfoBase : BindableBase
{
public virtual PointBase Position
public virtual ConnectorPoint Location
{
get;
}

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;
using AIStudio.Wpf.DiagramDesigner.Geometry;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
namespace AIStudio.Wpf.DiagramDesigner
{

View File

@@ -4,51 +4,62 @@ using System.ComponentModel;
using System.Linq;
//using System.Windows;
using System.Windows.Media;
using AIStudio.Wpf.DiagramDesigner.Geometry;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
using AIStudio.Wpf.DiagramDesigner.Helpers;
namespace AIStudio.Wpf.DiagramDesigner
{
public class ConnectorViewModel : SelectableDesignerItemViewModelBase
{
public ConnectorViewModel(IDiagramViewModel parent, FullyCreatedConnectorInfo sourceConnectorInfo, FullyCreatedConnectorInfo sinkConnectorInfo,
SelectableDesignerItemBase designer, DrawMode vectorLineDrawMode) : base(parent, designer)
{
VectorLineDrawMode = vectorLineDrawMode;
Init(sourceConnectorInfo, sinkConnectorInfo);
}
public ConnectorViewModel(IDiagramViewModel parent, FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo, DrawMode vectorLineDrawMode)
public ConnectorViewModel(IDiagramViewModel parent, FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo, DrawMode drawMode, RouterMode routerMode)
{
Parent = parent;
VectorLineDrawMode = vectorLineDrawMode;
PathMode = drawMode.ToString().Replace("ConnectingLine","");
RouterMode = routerMode.ToString();
Init(sourceConnectorInfo, sinkConnectorInfo);
}
public ConnectorViewModel( FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo, DrawMode vectorLineDrawMode):this(null, sourceConnectorInfo, sinkConnectorInfo, vectorLineDrawMode)
public ConnectorViewModel(IDiagramViewModel parent, FullyCreatedConnectorInfo sourceConnectorInfo, FullyCreatedConnectorInfo sinkConnectorInfo, ConnectionItem designer) : base(parent, designer)
{
PathMode = designer.PathMode;
RouterMode = designer.RouterMode;
Init(sourceConnectorInfo, sinkConnectorInfo);
}
public ConnectorViewModel(FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo, DrawMode drawMode, RouterMode routerMode) :this(null, sourceConnectorInfo, sinkConnectorInfo, drawMode, routerMode)
{
}
private void Init(FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo)
{
this.Parent = sourceConnectorInfo.DataItem.Parent;
var routetype = GlobalType.AllTypes.Where(p => typeof(IRouter).IsAssignableFrom(p)).FirstOrDefault(p => p.Name == RouterMode);
Router = routetype != null ? (System.Activator.CreateInstance(routetype) as IRouter) : new NormalRouter();
var pathGeneratortype = GlobalType.AllTypes.Where(p => typeof(IPathGenerator).IsAssignableFrom(p)).FirstOrDefault(p => p.Name == PathMode);
PathGenerator = pathGeneratortype != null ? (System.Activator.CreateInstance(pathGeneratortype) as IPathGenerator) : new SmoothPathGenerator();
this.SourceConnectorInfo = sourceConnectorInfo;
this.SinkConnectorInfo = sinkConnectorInfo;
DeleteConnectionCommand = new SimpleCommand(DeleteConnection);
if (Parent != null && Parent.ColorViewModel != null)
{
this.ColorViewModel = CopyHelper.Mapper(Parent.ColorViewModel);
}
if (sinkConnectorInfo is FullyCreatedConnectorInfo sink && sink.DataItem.ShowArrow == false)
{
this.ColorViewModel.RightArrowPathStyle = ArrowPathStyle.None;
}
}
public override SelectableDesignerItemBase ToXmlObject()
{
if (IsFullConnection)
{
ConnectionItem connection = new ConnectionItem(
SourceConnectorInfo.DataItem.Id,
SourceConnectorInfo.Orientation,
SourceConnectorInfo.DataItem.GetType(),
GetXRatioFromConnector(SourceConnectorInfo),
GetYRatioFromConnector(SourceConnectorInfo),
SourceConnectorInfo.IsInnerPoint,
SinkConnectorInfoFully.DataItem.Id,
SinkConnectorInfoFully.Orientation,
SinkConnectorInfoFully.DataItem.GetType(),
GetXRatioFromConnector(SinkConnectorInfoFully),
GetYRatioFromConnector(SinkConnectorInfoFully),
SinkConnectorInfoFully.IsInnerPoint,
this);
ConnectionItem connection = new ConnectionItem(this);
return connection;
}
@@ -61,12 +72,7 @@ namespace AIStudio.Wpf.DiagramDesigner
public override Type ToXmlType()
{
return typeof(ConnectionItem);
}
public IPathFinder PathFinder
{
get; set;
}
}
private PointBase _sourceA;
public PointBase SourceA
@@ -165,11 +171,39 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
public DrawMode VectorLineDrawMode
public string PathMode
{
get; set;
}
public string RouterMode
{
get; set;
}
public IRouter Router
{
get; set;
}
public IPathGenerator PathGenerator
{
get; set;
}
private PathGeneratorResult _pathGeneratorResult;
public PathGeneratorResult PathGeneratorResult
{
get
{
return _pathGeneratorResult;
}
private set
{
SetProperty(ref _pathGeneratorResult, value);
}
}
//待完善这两处
public List<LinkVertexModel> Vertices { get; } = new List<LinkVertexModel>();
public List<LinkLabelModel> Labels { get; set; } = new List<LinkLabelModel>();
@@ -185,20 +219,6 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
public ConnectorInfo ConnectorInfo(ConnectorOrientation orientation, double left, double top, double width, double height, PointBase position)
{
return new ConnectorInfo()
{
Orientation = orientation,
DesignerItemSize = new SizeBase(width, height),
DesignerItemLeft = left,
DesignerItemTop = top,
Position = position
};
}
private FullyCreatedConnectorInfo _sourceConnectorInfo;
public FullyCreatedConnectorInfo SourceConnectorInfo
{
@@ -227,15 +247,11 @@ namespace AIStudio.Wpf.DiagramDesigner
{
if (SetProperty(ref _sinkConnectorInfo, value))
{
SourceB = _sinkConnectorInfo.Location;
if (_sinkConnectorInfo is FullyCreatedConnectorInfo)
{
SourceB = PointHelper.GetPointForConnector((FullyCreatedConnectorInfo)_sinkConnectorInfo);
{
(((FullyCreatedConnectorInfo)_sinkConnectorInfo).DataItem as INotifyPropertyChanged).PropertyChanged += new WeakINPCEventHandler(ConnectorViewModel_PropertyChanged).Handler;
}
else
{
SourceB = SinkConnectorInfoPart.Position;
}
}
}
}
@@ -256,11 +272,11 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
public ConnectorPoint OnGoingPosition
public PointBase OnGoingPosition
{
get
{
return SinkConnectorInfoPart?.Position;
return SinkConnectorInfoPart?.Location?.MiddlePosition ?? PointBase.Zero;
}
}
@@ -274,52 +290,6 @@ namespace AIStudio.Wpf.DiagramDesigner
public bool IsPortless => SourceConnectorInfo?.DataItem?.Connectors?.Count() == 0;
public double GetXRatioFromConnector(FullyCreatedConnectorInfo info)
{
if (info.IsInnerPoint)
{
return info.XRatio;
}
else
{
switch (info.Orientation)
{
case ConnectorOrientation.Top:
return 0.5;
case ConnectorOrientation.Left:
return 0;
case ConnectorOrientation.Bottom:
return 0.5;
case ConnectorOrientation.Right:
return 1;
default: return info.XRatio;
}
}
}
public double GetYRatioFromConnector(FullyCreatedConnectorInfo info)
{
if (info.IsInnerPoint)
{
return info.YRatio;
}
else
{
switch (info.Orientation)
{
case ConnectorOrientation.Top:
return 0;
case ConnectorOrientation.Left:
return 0.5;
case ConnectorOrientation.Bottom:
return 1;
case ConnectorOrientation.Right:
return 0.5;
default: return info.YRatio;
}
}
}
private void UpdateArea()
{
Area = new RectangleBase(SourceA, SourceB);
@@ -327,13 +297,17 @@ namespace AIStudio.Wpf.DiagramDesigner
private void UpdateConnectionPoints()
{
ConnectionPoints = PathFinder.UpdateConnectionPoints(Parent, SourceA, SourceB, SourceConnectorInfo, SinkConnectorInfo);
StartPoint = ConnectionPoints.First();
EndPoint = ConnectionPoints.Last();
//ConnectionPoints = PathFinder.UpdateConnectionPoints(Parent, SourceA, SourceB, SourceConnectorInfo, SinkConnectorInfo);
//StartPoint = ConnectionPoints.First();
//EndPoint = ConnectionPoints.Last();
//var router = Routers.Normal(Parent, this);
//var pathGenerator = PathGenerators.Smooth(Parent, this, router, SourceA, SourceB);
var route = Router.Get(Parent, this);
(var source, var target) = FindConnectionPoints(route);
if (source == null || target == null)
return;
PathGeneratorResult = PathGenerator.Get(Parent, this, route, source.Value, target.Value);
}
private void ConnectorViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
@@ -364,36 +338,7 @@ namespace AIStudio.Wpf.DiagramDesigner
break;
}
}
private void Init(FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo)
{
this.Parent = sourceConnectorInfo.DataItem.Parent;
if (VectorLineDrawMode == DrawMode.ConnectingLine)
{
PathFinder = new StraightLinePathFinder();
}
else if (VectorLineDrawMode == DrawMode.BoundaryConnectingLine)
{
PathFinder = new BoundaryPathFinder();
}
else
{
PathFinder = new OrthogonalPathFinder();
}
this.SourceConnectorInfo = sourceConnectorInfo;
this.SinkConnectorInfo = sinkConnectorInfo;
DeleteConnectionCommand = new SimpleCommand(DeleteConnection);
if (Parent != null && Parent.ColorViewModel != null)
{
this.ColorViewModel = CopyHelper.Mapper(Parent.ColorViewModel);
}
if (sinkConnectorInfo is FullyCreatedConnectorInfo sink && sink.DataItem.ShowArrow == false)
{
this.ColorViewModel.RightArrowPathStyle = ArrowPathStyle.None;
}
}
}
public SimpleCommand DeleteConnectionCommand
{
@@ -461,34 +406,82 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
//private (PointInfoBase source, PointInfoBase target) FindConnectionPoints(PointInfoBase[] route)
//{
// if (IsPortless) // Portless
// {
// if (SourceConnectorInfo.DataItem == null || (IsFullConnection && SinkConnectorInfoFully.DataItem == null))
// return (null, null);
private (PointBase? source, PointBase? target) FindConnectionPoints(PointBase[] route)
{
if (IsPortless) // Portless
{
if (SourceConnectorInfo.DataItem == null || (IsFullConnection && SinkConnectorInfoFully.DataItem == null))
return (null, null);
var sourceCenter = SourceConnectorInfo.DataItem.GetBounds().Center;
var targetCenter = SinkConnectorInfoFully?.DataItem?.GetBounds().Center ?? OnGoingPosition;
var firstPt = route.Length > 0 ? route[0] : targetCenter;
var secondPt = route.Length > 0 ? route[0] : sourceCenter;
var sourceLine = new LineBase(firstPt, sourceCenter);
var targetLine = new LineBase(secondPt, targetCenter);
var sourceIntersections = SourceConnectorInfo.DataItem.GetShape().GetIntersectionsWithLine(sourceLine);
var targetIntersections = SinkConnectorInfoFully.DataItem.GetShape()?.GetIntersectionsWithLine(targetLine) ?? new PointBase[] { OnGoingPosition };
var sourceIntersection = GetClosestPointTo(sourceIntersections, firstPt);
var targetIntersection = GetClosestPointTo(targetIntersections, secondPt);
return (sourceIntersection ?? sourceCenter, targetIntersection ?? targetCenter);
}
else
{
var source = GetPortPositionBasedOnAlignment(SourceConnectorInfo, ColorViewModel.LeftArrowSizeStyle);
var target = GetPortPositionBasedOnAlignment(SinkConnectorInfoFully, ColorViewModel.RightArrowSizeStyle);
return (source, target ?? OnGoingPosition);
}
}
private PointBase? GetPortPositionBasedOnAlignment(ConnectorInfoBase port, ArrowSizeStyle marker)
{
if (port == null)
return null;
if (marker == null)
return port.Location.MiddlePosition;
var pt = port.Location.Position;
switch (port.Orientation)
{
case ConnectorOrientation.Top:
return new PointBase(pt.X + port.ConnectorWidth / 2, pt.Y);
case ConnectorOrientation.TopRight:
return new PointBase(pt.X + port.ConnectorWidth, pt.Y);
case ConnectorOrientation.Right:
return new PointBase(pt.X + port.ConnectorWidth, pt.Y + port.ConnectorHeight / 2);
case ConnectorOrientation.BottomRight:
return new PointBase(pt.X + port.ConnectorWidth, pt.Y + port.ConnectorHeight);
case ConnectorOrientation.Bottom:
return new PointBase(pt.X + port.ConnectorWidth / 2, pt.Y + port.ConnectorHeight);
case ConnectorOrientation.BottomLeft:
return new PointBase(pt.X, pt.Y + port.ConnectorHeight);
case ConnectorOrientation.Left:
return new PointBase(pt.X, pt.Y + port.ConnectorHeight / 2);
default:
return pt;
}
}
private PointBase? GetClosestPointTo(IEnumerable<PointBase> points, PointBase point)
{
var minDist = double.MaxValue;
PointBase? minPoint = null;
foreach (var pt in points)
{
var dist = pt.DistanceTo(point);
if (dist < minDist)
{
minDist = dist;
minPoint = pt;
}
}
return minPoint;
}
// var sourceCenter = SourceConnectorInfo.DataItem.GetBounds().Center;
// var targetCenter = SinkConnectorInfoFully?.DataItem?.GetBounds().Center ?? SinkConnectorInfoFully.Position;
// var firstPt = route.Length > 0 ? route[0] : targetCenter;
// var secondPt = route.Length > 0 ? route[0] : sourceCenter;
// var sourceLine = new Line(firstPt, sourceCenter);
// var targetLine = new Line(secondPt, targetCenter);
// var sourceIntersections = Link.SourceNode.GetShape().GetIntersectionsWithLine(sourceLine);
// var targetIntersections = Link.TargetNode.GetShape().GetIntersectionsWithLine(targetLine);
// var sourceIntersection = GetClosestPointTo(sourceIntersections, firstPt);
// var targetIntersection = GetClosestPointTo(targetIntersections, secondPt);
// return (sourceIntersection ?? sourceCenter, targetIntersection ?? targetCenter);
// }
// else
// {
// if (!Link.SourcePort.Initialized || Link.TargetPort?.Initialized == false)
// return (null, null);
// var source = GetPortPositionBasedOnAlignment(Link.SourcePort, Link.SourceMarker);
// var target = GetPortPositionBasedOnAlignment(Link.TargetPort, Link.TargetMarker);
// return (source, target ?? Link.OnGoingPosition);
// }
//}
}
}

View File

@@ -7,7 +7,7 @@ using System.Windows;
using System.Linq;
using System.Reactive.Linq;
using AIStudio.Wpf.DiagramDesigner.Models;
using AIStudio.Wpf.DiagramDesigner.Geometry;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
namespace AIStudio.Wpf.DiagramDesigner
{
@@ -15,14 +15,17 @@ namespace AIStudio.Wpf.DiagramDesigner
{
public DesignerItemViewModelBase() : base()
{
ShapeDefiner = Shapes.Rectangle;
}
public DesignerItemViewModelBase(IDiagramViewModel parent, DesignerItemBase designer) : base(parent, designer)
{
ShapeDefiner = Shapes.Rectangle;
}
public DesignerItemViewModelBase(IDiagramViewModel parent, string json) : base(parent, json)
{
ShapeDefiner = Shapes.Rectangle;
}
protected override void Init()
@@ -415,21 +418,23 @@ namespace AIStudio.Wpf.DiagramDesigner
public RectangleBase GetBounds(bool includePorts = false)
{
if (!includePorts)
return new RectangleBase(Left, Top, ItemWidth, ItemHeight);
return new RectangleBase(Position, Size);
var leftPort = LeftConnector;
var topPort = TopConnector;
var rightPort = RightConnector;
var bottomPort = BottomConnector;
var left = leftPort == null ? Left: Math.Min(Left, leftPort.Position.X);
var top = topPort == null ? Top : Math.Min(Left, topPort.Position.Y);
var right = rightPort == null ? Left + ItemWidth :
Math.Max(rightPort.Position.X + rightPort.ConnectorWidth, Left + ItemWidth);
var bottom = bottomPort == null ? Top + ItemHeight :
Math.Max(bottomPort.Position.Y + bottomPort.ConnectorHeight, Top + ItemHeight);
var left = leftPort == null ? Position.X: Math.Min(Position.X, leftPort.Location.Position.X);
var top = topPort == null ? Position.Y : Math.Min(Position.Y, topPort.Location.Position.Y);
var right = rightPort == null ? Position.X + ItemWidth :
Math.Max(rightPort.Location.Position.X + rightPort.ConnectorWidth, Position.X + ItemWidth);
var bottom = bottomPort == null ? Position.Y + ItemHeight :
Math.Max(bottomPort.Location.Position.Y + bottomPort.ConnectorHeight, Position.Y + ItemHeight);
return new RectangleBase(left, top, right, bottom);
return new RectangleBase(left, top, right, bottom, true);
}
public IShape GetShape() => ShapeDefiner(this);
}
}

View File

@@ -8,7 +8,7 @@ using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using AIStudio.Wpf.DiagramDesigner.Geometry;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
using AIStudio.Wpf.DiagramDesigner.Helpers;
using AIStudio.Wpf.DiagramDesigner.Models;
using Newtonsoft.Json;
@@ -1489,7 +1489,7 @@ namespace AIStudio.Wpf.DiagramDesigner
ConnectorOrientation sinkConnectorOrientation = connectionItem.SinkOrientation;
FullyCreatedConnectorInfo sinkConnectorInfo = GetFullConnectorInfo(connectionItem.Id, sinkItem, sinkConnectorOrientation, connectionItem.SinkXRatio, connectionItem.SinkYRatio, connectionItem.SinkInnerPoint);
ConnectorViewModel connectionVM = new ConnectorViewModel(this, sourceConnectorInfo, sinkConnectorInfo, connectionItem, connectionItem.VectorLineDrawMode);
ConnectorViewModel connectionVM = new ConnectorViewModel(this, sourceConnectorInfo, sinkConnectorInfo, connectionItem);
connectors.Add(connectionVM);
DesignerItemViewModelBase textItem = items.OfType<DesignerItemViewModelBase>().FirstOrDefault(x => x.ParentId == connectionItem.Id);

View File

@@ -3,13 +3,13 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using AIStudio.Wpf.DiagramDesigner.Geometry;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
namespace AIStudio.Wpf.DiagramDesigner
{
public class FullyCreatedConnectorInfo : ConnectorInfoBase
{
public override PointBase Position
public override ConnectorPoint Location
{
get
{
@@ -152,6 +152,52 @@ namespace AIStudio.Wpf.DiagramDesigner
return menuOptions;
}
}
public double GetXRatioFromConnector()
{
if (IsInnerPoint)
{
return XRatio;
}
else
{
switch (Orientation)
{
case ConnectorOrientation.Top:
return 0.5;
case ConnectorOrientation.Left:
return 0;
case ConnectorOrientation.Bottom:
return 0.5;
case ConnectorOrientation.Right:
return 1;
default: return XRatio;
}
}
}
public double GetYRatioFromConnector()
{
if (IsInnerPoint)
{
return YRatio;
}
else
{
switch (Orientation)
{
case ConnectorOrientation.Top:
return 0;
case ConnectorOrientation.Left:
return 0.5;
case ConnectorOrientation.Bottom:
return 1;
case ConnectorOrientation.Right:
return 0.5;
default: return YRatio;
}
}
}
}

View File

@@ -1,4 +1,4 @@
using AIStudio.Wpf.DiagramDesigner.Geometry;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
namespace AIStudio.Wpf.DiagramDesigner
{

View File

@@ -3,24 +3,24 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using AIStudio.Wpf.DiagramDesigner.Geometry;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
namespace AIStudio.Wpf.DiagramDesigner
{
public class PartCreatedConnectionInfo : ConnectorInfoBase
{
private PointBase position;
public override PointBase Position
private ConnectorPoint location;
public override ConnectorPoint Location
{
get
{
return position;
return location;
}
}
public PartCreatedConnectionInfo(double X, double Y) : base(ConnectorOrientation.None)
{
this.position = new PointBase(X, Y);
this.location = new ConnectorPoint(X, Y);
}
}
}