部分连接线拖拽完成

This commit is contained in:
艾竹
2023-05-03 09:59:46 +08:00
parent 6de36f2473
commit 1536e5018d
33 changed files with 997 additions and 158 deletions

View File

@@ -17,12 +17,12 @@ namespace AIStudio.Wpf.DiagramDesigner.Algorithms
if (link.IsFullConnection == false)
continue;
var sourcePorts = link.SourceConnectorInfo.DataItem.Connectors;
var sourcePorts = link.SourceConnectorInfoFully.DataItem.Connectors;
var targetPorts = link.SinkConnectorInfoFully.DataItem.Connectors;
// Find the ports with minimal distance
var minDistance = double.MaxValue;
var minSourcePort = link.SourceConnectorInfo;
var minSourcePort = link.SourceConnectorInfoFully;
var minTargetPort = link.SinkConnectorInfoFully;
foreach (var sourcePort in sourcePorts)
{
@@ -41,16 +41,16 @@ namespace AIStudio.Wpf.DiagramDesigner.Algorithms
// Reconnect
if (link.SourceConnectorInfo != minSourcePort)
{
//portsToRefresh.Add(link.SourceConnectorInfo);
//portsToRefresh.Add(link.SourceConnectorInfoFully);
//portsToRefresh.Add(minSourcePort);
link.SetSourcePort(minSourcePort);
link.SourceConnectorInfo = minSourcePort;
}
if (link.SinkConnectorInfo != minTargetPort)
{
//portsToRefresh.Add(link.SinkConnectorInfoFully);
//portsToRefresh.Add(minTargetPort);
link.SetSinkPort(minTargetPort);
link.SinkConnectorInfo = minTargetPort;
}
}

View File

@@ -32,14 +32,14 @@ namespace AIStudio.Wpf.DiagramDesigner
return element as DesignerCanvas;
}
public FullyCreatedConnectorInfo Info
public ConnectorInfoBase Info
{
get
{
if (Content is FullyCreatedConnectorInfo connectorInfo)
if (Content is ConnectorInfoBase connectorInfo)
return connectorInfo;
return this.DataContext as FullyCreatedConnectorInfo;
return this.DataContext as ConnectorInfoBase;
}
}

View File

