箭头分离到独立的model中,方便自定义path

This commit is contained in:
艾竹
2023-01-26 18:27:17 +08:00
parent f11a4170d8
commit 9bb6c6d321
42 changed files with 993 additions and 299 deletions

View File

@@ -120,71 +120,7 @@ namespace AIStudio.Wpf.DiagramDesigner
RaisePropertyChanged(nameof(LineWidth));
}
}
}
private ArrowPathStyle _leftArrowPathStyle = ArrowPathStyle.None;
public ArrowPathStyle LeftArrowPathStyle
{
get
{
return _leftArrowPathStyle;
}
set
{
if (!SetProperty(ref _leftArrowPathStyle, value))
{
RaisePropertyChanged(nameof(LeftArrowPathStyle));
}
}
}
private ArrowPathStyle _rightArrowPathStyle = ArrowPathStyle.Arrow;
public ArrowPathStyle RightArrowPathStyle
{
get
{
return _rightArrowPathStyle;
}
set
{
if (!SetProperty(ref _rightArrowPathStyle, value))
{
RaisePropertyChanged(nameof(RightArrowPathStyle));
}
}
}
private ArrowSizeStyle _leftArrowSizeStyle = ArrowSizeStyle.Middle;
public ArrowSizeStyle LeftArrowSizeStyle
{
get
{
return _leftArrowSizeStyle;
}
set
{
if (!SetProperty(ref _leftArrowSizeStyle, value))
{
RaisePropertyChanged(nameof(LeftArrowSizeStyle));
}
}
}
private ArrowSizeStyle _rightArrowSizeStyle = ArrowSizeStyle.Middle;
public ArrowSizeStyle RightArrowSizeStyle
{
get
{
return _rightArrowSizeStyle;
}
set
{
if (!SetProperty(ref _rightArrowSizeStyle, value))
{
RaisePropertyChanged(nameof(RightArrowSizeStyle));
}
}
}
}
private LineDashStyle _lineDashStyle = LineDashStyle.None;
public LineDashStyle LineDashStyle
@@ -201,22 +137,6 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
}
public double LeftArrowSize
{
get
{
return LeftArrowPathStyle == ArrowPathStyle.None ? 0d : (double)LeftArrowSizeStyle;
}
}
public double RightArrowSize
{
get
{
return RightArrowPathStyle == ArrowPathStyle.None ? 0d : (double)RightArrowSizeStyle;
}
}
}

View File

