Files
aistudio-wpf-diagram/AIStudio.Wpf.DiagramDesigner/Controls/DesignerCanvas.cs

1011 lines
39 KiB
C#
Raw Normal View History

2021-07-23 09:42:22 +08:00
using System;
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
{
#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;
}
}
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
_partialConnection = new ConnectionViewModel(_viewModel, sourceDataItem, new PartCreatedConnectorInfo(point.X, point.Y), LineDrawMode, RouterMode);
2023-05-02 14:28:51 +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-16 19:03:15 +08:00
private BlockItemsContainer _sourceItemsContainer;
public BlockItemsContainer SourceItemsContainer
{
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-17 23:55:54 +08:00
sourceContainerInfo.DataItem.RemoveChild(_sourceItemsContainer.DragObject, sourceContainerInfo);
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
{
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
{
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
#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;
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
}
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();
_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
}
#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);
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
}
#endregion
2021-07-23 09:42:22 +08:00
protected override void OnMouseDown(MouseButtonEventArgs e)
{
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)))
{
_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))
{
// create rubberband adorner
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this);
if (adornerLayer != null)
{
DrawingRubberbandAdorner adorner = new DrawingRubberbandAdorner(this, currentPoint);
if (adorner != null)
{
adornerLayer.Add(adorner);
}
}
}
else if (_service.DrawModeViewModel.LineDrawModeSelected)//画线模式,可以不命中实体
{
if (SourceConnector == null)
{
//新建一个Part连接点
SourceConnector = new Connector() { Content = new PartCreatedConnectorInfo(currentPoint.X, currentPoint.Y), Tag = "虚拟的连接点" };
}
}
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());
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)
{
_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
if (_viewModel.DiagramOption.SnappingOption.EnableSnapping)
2023-01-26 20:05:21 +08:00
{
var nearPort = _viewModel.FindNearPortToAttachTo(_partialConnection);
if (nearPort != null)
2023-01-26 20:05:21 +08:00
{
_partialConnection.SinkConnectorInfo = nearPort;
2023-01-26 20:05:21 +08:00
}
}
2021-07-23 09:42: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 });
}
}
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);
}
}
}
2021-07-23 09:42:22 +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
_viewModel.Delete(_partialConnection);
_viewModel.AddCommand.Execute(new ConnectionViewModel(_viewModel, sourceDataItem, sinkDataItem, LineDrawMode, RouterMode));
2023-01-26 20:05:21 +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);
_viewModel.Delete(_partialConnection);
_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
_viewModel.Delete(_partialConnection);
2021-07-23 09:42:22 +08:00
}
}
else if (SourceItemsContainer != null)
{
(_viewModel as IBlockDiagramViewModel).FinishNearBlock(new System.Collections.Generic.List<BlockDesignerItemViewModel> { SourceItemsContainer.DragObject });
ExitCursor();
}
2023-01-26 20:05:21 +08:00
2023-05-03 18:35:01 +08:00
SourceConnector = null;
SinkConnector = null;
_partialConnection = null;
SourceItemsContainer = null;
2021-07-23 09:42:22 +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-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))
{
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
}
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))))
{
var position = e.GetPosition(this);
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 });
}
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
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();
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);
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;
foreach (var item in designerItems.OfType<DesignerItemViewModelBase>())
{
2023-02-03 22:36:08 +08:00
item.Left += position.X - itemswidth / 2;
item.Top += position.Y - itemsheight / 2;
}
_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
{
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
{
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;
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;
}
2022-12-04 23:07:20 +08:00
}
itemBase.Left = Math.Max(0, position.X - itemBase.GetItemWidth() / 2);
itemBase.Top = Math.Max(0, position.Y - itemBase.GetItemHeight() / 2);
_viewModel.AddCommand.Execute(itemBase);
if (itemBase is BlockDesignerItemViewModel block)
{
2023-06-20 13:46:26 +08:00
(_viewModel as IBlockDiagramViewModel).FinishNearBlock(new System.Collections.Generic.List<BlockDesignerItemViewModel> { block });
}
2021-07-23 09:42:22 +08:00
}
}
else
2021-07-23 09:42: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
{
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();
}
2021-07-23 09:42:22 +08:00
}
2023-01-26 20:05:21 +08:00
}