using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Windows; using System.Windows.Media; 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) { Parent = parent; VectorLineDrawMode = vectorLineDrawMode; Init(sourceConnectorInfo, sinkConnectorInfo); } public ConnectorViewModel( FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo, DrawMode vectorLineDrawMode):this(null, sourceConnectorInfo, sinkConnectorInfo, vectorLineDrawMode) { } public override SelectableDesignerItemBase ToXmlObject() { if (SinkConnectorInfo is FullyCreatedConnectorInfo sinkConnector) { ConnectionItem connection = new ConnectionItem( SourceConnectorInfo.DataItem.Id, SourceConnectorInfo.Orientation, SourceConnectorInfo.DataItem.GetType(), GetXRatioFromConnector(SourceConnectorInfo), GetYRatioFromConnector(SourceConnectorInfo), SourceConnectorInfo.IsInnerPoint, sinkConnector.DataItem.Id, sinkConnector.Orientation, sinkConnector.DataItem.GetType(), GetXRatioFromConnector(sinkConnector), GetYRatioFromConnector(sinkConnector), sinkConnector.IsInnerPoint, this); return connection; } else { return null; } } public override Type ToXmlType() { return typeof(ConnectionItem); } public IPathFinder PathFinder { get; set; } public bool IsFullConnection { get { return _sinkConnectorInfo is FullyCreatedConnectorInfo; } } private Point _sourceA; public Point SourceA { get { return _sourceA; } set { if (SetProperty(ref _sourceA, value)) { UpdateArea(); } } } private Point _sourceB; public Point SourceB { get { return _sourceB; } set { if (SetProperty(ref _sourceB, value)) { UpdateArea(); } } } private List _connectionPoints; public List ConnectionPoints { get { return _connectionPoints; } private set { if (_connectionPoints != null) { _connectionPoints.ForEach(p => p.PropertyChanged -= new WeakINPCEventHandler(ConnectionPoint_PropertyChanged).Handler); } SetProperty(ref _connectionPoints, value); if (_connectionPoints != null) { _connectionPoints.ForEach(p => p.PropertyChanged += new WeakINPCEventHandler(ConnectionPoint_PropertyChanged).Handler); } } } private Point _startPoint; public Point StartPoint { get { return _startPoint; } private set { SetProperty(ref _startPoint, value); } } private Point _endPoint; public Point EndPoint { get { return _endPoint; } private set { SetProperty(ref _endPoint, value); } } private Rect _area; public Rect Area { get { return _area; } private set { Rect oldarea = _area; if (SetProperty(ref _area, value)) { UpdateConnectionPoints(); OutTextItemLocation(oldarea, value); } } } public DrawMode VectorLineDrawMode { get; set; } public virtual Dictionary PropertiesSetting { get { return new Dictionary() { { "Text","文本" }, }; } } public ConnectorInfo ConnectorInfo(ConnectorOrientation orientation, double left, double top, double width, double height, Point position) { return new ConnectorInfo() { Orientation = orientation, DesignerItemSize = new Size(width, height), DesignerItemLeft = left, DesignerItemTop = top, Position = position }; } private FullyCreatedConnectorInfo _sourceConnectorInfo; public FullyCreatedConnectorInfo SourceConnectorInfo { get { return _sourceConnectorInfo; } set { if (SetProperty(ref _sourceConnectorInfo, value)) { SourceA = PointHelper.GetPointForConnector(_sourceConnectorInfo); (_sourceConnectorInfo.DataItem as INotifyPropertyChanged).PropertyChanged += new WeakINPCEventHandler(ConnectorViewModel_PropertyChanged).Handler; } } } private ConnectorInfoBase _sinkConnectorInfo; public ConnectorInfoBase SinkConnectorInfo { get { return _sinkConnectorInfo; } set { if (SetProperty(ref _sinkConnectorInfo, value)) { if (_sinkConnectorInfo is FullyCreatedConnectorInfo) { SourceB = PointHelper.GetPointForConnector((FullyCreatedConnectorInfo)_sinkConnectorInfo); (((FullyCreatedConnectorInfo)_sinkConnectorInfo).DataItem as INotifyPropertyChanged).PropertyChanged += new WeakINPCEventHandler(ConnectorViewModel_PropertyChanged).Handler; } else { SourceB = ((PartCreatedConnectionInfo)SinkConnectorInfo).CurrentLocation; } } } } 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 Rect(SourceA, SourceB); } private void UpdateConnectionPoints() { ConnectionPoints = PathFinder.UpdateConnectionPoints(Parent, SourceA, SourceB, SourceConnectorInfo, SinkConnectorInfo); StartPoint = ConnectionPoints.First(); EndPoint = ConnectionPoints.Last(); } private void ConnectorViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e) { switch (e.PropertyName) { case "ItemHeight": case "ItemWidth": case "Left": case "Top": SourceA = PointHelper.GetPointForConnector(this.SourceConnectorInfo); if (this.SinkConnectorInfo is FullyCreatedConnectorInfo) { SourceB = PointHelper.GetPointForConnector((FullyCreatedConnectorInfo)this.SinkConnectorInfo); } break; } } private void ConnectionPoint_PropertyChanged(object sender, PropertyChangedEventArgs e) { switch (e.PropertyName) { case "Left": case "Top": RaisePropertyChanged(nameof(ConnectionPoints)); 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 { get; set; } private void DeleteConnection(object args) { if (this.Parent is IDiagramViewModel) { var diagramVM = this.Parent as IDiagramViewModel; diagramVM.RemoveItemCommand.Execute(this); } } protected override void ExecuteEditCommand(object param) { if (this.OutTextItem != null) return; AddText(""); } public void AddText(string text) { if (this.Parent is IDiagramViewModel) { var diagramVM = this.Parent as IDiagramViewModel; TextDesignerItemViewModel textitem = new TextDesignerItemViewModel(); textitem.ItemWidth = Double.NaN; textitem.ItemHeight = double.NaN; if (diagramVM.DiagramType == DiagramType.FlowChart) { var mid = (int)(ConnectionPoints.Count / 2); var p = BoundaryPathFinder.SegmentMiddlePoint(ConnectionPoints[mid - 1], ConnectionPoints[mid]); textitem.Left = this.Area.Left + p.X + 2; textitem.Top = this.Area.Top + p.Y - 15; } else { textitem.Left = this.Area.Left + this.Area.Width / 2 - 16; textitem.Top = this.Area.Top + this.Area.Height / 2 - 5; } textitem.Watermark = null; textitem.ZIndex = diagramVM.Items.Count; textitem.ParentId = this.Id; textitem.ParentItem = this; textitem.ColorViewModel.FillColor = new ColorObject() { Color = Colors.White }; textitem.Text = text; diagramVM.DirectAddItemCommand.Execute(textitem); this.OutTextItem = textitem; } } public void OutTextItemLocation(Rect oldArea, Rect newArea) { if (this.OutTextItem is TextDesignerItemViewModel text) { var oldpoint = new Point(oldArea.Left + oldArea.Width / 2, oldArea.Top + oldArea.Height / 2); var newpoint = new Point(newArea.Left + newArea.Width / 2, newArea.Top + newArea.Height / 2); text.Left = text.Left + newpoint.X - oldpoint.X; text.Top = text.Top + newpoint.Y - oldpoint.Y; } } } }