mirror of
https://gitee.com/akwkevin/aistudio.-wpf.-diagram
synced 2026-03-06 17:50:51 +08:00
可以把连线从节点上拖下来,并且依附上去。
This commit is contained in:
@@ -5,6 +5,7 @@ using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using AIStudio.Wpf.DiagramDesigner.Controls;
|
||||
@@ -480,7 +481,7 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
|
||||
protected override void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (IsLoaded == false) return;
|
||||
if (IsLoaded == false || IsInternalChanged == true ) return;
|
||||
|
||||
if (sender is ConnectionViewModel)
|
||||
{
|
||||
@@ -513,10 +514,6 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
{
|
||||
SourceConnectorInfoFully.DataItem.PropertyChanged += new WeakINPCEventHandler(Item_PropertyChanged).Handler;
|
||||
}
|
||||
//else if (SourceConnectorInfoPart != null)
|
||||
//{
|
||||
// SourceConnectorInfoPart.PropertyChanged += new WeakINPCEventHandler(Item_PropertyChanged).Handler;
|
||||
//}
|
||||
}
|
||||
break;
|
||||
case nameof(SinkConnectorInfo):
|
||||
@@ -527,10 +524,6 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
{
|
||||
SinkConnectorInfoFully.DataItem.PropertyChanged += new WeakINPCEventHandler(Item_PropertyChanged).Handler;
|
||||
}
|
||||
//else if (SinkConnectorInfoPart != null)
|
||||
//{
|
||||
// SinkConnectorInfoPart.PropertyChanged += new WeakINPCEventHandler(Item_PropertyChanged).Handler;
|
||||
//}
|
||||
}
|
||||
break;
|
||||
case nameof(IsSelected):
|
||||
@@ -580,15 +573,48 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (sender is ConnectorVertexModel)
|
||||
else if (sender is ConnectorVertexModel connectorVertexModel)
|
||||
{
|
||||
switch (e.PropertyName)
|
||||
{
|
||||
case nameof(ConnectorPointModel.X):
|
||||
case nameof(ConnectorPointModel.Y):
|
||||
UpdatePathGeneratorResult();
|
||||
if (connectorVertexModel.ConnectorVertexType == ConnectorVertexType.None)
|
||||
{
|
||||
UpdatePathGeneratorResult();
|
||||
}
|
||||
else if(connectorVertexModel.ConnectorVertexType == ConnectorVertexType.Start)
|
||||
{
|
||||
SetSourcePort(new PartCreatedConnectorInfo(connectorVertexModel.Position.X, connectorVertexModel.Position.Y));
|
||||
this.ZIndex = -1;
|
||||
}
|
||||
else if (connectorVertexModel.ConnectorVertexType == ConnectorVertexType.End)
|
||||
{
|
||||
SetSinkPort(new PartCreatedConnectorInfo(connectorVertexModel.Position.X, connectorVertexModel.Position.Y));
|
||||
this.ZIndex = -1;
|
||||
}
|
||||
break;
|
||||
case nameof(ConnectorPointModel.DragStart):
|
||||
if (connectorVertexModel.DragStart == false)
|
||||
{
|
||||
if (connectorVertexModel.ConnectorVertexType == ConnectorVertexType.Start)
|
||||
{
|
||||
var nearPort = Root.FindNearPortToAttachTo(this, ConnectorVertexType.Start);
|
||||
if (nearPort != null)
|
||||
{
|
||||
SetSourcePort(nearPort);
|
||||
}
|
||||
}
|
||||
else if (connectorVertexModel.ConnectorVertexType == ConnectorVertexType.End)
|
||||
{
|
||||
var nearPort = Root.FindNearPortToAttachTo(this, ConnectorVertexType.End);
|
||||
if (nearPort != null)
|
||||
{
|
||||
SetSinkPort(nearPort);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
else if (sender is ConnectorLabelModel linkLabelModel)
|
||||
@@ -613,21 +639,6 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
}
|
||||
}
|
||||
}
|
||||
//else if (sender is PartCreatedConnectorInfo)
|
||||
//{
|
||||
// if (e.PropertyName == "Position")
|
||||
// {
|
||||
// if (sender == SourceConnectorInfoPart)
|
||||
// {
|
||||
// SourceA = SourceConnectorInfo.Position;
|
||||
// }
|
||||
// else if (sender == SinkConnectorInfoPart)
|
||||
// {
|
||||
// SourceB = SinkConnectorInfo.Position;
|
||||
// }
|
||||
// UpdatePathGeneratorResult();
|
||||
// }
|
||||
//}
|
||||
else if (sender is ColorViewModel)
|
||||
{
|
||||
|
||||
@@ -679,29 +690,31 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
|
||||
var startVertice = Vertices.FirstOrDefault(p => p.ConnectorVertexType == ConnectorVertexType.Start);
|
||||
if (startVertice == null)
|
||||
{
|
||||
startVertice = new ConnectorVertexModel(this, StartPoint) { ConnectorVertexType = ConnectorVertexType.Start };
|
||||
startVertice.ColorViewModel.FillColor.Color = Colors.DarkRed;
|
||||
startVertice.ColorViewModel.LineColor.Color = Colors.DarkRed;
|
||||
Vertices.Add(startVertice);
|
||||
{
|
||||
startVertice = AddEndsVertex(StartPoint, ConnectorVertexType.Start);
|
||||
}
|
||||
else
|
||||
{
|
||||
IsInternalChanged = true;
|
||||
startVertice.SetPosition(StartPoint);
|
||||
IsInternalChanged = true;
|
||||
}
|
||||
startVertice.ColorViewModel.FillColor.Color = SourceConnectorInfoFully != null? Colors.DarkRed : Colors.Blue;
|
||||
startVertice.ColorViewModel.LineColor.Color = SourceConnectorInfoFully != null ? Colors.DarkRed : Colors.Blue;
|
||||
|
||||
var endVertice = Vertices.FirstOrDefault(p => p.ConnectorVertexType == ConnectorVertexType.End);
|
||||
if (endVertice == null)
|
||||
{
|
||||
endVertice = new ConnectorVertexModel(this, EndPoint) { ConnectorVertexType = ConnectorVertexType.End };
|
||||
endVertice.ColorViewModel.FillColor.Color = Colors.DarkRed;
|
||||
endVertice.ColorViewModel.LineColor.Color = Colors.DarkRed;
|
||||
Vertices.Add(endVertice);
|
||||
endVertice = AddEndsVertex(EndPoint, ConnectorVertexType.End);
|
||||
}
|
||||
else
|
||||
{
|
||||
IsInternalChanged = true;
|
||||
endVertice.SetPosition(EndPoint);
|
||||
IsInternalChanged = false;
|
||||
}
|
||||
endVertice.ColorViewModel.FillColor.Color = SinkConnectorInfoFully != null ? Colors.DarkRed : Colors.Blue;
|
||||
endVertice.ColorViewModel.LineColor.Color = SinkConnectorInfoFully != null ? Colors.DarkRed : Colors.Blue;
|
||||
|
||||
var paths = Labels.Count > 0 ? PathGeneratorResult.Paths.Select(p => new SvgPath(p)).ToArray() : Array.Empty<SvgPath>();
|
||||
foreach (var label in Labels)
|
||||
@@ -809,12 +822,12 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
return minPoint;
|
||||
}
|
||||
|
||||
public void SetSourcePort(FullyCreatedConnectorInfo port)
|
||||
public void SetSourcePort(ConnectorInfoBase port)
|
||||
{
|
||||
SourceConnectorInfo = port;
|
||||
}
|
||||
|
||||
public void SetSinkPort(FullyCreatedConnectorInfo port)
|
||||
public void SetSinkPort(ConnectorInfoBase port)
|
||||
{
|
||||
SinkConnectorInfo = port;
|
||||
}
|
||||
@@ -943,6 +956,16 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
UpdatePathGeneratorResult();
|
||||
}
|
||||
|
||||
public ConnectorVertexModel AddEndsVertex(PointBase pointBase, ConnectorVertexType connectorVertexType)
|
||||
{
|
||||
var vertice = new ConnectorVertexModel(this, pointBase);
|
||||
vertice.ConnectorVertexType= connectorVertexType;
|
||||
vertice.PropertyChanged += new WeakINPCEventHandler(Item_PropertyChanged).Handler;
|
||||
Vertices.Add(vertice);
|
||||
|
||||
return vertice;
|
||||
}
|
||||
|
||||
public void RemoveVertex(ConnectorVertexModel vertice)
|
||||
{
|
||||
Vertices.Remove(vertice);
|
||||
|
||||
@@ -143,7 +143,10 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
{
|
||||
ConnectorHeight = ScreenHelper.MmToWidth(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool CanAttachTo(ConnectorInfoBase port)
|
||||
=> port != this && !port.IsReadOnly;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,29 +144,48 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
}
|
||||
public virtual PointBase MiddlePosition => new PointBase(X, Y);
|
||||
|
||||
private double connectorWidth = 8;
|
||||
private double _connectorWidth = 8;
|
||||
public double ConnectorWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
return connectorWidth;
|
||||
return _connectorWidth;
|
||||
}
|
||||
set
|
||||
{
|
||||
connectorWidth = value;
|
||||
_connectorWidth = value;
|
||||
}
|
||||
}
|
||||
|
||||
private double connectorHeight = 8;
|
||||
private double _connectorHeight = 8;
|
||||
public double ConnectorHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
return connectorHeight;
|
||||
return _connectorHeight;
|
||||
}
|
||||
set
|
||||
{
|
||||
connectorHeight = value;
|
||||
_connectorHeight = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetPosition(PointBase position)
|
||||
{
|
||||
X = position.X;
|
||||
Y = position.Y;
|
||||
}
|
||||
|
||||
private bool _dragStart;
|
||||
public bool DragStart
|
||||
{
|
||||
get
|
||||
{
|
||||
return _dragStart;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetProperty(ref _dragStart, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,13 +86,6 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
Connector.RemoveVertex(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetPosition(PointBase position)
|
||||
{
|
||||
X = position.X;
|
||||
Y = position.Y;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum ConnectorVertexType
|
||||
|
||||
@@ -316,8 +316,17 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool CanAttachTo(FullyCreatedConnectorInfo port)
|
||||
=> port != this && !port.IsReadOnly && DataItem != port.DataItem;
|
||||
public override bool CanAttachTo(ConnectorInfoBase port)
|
||||
{
|
||||
if (port is FullyCreatedConnectorInfo fullyCreatedConnectorInfo)
|
||||
{
|
||||
return port != this && !port.IsReadOnly && DataItem != fullyCreatedConnectorInfo.DataItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
return base.CanAttachTo(port);
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
|
||||
@@ -136,7 +136,7 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
|
||||
}
|
||||
|
||||
public override bool CanAttachTo(FullyCreatedConnectorInfo port)
|
||||
public override bool CanAttachTo(ConnectorInfoBase port)
|
||||
{
|
||||
if (!base.CanAttachTo(port))
|
||||
{
|
||||
|
||||
@@ -17,6 +17,11 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
{
|
||||
get; set;
|
||||
} = new ShortcutOption();
|
||||
|
||||
public SnappingOption SnappingOption
|
||||
{
|
||||
get; set;
|
||||
} = new SnappingOption();
|
||||
}
|
||||
|
||||
public class LayoutOption
|
||||
@@ -24,6 +29,22 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
|
||||
}
|
||||
|
||||
public class SnappingOption
|
||||
{
|
||||
public bool EnableSnapping
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public double SnappingRadius
|
||||
{
|
||||
get; set;
|
||||
} = 50;
|
||||
public double HittingRadius
|
||||
{
|
||||
get; set;
|
||||
} = 20;
|
||||
}
|
||||
|
||||
public class ShortcutOption
|
||||
{
|
||||
[Description("Select All shortcut (CTRL+A by default)")]
|
||||
|
||||
@@ -3350,5 +3350,46 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 自动依附节点
|
||||
public FullyCreatedConnectorInfo FindNearPortToAttachTo(ConnectionViewModel partialConnection, ConnectorVertexType connectorVertexType)
|
||||
{
|
||||
if (partialConnection == null)
|
||||
return null;
|
||||
|
||||
foreach (var port in Items.OfType<DesignerItemViewModelBase>().ToList().SelectMany(n => n.Connectors))
|
||||
{
|
||||
if (connectorVertexType == ConnectorVertexType.Start)
|
||||
{
|
||||
if (partialConnection.SourceConnectorInfo.Position.DistanceTo(port.Position) < DiagramOption.SnappingOption.HittingRadius &&
|
||||
partialConnection.SinkConnectorInfo?.CanAttachTo(port) == true)
|
||||
return port;
|
||||
}
|
||||
else if (connectorVertexType == ConnectorVertexType.End)
|
||||
{
|
||||
if (partialConnection.SinkConnectorInfo.Position.DistanceTo(port.Position) < DiagramOption.SnappingOption.HittingRadius &&
|
||||
partialConnection.SourceConnectorInfo?.CanAttachTo(port) == true)
|
||||
return port;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public FullyCreatedConnectorInfo FindNearPortToAttachTo(ConnectionViewModel partialConnection)
|
||||
{
|
||||
if (partialConnection == null)
|
||||
return null;
|
||||
|
||||
foreach (var port in Items.OfType<DesignerItemViewModelBase>().ToList().SelectMany(n => n.Connectors))
|
||||
{
|
||||
if (partialConnection.OnGoingPosition.DistanceTo(port.Position) < DiagramOption.SnappingOption.SnappingRadius &&
|
||||
partialConnection.SourceConnectorInfoFully?.CanAttachTo(port) == true)
|
||||
return port;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,6 +147,11 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
get;set;
|
||||
}
|
||||
|
||||
public bool IsInternalChanged
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public IDiagramViewModel Root
|
||||
{
|
||||
get; set;
|
||||
@@ -461,12 +466,12 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
|
||||
protected virtual void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (IsLoaded == false) { return; }
|
||||
if (IsLoaded == false || IsInternalChanged == true) { return; }
|
||||
}
|
||||
|
||||
protected void FontViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (IsLoaded == false) { return; }
|
||||
if (IsLoaded == false || IsInternalChanged == true) { return; }
|
||||
|
||||
if (e.PropertyName == nameof(FontViewModel.FontCase))
|
||||
{
|
||||
@@ -478,21 +483,21 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
|
||||
protected void ColorViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (IsLoaded == false) { return; }
|
||||
if (IsLoaded == false || IsInternalChanged == true ) { return; }
|
||||
|
||||
RaisePropertyChanged(sender, e);
|
||||
}
|
||||
|
||||
protected void ShapeViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (IsLoaded == false) { return; }
|
||||
if (IsLoaded == false || IsInternalChanged == true) { return; }
|
||||
|
||||
RaisePropertyChanged(sender, e);
|
||||
}
|
||||
|
||||
protected void AnimationViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (IsLoaded == false) { return; }
|
||||
if (IsLoaded == false || IsInternalChanged == true) { return; }
|
||||
|
||||
RaisePropertyChanged(sender, e);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user