Files
aistudio-wpf-diagram/AIStudio.Wpf.DiagramDesigner/Adorners/RubberbandAdorner.cs
2023-04-08 14:28:51 +08:00

257 lines
10 KiB
C#

using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System;
using System.Collections.Generic;
using System.Linq;
using AIStudio.Wpf.DiagramDesigner.ViewModels;
using AIStudio.Wpf.DiagramDesigner.ViewModels.BaseViewModel;
using System.Windows.Threading;
namespace AIStudio.Wpf.DiagramDesigner
{
public class RubberbandAdorner : Adorner
{
private Point? startPoint;
private Point? endPoint;
private List<Point> pointList = new List<Point>();
private Pen rubberbandPen;
private DesignerCanvas _designerCanvas;
private IDiagramViewModel _viewModel
{
get
{
return _designerCanvas.DataContext as IDiagramViewModel;
}
}
private IDiagramServiceProvider _service
{
get
{
return DiagramServicesProvider.Instance.Provider;
}
}
public RubberbandAdorner(DesignerCanvas designerCanvas, Point? dragStartPoint)
: base(designerCanvas)
{
this._designerCanvas = designerCanvas;
this._designerCanvas.Focus();
this.startPoint = dragStartPoint;
rubberbandPen = new Pen(Brushes.LightSlateGray, 1);
rubberbandPen.DashStyle = new DashStyle(new double[] { 2 }, 1);
}
protected override void OnMouseMove(System.Windows.Input.MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
if (!this.IsMouseCaptured)
this.CaptureMouse();
endPoint = e.GetPosition(this);
if (this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Polyline)
{
if (pointList.Count == 0 && this.startPoint.HasValue)
{
pointList.Add(this.startPoint.Value);
}
pointList.Add(endPoint.Value);
}
UpdateSelection();
this.InvalidateVisual();
}
else if (this._service.DrawModeViewModel.GetDrawMode() == DrawMode.DirectLine)
{
if (!this.IsMouseCaptured)
this.CaptureMouse();
endPoint = e.GetPosition(this);
if (pointList.Count == 0 && this.startPoint.HasValue)
{
pointList.Add(this.startPoint.Value);
}
UpdateSelection();
this.InvalidateVisual();
}
else
{
if (this.IsMouseCaptured) this.ReleaseMouseCapture();
}
e.Handled = true;
}
protected override void OnMouseUp(System.Windows.Input.MouseButtonEventArgs e)
{
if (this._service.DrawModeViewModel.GetDrawMode() == DrawMode.DirectLine && e.ChangedButton == MouseButton.Left)
{
//按着ctrl自动封闭曲线
if (Keyboard.IsKeyDown(Key.LeftCtrl) == true || Keyboard.IsKeyDown(Key.RightCtrl) == true)
{
pointList.Add(this.startPoint.Value);
}
else
{
endPoint = e.GetPosition(this);
pointList.Add(endPoint.Value);
UpdateSelection();
this.InvalidateVisual();
return;
}
}
// release mouse capture
if (this.IsMouseCaptured) this.ReleaseMouseCapture();
// remove this adorner from adorner layer
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this._designerCanvas);
if (adornerLayer != null)
adornerLayer.Remove(this);
if (this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Line ||
this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Rectangle ||
this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Ellipse ||
this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Polyline ||
this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Polygon ||
this._service.DrawModeViewModel.GetDrawMode() == DrawMode.DirectLine ||
this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Text)
{
if (this.startPoint.HasValue && this.endPoint.HasValue)
{
if (this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Text)
{
TextDesignerItemViewModel itemBase = new TextDesignerItemViewModel();
Point position = e.GetPosition(this);
itemBase.Left = Math.Min(this.startPoint.Value.X, this.endPoint.Value.X);
itemBase.Top = Math.Min(this.startPoint.Value.Y, this.endPoint.Value.Y);
itemBase.ItemWidth = Math.Abs(this.endPoint.Value.X - this.startPoint.Value.X);
itemBase.ItemHeight = Math.Abs(this.endPoint.Value.Y - this.startPoint.Value.Y);
_viewModel.AddItemCommand.Execute(itemBase);
}
else if (this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Polyline
|| this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Polygon
|| this._service.DrawModeViewModel.GetDrawMode() == DrawMode.DirectLine)
{
ShapeDesignerItemViewModel itemBase = new ShapeDesignerItemViewModel(this._service.DrawModeViewModel.GetDrawMode(), pointList);
_viewModel.AddItemCommand.Execute(itemBase);
}
else
{
ShapeDesignerItemViewModel itemBase = new ShapeDesignerItemViewModel(this._service.DrawModeViewModel.GetDrawMode(), new List<Point> { this.startPoint.Value, this.endPoint.Value });
_viewModel.AddItemCommand.Execute(itemBase);
}
}
this._service.DrawModeViewModel.ResetDrawMode();
}
e.Handled = true;
}
protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
// without a background the OnMouseMove event would not be fired !
// Alternative: implement a Canvas as a child of this adorner, like
// the ConnectionAdorner does.
dc.DrawRectangle(Brushes.Transparent, null, new Rect(RenderSize));
if (this.startPoint.HasValue && this.endPoint.HasValue)
{
if (this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Line)
{
dc.DrawLine(rubberbandPen, this.startPoint.Value, this.endPoint.Value);
}
else if (this._service.DrawModeViewModel.GetDrawMode() == DrawMode.Ellipse)
{
var centerPoint = new Point((this.startPoint.Value.X + this.endPoint.Value.X) / 2, (this.startPoint.Value.Y + this.endPoint.Value.Y) / 2);
dc.DrawEllipse(Brushes.Transparent, rubberbandPen, centerPoint, Math.Abs(this.startPoint.Value.X - this.endPoint.Value.X) / 2, Math.Abs(this.startPoint.Value.Y - this.endPoint.Value.Y) / 2);
}
else if (_service.DrawModeViewModel.GetDrawMode() == DrawMode.Polyline)
{
var disList = pointList.ToList();
for (int i = 1; i < pointList.Count; i++)
{
dc.DrawLine(rubberbandPen, disList[i - 1], disList[i]);
}
}
else if (_service.DrawModeViewModel.GetDrawMode() == DrawMode.DirectLine)
{
var disList = pointList.ToList();
//按着ctrl自动封闭曲线
if (Keyboard.IsKeyDown(Key.LeftCtrl) == true || Keyboard.IsKeyDown(Key.RightCtrl) == true)
{
disList.Add(this.startPoint.Value);
}
else
{
disList.Add(this.endPoint.Value);
}
for (int i = 1; i < disList.Count; i++)
{
dc.DrawLine(rubberbandPen, disList[i - 1], disList[i]);
}
}
else
{
dc.DrawRectangle(Brushes.Transparent, rubberbandPen, new Rect(this.startPoint.Value, this.endPoint.Value));
}
}
}
private T GetParent<T>(Type parentType, DependencyObject dependencyObject) where T : DependencyObject
{
DependencyObject parent = VisualTreeHelper.GetParent(dependencyObject);
if (parent.GetType() == parentType)
return (T)parent;
return GetParent<T>(parentType, parent);
}
private void UpdateSelection()
{
IDiagramViewModel vm = (_designerCanvas.DataContext as IDiagramViewModel);
Rect rubberBand = new Rect(startPoint.Value, endPoint.Value);
ItemsControl itemsControl = GetParent<ItemsControl>(typeof(ItemsControl), _designerCanvas);
foreach (SelectableDesignerItemViewModelBase item in vm.Items)
{
if (item is SelectableDesignerItemViewModelBase)
{
DependencyObject container = itemsControl.ItemContainerGenerator.ContainerFromItem(item);
Rect itemRect = VisualTreeHelper.GetDescendantBounds((Visual)container);
Rect itemBounds = ((Visual)container).TransformToAncestor(_designerCanvas).TransformBounds(itemRect);
if (rubberBand.Contains(itemBounds))
{
//item.IsSelected = true;
vm.SelectionService.AddToSelection(item);
}
else
{
if (!(Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)))
{
//item.IsSelected = false;
vm.SelectionService.RemoveFromSelection(item);
}
}
}
}
}
}
}