using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
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;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
using AIStudio.Wpf.DiagramDesigner.Helpers;
using SvgPathProperties;
namespace AIStudio.Wpf.DiagramDesigner
{
///
/// DefaultLink
///
public class ConnectionViewModel : SelectableDesignerItemViewModelBase
{
public ConnectionViewModel()
{
}
public ConnectionViewModel(ConnectorInfoBase sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo, DrawMode drawMode = DrawMode.ConnectingLineSmooth, RouterMode routerMode = AIStudio.Wpf.DiagramDesigner.RouterMode.RouterNormal) : this(null, sourceConnectorInfo, sinkConnectorInfo, drawMode, routerMode)
{
}
public ConnectionViewModel(IDiagramViewModel root, ConnectorInfoBase sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo, DrawMode drawMode = DrawMode.ConnectingLineSmooth, RouterMode routerMode = AIStudio.Wpf.DiagramDesigner.RouterMode.RouterNormal) : base(root)
{
_pathMode = drawMode.ToString();
_routerMode = routerMode.ToString();
Init(root, sourceConnectorInfo, sinkConnectorInfo);
}
public ConnectionViewModel(IDiagramViewModel root, ConnectorInfoBase sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo, ConnectionItem designer) : base(root, designer)
{
_pathMode = designer.PathMode;
_routerMode = designer.RouterMode;
Init(root, sourceConnectorInfo, sinkConnectorInfo);
}
public override SelectableItemBase GetSerializableObject()
{
if (IsFullConnection)
{
ConnectionItem connection = new ConnectionItem(this);
return connection;
}
else//Todo,半连接线也可序列化
{
return null;
}
}
protected virtual void Init(IDiagramViewModel root, ConnectorInfoBase sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo)
{
IsLoaded = false;
this.Root = root ?? sourceConnectorInfo.Root;
if (sinkConnectorInfo is FullyCreatedConnectorInfo sink && sink.DataItem.ShowArrow == false)
{
this.ShapeViewModel.SinkMarker = new SharpPath("", 10, 10, PathStyle.None, SizeStyle.Middle);
}
var routetype = TypeHelper.GetType(RouterMode);
Router = routetype != null ? (System.Activator.CreateInstance(routetype) as IRouter) : new RouterNormal();
var pathGeneratortype = TypeHelper.GetType(PathMode);
PathGenerator = pathGeneratortype != null ? (System.Activator.CreateInstance(pathGeneratortype) as IPathGenerator) : new ConnectingLineSmooth();
IsLoaded= true;
this.SourceConnectorInfo = sourceConnectorInfo;
this.SinkConnectorInfo = sinkConnectorInfo;
DeleteConnectionCommand = new SimpleCommand(Command_Enable, DeleteConnection);
AddVertexCommand = new SimpleCommand(Command_Enable, AddVertex);
AddLabelCommand = new SimpleCommand(Command_Enable, para => AddLabel());
}
protected override void LoadDesignerItemViewModel(SelectableItemBase designerbase)
{
base.LoadDesignerItemViewModel(designerbase);
if (designerbase is ConnectionItem designer)
{
Vertices = new ObservableCollection(designer.Vertices.Select(p => new ConnectorVertexModel(this.Root, this, designer)));
Labels = new ObservableCollection(designer.Labels.Select(p => new ConnectorLabelModel(this.Root, this, designer)));
}
}
#region 属性
private string _text;
[Browsable(true)]
[CanDo]
public override string Text
{
get
{
var text = _text;
if (Labels?.Count > 0)
{
text = Labels[0].Text;
}
if (FontViewModel.FontCase == FontCase.Upper)
{
return text?.ToUpper();
}
else if (FontViewModel.FontCase == FontCase.Lower)
{
return text?.ToLower();
}
else
{
return text;
}
}
set
{
if (SetProperty(ref _text, value))
{
if (!string.IsNullOrEmpty(_text))
{
if (Labels?.Count > 0)
{
Labels[0].Text = _text;
}
else
{
AddLabel(_text);
}
}
else
{
ClearLabel();
}
}
}
}
private PointBase _sourceA;
public PointBase SourceA
{
get
{
return _sourceA;
}
set
{
SetProperty(ref _sourceA, value);
}
}
private PointBase _sourceB;
public PointBase SourceB
{
get
{
return _sourceB;
}
set
{
SetProperty(ref _sourceB, value);
}
}
private PointBase _startPoint;
public PointBase StartPoint
{
get
{
return _startPoint;
}
private set
{
SetProperty(ref _startPoint, value);
}
}
private PointBase _endPoint;
public PointBase EndPoint
{
get
{
return _endPoint;
}
private set
{
SetProperty(ref _endPoint, value);
}
}
private double _startAngle;
public double StartAngle
{
get
{
return _startAngle;
}
private set
{
SetProperty(ref _startAngle, value);
}
}
private double _endAngle;
public double EndAngle
{
get
{
return _endAngle;
}
private set
{
SetProperty(ref _endAngle, value);
}
}
private RectangleBase _startRectangle;
public RectangleBase StartRectangle
{
get
{
return _startRectangle;
}
private set
{
SetProperty(ref _startRectangle, value);
}
}
private RectangleBase _endRectangle;
public RectangleBase EndRectangle
{
get
{
return _endRectangle;
}
private set
{
SetProperty(ref _endRectangle, value);
}
}
private Thickness _dragThumbMargin;
public Thickness DragThumbMargin
{
get
{
return _dragThumbMargin;
}
private set
{
SetProperty(ref _dragThumbMargin, value);
}
}
private RectangleBase _area;
public RectangleBase Area
{
get
{
return _area;
}
private set
{
SetProperty(ref _area, value);
}
}
private string _pathMode;
public string PathMode
{
get
{
return _pathMode;
}
set
{
SetProperty(ref _pathMode, value);
}
}
private string _routerMode;
public string RouterMode
{
get
{
return _routerMode;
}
set
{
SetProperty(ref _routerMode, value);
}
}
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);
}
}
private bool _shouldInsertAnchor;
public bool ShouldInsertAnchor
{
get
{
return _shouldInsertAnchor;
}
set
{
SetProperty(ref _shouldInsertAnchor, value);
}
}
//待完善这两处
private ObservableCollection _vertices = new ObservableCollection();
public ObservableCollection Vertices
{
get
{
return _vertices;
}
private set
{
SetProperty(ref _vertices, value);
}
}
private ObservableCollection _labels = new ObservableCollection();
public ObservableCollection Labels
{
get
{
return _labels;
}
private set
{
SetProperty(ref _labels, value);
}
}
public virtual Dictionary PropertiesSetting
{
get
{
return new Dictionary()
{
{ "Text","文本" },
};
}
}
private ConnectorInfoBase _sourceConnectorInfo;
public ConnectorInfoBase SourceConnectorInfo
{
get
{
return _sourceConnectorInfo;
}
set
{
SetProperty(ref _sourceConnectorInfo, value);
}
}
public FullyCreatedConnectorInfo SourceConnectorInfoFully
{
get
{
return SourceConnectorInfo as FullyCreatedConnectorInfo;
}
}
public PartCreatedConnectorInfo SourceConnectorInfoPart
{
get
{
return SourceConnectorInfo as PartCreatedConnectorInfo;
}
}
private ConnectorInfoBase _sinkConnectorInfo;
public ConnectorInfoBase SinkConnectorInfo
{
get
{
return _sinkConnectorInfo;
}
set
{
SetProperty(ref _sinkConnectorInfo, value);
}
}
public FullyCreatedConnectorInfo SinkConnectorInfoFully
{
get
{
return SinkConnectorInfo as FullyCreatedConnectorInfo;
}
}
public PartCreatedConnectorInfo SinkConnectorInfoPart
{
get
{
return SinkConnectorInfo as PartCreatedConnectorInfo;
}
}
public PointBase OnGoingPosition
{
get
{
return SinkConnectorInfoPart?.MiddlePosition ?? PointBase.Zero;
}
}
public bool IsFullConnection
{
get
{
return SourceConnectorInfoFully != null && SinkConnectorInfoFully != null;
}
}
public double SmoothMargin { get; set; } = 125;
public double SmoothAutoSlope { get; set; } = 1;
public double OrthogonalShapeMargin { get; set; } = 10;
public double OrthogonalGlobalBoundsMargin { get; set; } = 50;
public bool IsPortless => SourceConnectorInfoFully?.IsPortless == true || SinkConnectorInfoFully?.IsPortless == true;
#endregion
#region 方法
public ICommand DeleteConnectionCommand
{
get; set;
}
public ICommand AddVertexCommand
{
get; set;
}
public ICommand AddLabelCommand
{
get; set;
}
#endregion
protected override void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (IsLoaded == false || IsInternalChanged == true ) return;
if (sender is ConnectionViewModel)
{
switch (e.PropertyName)
{
case nameof(SourceA):
case nameof(SourceB):
UpdateArea();
break;
case nameof(Area):
UpdatePathGeneratorResult();
break;
case nameof(Vertices):
foreach (var vertice in Vertices)
{
vertice.PropertyChanged += new WeakINPCEventHandler(Item_PropertyChanged).Handler;
}
break;
case nameof(Labels):
foreach (var label in Labels)
{
label.PropertyChanged += new WeakINPCEventHandler(Item_PropertyChanged).Handler;
}
break;
case nameof(SourceConnectorInfo):
if (SourceConnectorInfo != null)
{
SourceA = SourceConnectorInfo.Position;
if (SourceConnectorInfoFully != null)
{
SourceConnectorInfoFully.DataItem.PropertyChanged += new WeakINPCEventHandler(Item_PropertyChanged).Handler;
}
}
break;
case nameof(SinkConnectorInfo):
if (SinkConnectorInfo != null)
{
SourceB = SinkConnectorInfo.Position;
if (SinkConnectorInfoFully != null)
{
SinkConnectorInfoFully.DataItem.PropertyChanged += new WeakINPCEventHandler(Item_PropertyChanged).Handler;
}
}
break;
case nameof(IsSelected):
if (IsSelected == false)
{
Labels.FirstOrDefault()?.AddToSelection(false, true);
}
break;
case nameof(RouterMode):
var routetype = TypeHelper.GetType(RouterMode);
Router = routetype != null ? (System.Activator.CreateInstance(routetype) as IRouter) : new RouterNormal();
UpdatePathGeneratorResult();
break;
case nameof(PathMode):
var pathGeneratortype = TypeHelper.GetType(PathMode);
PathGenerator = pathGeneratortype != null ? (System.Activator.CreateInstance(pathGeneratortype) as IPathGenerator) : new ConnectingLineSmooth();
UpdatePathGeneratorResult();
break;
}
}
else if (sender is ShapeViewModel)
{
if (e.PropertyName == nameof(ShapeViewModel.SourceMarker) ||
e.PropertyName == nameof(ShapeViewModel.SinkMarker))
{
UpdatePathGeneratorResult();
}
}
else if (sender is DesignerItemViewModelBase)
{
switch (e.PropertyName)
{
case nameof(DesignerItemViewModelBase.ItemHeight):
case nameof(DesignerItemViewModelBase.ItemWidth):
case nameof(DesignerItemViewModelBase.Left):
case nameof(DesignerItemViewModelBase.Top):
if (IsFullConnection)
{
//减少触发一次画线
SourceA = PointHelper.GetPointForConnector(this.SourceConnectorInfoFully);
SourceB = PointHelper.GetPointForConnector(this.SinkConnectorInfoFully);
}
else
{
SourceA = SourceConnectorInfo.MiddlePosition;
}
break;
}
}
else if (sender is ConnectorVertexModel connectorVertexModel)
{
switch (e.PropertyName)
{
case nameof(ConnectorPointModel.X):
case nameof(ConnectorPointModel.Y):
if (connectorVertexModel.ConnectorVertexType == ConnectorVertexType.None)
{
UpdatePathGeneratorResult();
}
else if(connectorVertexModel.ConnectorVertexType == ConnectorVertexType.Start)
{
var nearPort = Root.FindNearPortToAttachTo(this, ConnectorVertexType.Start);
SetSourcePort(new PartCreatedConnectorInfo(connectorVertexModel.Position.X, connectorVertexModel.Position.Y));
}
else if (connectorVertexModel.ConnectorVertexType == ConnectorVertexType.End)
{
var nearPort = Root.FindNearPortToAttachTo(this, ConnectorVertexType.End);
SetSinkPort(new PartCreatedConnectorInfo(connectorVertexModel.Position.X, connectorVertexModel.Position.Y));
}
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);
}
}
Root?.ClearNearPort();
}
break;
}
}
else if (sender is ConnectorLabelModel linkLabelModel)
{
switch (e.PropertyName)
{
case nameof(ConnectorPointModel.X):
{
if (e is ValuePropertyChangedEventArgs valuePropertyChangedEventArgs)
{
linkLabelModel.UpdateOffsetX((double)valuePropertyChangedEventArgs.OldValue, (double)valuePropertyChangedEventArgs.NewValue);
}
break;
}
case nameof(ConnectorPointModel.Y):
{
if (e is ValuePropertyChangedEventArgs valuePropertyChangedEventArgs)
{
linkLabelModel.UpdateOffsetY((double)valuePropertyChangedEventArgs.OldValue, (double)valuePropertyChangedEventArgs.NewValue);
}
break;
}
}
}
else if (sender is ColorViewModel)
{
}
}
public override bool Verify()
{
return IsFullConnection == false || SourceConnectorInfo?.CanAttachTo(SinkConnectorInfo) == true;
}
private void UpdateArea()
{
Area = new RectangleBase(SourceA, SourceB);
}
private void UpdatePathGeneratorResult()
{
if (SourceConnectorInfo == null || SinkConnectorInfo == null)
return;
var route = Router.Get(Root, this);
(var source, var target) = FindConnectionPoints(route);
if (source == null || target == null)
return;
PathGeneratorResult = PathGenerator.Get(Root, this, route, source.Value, target.Value);
var startMiddle = new RectangleBase
(
(PathGeneratorResult.SourceMarkerPosition.X + (source.Value.X - Area.Left)) / 2,
(PathGeneratorResult.SourceMarkerPosition.Y + (source.Value.Y - Area.Top)) / 2,
0,
0
);
var endMiddle = new RectangleBase
(
(PathGeneratorResult.TargetMarkerPosition.X + (target.Value.X - Area.Left)) / 2,
(PathGeneratorResult.TargetMarkerPosition.Y + (target.Value.Y - Area.Top)) / 2,
0,
0
);
StartRectangle = startMiddle.InflateRectangle(GetSourceMarkerWidth() / 2, GetSourceMarkerHeight() / 2);
EndRectangle = endMiddle.InflateRectangle(GetSinkMarkerWidth() / 2, GetSinkMarkerHeight() / 2);
StartAngle = PathGeneratorResult.SourceMarkerAngle;
EndAngle = PathGeneratorResult.TargetMarkerAngle;
StartPoint = new PointBase(source.Value.X - Area.Left , source.Value.Y - Area.Top );
EndPoint = new PointBase(target.Value.X - Area.Left , target.Value.Y - Area.Top);
var startVertice = Vertices.FirstOrDefault(p => p.ConnectorVertexType == ConnectorVertexType.Start);
if (startVertice == null)
{
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 = 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();
foreach (var label in Labels)
{
label.UpdatePosition(paths);
}
double marginwidth = 0;
double marginheight = 0;
if (Area.Width > SourceConnectorInfo.ConnectorWidth + SinkConnectorInfo.ConnectorWidth)
{
marginwidth = (SourceConnectorInfo.ConnectorWidth + SinkConnectorInfo.ConnectorWidth) / 2;
}
if (Area.Height > SourceConnectorInfo.ConnectorHeight + SinkConnectorInfo.ConnectorHeight)
{
marginheight = (SourceConnectorInfo.ConnectorHeight + SinkConnectorInfo.ConnectorHeight) / 2;
}
DragThumbMargin = new Thickness(marginwidth, marginheight, marginwidth, marginheight);
}
private void DeleteConnection(object args)
{
if (this.Root is IDiagramViewModel)
{
var diagramVM = this.Root as IDiagramViewModel;
diagramVM.DeleteCommand.Execute(this);
}
}
private (PointBase? source, PointBase? target) FindConnectionPoints(PointBase[] route)
{
if (IsPortless) // Portless
{
if (SourceConnectorInfoFully?.DataItem == null || SinkConnectorInfoFully?.DataItem == null)
return (null, null);
var sourceCenter = SourceConnectorInfoFully.IsPortless ? SourceConnectorInfoFully.DataItem.MiddlePosition : SourceConnectorInfoFully.MiddlePosition;
var targetCenter = SinkConnectorInfoFully?.IsPortless == true ? SinkConnectorInfoFully?.DataItem?.MiddlePosition ?? OnGoingPosition : SinkConnectorInfoFully?.MiddlePosition ?? 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 = SourceConnectorInfoFully.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 = SourceConnectorInfo.MiddlePosition;//GetPortPositionBasedOnAlignment(SourceConnectorInfoFully, ColorViewModel.LeftArrowSizeStyle);
var target = SinkConnectorInfo.MiddlePosition;// GetPortPositionBasedOnAlignment(SinkConnectorInfoFully, ColorViewModel.RightArrowSizeStyle);
return (source, target);
}
}
private PointBase? GetPortPositionBasedOnAlignment(ConnectorInfoBase port, SizeStyle marker)
{
if (port == null)
return null;
if (marker == 0)
return port.MiddlePosition;
var pt = port.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 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;
}
public void SetSourcePort(ConnectorInfoBase port)
{
SourceConnectorInfo = port;
}
public void SetSinkPort(ConnectorInfoBase port)
{
SinkConnectorInfo = port;
}
public void SetPartPostion(PointBase? sourcePoint, PointBase? sinkPoint)
{
if (sourcePoint != null)
{
SourceConnectorInfoPart.Position = sourcePoint.Value;
_sourceA = SourceConnectorInfoPart.Position;
}
if (sinkPoint != null)
{
SinkConnectorInfoPart.Position = sinkPoint.Value;
_sourceB = SinkConnectorInfoPart.Position;
}
UpdateArea();
}
public void UpdateConnectionMode(FullyCreatedConnectorInfo source, FullyCreatedConnectorInfo sink, string pathmode, string routermode)
{
//先置空,避免更新
SourceConnectorInfo = null;
SinkConnectorInfo = null;
PathMode = pathmode;
RouterMode = routermode;
SourceConnectorInfo = source;
SinkConnectorInfo = sink;
}
public void SetPathGeneratorParameter(double? smoothMargin, double? smoothAutoSlope, double? orthogonalShapeMargin, double? orthogonalGlobalBoundsMargin)
{
bool hasChanged = false;
if (smoothMargin != null && SmoothMargin != smoothMargin)
{
hasChanged = true;
SmoothMargin = smoothMargin.Value;
}
if (smoothAutoSlope != null && SmoothAutoSlope != smoothAutoSlope)
{
hasChanged = true;
SmoothAutoSlope = smoothAutoSlope.Value;
}
if (orthogonalShapeMargin != null && OrthogonalShapeMargin != orthogonalShapeMargin)
{
hasChanged = true;
OrthogonalShapeMargin = orthogonalShapeMargin.Value;
}
if (orthogonalGlobalBoundsMargin != null && OrthogonalGlobalBoundsMargin != orthogonalGlobalBoundsMargin)
{
hasChanged = true;
OrthogonalGlobalBoundsMargin = orthogonalGlobalBoundsMargin.Value;
}
if (hasChanged)
{
UpdatePathGeneratorResult();
}
}
public void SetVisible(bool visible)
{
Visible = visible;
}
public double GetSourceMarkerWidth()
{
if (string.IsNullOrEmpty(ShapeViewModel.SourceMarker.Path))
{
return 0;
}
return ShapeViewModel.SourceMarker.Width;
}
public double GetSourceMarkerHeight()
{
if (string.IsNullOrEmpty(ShapeViewModel.SourceMarker.Path))
{
return 0;
}
return ShapeViewModel.SourceMarker.Height;
}
public double GetSinkMarkerWidth()
{
if (string.IsNullOrEmpty(ShapeViewModel.SinkMarker.Path))
{
return 0;
}
return ShapeViewModel.SinkMarker.Width;
}
public double GetSinkMarkerHeight()
{
if (string.IsNullOrEmpty(ShapeViewModel.SinkMarker.Path))
{
return 0;
}
return ShapeViewModel.SinkMarker.Height;
}
#region 双击添加
private void AddVertex(object parameter)
{
MouseButtonEventArgs mosueArg = ((EventToCommandArgs)parameter).EventArgs as MouseButtonEventArgs;
var position = mosueArg.GetPosition(((EventToCommandArgs)parameter).Sender as IInputElement);
AddVertex(position, false);
if (!((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control))
{
ShouldInsertAnchor = false;
}
}
public void AddVertex(PointBase pointBase, bool absolute = true)
{
if (absolute)
{
pointBase = new PointBase(pointBase.X - Area.Left, pointBase.Y - Area.Top);
}
var vertice = new ConnectorVertexModel(this, pointBase);
vertice.ColorViewModel.LineColor.Color = Colors.Blue;
vertice.PropertyChanged += new WeakINPCEventHandler(Item_PropertyChanged).Handler;
Vertices.Add(vertice);
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);
UpdatePathGeneratorResult();
}
protected override void ExecuteEditCommand(object param)
{
AddLabel();
}
public void AddLabel(string text = null, double? distance = null, PointBase? offset = null)
{
var label = new ConnectorLabelModel(this, text?.ToString(), distance, offset);
label.PropertyChanged += new WeakINPCEventHandler(Item_PropertyChanged).Handler;
label.IsSelected = true;
Labels.Add(label);
var paths = Labels.Count > 0 ? PathGeneratorResult?.Paths.Select(p => new SvgPath(p)).ToArray() : Array.Empty();
label.UpdatePosition(paths);
}
public void RemoveLabel(ConnectorLabelModel label)
{
Labels.Remove(label);
}
public void ClearLabel()
{
Labels?.Clear();
}
#endregion
}
}