@@ -37,7 +37,7 @@ namespace AIStudio.Wpf.DiagramDesigner
return DiagramServicesProvider.Instance.Provider;
}
}
private ConnectionViewModel partialConnection;
private ConnectionViewModel partialConnection;
private Point? rubberbandSelectionStartPoint = null;
@@ -54,11 +54,14 @@ namespace AIStudio.Wpf.DiagramDesigner
{
sourceConnector = value;
FullyCreatedConnectorInfo sourceDataItem = sourceConnector.Info;
ConnectorInfoBase sourceDataItem = sourceConnector.Info;
//Rect rectangleBounds = sourceConnector.TransformToVisual(this).TransformBounds(new Rect(sourceConnector.RenderSize));
//Point point = new Point(rectangleBounds.Left + (rectangleBounds.Width / 2),
// rectangleBounds.Bottom + (rectangleBounds.Height / 2));
Point point = sourceDataItem.MiddlePosition;
Rect rectangleBounds = sourceConnector.TransformToVisual(this).TransformBounds(new Rect(sourceConnector.RenderSize));
Point point = new Point(rectangleBounds.Left + (rectangleBounds.Width / 2),
rectangleBounds.Bottom + (rectangleBounds.Height / 2));
partialConnection = new ConnectionViewModel(_viewModel, sourceDataItem, new PartCreatedConnectorInfo(point.X, point.Y), DrawMode, RouterMode);
_viewModel.Add(partialConnection);
@@ -127,7 +130,7 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
}
#region GridCellSize
public static readonly DependencyProperty GridCellSizeProperty =
@@ -350,13 +353,24 @@ namespace AIStudio.Wpf.DiagramDesigner
{
// in case that this click is the start for a
// drag operation we cache the start point
rubberbandSelectionStartPoint = e.GetPosition(this);
Point currentPoint = e.GetPosition(this);
rubberbandSelectionStartPoint = currentPoint;
if (!(Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)))
{
_viewModel.ClearSelectedItems();
}
if (_service.DrawModeViewModel.LineDrawModeSelected)//画线模式,可以不命中实体
{
if (SourceConnector == null)
{
//新建一个Part连接点
SourceConnector = new Connector() { Content = new PartCreatedConnectorInfo(currentPoint.X, currentPoint.Y) };
}
}
e.Handled = true;
}
}
@@ -365,8 +379,8 @@ namespace AIStudio.Wpf.DiagramDesigner
protected override void OnMouseMove(MouseEventArgs e)
{
var focusedElement = Keyboard.FocusedElement;
Debug.WriteLine("focusedElement" + focusedElement?.ToString());
//var focusedElement = Keyboard.FocusedElement;
//Debug.WriteLine("focusedElement" + focusedElement?.ToString());
base.OnMouseMove(e);
@@ -440,32 +454,36 @@ namespace AIStudio.Wpf.DiagramDesigner
if (sourceConnector != null)
{
FullyCreatedConnectorInfo sourceDataItem = sourceConnector.Info;
ConnectorInfoBase sourceDataItem = sourceConnector.Info;
if (sinkConnector != null)
{
ConnectorInfoBase sinkDataItem = sinkConnector.Info;
FullyCreatedConnectorInfo sinkDataItem = sinkConnector.Info;
int indexOfLastTempConnection = sinkDataItem.DataItem.Root.Items.Count - 1;
sinkDataItem.DataItem.Root.Remove(
sinkDataItem.DataItem.Root.Items[indexOfLastTempConnection]);
sinkDataItem.DataItem.Root.AddItemCommand.Execute(new ConnectionViewModel(_viewModel, sourceDataItem, sinkDataItem, DrawMode, RouterMode));
_viewModel.Remove(partialConnection);
_viewModel.AddItemCommand.Execute(new ConnectionViewModel(_viewModel, sourceDataItem, sinkDataItem, DrawMode, RouterMode));
}
else if (partialConnection.IsFullConnection)//自动连接模式
{
partialConnection.RaiseFullConnection();
}
else if (_service.DrawModeViewModel.LineDrawModeSelected)
{
Point currentPoint = e.GetPosition(this);
ConnectorInfoBase sinkDataItem = new PartCreatedConnectorInfo(currentPoint.X, currentPoint.Y);
_viewModel.Remove(partialConnection);
_viewModel.AddItemCommand.Execute(new ConnectionViewModel(_viewModel, sourceDataItem, sinkDataItem, DrawMode, RouterMode));
}
else
{
//Need to remove last item as we did not finish drawing the path
int indexOfLastTempConnection = sourceDataItem.DataItem.Root.Items.Count - 1;
sourceDataItem.DataItem.Root.Remove(
sourceDataItem.DataItem.Root.Items[indexOfLastTempConnection]);
_viewModel.Remove(partialConnection);
}
}
sourceConnector = null;
sinkConnector = null;
partialConnection = null;
if (_service.DrawModeViewModel.GetDrawMode() != DrawMode.DirectLine)
{
@@ -534,7 +552,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{
if (hitObject is Connector connector)
{
return connector;
return connector;
}
hitObject = VisualTreeHelper.GetParent(hitObject);
}
@@ -622,7 +640,7 @@ namespace AIStudio.Wpf.DiagramDesigner
foreach (var port in _viewModel.Items.OfType<DesignerItemViewModelBase>().ToList().SelectMany(n => n.Connectors))
{
if (partialConnection.OnGoingPosition.DistanceTo(port.Position) < SnappingRadius &&
partialConnection.SourceConnectorInfo.CanAttachTo(port))
partialConnection.SourceConnectorInfoFully?.CanAttachTo(port) == true)
return port;
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Windows;
@@ -44,10 +45,14 @@ namespace AIStudio.Wpf.DiagramDesigner.Controls
designerItems.AddRange(designerItem.Root.SelectionService.GetGroupMembers(groupable).OfType<SelectableDesignerItemViewModelBase>());
}
//拖动连线,把连接者也一起移动
if (designerItem is ConnectionViewModel connector)
{
designerItems.Add(connector.SourceConnectorInfo.DataItem);
if (connector.IsFullConnection)
if (connector.SourceConnectorInfoFully != null)
{
designerItems.Add(connector.SourceConnectorInfoFully.DataItem);
}
if (connector.SinkConnectorInfoFully != null)
{
designerItems.Add(connector.SinkConnectorInfoFully.DataItem);
}
@@ -66,6 +71,13 @@ namespace AIStudio.Wpf.DiagramDesigner.Controls
item.SetOldValue(item.TopLeft, nameof(item.TopLeft));
}
//部分连接点可以移动
foreach (ConnectionViewModel item in designerItems.OfType<ConnectionViewModel>())
{
item.SourceConnectorInfoPart?.SetOldValue(item.SourceConnectorInfoPart.Position, nameof(item.SourceConnectorInfoPart.Position));
item.SinkConnectorInfoPart?.SetOldValue(item.SinkConnectorInfoPart.Position, nameof(item.SinkConnectorInfoPart.Position));
}
e.Handled = true;
}
else
@@ -76,10 +88,10 @@ namespace AIStudio.Wpf.DiagramDesigner.Controls
private void DragThumb_DragCompleted(object sender, DragCompletedEventArgs e)
{
if (drag == false)
if (drag == false)
{
Interlocked.Decrement(ref DiagramViewModel.DoCommandManager.BeginDo);
return;
return;
}
if (designerItems != null)
@@ -92,6 +104,16 @@ namespace AIStudio.Wpf.DiagramDesigner.Controls
Dictionary<DesignerItemViewModelBase, Tuple<PointBase, PointBase>> infos =
designerItems.OfType<DesignerItemViewModelBase>().ToDictionary(p => p,
p => new Tuple<PointBase, PointBase>(p.GetOldValue<PointBase>(nameof(p.TopLeft)), p.TopLeft));
//部分连接点可以移动
Dictionary<ConnectionViewModel, Tuple<Tuple<PointBase?, PointBase?>, Tuple<PointBase?, PointBase?>>> conncetorinfos =
designerItems.OfType<ConnectionViewModel>().ToDictionary(p => p,
p => new Tuple<Tuple<PointBase?, PointBase?>, Tuple<PointBase?, PointBase?>>(
new Tuple<PointBase?, PointBase?>(p.SourceConnectorInfoPart?.GetOldValue<PointBase>(nameof(p.SourceConnectorInfoPart.Position)),
p.SinkConnectorInfoPart?.GetOldValue<PointBase>(nameof(p.SinkConnectorInfoPart.Position))),
new Tuple<PointBase?, PointBase?>(p.SourceConnectorInfoPart?.Position,
p.SinkConnectorInfoPart?.Position)));
Interlocked.Decrement(ref DiagramViewModel.DoCommandManager.BeginDo);
DiagramViewModel.DoCommandManager.DoNewCommand(this.ToString(),
() => {
@@ -99,12 +121,20 @@ namespace AIStudio.Wpf.DiagramDesigner.Controls
{
info.Key.TopLeft = info.Value.Item2;
}
foreach (var info in conncetorinfos)
{
info.Key.SetPartPostion(info.Value.Item2.Item1, info.Value.Item2.Item2);
}
},
() => {
foreach (var info in infos)
{
info.Key.TopLeft = info.Value.Item1;
}
foreach (var info in conncetorinfos)
{
info.Key.SetPartPostion(info.Value.Item1.Item1, info.Value.Item1.Item2);
}
});
e.Handled = true;
}
@@ -121,6 +151,22 @@ namespace AIStudio.Wpf.DiagramDesigner.Controls
item.Top += e.VerticalChange;
}
//部分连接点可以移动
foreach (ConnectionViewModel item in designerItems.OfType<ConnectionViewModel>())
{
PointBase? sourcePoint = null;
PointBase? sinkPoint = null;
if (item.SourceConnectorInfoPart != null)
{
sourcePoint = new PointBase(item.SourceConnectorInfoPart.Position.X + e.HorizontalChange, item.SourceConnectorInfoPart.Position.Y + e.VerticalChange);
}
if (item.SinkConnectorInfoPart != null)
{
sinkPoint = new PointBase(item.SinkConnectorInfoPart.Position.X + e.HorizontalChange, item.SinkConnectorInfoPart.Position.Y + e.VerticalChange);
}
item.SetPartPostion(sourcePoint, sinkPoint);
}
e.Handled = true;
}
}

