mirror of
https://gitee.com/akwkevin/aistudio.-wpf.-diagram
synced 2026-03-02 15:50:51 +08:00
IsPortless 画线
This commit is contained in:
@@ -56,7 +56,7 @@ namespace AIStudio.Wpf.DiagramDesigner.Demo
|
||||
Children=new List<MenuItemViewModel>
|
||||
{
|
||||
new MenuItemViewModel(){Title = "Svg"},
|
||||
new MenuItemViewModel(){Title = "Portless"},
|
||||
new MenuItemViewModel(){Title = "PortlessLinks"},
|
||||
}
|
||||
},
|
||||
new MenuItemViewModel(){Title = "Links",
|
||||
@@ -87,13 +87,13 @@ namespace AIStudio.Wpf.DiagramDesigner.Demo
|
||||
},
|
||||
new MenuItemViewModel(){Title = "Algorithms",
|
||||
Children=new List<MenuItemViewModel>
|
||||
{
|
||||
|
||||
{
|
||||
new MenuItemViewModel(){Title = "ReconnectLinksToClosestPorts"},
|
||||
}
|
||||
},
|
||||
new MenuItemViewModel(){Title = "Animations",
|
||||
Children=new List<MenuItemViewModel>
|
||||
{
|
||||
{
|
||||
new MenuItemViewModel(){Title = "PathAnimation"},
|
||||
new MenuItemViewModel(){Title = "LineAnimation"},
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
|
||||
namespace AIStudio.Wpf.DiagramDesigner.Demo.ViewModels
|
||||
{
|
||||
class PortlessLinksViewModel : BaseViewModel
|
||||
{
|
||||
public PortlessLinksViewModel()
|
||||
{
|
||||
Title = "Portless Links";
|
||||
Info = "Starting from 2.0, you can create links between nodes directly! " +
|
||||
"All you need to specify is the shape of your nodes in order to calculate the connection points.";
|
||||
|
||||
DiagramViewModel = new DiagramViewModel();
|
||||
DiagramViewModel.PageSizeType = PageSizeType.Custom;
|
||||
DiagramViewModel.PageSize = new Size(double.NaN, double.NaN);
|
||||
DiagramViewModel.ColorViewModel = new ColorViewModel();
|
||||
DiagramViewModel.ColorViewModel.FillColor.Color = System.Windows.Media.Colors.Orange;
|
||||
|
||||
DefaultDesignerItemViewModel node1 = new DefaultDesignerItemViewModel(DiagramViewModel) { Left = 50, Top = 50, Text = "1" };
|
||||
DiagramViewModel.DirectAddItemCommand.Execute(node1);
|
||||
|
||||
DefaultDesignerItemViewModel node2 = new DefaultDesignerItemViewModel(DiagramViewModel) { Left = 300, Top = 50, Text = "2" };
|
||||
DiagramViewModel.DirectAddItemCommand.Execute(node2);
|
||||
|
||||
DefaultDesignerItemViewModel node3 = new DefaultDesignerItemViewModel(DiagramViewModel) { Left = 300, Top = 300, Text = "3" };
|
||||
DiagramViewModel.DirectAddItemCommand.Execute(node3);
|
||||
|
||||
DefaultDesignerItemViewModel node4 = new DefaultDesignerItemViewModel(DiagramViewModel) { Left = 50, Top = 300, Text = "4" };
|
||||
DiagramViewModel.DirectAddItemCommand.Execute(node4);
|
||||
|
||||
ConnectionViewModel connector1 = new ConnectionViewModel(DiagramViewModel, node1.PortlessConnector, node2.PortlessConnector, DrawMode.ConnectingLineSmooth, RouterMode.RouterNormal);
|
||||
DiagramViewModel.DirectAddItemCommand.Execute(connector1);
|
||||
|
||||
ConnectionViewModel connector2 = new ConnectionViewModel(DiagramViewModel, node2.PortlessConnector, node3.RightConnector, DrawMode.ConnectingLineSmooth, RouterMode.RouterNormal);
|
||||
DiagramViewModel.DirectAddItemCommand.Execute(connector2);
|
||||
|
||||
ConnectionViewModel connector3 = new ConnectionViewModel(DiagramViewModel, node3.LeftConnector, node4.PortlessConnector, DrawMode.ConnectingLineSmooth, RouterMode.RouterNormal);
|
||||
DiagramViewModel.DirectAddItemCommand.Execute(connector3);
|
||||
|
||||
DiagramViewModel.ClearSelectedItemsCommand.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,18 @@
|
||||
xmlns:controls="clr-namespace:AIStudio.Wpf.DiagramDesigner.Demo.Controls"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<DataTemplate DataType="{x:Type dd:GroupDesignerItemViewModel}">
|
||||
<Grid IsHitTestVisible="{Binding IsHitTestVisible}">
|
||||
<TextBlock Text="Group"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid>
|
||||
<!-- Diagram Control -->
|
||||
<dd:DiagramControl x:Name="diagram" DataContext="{Binding DiagramViewModel}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
|
||||
<dd:DiagramControl x:Name="diagram" DataContext="{Binding DiagramViewModel}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
|
||||
</dd:DiagramControl>
|
||||
|
||||
<controls:TitleControl/>
|
||||
</Grid>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<UserControl x:Class="AIStudio.Wpf.DiagramDesigner.Demo.Views.PortlessLinksView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:dd="https://gitee.com/akwkevin/aistudio.-wpf.-diagram"
|
||||
xmlns:controls="clr-namespace:AIStudio.Wpf.DiagramDesigner.Demo.Controls"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<!-- Diagram Control -->
|
||||
<dd:DiagramControl x:Name="diagram" DataContext="{Binding DiagramViewModel}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
|
||||
|
||||
<controls:TitleControl/>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace AIStudio.Wpf.DiagramDesigner.Demo.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// PortlessLinksView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class PortlessLinksView : UserControl
|
||||
{
|
||||
public PortlessLinksView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
SmallChange="0.1"
|
||||
LargeChange="0.1"
|
||||
Width="200"
|
||||
HorizontalAlignment="Right"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"/>
|
||||
|
||||
<controls:TitleControl/>
|
||||
|
||||
@@ -17,22 +17,40 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
point = new PointBase(connector.DataItem.Left + connector.DataItem.ItemWidth * connector.XRatio - connector.ConnectorWidth / 2,
|
||||
connector.DataItem.Top + connector.DataItem.ItemHeight * connector.YRatio - connector.ConnectorHeight / 2);
|
||||
}
|
||||
else if (connector.IsPortless)
|
||||
{
|
||||
point = connector.DataItem?.GetBounds().Center?? connector.MiddlePosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
switch (connector.Orientation)
|
||||
{
|
||||
case ConnectorOrientation.Left:
|
||||
point = new PointBase(connector.DataItem.Left - connector.ConnectorWidth / 2, connector.DataItem.Top + (connector.DataItem.ItemHeight / 2) - connector.ConnectorHeight / 2);
|
||||
break;
|
||||
case ConnectorOrientation.TopLeft:
|
||||
point = new PointBase(connector.DataItem.Left - connector.ConnectorWidth / 2, connector.DataItem.Top - connector.ConnectorHeight / 2);
|
||||
break;
|
||||
case ConnectorOrientation.Top:
|
||||
point = new PointBase(connector.DataItem.Left + (connector.DataItem.ItemWidth / 2) - connector.ConnectorWidth / 2, connector.DataItem.Top - connector.ConnectorHeight / 2);
|
||||
break;
|
||||
case ConnectorOrientation.Bottom:
|
||||
point = new PointBase(connector.DataItem.Left + (connector.DataItem.ItemWidth / 2) - connector.ConnectorWidth / 2, (connector.DataItem.Top + connector.DataItem.ItemHeight) - connector.ConnectorHeight / 2);
|
||||
case ConnectorOrientation.TopRight:
|
||||
point = new PointBase(connector.DataItem.Left + connector.DataItem.ItemWidth - connector.ConnectorWidth / 2, connector.DataItem.Top - connector.ConnectorHeight / 2);
|
||||
break;
|
||||
case ConnectorOrientation.Right:
|
||||
point = new PointBase(connector.DataItem.Left + connector.DataItem.ItemWidth - connector.ConnectorWidth / 2, connector.DataItem.Top + (connector.DataItem.ItemHeight / 2) - connector.ConnectorHeight / 2);
|
||||
break;
|
||||
case ConnectorOrientation.Left:
|
||||
point = new PointBase(connector.DataItem.Left - connector.ConnectorWidth / 2, connector.DataItem.Top + (connector.DataItem.ItemHeight / 2) - connector.ConnectorHeight / 2);
|
||||
case ConnectorOrientation.BottomRight:
|
||||
point = new PointBase(connector.DataItem.Left + connector.DataItem.ItemWidth - connector.ConnectorWidth / 2, connector.DataItem.Top + connector.DataItem.ItemHeight - connector.ConnectorHeight / 2);
|
||||
break;
|
||||
case ConnectorOrientation.Bottom:
|
||||
point = new PointBase(connector.DataItem.Left + (connector.DataItem.ItemWidth / 2) - connector.ConnectorWidth / 2, connector.DataItem.Top + connector.DataItem.ItemHeight - connector.ConnectorHeight / 2);
|
||||
break;
|
||||
case ConnectorOrientation.BottomLeft:
|
||||
point = new PointBase(connector.DataItem.Left - connector.ConnectorWidth / 2, connector.DataItem.Top + connector.DataItem.ItemHeight - connector.ConnectorHeight / 2);
|
||||
break;
|
||||
default:
|
||||
point = new PointBase(connector.DataItem.Left + (connector.DataItem.ItemWidth / 2) - connector.ConnectorWidth / 2, connector.DataItem.Top + (connector.DataItem.ItemHeight / 2) - connector.ConnectorHeight / 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
VerticalContentAlignment="{Binding FontViewModel.VerticalAlignment}"
|
||||
TextBlock.LineHeight="{Binding FontViewModel.LineHeight}"
|
||||
AcceptsReturn="True"
|
||||
IsHitTestVisible="False"
|
||||
s:ControlAttachProperty.Watermark="{Binding Path=(s:ControlAttachProperty.Watermark),RelativeSource={RelativeSource AncestorType={x:Type s:TextControl}}}"
|
||||
Style="{StaticResource WaterTextBoxWithEffect}" IsReadOnly="True">
|
||||
|
||||
|
||||
@@ -18,15 +18,15 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
/// </summary>
|
||||
public partial class TextControl : UserControl
|
||||
{
|
||||
public static readonly DependencyProperty DoubleEditProperty = DependencyProperty.Register(
|
||||
nameof(DoubleEdit), typeof(bool), typeof(TextControl), new FrameworkPropertyMetadata(
|
||||
true));
|
||||
//public static readonly DependencyProperty DoubleEditProperty = DependencyProperty.Register(
|
||||
// nameof(DoubleEdit), typeof(bool), typeof(TextControl), new FrameworkPropertyMetadata(
|
||||
// true));
|
||||
|
||||
public bool DoubleEdit
|
||||
{
|
||||
get => (bool)GetValue(DoubleEditProperty);
|
||||
set => SetValue(DoubleEditProperty, value);
|
||||
}
|
||||
//public bool DoubleEdit
|
||||
//{
|
||||
// get => (bool)GetValue(DoubleEditProperty);
|
||||
// set => SetValue(DoubleEditProperty, value);
|
||||
//}
|
||||
|
||||
public TextControl()
|
||||
{
|
||||
@@ -69,13 +69,7 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
|
||||
{
|
||||
base.OnPreviewMouseDown(e);
|
||||
|
||||
if (DoubleEdit == false)
|
||||
else if (e.PropertyName == "EditText")
|
||||
{
|
||||
PART_ShowText.Visibility = Visibility.Visible;
|
||||
PART_TextBlock.Visibility = Visibility.Collapsed;
|
||||
@@ -87,21 +81,37 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPreviewMouseDoubleClick(MouseButtonEventArgs e)
|
||||
{
|
||||
base.OnPreviewMouseDoubleClick(e);
|
||||
//protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
|
||||
//{
|
||||
// base.OnPreviewMouseDown(e);
|
||||
|
||||
if (DoubleEdit == true)
|
||||
{
|
||||
PART_ShowText.Visibility = Visibility.Visible;
|
||||
PART_TextBlock.Visibility = Visibility.Collapsed;
|
||||
PART_ShowText.Focus();
|
||||
if (!string.IsNullOrEmpty(PART_ShowText.Text))
|
||||
{
|
||||
PART_ShowText.SelectionStart = PART_ShowText.Text.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (DoubleEdit == false)
|
||||
// {
|
||||
// PART_ShowText.Visibility = Visibility.Visible;
|
||||
// PART_TextBlock.Visibility = Visibility.Collapsed;
|
||||
// PART_ShowText.Focus();
|
||||
// if (!string.IsNullOrEmpty(PART_ShowText.Text))
|
||||
// {
|
||||
// PART_ShowText.SelectionStart = PART_ShowText.Text.Length;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//protected override void OnPreviewMouseDoubleClick(MouseButtonEventArgs e)
|
||||
//{
|
||||
// base.OnPreviewMouseDoubleClick(e);
|
||||
|
||||
// if (DoubleEdit == true)
|
||||
// {
|
||||
// PART_ShowText.Visibility = Visibility.Visible;
|
||||
// PART_TextBlock.Visibility = Visibility.Collapsed;
|
||||
// PART_ShowText.Focus();
|
||||
// if (!string.IsNullOrEmpty(PART_ShowText.Text))
|
||||
// {
|
||||
// PART_ShowText.SelectionStart = PART_ShowText.Text.Length;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
public class ControlAttachProperty
|
||||
|
||||
@@ -370,7 +370,7 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
RaisePropertyChanged(nameof(IsFullConnection));
|
||||
}
|
||||
|
||||
public bool IsPortless => SourceConnectorInfo?.DataItem?.Connectors?.Count() == 0;
|
||||
public bool IsPortless => SourceConnectorInfo.IsPortless || SinkConnectorInfoFully?.IsPortless == true;
|
||||
#endregion
|
||||
|
||||
#region 方法
|
||||
@@ -607,9 +607,9 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
{
|
||||
if (SourceConnectorInfo.DataItem == null || (IsFullConnection && SinkConnectorInfoFully.DataItem == null))
|
||||
return (null, null);
|
||||
|
||||
var sourceCenter = SourceConnectorInfo.DataItem.GetBounds().Center;
|
||||
var targetCenter = SinkConnectorInfoFully?.DataItem?.GetBounds().Center ?? OnGoingPosition;
|
||||
|
||||
var sourceCenter = SourceConnectorInfo.IsPortless ? SourceConnectorInfo.DataItem.GetBounds().Center : SourceConnectorInfo.MiddlePosition;
|
||||
var targetCenter = SinkConnectorInfoFully?.IsPortless == true ? SinkConnectorInfoFully?.DataItem?.GetBounds().Center ?? 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);
|
||||
@@ -618,7 +618,8 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
var targetIntersections = SinkConnectorInfoFully.DataItem.GetShape()?.GetIntersectionsWithLine(targetLine) ?? new PointBase[] { OnGoingPosition };
|
||||
var sourceIntersection = GetClosestPointTo(sourceIntersections, firstPt);
|
||||
var targetIntersection = GetClosestPointTo(targetIntersections, secondPt);
|
||||
return (sourceIntersection ?? sourceCenter, targetIntersection ?? targetCenter);
|
||||
|
||||
return (sourceIntersection ?? sourceCenter,targetIntersection ?? targetCenter);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -626,6 +627,8 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
var target = SinkConnectorInfo.MiddlePosition;// GetPortPositionBasedOnAlignment(SinkConnectorInfoFully, ColorViewModel.RightArrowSizeStyle);
|
||||
return (source, target);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private PointBase? GetPortPositionBasedOnAlignment(ConnectorInfoBase port, ArrowSizeStyle marker)
|
||||
|
||||
@@ -143,6 +143,11 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
get; set;
|
||||
}
|
||||
|
||||
public bool IsPortless
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public ValueTypePoint _valueTypePoint;
|
||||
public ValueTypePoint ValueTypePoint
|
||||
{
|
||||
|
||||
@@ -64,10 +64,10 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
|
||||
protected virtual void InitConnector()
|
||||
{
|
||||
connectors.Add(new FullyCreatedConnectorInfo(this, ConnectorOrientation.Top));
|
||||
connectors.Add(new FullyCreatedConnectorInfo(this, ConnectorOrientation.Bottom));
|
||||
connectors.Add(new FullyCreatedConnectorInfo(this, ConnectorOrientation.Left));
|
||||
connectors.Add(new FullyCreatedConnectorInfo(this, ConnectorOrientation.Right));
|
||||
connectors.Add(new FullyCreatedConnectorInfo(this.Root, this, ConnectorOrientation.Top));
|
||||
connectors.Add(new FullyCreatedConnectorInfo(this.Root, this, ConnectorOrientation.Bottom));
|
||||
connectors.Add(new FullyCreatedConnectorInfo(this.Root, this, ConnectorOrientation.Left));
|
||||
connectors.Add(new FullyCreatedConnectorInfo(this.Root, this, ConnectorOrientation.Right));
|
||||
}
|
||||
|
||||
#region 属性
|
||||
@@ -135,6 +135,18 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
}
|
||||
}
|
||||
|
||||
private FullyCreatedConnectorInfo _portlessConnector;
|
||||
public FullyCreatedConnectorInfo PortlessConnector
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_portlessConnector == null)
|
||||
_portlessConnector = new FullyCreatedConnectorInfo(this.Root, this, ConnectorOrientation.None) { IsPortless = true };
|
||||
|
||||
return _portlessConnector;
|
||||
}
|
||||
}
|
||||
|
||||
public Style ConnectorStyle
|
||||
{
|
||||
get; set;
|
||||
|
||||
@@ -191,6 +191,8 @@ namespace AIStudio.Wpf.DiagramDesigner
|
||||
if (IsReadOnly == true) return;
|
||||
|
||||
ShowText = true;
|
||||
|
||||
RaisePropertyChanged("EditText");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user