连接点可以添加文字

This commit is contained in:
艾竹
2023-01-22 21:46:59 +08:00
parent ad227aee0c
commit 4c37fb9772
16 changed files with 371 additions and 122 deletions

View File

@@ -1103,6 +1103,8 @@ namespace AIStudio.Wpf.DiagramApp.ViewModels
private void SelectedColorExecuted(object para) private void SelectedColorExecuted(object para)
{ {
if (para == null) return;
switch (ColorType) switch (ColorType)
{ {
case Models.ColorType.Text: DiagramsViewModel?.SetFont(new FontViewModel() { FontColor = (Color)para }, "FontColor"); break; case Models.ColorType.Text: DiagramsViewModel?.SetFont(new FontViewModel() { FontColor = (Color)para }, "FontColor"); break;

View File

@@ -998,10 +998,10 @@
<Fluent:Button Margin="5" Command="{Binding DistributeVerticalCommand}" Size="Small" Icon="/AIStudio.Wpf.DiagramApp;component/Images/DistributeObjectsVertical.png"/> <Fluent:Button Margin="5" Command="{Binding DistributeVerticalCommand}" Size="Small" Icon="/AIStudio.Wpf.DiagramApp;component/Images/DistributeObjectsVertical.png"/>
</StackPanel> </StackPanel>
</Fluent:DropDownButton> </Fluent:DropDownButton>
<Fluent:DropDownButton Header="翻转" Icon="{iconPacks:VaadinIcons Kind=FlipH}" Width="50" VerticalAlignment="Top" IsEnabled="{Binding SelectedItem.ShowRotate}"> <Fluent:SplitButton Header="翻转" Icon="{iconPacks:VaadinIcons Kind=FlipH}" Width="50" VerticalAlignment="Top" IsCheckable="True" IsChecked="{Binding SelectedItem.ShowRotate}">
<Fluent:DropDownButton.LargeIcon> <Fluent:SplitButton.LargeIcon>
<iconPacks:PackIconVaadinIcons Kind="FlipH" VerticalAlignment="Center" HorizontalAlignment="Center"/> <iconPacks:PackIconVaadinIcons Kind="FlipH" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Fluent:DropDownButton.LargeIcon> </Fluent:SplitButton.LargeIcon>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<TextBlock Margin="5" Text="镜像" VerticalAlignment="Center"/> <TextBlock Margin="5" Text="镜像" VerticalAlignment="Center"/>
<Fluent:ToggleButton IsChecked="{Binding SelectedItem.ScaleX,Converter={dd:ConverterValueMapToBool Parameter='1'}, ConverterParameter='-1'}" <Fluent:ToggleButton IsChecked="{Binding SelectedItem.ScaleX,Converter={dd:ConverterValueMapToBool Parameter='1'}, ConverterParameter='-1'}"
@@ -1015,7 +1015,7 @@
<Fluent:Spinner Margin="5" Width="60" Size="Small" Value="{Binding SelectedItem.Angle,Mode=TwoWay}" Maximum="359" Minimum="0" <Fluent:Spinner Margin="5" Width="60" Size="Small" Value="{Binding SelectedItem.Angle,Mode=TwoWay}" Maximum="359" Minimum="0"
Format="0 deg" /> Format="0 deg" />
</StackPanel> </StackPanel>
</Fluent:DropDownButton> </Fluent:SplitButton>
<Fluent:DropDownButton Header="大小" Icon="{iconPacks:FontAwesome Kind=ArrowsAltSolid}" Width="50" VerticalAlignment="Top"> <Fluent:DropDownButton Header="大小" Icon="{iconPacks:FontAwesome Kind=ArrowsAltSolid}" Width="50" VerticalAlignment="Top">
<Fluent:DropDownButton.LargeIcon> <Fluent:DropDownButton.LargeIcon>
<iconPacks:PackIconFontAwesome Kind="ExpandArrowsAltSolid" VerticalAlignment="Center" HorizontalAlignment="Center"/> <iconPacks:PackIconFontAwesome Kind="ExpandArrowsAltSolid" VerticalAlignment="Center" HorizontalAlignment="Center"/>

View File

@@ -24,6 +24,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.31" /> <PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.31" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="SvgPathProperties" Version="1.1.2" />
<PackageReference Include="System.Reactive" Version="5.0.0" /> <PackageReference Include="System.Reactive" Version="5.0.0" />
<PackageReference Include="WpfAnimatedGif" Version="2.0.0" /> <PackageReference Include="WpfAnimatedGif" Version="2.0.0" />
</ItemGroup> </ItemGroup>

View File

@@ -43,33 +43,28 @@ namespace AIStudio.Wpf.DiagramDesigner
static void Fe_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) static void Fe_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{ {
SelectableDesignerItemViewModelBase selectableDesignerItemViewModelBase = if (((FrameworkElement)sender).DataContext is ISelectable selectable)
(SelectableDesignerItemViewModelBase)((FrameworkElement)sender).DataContext;
if(selectableDesignerItemViewModelBase != null && selectableDesignerItemViewModelBase.IsHitTestVisible)
{ {
if ((Keyboard.Modifiers & (ModifierKeys.Shift | ModifierKeys.Control)) != ModifierKeys.None) if (selectable.IsHitTestVisible)
{ {
if ((Keyboard.Modifiers & (ModifierKeys.Shift)) != ModifierKeys.None) if ((Keyboard.Modifiers & (ModifierKeys.Shift | ModifierKeys.Control)) != ModifierKeys.None)
{ {
selectableDesignerItemViewModelBase.IsSelected = !selectableDesignerItemViewModelBase.IsSelected; if ((Keyboard.Modifiers & (ModifierKeys.Shift)) != ModifierKeys.None)
} {
selectable.IsSelected = !selectable.IsSelected;
}
if ((Keyboard.Modifiers & (ModifierKeys.Control)) != ModifierKeys.None) if ((Keyboard.Modifiers & (ModifierKeys.Control)) != ModifierKeys.None)
{
selectable.IsSelected = !selectable.IsSelected;
}
}
else if (!selectable.IsSelected)
{ {
selectableDesignerItemViewModelBase.IsSelected = !selectableDesignerItemViewModelBase.IsSelected; selectable.AddToSelection(true);
} }
} }
else if (!selectableDesignerItemViewModelBase.IsSelected) }
{
foreach (SelectableDesignerItemViewModelBase item in selectableDesignerItemViewModelBase.Parent.SelectedItems)
item.IsSelected = false;
selectableDesignerItemViewModelBase.Parent.SelectedItems.Clear();
//selectableDesignerItemViewModelBase.IsSelected = true;
selectableDesignerItemViewModelBase.Parent.SelectionService.AddToSelection(selectableDesignerItemViewModelBase);
}
}
} }
} }
} }

