mirror of
https://gitee.com/akwkevin/aistudio.-wpf.-diagram
synced 2026-03-03 00:00:57 +08:00
系统优化
This commit is contained in:
@@ -8,7 +8,7 @@
|
|||||||
<PackageIcon>A.png</PackageIcon>
|
<PackageIcon>A.png</PackageIcon>
|
||||||
<PackageIconUrl />
|
<PackageIconUrl />
|
||||||
<NeutralLanguage />
|
<NeutralLanguage />
|
||||||
<Version>1.1.9</Version>
|
<Version>1.2.0</Version>
|
||||||
<Description>一个Wpf的Diagram控件基础库</Description>
|
<Description>一个Wpf的Diagram控件基础库</Description>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,21 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IDrawModeViewModel DrawModeViewModel
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_viewModel.DrawModeViewModel != null)
|
||||||
|
{
|
||||||
|
return _viewModel.DrawModeViewModel;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return _service.DrawModeViewModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private DrawMode DrawMode
|
private DrawMode DrawMode
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|||||||
@@ -36,6 +36,21 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IDrawModeViewModel DrawModeViewModel
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_viewModel.DrawModeViewModel != null)
|
||||||
|
{
|
||||||
|
return _viewModel.DrawModeViewModel;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return _service.DrawModeViewModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public RubberbandAdorner(DesignerCanvas designerCanvas, Point? dragStartPoint)
|
public RubberbandAdorner(DesignerCanvas designerCanvas, Point? dragStartPoint)
|
||||||
: base(designerCanvas)
|
: base(designerCanvas)
|
||||||
{
|
{
|
||||||
@@ -77,11 +92,11 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
if (adornerLayer != null)
|
if (adornerLayer != null)
|
||||||
adornerLayer.Remove(this);
|
adornerLayer.Remove(this);
|
||||||
|
|
||||||
if (this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Text)
|
if (this.DrawModeViewModel.GetDrawMode() == DrawMode.Text)
|
||||||
{
|
{
|
||||||
if (this.startPoint.HasValue && this.endPoint.HasValue)
|
if (this.startPoint.HasValue && this.endPoint.HasValue)
|
||||||
{
|
{
|
||||||
if (this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Text)
|
if (this.DrawModeViewModel.GetDrawMode() == DrawMode.Text)
|
||||||
{
|
{
|
||||||
TextDesignerItemViewModel itemBase = new TextDesignerItemViewModel();
|
TextDesignerItemViewModel itemBase = new TextDesignerItemViewModel();
|
||||||
Point position = e.GetPosition(this);
|
Point position = e.GetPosition(this);
|
||||||
@@ -93,7 +108,7 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
_viewModel.AddCommand.Execute(itemBase);
|
_viewModel.AddCommand.Execute(itemBase);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._service.DrawModeViewModel.ResetDrawMode();
|
this.DrawModeViewModel.ResetDrawMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
|
|||||||
@@ -83,9 +83,11 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
dataObject.ContentType = toolBoxData.Type;
|
dataObject.ContentType = toolBoxData.Type;
|
||||||
dataObject.DesiredSize = toolBoxData.DesiredSize;
|
dataObject.DesiredSize = toolBoxData.DesiredSize;
|
||||||
dataObject.DesiredMinSize = toolBoxData.DesiredMinSize;
|
dataObject.DesiredMinSize = toolBoxData.DesiredMinSize;
|
||||||
|
dataObject.ConnectorInfo = toolBoxData.ConnectorInfo;
|
||||||
dataObject.Icon = toolBoxData.Icon;
|
dataObject.Icon = toolBoxData.Icon;
|
||||||
dataObject.Text = toolBoxData.Text;
|
dataObject.Text = toolBoxData.Text;
|
||||||
dataObject.ColorViewModel = toolBoxData.ColorViewModel;
|
dataObject.ColorViewModel = toolBoxData.ColorViewModel;
|
||||||
|
dataObject.FontViewModel = toolBoxData.FontViewModel;
|
||||||
if (toolBoxData.Addition is DesignerItemViewModelBase designerItemViewModelBase)
|
if (toolBoxData.Addition is DesignerItemViewModelBase designerItemViewModelBase)
|
||||||
{
|
{
|
||||||
dataObject.DesignerItem = designerItemViewModelBase.ToSerializableItem();
|
dataObject.DesignerItem = designerItemViewModelBase.ToSerializableItem();
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
if (EqualityComparer<T>.Default.Equals(storage, value))
|
if (EqualityComparer<T>.Default.Equals(storage, value))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (propertyName == "IsSelected")
|
if (propertyName == "IsSelected" || propertyName == "IsReadOnly")
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -100,7 +100,7 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
{
|
{
|
||||||
if (EqualityComparer<T>.Default.Equals(storage, value)) return false;
|
if (EqualityComparer<T>.Default.Equals(storage, value)) return false;
|
||||||
|
|
||||||
if (propertyName == "IsSelected")
|
if (propertyName == "IsSelected" || propertyName == "IsReadOnly")
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
@@ -57,7 +58,7 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
|
|
||||||
Point point = sourceDataItem.MiddlePosition;
|
Point point = sourceDataItem.MiddlePosition;
|
||||||
|
|
||||||
_partialConnection = new ConnectionViewModel(_viewModel, sourceDataItem, new PartCreatedConnectorInfo(point.X, point.Y), LineDrawMode, RouterMode);
|
_partialConnection = new ConnectionViewModel(_viewModel, sourceDataItem, new PartCreatedConnectorInfo(point.X, point.Y), DrawModeViewModel.LineDrawMode, DrawModeViewModel.LineRouterMode);
|
||||||
|
|
||||||
_viewModel.Add(_partialConnection);
|
_viewModel.Add(_partialConnection);
|
||||||
_partialConnection.ZIndex = -1;
|
_partialConnection.ZIndex = -1;
|
||||||
@@ -110,6 +111,20 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IDrawModeViewModel DrawModeViewModel
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_viewModel.DrawModeViewModel != null)
|
||||||
|
{
|
||||||
|
return _viewModel.DrawModeViewModel;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return _service.DrawModeViewModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
private DrawMode DrawMode
|
private DrawMode DrawMode
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -125,36 +140,6 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DrawMode LineDrawMode
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_viewModel.DrawModeViewModel != null)
|
|
||||||
{
|
|
||||||
return _viewModel.DrawModeViewModel.LineDrawMode;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return _service.DrawModeViewModel.LineDrawMode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private RouterMode RouterMode
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_viewModel.DrawModeViewModel != null)
|
|
||||||
{
|
|
||||||
return _viewModel.DrawModeViewModel.LineRouterMode;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return _service.DrawModeViewModel.LineRouterMode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region GridCellSize
|
#region GridCellSize
|
||||||
|
|
||||||
public static readonly DependencyProperty GridCellSizeProperty =
|
public static readonly DependencyProperty GridCellSizeProperty =
|
||||||
@@ -511,22 +496,22 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
{
|
{
|
||||||
if (e.PropertyName == nameof(CursorMode))
|
if (e.PropertyName == nameof(CursorMode))
|
||||||
{
|
{
|
||||||
if (_service.DrawModeViewModel.CursorMode == CursorMode.Format)
|
if (DrawModeViewModel.CursorMode == CursorMode.Format)
|
||||||
{
|
{
|
||||||
EnterFormat();
|
EnterFormat();
|
||||||
}
|
}
|
||||||
else if (_service.DrawModeViewModel.CursorMode == CursorMode.Move)
|
else if (DrawModeViewModel.CursorMode == CursorMode.Move)
|
||||||
{
|
{
|
||||||
EnterMove();
|
EnterMove();
|
||||||
}
|
}
|
||||||
else if (_service.DrawModeViewModel.CursorMode == CursorMode.Exit)
|
else if (DrawModeViewModel.CursorMode == CursorMode.Exit)
|
||||||
{
|
{
|
||||||
ExitCursor();
|
ExitCursor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (e.PropertyName == nameof(_service.DrawModeViewModel.DrawingDrawMode))
|
else if (e.PropertyName == nameof(DrawModeViewModel.DrawingDrawMode))
|
||||||
{
|
{
|
||||||
if (_service.DrawModeViewModel.DrawingDrawMode == DrawMode.ColorPicker)
|
if (DrawModeViewModel.DrawingDrawMode == DrawMode.ColorPicker)
|
||||||
{
|
{
|
||||||
EnterColorPicker();
|
EnterColorPicker();
|
||||||
}
|
}
|
||||||
@@ -576,7 +561,7 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
{
|
{
|
||||||
item.IsHitTestVisible = true;
|
item.IsHitTestVisible = true;
|
||||||
}
|
}
|
||||||
_service.DrawModeViewModel.CursorMode = CursorMode.Normal;
|
DrawModeViewModel.CursorMode = CursorMode.Normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Format(SelectableDesignerItemViewModelBase source, SelectableDesignerItemViewModelBase target)
|
private void Format(SelectableDesignerItemViewModelBase source, SelectableDesignerItemViewModelBase target)
|
||||||
@@ -596,7 +581,7 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (_service.DrawModeViewModel.CursorMode == CursorMode.Format)
|
if (DrawModeViewModel.CursorMode == CursorMode.Format)
|
||||||
{
|
{
|
||||||
var element = (e.OriginalSource as FrameworkElement);
|
var element = (e.OriginalSource as FrameworkElement);
|
||||||
if (element.DataContext is SelectableDesignerItemViewModelBase target)
|
if (element.DataContext is SelectableDesignerItemViewModelBase target)
|
||||||
@@ -607,7 +592,7 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
|
|
||||||
ExitCursor();
|
ExitCursor();
|
||||||
}
|
}
|
||||||
else if (_service.DrawModeViewModel.CursorMode == CursorMode.Move)
|
else if (DrawModeViewModel.CursorMode == CursorMode.Move)
|
||||||
{
|
{
|
||||||
ExitCursor();
|
ExitCursor();
|
||||||
return;
|
return;
|
||||||
@@ -629,8 +614,8 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_service.DrawModeViewModel.SharpDrawModeSelected ||
|
if (DrawModeViewModel.SharpDrawModeSelected ||
|
||||||
(_service.DrawModeViewModel.DrawingDrawModeSelected && _service.DrawModeViewModel.DrawingDrawMode != DrawMode.Select))
|
(DrawModeViewModel.DrawingDrawModeSelected && DrawModeViewModel.DrawingDrawMode != DrawMode.Select))
|
||||||
{
|
{
|
||||||
// create rubberband adorner
|
// create rubberband adorner
|
||||||
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this);
|
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this);
|
||||||
@@ -643,7 +628,7 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (_service.DrawModeViewModel.LineDrawModeSelected)//画线模式,可以不命中实体
|
else if (DrawModeViewModel.LineDrawModeSelected)//画线模式,可以不命中实体
|
||||||
{
|
{
|
||||||
if (SourceConnector == null)
|
if (SourceConnector == null)
|
||||||
{
|
{
|
||||||
@@ -676,7 +661,7 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
_viewModel.CurrentColor = ColorPickerManager.GetColor(point.X, point.Y);
|
_viewModel.CurrentColor = ColorPickerManager.GetColor(point.X, point.Y);
|
||||||
|
|
||||||
//移动
|
//移动
|
||||||
if (_service.DrawModeViewModel.CursorMode == CursorMode.Move)
|
if (DrawModeViewModel.CursorMode == CursorMode.Move)
|
||||||
{
|
{
|
||||||
_viewModel.SelectedItems.OfType<DesignerItemViewModelBase>().ToList().ForEach(p => {
|
_viewModel.SelectedItems.OfType<DesignerItemViewModelBase>().ToList().ForEach(p => {
|
||||||
p.Left = currentPoint.X;
|
p.Left = currentPoint.X;
|
||||||
@@ -692,7 +677,7 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
_partialConnection.SinkConnectorInfo = new PartCreatedConnectorInfo(currentPoint.X, currentPoint.Y);
|
_partialConnection.SinkConnectorInfo = new PartCreatedConnectorInfo(currentPoint.X, currentPoint.Y);
|
||||||
|
|
||||||
SinkConnector = HitTesting(currentPoint);
|
SinkConnector = HitTesting(currentPoint);
|
||||||
if (SinkConnector?.Info?.CanAttachTo(SourceConnector?.Info) == false)
|
if (SinkConnector != SourceConnector && SinkConnector?.Info?.CanAttachTo(SourceConnector?.Info) == false)
|
||||||
{
|
{
|
||||||
SinkConnector.Info.DisableAttachTo = true;
|
SinkConnector.Info.DisableAttachTo = true;
|
||||||
}
|
}
|
||||||
@@ -759,19 +744,19 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
ConnectorInfoBase sinkDataItem = SinkConnector.Info;
|
ConnectorInfoBase sinkDataItem = SinkConnector.Info;
|
||||||
|
|
||||||
_viewModel.Delete(_partialConnection);
|
_viewModel.Delete(_partialConnection);
|
||||||
_viewModel.AddCommand.Execute(new ConnectionViewModel(_viewModel, sourceDataItem, sinkDataItem, LineDrawMode, RouterMode));
|
_viewModel.AddCommand.Execute(new ConnectionViewModel(_viewModel, sourceDataItem, sinkDataItem, DrawModeViewModel.LineDrawMode, DrawModeViewModel.LineRouterMode));
|
||||||
}
|
}
|
||||||
else if (_partialConnection.IsFullConnection)//自动连接模式
|
else if (_partialConnection.IsFullConnection)//自动连接模式
|
||||||
{
|
{
|
||||||
_viewModel.ClearAttachTo();
|
_viewModel.ClearAttachTo();
|
||||||
}
|
}
|
||||||
else if (_service.DrawModeViewModel.LineDrawModeSelected)
|
else if (DrawModeViewModel.LineDrawModeSelected)
|
||||||
{
|
{
|
||||||
Point currentPoint = e.GetPosition(this);
|
Point currentPoint = e.GetPosition(this);
|
||||||
ConnectorInfoBase sinkDataItem = new PartCreatedConnectorInfo(currentPoint.X, currentPoint.Y);
|
ConnectorInfoBase sinkDataItem = new PartCreatedConnectorInfo(currentPoint.X, currentPoint.Y);
|
||||||
|
|
||||||
_viewModel.Delete(_partialConnection);
|
_viewModel.Delete(_partialConnection);
|
||||||
_viewModel.AddCommand.Execute(new ConnectionViewModel(_viewModel, sourceDataItem, sinkDataItem, LineDrawMode, RouterMode));
|
_viewModel.AddCommand.Execute(new ConnectionViewModel(_viewModel, sourceDataItem, sinkDataItem, DrawModeViewModel.LineDrawMode, DrawModeViewModel.LineRouterMode));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -791,7 +776,7 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
|
|
||||||
SourceItemsContainer = null;
|
SourceItemsContainer = null;
|
||||||
|
|
||||||
_service.DrawModeViewModel.ResetDrawMode();
|
DrawModeViewModel.ResetDrawMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnPreviewKeyDown(KeyEventArgs e)
|
protected override void OnPreviewKeyDown(KeyEventArgs e)
|
||||||
@@ -944,6 +929,10 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
itemBase.MinItemWidth = dragObject.DesiredMinSize.Value.Width;
|
itemBase.MinItemWidth = dragObject.DesiredMinSize.Value.Width;
|
||||||
itemBase.MinItemHeight = dragObject.DesiredMinSize.Value.Height;
|
itemBase.MinItemHeight = dragObject.DesiredMinSize.Value.Height;
|
||||||
}
|
}
|
||||||
|
if (dragObject.ConnectorInfo != null)
|
||||||
|
{
|
||||||
|
InitConnectorInfo(itemBase, dragObject.ConnectorInfo);
|
||||||
|
}
|
||||||
_viewModel.AddCommand.Execute(itemBase);
|
_viewModel.AddCommand.Execute(itemBase);
|
||||||
|
|
||||||
if (itemBase is BlockDesignerItemViewModel block)
|
if (itemBase is BlockDesignerItemViewModel block)
|
||||||
@@ -966,6 +955,7 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
if (!string.IsNullOrEmpty(dragObject.Icon))
|
if (!string.IsNullOrEmpty(dragObject.Icon))
|
||||||
itemBase.Icon = dragObject.Icon;
|
itemBase.Icon = dragObject.Icon;
|
||||||
itemBase.ColorViewModel = CopyHelper.Mapper(dragObject.ColorViewModel);
|
itemBase.ColorViewModel = CopyHelper.Mapper(dragObject.ColorViewModel);
|
||||||
|
itemBase.FontViewModel = CopyHelper.Mapper(dragObject.FontViewModel);
|
||||||
if (dragObject.DesiredSize != null)
|
if (dragObject.DesiredSize != null)
|
||||||
{
|
{
|
||||||
itemBase.ItemWidth = dragObject.DesiredSize.Value.Width;
|
itemBase.ItemWidth = dragObject.DesiredSize.Value.Width;
|
||||||
@@ -976,7 +966,10 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
itemBase.MinItemWidth = dragObject.DesiredMinSize.Value.Width;
|
itemBase.MinItemWidth = dragObject.DesiredMinSize.Value.Width;
|
||||||
itemBase.MinItemHeight = dragObject.DesiredMinSize.Value.Height;
|
itemBase.MinItemHeight = dragObject.DesiredMinSize.Value.Height;
|
||||||
}
|
}
|
||||||
|
if (dragObject.ConnectorInfo != null)
|
||||||
|
{
|
||||||
|
InitConnectorInfo(itemBase, dragObject.ConnectorInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
itemBase.Left = Math.Max(0, position.X - itemBase.GetItemWidth() / 2);
|
itemBase.Left = Math.Max(0, position.X - itemBase.GetItemWidth() / 2);
|
||||||
itemBase.Top = Math.Max(0, position.Y - itemBase.GetItemHeight() / 2);
|
itemBase.Top = Math.Max(0, position.Y - itemBase.GetItemHeight() / 2);
|
||||||
@@ -1013,5 +1006,14 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
|
|
||||||
this.Focus();
|
this.Focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InitConnectorInfo(DesignerItemViewModelBase itemBase, List<FullyCreatedConnectorInfo> connectorInfos)
|
||||||
|
{
|
||||||
|
itemBase.ClearConnectors();
|
||||||
|
foreach (var connectorInfo in connectorInfos)
|
||||||
|
{
|
||||||
|
itemBase.AddConnector(new FullyCreatedConnectorInfo(itemBase, connectorInfo.Orientation, connectorInfo.IsInnerPoint, connectorInfo.IsPortless) { XRatio = connectorInfo.XRatio, YRatio = connectorInfo.YRatio });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,15 +90,18 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
D d = Activator.CreateInstance<D>(); //构造新实例
|
D d = Activator.CreateInstance<D>(); //构造新实例
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var Types = s.GetType();//获得类型
|
if (s != null)
|
||||||
var Typed = typeof(D);
|
|
||||||
foreach (PropertyInfo sp in Types.GetProperties().Where(p => p.CanRead))//获得类型的属性字段
|
|
||||||
{
|
{
|
||||||
foreach (PropertyInfo dp in Typed.GetProperties().Where(p => p.CanWrite))
|
var Types = s.GetType();//获得类型
|
||||||
|
var Typed = typeof(D);
|
||||||
|
foreach (PropertyInfo sp in Types.GetProperties().Where(p => p.CanRead))//获得类型的属性字段
|
||||||
{
|
{
|
||||||
if (dp.Name == sp.Name && dp.PropertyType == sp.PropertyType)//判断属性名是否相同
|
foreach (PropertyInfo dp in Typed.GetProperties().Where(p => p.CanWrite))
|
||||||
{
|
{
|
||||||
dp.SetValue(d, sp.GetValue(s, null), null);//获得s对象属性的值复制给d对象的属性
|
if (dp.Name == sp.Name && dp.PropertyType == sp.PropertyType)//判断属性名是否相同
|
||||||
|
{
|
||||||
|
dp.SetValue(d, sp.GetValue(s, null), null);//获得s对象属性的值复制给d对象的属性
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
{
|
{
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
public List<FullyCreatedConnectorInfo> ConnectorInfo
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
public Type ContentType
|
public Type ContentType
|
||||||
{
|
{
|
||||||
get; set;
|
get; set;
|
||||||
@@ -33,9 +37,16 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
{
|
{
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IFontViewModel FontViewModel
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
public object DesignerItem
|
public object DesignerItem
|
||||||
{
|
{
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
{
|
{
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
public IFontViewModel FontViewModel
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
public double Width
|
public double Width
|
||||||
{
|
{
|
||||||
get; set;
|
get; set;
|
||||||
@@ -41,6 +45,10 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
{
|
{
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
public List<FullyCreatedConnectorInfo> ConnectorInfo
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
public string Description
|
public string Description
|
||||||
{
|
{
|
||||||
get; set;
|
get; set;
|
||||||
|
|||||||
727
AIStudio.Wpf.DiagramDesigner/Routers/Pather.cs
Normal file
727
AIStudio.Wpf.DiagramDesigner/Routers/Pather.cs
Normal file
@@ -0,0 +1,727 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using AIStudio.Wpf.DiagramDesigner.Geometrys;
|
||||||
|
|
||||||
|
namespace AIStudio.Wpf.DiagramDesigner
|
||||||
|
{
|
||||||
|
internal class PathFinder
|
||||||
|
{
|
||||||
|
const int margin = 8;
|
||||||
|
const double CORNER = 6;
|
||||||
|
|
||||||
|
private static List<PointBase> AddCornerPoints(List<PointBase> linePoints)
|
||||||
|
{
|
||||||
|
if (linePoints.Count < 3 || CORNER <= 0) return linePoints;
|
||||||
|
List<PointBase> points = new List<PointBase>();
|
||||||
|
points.Add(linePoints[0]);
|
||||||
|
for (int i = 1; i < linePoints.Count - 1; i++)
|
||||||
|
{
|
||||||
|
double x1 = linePoints[i].X;
|
||||||
|
double x0 = linePoints[i - 1].X;
|
||||||
|
double y1 = linePoints[i].Y;
|
||||||
|
double y0 = linePoints[i - 1].Y;
|
||||||
|
if (x1 == x0)
|
||||||
|
{
|
||||||
|
double x2 = linePoints[i + 1].X;
|
||||||
|
if (y1 > y0)
|
||||||
|
{
|
||||||
|
if (y1 - y0 > CORNER && Math.Abs(x2 - x1) > CORNER)
|
||||||
|
{
|
||||||
|
points.Add(new PointBase(x1, y1 - CORNER));
|
||||||
|
points.Add(new PointBase(x2 > x1 ? x1 + CORNER : x1 - CORNER, y1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (y0 - y1 > CORNER && Math.Abs(x2 - x1) > CORNER)
|
||||||
|
{
|
||||||
|
points.Add(new PointBase(x1, y1 + CORNER));
|
||||||
|
points.Add(new PointBase(x2 > x1 ? x1 + CORNER : x1 - CORNER, y1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (y1 == y0)
|
||||||
|
{
|
||||||
|
double y2 = linePoints[i + 1].Y;
|
||||||
|
if (x1 > x0)
|
||||||
|
{
|
||||||
|
if (x1 - x0 > CORNER && Math.Abs(y2 - y1) > CORNER)
|
||||||
|
{
|
||||||
|
points.Add(new PointBase(x1 - CORNER, y1));
|
||||||
|
points.Add(new PointBase(x1, y2 > y1 ? y1 + CORNER : y1 - CORNER));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (x0 - x1 > CORNER && Math.Abs(y2 - y1) > CORNER)
|
||||||
|
{
|
||||||
|
points.Add(new PointBase(x1 + CORNER, y1));
|
||||||
|
points.Add(new PointBase(x1, y2 > y1 ? y1 + CORNER : y1 - CORNER));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
points.Add(linePoints[linePoints.Count - 1]);
|
||||||
|
return points.Count % 2 == 0 ? points : linePoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static List<PointBase> GetDirectLine(ConnectorInfoBase source, ConnectorInfoBase sink)
|
||||||
|
{
|
||||||
|
List<PointBase> linePoints = new List<PointBase>();
|
||||||
|
linePoints.Add(source.MiddlePosition);
|
||||||
|
linePoints.Add(sink.MiddlePosition);
|
||||||
|
return linePoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static List<PointBase> GetConnectionLine(ConnectorInfoBase source, ConnectorInfoBase sink, bool showLastLine)
|
||||||
|
{
|
||||||
|
List<PointBase> linePoints = new List<PointBase>();
|
||||||
|
|
||||||
|
RectangleBase rectSource = GetRectWithMargin(source, margin);
|
||||||
|
RectangleBase rectSink = GetRectWithMargin(sink, margin);
|
||||||
|
|
||||||
|
PointBase startPoint = GetOffsetPoint(source, rectSource);
|
||||||
|
PointBase endPoint = GetOffsetPoint(sink, rectSink);
|
||||||
|
|
||||||
|
linePoints.Add(startPoint);
|
||||||
|
PointBase currentPoint = startPoint;
|
||||||
|
|
||||||
|
if (!rectSink.Contains(currentPoint) && !rectSource.Contains(endPoint))
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
#region source node
|
||||||
|
|
||||||
|
if (IsPointVisible(currentPoint, endPoint, new RectangleBase[] { rectSource, rectSink }))
|
||||||
|
{
|
||||||
|
linePoints.Add(endPoint);
|
||||||
|
currentPoint = endPoint;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
PointBase neighbour = GetNearestVisibleNeighborSink(currentPoint, endPoint, sink, rectSource, rectSink);
|
||||||
|
if (!double.IsNaN(neighbour.X))
|
||||||
|
{
|
||||||
|
linePoints.Add(neighbour);
|
||||||
|
linePoints.Add(endPoint);
|
||||||
|
currentPoint = endPoint;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPoint == startPoint)
|
||||||
|
{
|
||||||
|
bool flag;
|
||||||
|
PointBase n = GetNearestNeighborSource(source, endPoint, rectSource, rectSink, out flag);
|
||||||
|
linePoints.Add(n);
|
||||||
|
currentPoint = n;
|
||||||
|
|
||||||
|
if (!IsRectVisible(currentPoint, rectSink, new RectangleBase[] { rectSource }))
|
||||||
|
{
|
||||||
|
PointBase n1, n2;
|
||||||
|
GetOppositeCorners(source.Orientation, rectSource, out n1, out n2);
|
||||||
|
if (flag)
|
||||||
|
{
|
||||||
|
linePoints.Add(n1);
|
||||||
|
currentPoint = n1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
linePoints.Add(n2);
|
||||||
|
currentPoint = n2;
|
||||||
|
}
|
||||||
|
if (!IsRectVisible(currentPoint, rectSink, new RectangleBase[] { rectSource }))
|
||||||
|
{
|
||||||
|
if (flag)
|
||||||
|
{
|
||||||
|
linePoints.Add(n2);
|
||||||
|
currentPoint = n2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
linePoints.Add(n1);
|
||||||
|
currentPoint = n1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region sink node
|
||||||
|
|
||||||
|
else // from here on we jump to the sink node
|
||||||
|
{
|
||||||
|
PointBase n1, n2; // neighbour corner
|
||||||
|
PointBase s1, s2; // opposite corner
|
||||||
|
GetNeighborCorners(sink.Orientation, rectSink, out s1, out s2);
|
||||||
|
GetOppositeCorners(sink.Orientation, rectSink, out n1, out n2);
|
||||||
|
|
||||||
|
bool n1Visible = IsPointVisible(currentPoint, n1, new RectangleBase[] { rectSource, rectSink });
|
||||||
|
bool n2Visible = IsPointVisible(currentPoint, n2, new RectangleBase[] { rectSource, rectSink });
|
||||||
|
|
||||||
|
if (n1Visible && n2Visible)
|
||||||
|
{
|
||||||
|
if (rectSource.Contains(n1))
|
||||||
|
{
|
||||||
|
linePoints.Add(n2);
|
||||||
|
if (rectSource.Contains(s2))
|
||||||
|
{
|
||||||
|
linePoints.Add(n1);
|
||||||
|
linePoints.Add(s1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
linePoints.Add(s2);
|
||||||
|
|
||||||
|
linePoints.Add(endPoint);
|
||||||
|
currentPoint = endPoint;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rectSource.Contains(n2))
|
||||||
|
{
|
||||||
|
linePoints.Add(n1);
|
||||||
|
if (rectSource.Contains(s1))
|
||||||
|
{
|
||||||
|
linePoints.Add(n2);
|
||||||
|
linePoints.Add(s2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
linePoints.Add(s1);
|
||||||
|
|
||||||
|
linePoints.Add(endPoint);
|
||||||
|
currentPoint = endPoint;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Distance(n1, endPoint) <= Distance(n2, endPoint)))
|
||||||
|
{
|
||||||
|
linePoints.Add(n1);
|
||||||
|
if (rectSource.Contains(s1))
|
||||||
|
{
|
||||||
|
linePoints.Add(n2);
|
||||||
|
linePoints.Add(s2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
linePoints.Add(s1);
|
||||||
|
linePoints.Add(endPoint);
|
||||||
|
currentPoint = endPoint;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
linePoints.Add(n2);
|
||||||
|
if (rectSource.Contains(s2))
|
||||||
|
{
|
||||||
|
linePoints.Add(n1);
|
||||||
|
linePoints.Add(s1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
linePoints.Add(s2);
|
||||||
|
linePoints.Add(endPoint);
|
||||||
|
currentPoint = endPoint;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (n1Visible)
|
||||||
|
{
|
||||||
|
linePoints.Add(n1);
|
||||||
|
if (rectSource.Contains(s1))
|
||||||
|
{
|
||||||
|
linePoints.Add(n2);
|
||||||
|
linePoints.Add(s2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
linePoints.Add(s1);
|
||||||
|
linePoints.Add(endPoint);
|
||||||
|
currentPoint = endPoint;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
linePoints.Add(n2);
|
||||||
|
if (rectSource.Contains(s2))
|
||||||
|
{
|
||||||
|
linePoints.Add(n1);
|
||||||
|
linePoints.Add(s1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
linePoints.Add(s2);
|
||||||
|
linePoints.Add(endPoint);
|
||||||
|
currentPoint = endPoint;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
linePoints.Add(endPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
linePoints = OptimizeLinePoints(linePoints, new RectangleBase[] { rectSource, rectSink }, source.Orientation, sink.Orientation);
|
||||||
|
|
||||||
|
CheckPathEnd(source, sink, showLastLine, linePoints);
|
||||||
|
//return linePoints;
|
||||||
|
return AddCornerPoints(linePoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static List<PointBase> GetConnectionLine(ConnectorInfoBase source, PointBase sinkPoint, ConnectorOrientation preferredOrientation)
|
||||||
|
{
|
||||||
|
List<PointBase> linePoints = new List<PointBase>();
|
||||||
|
RectangleBase rectSource = GetRectWithMargin(source, 5);
|
||||||
|
PointBase startPoint = GetOffsetPoint(source, rectSource);
|
||||||
|
PointBase endPoint = sinkPoint;
|
||||||
|
|
||||||
|
linePoints.Add(startPoint);
|
||||||
|
PointBase currentPoint = startPoint;
|
||||||
|
|
||||||
|
if (!rectSource.Contains(endPoint))
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (IsPointVisible(currentPoint, endPoint, new RectangleBase[] { rectSource }))
|
||||||
|
{
|
||||||
|
linePoints.Add(endPoint);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sideFlag;
|
||||||
|
PointBase n = GetNearestNeighborSource(source, endPoint, rectSource, out sideFlag);
|
||||||
|
linePoints.Add(n);
|
||||||
|
currentPoint = n;
|
||||||
|
|
||||||
|
if (IsPointVisible(currentPoint, endPoint, new RectangleBase[] { rectSource }))
|
||||||
|
{
|
||||||
|
linePoints.Add(endPoint);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PointBase n1, n2;
|
||||||
|
GetOppositeCorners(source.Orientation, rectSource, out n1, out n2);
|
||||||
|
if (sideFlag)
|
||||||
|
linePoints.Add(n1);
|
||||||
|
else
|
||||||
|
linePoints.Add(n2);
|
||||||
|
|
||||||
|
linePoints.Add(endPoint);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
linePoints.Add(endPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preferredOrientation != ConnectorOrientation.None)
|
||||||
|
linePoints = OptimizeLinePoints(linePoints, new RectangleBase[] { rectSource }, source.Orientation, preferredOrientation);
|
||||||
|
else
|
||||||
|
linePoints = OptimizeLinePoints(linePoints, new RectangleBase[] { rectSource }, source.Orientation, GetOpositeOrientation(source.Orientation));
|
||||||
|
|
||||||
|
return linePoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<PointBase> OptimizeLinePoints(List<PointBase> linePoints, RectangleBase[] rectangles, ConnectorOrientation sourceOrientation, ConnectorOrientation sinkOrientation)
|
||||||
|
{
|
||||||
|
List<PointBase> points = new List<PointBase>();
|
||||||
|
int cut = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < linePoints.Count; i++)
|
||||||
|
{
|
||||||
|
if (i >= cut)
|
||||||
|
{
|
||||||
|
for (int k = linePoints.Count - 1; k > i; k--)
|
||||||
|
{
|
||||||
|
if (IsPointVisible(linePoints[i], linePoints[k], rectangles))
|
||||||
|
{
|
||||||
|
cut = k;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
points.Add(linePoints[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Line
|
||||||
|
for (int j = 0; j < points.Count - 1; j++)
|
||||||
|
{
|
||||||
|
if (points[j].X != points[j + 1].X && points[j].Y != points[j + 1].Y)
|
||||||
|
{
|
||||||
|
ConnectorOrientation orientationFrom;
|
||||||
|
ConnectorOrientation orientationTo;
|
||||||
|
|
||||||
|
// orientation from point
|
||||||
|
if (j == 0)
|
||||||
|
orientationFrom = sourceOrientation;
|
||||||
|
else
|
||||||
|
orientationFrom = GetOrientation(points[j], points[j - 1]);
|
||||||
|
|
||||||
|
// orientation to pint
|
||||||
|
if (j == points.Count - 2)
|
||||||
|
orientationTo = sinkOrientation;
|
||||||
|
else
|
||||||
|
orientationTo = GetOrientation(points[j + 1], points[j + 2]);
|
||||||
|
|
||||||
|
|
||||||
|
if ((orientationFrom == ConnectorOrientation.Left || orientationFrom == ConnectorOrientation.Right) &&
|
||||||
|
(orientationTo == ConnectorOrientation.Left || orientationTo == ConnectorOrientation.Right))
|
||||||
|
{
|
||||||
|
double centerX = Math.Min(points[j].X, points[j + 1].X) + Math.Abs(points[j].X - points[j + 1].X) / 2;
|
||||||
|
points.Insert(j + 1, new PointBase(centerX, points[j].Y));
|
||||||
|
points.Insert(j + 2, new PointBase(centerX, points[j + 2].Y));
|
||||||
|
if (points.Count - 1 > j + 3)
|
||||||
|
points.RemoveAt(j + 3);
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((orientationFrom == ConnectorOrientation.Top || orientationFrom == ConnectorOrientation.Bottom) &&
|
||||||
|
(orientationTo == ConnectorOrientation.Top || orientationTo == ConnectorOrientation.Bottom))
|
||||||
|
{
|
||||||
|
double centerY = Math.Min(points[j].Y, points[j + 1].Y) + Math.Abs(points[j].Y - points[j + 1].Y) / 2;
|
||||||
|
points.Insert(j + 1, new PointBase(points[j].X, centerY));
|
||||||
|
points.Insert(j + 2, new PointBase(points[j + 2].X, centerY));
|
||||||
|
if (points.Count - 1 > j + 3)
|
||||||
|
points.RemoveAt(j + 3);
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((orientationFrom == ConnectorOrientation.Left || orientationFrom == ConnectorOrientation.Right) &&
|
||||||
|
(orientationTo == ConnectorOrientation.Top || orientationTo == ConnectorOrientation.Bottom))
|
||||||
|
{
|
||||||
|
points.Insert(j + 1, new PointBase(points[j + 1].X, points[j].Y));
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((orientationFrom == ConnectorOrientation.Top || orientationFrom == ConnectorOrientation.Bottom) &&
|
||||||
|
(orientationTo == ConnectorOrientation.Left || orientationTo == ConnectorOrientation.Right))
|
||||||
|
{
|
||||||
|
points.Insert(j + 1, new PointBase(points[j].X, points[j + 1].Y));
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ConnectorOrientation GetOrientation(PointBase p1, PointBase p2)
|
||||||
|
{
|
||||||
|
if (p1.X == p2.X)
|
||||||
|
{
|
||||||
|
if (p1.Y >= p2.Y)
|
||||||
|
return ConnectorOrientation.Bottom;
|
||||||
|
else
|
||||||
|
return ConnectorOrientation.Top;
|
||||||
|
}
|
||||||
|
else if (p1.Y == p2.Y)
|
||||||
|
{
|
||||||
|
if (p1.X >= p2.X)
|
||||||
|
return ConnectorOrientation.Right;
|
||||||
|
else
|
||||||
|
return ConnectorOrientation.Left;
|
||||||
|
}
|
||||||
|
throw new Exception("Failed to retrieve orientation");
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
private static Orientation GetOrientation(ConnectorOrientation sourceOrientation)
|
||||||
|
{
|
||||||
|
switch (sourceOrientation)
|
||||||
|
{
|
||||||
|
case ConnectorOrientation.Left:
|
||||||
|
return Orientation.Horizontal;
|
||||||
|
case ConnectorOrientation.Top:
|
||||||
|
return Orientation.Vertical;
|
||||||
|
case ConnectorOrientation.Right:
|
||||||
|
return Orientation.Horizontal;
|
||||||
|
case ConnectorOrientation.Bottom:
|
||||||
|
return Orientation.Vertical;
|
||||||
|
default:
|
||||||
|
throw new Exception("Unknown ConnectorOrientation");
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
private static PointBase GetNearestNeighborSource(ConnectorInfoBase source, PointBase endPoint, RectangleBase rectSource, RectangleBase rectSink, out bool flag)
|
||||||
|
{
|
||||||
|
PointBase n1, n2; // neighbors
|
||||||
|
GetNeighborCorners(source.Orientation, rectSource, out n1, out n2);
|
||||||
|
|
||||||
|
if (rectSink.Contains(n1))
|
||||||
|
{
|
||||||
|
flag = false;
|
||||||
|
return n2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rectSink.Contains(n2))
|
||||||
|
{
|
||||||
|
flag = true;
|
||||||
|
return n1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Distance(n1, endPoint) <= Distance(n2, endPoint)))
|
||||||
|
{
|
||||||
|
flag = true;
|
||||||
|
return n1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
flag = false;
|
||||||
|
return n2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PointBase GetNearestNeighborSource(ConnectorInfoBase source, PointBase endPoint, RectangleBase rectSource, out bool flag)
|
||||||
|
{
|
||||||
|
PointBase n1, n2; // neighbors
|
||||||
|
GetNeighborCorners(source.Orientation, rectSource, out n1, out n2);
|
||||||
|
|
||||||
|
if ((Distance(n1, endPoint) <= Distance(n2, endPoint)))
|
||||||
|
{
|
||||||
|
flag = true;
|
||||||
|
return n1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
flag = false;
|
||||||
|
return n2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PointBase GetNearestVisibleNeighborSink(PointBase currentPoint, PointBase endPoint, ConnectorInfoBase sink, RectangleBase rectSource, RectangleBase rectSink)
|
||||||
|
{
|
||||||
|
PointBase s1, s2; // neighbors on sink side
|
||||||
|
GetNeighborCorners(sink.Orientation, rectSink, out s1, out s2);
|
||||||
|
|
||||||
|
bool flag1 = IsPointVisible(currentPoint, s1, new RectangleBase[] { rectSource, rectSink });
|
||||||
|
bool flag2 = IsPointVisible(currentPoint, s2, new RectangleBase[] { rectSource, rectSink });
|
||||||
|
|
||||||
|
if (flag1) // s1 visible
|
||||||
|
{
|
||||||
|
if (flag2) // s1 and s2 visible
|
||||||
|
{
|
||||||
|
if (rectSink.Contains(s1))
|
||||||
|
return s2;
|
||||||
|
|
||||||
|
if (rectSink.Contains(s2))
|
||||||
|
return s1;
|
||||||
|
|
||||||
|
if ((Distance(s1, endPoint) <= Distance(s2, endPoint)))
|
||||||
|
return s1;
|
||||||
|
else
|
||||||
|
return s2;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return s1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // s1 not visible
|
||||||
|
{
|
||||||
|
if (flag2) // only s2 visible
|
||||||
|
{
|
||||||
|
return s2;
|
||||||
|
}
|
||||||
|
else // s1 and s2 not visible
|
||||||
|
{
|
||||||
|
return new PointBase(double.NaN, double.NaN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsPointVisible(PointBase fromPoint, PointBase targetPoint, RectangleBase[] rectangles)
|
||||||
|
{
|
||||||
|
foreach (RectangleBase rect in rectangles)
|
||||||
|
{
|
||||||
|
if (RectangleIntersectsLine(rect, fromPoint, targetPoint))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsRectVisible(PointBase fromPoint, RectangleBase targetRect, RectangleBase[] rectangles)
|
||||||
|
{
|
||||||
|
if (IsPointVisible(fromPoint, targetRect.TopLeft, rectangles))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (IsPointVisible(fromPoint, targetRect.TopRight, rectangles))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (IsPointVisible(fromPoint, targetRect.BottomLeft, rectangles))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (IsPointVisible(fromPoint, targetRect.BottomRight, rectangles))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool RectangleIntersectsLine(RectangleBase rect, PointBase startPoint, PointBase endPoint)
|
||||||
|
{
|
||||||
|
rect.Inflate(-1, -1);
|
||||||
|
return rect.IntersectsWith(new RectangleBase(startPoint, endPoint));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GetOppositeCorners(ConnectorOrientation orientation, RectangleBase rect, out PointBase n1, out PointBase n2)
|
||||||
|
{
|
||||||
|
switch (orientation)
|
||||||
|
{
|
||||||
|
case ConnectorOrientation.Left:
|
||||||
|
n1 = rect.TopRight; n2 = rect.BottomRight;
|
||||||
|
break;
|
||||||
|
case ConnectorOrientation.Top:
|
||||||
|
n1 = rect.BottomLeft; n2 = rect.BottomRight;
|
||||||
|
break;
|
||||||
|
case ConnectorOrientation.Right:
|
||||||
|
n1 = rect.TopLeft; n2 = rect.BottomLeft;
|
||||||
|
break;
|
||||||
|
case ConnectorOrientation.Bottom:
|
||||||
|
n1 = rect.TopLeft; n2 = rect.TopRight;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception("No opposite corners found!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GetNeighborCorners(ConnectorOrientation orientation, RectangleBase rect, out PointBase n1, out PointBase n2)
|
||||||
|
{
|
||||||
|
switch (orientation)
|
||||||
|
{
|
||||||
|
case ConnectorOrientation.Left:
|
||||||
|
n1 = rect.TopLeft; n2 = rect.BottomLeft;
|
||||||
|
break;
|
||||||
|
case ConnectorOrientation.Top:
|
||||||
|
n1 = rect.TopLeft; n2 = rect.TopRight;
|
||||||
|
break;
|
||||||
|
case ConnectorOrientation.Right:
|
||||||
|
n1 = rect.TopRight; n2 = rect.BottomRight;
|
||||||
|
break;
|
||||||
|
case ConnectorOrientation.Bottom:
|
||||||
|
n1 = rect.BottomLeft; n2 = rect.BottomRight;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception("No neighour corners found!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double Distance(PointBase p1, PointBase p2)
|
||||||
|
{
|
||||||
|
return PointBase.Subtract(p1, p2).Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RectangleBase GetRectWithMargin(ConnectorInfoBase connectorThumb, double margin)
|
||||||
|
{
|
||||||
|
RectangleBase rect;
|
||||||
|
if (connectorThumb is FullyCreatedConnectorInfo fullyCreated)
|
||||||
|
{
|
||||||
|
rect = fullyCreated.DataItem.GetBounds();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rect = new RectangleBase();
|
||||||
|
}
|
||||||
|
|
||||||
|
rect.Inflate(margin, margin);
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PointBase GetOffsetPoint(ConnectorInfoBase connector, RectangleBase rect)
|
||||||
|
{
|
||||||
|
PointBase offsetPoint = new PointBase();
|
||||||
|
|
||||||
|
switch (connector.Orientation)
|
||||||
|
{
|
||||||
|
case ConnectorOrientation.Left:
|
||||||
|
offsetPoint = new PointBase(rect.Left, connector.MiddlePosition.Y);
|
||||||
|
break;
|
||||||
|
case ConnectorOrientation.Top:
|
||||||
|
offsetPoint = new PointBase(connector.MiddlePosition.X, rect.Top);
|
||||||
|
break;
|
||||||
|
case ConnectorOrientation.Right:
|
||||||
|
offsetPoint = new PointBase(rect.Right, connector.MiddlePosition.Y);
|
||||||
|
break;
|
||||||
|
case ConnectorOrientation.Bottom:
|
||||||
|
offsetPoint = new PointBase(connector.MiddlePosition.X, rect.Bottom);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return offsetPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CheckPathEnd(ConnectorInfoBase source, ConnectorInfoBase sink, bool showLastLine, List<PointBase> linePoints)
|
||||||
|
{
|
||||||
|
if (showLastLine)
|
||||||
|
{
|
||||||
|
PointBase startPoint = new PointBase(0, 0);
|
||||||
|
PointBase endPoint = new PointBase(0, 0);
|
||||||
|
double marginPath = 10;
|
||||||
|
switch (source.Orientation)
|
||||||
|
{
|
||||||
|
case ConnectorOrientation.Left:
|
||||||
|
startPoint = new PointBase(source.MiddlePosition.X - marginPath, source.MiddlePosition.Y);
|
||||||
|
break;
|
||||||
|
case ConnectorOrientation.Top:
|
||||||
|
startPoint = new PointBase(source.MiddlePosition.X, source.MiddlePosition.Y - marginPath);
|
||||||
|
break;
|
||||||
|
case ConnectorOrientation.Right:
|
||||||
|
startPoint = new PointBase(source.MiddlePosition.X + marginPath, source.MiddlePosition.Y);
|
||||||
|
break;
|
||||||
|
case ConnectorOrientation.Bottom:
|
||||||
|
startPoint = new PointBase(source.MiddlePosition.X, source.MiddlePosition.Y + marginPath);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (sink.Orientation)
|
||||||
|
{
|
||||||
|
case ConnectorOrientation.Left:
|
||||||
|
endPoint = new PointBase(sink.MiddlePosition.X - marginPath, sink.MiddlePosition.Y);
|
||||||
|
break;
|
||||||
|
case ConnectorOrientation.Top:
|
||||||
|
endPoint = new PointBase(sink.MiddlePosition.X, sink.MiddlePosition.Y - marginPath);
|
||||||
|
break;
|
||||||
|
case ConnectorOrientation.Right:
|
||||||
|
endPoint = new PointBase(sink.MiddlePosition.X + marginPath, sink.MiddlePosition.Y);
|
||||||
|
break;
|
||||||
|
case ConnectorOrientation.Bottom:
|
||||||
|
endPoint = new PointBase(sink.MiddlePosition.X, sink.MiddlePosition.Y + marginPath);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
linePoints.Insert(0, startPoint);
|
||||||
|
linePoints.Add(endPoint);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
linePoints.Insert(0, source.MiddlePosition);
|
||||||
|
linePoints.Add(sink.MiddlePosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ConnectorOrientation GetOpositeOrientation(ConnectorOrientation connectorOrientation)
|
||||||
|
{
|
||||||
|
switch (connectorOrientation)
|
||||||
|
{
|
||||||
|
case ConnectorOrientation.Left:
|
||||||
|
return ConnectorOrientation.Right;
|
||||||
|
case ConnectorOrientation.Top:
|
||||||
|
return ConnectorOrientation.Bottom;
|
||||||
|
case ConnectorOrientation.Right:
|
||||||
|
return ConnectorOrientation.Left;
|
||||||
|
case ConnectorOrientation.Bottom:
|
||||||
|
return ConnectorOrientation.Top;
|
||||||
|
default:
|
||||||
|
return ConnectorOrientation.Top;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -38,6 +38,8 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
var connector = ItemContainerGenerator.ContainerFromItem(item) as ContentPresenter;
|
var connector = ItemContainerGenerator.ContainerFromItem(item) as ContentPresenter;
|
||||||
if (connector != null)
|
if (connector != null)
|
||||||
{
|
{
|
||||||
|
vm.PropertyChanged -= Vm_PropertyChanged;
|
||||||
|
vm.PropertyChanged += Vm_PropertyChanged;
|
||||||
Canvas.SetLeft(connector, vm.DataItem.GetItemWidth() * vm.XRatio - vm.ConnectorWidth / 2);
|
Canvas.SetLeft(connector, vm.DataItem.GetItemWidth() * vm.XRatio - vm.ConnectorWidth / 2);
|
||||||
Canvas.SetTop(connector, vm.DataItem.GetItemHeight() * vm.YRatio - vm.ConnectorHeight / 2);
|
Canvas.SetTop(connector, vm.DataItem.GetItemHeight() * vm.YRatio - vm.ConnectorHeight / 2);
|
||||||
}
|
}
|
||||||
@@ -65,6 +67,21 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
{
|
{
|
||||||
var vm = connector.DataContext as FullyCreatedConnectorInfo;
|
var vm = connector.DataContext as FullyCreatedConnectorInfo;
|
||||||
if (vm != null)
|
if (vm != null)
|
||||||
|
{
|
||||||
|
vm.PropertyChanged -= Vm_PropertyChanged;
|
||||||
|
vm.PropertyChanged += Vm_PropertyChanged;
|
||||||
|
Canvas.SetLeft(connector, vm.DataItem.GetItemWidth() * vm.XRatio - vm.ConnectorWidth / 2);
|
||||||
|
Canvas.SetTop(connector, vm.DataItem.GetItemHeight() * vm.YRatio - vm.ConnectorHeight / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Vm_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (sender is FullyCreatedConnectorInfo vm)
|
||||||
|
{
|
||||||
|
var connector = ItemContainerGenerator.ContainerFromItem(vm) as ContentPresenter;
|
||||||
|
if (connector != null)
|
||||||
{
|
{
|
||||||
Canvas.SetLeft(connector, vm.DataItem.GetItemWidth() * vm.XRatio - vm.ConnectorWidth / 2);
|
Canvas.SetLeft(connector, vm.DataItem.GetItemWidth() * vm.XRatio - vm.ConnectorWidth / 2);
|
||||||
Canvas.SetTop(connector, vm.DataItem.GetItemHeight() * vm.YRatio - vm.ConnectorHeight / 2);
|
Canvas.SetTop(connector, vm.DataItem.GetItemHeight() * vm.YRatio - vm.ConnectorHeight / 2);
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
{
|
{
|
||||||
public class FullyCreatedConnectorInfo : ConnectorInfoBase
|
public class FullyCreatedConnectorInfo : ConnectorInfoBase
|
||||||
{
|
{
|
||||||
|
public FullyCreatedConnectorInfo(ConnectorOrientation orientation, bool isInnerPoint = false, bool isPortless = false)
|
||||||
|
: this(null, orientation, isInnerPoint, isPortless)
|
||||||
|
{
|
||||||
|
}
|
||||||
public FullyCreatedConnectorInfo(DesignerItemViewModelBase dataItem, ConnectorOrientation orientation, bool isInnerPoint = false, bool isPortless = false)
|
public FullyCreatedConnectorInfo(DesignerItemViewModelBase dataItem, ConnectorOrientation orientation, bool isInnerPoint = false, bool isPortless = false)
|
||||||
: this(null, dataItem, orientation, isInnerPoint, isPortless)
|
: this(null, dataItem, orientation, isInnerPoint, isPortless)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -249,8 +249,8 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ItemWidth = Geometry.Bounds.Width;// + ColorViewModel.LineWidth * 0.5;
|
ItemWidth = Geometry.Bounds.Width + ColorViewModel.LineWidth * 1 - 1;
|
||||||
ItemHeight = Geometry.Bounds.Height;// + ColorViewModel.LineWidth * 0.5;
|
ItemHeight = Geometry.Bounds.Height + ColorViewModel.LineWidth * 1 - 1;
|
||||||
Left = point.X;
|
Left = point.X;
|
||||||
Top = point.Y;
|
Top = point.Y;
|
||||||
}
|
}
|
||||||
@@ -270,8 +270,8 @@ namespace AIStudio.Wpf.DiagramDesigner
|
|||||||
ScaleTransform scaleTransform = transformGroup.Children.OfType<ScaleTransform>().FirstOrDefault();
|
ScaleTransform scaleTransform = transformGroup.Children.OfType<ScaleTransform>().FirstOrDefault();
|
||||||
transformGroup.Children.Remove(scaleTransform); ;
|
transformGroup.Children.Remove(scaleTransform); ;
|
||||||
|
|
||||||
double radiox = ItemWidth / Geometry.Bounds.Width;
|
double radiox = (ItemWidth - ColorViewModel.LineWidth * 1 + 1) / Geometry.Bounds.Width;
|
||||||
double radioy = ItemHeight / Geometry.Bounds.Height;
|
double radioy = (ItemHeight - ColorViewModel.LineWidth * 1 + 1) / Geometry.Bounds.Height;
|
||||||
transformGroup.Children.Add(new ScaleTransform(radiox, radioy));
|
transformGroup.Children.Add(new ScaleTransform(radiox, radioy));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2530,7 +2530,8 @@ namespace AIStudio.Wpf.Logical.ViewModels
|
|||||||
{
|
{
|
||||||
var first = Input.Values.FirstOrDefault();
|
var first = Input.Values.FirstOrDefault();
|
||||||
Value = first.ConnectorValue;
|
Value = first.ConnectorValue;
|
||||||
LinkPoint.Value = first.ConnectorValue;
|
if (LinkPoint !=null)
|
||||||
|
LinkPoint.Value = first.ConnectorValue;
|
||||||
foreach (var output in Output)
|
foreach (var output in Output)
|
||||||
{
|
{
|
||||||
output.Value.ConnectorValue = first.ConnectorValue;
|
output.Value.ConnectorValue = first.ConnectorValue;
|
||||||
|
|||||||
Reference in New Issue
Block a user