@@ -3,22 +3,6 @@ using System.ComponentModel;
namespace AIStudio.Wpf.DiagramDesigner
{
/// <summary>
/// Simple service interface
/// </summary>
public interface IDiagramServiceProvider : INotifyPropertyChanged
{
IColorViewModel ColorViewModel { get; }
IFontViewModel FontViewModel { get; }
IDrawModeViewModel DrawModeViewModel { get; }
IQuickThemeViewModel QuickThemeViewModel { get; }
ILockObjectViewModel LockObjectViewModel { get; }
SelectableDesignerItemViewModelBase SelectedItem { get; set; }
IColorViewModel CopyDefaultColorViewModel();
IFontViewModel CopyDefaultFontViewModel();
}
/// <summary>
/// Simple service locator
/// </summary>
@@ -28,7 +12,9 @@ namespace AIStudio.Wpf.DiagramDesigner
{
ColorViewModel = new ColorViewModel();
FontViewModel = new FontViewModel();
ShapeViewModel = new ShapeViewModel();
LockObjectViewModel = new LockObjectViewModel();
_drawModeViewModel = new DrawModeViewModel();
_quickThemeViewModel = new QuickThemeViewModel();
@@ -37,6 +23,7 @@ namespace AIStudio.Wpf.DiagramDesigner
SetOldValue<IColorViewModel>(ColorViewModel, nameof(ColorViewModel));
SetOldValue<IFontViewModel>(FontViewModel, nameof(FontViewModel));
SetOldValue<IShapeViewModel>(ShapeViewModel, nameof(ShapeViewModel));
SetOldValue<ILockObjectViewModel>(LockObjectViewModel, nameof(LockObjectViewModel));
}
@@ -57,6 +44,12 @@ namespace AIStudio.Wpf.DiagramDesigner
return CopyHelper.Mapper<FontViewModel, IFontViewModel>(viewModel);
}
public IShapeViewModel CopyDefaultShapeViewModel()
{
var viewModel = GetOldValue<ShapeViewModel>(nameof(ShapeViewModel));
return CopyHelper.Mapper(viewModel);
}
private IColorViewModel _colorViewModel;
public IColorViewModel ColorViewModel
{
@@ -76,7 +69,7 @@ namespace AIStudio.Wpf.DiagramDesigner
_colorViewModel.PropertyChanged += ViewModel_PropertyChanged;
}
}
}
}
private IFontViewModel _fontViewModel;
public IFontViewModel FontViewModel
@@ -99,6 +92,27 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
private IShapeViewModel _linkMarkerViewModel;
public IShapeViewModel ShapeViewModel
{
get
{
return _linkMarkerViewModel;
}
set
{
if (_linkMarkerViewModel != null)
{
_linkMarkerViewModel.PropertyChanged -= ViewModel_PropertyChanged;
}
SetProperty(ref _linkMarkerViewModel, value);
if (_linkMarkerViewModel != null)
{
_linkMarkerViewModel.PropertyChanged += ViewModel_PropertyChanged;
}
}
}
private DrawModeViewModel _drawModeViewModel;
public IDrawModeViewModel DrawModeViewModel
{
@@ -151,12 +165,14 @@ namespace AIStudio.Wpf.DiagramDesigner
{
ColorViewModel = GetOldValue<ColorViewModel>(nameof(ColorViewModel));
FontViewModel = GetOldValue<FontViewModel>(nameof(FontViewModel));
ShapeViewModel = GetOldValue<ShapeViewModel>(nameof(ShapeViewModel));
LockObjectViewModel = GetOldValue<LockObjectViewModel>(nameof(LockObjectViewModel));
}
else
{
ColorViewModel = _selectedItem.ColorViewModel;
FontViewModel = _selectedItem.FontViewModel;
ShapeViewModel = _selectedItem.ShapeViewModel;
LockObjectViewModel = _selectedItem.LockObjectViewModel;
}
}
@@ -168,8 +184,6 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
/// <summary>
/// Simple service locator helper
/// </summary>

View File

@@ -25,33 +25,10 @@ namespace AIStudio.Wpf.DiagramDesigner
{
get; set;
}
ArrowPathStyle LeftArrowPathStyle
LineDashStyle LineDashStyle
{
get; set;
}
ArrowPathStyle RightArrowPathStyle
{
get; set;
}
ArrowSizeStyle LeftArrowSizeStyle
{
get; set;
}
ArrowSizeStyle RightArrowSizeStyle
{
get; set;
}
double LeftArrowSize
{
get;
}
double RightArrowSize
{
get;
}
event PropertyChangedEventHandler PropertyChanged;
}
}

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
namespace AIStudio.Wpf.DiagramDesigner
{
/// <summary>
/// Simple service interface
/// </summary>
public interface IDiagramServiceProvider : INotifyPropertyChanged
{
IColorViewModel ColorViewModel
{
get;
}
IFontViewModel FontViewModel
{
get;
}
IShapeViewModel ShapeViewModel
{
get;
}
IDrawModeViewModel DrawModeViewModel
{
get;
}
IQuickThemeViewModel QuickThemeViewModel
{
get;
}
ILockObjectViewModel LockObjectViewModel
{
get;
}
SelectableDesignerItemViewModelBase SelectedItem
{
get; set;
}
IColorViewModel CopyDefaultColorViewModel();
IFontViewModel CopyDefaultFontViewModel();
IShapeViewModel CopyDefaultShapeViewModel();
}
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
namespace AIStudio.Wpf.DiagramDesigner
{
public interface IShapeViewModel
{
ILinkMarker SourceMarker
{
get; set;
}
ILinkMarker SinkMarker
{
get; set;
}
event PropertyChangedEventHandler PropertyChanged;
}
}

View File

@@ -0,0 +1,201 @@
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, ArrowPathStyle.None, ArrowSizeStyle.Middle);
public static LinkMarker Arrow { get; } = new LinkMarker("M 0 -5 10 0 0 5 z", 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, ArrowPathStyle.Circle, ArrowSizeStyle.Middle);
public static LinkMarker Square { get; } = new LinkMarker("M 0 -5 10 -5 10 5 0 5 z", 10, ArrowPathStyle.Square, ArrowSizeStyle.Middle);
public static readonly Dictionary<ArrowPathStyle, string> ArrowDictionary = new Dictionary<ArrowPathStyle, string>()
{
{ ArrowPathStyle.None, None.Path },
{ ArrowPathStyle.Arrow, Arrow.Path },
{ ArrowPathStyle.Circle, Circle.Path },
{ ArrowPathStyle.Square, Square.Path },
};
public LinkMarker()
{
}
public LinkMarker(string path, double width, ArrowPathStyle arrowPathStyle, ArrowSizeStyle arrowSizeStyle)
{
Path = path;
Width = width;
_pathStyle = arrowPathStyle;
_sizeStyle = arrowSizeStyle;
}
private string _path;
public string Path
{
get
{
return _path;
}
set
{
SetProperty(ref _path, value);
}
}
private double _witdh;
public double Width
{
get
{
return _witdh;
}
set
{
SetProperty(ref _witdh, value);
}
}
private ArrowPathStyle _pathStyle = ArrowPathStyle.None;
public ArrowPathStyle PathStyle
{
get
{
return _pathStyle;
}
set
{
if (SetProperty(ref _pathStyle, value))
{
if (ArrowDictionary.ContainsKey(_pathStyle))
{
Path = ArrowDictionary[_pathStyle];
}
}
}
}
private ArrowSizeStyle _sizeStyle = ArrowSizeStyle.Middle;
public ArrowSizeStyle SizeStyle
{
get
{
return _sizeStyle;
}
set
{
if (SetProperty(ref _sizeStyle, value))
{
Width = (double)_sizeStyle;
}
}
}
public static LinkMarker NewArrow(double width, double height)
=> new LinkMarker(FormattableString.Invariant($"M 0 -{height / 2} {width} 0 0 {height / 2}"), width, 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, 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, ArrowPathStyle.Square, (ArrowSizeStyle)width);
public static LinkMarker NewSquare(double size) => NewRectangle(size, size);
}
public interface ILinkMarker
{
string Path
{
get; set;
}
double Width
{
get; set;
}
ArrowPathStyle PathStyle
{
get; set;
}
ArrowSizeStyle SizeStyle
{
get; set;
}
}
}