View File

@@ -413,7 +413,9 @@ namespace AIStudio.Wpf.DiagramDesigner
protected override void OnPreviewKeyDown(KeyEventArgs e) protected override void OnPreviewKeyDown(KeyEventArgs e)
{ {
base.OnPreviewKeyDown(e); base.OnPreviewKeyDown(e);
//FFE6E6FA
} }
protected override Size MeasureOverride(Size constraint) protected override Size MeasureOverride(Size constraint)

View File

@@ -116,5 +116,11 @@ namespace AIStudio.Wpf.DiagramDesigner
Vertices = SerializeHelper.DeserializePointList(value); Vertices = SerializeHelper.DeserializePointList(value);
} }
} }
[XmlArray]
public List<ConnectorItem> Connectors
{
get; set;
}
} }
} }

View File

@@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace AIStudio.Wpf.DiagramDesigner.Models.Serializables
{
public class LinkLabelItem
{
}
}

View File

@@ -541,11 +541,6 @@
<Canvas.InputBindings> <Canvas.InputBindings>
<MouseBinding MouseAction="LeftDoubleClick" Command="{Binding EditCommand}" CommandParameter="{Binding }" /> <MouseBinding MouseAction="LeftDoubleClick" Command="{Binding EditCommand}" CommandParameter="{Binding }" />
</Canvas.InputBindings> </Canvas.InputBindings>
<!--<Polyline x:Name="poly"
Points="{Binding Path=Vertices, Converter={x:Static s:ConnectionPointConverter.Instance}}"
Stroke="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}"
StrokeThickness="{Binding ColorViewModel.LineWidth}"
StrokeDashArray="{Binding ColorViewModel.LineDashStyle,Converter={StaticResource LineDashConverter}}" />-->
<Path x:Name="poly" Stroke="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}" <Path x:Name="poly" Stroke="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}"
StrokeThickness="{Binding ColorViewModel.LineWidth}" StrokeThickness="{Binding ColorViewModel.LineWidth}"
StrokeDashArray="{Binding ColorViewModel.LineDashStyle,Converter={StaticResource LineDashConverter}}"> StrokeDashArray="{Binding ColorViewModel.LineDashStyle,Converter={StaticResource LineDashConverter}}">
@@ -600,7 +595,7 @@
</c:DragThumb.InputBindings> </c:DragThumb.InputBindings>
</c:DragThumb> </c:DragThumb>
<s:PointContainer x:Name="PART_PointContainer" Style="{StaticResource innerConnectorContainer}" ItemsSource="{Binding Vertices}" Visibility="Collapsed"> <s:PointContainer x:Name="PART_VerticesContainer" Style="{StaticResource innerConnectorContainer}" ItemsSource="{Binding Vertices}" Visibility="Collapsed">
<s:PointContainer.ItemTemplate> <s:PointContainer.ItemTemplate>
<DataTemplate> <DataTemplate>
<Grid> <Grid>
@@ -616,7 +611,24 @@
</Style> </Style>
</s:PointContainer.Resources> </s:PointContainer.Resources>
</s:PointContainer> </s:PointContainer>
<s:PointContainer x:Name="PART_LabelsContainer" Style="{StaticResource innerConnectorContainer}" ItemsSource="{Binding Labels}" >
<s:PointContainer.ItemTemplate>
<DataTemplate>
<Grid s:SelectionProps.EnabledForSelection="True" Background="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}">
<c:PointDragThumb Cursor="SizeAll" Opacity="0"/>
<s:TextControl Margin="5" />
</Grid>
</DataTemplate>
</s:PointContainer.ItemTemplate>
<s:PointContainer.Resources>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="Canvas.Left" Value="{Binding Left}" />
<Setter Property="Canvas.Top" Value="{Binding Top}" />
</Style>
</s:PointContainer.Resources>
</s:PointContainer>
<Rectangle Fill="#7F243859" Opacity="0.5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Visibility="{Binding ShouldInsertAnchor, Converter={StaticResource BooleanToVisibilityConverter}}"> <Rectangle Fill="#7F243859" Opacity="0.5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Visibility="{Binding ShouldInsertAnchor, Converter={StaticResource BooleanToVisibilityConverter}}">
<i:Interaction.Behaviors> <i:Interaction.Behaviors>
<s:ControlMouseLeftButtonDownCommandBehavior Command="{Binding AddVertexCommand}" /> <s:ControlMouseLeftButtonDownCommandBehavior Command="{Binding AddVertexCommand}" />
@@ -635,7 +647,7 @@
<Setter TargetName="rightarrow" <Setter TargetName="rightarrow"
Property="Fill" Property="Fill"
Value="Black" /> Value="Black" />
<Setter TargetName="PART_PointContainer" <Setter TargetName="PART_VerticesContainer"
Property="Visibility" Property="Visibility"
Value="Visible"/> Value="Visible"/>
</DataTrigger> </DataTrigger>
@@ -651,14 +663,14 @@
<Setter TargetName="rightarrow" <Setter TargetName="rightarrow"
Property="Fill" Property="Fill"
Value="Black" /> Value="Black" />
<Setter TargetName="PART_PointContainer" <Setter TargetName="PART_VerticesContainer"
Property="Visibility" Property="Visibility"
Value="Visible"/> Value="Visible"/>
</DataTrigger> </DataTrigger>
<DataTrigger Value="True" <DataTrigger Value="True"
Binding="{Binding ShouldInsertAnchor}"> Binding="{Binding ShouldInsertAnchor}">
<Setter TargetName="PART_PointContainer" <Setter TargetName="PART_VerticesContainer"
Property="Visibility" Property="Visibility"
Value="Visible"/> Value="Visible"/>
</DataTrigger> </DataTrigger>

