2021-07-23 09:42:22 +08:00
|
|
|
|
using System;
|
2023-06-11 23:58:22 +08:00
|
|
|
|
using System.Linq;
|
2021-07-23 09:42:22 +08:00
|
|
|
|
using System.Windows;
|
|
|
|
|
|
using System.Windows.Controls;
|
|
|
|
|
|
using System.Windows.Documents;
|
|
|
|
|
|
using System.Windows.Input;
|
|
|
|
|
|
using System.Windows.Media;
|
2024-01-01 20:37:06 +08:00
|
|
|
|
using System.Windows.Media.Media3D;
|
2021-07-23 09:42:22 +08:00
|
|
|
|
using System.Windows.Resources;
|
2023-08-27 16:02:28 +08:00
|
|
|
|
using AIStudio.Wpf.DiagramDesigner.Helpers;
|
2023-02-03 22:25:03 +08:00
|
|
|
|
using AIStudio.Wpf.DiagramDesigner.Models;
|
2023-03-18 21:44:58 +08:00
|
|
|
|
using AIStudio.Wpf.DiagramDesigner.ViewModels;
|
|
|
|
|
|
using AIStudio.Wpf.DiagramDesigner.ViewModels.BaseViewModel;
|
2021-07-23 09:42:22 +08:00
|
|
|
|
|
2022-10-28 22:45:39 +08:00
|
|
|
|
namespace AIStudio.Wpf.DiagramDesigner
|
2021-07-23 09:42:22 +08:00
|
|
|
|
{
|
|
|
|
|
|
public class DesignerCanvas : Canvas
|
|
|
|
|
|
{
|
2023-04-08 14:22:12 +08:00
|
|
|
|
#region 属性
|
2023-01-26 20:05:21 +08:00
|
|
|
|
private IDiagramViewModel _viewModel
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return DataContext as IDiagramViewModel;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
private IDiagramServiceProvider _service
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return DiagramServicesProvider.Instance.Provider;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-06-11 23:58:22 +08:00
|
|
|
|
private ConnectionViewModel _partialConnection;
|
2021-07-23 09:42:22 +08:00
|
|
|
|
|
|
|
|
|
|
private Point? rubberbandSelectionStartPoint = null;
|
|
|
|
|
|
|
2023-05-03 18:35:01 +08:00
|
|
|
|
private Connector _sourceConnector;
|
2023-05-02 14:28:51 +08:00
|
|
|
|
public Connector SourceConnector
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
2023-05-03 18:35:01 +08:00
|
|
|
|
return _sourceConnector;
|
2023-05-02 14:28:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
2023-05-03 18:35:01 +08:00
|
|
|
|
if (_sourceConnector != value)
|
2023-05-02 14:28:51 +08:00
|
|
|
|
{
|
2023-05-03 18:35:01 +08:00
|
|
|
|
_sourceConnector = value;
|
|
|
|
|
|
if (_sourceConnector != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
ConnectorInfoBase sourceDataItem = _sourceConnector.Info;
|
2023-05-03 09:59:46 +08:00
|
|
|
|
|
2023-05-03 18:35:01 +08:00
|
|
|
|
//Rect rectangleBounds = _sourceConnector.TransformToVisual(this).TransformBounds(new Rect(_sourceConnector.RenderSize));
|
|
|
|
|
|
//Point point = new Point(rectangleBounds.Left + (rectangleBounds.Width / 2),
|
|
|
|
|
|
// rectangleBounds.Bottom + (rectangleBounds.Height / 2));
|
2023-05-03 09:59:46 +08:00
|
|
|
|
|
2023-05-03 18:35:01 +08:00
|
|
|
|
Point point = sourceDataItem.MiddlePosition;
|
2023-05-02 14:28:51 +08:00
|
|
|
|
|
2023-06-11 23:58:22 +08:00
|
|
|
|
_partialConnection = new ConnectionViewModel(_viewModel, sourceDataItem, new PartCreatedConnectorInfo(point.X, point.Y), LineDrawMode, RouterMode);
|
2023-05-02 14:28:51 +08:00
|
|
|
|
|
2023-06-11 23:58:22 +08:00
|
|
|
|
_viewModel.Add(_partialConnection);
|
|
|
|
|
|
_partialConnection.ZIndex = -1;
|
2023-05-03 18:35:01 +08:00
|
|
|
|
}
|
2023-05-02 14:28:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-05-03 18:35:01 +08:00
|
|
|
|
private Connector _sinkConnector;
|
|
|
|
|
|
public Connector SinkConnector
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return _sinkConnector;
|
|
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_sinkConnector != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
_sinkConnector.Info.DisableAttachTo = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (_sinkConnector != value)
|
|
|
|
|
|
{
|
|
|
|
|
|
_sinkConnector = value;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-06-27 10:57:16 +08:00
|
|
|
|
|
2023-06-16 19:03:15 +08:00
|
|
|
|
private BlockItemsContainer _sourceItemsContainer;
|
|
|
|
|
|
public BlockItemsContainer SourceItemsContainer
|
2023-06-11 23:58:22 +08:00
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return _sourceItemsContainer;
|
|
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_sourceItemsContainer != value)
|
|
|
|
|
|
{
|
|
|
|
|
|
_sourceItemsContainer = value;
|
|
|
|
|
|
if (_sourceItemsContainer != null)
|
|
|
|
|
|
{
|
2023-06-17 23:55:54 +08:00
|
|
|
|
BlockItemsContainerInfo sourceContainerInfo = _sourceItemsContainer.Info;
|
2023-06-11 23:58:22 +08:00
|
|
|
|
|
2023-06-17 23:55:54 +08:00
|
|
|
|
sourceContainerInfo.DataItem.RemoveChild(_sourceItemsContainer.DragObject, sourceContainerInfo);
|
2023-06-11 23:58:22 +08:00
|
|
|
|
|
|
|
|
|
|
EnterMove();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-05-02 14:28:51 +08:00
|
|
|
|
|
2023-01-12 23:02:53 +08:00
|
|
|
|
private DrawMode DrawMode
|
2022-12-04 23:07:20 +08:00
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
2023-01-26 22:25:48 +08:00
|
|
|
|
if (_viewModel.DrawModeViewModel != null)
|
2022-12-04 23:07:20 +08:00
|
|
|
|
{
|
2023-05-14 00:31:25 +08:00
|
|
|
|
return _viewModel.DrawModeViewModel.GetDrawMode();
|
2022-12-04 23:07:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2023-05-14 00:31:25 +08:00
|
|
|
|
return _service.DrawModeViewModel.GetDrawMode();
|
2023-01-12 23:02:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-05-17 08:40:55 +08:00
|
|
|
|
|
|
|
|
|
|
private DrawMode LineDrawMode
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_viewModel.DrawModeViewModel != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return _viewModel.DrawModeViewModel.LineDrawMode;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
return _service.DrawModeViewModel.LineDrawMode;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-01-12 23:02:53 +08:00
|
|
|
|
private RouterMode RouterMode
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
2023-01-26 22:25:48 +08:00
|
|
|
|
if (_viewModel.DrawModeViewModel != null)
|
2023-01-12 23:02:53 +08:00
|
|
|
|
{
|
|
|
|
|
|
return _viewModel.DrawModeViewModel.LineRouterMode;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
return _service.DrawModeViewModel.LineRouterMode;
|
2022-12-04 23:07:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-07-23 09:42:22 +08:00
|
|
|
|
#region GridCellSize
|
|
|
|
|
|
|
|
|
|
|
|
public static readonly DependencyProperty GridCellSizeProperty =
|
2023-01-24 09:02:40 +08:00
|
|
|
|
DependencyProperty.Register(nameof(GridCellSize),
|
2021-07-23 09:42:22 +08:00
|
|
|
|
typeof(Size),
|
|
|
|
|
|
typeof(DesignerCanvas),
|
|
|
|
|
|
new FrameworkPropertyMetadata(new Size(50, 50), FrameworkPropertyMetadataOptions.AffectsRender));
|
|
|
|
|
|
|
|
|
|
|
|
public Size GridCellSize
|
|
|
|
|
|
{
|
2023-01-26 20:05:21 +08:00
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return (Size)GetValue(GridCellSizeProperty);
|
|
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
SetValue(GridCellSizeProperty, value);
|
|
|
|
|
|
}
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region ShowGrid
|
|
|
|
|
|
|
|
|
|
|
|
public static readonly DependencyProperty ShowGridProperty =
|
2023-01-24 09:02:40 +08:00
|
|
|
|
DependencyProperty.Register(nameof(ShowGrid),
|
2021-07-23 09:42:22 +08:00
|
|
|
|
typeof(bool),
|
|
|
|
|
|
typeof(DesignerCanvas),
|
|
|
|
|
|
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender));
|
|
|
|
|
|
|
|
|
|
|
|
public bool ShowGrid
|
|
|
|
|
|
{
|
2023-01-26 20:05:21 +08:00
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return (bool)GetValue(ShowGridProperty);
|
|
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
SetValue(ShowGridProperty, value);
|
|
|
|
|
|
}
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region GridColor
|
|
|
|
|
|
|
|
|
|
|
|
public static readonly DependencyProperty GridColorProperty =
|
2023-01-24 09:02:40 +08:00
|
|
|
|
DependencyProperty.Register(nameof(GridColor),
|
2021-07-23 09:42:22 +08:00
|
|
|
|
typeof(Color),
|
|
|
|
|
|
typeof(DesignerCanvas),
|
|
|
|
|
|
new FrameworkPropertyMetadata(Colors.LightGray, FrameworkPropertyMetadataOptions.AffectsRender));
|
|
|
|
|
|
|
|
|
|
|
|
public Color GridColor
|
|
|
|
|
|
{
|
2023-01-26 20:05:21 +08:00
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return (Color)GetValue(GridColorProperty);
|
|
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
SetValue(GridColorProperty, value);
|
|
|
|
|
|
}
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2024-01-01 20:37:06 +08:00
|
|
|
|
#region AutoGrowth
|
|
|
|
|
|
|
|
|
|
|
|
public static readonly DependencyProperty AutoGrowthProperty =
|
|
|
|
|
|
DependencyProperty.Register(nameof(AutoGrowth),
|
|
|
|
|
|
typeof(bool),
|
|
|
|
|
|
typeof(DesignerCanvas),
|
|
|
|
|
|
new FrameworkPropertyMetadata(true));
|
|
|
|
|
|
|
|
|
|
|
|
public bool AutoGrowth
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return (bool)GetValue(AutoGrowthProperty);
|
|
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
SetValue(AutoGrowthProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region CornerRadius
|
|
|
|
|
|
|
|
|
|
|
|
public static readonly DependencyProperty CornerRadiusProperty =
|
|
|
|
|
|
DependencyProperty.Register(nameof(CornerRadius),
|
|
|
|
|
|
typeof(CornerRadius),
|
|
|
|
|
|
typeof(DesignerCanvas),
|
|
|
|
|
|
new FrameworkPropertyMetadata(new CornerRadius()));
|
|
|
|
|
|
|
|
|
|
|
|
public CornerRadius CornerRadius
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return (CornerRadius)GetValue(CornerRadiusProperty);
|
|
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
SetValue(CornerRadiusProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2023-01-24 20:51:39 +08:00
|
|
|
|
#region GridMarginSize 单位mm
|
2021-07-23 09:42:22 +08:00
|
|
|
|
|
2023-01-24 20:51:39 +08:00
|
|
|
|
public static readonly DependencyProperty GridMarginSizeProperty =
|
|
|
|
|
|
DependencyProperty.Register(nameof(GridMarginSize),
|
|
|
|
|
|
typeof(Size),
|
2021-07-23 09:42:22 +08:00
|
|
|
|
typeof(DesignerCanvas),
|
2023-01-24 20:51:39 +08:00
|
|
|
|
new FrameworkPropertyMetadata(new Size(28, 28), FrameworkPropertyMetadataOptions.AffectsRender));
|
2021-07-23 09:42:22 +08:00
|
|
|
|
|
2023-01-24 20:51:39 +08:00
|
|
|
|
public Size GridMarginSize
|
2021-07-23 09:42:22 +08:00
|
|
|
|
{
|
2023-01-26 20:05:21 +08:00
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return (Size)GetValue(GridMarginSizeProperty);
|
|
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
SetValue(GridMarginSizeProperty, value);
|
|
|
|
|
|
}
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2023-04-08 14:22:12 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 初始化
|
2021-07-23 09:42:22 +08:00
|
|
|
|
public DesignerCanvas()
|
|
|
|
|
|
{
|
2023-03-12 15:26:58 +08:00
|
|
|
|
this.Focusable = true;
|
2021-07-23 09:42:22 +08:00
|
|
|
|
|
2023-03-12 15:26:58 +08:00
|
|
|
|
this.Loaded += DesignerCanvas_Loaded;
|
2023-04-15 21:55:27 +08:00
|
|
|
|
this.IsVisibleChanged += DesignerCanvas_IsVisibleChanged;
|
2023-06-27 10:57:16 +08:00
|
|
|
|
this.DataContextChanged += DesignerCanvas_DataContextChanged;
|
2023-05-27 12:35:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void DesignerCanvas_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
if (e.OldValue is IDiagramViewModel oldvalue)
|
|
|
|
|
|
{
|
|
|
|
|
|
//var image = this.ToBitmap().ToBitmapSource();
|
|
|
|
|
|
//oldvalue.Thumbnail = new ImageBrush(image) { Stretch = Stretch.Uniform };
|
|
|
|
|
|
}
|
|
|
|
|
|
if (e.NewValue is IDiagramViewModel newvalue)
|
|
|
|
|
|
{
|
|
|
|
|
|
newvalue.Thumbnail = new VisualBrush(this) { Stretch = Stretch.Uniform };
|
|
|
|
|
|
}
|
2023-04-15 21:55:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void DesignerCanvas_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (IsVisible)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.Focus();
|
|
|
|
|
|
}
|
2023-03-12 15:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-06-27 10:57:16 +08:00
|
|
|
|
protected void DesignerCanvas_Loaded(object sender, RoutedEventArgs e)
|
2023-03-12 15:26:58 +08:00
|
|
|
|
{
|
2023-07-09 21:03:35 +08:00
|
|
|
|
//Mediator.Instance.Register(this);
|
2023-03-12 15:26:58 +08:00
|
|
|
|
this.Focus();
|
2023-05-21 22:06:59 +08:00
|
|
|
|
_service.PropertyChanged += _service_PropertyChanged;
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void OnRender(DrawingContext dc)
|
|
|
|
|
|
{
|
|
|
|
|
|
var rect = new Rect(0, 0, RenderSize.Width, RenderSize.Height);
|
|
|
|
|
|
dc.DrawRectangle(Background, null, rect);
|
|
|
|
|
|
if (ShowGrid && GridCellSize.Width > 0 && GridCellSize.Height > 0)
|
|
|
|
|
|
DrawGrid(dc, rect);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-01-01 20:37:06 +08:00
|
|
|
|
public static Geometry GetRoundRectangle(Rect baseRect, Thickness borderThickness, CornerRadius cornerRadius)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Normalizing the corner radius
|
|
|
|
|
|
if (cornerRadius.TopLeft < double.Epsilon)
|
|
|
|
|
|
{
|
|
|
|
|
|
cornerRadius.TopLeft = 0.0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (cornerRadius.TopRight < double.Epsilon)
|
|
|
|
|
|
{
|
|
|
|
|
|
cornerRadius.TopRight = 0.0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (cornerRadius.BottomLeft < double.Epsilon)
|
|
|
|
|
|
{
|
|
|
|
|
|
cornerRadius.BottomLeft = 0.0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (cornerRadius.BottomRight < double.Epsilon)
|
|
|
|
|
|
{
|
|
|
|
|
|
cornerRadius.BottomRight = 0.0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Taking the border thickness into account
|
|
|
|
|
|
var leftHalf = borderThickness.Left * 0.5;
|
|
|
|
|
|
if (leftHalf < double.Epsilon)
|
|
|
|
|
|
{
|
|
|
|
|
|
leftHalf = 0.0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var topHalf = borderThickness.Top * 0.5;
|
|
|
|
|
|
if (topHalf < double.Epsilon)
|
|
|
|
|
|
{
|
|
|
|
|
|
topHalf = 0.0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var rightHalf = borderThickness.Right * 0.5;
|
|
|
|
|
|
if (rightHalf < double.Epsilon)
|
|
|
|
|
|
{
|
|
|
|
|
|
rightHalf = 0.0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var bottomHalf = borderThickness.Bottom * 0.5;
|
|
|
|
|
|
if (bottomHalf < double.Epsilon)
|
|
|
|
|
|
{
|
|
|
|
|
|
bottomHalf = 0.0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Create the rectangles for the corners that needs to be curved in the base rectangle
|
|
|
|
|
|
// TopLeft Rectangle
|
|
|
|
|
|
var topLeftRect = new Rect(
|
|
|
|
|
|
baseRect.Location.X,
|
|
|
|
|
|
baseRect.Location.Y,
|
|
|
|
|
|
Math.Max(0.0, cornerRadius.TopLeft - leftHalf),
|
|
|
|
|
|
Math.Max(0.0, cornerRadius.TopLeft - rightHalf));
|
|
|
|
|
|
|
|
|
|
|
|
// TopRight Rectangle
|
|
|
|
|
|
var topRightRect = new Rect(
|
|
|
|
|
|
baseRect.Location.X + baseRect.Width - cornerRadius.TopRight + rightHalf,
|
|
|
|
|
|
baseRect.Location.Y,
|
|
|
|
|
|
Math.Max(0.0, cornerRadius.TopRight - rightHalf),
|
|
|
|
|
|
Math.Max(0.0, cornerRadius.TopRight - topHalf));
|
|
|
|
|
|
|
|
|
|
|
|
// BottomRight Rectangle
|
|
|
|
|
|
var bottomRightRect = new Rect(
|
|
|
|
|
|
baseRect.Location.X + baseRect.Width - cornerRadius.BottomRight + rightHalf,
|
|
|
|
|
|
baseRect.Location.Y + baseRect.Height - cornerRadius.BottomRight + bottomHalf,
|
|
|
|
|
|
Math.Max(0.0, cornerRadius.BottomRight - rightHalf),
|
|
|
|
|
|
Math.Max(0.0, cornerRadius.BottomRight - bottomHalf));
|
|
|
|
|
|
|
|
|
|
|
|
// BottomLeft Rectangle
|
|
|
|
|
|
var bottomLeftRect = new Rect(
|
|
|
|
|
|
baseRect.Location.X,
|
|
|
|
|
|
baseRect.Location.Y + baseRect.Height - cornerRadius.BottomLeft + bottomHalf,
|
|
|
|
|
|
Math.Max(0.0, cornerRadius.BottomLeft - leftHalf),
|
|
|
|
|
|
Math.Max(0.0, cornerRadius.BottomLeft - bottomHalf));
|
|
|
|
|
|
|
|
|
|
|
|
// Adjust the _width of the TopLeft and TopRight rectangles so that they are proportional to the _width of the baseRect
|
|
|
|
|
|
if (topLeftRect.Right > topRightRect.Left)
|
|
|
|
|
|
{
|
|
|
|
|
|
var newWidth = (topLeftRect.Width / (topLeftRect.Width + topRightRect.Width)) * baseRect.Width;
|
|
|
|
|
|
topLeftRect = new Rect(topLeftRect.Location.X, topLeftRect.Location.Y, newWidth, topLeftRect.Height);
|
|
|
|
|
|
topRightRect = new Rect(
|
|
|
|
|
|
baseRect.Left + newWidth,
|
|
|
|
|
|
topRightRect.Location.Y,
|
|
|
|
|
|
Math.Max(0.0, baseRect.Width - newWidth),
|
|
|
|
|
|
topRightRect.Height);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Adjust the height of the TopRight and BottomRight rectangles so that they are proportional to the height of the baseRect
|
|
|
|
|
|
if (topRightRect.Bottom > bottomRightRect.Top)
|
|
|
|
|
|
{
|
|
|
|
|
|
var newHeight = (topRightRect.Height / (topRightRect.Height + bottomRightRect.Height)) * baseRect.Height;
|
|
|
|
|
|
topRightRect = new Rect(topRightRect.Location.X, topRightRect.Location.Y, topRightRect.Width, newHeight);
|
|
|
|
|
|
bottomRightRect = new Rect(
|
|
|
|
|
|
bottomRightRect.Location.X,
|
|
|
|
|
|
baseRect.Top + newHeight,
|
|
|
|
|
|
bottomRightRect.Width,
|
|
|
|
|
|
Math.Max(0.0, baseRect.Height - newHeight));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Adjust the _width of the BottomLeft and BottomRight rectangles so that they are proportional to the _width of the baseRect
|
|
|
|
|
|
if (bottomRightRect.Left < bottomLeftRect.Right)
|
|
|
|
|
|
{
|
|
|
|
|
|
var newWidth = (bottomLeftRect.Width / (bottomLeftRect.Width + bottomRightRect.Width)) * baseRect.Width;
|
|
|
|
|
|
bottomLeftRect = new Rect(bottomLeftRect.Location.X, bottomLeftRect.Location.Y, newWidth, bottomLeftRect.Height);
|
|
|
|
|
|
bottomRightRect = new Rect(
|
|
|
|
|
|
baseRect.Left + newWidth,
|
|
|
|
|
|
bottomRightRect.Location.Y,
|
|
|
|
|
|
Math.Max(0.0, baseRect.Width - newWidth),
|
|
|
|
|
|
bottomRightRect.Height);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Adjust the height of the TopLeft and BottomLeft rectangles so that they are proportional to the height of the baseRect
|
|
|
|
|
|
if (bottomLeftRect.Top < topLeftRect.Bottom)
|
|
|
|
|
|
{
|
|
|
|
|
|
var newHeight = (topLeftRect.Height / (topLeftRect.Height + bottomLeftRect.Height)) * baseRect.Height;
|
|
|
|
|
|
topLeftRect = new Rect(topLeftRect.Location.X, topLeftRect.Location.Y, topLeftRect.Width, newHeight);
|
|
|
|
|
|
bottomLeftRect = new Rect(
|
|
|
|
|
|
bottomLeftRect.Location.X,
|
|
|
|
|
|
baseRect.Top + newHeight,
|
|
|
|
|
|
bottomLeftRect.Width,
|
|
|
|
|
|
Math.Max(0.0, baseRect.Height - newHeight));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var roundedRectGeometry = new StreamGeometry();
|
|
|
|
|
|
|
|
|
|
|
|
using (var context = roundedRectGeometry.Open())
|
|
|
|
|
|
{
|
|
|
|
|
|
// Begin from the Bottom of the TopLeft Arc and proceed clockwise
|
|
|
|
|
|
context.BeginFigure(topLeftRect.BottomLeft, true, true);
|
|
|
|
|
|
|
|
|
|
|
|
// TopLeft Arc
|
|
|
|
|
|
context.ArcTo(topLeftRect.TopRight, topLeftRect.Size, 0, false, SweepDirection.Clockwise, true, true);
|
|
|
|
|
|
|
|
|
|
|
|
// Top Line
|
|
|
|
|
|
context.LineTo(topRightRect.TopLeft, true, true);
|
|
|
|
|
|
|
|
|
|
|
|
// TopRight Arc
|
|
|
|
|
|
context.ArcTo(topRightRect.BottomRight, topRightRect.Size, 0, false, SweepDirection.Clockwise, true, true);
|
|
|
|
|
|
|
|
|
|
|
|
// Right Line
|
|
|
|
|
|
context.LineTo(bottomRightRect.TopRight, true, true);
|
|
|
|
|
|
|
|
|
|
|
|
// BottomRight Arc
|
|
|
|
|
|
context.ArcTo(bottomRightRect.BottomLeft, bottomRightRect.Size, 0, false, SweepDirection.Clockwise, true, true);
|
|
|
|
|
|
|
|
|
|
|
|
// Bottom Line
|
|
|
|
|
|
context.LineTo(bottomLeftRect.BottomRight, true, true);
|
|
|
|
|
|
|
|
|
|
|
|
// BottomLeft Arc
|
|
|
|
|
|
context.ArcTo(bottomLeftRect.TopLeft, bottomLeftRect.Size, 0, false, SweepDirection.Clockwise, true, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return roundedRectGeometry;
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2021-07-23 09:42:22 +08:00
|
|
|
|
protected virtual void DrawGrid(DrawingContext dc, Rect rect)
|
|
|
|
|
|
{
|
|
|
|
|
|
//using .5 forces wpf to draw a single pixel line
|
2023-01-24 20:51:39 +08:00
|
|
|
|
for (var i = GridMarginSize.Height + 0.5; i < rect.Height - GridMarginSize.Height; i += GridCellSize.Height)
|
|
|
|
|
|
dc.DrawLine(new Pen(new SolidColorBrush(GridColor), 1), new Point(GridMarginSize.Width, i), new Point(rect.Width - GridMarginSize.Width, i));
|
|
|
|
|
|
dc.DrawLine(new Pen(new SolidColorBrush(GridColor), 1), new Point(GridMarginSize.Width, rect.Height - GridMarginSize.Height), new Point(rect.Width - GridMarginSize.Width, rect.Height - GridMarginSize.Height));
|
2021-07-23 09:42:22 +08:00
|
|
|
|
|
2023-01-24 20:51:39 +08:00
|
|
|
|
for (var i = GridMarginSize.Width + 0.5; i < rect.Width - GridMarginSize.Width; i += GridCellSize.Width)
|
|
|
|
|
|
dc.DrawLine(new Pen(new SolidColorBrush(GridColor), 1), new Point(i, GridMarginSize.Height), new Point(i, rect.Height - GridMarginSize.Height));
|
|
|
|
|
|
dc.DrawLine(new Pen(new SolidColorBrush(GridColor), 1), new Point(rect.Width - GridMarginSize.Width, GridMarginSize.Height), new Point(rect.Width - GridMarginSize.Width, rect.Height - GridMarginSize.Height));
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-04-08 14:22:12 +08:00
|
|
|
|
#region Format/Move
|
2021-07-23 09:42:22 +08:00
|
|
|
|
private void _service_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (sender is IDrawModeViewModel)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (e.PropertyName == nameof(CursorMode))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_service.DrawModeViewModel.CursorMode == CursorMode.Format)
|
|
|
|
|
|
{
|
|
|
|
|
|
EnterFormat();
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (_service.DrawModeViewModel.CursorMode == CursorMode.Move)
|
|
|
|
|
|
{
|
|
|
|
|
|
EnterMove();
|
|
|
|
|
|
}
|
2023-05-14 00:31:25 +08:00
|
|
|
|
else if (_service.DrawModeViewModel.CursorMode == CursorMode.Exit)
|
|
|
|
|
|
{
|
|
|
|
|
|
ExitCursor();
|
|
|
|
|
|
}
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
2023-05-14 15:06:30 +08:00
|
|
|
|
else if (e.PropertyName == nameof(_service.DrawModeViewModel.DrawingDrawMode))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_service.DrawModeViewModel.DrawingDrawMode == DrawMode.ColorPicker)
|
|
|
|
|
|
{
|
|
|
|
|
|
EnterColorPicker();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void EnterFormat()
|
|
|
|
|
|
{
|
2022-10-28 22:45:39 +08:00
|
|
|
|
StreamResourceInfo sri = Application.GetResourceStream(new Uri("pack://application:,,,/AIStudio.Wpf.DiagramDesigner;component/Images/FormatPainter.cur", UriKind.RelativeOrAbsolute));
|
2021-07-23 09:42:22 +08:00
|
|
|
|
this.Cursor = new Cursor(sri.Stream);
|
2023-05-09 23:22:17 +08:00
|
|
|
|
|
2023-01-24 09:02:40 +08:00
|
|
|
|
foreach (SelectableDesignerItemViewModelBase item in _viewModel.Items)
|
2021-07-23 09:42:22 +08:00
|
|
|
|
{
|
|
|
|
|
|
item.IsHitTestVisible = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void EnterMove()
|
|
|
|
|
|
{
|
|
|
|
|
|
this.Cursor = Cursors.SizeAll;
|
2023-01-24 09:02:40 +08:00
|
|
|
|
foreach (SelectableDesignerItemViewModelBase item in _viewModel.Items)
|
2021-07-23 09:42:22 +08:00
|
|
|
|
{
|
|
|
|
|
|
item.IsHitTestVisible = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-05-14 00:31:25 +08:00
|
|
|
|
private void EnterColorPicker()
|
|
|
|
|
|
{
|
2023-05-27 12:35:44 +08:00
|
|
|
|
|
2023-05-14 00:31:25 +08:00
|
|
|
|
// create rubberband adorner
|
|
|
|
|
|
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this);
|
|
|
|
|
|
if (adornerLayer != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
DrawingRubberbandAdorner adorner = new DrawingRubberbandAdorner(this, new Point());
|
|
|
|
|
|
if (adorner != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
adornerLayer.Add(adorner);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-07-23 09:42:22 +08:00
|
|
|
|
private void ExitCursor()
|
|
|
|
|
|
{
|
|
|
|
|
|
this.Cursor = Cursors.Arrow;
|
2023-01-24 09:02:40 +08:00
|
|
|
|
foreach (SelectableDesignerItemViewModelBase item in _viewModel.Items)
|
2021-07-23 09:42:22 +08:00
|
|
|
|
{
|
|
|
|
|
|
item.IsHitTestVisible = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
_service.DrawModeViewModel.CursorMode = CursorMode.Normal;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-01-24 09:02:40 +08:00
|
|
|
|
private void Format(SelectableDesignerItemViewModelBase source, SelectableDesignerItemViewModelBase target)
|
2021-07-23 09:42:22 +08:00
|
|
|
|
{
|
|
|
|
|
|
CopyHelper.CopyPropertyValue(source.ColorViewModel, target.ColorViewModel);
|
|
|
|
|
|
CopyHelper.CopyPropertyValue(source.FontViewModel, target.FontViewModel);
|
2023-04-08 14:22:12 +08:00
|
|
|
|
CopyHelper.CopyPropertyValue(source.ShapeViewModel, target.ShapeViewModel);
|
2023-04-29 15:29:22 +08:00
|
|
|
|
CopyHelper.CopyPropertyValue(source.AnimationViewModel, target.AnimationViewModel);
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
2023-04-08 14:22:12 +08:00
|
|
|
|
#endregion
|
2021-07-23 09:42:22 +08:00
|
|
|
|
|
|
|
|
|
|
protected override void OnMouseDown(MouseButtonEventArgs e)
|
|
|
|
|
|
{
|
2023-04-08 14:22:12 +08:00
|
|
|
|
base.OnMouseDown(e);
|
2023-03-12 15:26:58 +08:00
|
|
|
|
|
2022-12-04 23:07:20 +08:00
|
|
|
|
if (_viewModel.IsReadOnly) return;
|
2021-07-23 09:42:22 +08:00
|
|
|
|
|
|
|
|
|
|
if (_service.DrawModeViewModel.CursorMode == CursorMode.Format)
|
|
|
|
|
|
{
|
|
|
|
|
|
var element = (e.OriginalSource as FrameworkElement);
|
2023-01-24 09:02:40 +08:00
|
|
|
|
if (element.DataContext is SelectableDesignerItemViewModelBase target)
|
2021-07-23 09:42:22 +08:00
|
|
|
|
{
|
|
|
|
|
|
Format(_viewModel.SelectedItems.FirstOrDefault(), target);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ExitCursor();
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (_service.DrawModeViewModel.CursorMode == CursorMode.Move)
|
|
|
|
|
|
{
|
|
|
|
|
|
ExitCursor();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (e.LeftButton == MouseButtonState.Pressed)
|
|
|
|
|
|
{
|
|
|
|
|
|
//if we are source of event, we are rubberband selecting
|
|
|
|
|
|
if (e.Source == this)
|
|
|
|
|
|
{
|
|
|
|
|
|
// in case that this click is the start for a
|
|
|
|
|
|
// drag operation we cache the start point
|
2023-05-03 09:59:46 +08:00
|
|
|
|
Point currentPoint = e.GetPosition(this);
|
|
|
|
|
|
rubberbandSelectionStartPoint = currentPoint;
|
2021-07-23 09:42:22 +08:00
|
|
|
|
|
|
|
|
|
|
if (!(Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)))
|
|
|
|
|
|
{
|
2023-04-08 14:22:12 +08:00
|
|
|
|
_viewModel.ClearSelectedItems();
|
2021-07-23 09:42:22 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
2023-05-27 12:35:44 +08:00
|
|
|
|
|
|
|
|
|
|
if (_service.DrawModeViewModel.SharpDrawModeSelected ||
|
2023-05-14 18:02:59 +08:00
|
|
|
|
(_service.DrawModeViewModel.DrawingDrawModeSelected && _service.DrawModeViewModel.DrawingDrawMode != DrawMode.Select))
|
2023-05-07 23:01:38 +08:00
|
|
|
|
{
|
|
|
|
|
|
// create rubberband adorner
|
|
|
|
|
|
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this);
|
|
|
|
|
|
if (adornerLayer != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
DrawingRubberbandAdorner adorner = new DrawingRubberbandAdorner(this, currentPoint);
|
|
|
|
|
|
if (adorner != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
adornerLayer.Add(adorner);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-05-21 22:06:59 +08:00
|
|
|
|
else if (_service.DrawModeViewModel.LineDrawModeSelected)//画线模式,可以不命中实体
|
|
|
|
|
|
{
|
|
|
|
|
|
if (SourceConnector == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
//新建一个Part连接点
|
|
|
|
|
|
SourceConnector = new Connector() { Content = new PartCreatedConnectorInfo(currentPoint.X, currentPoint.Y), Tag = "虚拟的连接点" };
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-04-08 14:22:12 +08:00
|
|
|
|
e.Handled = true;
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void OnMouseMove(MouseEventArgs e)
|
|
|
|
|
|
{
|
2023-05-27 12:35:44 +08:00
|
|
|
|
//var focusedElement = Keyboard.FocusedElement;
|
|
|
|
|
|
//Debug.WriteLine("focusedElement:" + focusedElement?.ToString());
|
2023-04-08 14:22:12 +08:00
|
|
|
|
|
2021-07-23 09:42:22 +08:00
|
|
|
|
base.OnMouseMove(e);
|
|
|
|
|
|
|
2022-12-04 23:07:20 +08:00
|
|
|
|
if (_viewModel.IsReadOnly) return;
|
|
|
|
|
|
|
2021-07-23 09:42:22 +08:00
|
|
|
|
Point currentPoint = e.GetPosition(this);
|
2023-02-11 23:51:48 +08:00
|
|
|
|
_viewModel.CurrentPoint = new Point(ScreenHelper.WidthToMm(currentPoint.X), ScreenHelper.WidthToMm(currentPoint.Y));
|
2021-07-23 09:42:22 +08:00
|
|
|
|
var point = CursorPointManager.GetCursorPosition();
|
|
|
|
|
|
_viewModel.CurrentColor = ColorPickerManager.GetColor(point.X, point.Y);
|
|
|
|
|
|
|
2023-05-02 14:28:51 +08:00
|
|
|
|
//移动
|
2021-07-23 09:42:22 +08:00
|
|
|
|
if (_service.DrawModeViewModel.CursorMode == CursorMode.Move)
|
|
|
|
|
|
{
|
2023-01-26 20:05:21 +08:00
|
|
|
|
_viewModel.SelectedItems.OfType<DesignerItemViewModelBase>().ToList().ForEach(p => {
|
2021-07-23 09:42:22 +08:00
|
|
|
|
p.Left = currentPoint.X;
|
|
|
|
|
|
p.Top = currentPoint.Y;
|
|
|
|
|
|
});
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (SourceConnector != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (e.LeftButton == MouseButtonState.Pressed)
|
|
|
|
|
|
{
|
2023-06-11 23:58:22 +08:00
|
|
|
|
_partialConnection.SinkConnectorInfo = new PartCreatedConnectorInfo(currentPoint.X, currentPoint.Y);
|
2023-05-03 18:35:01 +08:00
|
|
|
|
|
|
|
|
|
|
SinkConnector = HitTesting(currentPoint);
|
|
|
|
|
|
if (SinkConnector?.Info?.CanAttachTo(SourceConnector?.Info) == false)
|
|
|
|
|
|
{
|
|
|
|
|
|
SinkConnector.Info.DisableAttachTo = true;
|
|
|
|
|
|
}
|
2023-01-26 20:05:21 +08:00
|
|
|
|
|
2023-05-07 23:01:38 +08:00
|
|
|
|
if (_viewModel.DiagramOption.SnappingOption.EnableSnapping)
|
2023-01-26 20:05:21 +08:00
|
|
|
|
{
|
2023-06-11 23:58:22 +08:00
|
|
|
|
var nearPort = _viewModel.FindNearPortToAttachTo(_partialConnection);
|
2023-05-03 13:28:16 +08:00
|
|
|
|
if (nearPort != null)
|
2023-01-26 20:05:21 +08:00
|
|
|
|
{
|
2023-06-11 23:58:22 +08:00
|
|
|
|
_partialConnection.SinkConnectorInfo = nearPort;
|
2023-01-26 20:05:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-06-11 23:58:22 +08:00
|
|
|
|
else if (SourceItemsContainer != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (e.LeftButton == MouseButtonState.Pressed)
|
|
|
|
|
|
{
|
|
|
|
|
|
SourceItemsContainer.DragObject.Left = currentPoint.X - SourceItemsContainer.DragOffset.X;
|
|
|
|
|
|
SourceItemsContainer.DragObject.Top = currentPoint.Y - SourceItemsContainer.DragOffset.Y;
|
|
|
|
|
|
|
2023-06-20 13:46:26 +08:00
|
|
|
|
(_viewModel as IBlockDiagramViewModel).PreviewNearBlock(new System.Collections.Generic.List<BlockDesignerItemViewModel> { SourceItemsContainer.DragObject });
|
2023-06-11 23:58:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-07-23 09:42:22 +08:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// if mouse button is not pressed we have no drag operation, ...
|
2023-05-02 14:28:51 +08:00
|
|
|
|
if (e.LeftButton != MouseButtonState.Pressed)
|
2021-07-23 09:42:22 +08:00
|
|
|
|
rubberbandSelectionStartPoint = null;
|
|
|
|
|
|
|
|
|
|
|
|
// ... but if mouse button is pressed and start
|
|
|
|
|
|
// point value is set we do have one
|
|
|
|
|
|
if (this.rubberbandSelectionStartPoint.HasValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
// create rubberband adorner
|
|
|
|
|
|
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this);
|
|
|
|
|
|
if (adornerLayer != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
RubberbandAdorner adorner = new RubberbandAdorner(this, rubberbandSelectionStartPoint);
|
|
|
|
|
|
if (adorner != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
adornerLayer.Add(adorner);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-04-08 14:22:12 +08:00
|
|
|
|
}
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
2023-04-08 14:22:12 +08:00
|
|
|
|
|
|
|
|
|
|
e.Handled = true;
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void OnMouseUp(MouseButtonEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnMouseUp(e);
|
|
|
|
|
|
|
2022-12-04 23:07:20 +08:00
|
|
|
|
if (_viewModel.IsReadOnly) return;
|
|
|
|
|
|
|
2021-07-23 09:42:22 +08:00
|
|
|
|
Mediator.Instance.NotifyColleagues<bool>("DoneDrawingMessage", true);
|
|
|
|
|
|
|
2023-05-03 18:35:01 +08:00
|
|
|
|
if (SourceConnector != null)
|
2021-07-23 09:42:22 +08:00
|
|
|
|
{
|
2023-05-03 18:35:01 +08:00
|
|
|
|
ConnectorInfoBase sourceDataItem = SourceConnector.Info;
|
|
|
|
|
|
if (SinkConnector != null && SinkConnector.Info?.DisableAttachTo == false)
|
2021-07-23 09:42:22 +08:00
|
|
|
|
{
|
2023-05-03 18:35:01 +08:00
|
|
|
|
ConnectorInfoBase sinkDataItem = SinkConnector.Info;
|
2023-05-02 14:28:51 +08:00
|
|
|
|
|
2023-06-11 23:58:22 +08:00
|
|
|
|
_viewModel.Delete(_partialConnection);
|
2023-05-21 22:06:59 +08:00
|
|
|
|
_viewModel.AddCommand.Execute(new ConnectionViewModel(_viewModel, sourceDataItem, sinkDataItem, LineDrawMode, RouterMode));
|
2023-01-26 20:05:21 +08:00
|
|
|
|
}
|
2023-06-11 23:58:22 +08:00
|
|
|
|
else if (_partialConnection.IsFullConnection)//自动连接模式
|
2023-01-26 20:05:21 +08:00
|
|
|
|
{
|
2023-06-28 12:06:58 +08:00
|
|
|
|
_viewModel.ClearAttachTo();
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
2023-05-03 09:59:46 +08:00
|
|
|
|
else if (_service.DrawModeViewModel.LineDrawModeSelected)
|
|
|
|
|
|
{
|
|
|
|
|
|
Point currentPoint = e.GetPosition(this);
|
|
|
|
|
|
ConnectorInfoBase sinkDataItem = new PartCreatedConnectorInfo(currentPoint.X, currentPoint.Y);
|
|
|
|
|
|
|
2023-06-11 23:58:22 +08:00
|
|
|
|
_viewModel.Delete(_partialConnection);
|
2023-05-21 22:06:59 +08:00
|
|
|
|
_viewModel.AddCommand.Execute(new ConnectionViewModel(_viewModel, sourceDataItem, sinkDataItem, LineDrawMode, RouterMode));
|
2023-05-03 09:59:46 +08:00
|
|
|
|
}
|
2021-07-23 09:42:22 +08:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
//Need to remove last item as we did not finish drawing the path
|
2023-06-11 23:58:22 +08:00
|
|
|
|
_viewModel.Delete(_partialConnection);
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-06-11 23:58:22 +08:00
|
|
|
|
else if (SourceItemsContainer != null)
|
|
|
|
|
|
{
|
2023-06-27 10:57:16 +08:00
|
|
|
|
(_viewModel as IBlockDiagramViewModel).FinishNearBlock(new System.Collections.Generic.List<BlockDesignerItemViewModel> { SourceItemsContainer.DragObject });
|
2023-06-11 23:58:22 +08:00
|
|
|
|
ExitCursor();
|
|
|
|
|
|
}
|
2023-01-26 20:05:21 +08:00
|
|
|
|
|
2023-05-03 18:35:01 +08:00
|
|
|
|
SourceConnector = null;
|
|
|
|
|
|
SinkConnector = null;
|
2023-06-11 23:58:22 +08:00
|
|
|
|
_partialConnection = null;
|
|
|
|
|
|
|
|
|
|
|
|
SourceItemsContainer = null;
|
2021-07-23 09:42:22 +08:00
|
|
|
|
|
2023-05-07 23:01:38 +08:00
|
|
|
|
_service.DrawModeViewModel.ResetDrawMode();
|
2023-03-12 15:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void OnPreviewKeyDown(KeyEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnPreviewKeyDown(e);
|
|
|
|
|
|
|
|
|
|
|
|
if (_viewModel.IsReadOnly) return;
|
|
|
|
|
|
|
|
|
|
|
|
e.Handled = _viewModel.ExecuteShortcut(e);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void OnPreviewMouseWheel(MouseWheelEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnPreviewMouseWheel(e);
|
|
|
|
|
|
|
|
|
|
|
|
if (Keyboard.IsKeyDown(Key.LeftCtrl) == false
|
|
|
|
|
|
&& Keyboard.IsKeyDown(Key.RightCtrl) == false)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var newZoomValue = _viewModel.ZoomValue + (e.Delta > 0 ? 0.1 : -0.1);
|
|
|
|
|
|
|
|
|
|
|
|
_viewModel.ZoomValue = Math.Max(Math.Min(newZoomValue, _viewModel.MaximumZoomValue), _viewModel.MinimumZoomValue);
|
|
|
|
|
|
|
|
|
|
|
|
e.Handled = true;
|
|
|
|
|
|
}
|
2021-08-01 22:30:12 +08:00
|
|
|
|
|
2021-07-23 09:42:22 +08:00
|
|
|
|
protected override Size MeasureOverride(Size constraint)
|
|
|
|
|
|
{
|
2024-01-01 20:37:06 +08:00
|
|
|
|
if (AutoGrowth)
|
2021-07-23 09:42:22 +08:00
|
|
|
|
{
|
2024-01-01 20:37:06 +08:00
|
|
|
|
Size size = new Size();
|
|
|
|
|
|
foreach (UIElement element in this.InternalChildren)
|
|
|
|
|
|
{
|
|
|
|
|
|
double left = Canvas.GetLeft(element);
|
|
|
|
|
|
double top = Canvas.GetTop(element);
|
|
|
|
|
|
left = double.IsNaN(left) ? 0 : left;
|
|
|
|
|
|
top = double.IsNaN(top) ? 0 : top;
|
2021-07-23 09:42:22 +08:00
|
|
|
|
|
2024-01-01 20:37:06 +08:00
|
|
|
|
//measure desired size for each child
|
|
|
|
|
|
element.Measure(constraint);
|
2021-07-23 09:42:22 +08:00
|
|
|
|
|
2024-01-01 20:37:06 +08:00
|
|
|
|
Size desiredSize = element.DesiredSize;
|
|
|
|
|
|
if (!double.IsNaN(desiredSize.Width) && !double.IsNaN(desiredSize.Height))
|
|
|
|
|
|
{
|
|
|
|
|
|
size.Width = Math.Max(size.Width, left + desiredSize.Width);
|
|
|
|
|
|
size.Height = Math.Max(size.Height, top + desiredSize.Height);
|
|
|
|
|
|
}
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
2024-01-01 20:37:06 +08:00
|
|
|
|
// add margin
|
|
|
|
|
|
size.Width += 10;
|
|
|
|
|
|
size.Height += 10;
|
2021-07-23 09:42:22 +08:00
|
|
|
|
|
2024-01-01 20:37:06 +08:00
|
|
|
|
return size;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
return base.MeasureOverride(constraint);
|
|
|
|
|
|
}
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-05-02 14:28:51 +08:00
|
|
|
|
private Connector HitTesting(Point hitPoint)
|
2021-07-23 09:42:22 +08:00
|
|
|
|
{
|
|
|
|
|
|
DependencyObject hitObject = this.InputHitTest(hitPoint) as DependencyObject;
|
|
|
|
|
|
while (hitObject != null &&
|
|
|
|
|
|
hitObject.GetType() != typeof(DesignerCanvas))
|
|
|
|
|
|
{
|
2023-04-08 14:22:12 +08:00
|
|
|
|
if (hitObject is Connector connector)
|
2021-07-23 09:42:22 +08:00
|
|
|
|
{
|
2023-05-03 09:59:46 +08:00
|
|
|
|
return connector;
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
hitObject = VisualTreeHelper.GetParent(hitObject);
|
|
|
|
|
|
}
|
2023-05-02 14:28:51 +08:00
|
|
|
|
|
|
|
|
|
|
return null;
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-06-11 23:58:22 +08:00
|
|
|
|
protected override void OnDragOver(DragEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
DragObject dragObject = e.Data.GetData(typeof(DragObject)) as DragObject;
|
|
|
|
|
|
if (dragObject != null && (dragObject.ContentType == typeof(BlockDesignerItemViewModel) || dragObject.ContentType.IsSubclassOf(typeof(BlockDesignerItemViewModel))))
|
|
|
|
|
|
{
|
2023-06-27 10:57:16 +08:00
|
|
|
|
var position = e.GetPosition(this);
|
2023-06-11 23:58:22 +08:00
|
|
|
|
|
|
|
|
|
|
BlockDesignerItemViewModel itemBase = Activator.CreateInstance(dragObject.ContentType) as BlockDesignerItemViewModel;
|
|
|
|
|
|
itemBase.Text = dragObject.Text;
|
|
|
|
|
|
itemBase.Icon = dragObject.Icon;
|
|
|
|
|
|
itemBase.ColorViewModel = CopyHelper.Mapper(dragObject.ColorViewModel);
|
|
|
|
|
|
if (dragObject.DesiredSize != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
itemBase.ItemWidth = dragObject.DesiredSize.Value.Width;
|
|
|
|
|
|
itemBase.ItemHeight = dragObject.DesiredSize.Value.Height;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (dragObject.DesiredMinSize != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
itemBase.MinItemWidth = dragObject.DesiredMinSize.Value.Width;
|
|
|
|
|
|
itemBase.MinItemHeight = dragObject.DesiredMinSize.Value.Height;
|
|
|
|
|
|
}
|
|
|
|
|
|
itemBase.Left = Math.Max(0, position.X - itemBase.GetItemWidth() / 2);
|
|
|
|
|
|
itemBase.Top = Math.Max(0, position.Y - itemBase.GetItemHeight() / 2);
|
|
|
|
|
|
|
2023-06-20 13:46:26 +08:00
|
|
|
|
(_viewModel as IBlockDiagramViewModel)?.PreviewNearBlock(new System.Collections.Generic.List<BlockDesignerItemViewModel> { itemBase });
|
2023-06-27 10:57:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-06-11 23:58:22 +08:00
|
|
|
|
base.OnDragOver(e);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-07-23 09:42:22 +08:00
|
|
|
|
protected override void OnDrop(DragEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnDrop(e);
|
2022-12-04 23:07:20 +08:00
|
|
|
|
|
2023-04-08 14:22:12 +08:00
|
|
|
|
if (_viewModel.IsReadOnly) return;
|
2022-12-04 23:07:20 +08:00
|
|
|
|
|
2021-07-23 09:42:22 +08:00
|
|
|
|
DragObject dragObject = e.Data.GetData(typeof(DragObject)) as DragObject;
|
|
|
|
|
|
if (dragObject != null)
|
|
|
|
|
|
{
|
2023-04-08 21:48:43 +08:00
|
|
|
|
_viewModel.ClearSelectedItems();
|
2023-04-08 14:22:12 +08:00
|
|
|
|
Point position = e.GetPosition(this);
|
2023-02-03 22:25:03 +08:00
|
|
|
|
if (dragObject.DesignerItem is SerializableObject serializableObject)
|
2021-07-23 09:42:22 +08:00
|
|
|
|
{
|
2023-02-03 22:25:03 +08:00
|
|
|
|
var designerItems = serializableObject.ToObject();
|
2023-02-03 22:36:08 +08:00
|
|
|
|
var minleft = designerItems.OfType<DesignerItemViewModelBase>().Min(p => p.Left);
|
|
|
|
|
|
var mintop = designerItems.OfType<DesignerItemViewModelBase>().Min(p => p.Top);
|
2023-06-11 23:58:22 +08:00
|
|
|
|
var maxright = designerItems.OfType<DesignerItemViewModelBase>().Max(p => p.Left + p.GetItemWidth());
|
|
|
|
|
|
var maxbottom = designerItems.OfType<DesignerItemViewModelBase>().Max(p => p.Top + p.GetItemHeight());
|
2023-02-03 22:36:08 +08:00
|
|
|
|
var itemswidth = maxright - minleft;
|
|
|
|
|
|
var itemsheight = maxbottom - mintop;
|
|
|
|
|
|
|
2023-02-03 18:23:53 +08:00
|
|
|
|
foreach (var item in designerItems.OfType<DesignerItemViewModelBase>())
|
|
|
|
|
|
{
|
2023-02-03 22:36:08 +08:00
|
|
|
|
item.Left += position.X - itemswidth / 2;
|
2023-04-08 14:22:12 +08:00
|
|
|
|
item.Top += position.Y - itemsheight / 2;
|
2023-02-03 18:23:53 +08:00
|
|
|
|
}
|
2023-05-21 22:06:59 +08:00
|
|
|
|
_viewModel.AddCommand.Execute(designerItems);
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
2023-08-27 16:02:28 +08:00
|
|
|
|
else if (dragObject.DesignerItem is SerializableItem serializableItem)
|
|
|
|
|
|
{
|
|
|
|
|
|
Type type = TypeHelper.GetType(serializableItem.ModelTypeName);
|
|
|
|
|
|
DesignerItemViewModelBase itemBase = Activator.CreateInstance(type, _viewModel, serializableItem, ".json") as DesignerItemViewModelBase;
|
|
|
|
|
|
itemBase.Left = Math.Max(0, position.X - itemBase.GetItemWidth() / 2);
|
|
|
|
|
|
itemBase.Top = Math.Max(0, position.Y - itemBase.GetItemHeight() / 2);
|
|
|
|
|
|
if (dragObject.DesiredSize != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
itemBase.ItemWidth = dragObject.DesiredSize.Value.Width;
|
|
|
|
|
|
itemBase.ItemHeight = dragObject.DesiredSize.Value.Height;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (dragObject.DesiredMinSize != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
itemBase.MinItemWidth = dragObject.DesiredMinSize.Value.Width;
|
|
|
|
|
|
itemBase.MinItemHeight = dragObject.DesiredMinSize.Value.Height;
|
|
|
|
|
|
}
|
|
|
|
|
|
_viewModel.AddCommand.Execute(itemBase);
|
|
|
|
|
|
|
|
|
|
|
|
if (itemBase is BlockDesignerItemViewModel block)
|
|
|
|
|
|
{
|
|
|
|
|
|
(_viewModel as IBlockDiagramViewModel).FinishNearBlock(new System.Collections.Generic.List<BlockDesignerItemViewModel> { block });
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-07-23 09:42:22 +08:00
|
|
|
|
else
|
|
|
|
|
|
{
|
2023-02-03 18:23:53 +08:00
|
|
|
|
DesignerItemViewModelBase itemBase = null;
|
|
|
|
|
|
if (dragObject.DesignerItem is DesignerItemBase)
|
|
|
|
|
|
{
|
|
|
|
|
|
itemBase = Activator.CreateInstance(dragObject.ContentType, _viewModel, dragObject.DesignerItem) as DesignerItemViewModelBase;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
2022-12-04 23:07:20 +08:00
|
|
|
|
{
|
2023-02-03 18:23:53 +08:00
|
|
|
|
itemBase = Activator.CreateInstance(dragObject.ContentType) as DesignerItemViewModelBase;
|
2023-07-20 22:40:04 +08:00
|
|
|
|
if (!string.IsNullOrEmpty(dragObject.Text))
|
|
|
|
|
|
itemBase.Text = dragObject.Text;
|
|
|
|
|
|
if (!string.IsNullOrEmpty(dragObject.Icon))
|
|
|
|
|
|
itemBase.Icon = dragObject.Icon;
|
2023-02-03 18:23:53 +08:00
|
|
|
|
itemBase.ColorViewModel = CopyHelper.Mapper(dragObject.ColorViewModel);
|
|
|
|
|
|
if (dragObject.DesiredSize != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
itemBase.ItemWidth = dragObject.DesiredSize.Value.Width;
|
|
|
|
|
|
itemBase.ItemHeight = dragObject.DesiredSize.Value.Height;
|
|
|
|
|
|
}
|
2023-06-11 23:58:22 +08:00
|
|
|
|
if (dragObject.DesiredMinSize != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
itemBase.MinItemWidth = dragObject.DesiredMinSize.Value.Width;
|
|
|
|
|
|
itemBase.MinItemHeight = dragObject.DesiredMinSize.Value.Height;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-12-04 23:07:20 +08:00
|
|
|
|
}
|
2023-06-11 23:58:22 +08:00
|
|
|
|
itemBase.Left = Math.Max(0, position.X - itemBase.GetItemWidth() / 2);
|
2023-06-27 10:57:16 +08:00
|
|
|
|
itemBase.Top = Math.Max(0, position.Y - itemBase.GetItemHeight() / 2);
|
2023-05-21 22:06:59 +08:00
|
|
|
|
_viewModel.AddCommand.Execute(itemBase);
|
2023-06-11 23:58:22 +08:00
|
|
|
|
|
|
|
|
|
|
if (itemBase is BlockDesignerItemViewModel block)
|
|
|
|
|
|
{
|
2023-06-20 13:46:26 +08:00
|
|
|
|
(_viewModel as IBlockDiagramViewModel).FinishNearBlock(new System.Collections.Generic.List<BlockDesignerItemViewModel> { block });
|
2023-06-11 23:58:22 +08:00
|
|
|
|
}
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-06-11 23:58:22 +08:00
|
|
|
|
else
|
2021-07-23 09:42:22 +08:00
|
|
|
|
{
|
2023-06-11 23:58:22 +08:00
|
|
|
|
var dragFile = e.Data.GetData(DataFormats.FileDrop);
|
|
|
|
|
|
if (dragFile != null && dragFile is string[] files)
|
2021-07-23 09:42:22 +08:00
|
|
|
|
{
|
2023-06-11 23:58:22 +08:00
|
|
|
|
foreach (var file in files)
|
|
|
|
|
|
{
|
|
|
|
|
|
_viewModel.ClearSelectedItems();
|
|
|
|
|
|
Point position = e.GetPosition(this);
|
|
|
|
|
|
ImageItemViewModel itemBase = new ImageItemViewModel();
|
|
|
|
|
|
itemBase.Icon = file;
|
|
|
|
|
|
itemBase.Suffix = System.IO.Path.GetExtension(itemBase.Icon).ToLower();
|
|
|
|
|
|
itemBase.InitWidthAndHeight();
|
|
|
|
|
|
itemBase.AutoSize();
|
|
|
|
|
|
|
|
|
|
|
|
itemBase.Left = Math.Max(0, position.X - itemBase.GetItemWidth() / 2);
|
|
|
|
|
|
itemBase.Top = Math.Max(0, position.Y - itemBase.GetItemHeight() / 2);
|
|
|
|
|
|
_viewModel.AddCommand.Execute(itemBase);
|
|
|
|
|
|
}
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-04-05 08:57:31 +08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
|
|
|
|
|
|
|
this.Focus();
|
2023-05-07 23:01:38 +08:00
|
|
|
|
}
|
2021-07-23 09:42:22 +08:00
|
|
|
|
}
|
2023-01-26 20:05:21 +08:00
|
|
|
|
}
|