Files
aistudio-wpf-diagram/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/DesignerItemViewModelBase.cs
艾竹 f48838f54a Mind
2023-03-07 22:59:27 +08:00

722 lines
20 KiB
C#

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;
this.CornerRadius = designer.CornerRadius;
this.BorderThickness = designer.BorderThickness;
}
}
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 FirstConnector
{
get
{
return connectors?.FirstOrDefault();
}
}
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;
public bool ShowResized
{
get; set;
}
private bool alwayForResized;
public bool AlwayForResized
{
get
{
return alwayForResized;
}
set
{
SetProperty(ref alwayForResized, value);
}
}
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);
}
}
private CornerRadius _cornerRadius = new CornerRadius(3);
public CornerRadius CornerRadius
{
get
{
return _cornerRadius;
}
set
{
SetProperty(ref _cornerRadius, value);
}
}
private Thickness _borderThickness = new Thickness(1);
public Thickness BorderThickness
{
get
{
return _borderThickness;
}
set
{
SetProperty(ref _borderThickness, value);
}
}
/// <summary>
/// 连接点是否可以按偏移自定义
/// </summary>
public bool IsInnerConnector
{
get; set;
}
protected ObservableCollection<FullyCreatedConnectorInfo> connectors = new ObservableCollection<FullyCreatedConnectorInfo>();
public IEnumerable<FullyCreatedConnectorInfo> Connectors
{
get
{
return connectors;
}
}
protected ObservableCollection<CinchMenuItem> menuOptions;
public IEnumerable<CinchMenuItem> 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<NotifyCollectionChangedEventArgs> WhenConnectorsChanged
{
get
{
return Observable
.FromEventPattern<NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(
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<double>(nameof(Left)), GetOldValue<double>(nameof(Top))), TopLeft);
}
public void RaiseItemWidthHeight()
{
this.RaisePropertyChanged(nameof(Size), new SizeBase(GetOldValue<double>(nameof(ItemWidth)), GetOldValue<double>(nameof(ItemHeight))), Size);
}
public void RaiseAngle()
{
this.RaisePropertyChanged(nameof(Angle), GetOldValue<double>(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
}
}