View File

@@ -18,14 +18,14 @@ namespace AIStudio.Wpf.DiagramDesigner
/// </summary> /// </summary>
public partial class TextControl : UserControl public partial class TextControl : UserControl
{ {
public static readonly DependencyProperty TextProperty = DependencyProperty.Register( public static readonly DependencyProperty DoubleEditProperty = DependencyProperty.Register(
"DoubleEdit", typeof(bool), typeof(TextControl), new FrameworkPropertyMetadata( nameof(DoubleEdit), typeof(bool), typeof(TextControl), new FrameworkPropertyMetadata(
true)); true));
public bool DoubleEdit public bool DoubleEdit
{ {
get => (bool)GetValue(TextProperty); get => (bool)GetValue(DoubleEditProperty);
set => SetValue(TextProperty, value); set => SetValue(DoubleEditProperty, value);
} }
public TextControl() public TextControl()
@@ -48,7 +48,10 @@ namespace AIStudio.Wpf.DiagramDesigner
PART_ShowText.SelectionStart = PART_ShowText.Text.Length; PART_ShowText.SelectionStart = PART_ShowText.Text.Length;
} }
(this.DataContext as SelectableDesignerItemViewModelBase).PropertyChanged += TextControl_PropertyChanged; if (this.DataContext is ISelectable selectable)
{
selectable.PropertyChanged += TextControl_PropertyChanged;
}
TextControl_PropertyChanged(this.DataContext, new System.ComponentModel.PropertyChangedEventArgs("IsSelected")); TextControl_PropertyChanged(this.DataContext, new System.ComponentModel.PropertyChangedEventArgs("IsSelected"));
} }
@@ -56,9 +59,9 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
if (e.PropertyName == "IsSelected") if (e.PropertyName == "IsSelected")
{ {
if (sender is SelectableDesignerItemViewModelBase itemViewModelBase) if (sender is ISelectable selectable)
{ {
if (itemViewModelBase.IsSelected == false) if (selectable.IsSelected == false)
{ {
PART_ShowText.Visibility = Visibility.Collapsed; PART_ShowText.Visibility = Visibility.Collapsed;
PART_TextBlock.Visibility = Visibility.Visible; PART_TextBlock.Visibility = Visibility.Visible;

View File

@@ -20,7 +20,7 @@ namespace AIStudio.Wpf.DiagramDesigner
public ColorViewModel() public ColorViewModel()
{ {
LineColor = new ColorObject() { Color = Colors.Gray }; LineColor = new ColorObject() { Color = Colors.Gray };
FillColor = new ColorObject() { Color = Colors.Transparent }; FillColor = new ColorObject() { Color = Colors.White };
} }
private IColorObject _lineColor; private IColorObject _lineColor;
public IColorObject LineColor public IColorObject LineColor

View File

@@ -125,7 +125,20 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
SetProperty(ref _colorViewModel, value); SetProperty(ref _colorViewModel, value);
} }
} }
private IFontViewModel _fontViewModel;
public IFontViewModel FontViewModel
{
get
{
return _fontViewModel;
}
set
{
SetProperty(ref _fontViewModel, value);
}
}
public static ConnectorPoint operator -(ConnectorPoint a, ConnectorPoint b) public static ConnectorPoint operator -(ConnectorPoint a, ConnectorPoint b)
{ {

View File

@@ -5,10 +5,10 @@ using System.ComponentModel;
using System.Linq; using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
//using System.Windows;
using System.Windows.Media; using System.Windows.Media;
using AIStudio.Wpf.DiagramDesigner.Geometrys; using AIStudio.Wpf.DiagramDesigner.Geometrys;
using AIStudio.Wpf.DiagramDesigner.Helpers; using AIStudio.Wpf.DiagramDesigner.Helpers;
using SvgPathProperties;
namespace AIStudio.Wpf.DiagramDesigner namespace AIStudio.Wpf.DiagramDesigner
{ {
@@ -39,7 +39,7 @@ namespace AIStudio.Wpf.DiagramDesigner
protected virtual void Init(FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo) protected virtual void Init(FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo)
{ {
this.Parent = sourceConnectorInfo.DataItem.Parent; this.Parent = sourceConnectorInfo.DataItem.Parent;
if (Parent != null && Parent.ColorViewModel != null) if (Parent != null && Parent.ColorViewModel != null)
{ {
this.ColorViewModel = CopyHelper.Mapper(Parent.ColorViewModel); this.ColorViewModel = CopyHelper.Mapper(Parent.ColorViewModel);
@@ -60,7 +60,7 @@ namespace AIStudio.Wpf.DiagramDesigner
this.SourceConnectorInfo = sourceConnectorInfo; this.SourceConnectorInfo = sourceConnectorInfo;
this.SinkConnectorInfo = sinkConnectorInfo; this.SinkConnectorInfo = sinkConnectorInfo;
DeleteConnectionCommand = new SimpleCommand(DeleteConnection); DeleteConnectionCommand = new SimpleCommand(DeleteConnection);
AddVertexCommand = new SimpleCommand(AddVertex); AddVertexCommand = new SimpleCommand(AddVertex);
} }
protected void LoadDesignerItemViewModel(SelectableDesignerItemBase designerbase) protected void LoadDesignerItemViewModel(SelectableDesignerItemBase designerbase)
@@ -112,7 +112,7 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
set set
{ {
SetProperty(ref _sourceB, value); SetProperty(ref _sourceB, value);
} }
} }
@@ -177,7 +177,7 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
private set private set
{ {
SetProperty(ref _area, value); SetProperty(ref _area, value);
} }
} }
@@ -241,7 +241,18 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
} }
public List<LinkLabelModel> Labels { get; set; } = new List<LinkLabelModel>(); private ObservableCollection<LinkLabelModel> _labels = new ObservableCollection<LinkLabelModel>();
public ObservableCollection<LinkLabelModel> Labels
{
get
{
return _labels;
}
private set
{
SetProperty(ref _labels, value);
}
}
public virtual Dictionary<string, string> PropertiesSetting public virtual Dictionary<string, string> PropertiesSetting
{ {
@@ -277,7 +288,7 @@ namespace AIStudio.Wpf.DiagramDesigner
set set
{ {
SetProperty(ref _sinkConnectorInfo, value); SetProperty(ref _sinkConnectorInfo, value);
} }
} }
@@ -351,6 +362,12 @@ namespace AIStudio.Wpf.DiagramDesigner
vertice.PropertyChanged += new WeakINPCEventHandler(ConnectorViewModel_PropertyChanged).Handler; vertice.PropertyChanged += new WeakINPCEventHandler(ConnectorViewModel_PropertyChanged).Handler;
} }
break; break;
case nameof(Labels):
foreach (var label in Labels)
{
label.PropertyChanged += new WeakINPCEventHandler(ConnectorViewModel_PropertyChanged).Handler;
}
break;
case nameof(SourceConnectorInfo): case nameof(SourceConnectorInfo):
SourceA = PointHelper.GetPointForConnector(SourceConnectorInfo); SourceA = PointHelper.GetPointForConnector(SourceConnectorInfo);
(SourceConnectorInfo.DataItem as INotifyPropertyChanged).PropertyChanged += new WeakINPCEventHandler(ConnectorViewModel_PropertyChanged).Handler; (SourceConnectorInfo.DataItem as INotifyPropertyChanged).PropertyChanged += new WeakINPCEventHandler(ConnectorViewModel_PropertyChanged).Handler;
@@ -362,6 +379,12 @@ namespace AIStudio.Wpf.DiagramDesigner
(((FullyCreatedConnectorInfo)SinkConnectorInfo).DataItem as INotifyPropertyChanged).PropertyChanged += new WeakINPCEventHandler(ConnectorViewModel_PropertyChanged).Handler; (((FullyCreatedConnectorInfo)SinkConnectorInfo).DataItem as INotifyPropertyChanged).PropertyChanged += new WeakINPCEventHandler(ConnectorViewModel_PropertyChanged).Handler;
} }
break; break;
case nameof(IsSelected):
if (IsSelected == false)
{
Labels.FirstOrDefault()?.AddToSelection(false);
}
break;
} }
} }
@@ -395,13 +418,35 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
switch (e.PropertyName) switch (e.PropertyName)
{ {
case nameof(ConnectorPoint.Left): case nameof(ConnectorPoint.X):
case nameof(ConnectorPoint.Top): case nameof(ConnectorPoint.Y):
UpdatePathGeneratorResult(); UpdatePathGeneratorResult();
break; break;
} }
} }
else if (sender is LinkLabelModel linkLabelModel)
{
switch (e.PropertyName)
{
case nameof(ConnectorPoint.X):
{
if (e is ValuePropertyChangedEventArgs valuePropertyChangedEventArgs)
{
linkLabelModel.UpdateOffsetX((double)valuePropertyChangedEventArgs.OldValue, (double)valuePropertyChangedEventArgs.NewValue);
}
break;
}
case nameof(ConnectorPoint.Y):
{
if (e is ValuePropertyChangedEventArgs valuePropertyChangedEventArgs)
{
linkLabelModel.UpdateOffsetY((double)valuePropertyChangedEventArgs.OldValue, (double)valuePropertyChangedEventArgs.NewValue);
}
break;
}
}
}
} }
private void UpdateArea() private void UpdateArea()
@@ -485,6 +530,12 @@ namespace AIStudio.Wpf.DiagramDesigner
StartAngle = PathGeneratorResult.SourceMarkerAngle; StartAngle = PathGeneratorResult.SourceMarkerAngle;
EndAngle = PathGeneratorResult.TargetMarkerAngle; EndAngle = PathGeneratorResult.TargetMarkerAngle;
var paths = Labels.Count > 0 ? PathGeneratorResult.Paths.Select(p => new SvgPath(p)).ToArray() : Array.Empty<SvgPath>();
foreach (var label in Labels)
{
label.UpdatePosition(paths);
}
} }
private void DeleteConnection(object args) private void DeleteConnection(object args)
@@ -496,22 +547,6 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
} }
private void AddVertex(object parameter)
{
MouseButtonEventArgs mosueArg = ((EventToCommandArgs)parameter).EventArgs as MouseButtonEventArgs;
var position = mosueArg.GetPosition(((EventToCommandArgs)parameter).Sender as IInputElement);
var vertice = new LinkVertexModel(this, new PointBase(position.X, position.Y));
vertice.PropertyChanged += new WeakINPCEventHandler(ConnectorViewModel_PropertyChanged).Handler;
Vertices.Add(vertice);
UpdatePathGeneratorResult();
if (!((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control))
{
ShouldInsertAnchor = false;
}
}
private (PointBase? source, PointBase? target) FindConnectionPoints(PointBase[] route) private (PointBase? source, PointBase? target) FindConnectionPoints(PointBase[] route)
{ {
if (IsPortless) // Portless if (IsPortless) // Portless
@@ -544,7 +579,7 @@ namespace AIStudio.Wpf.DiagramDesigner
if (port == null) if (port == null)
return null; return null;
if (marker == null) if (marker == 0)
return port.MiddlePosition; return port.MiddlePosition;
var pt = port.Position; var pt = port.Position;
@@ -588,6 +623,22 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
#region #region
private void AddVertex(object parameter)
{
MouseButtonEventArgs mosueArg = ((EventToCommandArgs)parameter).EventArgs as MouseButtonEventArgs;
var position = mosueArg.GetPosition(((EventToCommandArgs)parameter).Sender as IInputElement);
var vertice = new LinkVertexModel(this, new PointBase(position.X, position.Y));
vertice.PropertyChanged += new WeakINPCEventHandler(ConnectorViewModel_PropertyChanged).Handler;
Vertices.Add(vertice);
UpdatePathGeneratorResult();
if (!((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control))
{
ShouldInsertAnchor = false;
}
}
protected override void ExecuteEditCommand(object param) protected override void ExecuteEditCommand(object param)
{ {
if (this.OutTextItem != null) return; if (this.OutTextItem != null) return;
@@ -596,48 +647,25 @@ namespace AIStudio.Wpf.DiagramDesigner
public void AddText(string text) public void AddText(string text)
{ {
if (this.Parent is IDiagramViewModel) var label = new LinkLabelModel(this, "");
{ label.PropertyChanged += new WeakINPCEventHandler(ConnectorViewModel_PropertyChanged).Handler;
var diagramVM = this.Parent as IDiagramViewModel; label.IsSelected = true;
Labels.Add(label);
TextDesignerItemViewModel textitem = new TextDesignerItemViewModel(); var paths = Labels.Count > 0 ? PathGeneratorResult.Paths.Select(p => new SvgPath(p)).ToArray() : Array.Empty<SvgPath>();
textitem.ItemWidth = Double.NaN; label.UpdatePosition(paths);
textitem.ItemHeight = double.NaN;
//if (this.PathMode == DrawMode.ConnectingLineBoundary.ToString())
//{
// var mid = (int)(ConnectionPoints.Count / 2);
// var p = PathGenerators.SegmentMiddlePoint(ConnectionPoints[mid - 1], ConnectionPoints[mid]);
// textitem.Left = this.Area.Left + p.X + 2;
// textitem.Top = this.Area.Top + p.Y - 15;
//}
//else
{
textitem.Left = this.Area.Left + this.Area.Width / 2 - 16;
textitem.Top = this.Area.Top + this.Area.Height / 2 - 5;
}
textitem.Watermark = null;
textitem.ZIndex = diagramVM.Items.Count;
textitem.ParentId = this.Id;
textitem.ParentItem = this;
textitem.ColorViewModel.FillColor = new ColorObject() { Color = Colors.White };
textitem.Text = text;
diagramVM.DirectAddItemCommand.Execute(textitem);
this.OutTextItem = textitem;
}
} }
public void OutTextItemLocation(RectangleBase oldArea, RectangleBase newArea) public void OutTextItemLocation(RectangleBase oldArea, RectangleBase newArea)
{ {
if (this.OutTextItem is TextDesignerItemViewModel text) //if (this.OutTextItem is TextDesignerItemViewModel text)
{ //{
var oldpoint = new PointBase(oldArea.Left + oldArea.Width / 2, oldArea.Top + oldArea.Height / 2); // var oldpoint = new PointBase(oldArea.Left + oldArea.Width / 2, oldArea.Top + oldArea.Height / 2);
var newpoint = new PointBase(newArea.Left + newArea.Width / 2, newArea.Top + newArea.Height / 2); // var newpoint = new PointBase(newArea.Left + newArea.Width / 2, newArea.Top + newArea.Height / 2);
text.Left = text.Left + newpoint.X - oldpoint.X; // text.Left = text.Left + newpoint.X - oldpoint.X;
text.Top = text.Top + newpoint.Y - oldpoint.Y; // text.Top = text.Top + newpoint.Y - oldpoint.Y;
} //}
} }
#endregion #endregion
} }

View File

@@ -188,7 +188,20 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
} }
public bool ShowRotate { get; set; } = true; private bool _showRotate = false;
[Browsable(true)]
public bool ShowRotate
{
get
{
return _showRotate;
}
set
{
SetProperty(ref _showRotate, value);
}
}
public bool ShowArrow { get; set; } = true; public bool ShowArrow { get; set; } = true;
private double _left; private double _left;

View File

@@ -1,32 +1,171 @@
namespace AIStudio.Wpf.DiagramDesigner using System.Linq;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
using SvgPathProperties;
namespace AIStudio.Wpf.DiagramDesigner
{ {
public class LinkLabelModel : ConnectorPoint public class LinkLabelModel : ConnectorPoint, ISelectable
{ {
public LinkLabelModel(ConnectorViewModel parent, string id, string content, double? distance = null, ConnectorPoint offset = null) public LinkLabelModel(ConnectorViewModel parent, string content, double? distance = null, PointBase? offset = null)
{ {
Parent = parent; Parent = parent;
Content = content; Text = content;
Distance = distance; Distance = distance;
Offset = offset; Offset = offset ?? new PointBase();
FontViewModel = Parent.FontViewModel;
ColorViewModel = Parent.ColorViewModel;
} }
public LinkLabelModel(ConnectorViewModel parent, string content, double? distance = null, ConnectorPoint offset = null) public ConnectorViewModel Parent
{ {
Parent = parent; get;
Content = content; }
Distance = distance;
Offset = offset; public bool IsHitTestVisible
{
get
{
return Parent.IsHitTestVisible;
}
}
private string _text;
public string Text
{
get
{
return _text;
}
set
{
SetProperty(ref _text, value);
}
} }
public ConnectorViewModel Parent { get; }
public string Content { get; set; }
/// <summary> /// <summary>
/// 3 types of values are possible: /// 3 types of values are possible:
/// <para>- A number between 0 and 1: Position relative to the link's length</para> /// <para>- A number between 0 and 1: Position relative to the link's length</para>
/// <para>- A positive number, greater than 1: Position away from the start</para> /// <para>- A positive number, greater than 1: Position away from the start</para>
/// <para>- A negative number, less than 0: Position away from the end</para> /// <para>- A negative number, less than 0: Position away from the end</para>
/// </summary> /// </summary>
public double? Distance { get; set; } public double? Distance
public ConnectorPoint Offset { get; set; } {
get; set;
}
public PointBase Offset
{
get; set;
}
private bool _isSelected;
public bool IsSelected
{
get
{
return _isSelected;
}
set
{
if (SetProperty(ref _isSelected, value))
{
//如果没有文字,失去焦点自动清除
if (_isSelected == false && string.IsNullOrEmpty(Text))
{
Parent.Labels.Remove(this);
}
}
}
}
public override PointBase Position
{
get
{
return new PointBase(Parent.Area.Left + Left, Parent.Area.Top + Top);
}
}
public override PointBase MiddlePosition => new PointBase(Parent.Area.Left + Left + ConnectorWidth / 2, Parent.Area.Top + Top + ConnectorHeight / 2);
private bool updating = false;
public void UpdatePosition(SvgPath[] paths)
{
var position = FindPosition(paths);
if (position == null)
return;
updating = true;
X = position.Value.X;
Y = position.Value.Y;
updating = false;
}
public PointBase? FindPosition(SvgPath[] paths)
{
var totalLength = paths.Sum(p => p.Length);
double length;
if (Distance >= 0 && Distance <= 1)
{
length = Distance.Value * totalLength;
}
else if (Distance > 1)
{
length = Distance.Value;
}
else if (Distance < 0)
{
length = totalLength + Distance.Value;
}
else
{
length = totalLength * (Parent.Labels.IndexOf(this) + 1) / (Parent.Labels.Count + 1);
}
foreach (var path in paths)
{
var pathLength = path.Length;
if (length < pathLength)
{
var pt = path.GetPointAtLength(length);
return new PointBase(pt.X + Offset.X, pt.Y + Offset.Y);
}
length -= pathLength;
}
return null;
}
public void UpdateOffsetX(double oldvalue, double newvalue)
{
if (updating == true) return;
Offset += new VectorBase(newvalue - oldvalue, 0);
}
public void UpdateOffsetY(double oldvalue, double newvalue)
{
if (updating == true) return;
Offset += new VectorBase(0, newvalue - oldvalue);
}
public void AddToSelection(bool selected)
{
foreach (var item in Parent.Labels)
item.IsSelected = false;
if (selected == true)
{
IsSelected = true;
}
}
} }
} }

View File

@@ -364,6 +364,18 @@ namespace AIStudio.Wpf.DiagramDesigner
IsSelected = select; IsSelected = select;
} }
public void AddToSelection(bool selected)
{
foreach (SelectableDesignerItemViewModelBase item in Parent.SelectedItems)
item.IsSelected = false;
Parent.SelectedItems.Clear();
if (selected == true)
{
Parent.SelectionService.AddToSelection(this);
}
}
private void FontViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) private void FontViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{ {
if (e.PropertyName == "FontCase") if (e.PropertyName == "FontCase")

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@@ -7,6 +8,18 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
public interface ISelectable public interface ISelectable
{ {
bool IsSelected { get; set; } bool IsSelected
{
get; set;
}
bool IsHitTestVisible
{
get;
}
void AddToSelection(bool selected);
event PropertyChangedEventHandler PropertyChanged;
} }
} }