View File

@@ -53,17 +53,14 @@ namespace AIStudio.Wpf.DiagramDesigner
protected virtual void Init(FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo)
{
this.Root = sourceConnectorInfo.DataItem.Root;
if (Root != null && Root.ColorViewModel != null)
{
this.ColorViewModel = CopyHelper.Mapper(Root.ColorViewModel);
}
this.ColorViewModel.FillColor.Color = Colors.Red;
if (sinkConnectorInfo is FullyCreatedConnectorInfo sink && sink.DataItem.ShowArrow == false)
{
this.ColorViewModel.RightArrowPathStyle = ArrowPathStyle.None;
this.ShapeViewModel.SinkMarker = LinkMarker.None;
}
ColorViewModel.PropertyChanged += ConnectorViewModel_PropertyChanged;
this.ColorViewModel.PropertyChanged += ConnectorViewModel_PropertyChanged;
this.ShapeViewModel.PropertyChanged += ConnectorViewModel_PropertyChanged;
this.PropertyChanged += ConnectorViewModel_PropertyChanged;
var routetype = GlobalType.AllTypes.Where(p => typeof(IRouter).IsAssignableFrom(p)).FirstOrDefault(p => p.Name == RouterMode);
@@ -76,7 +73,7 @@ namespace AIStudio.Wpf.DiagramDesigner
this.SinkConnectorInfo = sinkConnectorInfo;
DeleteConnectionCommand = new SimpleCommand(Command_Enable, DeleteConnection);
AddVertexCommand = new SimpleCommand(Command_Enable, AddVertex);
AddLabelCommand = new SimpleCommand(Command_Enable, AddLabel);
AddLabelCommand = new SimpleCommand(Command_Enable, para => AddLabel());
}
protected override void LoadDesignerItemViewModel(IDiagramViewModel root, SelectableItemBase designerbase)
@@ -452,12 +449,10 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
else if (sender is ColorViewModel)
else if (sender is ShapeViewModel)
{
if (e.PropertyName == nameof(ColorViewModel.LeftArrowPathStyle) ||
e.PropertyName == nameof(ColorViewModel.LeftArrowSizeStyle) ||
e.PropertyName == nameof(ColorViewModel.RightArrowPathStyle) ||
e.PropertyName == nameof(ColorViewModel.RightArrowSizeStyle))
if (e.PropertyName == nameof(ShapeViewModel.SourceMarker) ||
e.PropertyName == nameof(ShapeViewModel.SinkMarker))
{
UpdatePathGeneratorResult();
}
@@ -536,22 +531,22 @@ namespace AIStudio.Wpf.DiagramDesigner
{
case ConnectorOrientation.Left:
{
StartPoint = new PointBase(PathGeneratorResult.SourceMarkerPosition.X, PathGeneratorResult.SourceMarkerPosition.Y - ColorViewModel.LeftArrowSize / 2);
StartPoint = new PointBase(PathGeneratorResult.SourceMarkerPosition.X, PathGeneratorResult.SourceMarkerPosition.Y - GetSourceMarkerWidth() / 2);
break;
}
case ConnectorOrientation.Top:
{
StartPoint = new PointBase(PathGeneratorResult.SourceMarkerPosition.X - ColorViewModel.LeftArrowSize / 2, PathGeneratorResult.SourceMarkerPosition.Y);
StartPoint = new PointBase(PathGeneratorResult.SourceMarkerPosition.X - GetSourceMarkerWidth() / 2, PathGeneratorResult.SourceMarkerPosition.Y);
break;
}
case ConnectorOrientation.Right:
{
StartPoint = new PointBase(PathGeneratorResult.SourceMarkerPosition.X - ColorViewModel.LeftArrowSize, PathGeneratorResult.SourceMarkerPosition.Y - ColorViewModel.LeftArrowSize / 2);
StartPoint = new PointBase(PathGeneratorResult.SourceMarkerPosition.X - GetSourceMarkerWidth(), PathGeneratorResult.SourceMarkerPosition.Y - GetSourceMarkerWidth() / 2);
break;
}
case ConnectorOrientation.Bottom:
{
StartPoint = new PointBase(PathGeneratorResult.SourceMarkerPosition.X - ColorViewModel.LeftArrowSize / 2, PathGeneratorResult.SourceMarkerPosition.Y - ColorViewModel.LeftArrowSize);
StartPoint = new PointBase(PathGeneratorResult.SourceMarkerPosition.X - GetSourceMarkerWidth() / 2, PathGeneratorResult.SourceMarkerPosition.Y - GetSourceMarkerWidth());
break;
}
default:
@@ -566,23 +561,23 @@ namespace AIStudio.Wpf.DiagramDesigner
{
case ConnectorOrientation.Left:
{
EndPoint = new PointBase(PathGeneratorResult.TargetMarkerPosition.X, PathGeneratorResult.TargetMarkerPosition.Y - ColorViewModel.RightArrowSize / 2);
EndPoint = new PointBase(PathGeneratorResult.TargetMarkerPosition.X, PathGeneratorResult.TargetMarkerPosition.Y - GetSinkMarkerWidth() / 2);
break;
}
case ConnectorOrientation.Top:
{
EndPoint = new PointBase(PathGeneratorResult.TargetMarkerPosition.X - ColorViewModel.RightArrowSize / 2, PathGeneratorResult.TargetMarkerPosition.Y);
EndPoint = new PointBase(PathGeneratorResult.TargetMarkerPosition.X - GetSinkMarkerWidth() / 2, PathGeneratorResult.TargetMarkerPosition.Y);
break;
}
case ConnectorOrientation.Right:
{
EndPoint = new PointBase(PathGeneratorResult.TargetMarkerPosition.X - ColorViewModel.RightArrowSize, PathGeneratorResult.TargetMarkerPosition.Y - ColorViewModel.RightArrowSize / 2);
EndPoint = new PointBase(PathGeneratorResult.TargetMarkerPosition.X - GetSinkMarkerWidth(), PathGeneratorResult.TargetMarkerPosition.Y - GetSinkMarkerWidth() / 2);
break;
}
case ConnectorOrientation.Bottom:
{
EndPoint = new PointBase(PathGeneratorResult.TargetMarkerPosition.X - ColorViewModel.RightArrowSize / 2, PathGeneratorResult.TargetMarkerPosition.Y - ColorViewModel.RightArrowSize);
EndPoint = new PointBase(PathGeneratorResult.TargetMarkerPosition.X - GetSinkMarkerWidth() / 2, PathGeneratorResult.TargetMarkerPosition.Y - GetSinkMarkerWidth());
break;
}
default:
@@ -686,6 +681,34 @@ namespace AIStudio.Wpf.DiagramDesigner
return minPoint;
}
public void SetSourcePort(FullyCreatedConnectorInfo port)
{
SourceConnectorInfo = port;
}
public void SetSinkPort(FullyCreatedConnectorInfo port)
{
SinkConnectorInfo = port;
}
public double GetSourceMarkerWidth()
{
if (string.IsNullOrEmpty(ShapeViewModel.SourceMarker.Path))
{
return 0;
}
return ShapeViewModel.SourceMarker.Width;
}
public double GetSinkMarkerWidth()
{
if (string.IsNullOrEmpty(ShapeViewModel.SinkMarker.Path))
{
return 0;
}
return ShapeViewModel.SinkMarker.Width;
}
#region
private void AddVertex(object parameter)
{
@@ -708,9 +731,9 @@ namespace AIStudio.Wpf.DiagramDesigner
AddLabel();
}
public void AddLabel(object text = null)
public void AddLabel(string text = null, double? distance = null, PointBase? offset = null)
{
var label = new ConnectorLabelModel(this, text?.ToString());
var label = new ConnectorLabelModel(this, text?.ToString(), distance, offset);
label.PropertyChanged += new WeakINPCEventHandler(ConnectorViewModel_PropertyChanged).Handler;
label.IsSelected = true;
Labels.Add(label);

View File

@@ -35,6 +35,9 @@ namespace AIStudio.Wpf.DiagramDesigner
{
base.Init();
ConnectorWidth = 30;
ConnectorHeight = 30;
DeleteLabelCommand = new SimpleCommand(Command_Enable, DeleteLabel);
}

View File

@@ -67,6 +67,16 @@ namespace AIStudio.Wpf.DiagramDesigner
get; set;
}
public IFontViewModel FontViewModel
{
get; set;
}
public IShapeViewModel ShapeViewModel
{
get; set;
}
private PageSizeType _pageSizeType = PageSizeType.A4;
public PageSizeType PageSizeType
{

View File

@@ -62,8 +62,32 @@ namespace AIStudio.Wpf.DiagramDesigner
protected virtual void Init()
{
ColorViewModel = _service.CopyDefaultColorViewModel();
FontViewModel = _service.CopyDefaultFontViewModel();
if (Root?.ColorViewModel != null)
{
this.ColorViewModel = CopyHelper.Mapper(Root.ColorViewModel);
}
else
{
this.ColorViewModel = _service.CopyDefaultColorViewModel();
}
if (Root?.FontViewModel != null)
{
this.FontViewModel = CopyHelper.Mapper<FontViewModel, IFontViewModel>(Root.FontViewModel);
}
else
{
this.FontViewModel = _service.CopyDefaultFontViewModel();
}
if (Root?.ShapeViewModel != null)
{
this.ShapeViewModel = CopyHelper.Mapper(Root.ShapeViewModel);
}
else
{
this.ShapeViewModel = _service.CopyDefaultShapeViewModel();
}
LockObjectViewModel = new LockObjectViewModel();
}
@@ -80,6 +104,7 @@ namespace AIStudio.Wpf.DiagramDesigner
ColorViewModel = CopyHelper.Mapper(designerbase.ColorItem);
FontViewModel = CopyHelper.Mapper<FontViewModel, FontItem>(designerbase.FontItem);
ShapeViewModel = CopyHelper.Mapper(designerbase.SharpItem);
}
public IDiagramViewModel Root
@@ -220,6 +245,19 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
private IShapeViewModel _shapeViewModel;
public IShapeViewModel ShapeViewModel
{
get
{
return _shapeViewModel;
}
set
{
SetProperty(ref _shapeViewModel, value);
}
}
public ILockObjectViewModel LockObjectViewModel
{
get; set;

View File

@@ -258,6 +258,14 @@ namespace AIStudio.Wpf.DiagramDesigner
{
get; set;
}
IFontViewModel FontViewModel
{
get; set;
}
IShapeViewModel ShapeViewModel
{
get; set;
}
#endregion
//用于wpf大小与物理像素之间转换
double ScreenScale