using System; using System.Linq; using AIStudio.Wpf.DiagramDesigner.Geometrys; using AIStudio.Wpf.DiagramDesigner.Models; using SvgPathProperties; namespace AIStudio.Wpf.DiagramDesigner { public class ConnectorLabelModel : ConnectorPointModel, ISelectable { public ConnectorLabelModel(ConnectionViewModel connector, string content, double? distance = null, PointBase? offset = null) { Parent = connector; Text = content; Distance = distance; Offset = offset ?? new PointBase(); } public ConnectorLabelModel(IDiagramViewModel root, ConnectionViewModel connector, SelectableItemBase designer) : base(root, designer) { Parent = connector; } public ConnectorLabelModel(IDiagramViewModel root, ConnectionViewModel connector, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType) { Parent = connector; } public override SelectableItemBase GetSerializableObject() { return new ConnectorLabelItem(this); } protected override void Init() { base.Init(); DeleteLabelCommand = new SimpleCommand(Command_Enable, DeleteLabel); } protected override void LoadDesignerItemViewModel(IDiagramViewModel root, SelectableItemBase designerbase) { base.LoadDesignerItemViewModel(root, designerbase); if (designerbase is ConnectorLabelItem designer) { Distance = designer.Distance; Offset = designer.Offset; } } #region 属性 public ConnectionViewModel Connector { get { return Parent as ConnectionViewModel; } } /// /// 3 types of values are possible: /// - A number between 0 and 1: Position relative to the link's length /// - A positive number, greater than 1: Position away from the start /// - A negative number, less than 0: Position away from the end /// public double? Distance { get; set; } public PointBase Offset { get; set; } //private bool _isSelected; public override bool IsSelected { get { return _isSelected; } set { if (SetProperty(ref _isSelected, value)) { //如果没有文字,失去焦点自动清除 if (_isSelected == false && string.IsNullOrEmpty(Text)) { Connector.Labels.Remove(this); } } } } public SimpleCommand DeleteLabelCommand { get; set; } #endregion private bool updating = false; public void UpdatePosition(SvgPath[] paths) { if (paths == null) return; var position = FindPosition(paths); if (position == null) return; updating = true; X = position.Value.X; Y = position.Value.Y; updating = false; } public PointBase? FindPosition(SvgPath[] paths) { var totalLength = paths.Sum(p => p.Length); double length; if (Distance >= 0 && Distance <= 1) { length = Distance.Value * totalLength; } else if (Distance > 1) { length = Distance.Value; } else if (Distance < 0) { length = totalLength + Distance.Value; } else { length = totalLength * (Connector.Labels.IndexOf(this) + 1) / (Connector.Labels.Count + 1); } foreach (var path in paths) { var pathLength = path.Length; if (length < pathLength) { var pt = path.GetPointAtLength(length); return new PointBase(pt.X + Offset.X, pt.Y + Offset.Y); } length -= pathLength; } return null; } public void UpdateOffsetX(double oldvalue, double newvalue) { if (updating == true) return; Offset += new VectorBase(newvalue - oldvalue, 0); } public void UpdateOffsetY(double oldvalue, double newvalue) { if (updating == true) return; Offset += new VectorBase(0, newvalue - oldvalue); } public override void AddToSelection(bool selected) { foreach (var item in Connector.Labels.ToList()) item.IsSelected = false; if (selected == true) { IsSelected = true; } } private void DeleteLabel(object parameter) { if (parameter is ConnectorLabelModel label) { Connector.Labels.Remove(label); } } } }