using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Windows; using System.Linq; using System.Reactive.Linq; using AIStudio.Wpf.DiagramDesigner.Models; using AIStudio.Wpf.DiagramDesigner.Geometrys; namespace AIStudio.Wpf.DiagramDesigner { public abstract class DesignerItemViewModelBase : SelectableDesignerItemViewModelBase { public DesignerItemViewModelBase() : this(null) { } public DesignerItemViewModelBase(IDiagramViewModel root) : base(root) { ShapeDefiner = Shapes.Rectangle; } public DesignerItemViewModelBase(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer) { ShapeDefiner = Shapes.Rectangle; } public DesignerItemViewModelBase(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType) { ShapeDefiner = Shapes.Rectangle; } public override SelectableItemBase GetSerializableObject() { return new DesignerItemBase(this); } protected override void Init(IDiagramViewModel root) { base.Init(root); InitConnector(); } protected override void LoadDesignerItemViewModel(SelectableItemBase designerbase) { base.LoadDesignerItemViewModel(designerbase); if (designerbase is DesignerItemBase designer) { this.PhysicalLeft = designer.PhysicalLeft; this.PhysicalTop = designer.PhysicalTop; this.Angle = designer.Angle; this.ScaleX = designer.ScaleX; this.ScaleY = designer.ScaleY; this.PhysicalItemWidth = designer.PhysicalItemWidth; this.PhysicalItemHeight = designer.PhysicalItemHeight; this.Icon = designer.Icon; } } protected virtual void InitConnector() { connectors.Add(new FullyCreatedConnectorInfo(this.Root, this, ConnectorOrientation.Top)); connectors.Add(new FullyCreatedConnectorInfo(this.Root, this, ConnectorOrientation.Bottom)); connectors.Add(new FullyCreatedConnectorInfo(this.Root, this, ConnectorOrientation.Left)); connectors.Add(new FullyCreatedConnectorInfo(this.Root, this, ConnectorOrientation.Right)); } #region 属性 public FullyCreatedConnectorInfo TopConnector { get { return connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.Top); } } public FullyCreatedConnectorInfo BottomConnector { get { return connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.Bottom); } } public FullyCreatedConnectorInfo LeftConnector { get { return connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.Left); } } public FullyCreatedConnectorInfo RightConnector { get { return connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.Right); } } public FullyCreatedConnectorInfo TopLeftConnector { get { return connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.TopLeft); } } public FullyCreatedConnectorInfo TopRightConnector { get { return connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.TopRight); } } public FullyCreatedConnectorInfo BottomLeftConnector { get { return connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.BottomLeft); } } public FullyCreatedConnectorInfo BottomRightConnector { get { return connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.BottomRight); } } private FullyCreatedConnectorInfo _portlessConnector; public FullyCreatedConnectorInfo PortlessConnector { get { if (_portlessConnector == null) _portlessConnector = new FullyCreatedConnectorInfo(this.Root, this, ConnectorOrientation.None) { IsPortless = true }; return _portlessConnector; } } public Style ConnectorStyle { get; set; } public ShapeDefiner ShapeDefiner { get; } public virtual PointBase MiddlePosition { get { return GetBounds().Center; } } private string _icon; [CanDo] public string Icon { get { return _icon; } set { SetProperty(ref _icon, value); } } private double _itemWidth = 65; [CanDo] public double ItemWidth { get { return _itemWidth; } set { if (value <= 0) return; if (SetProperty(ref _itemWidth, value)) { RaisePropertyChanged(nameof(PhysicalItemWidth)); } } } private double _itemHeight = 65; [CanDo] public double ItemHeight { get { return _itemHeight; } set { if (value <= 0) return; if (SetProperty(ref _itemHeight, value)) { RaisePropertyChanged(nameof(PhysicalItemHeight)); } } } [DisplayName("ItemWidth(mm)")] [Browsable(true)] public double PhysicalItemWidth { get { return ScreenHelper.WidthToMm(ItemWidth); } set { ItemWidth = ScreenHelper.MmToWidth(value); } } [DisplayName("ItemHeight(mm)")] [Browsable(true)] public double PhysicalItemHeight { get { return ScreenHelper.WidthToMm(ItemHeight); } set { ItemHeight = ScreenHelper.MmToWidth(value); } } [CanDo] public SizeBase Size { get { return new SizeBase(ItemWidth, ItemHeight); } set { ItemWidth = value.Width; ItemHeight = value.Height; } } private bool _showConnectors = false; public bool ShowConnectors { get { return _showConnectors; } set { if (SetProperty(ref _showConnectors, value)) { foreach (var connector in connectors) { connector.ShowConnectors = value; } } } } private bool _showResize = true; public bool ShowResize { get { return _showResize; } set { SetProperty(ref _showResize, value); } } private bool _showRotate = false; public bool ShowRotate { get { return _showRotate; } set { SetProperty(ref _showRotate, value); } } public bool ShowArrow { get; set; } = true; private bool enabledForConnection = true; public bool EnabledForConnection { get { return enabledForConnection; } set { SetProperty(ref enabledForConnection, value); } } private bool enabledForSelection = true; public bool EnabledForSelection { get { return enabledForSelection; } set { SetProperty(ref enabledForSelection, value); } } private double _left; [CanDo] public double Left { get { return _left; } set { SetProperty(ref _left, value); } } private double _top; [CanDo] public double Top { get { return _top; } set { SetProperty(ref _top, value); } } [DisplayName("Left(mm)")] [Browsable(true)] public double PhysicalLeft { get { return ScreenHelper.WidthToMm(Left); } set { Left = ScreenHelper.MmToWidth(value); } } [DisplayName("Top(mm)")] [Browsable(true)] public double PhysicalTop { get { return ScreenHelper.WidthToMm(Top); } set { Top = ScreenHelper.MmToWidth(value); } } public PointBase Position { get { return new PointBase(Left, Top); } } [CanDo] public PointBase TopLeft { get { return new PointBase(Left, Top); } set { Left = value.X; Top = value.Y; } } private double _angle; [CanDo] public double Angle { get { return _angle; } set { SetProperty(ref _angle, value); } } private double _scaleX = 1; [CanDo] public double ScaleX { get { return _scaleX; } set { SetProperty(ref _scaleX, value); } } private double _scaleY = 1; [CanDo] public double ScaleY { get { return _scaleY; } set { SetProperty(ref _scaleY, value); } } private double _margin; public double Margin { get { return _margin; } set { SetProperty(ref _margin, value); } } /// /// 连接点是否可以按偏移自定义 /// public bool IsInnerConnector { get; set; } protected ObservableCollection connectors = new ObservableCollection(); public IEnumerable Connectors { get { return connectors; } } protected ObservableCollection menuOptions; public IEnumerable MenuOptions { get { return menuOptions; } } public bool ShowMenuOptions { get { if (MenuOptions == null || MenuOptions.Count() == 0) return false; else return true; } } public bool BeginDo { get; set; } public IObservable WhenConnectorsChanged { get { return Observable .FromEventPattern( h => this.connectors.CollectionChanged += h, h => this.connectors.CollectionChanged -= h) .Select(x => x.EventArgs); } } #endregion #region 方法 public void AddConnector(FullyCreatedConnectorInfo connector) { if (!connectors.Contains(connector)) { connectors.Add(connector); } } public void RemoveConnector(FullyCreatedConnectorInfo connector) { if (connectors.Contains(connector)) { connectors.Remove(connector); } } public void ClearConnectors() { connectors.Clear(); } public void SetCellAlignment() { if (!(this is TextDesignerItemViewModel)) { if (Root.CellHorizontalAlignment == CellHorizontalAlignment.Center) { if (Root.GridCellSize.Width > this.ItemWidth) { this.Left = (int)(this.Left / Root.GridCellSize.Width) * Root.GridCellSize.Width + Root.GridMarginSize.Width + (Root.GridCellSize.Width - this.ItemWidth) / 2; } } else if (Root.CellHorizontalAlignment == CellHorizontalAlignment.Left) { this.Left = (int)(this.Left / Root.GridCellSize.Width) * Root.GridCellSize.Width + Root.GridMarginSize.Width; } else if (Root.CellHorizontalAlignment == CellHorizontalAlignment.Right) { if (Root.GridCellSize.Width > this.ItemWidth) { this.Left = (int)(this.Left / Root.GridCellSize.Width) * Root.GridCellSize.Width + Root.GridMarginSize.Width + (Root.GridCellSize.Width - this.ItemWidth); } } if (Root.CellVerticalAlignment == CellVerticalAlignment.Center) { if (Root.GridCellSize.Height > this.ItemHeight) { this.Top = (int)(this.Top / Root.GridCellSize.Height) * Root.GridCellSize.Height + Root.GridMarginSize.Height + (Root.GridCellSize.Height - this.ItemHeight) / 2; } } else if (Root.CellVerticalAlignment == CellVerticalAlignment.Top) { this.Top = (int)(this.Top / Root.GridCellSize.Height) * Root.GridCellSize.Height + Root.GridMarginSize.Height; } else if (Root.CellVerticalAlignment == CellVerticalAlignment.Bottom) { if (Root.GridCellSize.Height > this.ItemHeight) { this.Top = (int)(this.Top / Root.GridCellSize.Height) * Root.GridCellSize.Height + Root.GridMarginSize.Height + (Root.GridCellSize.Height - this.ItemHeight); } } } } public void RaiseTopLeft() { this.RaisePropertyChanged(nameof(TopLeft), new PointBase(GetOldValue(nameof(Left)), GetOldValue(nameof(Top))), TopLeft); } public void RaiseItemWidthHeight() { this.RaisePropertyChanged(nameof(Size), new SizeBase(GetOldValue(nameof(ItemWidth)), GetOldValue(nameof(ItemHeight))), Size); } public void RaiseAngle() { this.RaisePropertyChanged(nameof(Angle), GetOldValue(nameof(Angle)), Angle); } public FullyCreatedConnectorInfo GetFullConnectorInfo(Guid connectorId, ConnectorOrientation connectorOrientation, double xRatio, double yRatio, bool isInnerPoint, bool isPortless) { if (isInnerPoint) { return this.Connectors.Where(p => p.XRatio == xRatio && p.YRatio == yRatio).FirstOrDefault(); } else if (isPortless) { return this.PortlessConnector; } else { switch (connectorOrientation) { case ConnectorOrientation.Left: return this.LeftConnector; case ConnectorOrientation.TopLeft: return this.TopLeftConnector; case ConnectorOrientation.Top: return this.TopConnector; case ConnectorOrientation.TopRight: return this.TopRightConnector; case ConnectorOrientation.Right: return this.RightConnector; case ConnectorOrientation.BottomRight: return this.BottomRightConnector; case ConnectorOrientation.Bottom: return this.BottomConnector; case ConnectorOrientation.BottomLeft: return this.BottomLeftConnector; default: throw new InvalidOperationException( string.Format("Found invalid persisted Connector Orientation for Connector Id: {0}", connectorId)); } } } public RectangleBase GetBounds(bool includePorts = false) { if (!includePorts) return new RectangleBase(Position, Size); var leftPort = LeftConnector; var topPort = TopConnector; var rightPort = RightConnector; var bottomPort = BottomConnector; var left = leftPort == null ? Position.X : Math.Min(Position.X, leftPort.Position.X); var top = topPort == null ? Position.Y : Math.Min(Position.Y, topPort.Position.Y); var right = rightPort == null ? Position.X + ItemWidth : Math.Max(rightPort.Position.X + rightPort.ConnectorWidth, Position.X + ItemWidth); var bottom = bottomPort == null ? Position.Y + ItemHeight : Math.Max(bottomPort.Position.Y + bottomPort.ConnectorHeight, Position.Y + ItemHeight); return new RectangleBase(left, top, right, bottom, true); } public IShape GetShape() => ShapeDefiner(this); #endregion } }