using System; using System.Collections.Generic; using System.Text; namespace AIStudio.Wpf.DiagramDesigner { public class ShapeViewModel : BindableBase, IShapeViewModel { private ILinkMarker _sourceMarker = LinkMarker.None; public ILinkMarker SourceMarker { get { return _sourceMarker; } set { if (_sourceMarker != value) { if (_sourceMarker != null && _sourceMarker is LinkMarker _linkMarker1) { _linkMarker1.PropertyChanged -= ShapeViewModel_PropertyChanged; } SetProperty(ref _sourceMarker, value); if (_sourceMarker != null && _sourceMarker is LinkMarker _linkMarker2) { _linkMarker2.PropertyChanged += ShapeViewModel_PropertyChanged; } } else { RaisePropertyChanged(nameof(SourceMarker)); } } } private ILinkMarker _sinkMarker = LinkMarker.Arrow; public ILinkMarker SinkMarker { get { return _sinkMarker; } set { if (_sinkMarker != value) { if (_sinkMarker != null && _sinkMarker is LinkMarker _linkMarker1) { _linkMarker1.PropertyChanged -= ShapeViewModel_PropertyChanged; } SetProperty(ref _sinkMarker, value); if (_sinkMarker != null && _sinkMarker is LinkMarker _linkMarker2) { _linkMarker2.PropertyChanged += ShapeViewModel_PropertyChanged; } } else { RaisePropertyChanged(nameof(SinkMarker)); } } } private void ShapeViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (sender == SourceMarker) { RaisePropertyChanged(nameof(SourceMarker)); } else if (sender == SinkMarker) { RaisePropertyChanged(nameof(SinkMarker)); } } } public class LinkMarker : BindableBase, ILinkMarker { public static LinkMarker None { get; } = new LinkMarker("", 10, 10, ArrowPathStyle.None, ArrowSizeStyle.Middle); public static LinkMarker Arrow { get; } = new LinkMarker("M 0 -5 10 0 0 5 z", 10, 10, ArrowPathStyle.Arrow, ArrowSizeStyle.Middle); public static LinkMarker Circle { get; } = new LinkMarker("M 0, 0 a 5,5 0 1,0 10,0 a 5,5 0 1,0 -10,0", 10, 10, ArrowPathStyle.Circle, ArrowSizeStyle.Middle); public static LinkMarker Square { get; } = new LinkMarker("M 0 -5 10 -5 10 5 0 5 z", 10, 10, ArrowPathStyle.Square, ArrowSizeStyle.Middle); public static readonly Dictionary ArrowDictionary = new Dictionary() { { ArrowPathStyle.None, None.Path }, { ArrowPathStyle.Arrow, Arrow.Path }, { ArrowPathStyle.Circle, Circle.Path }, { ArrowPathStyle.Square, Square.Path }, }; public LinkMarker() { } public LinkMarker(string path, double width, double height, ArrowPathStyle arrowPathStyle, ArrowSizeStyle arrowSizeStyle) { Path = path; Width = width; Height = height; _pathStyle = arrowPathStyle; _sizeStyle = arrowSizeStyle; } private string _path; [CanDo] public string Path { get { return _path; } set { SetProperty(ref _path, value); } } private double _witdh; [CanDo] public double Width { get { return _witdh; } set { SetProperty(ref _witdh, value); } } private double _height; [CanDo] public double Height { get { return _height; } set { SetProperty(ref _height, value); } } private ArrowPathStyle _pathStyle = ArrowPathStyle.None; [CanDo] public ArrowPathStyle PathStyle { get { return _pathStyle; } set { if (SetProperty(ref _pathStyle, value)) { if (ArrowDictionary.ContainsKey(_pathStyle)) { Path = ArrowDictionary[_pathStyle]; } } } } private ArrowSizeStyle _sizeStyle = ArrowSizeStyle.Middle; [CanDo] public ArrowSizeStyle SizeStyle { get { return _sizeStyle; } set { if (SetProperty(ref _sizeStyle, value)) { Width = (double)_sizeStyle; Height = (double)_sizeStyle; } } } public static LinkMarker NewArrow(double width, double height) => new LinkMarker(FormattableString.Invariant($"M 0 -{height / 2} {width} 0 0 {height / 2}"), width, height, ArrowPathStyle.Arrow, (ArrowSizeStyle)width); public static LinkMarker NewCircle(double r) => new LinkMarker(FormattableString.Invariant($"M 0, 0 a {r},{r} 0 1,0 {r * 2},0 a {r},{r} 0 1,0 -{r * 2},0"), r * 2, r * 2, ArrowPathStyle.Circle, (ArrowSizeStyle)(r * 2)); public static LinkMarker NewRectangle(double width, double height) => new LinkMarker(FormattableString.Invariant($"M 0 -{height / 2} {width} -{height / 2} {width} {height / 2} 0 {height / 2} z"), width, height, ArrowPathStyle.Square, (ArrowSizeStyle)width); public static LinkMarker NewSquare(double size) => NewRectangle(size, size); } public interface ILinkMarker { string Path { get; set; } double Width { get; set; } double Height { get; set; } ArrowPathStyle PathStyle { get; set; } ArrowSizeStyle SizeStyle { get; set; } } }