Files
aistudio-wpf-diagram/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DesignerItemViewModelBase.cs

676 lines
19 KiB
C#
Raw Normal View History

2021-07-23 09:42:22 +08:00
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;
2023-01-12 23:02:53 +08:00
using AIStudio.Wpf.DiagramDesigner.Geometrys;
2021-07-23 09:42:22 +08:00
2022-10-28 22:45:39 +08:00
namespace AIStudio.Wpf.DiagramDesigner
2021-07-23 09:42:22 +08:00
{
2023-01-24 09:02:40 +08:00
public abstract class DesignerItemViewModelBase : SelectableDesignerItemViewModelBase
2021-07-23 09:42:22 +08:00
{
2023-01-27 14:54:03 +08:00
public DesignerItemViewModelBase() : this(null)
{
}
public DesignerItemViewModelBase(IDiagramViewModel root) : base(root)
2021-07-23 09:42:22 +08:00
{
2023-01-12 23:02:53 +08:00
ShapeDefiner = Shapes.Rectangle;
2021-07-23 09:42:22 +08:00
}
2023-01-24 17:53:04 +08:00
public DesignerItemViewModelBase(IDiagramViewModel root, SelectableItemBase designer) : base(root, designer)
2021-07-23 09:42:22 +08:00
{
2023-01-12 23:02:53 +08:00
ShapeDefiner = Shapes.Rectangle;
2021-07-23 09:42:22 +08:00
}
2023-01-25 11:11:27 +08:00
public DesignerItemViewModelBase(IDiagramViewModel root, SerializableItem serializableItem, string serializableType) : base(root, serializableItem, serializableType)
{
2023-01-12 23:02:53 +08:00
ShapeDefiner = Shapes.Rectangle;
}
2023-01-25 11:11:27 +08:00
public override SelectableItemBase GetSerializableObject()
{
return new DesignerItemBase(this);
}
2023-01-27 14:54:03 +08:00
protected override void Init(IDiagramViewModel root)
2021-07-23 09:42:22 +08:00
{
2023-01-27 14:54:03 +08:00
base.Init(root);
2021-07-23 09:42:22 +08:00
InitConnector();
2021-07-23 09:42:22 +08:00
}
2023-01-27 14:54:03 +08:00
protected override void LoadDesignerItemViewModel(SelectableItemBase designerbase)
2021-07-23 09:42:22 +08:00
{
2023-01-27 14:54:03 +08:00
base.LoadDesignerItemViewModel(designerbase);
2021-07-23 09:42:22 +08:00
2023-01-24 17:53:04 +08:00
if (designerbase is DesignerItemBase designer)
{
2023-02-11 22:20:24 +08:00
this.PhysicalLeft = designer.PhysicalLeft;
this.PhysicalTop = designer.PhysicalTop;
2023-01-24 17:53:04 +08:00
this.Angle = designer.Angle;
this.ScaleX = designer.ScaleX;
this.ScaleY = designer.ScaleY;
2023-02-11 22:20:24 +08:00
this.PhysicalItemWidth = designer.PhysicalItemWidth;
this.PhysicalItemHeight = designer.PhysicalItemHeight;
2023-01-24 17:53:04 +08:00
this.Icon = designer.Icon;
}
}
2021-07-23 09:42:22 +08:00
protected virtual void InitConnector()
{
2023-01-27 20:10:17 +08:00
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));
2021-07-23 09:42:22 +08:00
}
2023-01-23 15:43:44 +08:00
#region
2023-02-21 23:23:03 +08:00
public FullyCreatedConnectorInfo FirstConnector
{
get
{
return connectors?.FirstOrDefault();
}
}
2021-07-23 09:42:22 +08:00
public FullyCreatedConnectorInfo TopConnector
{
2023-01-25 23:55:30 +08:00
get
{
return connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.Top);
}
2021-07-23 09:42:22 +08:00
}
public FullyCreatedConnectorInfo BottomConnector
{
2023-01-25 23:55:30 +08:00
get
{
return connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.Bottom);
}
2021-07-23 09:42:22 +08:00
}
public FullyCreatedConnectorInfo LeftConnector
{
2023-01-25 23:55:30 +08:00
get
{
return connectors?.FirstOrDefault(p => p.Orientation == ConnectorOrientation.Left);
}
2021-07-23 09:42:22 +08:00
}
public FullyCreatedConnectorInfo RightConnector
{
2023-01-25 23:55:30 +08:00
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);
}
2021-07-23 09:42:22 +08:00
}
2023-01-27 20:10:17 +08:00
private FullyCreatedConnectorInfo _portlessConnector;
public FullyCreatedConnectorInfo PortlessConnector
{
get
{
if (_portlessConnector == null)
_portlessConnector = new FullyCreatedConnectorInfo(this.Root, this, ConnectorOrientation.None) { IsPortless = true };
return _portlessConnector;
}
}
2023-01-23 15:43:44 +08:00
public Style ConnectorStyle
{
get; set;
}
2023-01-08 09:22:37 +08:00
public ShapeDefiner ShapeDefiner
{
get;
}
2021-07-23 09:42:22 +08:00
2023-02-11 10:03:06 +08:00
public virtual PointBase MiddlePosition
{
get
{
return GetBounds().Center;
}
}
2021-07-23 09:42:22 +08:00
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;
2023-02-11 22:20:24 +08:00
if (SetProperty(ref _itemWidth, value))
2023-02-10 18:49:02 +08:00
{
2023-02-11 22:20:24 +08:00
RaisePropertyChanged(nameof(PhysicalItemWidth));
2023-02-10 18:49:02 +08:00
}
2021-07-23 09:42:22 +08:00
}
}
2023-02-12 09:26:27 +08:00
private double _itemHeight = 65;
2021-07-23 09:42:22 +08:00
[CanDo]
public double ItemHeight
{
get
{
return _itemHeight;
}
set
{
if (value <= 0) return;
2023-02-11 22:20:24 +08:00
if (SetProperty(ref _itemHeight, value))
{
RaisePropertyChanged(nameof(PhysicalItemHeight));
}
}
}
2023-02-12 09:26:27 +08:00
[DisplayName("ItemWidth(mm)")]
2023-02-11 22:20:24 +08:00
[Browsable(true)]
public double PhysicalItemWidth
{
get
{
2023-02-11 23:51:48 +08:00
return ScreenHelper.WidthToMm(ItemWidth);
2023-02-11 22:20:24 +08:00
}
set
{
2023-02-11 23:51:48 +08:00
ItemWidth = ScreenHelper.MmToWidth(value);
2023-02-11 22:20:24 +08:00
}
}
2023-02-12 09:26:27 +08:00
[DisplayName("ItemHeight(mm)")]
2023-02-11 22:20:24 +08:00
[Browsable(true)]
public double PhysicalItemHeight
{
get
{
2023-02-11 23:51:48 +08:00
return ScreenHelper.WidthToMm(ItemHeight);
2023-02-11 22:20:24 +08:00
}
set
{
2023-02-11 23:51:48 +08:00
ItemHeight = ScreenHelper.MmToWidth(value);
2021-07-23 09:42:22 +08:00
}
}
[CanDo]
2023-01-08 09:22:37 +08:00
public SizeBase Size
2021-07-23 09:42:22 +08:00
{
get
{
2023-01-08 09:22:37 +08:00
return new SizeBase(ItemWidth, ItemHeight);
2021-07-23 09:42:22 +08:00
}
set
{
2023-01-08 09:22:37 +08:00
ItemWidth = value.Width;
ItemHeight = value.Height;
2021-07-23 09:42:22 +08:00
}
}
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);
}
}
2023-01-22 21:46:59 +08:00
private bool _showRotate = false;
public bool ShowRotate
{
get
{
return _showRotate;
}
set
{
SetProperty(ref _showRotate, value);
}
}
public bool ShowArrow { get; set; } = true;
2021-07-23 09:42:22 +08:00
2023-02-19 21:38:28 +08:00
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);
}
}
2021-07-23 09:42:22 +08:00
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);
}
2023-01-08 09:22:37 +08:00
}
2021-07-23 09:42:22 +08:00
2023-02-12 09:26:27 +08:00
[DisplayName("Left(mm)")]
2023-02-11 22:20:24 +08:00
[Browsable(true)]
public double PhysicalLeft
{
get
{
2023-02-11 23:51:48 +08:00
return ScreenHelper.WidthToMm(Left);
2023-02-11 22:20:24 +08:00
}
set
{
2023-02-11 23:51:48 +08:00
Left = ScreenHelper.MmToWidth(value);
2023-02-11 22:20:24 +08:00
}
}
2023-02-12 09:26:27 +08:00
[DisplayName("Top(mm)")]
2023-02-11 22:20:24 +08:00
[Browsable(true)]
public double PhysicalTop
{
get
{
2023-02-11 23:51:48 +08:00
return ScreenHelper.WidthToMm(Top);
2023-02-11 22:20:24 +08:00
}
set
{
2023-02-11 23:51:48 +08:00
Top = ScreenHelper.MmToWidth(value);
2023-02-11 22:20:24 +08:00
}
}
2023-01-08 09:22:37 +08:00
public PointBase Position
{
get
{
return new PointBase(Left, Top);
}
}
2023-01-25 23:55:30 +08:00
[CanDo]
2023-01-08 09:22:37 +08:00
public PointBase TopLeft
2021-07-23 09:42:22 +08:00
{
get
{
2023-01-08 09:22:37 +08:00
return new PointBase(Left, Top);
2021-07-23 09:42:22 +08:00
}
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);
}
}
/// <summary>
/// 连接点是否可以按偏移自定义
/// </summary>
2023-01-25 23:55:30 +08:00
public bool IsInnerConnector
{
get; set;
}
2023-01-25 23:55:30 +08:00
protected ObservableCollection<FullyCreatedConnectorInfo> connectors = new ObservableCollection<FullyCreatedConnectorInfo>();
public IEnumerable<FullyCreatedConnectorInfo> Connectors
{
get
{
return connectors;
}
}
2021-07-23 09:42:22 +08:00
protected ObservableCollection<CinchMenuItem> menuOptions;
2023-01-25 23:55:30 +08:00
public IEnumerable<CinchMenuItem> MenuOptions
{
get
{
return menuOptions;
}
}
2021-07-23 09:42:22 +08:00
public bool ShowMenuOptions
{
get
{
if (MenuOptions == null || MenuOptions.Count() == 0)
return false;
else
return true;
}
}
2023-01-25 23:55:30 +08:00
public bool BeginDo
{
get; set;
}
2021-07-23 09:42:22 +08:00
public IObservable<NotifyCollectionChangedEventArgs> WhenConnectorsChanged
{
get
{
return Observable
.FromEventPattern<NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(
h => this.connectors.CollectionChanged += h,
h => this.connectors.CollectionChanged -= h)
.Select(x => x.EventArgs);
}
}
2023-01-23 15:43:44 +08:00
#endregion
#region
2021-07-23 09:42:22 +08:00
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))
{
2023-01-24 16:20:39 +08:00
if (Root.CellHorizontalAlignment == CellHorizontalAlignment.Center)
2021-07-23 09:42:22 +08:00
{
2023-01-24 16:20:39 +08:00
if (Root.GridCellSize.Width > this.ItemWidth)
{
2023-01-24 20:51:39 +08:00
this.Left = (int)(this.Left / Root.GridCellSize.Width) * Root.GridCellSize.Width + Root.GridMarginSize.Width + (Root.GridCellSize.Width - this.ItemWidth) / 2;
}
2021-07-23 09:42:22 +08:00
}
2023-01-24 16:20:39 +08:00
else if (Root.CellHorizontalAlignment == CellHorizontalAlignment.Left)
2021-07-23 09:42:22 +08:00
{
2023-01-24 20:51:39 +08:00
this.Left = (int)(this.Left / Root.GridCellSize.Width) * Root.GridCellSize.Width + Root.GridMarginSize.Width;
2021-07-23 09:42:22 +08:00
}
2023-01-24 16:20:39 +08:00
else if (Root.CellHorizontalAlignment == CellHorizontalAlignment.Right)
2021-07-23 09:42:22 +08:00
{
2023-01-24 16:20:39 +08:00
if (Root.GridCellSize.Width > this.ItemWidth)
{
2023-01-24 20:51:39 +08:00
this.Left = (int)(this.Left / Root.GridCellSize.Width) * Root.GridCellSize.Width + Root.GridMarginSize.Width + (Root.GridCellSize.Width - this.ItemWidth);
}
2021-07-23 09:42:22 +08:00
}
2023-01-24 16:20:39 +08:00
if (Root.CellVerticalAlignment == CellVerticalAlignment.Center)
{
2023-01-24 16:20:39 +08:00
if (Root.GridCellSize.Height > this.ItemHeight)
{
2023-01-24 20:51:39 +08:00
this.Top = (int)(this.Top / Root.GridCellSize.Height) * Root.GridCellSize.Height + Root.GridMarginSize.Height + (Root.GridCellSize.Height - this.ItemHeight) / 2;
}
2021-07-23 09:42:22 +08:00
}
2023-01-24 16:20:39 +08:00
else if (Root.CellVerticalAlignment == CellVerticalAlignment.Top)
{
2023-01-24 20:51:39 +08:00
this.Top = (int)(this.Top / Root.GridCellSize.Height) * Root.GridCellSize.Height + Root.GridMarginSize.Height;
2021-07-23 09:42:22 +08:00
}
2023-01-24 16:20:39 +08:00
else if (Root.CellVerticalAlignment == CellVerticalAlignment.Bottom)
{
2023-01-24 16:20:39 +08:00
if (Root.GridCellSize.Height > this.ItemHeight)
{
2023-01-24 20:51:39 +08:00
this.Top = (int)(this.Top / Root.GridCellSize.Height) * Root.GridCellSize.Height + Root.GridMarginSize.Height + (Root.GridCellSize.Height - this.ItemHeight);
}
2021-07-23 09:42:22 +08:00
}
2023-01-25 23:55:30 +08:00
}
2021-07-23 09:42:22 +08:00
}
public void RaiseTopLeft()
{
2023-01-08 09:22:37 +08:00
this.RaisePropertyChanged(nameof(TopLeft), new PointBase(GetOldValue<double>(nameof(Left)), GetOldValue<double>(nameof(Top))), TopLeft);
2021-07-23 09:42:22 +08:00
}
public void RaiseItemWidthHeight()
{
2023-01-08 09:22:37 +08:00
this.RaisePropertyChanged(nameof(Size), new SizeBase(GetOldValue<double>(nameof(ItemWidth)), GetOldValue<double>(nameof(ItemHeight))), Size);
2021-07-23 09:42:22 +08:00
}
public void RaiseAngle()
{
this.RaisePropertyChanged(nameof(Angle), GetOldValue<double>(nameof(Angle)), Angle);
}
2023-01-08 09:22:37 +08:00
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));
}
}
}
2023-01-08 09:22:37 +08:00
public RectangleBase GetBounds(bool includePorts = false)
{
if (!includePorts)
2023-01-12 23:02:53 +08:00
return new RectangleBase(Position, Size);
2023-01-08 09:22:37 +08:00
var leftPort = LeftConnector;
var topPort = TopConnector;
var rightPort = RightConnector;
var bottomPort = BottomConnector;
2023-01-25 23:55:30 +08:00
var left = leftPort == null ? Position.X : Math.Min(Position.X, leftPort.Position.X);
2023-01-15 20:27:39 +08:00
var top = topPort == null ? Position.Y : Math.Min(Position.Y, topPort.Position.Y);
2023-01-12 23:02:53 +08:00
var right = rightPort == null ? Position.X + ItemWidth :
2023-01-15 20:27:39 +08:00
Math.Max(rightPort.Position.X + rightPort.ConnectorWidth, Position.X + ItemWidth);
2023-01-12 23:02:53 +08:00
var bottom = bottomPort == null ? Position.Y + ItemHeight :
2023-01-15 20:27:39 +08:00
Math.Max(bottomPort.Position.Y + bottomPort.ConnectorHeight, Position.Y + ItemHeight);
2023-01-08 09:22:37 +08:00
2023-01-12 23:02:53 +08:00
return new RectangleBase(left, top, right, bottom, true);
2023-01-08 09:22:37 +08:00
}
2023-01-12 23:02:53 +08:00
public IShape GetShape() => ShapeDefiner(this);
2023-01-23 15:43:44 +08:00
#endregion
2021-07-23 09:42:22 +08:00
}
}