View File

@@ -370,13 +370,13 @@ namespace AIStudio.Wpf.DiagramDesigner
/// <summary>
/// Tries to locate a given item within the visual tree,
/// starting with the dependency object at a given position.
/// starting with the dependency object at a given _position.
/// </summary>
/// <typeparam name="T">The type of the element to be found
/// on the visual tree of the element at the given location.</typeparam>
/// <param name="reference">The main element which is used to perform
/// hit testing.</param>
/// <param name="point">The position to be evaluated on the origin.</param>
/// <param name="point">The _position to be evaluated on the origin.</param>
public static T TryFindFromPoint<T>(UIElement reference, Point point)
where T : DependencyObject
{

View File

@@ -441,13 +441,13 @@ namespace AIStudio.Wpf.DiagramDesigner.Helpers
/// <summary>
/// Tries to locate a given item within the visual tree,
/// starting with the dependency object at a given position.
/// starting with the dependency object at a given _position.
/// </summary>
/// <typeparam name="T">The type of the element to be found
/// on the visual tree of the element at the given location.</typeparam>
/// <param name="reference">The main element which is used to perform
/// hit testing.</param>
/// <param name="point">The position to be evaluated on the origin.</param>
/// <param name="point">The _position to be evaluated on the origin.</param>
public static T TryFindFromPoint<T>(UIElement reference, Point point)
where T : DependencyObject
{

View File

@@ -23,16 +23,16 @@ namespace AIStudio.Wpf.DiagramDesigner
}
public ConnectionItem(ConnectionViewModel viewmodel) : base(viewmodel)
public ConnectionItem(ConnectionViewModel viewmodel) : base(viewmodel)//Todo,半连接线也可序列化
{
this.SourceId = viewmodel.SourceConnectorInfo.DataItem.Id;
this.SourceOrientation = viewmodel.SourceConnectorInfo.Orientation;
this.SourceType = viewmodel.SourceConnectorInfo.DataItem.GetType();
this.SourceTypeName = viewmodel.SourceConnectorInfo.DataItem.GetType().FullName;
this.SourceXRatio = viewmodel.SourceConnectorInfo.GetXRatioFromConnector();
this.SourceYRatio = viewmodel.SourceConnectorInfo.GetYRatioFromConnector();
this.SourceInnerPoint = viewmodel.SourceConnectorInfo.IsInnerPoint;
this.SourceIsPortless = viewmodel.SourceConnectorInfo.IsPortless;
this.SourceId = viewmodel.SourceConnectorInfoFully.DataItem.Id;
this.SourceOrientation = viewmodel.SourceConnectorInfoFully.Orientation;
this.SourceType = viewmodel.SourceConnectorInfoFully.DataItem.GetType();
this.SourceTypeName = viewmodel.SourceConnectorInfoFully.DataItem.GetType().FullName;
this.SourceXRatio = viewmodel.SourceConnectorInfoFully.GetXRatioFromConnector();
this.SourceYRatio = viewmodel.SourceConnectorInfoFully.GetYRatioFromConnector();
this.SourceInnerPoint = viewmodel.SourceConnectorInfoFully.IsInnerPoint;
this.SourceIsPortless = viewmodel.SourceConnectorInfoFully.IsPortless;
this.SinkId = viewmodel.SinkConnectorInfoFully.DataItem.Id;
this.SinkOrientation = viewmodel.SinkConnectorInfoFully.Orientation;
@@ -41,7 +41,7 @@ namespace AIStudio.Wpf.DiagramDesigner
this.SinkXRatio = viewmodel.SinkConnectorInfoFully.GetXRatioFromConnector();
this.SinkYRatio = viewmodel.SinkConnectorInfoFully.GetYRatioFromConnector();
this.SinkInnerPoint = viewmodel.SinkConnectorInfoFully.IsInnerPoint;
this.SinkIsPortless = viewmodel.SourceConnectorInfo.IsPortless;
this.SinkIsPortless = viewmodel.SourceConnectorInfoFully.IsPortless;
this.RouterMode = viewmodel.RouterMode;
this.PathMode = viewmodel.PathMode;

View File

@@ -33,8 +33,8 @@ namespace AIStudio.Wpf.DiagramDesigner
private static PointBase[] GetRouteWithMiddlePoints(IDiagramViewModel _, ConnectionViewModel link, PointBase[] route)
{
var middle = GetMiddlePoints(
link.SourceConnectorInfo.MiddlePosition,
link.SourceConnectorInfo.Orientation,
link.SourceConnectorInfoFully.MiddlePosition,
link.SourceConnectorInfoFully.Orientation,
link.SinkConnectorInfo.MiddlePosition,
link.IsFullConnection ? link.SinkConnectorInfoFully.Orientation : (link.SinkConnectorInfo.MiddlePosition.Y >= link.SourceConnectorInfo.MiddlePosition.Y ? ConnectorOrientation.Top : ConnectorOrientation.Bottom),
_.GridCellSize,

View File

@@ -37,10 +37,10 @@ namespace AIStudio.Wpf.DiagramDesigner
private static PointBase[] GetRouteWithFullConnectionLine(IDiagramViewModel _, ConnectionViewModel link, PointBase[] route)
{
var sourceInnerPoint = link.SourceConnectorInfo.IsInnerPoint;
PointBase sourcePoint = link.SourceConnectorInfo.MiddlePosition;
var sourceInnerPoint = link.SourceConnectorInfoFully.IsInnerPoint;
PointBase sourcePoint = link.SourceConnectorInfoFully.MiddlePosition;
PointBase sinkPoint = link.SinkConnectorInfo.MiddlePosition;
ConnectorOrientation sourceOrientation = link.SourceConnectorInfo.Orientation;
ConnectorOrientation sourceOrientation = link.SourceConnectorInfoFully.Orientation;
ConnectorOrientation sinkOrientation = link.SinkConnectorInfoFully.Orientation;
List<PointBase> linePoints = new List<PointBase>();
@@ -242,7 +242,7 @@ namespace AIStudio.Wpf.DiagramDesigner
private static PointBase[] GetRouteWithPartConnectionLine(IDiagramViewModel diagramViewModel, ConnectionViewModel link, PointBase[] route)
{
var sourceInnerPoint = link.SourceConnectorInfo.IsInnerPoint;
var sourceInnerPoint = link.SourceConnectorInfoFully?.IsInnerPoint ?? false;
PointBase sourcePoint = link.SourceConnectorInfo.MiddlePosition;
PointBase sinkPoint = link.SinkConnectorInfo.MiddlePosition;
ConnectorOrientation sourceOrientation = link.SourceConnectorInfo.Orientation;
@@ -301,8 +301,8 @@ namespace AIStudio.Wpf.DiagramDesigner
linePoints = OptimizeLinePoints(linePoints, new RectangleBase[] { rectSource }, sourceOrientation, preferredOrientation);
else
linePoints = OptimizeLinePoints(linePoints, new RectangleBase[] { rectSource }, sourceOrientation, GetOpositeOrientation(sourceOrientation));
linePoints.Insert(0, sourcePoint);
linePoints.Insert(0, sourcePoint);
return linePoints.ToArray();
}

View File

@@ -70,7 +70,7 @@ namespace AIStudio.Wpf.DiagramDesigner
var cX = (route[0].X + route[1].X) / 2;
var cY = (route[0].Y + route[1].Y) / 2;
var sourceOrientation = link.SourceConnectorInfo?.Orientation;
var sourceOrientation = link.SourceConnectorInfo.Orientation;
if (sourceOrientation == ConnectorOrientation.None)//按照线条的四象限来处理。
{
var slope = (route[1].Y - route[0].Y) / (route[1].X - route[0].X);

View File

@@ -18,10 +18,10 @@ namespace AIStudio.Wpf.DiagramDesigner
if (link.IsFullConnection == false)
return Normal(_, link);
double x2 = link.SourceConnectorInfo.MiddlePosition.X < link.SinkConnectorInfoFully.MiddlePosition.X ?
link.SinkConnectorInfoFully.MiddlePosition.X - Math.Abs(link.SourceConnectorInfo.MiddlePosition.Y - link.SinkConnectorInfoFully.MiddlePosition.Y)
: link.SinkConnectorInfoFully.MiddlePosition.X + Math.Abs(link.SourceConnectorInfo.MiddlePosition.Y - link.SinkConnectorInfoFully.MiddlePosition.Y);
double y2 = link.SourceConnectorInfo.MiddlePosition.Y;
double x2 = link.SourceConnectorInfoFully.MiddlePosition.X < link.SinkConnectorInfoFully.MiddlePosition.X ?
link.SinkConnectorInfoFully.MiddlePosition.X - Math.Abs(link.SourceConnectorInfoFully.MiddlePosition.Y - link.SinkConnectorInfoFully.MiddlePosition.Y)
: link.SinkConnectorInfoFully.MiddlePosition.X + Math.Abs(link.SourceConnectorInfoFully.MiddlePosition.Y - link.SinkConnectorInfoFully.MiddlePosition.Y);
double y2 = link.SourceConnectorInfoFully.MiddlePosition.Y;
return new PointBase[] { new PointBase(x2, y2) };

View File

@@ -23,13 +23,13 @@ namespace AIStudio.Wpf.DiagramDesigner
var spots = new List<PointBase>();
var verticals = new List<double>();
var horizontals = new List<double>();
var sideA = link.SourceConnectorInfo.Orientation;
var sideA = link.SourceConnectorInfoFully.Orientation;
var sideAVertical = IsVerticalSide(sideA);
var sideB = link.SinkConnectorInfo.Orientation;
var sideBVertical = IsVerticalSide(sideB);
var originA = GetPortPositionBasedOnAlignment(link.SourceConnectorInfo);
var originA = GetPortPositionBasedOnAlignment(link.SourceConnectorInfoFully);
var originB = GetPortPositionBasedOnAlignment(link.SinkConnectorInfo);
var shapeA = link.SourceConnectorInfo.DataItem.GetBounds(includePorts: true);
var shapeA = link.SourceConnectorInfoFully.DataItem.GetBounds(includePorts: true);
var shapeB = link.SinkConnectorInfoFully.DataItem.GetBounds(includePorts: true);
var inflatedA = shapeA.InflateRectangle(shapeMargin, shapeMargin);
var inflatedB = shapeB.InflateRectangle(shapeMargin, shapeMargin);

View File

@@ -537,7 +537,7 @@
<dd:LineControl x:Name="line"/>
<!-- PART_DragThumb -->
<c:DragThumb x:Name="PART_DragThumb" Margin="8"
<c:DragThumb x:Name="PART_DragThumb" Margin="{Binding DragThumbMargin}"
Cursor="SizeAll" >
<c:DragThumb.InputBindings>
<MouseBinding MouseAction="LeftDoubleClick" Command="{Binding EditCommand}" CommandParameter="{Binding }" />

View File

@@ -71,36 +71,6 @@
</Path>
</Grid>
<!--<Grid Canvas.Left="{Binding StartPoint.X}"
Canvas.Top="{Binding StartPoint.Y}"
Width="{Binding SourceConnectorInfo.ConnectorWidth}"
Height="{Binding SourceConnectorInfo.ConnectorHeight}"
UseLayoutRounding="True"
SnapsToDevicePixels="True"
Visibility="{Binding IsSelected,Converter={StaticResource BooleanToVisibilityConverter}}">
<Ellipse Stroke="DarkRed"
StrokeThickness="1"
Margin="-2.5"/>
<Rectangle
Fill="DarkRed"
Margin="1"/>
</Grid>
<Grid Canvas.Left="{Binding EndPoint.X}"
Canvas.Top="{Binding EndPoint.Y}"
Width="{Binding SinkConnectorInfo.ConnectorWidth}"
Height="{Binding SinkConnectorInfo.ConnectorHeight}"
UseLayoutRounding="True"
SnapsToDevicePixels="True"
Visibility="{Binding IsSelected,Converter={StaticResource BooleanToVisibilityConverter}}">
<Ellipse Stroke="DarkRed"
StrokeThickness="1"
Margin="-2.5"/>
<Ellipse
Fill="DarkRed"
Margin="1"/>
</Grid>-->
<Path x:Name="ball"
Stretch="Fill"
Data="{Binding AnimationViewModel.AnimationPath.Path}"

View File

@@ -65,6 +65,7 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
//界面还未使用到
private bool _vectorRouterModeSelected;
public bool LineRouterModeSelected
{

View File

@@ -12,21 +12,43 @@ namespace AIStudio.Wpf.DiagramDesigner
void ResetDrawMode();
CursorMode CursorMode
{
get; set;
}
DrawMode LineDrawMode
{
bool CursorDrawModeSelected
{
get; set;
}
CursorMode CursorMode
{
get; set;
}
bool LineDrawModeSelected
{
get; set;
}
DrawMode LineDrawMode
{
get; set;
}
bool TextDrawModeSelected
{
get; set;
}
DrawMode TextDrawMode
{
get; set;
}
//界面还未使用到
RouterMode LineRouterMode
{
get; set;
}
bool ShapeDrawModeSelected
{
get; set;
}
DrawMode ShapeDrawMode
{
get; set;
}
bool EnableSnapping
{
get; set;

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Input;
@@ -23,19 +24,19 @@ namespace AIStudio.Wpf.DiagramDesigner
}
public ConnectionViewModel(FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo, DrawMode drawMode = DrawMode.ConnectingLineSmooth, RouterMode routerMode = AIStudio.Wpf.DiagramDesigner.RouterMode.RouterNormal) : this(null, sourceConnectorInfo, sinkConnectorInfo, drawMode, routerMode)
public ConnectionViewModel(ConnectorInfoBase sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo, DrawMode drawMode = DrawMode.ConnectingLineSmooth, RouterMode routerMode = AIStudio.Wpf.DiagramDesigner.RouterMode.RouterNormal) : this(null, sourceConnectorInfo, sinkConnectorInfo, drawMode, routerMode)
{
}
public ConnectionViewModel(IDiagramViewModel root, FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo, DrawMode drawMode = DrawMode.ConnectingLineSmooth, RouterMode routerMode = AIStudio.Wpf.DiagramDesigner.RouterMode.RouterNormal) : base(root)
public ConnectionViewModel(IDiagramViewModel root, ConnectorInfoBase sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo, DrawMode drawMode = DrawMode.ConnectingLineSmooth, RouterMode routerMode = AIStudio.Wpf.DiagramDesigner.RouterMode.RouterNormal) : base(root)
{
_pathMode = drawMode.ToString();
_routerMode = routerMode.ToString();
Init(root, sourceConnectorInfo, sinkConnectorInfo);
}
public ConnectionViewModel(IDiagramViewModel root, FullyCreatedConnectorInfo sourceConnectorInfo, FullyCreatedConnectorInfo sinkConnectorInfo, ConnectionItem designer) : base(root, designer)
public ConnectionViewModel(IDiagramViewModel root, ConnectorInfoBase sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo, ConnectionItem designer) : base(root, designer)
{
_pathMode = designer.PathMode;
_routerMode = designer.RouterMode;
@@ -50,13 +51,13 @@ namespace AIStudio.Wpf.DiagramDesigner
return connection;
}
else
else//Todo,半连接线也可序列化
{
return null;
}
}
protected virtual void Init(IDiagramViewModel root, FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo)
protected virtual void Init(IDiagramViewModel root, ConnectorInfoBase sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo)
{
IsLoaded = false;
this.Root = root ?? sourceConnectorInfo.Root;
@@ -244,6 +245,19 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
private Thickness _dragThumbMargin;
public Thickness DragThumbMargin
{
get
{
return _dragThumbMargin;
}
private set
{
SetProperty(ref _dragThumbMargin, value);
}
}
private RectangleBase _area;
public RectangleBase Area
{
@@ -357,8 +371,8 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
private FullyCreatedConnectorInfo _sourceConnectorInfo;
public FullyCreatedConnectorInfo SourceConnectorInfo
private ConnectorInfoBase _sourceConnectorInfo;
public ConnectorInfoBase SourceConnectorInfo
{
get
{
@@ -367,6 +381,23 @@ namespace AIStudio.Wpf.DiagramDesigner
set
{
SetProperty(ref _sourceConnectorInfo, value);
}
}
public FullyCreatedConnectorInfo SourceConnectorInfoFully
{
get
{
return SourceConnectorInfo as FullyCreatedConnectorInfo;
}
}
public PartCreatedConnectorInfo SourceConnectorInfoPart
{
get
{
return SourceConnectorInfo as PartCreatedConnectorInfo;
}
}
@@ -412,10 +443,11 @@ namespace AIStudio.Wpf.DiagramDesigner
{
get
{
return SinkConnectorInfoFully != null;
return SourceConnectorInfoFully != null && SinkConnectorInfoFully != null;
}
}
public void RaiseFullConnection()
{
RaisePropertyChanged(nameof(IsFullConnection));
@@ -426,7 +458,7 @@ namespace AIStudio.Wpf.DiagramDesigner
public double OrthogonalShapeMargin { get; set; } = 10;
public double OrthogonalGlobalBoundsMargin { get; set; } = 50;
public bool IsPortless => SourceConnectorInfo.IsPortless || SinkConnectorInfoFully?.IsPortless == true;
public bool IsPortless => SourceConnectorInfoFully?.IsPortless == true || SinkConnectorInfoFully?.IsPortless == true;
#endregion
#region
@@ -476,18 +508,29 @@ namespace AIStudio.Wpf.DiagramDesigner
case nameof(SourceConnectorInfo):
if (SourceConnectorInfo != null)
{
SourceA = PointHelper.GetPointForConnector(SourceConnectorInfo);
SourceConnectorInfo.DataItem.PropertyChanged += new WeakINPCEventHandler(Item_PropertyChanged).Handler;
SourceA = SourceConnectorInfo.Position;
if (SourceConnectorInfoFully != null)
{
SourceConnectorInfoFully.DataItem.PropertyChanged += new WeakINPCEventHandler(Item_PropertyChanged).Handler;
}
//else if (SourceConnectorInfoPart != null)
//{
// SourceConnectorInfoPart.PropertyChanged += new WeakINPCEventHandler(Item_PropertyChanged).Handler;
//}
}
break;
case nameof(SinkConnectorInfo):
if (SinkConnectorInfo != null)
{
SourceB = SinkConnectorInfo.Position;
if (IsFullConnection)
if (SinkConnectorInfoFully != null)
{
SinkConnectorInfoFully.DataItem.PropertyChanged += new WeakINPCEventHandler(Item_PropertyChanged).Handler;
}
//else if (SinkConnectorInfoPart != null)
//{
// SinkConnectorInfoPart.PropertyChanged += new WeakINPCEventHandler(Item_PropertyChanged).Handler;
//}
}
break;
case nameof(IsSelected):
@@ -513,7 +556,7 @@ namespace AIStudio.Wpf.DiagramDesigner
if (e.PropertyName == nameof(ShapeViewModel.SourceMarker) ||
e.PropertyName == nameof(ShapeViewModel.SinkMarker))
{
UpdatePathGeneratorResult();
UpdateArea();
}
}
else if (sender is DesignerItemViewModelBase)
@@ -527,12 +570,12 @@ namespace AIStudio.Wpf.DiagramDesigner
if (IsFullConnection)
{
//减少触发一次画线
SourceA = PointHelper.GetPointForConnector(this.SourceConnectorInfo);
SourceA = PointHelper.GetPointForConnector(this.SourceConnectorInfoFully);
SourceB = PointHelper.GetPointForConnector(this.SinkConnectorInfoFully);
}
else
{
SourceA = PointHelper.GetPointForConnector(this.SourceConnectorInfo);
SourceA = SourceConnectorInfo.MiddlePosition;
}
break;
}
@@ -570,6 +613,21 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
}
//else if (sender is PartCreatedConnectorInfo)
//{
// if (e.PropertyName == "Position")
// {
// if (sender == SourceConnectorInfoPart)
// {
// SourceA = SourceConnectorInfo.Position;
// }
// else if (sender == SinkConnectorInfoPart)
// {
// SourceB = SinkConnectorInfo.Position;
// }
// UpdatePathGeneratorResult();
// }
//}
else if (sender is ColorViewModel)
{
@@ -613,7 +671,7 @@ namespace AIStudio.Wpf.DiagramDesigner
StartAngle = PathGeneratorResult.SourceMarkerAngle;
EndAngle = PathGeneratorResult.TargetMarkerAngle;
//StartPoint = new PointBase(source.Value.X - Area.Left - SourceConnectorInfo.ConnectorWidth / 2, source.Value.Y - Area.Top - SourceConnectorInfo.ConnectorHeight / 2) ;
//StartPoint = new PointBase(source.Value.X - Area.Left - SourceConnectorInfoFully.ConnectorWidth / 2, source.Value.Y - Area.Top - SourceConnectorInfoFully.ConnectorHeight / 2) ;
//EndPoint = new PointBase(target.Value.X - Area.Left - SinkConnectorInfo.ConnectorWidth / 2 , target.Value.Y - Area.Top - SinkConnectorInfo.ConnectorHeight / 2 );
StartPoint = new PointBase(source.Value.X - Area.Left , source.Value.Y - Area.Top );
@@ -650,6 +708,18 @@ namespace AIStudio.Wpf.DiagramDesigner
{
label.UpdatePosition(paths);
}
double marginwidth = 0;
double marginheight = 0;
if (Area.Width > SourceConnectorInfo.ConnectorWidth + SinkConnectorInfo.ConnectorWidth)
{
marginwidth = (SourceConnectorInfo.ConnectorWidth + SinkConnectorInfo.ConnectorWidth) / 2;
}
if (Area.Height > SourceConnectorInfo.ConnectorHeight + SinkConnectorInfo.ConnectorHeight)
{
marginheight = (SourceConnectorInfo.ConnectorHeight + SinkConnectorInfo.ConnectorHeight) / 2;
}
DragThumbMargin = new Thickness(marginwidth, marginheight, marginwidth, marginheight);
}
private void DeleteConnection(object args)
@@ -665,17 +735,17 @@ namespace AIStudio.Wpf.DiagramDesigner
{
if (IsPortless) // Portless
{
if (SourceConnectorInfo.DataItem == null || (IsFullConnection && SinkConnectorInfoFully.DataItem == null))
if (SourceConnectorInfoFully?.DataItem == null || SinkConnectorInfoFully?.DataItem == null)
return (null, null);
var sourceCenter = SourceConnectorInfo.IsPortless ? SourceConnectorInfo.DataItem.MiddlePosition : SourceConnectorInfo.MiddlePosition;
var sourceCenter = SourceConnectorInfoFully.IsPortless ? SourceConnectorInfoFully.DataItem.MiddlePosition : SourceConnectorInfoFully.MiddlePosition;
var targetCenter = SinkConnectorInfoFully?.IsPortless == true ? SinkConnectorInfoFully?.DataItem?.MiddlePosition ?? OnGoingPosition : SinkConnectorInfoFully?.MiddlePosition ?? OnGoingPosition;
var firstPt = route.Length > 0 ? route[0] : targetCenter;
var secondPt = route.Length > 0 ? route[0] : sourceCenter;
var sourceLine = new LineBase(firstPt, sourceCenter);
var targetLine = new LineBase(secondPt, targetCenter);
var sourceIntersections = SourceConnectorInfo.DataItem.GetShape().GetIntersectionsWithLine(sourceLine);
var targetIntersections = SinkConnectorInfoFully.DataItem.GetShape()?.GetIntersectionsWithLine(targetLine) ?? new PointBase[] { OnGoingPosition };
var sourceIntersections = SourceConnectorInfoFully.DataItem.GetShape().GetIntersectionsWithLine(sourceLine);
var targetIntersections = SinkConnectorInfoFully?.DataItem?.GetShape()?.GetIntersectionsWithLine(targetLine) ?? new PointBase[] { OnGoingPosition };
var sourceIntersection = GetClosestPointTo(sourceIntersections, firstPt);
var targetIntersection = GetClosestPointTo(targetIntersections, secondPt);
@@ -683,7 +753,7 @@ namespace AIStudio.Wpf.DiagramDesigner
}
else
{
var source = SourceConnectorInfo.MiddlePosition;//GetPortPositionBasedOnAlignment(SourceConnectorInfo, ColorViewModel.LeftArrowSizeStyle);
var source = SourceConnectorInfo.MiddlePosition;//GetPortPositionBasedOnAlignment(SourceConnectorInfoFully, ColorViewModel.LeftArrowSizeStyle);
var target = SinkConnectorInfo.MiddlePosition;// GetPortPositionBasedOnAlignment(SinkConnectorInfoFully, ColorViewModel.RightArrowSizeStyle);
return (source, target);
}
@@ -749,6 +819,22 @@ namespace AIStudio.Wpf.DiagramDesigner
SinkConnectorInfo = port;
}
public void SetPartPostion(PointBase? sourcePoint, PointBase? sinkPoint)
{
if (sourcePoint != null)
{
SourceConnectorInfoPart.Position = sourcePoint.Value;
_sourceA = SourceConnectorInfoPart.Position;
}
if (sinkPoint != null)
{
SinkConnectorInfoPart.Position = sinkPoint.Value;
_sourceB = SinkConnectorInfoPart.Position;
}
UpdateArea();
}
public void UpdateConnectionMode(FullyCreatedConnectorInfo source, FullyCreatedConnectorInfo sink, string pathmode, string routermode)
{
//先置空,避免更新

View File

@@ -65,7 +65,7 @@ namespace AIStudio.Wpf.DiagramDesigner
#region
public virtual PointBase Position
{
get;
get;set;
}
public virtual PointBase MiddlePosition

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows;
@@ -16,20 +17,23 @@ namespace AIStudio.Wpf.DiagramDesigner
public PartCreatedConnectorInfo(IDiagramViewModel root, double X, double Y) : base(root, ConnectorOrientation.None)
{
this.position = new PointBase(X, Y);
this._position = new PointBase(X, Y);
}
private PointBase position;
private PointBase _position;
public override PointBase Position
{
get
{
return position;
return _position;
}
set
{
SetProperty(ref _position, value);
}
}
}
}

View File

@@ -1636,7 +1636,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{
if (!selectedConnections.Contains(connection))
{
DesignerItemViewModelBase sourceItem = selectedDesignerItems.FirstOrDefault(p => p.Id == connection.SourceConnectorInfo.DataItem.Id);
DesignerItemViewModelBase sourceItem = selectedDesignerItems.FirstOrDefault(p => p.Id == connection.SourceConnectorInfoFully?.DataItem.Id);
DesignerItemViewModelBase sinkItem = selectedDesignerItems.FirstOrDefault(p => p.Id == connection.SinkConnectorInfoFully?.DataItem?.Id);
if (sourceItem != null && sinkItem != null && BelongToSameGroup(sourceItem, sinkItem))
{

View File

@@ -254,9 +254,9 @@ namespace AIStudio.Wpf.DiagramDesigner
continue;
}
if (connector.SourceConnectorInfo.DataItem is LogicalGateItemViewModelBase sourceItem)
if (connector.SourceConnectorInfoFully?.DataItem is LogicalGateItemViewModelBase sourceItem)
{
var output = (connector.SourceConnectorInfo as LogicalConnectorInfo);
var output = (connector.SourceConnectorInfoFully as LogicalConnectorInfo);
if (EnableInputValue(connector, input.Value, output))
{
@@ -266,14 +266,14 @@ namespace AIStudio.Wpf.DiagramDesigner
input.Value.ConnectorValue = output.ConnectorValue;
input.Value.ConnectorString = output.ConnectorString;
input.Value.ColorViewModel.FillColor.Color = connector.SourceConnectorInfo.ColorViewModel.FillColor.Color;
input.Value.ColorViewModel.FillColor.Color = connector.SourceConnectorInfoFully.ColorViewModel.FillColor.Color;
if (LogicalType == LogicalType.Output)
{
input.Value.ConnectorValueType = (connector.SourceConnectorInfo as LogicalConnectorInfo).ConnectorValueType;
input.Value.ConnectorValueType = (connector.SourceConnectorInfoFully as LogicalConnectorInfo).ConnectorValueType;
}
else if (LogicalType == LogicalType.NOT)
{
input.Value.ConnectorValueType = ((connector.SourceConnectorInfo as LogicalConnectorInfo).ConnectorValueType == ConnectorValueType.Bool) ? ConnectorValueType.Bool : ConnectorValueType.Int;
input.Value.ConnectorValueType = ((connector.SourceConnectorInfoFully as LogicalConnectorInfo).ConnectorValueType == ConnectorValueType.Bool) ? ConnectorValueType.Bool : ConnectorValueType.Int;
}
sourceItem.ClearOutputValue(connector, output);
@@ -347,7 +347,7 @@ namespace AIStudio.Wpf.DiagramDesigner
protected ConnectionViewModel GetSinkItem(FullyCreatedConnectorInfo sourceConnector)
{
return Root?.Items.OfType<ConnectionViewModel>().FirstOrDefault(p => p.SourceConnectorInfo == sourceConnector);
return Root?.Items.OfType<ConnectionViewModel>().FirstOrDefault(p => p.SourceConnectorInfoFully == sourceConnector);
}
}
}