整理一下项目文件

This commit is contained in:
艾竹
2022-10-28 22:45:39 +08:00
parent 334297b074
commit 513937c1d6
598 changed files with 684 additions and 544 deletions

View File

@@ -0,0 +1,152 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
namespace AIStudio.Wpf.DiagramDesigner.Controls
{
public class BorderResizeThumb : Thumb
{
#region ResizeMode
/// <summary>
/// BindingWidthAndHeight Dependency Property
/// </summary>
public static readonly DependencyProperty ResizeModeProperty =
DependencyProperty.Register("ResizeMode", typeof(ResizeMode), typeof(BorderResizeThumb),
new FrameworkPropertyMetadata(ResizeMode.Size));
/// <summary>
/// Gets or sets the BindingWidthAndHeight property. This dependency property
/// indicates if the ResizableItemsControl is in Composing mode.
/// </summary>
public ResizeMode ResizeMode
{
get { return (ResizeMode)GetValue(ResizeModeProperty); }
set { SetValue(ResizeModeProperty, value); }
}
#endregion
#region ResizeElement
/// <summary>
/// BindingWidthAndHeight Dependency Property
/// </summary>
public static readonly DependencyProperty ResizeElementProperty =
DependencyProperty.Register("ResizeElement", typeof(FrameworkElement), typeof(BorderResizeThumb),
new FrameworkPropertyMetadata(null));
/// <summary>
/// Gets or sets the BindingWidthAndHeight property. This dependency property
/// indicates if the ResizableItemsControl is in Composing mode.
/// </summary>
public FrameworkElement ResizeElement
{
get { return (FrameworkElement)GetValue(ResizeElementProperty); }
set { SetValue(ResizeElementProperty, value); }
}
#endregion
public BorderResizeThumb()
{
base.DragDelta += new DragDeltaEventHandler(ResizeThumb_DragDelta);
}
void ResizeThumb_DragDelta(object sender, DragDeltaEventArgs e)
{
if (ResizeElement == null) return;
if (ResizeMode == ResizeMode.Size)
{
switch (base.VerticalAlignment)
{
case VerticalAlignment.Top:
if (ResizeElement.Height - e.VerticalChange > ResizeElement.MinHeight && ResizeElement.Height - e.VerticalChange < ResizeElement.MaxHeight)
{
ResizeElement.Height -= e.VerticalChange;
}
break;
case VerticalAlignment.Bottom:
if (ResizeElement.Height + e.VerticalChange > ResizeElement.MinHeight && ResizeElement.Height + e.VerticalChange < ResizeElement.MaxHeight)
{
ResizeElement.Height += e.VerticalChange;
}
break;
default:
break;
}
switch (base.HorizontalAlignment)
{
case HorizontalAlignment.Left:
if (ResizeElement.Width - e.HorizontalChange > ResizeElement.MinWidth && ResizeElement.Width - e.HorizontalChange < ResizeElement.MaxWidth)
{
ResizeElement.Width -= e.HorizontalChange;
}
break;
case HorizontalAlignment.Right:
if (ResizeElement.Width + e.HorizontalChange > ResizeElement.MinWidth && ResizeElement.Width + e.HorizontalChange < ResizeElement.MaxWidth)
{
ResizeElement.Width += e.HorizontalChange;
}
break;
default:
break;
}
}
else if (ResizeMode == ResizeMode.Margin)
{
switch (base.VerticalAlignment)
{
case VerticalAlignment.Top:
if (ResizeElement.Margin.Top + e.VerticalChange > 0)
{
ResizeElement.Margin = new Thickness(ResizeElement.Margin.Left, ResizeElement.Margin.Top + e.VerticalChange, ResizeElement.Margin.Right, ResizeElement.Margin.Bottom);
}
break;
case VerticalAlignment.Bottom:
if (ResizeElement.Margin.Bottom - e.VerticalChange > 0)
{
ResizeElement.Margin = new Thickness(ResizeElement.Margin.Left, ResizeElement.Margin.Top, ResizeElement.Margin.Right, ResizeElement.Margin.Bottom - e.VerticalChange);
}
break;
default:
break;
}
switch (base.HorizontalAlignment)
{
case HorizontalAlignment.Left:
if (ResizeElement.Margin.Left + e.HorizontalChange > 0)
{
ResizeElement.Margin = new Thickness(ResizeElement.Margin.Left + e.HorizontalChange, ResizeElement.Margin.Top, ResizeElement.Margin.Right, ResizeElement.Margin.Bottom);
}
break;
case HorizontalAlignment.Right:
if (ResizeElement.Margin.Right - e.HorizontalChange > 0)
{
ResizeElement.Margin = new Thickness(ResizeElement.Margin.Left, ResizeElement.Margin.Top, ResizeElement.Margin.Right - e.HorizontalChange, ResizeElement.Margin.Bottom);
}
break;
default:
break;
}
}
else if (ResizeMode == ResizeMode.DragMargin)
{
ResizeElement.Margin = new Thickness(ResizeElement.Margin.Left + e.HorizontalChange, ResizeElement.Margin.Top + e.VerticalChange, ResizeElement.Margin.Right - e.HorizontalChange, ResizeElement.Margin.Bottom - e.VerticalChange);
}
}
}
public enum ResizeMode
{
Size,
Margin,
DragMargin,
}
}

View File

@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AIStudio.Wpf.DiagramDesigner
{
/// <summary>
/// Provides a mechanism for constructing MenuItems
/// within a ViewModel
/// </summary>
/// <example>
/// <![CDATA[
///
/// AND IN VIEWMODEL C# DO THIS TO CREATE MENUS
/// private List<CinchMenuItem> CreateMenus()
/// {
/// var menu = new List<CinchMenuItem>();
/// //create the File Menu
/// var miFile = new CinchMenuItem("File");
/// var miExit = new CinchMenuItem("Exit");
/// miExit.Command = ExitApplicationCommand;
/// miFile.Children.Add(miExit);
/// menu.Add(miFile);
/// //create the Actions Menu
/// menu.Add(new CinchMenuItem("Actions"));
/// return menu;
/// }
///
///
/// public List<CinchMenuItem> MenuOptions
/// {
/// get
/// {
/// return CreateMenus();
/// }
/// }
///
/// AND IN XAML DO THE FOLLOWING FOR THE STYLE
/// <Style x:Key="ContextMenuItemStyle">
/// <Setter Property="MenuItem.Header" Value="{Binding Text}"/>
/// <Setter Property="MenuItem.ItemsSource" Value="{Binding Children}"/>
/// <Setter Property="MenuItem.Command" Value="{Binding Command}" />
/// <Setter Property="MenuItem.Icon" Value="{Binding Icon}" />
/// </Style>
///
/// AND YOU CAN CREATE A MENU LIKE THIS
/// <StackPanel Orientation="Horizontal">
/// <Image Source="{Binding Image}" Width="16" Height="16" />
/// <TextBlock Margin="5" HorizontalAlignment="Left" VerticalAlignment="Center"
/// Text="{Binding Header}" />
/// <StackPanel.ContextMenu>
/// <ContextMenu ItemContainerStyle="{StaticResource ContextMenuItemStyle}"
/// ItemsSource="{Binding MenuOptions}" />
/// </StackPanel.ContextMenu>
/// </StackPanel>
/// ]]>
/// </example>
public class CinchMenuItem
{
#region Public Properties
public String Text { get; set; }
public String IconUrl { get; set; }
public bool IsChecked { get; set; }
public bool IsCheckable { get; set; }
public List<CinchMenuItem> Children { get; private set; }
public Object CommandParameter { get; set; }
public SimpleCommand Command { get; set; }
#endregion
#region Ctor
public CinchMenuItem()
{
Children = new List<CinchMenuItem>();
}
public CinchMenuItem(string item)
{
Text = item;
Children = new List<CinchMenuItem>();
}
#endregion
}
}

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
namespace AIStudio.Wpf.DiagramDesigner
{
public class Connector : Control
{
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
DesignerCanvas canvas = GetDesignerCanvas(this);
if (canvas != null)
{
canvas.SourceConnector = this;
}
}
public ConnectorOrientation Orientation { get; set; }
// iterate through visual tree to get parent DesignerCanvas
private DesignerCanvas GetDesignerCanvas(DependencyObject element)
{
while (element != null && !(element is DesignerCanvas))
element = VisualTreeHelper.GetParent(element);
return element as DesignerCanvas;
}
}
}

View File

@@ -0,0 +1,516 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Xml;
using System.Linq;
using System.Windows.Shapes;
using System.Windows.Resources;
using System.Runtime.InteropServices;
namespace AIStudio.Wpf.DiagramDesigner
{
public class DesignerCanvas : Canvas
{
private IDiagramViewModel _viewModel { get { return DataContext as IDiagramViewModel; } }
private IDiagramServiceProvider _service { get { return DiagramServicesProvider.Instance.Provider; } }
private ConnectorViewModel partialConnection;
private List<Connector> connectorsHit = new List<Connector>();
private Point? rubberbandSelectionStartPoint = null;
#region GridCellSize
public static readonly DependencyProperty GridCellSizeProperty =
DependencyProperty.Register("GridCellSize",
typeof(Size),
typeof(DesignerCanvas),
new FrameworkPropertyMetadata(new Size(50, 50), FrameworkPropertyMetadataOptions.AffectsRender));
public Size GridCellSize
{
get { return (Size)GetValue(GridCellSizeProperty); }
set { SetValue(GridCellSizeProperty, value); }
}
#endregion
#region ShowGrid
public static readonly DependencyProperty ShowGridProperty =
DependencyProperty.Register("ShowGrid",
typeof(bool),
typeof(DesignerCanvas),
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender));
public bool ShowGrid
{
get { return (bool)GetValue(ShowGridProperty); }
set { SetValue(ShowGridProperty, value); }
}
#endregion
#region GridColor
public static readonly DependencyProperty GridColorProperty =
DependencyProperty.Register("GridColor",
typeof(Color),
typeof(DesignerCanvas),
new FrameworkPropertyMetadata(Colors.LightGray, FrameworkPropertyMetadataOptions.AffectsRender));
public Color GridColor
{
get { return (Color)GetValue(GridColorProperty); }
set { SetValue(GridColorProperty, value); }
}
#endregion
#region GridMargin mm
public static readonly DependencyProperty GridMarginProperty =
DependencyProperty.Register("GridMargin",
typeof(double),
typeof(DesignerCanvas),
new FrameworkPropertyMetadata(28d, FrameworkPropertyMetadataOptions.AffectsRender));
public double GridMargin
{
get { return (double)GetValue(GridMarginProperty); }
set { SetValue(GridMarginProperty, value); }
}
#endregion
public DesignerCanvas()
{
this.AllowDrop = true;
Mediator.Instance.Register(this);
_service.PropertyChanged += _service_PropertyChanged;
}
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);
}
protected virtual void DrawGrid(DrawingContext dc, Rect rect)
{
//using .5 forces wpf to draw a single pixel line
for (var i = GridMargin + 0.5; i < rect.Height - GridMargin; i += GridCellSize.Height)
dc.DrawLine(new Pen(new SolidColorBrush(GridColor), 1), new Point(GridMargin, i), new Point(rect.Width - GridMargin, i));
dc.DrawLine(new Pen(new SolidColorBrush(GridColor), 1), new Point(GridMargin, rect.Height - GridMargin), new Point(rect.Width - GridMargin, rect.Height - GridMargin));
for (var i = GridMargin + 0.5; i < rect.Width - GridMargin; i += GridCellSize.Width)
dc.DrawLine(new Pen(new SolidColorBrush(GridColor), 1), new Point(i, GridMargin), new Point(i, rect.Height - GridMargin));
dc.DrawLine(new Pen(new SolidColorBrush(GridColor), 1), new Point(rect.Width - GridMargin, GridMargin), new Point(rect.Width - GridMargin, rect.Height - GridMargin));
}
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();
}
}
}
}
#region Format/Move
private void EnterFormat()
{
StreamResourceInfo sri = Application.GetResourceStream(new Uri("pack://application:,,,/AIStudio.Wpf.DiagramDesigner;component/Images/FormatPainter.cur", UriKind.RelativeOrAbsolute));
this.Cursor = new Cursor(sri.Stream);
foreach (SelectableDesignerItemViewModelBase item in _viewModel.Items)
{
item.IsHitTestVisible = false;
}
}
private void EnterMove()
{
this.Cursor = Cursors.SizeAll;
foreach (SelectableDesignerItemViewModelBase item in _viewModel.Items)
{
item.IsHitTestVisible = false;
}
}
private void ExitCursor()
{
this.Cursor = Cursors.Arrow;
foreach (SelectableDesignerItemViewModelBase item in _viewModel.Items)
{
item.IsHitTestVisible = true;
}
_service.DrawModeViewModel.CursorMode = CursorMode.Normal;
}
#endregion
private void Format(SelectableDesignerItemViewModelBase source, SelectableDesignerItemViewModelBase target)
{
CopyHelper.CopyPropertyValue(source.ColorViewModel, target.ColorViewModel);
CopyHelper.CopyPropertyValue(source.FontViewModel, target.FontViewModel);
}
private Connector sourceConnector;
public Connector SourceConnector
{
get { return sourceConnector; }
set
{
if (sourceConnector != value)
{
sourceConnector = value;
connectorsHit.Add(sourceConnector);
FullyCreatedConnectorInfo sourceDataItem = sourceConnector.DataContext as FullyCreatedConnectorInfo;
Rect rectangleBounds = sourceConnector.TransformToVisual(this).TransformBounds(new Rect(sourceConnector.RenderSize));
Point point = new Point(rectangleBounds.Left + (rectangleBounds.Width / 2),
rectangleBounds.Bottom + (rectangleBounds.Height / 2));
partialConnection = new ConnectorViewModel(sourceDataItem, new PartCreatedConnectionInfo(point), _service.DrawModeViewModel.VectorLineDrawMode);
_viewModel.DirectAddItemCommand.Execute(partialConnection);
}
}
}
private FullyCreatedConnectorInfo sourceConnectorInfo;
public FullyCreatedConnectorInfo SourceConnectorInfo
{
get { return sourceConnectorInfo; }
set
{
if (sourceConnectorInfo != value)
{
sourceConnectorInfo = value;
sourceConnector = new Connector() { Name = "占位" };//占位使用
connectorsHit.Add(sourceConnector);
Rect rectangleBounds = new Rect(sourceConnectorInfo.DataItem.Left, sourceConnectorInfo.DataItem.Top, 3, 3);
Point point = new Point(rectangleBounds.Left + (rectangleBounds.Width / 2),
rectangleBounds.Bottom + (rectangleBounds.Height / 2));
partialConnection = new ConnectorViewModel(sourceConnectorInfo, new PartCreatedConnectionInfo(point), _service.DrawModeViewModel.VectorLineDrawMode);
_viewModel.DirectAddItemCommand.Execute(partialConnection);
}
}
}
protected override void OnMouseDown(MouseButtonEventArgs e)
{
base.OnMouseDown(e);
if (_service.DrawModeViewModel.CursorMode == CursorMode.Format)
{
var element = (e.OriginalSource as FrameworkElement);
if (element.DataContext is SelectableDesignerItemViewModelBase target)
{
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
rubberbandSelectionStartPoint = e.GetPosition(this);
IDiagramViewModel vm = (this.DataContext as IDiagramViewModel);
if (!(Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)))
{
vm.ClearSelectedItemsCommand.Execute(null);
}
e.Handled = true;
if (_service.DrawModeViewModel.GetDrawMode() == DrawMode.ConnectingLine)
{
if (connectorsHit.Count == 0)
{
LinkPointDesignerItemViewModel pointItemView = new LinkPointDesignerItemViewModel(rubberbandSelectionStartPoint.Value);
_viewModel.DirectAddItemCommand.Execute(pointItemView);
SourceConnectorInfo = pointItemView.TopConnector;
}
}
}
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
Point currentPoint = e.GetPosition(this);
_viewModel.CurrentPoint = currentPoint;
var point = CursorPointManager.GetCursorPosition();
_viewModel.CurrentColor = ColorPickerManager.GetColor(point.X, point.Y);
if (_service.DrawModeViewModel.CursorMode == CursorMode.Move)
{
_viewModel.SelectedItems.OfType<DesignerItemViewModelBase>().ToList().ForEach(p =>
{
p.Left = currentPoint.X;
p.Top = currentPoint.Y;
});
return;
}
if (SourceConnector != null)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
partialConnection.SinkConnectorInfo = new PartCreatedConnectionInfo(currentPoint);
HitTesting(currentPoint);
}
}
else
{
// if mouse button is not pressed we have no drag operation, ...
if (e.LeftButton != MouseButtonState.Pressed && _service.DrawModeViewModel.GetDrawMode() != DrawMode.DirectLine)
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);
}
}
}
}
e.Handled = true;
}
protected override void OnMouseUp(MouseButtonEventArgs e)
{
base.OnMouseUp(e);
if (_service.DrawModeViewModel.GetDrawMode() == DrawMode.DirectLine)
{
return;
}
Mediator.Instance.NotifyColleagues<bool>("DoneDrawingMessage", true);
if (sourceConnector != null)
{
FullyCreatedConnectorInfo sourceDataItem = sourceConnectorInfo ?? (sourceConnector.DataContext as FullyCreatedConnectorInfo);
if (connectorsHit.Count() == 2)
{
Connector sinkConnector = connectorsHit.Last();
FullyCreatedConnectorInfo sinkDataItem = sinkConnector.DataContext as FullyCreatedConnectorInfo;
int indexOfLastTempConnection = sinkDataItem.DataItem.Parent.Items.Count - 1;
sinkDataItem.DataItem.Parent.DirectRemoveItemCommand.Execute(
sinkDataItem.DataItem.Parent.Items[indexOfLastTempConnection]);
sinkDataItem.DataItem.Parent.AddItemCommand.Execute(new ConnectorViewModel(sourceDataItem, sinkDataItem, _service.DrawModeViewModel.VectorLineDrawMode));
}
else if (_service.DrawModeViewModel.GetDrawMode() == DrawMode.ConnectingLine && connectorsHit.Count() == 1)
{
LinkPointDesignerItemViewModel pointItemView = new LinkPointDesignerItemViewModel(e.GetPosition(this));
FullyCreatedConnectorInfo sinkDataItem = pointItemView.TopConnector;
int indexOfLastTempConnection = _viewModel.Items.Count - 1;
_viewModel.DirectRemoveItemCommand.Execute(_viewModel.Items[indexOfLastTempConnection]);
_viewModel.DirectAddItemCommand.Execute(pointItemView);
var connector = new ConnectorViewModel(sourceDataItem, sinkDataItem, _service.DrawModeViewModel.VectorLineDrawMode);
_viewModel.AddItemCommand.Execute(connector);
sourceDataItem.DataItem.ZIndex++;
connector.ZIndex--;
}
else
{
//Need to remove last item as we did not finish drawing the path
int indexOfLastTempConnection = sourceDataItem.DataItem.Parent.Items.Count - 1;
sourceDataItem.DataItem.Parent.DirectRemoveItemCommand.Execute(
sourceDataItem.DataItem.Parent.Items[indexOfLastTempConnection]);
}
}
connectorsHit = new List<Connector>();
sourceConnector = null;
sourceConnectorInfo = null;
_service.DrawModeViewModel.ResetDrawMode();
}
protected override void OnPreviewKeyDown(KeyEventArgs e)
{
base.OnPreviewKeyDown(e);
if (e.Key == Key.Left)
{
if (_viewModel.SelectedItems != null)
{
foreach(var item in _viewModel.SelectedItems.OfType<DesignerItemViewModelBase>())
{
item.Left -= 0.1;
}
}
}
else if (e.Key == Key.Right)
{
if (_viewModel.SelectedItems != null)
{
foreach (var item in _viewModel.SelectedItems.OfType<DesignerItemViewModelBase>())
{
item.Left += 0.1;
}
}
}
else if (e.Key == Key.Up)
{
if (_viewModel.SelectedItems != null)
{
foreach (var item in _viewModel.SelectedItems.OfType<DesignerItemViewModelBase>())
{
item.Top -= 0.1;
}
}
}
else if (e.Key == Key.Down)
{
if (_viewModel.SelectedItems != null)
{
foreach (var item in _viewModel.SelectedItems.OfType<DesignerItemViewModelBase>())
{
item.Top += 0.1;
}
}
}
}
protected override Size MeasureOverride(Size constraint)
{
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;
//measure desired size for each child
element.Measure(constraint);
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);
}
}
// add margin
size.Width += 10;
size.Height += 10;
return size;
}
private void HitTesting(Point hitPoint)
{
DependencyObject hitObject = this.InputHitTest(hitPoint) as DependencyObject;
while (hitObject != null &&
hitObject.GetType() != typeof(DesignerCanvas))
{
if (hitObject is Connector)
{
if (connectorsHit.Any(p => p.Name == "占位"))
{
connectorsHit.Remove(connectorsHit.FirstOrDefault(p => p.Name == "占位"));
}
if (!connectorsHit.Contains(hitObject as Connector))
connectorsHit.Add(hitObject as Connector);
}
hitObject = VisualTreeHelper.GetParent(hitObject);
}
}
protected override void OnDrop(DragEventArgs e)
{
base.OnDrop(e);
DragObject dragObject = e.Data.GetData(typeof(DragObject)) as DragObject;
if (dragObject != null)
{
(DataContext as IDiagramViewModel).ClearSelectedItemsCommand.Execute(null);
Point position = e.GetPosition(this);
DesignerItemViewModelBase itemBase = null;
if (dragObject.DesignerItem != null)
{
itemBase = (DesignerItemViewModelBase)Activator.CreateInstance(dragObject.ContentType, null, dragObject.DesignerItem);
}
else
{
itemBase = (DesignerItemViewModelBase)Activator.CreateInstance(dragObject.ContentType);
itemBase.Icon = dragObject.Icon;
itemBase.ColorViewModel = CopyHelper.Mapper(dragObject.ColorViewModel);
}
itemBase.Left = Math.Max(0, position.X - itemBase.ItemWidth / 2);
itemBase.Top = Math.Max(0, position.Y - itemBase.ItemHeight / 2);
(DataContext as IDiagramViewModel).AddItemCommand.Execute(itemBase);
}
var dragFile = e.Data.GetData(DataFormats.FileDrop);
if (dragFile != null && dragFile is string[] files)
{
foreach (var file in files)
{
(DataContext as IDiagramViewModel).ClearSelectedItemsCommand.Execute(null);
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.ItemWidth / 2);
itemBase.Top = Math.Max(0, position.Y - itemBase.ItemHeight / 2);
(DataContext as IDiagramViewModel).AddItemCommand.Execute(itemBase);
}
}
e.Handled = true;
}
}
}

View File

@@ -0,0 +1,110 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
namespace AIStudio.Wpf.DiagramDesigner.Controls
{
public class DragThumb : Thumb
{
public DragThumb()
{
base.DragDelta += new DragDeltaEventHandler(DragThumb_DragDelta);
base.DragStarted += DragThumb_DragStarted;
base.DragCompleted += DragThumb_DragCompleted;
}
private List<SelectableDesignerItemViewModelBase> designerItems;
private void DragThumb_DragStarted(object sender, DragStartedEventArgs e)
{
SelectableDesignerItemViewModelBase designerItem = this.DataContext as SelectableDesignerItemViewModelBase;
if (designerItem != null && designerItem.IsSelected)
{
// we only move DesignerItems
designerItems = designerItem.SelectedItems.ToList();
if (designerItem is ConnectorViewModel connector)
{
designerItems.Add(connector.SourceConnectorInfo.DataItem);
designerItems.Add((connector.SinkConnectorInfo as FullyCreatedConnectorInfo).DataItem);
if (designerItem.OutTextItem != null)
{
designerItems.Remove(designerItem.OutTextItem);//这个自动计算位置
}
}
if (designerItem is PointDesignerItemViewModel)
{
designerItems = new List<SelectableDesignerItemViewModelBase> { designerItem };
}
foreach (DesignerItemViewModelBase item in designerItems.OfType<DesignerItemViewModelBase>())
{
item.BeginDo = true;
item.SetOldValue(item.Left, nameof(item.Left));
item.SetOldValue(item.Top, nameof(item.Top));
}
e.Handled = true;
}
else
{
designerItems = null;
}
}
private void DragThumb_DragCompleted(object sender, DragCompletedEventArgs e)
{
if (designerItems != null)
{
foreach (DesignerItemViewModelBase item in designerItems.OfType<DesignerItemViewModelBase>())
{
item.SetCellAlignment();
item.BeginDo = false;
item.RaiseTopLeft();
}
e.Handled = true;
}
}
void DragThumb_DragDelta(object sender, DragDeltaEventArgs e)
{
if (designerItems != null)
{
double minLeft = double.MaxValue;
double minTop = double.MaxValue;
foreach (DesignerItemViewModelBase item in designerItems.OfType<DesignerItemViewModelBase>())
{
double left = item.Left;
double top = item.Top;
minLeft = double.IsNaN(left) ? 0 : Math.Min(left, minLeft);
minTop = double.IsNaN(top) ? 0 : Math.Min(top, minTop);
double deltaHorizontal = Math.Max(-minLeft, e.HorizontalChange);
double deltaVertical = Math.Max(-minTop, e.VerticalChange);
item.Left += deltaHorizontal;
item.Top += deltaVertical;
}
e.Handled = true;
}
}
private DesignerCanvas GetDesignerCanvas(DependencyObject element)
{
while (element != null && !(element is DesignerCanvas))
element = VisualTreeHelper.GetParent(element);
return element as DesignerCanvas;
}
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
namespace AIStudio.Wpf.DiagramDesigner
{
public class PointConnector : Control
{
}
}

View File

@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
namespace AIStudio.Wpf.DiagramDesigner.Controls
{
public class PointDragThumb : Thumb
{
public PointDragThumb()
{
base.DragDelta += new DragDeltaEventHandler(DragThumb_DragDelta);
base.DragStarted += DragThumb_DragStarted;
base.DragCompleted += DragThumb_DragCompleted;
}
private void DragThumb_DragStarted(object sender, DragStartedEventArgs e)
{
}
private void DragThumb_DragCompleted(object sender, DragCompletedEventArgs e)
{
}
void DragThumb_DragDelta(object sender, DragDeltaEventArgs e)
{
if (this.DataContext is PointInfoBase point)
{
double minLeft = double.MaxValue;
double minTop = double.MaxValue;
double left = point.X;
double top = point.Y;
minLeft = double.IsNaN(left) ? 0 : Math.Min(left, minLeft);
minTop = double.IsNaN(top) ? 0 : Math.Min(top, minTop);
double deltaHorizontal = Math.Max(-minLeft, e.HorizontalChange);
double deltaVertical = Math.Max(-minTop, e.VerticalChange);
point.X += deltaHorizontal;
point.Y += deltaVertical;
}
}
}
}

View File

@@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace AIStudio.Wpf.DiagramDesigner
{
public class RelativePositionPanel : Panel
{
public static readonly DependencyProperty RelativePositionProperty =
DependencyProperty.RegisterAttached("RelativePosition", typeof(Point), typeof(RelativePositionPanel),
new FrameworkPropertyMetadata(new Point(0, 0),
new PropertyChangedCallback(RelativePositionPanel.OnRelativePositionChanged)));
public static Point GetRelativePosition(UIElement element)
{
if (element == null)
{
throw new ArgumentNullException("element");
}
return (Point)element.GetValue(RelativePositionProperty);
}
public static void SetRelativePosition(UIElement element, Point value)
{
if (element == null)
{
throw new ArgumentNullException("element");
}
element.SetValue(RelativePositionProperty, value);
}
private static void OnRelativePositionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
UIElement reference = d as UIElement;
if (reference != null)
{
RelativePositionPanel parent = VisualTreeHelper.GetParent(reference) as RelativePositionPanel;
if (parent != null)
{
parent.InvalidateArrange();
}
}
}
protected override Size ArrangeOverride(Size arrangeSize)
{
foreach (UIElement element in base.InternalChildren)
{
if (element != null)
{
Point relPosition = GetRelativePosition(element);
double x = (arrangeSize.Width - element.DesiredSize.Width) * relPosition.X;
double y = (arrangeSize.Height - element.DesiredSize.Height) * relPosition.Y;
if (double.IsNaN(x)) x = 0;
if (double.IsNaN(y)) y = 0;
element.Arrange(new Rect(new Point(x, y), element.DesiredSize));
}
}
return arrangeSize;
}
protected override Size MeasureOverride(Size availableSize)
{
Size size = new Size(double.PositiveInfinity, double.PositiveInfinity);
// SDK docu says about InternalChildren Property: 'Classes that are derived from Panel
// should use this property, instead of the Children property, for internal overrides
// such as MeasureCore and ArrangeCore.
foreach (UIElement element in this.InternalChildren)
{
if (element != null)
element.Measure(size);
}
return base.MeasureOverride(availableSize);
}
}
}

View File

@@ -0,0 +1,196 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
namespace AIStudio.Wpf.DiagramDesigner.Controls
{
public class ResizeThumb : Thumb
{
public ResizeThumb()
{
base.DragDelta += new DragDeltaEventHandler(ResizeThumb_DragDelta);
base.DragStarted += ResizeThumb_DragStarted;
base.DragCompleted += ResizeThumb_DragCompleted;
}
private List<SelectableDesignerItemViewModelBase> designerItems;
IDiagramViewModel diagarmViewModel;
private void ResizeThumb_DragStarted(object sender, DragStartedEventArgs e)
{
DesignerItemViewModelBase designerItem = this.DataContext as DesignerItemViewModelBase;
diagarmViewModel = designerItem.Parent;
if (designerItem != null && designerItem.IsSelected)
{
designerItems = designerItem.SelectedItems.ToList();
foreach (DesignerItemViewModelBase item in designerItems.OfType<DesignerItemViewModelBase>())
{
item.BeginDo = true;
item.SetOldValue(item.ItemWidth, nameof(item.ItemWidth));
item.SetOldValue(item.ItemHeight, nameof(item.ItemHeight));
}
e.Handled = true;
}
else
{
designerItems = null;
}
}
private void ResizeThumb_DragCompleted(object sender, DragCompletedEventArgs e)
{
if (designerItems != null)
{
foreach (DesignerItemViewModelBase item in designerItems.OfType<DesignerItemViewModelBase>())
{
item.BeginDo = false;
item.RaiseItemWidthHeight();
}
e.Handled = true;
}
}
void ResizeThumb_DragDelta(object sender, DragDeltaEventArgs e)
{
if (designerItems != null)
{
double minLeft, minTop, minDeltaHorizontal, minDeltaVertical;
double dragDeltaVertical, dragDeltaHorizontal, scale;
CalculateDragLimits(designerItems.OfType<DesignerItemViewModelBase>(), out minLeft, out minTop,
out minDeltaHorizontal, out minDeltaVertical);
foreach (DesignerItemViewModelBase item in designerItems.OfType<DesignerItemViewModelBase>())
{
if (item != null && item.ParentId == Guid.Empty)
{
switch (base.VerticalAlignment)
{
case VerticalAlignment.Bottom:
dragDeltaVertical = Math.Min(-e.VerticalChange, minDeltaVertical);
scale = (item.ItemHeight - dragDeltaVertical) / item.ItemHeight;
DragBottom(scale, item, diagarmViewModel.SelectionService);
break;
case VerticalAlignment.Top:
double top = item.Top;
dragDeltaVertical = Math.Min(Math.Max(-minTop, e.VerticalChange), minDeltaVertical);
scale = (item.ItemHeight - dragDeltaVertical) / item.ItemHeight;
DragTop(scale, item, diagarmViewModel.SelectionService);
break;
default:
break;
}
switch (base.HorizontalAlignment)
{
case HorizontalAlignment.Left:
double left = item.Left;
dragDeltaHorizontal = Math.Min(Math.Max(-minLeft, e.HorizontalChange), minDeltaHorizontal);
scale = (item.ItemWidth - dragDeltaHorizontal) / item.ItemWidth;
DragLeft(scale, item, diagarmViewModel.SelectionService);
break;
case HorizontalAlignment.Right:
dragDeltaHorizontal = Math.Min(-e.HorizontalChange, minDeltaHorizontal);
scale = (item.ItemWidth - dragDeltaHorizontal) / item.ItemWidth;
DragRight(scale, item, diagarmViewModel.SelectionService);
break;
default:
break;
}
}
}
e.Handled = true;
}
}
#region Helper methods
private void DragLeft(double scale, DesignerItemViewModelBase item, SelectionService selectionService)
{
IEnumerable<DesignerItemViewModelBase> groupItems = selectionService.GetGroupMembers(item).Cast<DesignerItemViewModelBase>();
double groupLeft = item.Left + item.ItemWidth;
foreach (DesignerItemViewModelBase groupItem in groupItems)
{
double groupItemLeft = groupItem.Left;
double delta = (groupLeft - groupItemLeft) * (scale - 1);
groupItem.Left = groupItemLeft - delta;
groupItem.ItemWidth = groupItem.ItemWidth * scale;
}
}
private void DragTop(double scale, DesignerItemViewModelBase item, SelectionService selectionService)
{
IEnumerable<DesignerItemViewModelBase> groupItems = selectionService.GetGroupMembers(item).Cast<DesignerItemViewModelBase>();
double groupBottom = item.Top + item.ItemHeight;
foreach (DesignerItemViewModelBase groupItem in groupItems)
{
double groupItemTop = groupItem.Top;
double delta = (groupBottom - groupItemTop) * (scale - 1);
groupItem.Top = groupItemTop - delta;
groupItem.ItemHeight = groupItem.ItemHeight * scale;
}
}
private void DragRight(double scale, DesignerItemViewModelBase item, SelectionService selectionService)
{
IEnumerable<DesignerItemViewModelBase> groupItems = selectionService.GetGroupMembers(item).Cast<DesignerItemViewModelBase>();
double groupLeft = item.Left;
foreach (DesignerItemViewModelBase groupItem in groupItems)
{
double groupItemLeft = groupItem.Left;
double delta = (groupItemLeft - groupLeft) * (scale - 1);
groupItem.Left = groupItemLeft + delta;
groupItem.ItemWidth = groupItem.ItemWidth * scale;
}
}
private void DragBottom(double scale, DesignerItemViewModelBase item, SelectionService selectionService)
{
IEnumerable<DesignerItemViewModelBase> groupItems = selectionService.GetGroupMembers(item).Cast<DesignerItemViewModelBase>();
double groupTop = item.Top;
foreach (DesignerItemViewModelBase groupItem in groupItems)
{
double groupItemTop = groupItem.Top;
double delta = (groupItemTop - groupTop) * (scale - 1);
groupItem.Top = groupItemTop + delta;
groupItem.ItemHeight = groupItem.ItemHeight * scale;
}
}
private void CalculateDragLimits(IEnumerable<DesignerItemViewModelBase> selectedItems, out double minLeft, out double minTop, out double minDeltaHorizontal, out double minDeltaVertical)
{
minLeft = double.MaxValue;
minTop = double.MaxValue;
minDeltaHorizontal = double.MaxValue;
minDeltaVertical = double.MaxValue;
// drag limits are set by these parameters: canvas top, canvas left, minHeight, minWidth
// calculate min value for each parameter for each item
foreach (DesignerItemViewModelBase item in selectedItems)
{
double left = item.Left;
double top = item.Top;
minLeft = double.IsNaN(left) ? 0 : Math.Min(left, minLeft);
minTop = double.IsNaN(top) ? 0 : Math.Min(top, minTop);
minDeltaVertical = Math.Min(minDeltaVertical, 10);
minDeltaHorizontal = Math.Min(minDeltaHorizontal, 10);
}
}
#endregion
}
}

View File

@@ -0,0 +1,106 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
namespace AIStudio.Wpf.DiagramDesigner.Controls
{
public class RotateThumb : Thumb
{
private Point centerPoint;
private Vector startVector;
private double initialAngle;
private Canvas designerCanvas;
private DesignerItemViewModelBase designerItem;
private RotateTransform rotateTransform;
public RotateThumb()
{
DragDelta += RotateThumb_DragDelta;
DragStarted += RotateThumb_DragStarted;
DragCompleted += RotateThumb_DragCompleted;
}
private List<SelectableDesignerItemViewModelBase> designerItems;
private void RotateThumb_DragStarted(object sender, DragStartedEventArgs e)
{
this.designerItem = this.DataContext as DesignerItemViewModelBase;
if (this.designerItem != null)
{
designerItems = designerItem.SelectedItems.ToList();
foreach (DesignerItemViewModelBase item in designerItems.OfType<DesignerItemViewModelBase>())
{
item.BeginDo = true;
item.SetOldValue(this.designerItem.Angle, nameof(this.designerItem.Angle));
}
this.designerCanvas = GetDesignerCanvas(this);
if (this.designerCanvas != null)
{
this.centerPoint =
new Point(this.designerItem.Left + this.designerItem.ItemWidth * 0.5,
this.designerItem.Top + this.designerItem.ItemHeight * 0.5);
Point startPoint = Mouse.GetPosition(this.designerCanvas);
this.startVector = Point.Subtract(startPoint, this.centerPoint);
this.initialAngle = this.designerItem.Angle;
}
e.Handled = true;
}
else
{
designerItems = null;
}
}
private void RotateThumb_DragCompleted(object sender, DragCompletedEventArgs e)
{
this.designerItem = this.DataContext as DesignerItemViewModelBase;
if (this.designerItems != null)
{
foreach (DesignerItemViewModelBase item in designerItems.OfType<DesignerItemViewModelBase>())
{
item.BeginDo = false;
item.RaiseAngle();
}
e.Handled = true;
}
}
private void RotateThumb_DragDelta(object sender, DragDeltaEventArgs e)
{
if (this.designerItems != null && this.designerCanvas != null)
{
Point currentPoint = Mouse.GetPosition(this.designerCanvas);
Vector deltaVector = Point.Subtract(currentPoint, this.centerPoint);
double angle = Vector.AngleBetween(this.startVector, deltaVector);
foreach (DesignerItemViewModelBase item in designerItems.OfType<DesignerItemViewModelBase>())
{
item.Angle = this.initialAngle + Math.Round(angle, 0);
}
e.Handled = true;
}
}
private DesignerCanvas GetDesignerCanvas(DependencyObject element)
{
while (element != null && !(element is DesignerCanvas))
element = VisualTreeHelper.GetParent(element);
return element as DesignerCanvas;
}
}
}

View File

@@ -0,0 +1,162 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using System.Windows.Input;
namespace AIStudio.Wpf.DiagramDesigner
{
public class ZoomBox : Control
{
private Thumb zoomThumb;
private Canvas zoomCanvas;
private Slider zoomSlider;
private ScaleTransform scaleTransform;
#region DPs
#region ScrollViewer
public ScrollViewer ScrollViewer
{
get { return (ScrollViewer)GetValue(ScrollViewerProperty); }
set { SetValue(ScrollViewerProperty, value); }
}
public static readonly DependencyProperty ScrollViewerProperty =
DependencyProperty.Register("ScrollViewer", typeof(ScrollViewer), typeof(ZoomBox));
#endregion
#region DesignerCanvas
public static readonly DependencyProperty DesignerCanvasProperty =
DependencyProperty.Register("DesignerCanvas", typeof(DesignerCanvas), typeof(ZoomBox),
new FrameworkPropertyMetadata(null,
new PropertyChangedCallback(OnDesignerCanvasChanged)));
public DesignerCanvas DesignerCanvas
{
get { return (DesignerCanvas)GetValue(DesignerCanvasProperty); }
set { SetValue(DesignerCanvasProperty, value); }
}
private static void OnDesignerCanvasChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ZoomBox target = (ZoomBox)d;
DesignerCanvas oldDesignerCanvas = (DesignerCanvas)e.OldValue;
DesignerCanvas newDesignerCanvas = target.DesignerCanvas;
target.OnDesignerCanvasChanged(oldDesignerCanvas, newDesignerCanvas);
}
protected virtual void OnDesignerCanvasChanged(DesignerCanvas oldDesignerCanvas, DesignerCanvas newDesignerCanvas)
{
if (oldDesignerCanvas != null)
{
newDesignerCanvas.LayoutUpdated -= new EventHandler(this.DesignerCanvas_LayoutUpdated);
newDesignerCanvas.MouseWheel -= new MouseWheelEventHandler(this.DesignerCanvas_MouseWheel);
}
if (newDesignerCanvas != null)
{
newDesignerCanvas.LayoutUpdated += new EventHandler(this.DesignerCanvas_LayoutUpdated);
newDesignerCanvas.MouseWheel += new MouseWheelEventHandler(this.DesignerCanvas_MouseWheel);
newDesignerCanvas.LayoutTransform = this.scaleTransform;
}
}
#endregion
#endregion
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (this.ScrollViewer == null)
return;
this.zoomThumb = Template.FindName("PART_ZoomThumb", this) as Thumb;
if (this.zoomThumb == null)
throw new Exception("PART_ZoomThumb template is missing!");
this.zoomCanvas = Template.FindName("PART_ZoomCanvas", this) as Canvas;
if (this.zoomCanvas == null)
throw new Exception("PART_ZoomCanvas template is missing!");
this.zoomSlider = Template.FindName("PART_ZoomSlider", this) as Slider;
if (this.zoomSlider == null)
throw new Exception("PART_ZoomSlider template is missing!");
this.zoomThumb.DragDelta += new DragDeltaEventHandler(this.Thumb_DragDelta);
this.zoomSlider.ValueChanged += new RoutedPropertyChangedEventHandler<double>(this.ZoomSlider_ValueChanged);
this.scaleTransform = new ScaleTransform();
}
private void ZoomSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
double scale = e.NewValue / e.OldValue;
double halfViewportHeight = this.ScrollViewer.ViewportHeight / 2;
double newVerticalOffset = ((this.ScrollViewer.VerticalOffset + halfViewportHeight) * scale - halfViewportHeight);
double halfViewportWidth = this.ScrollViewer.ViewportWidth / 2;
double newHorizontalOffset = ((this.ScrollViewer.HorizontalOffset + halfViewportWidth) * scale - halfViewportWidth);
this.scaleTransform.ScaleX *= scale;
this.scaleTransform.ScaleY *= scale;
this.ScrollViewer.ScrollToHorizontalOffset(newHorizontalOffset);
this.ScrollViewer.ScrollToVerticalOffset(newVerticalOffset);
}
private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
{
double scale, xOffset, yOffset;
this.InvalidateScale(out scale, out xOffset, out yOffset);
this.ScrollViewer.ScrollToHorizontalOffset(this.ScrollViewer.HorizontalOffset + e.HorizontalChange / scale);
this.ScrollViewer.ScrollToVerticalOffset(this.ScrollViewer.VerticalOffset + e.VerticalChange / scale);
}
private void DesignerCanvas_LayoutUpdated(object sender, EventArgs e)
{
//htzk
try
{
double scale, xOffset, yOffset;
this.InvalidateScale(out scale, out xOffset, out yOffset);
this.zoomThumb.Width = this.ScrollViewer.ViewportWidth * scale;
this.zoomThumb.Height = this.ScrollViewer.ViewportHeight * scale;
Canvas.SetLeft(this.zoomThumb, xOffset + this.ScrollViewer.HorizontalOffset * scale);
Canvas.SetTop(this.zoomThumb, yOffset + this.ScrollViewer.VerticalOffset * scale);
}
catch { }
}
private void DesignerCanvas_MouseWheel(object sender, EventArgs e)
{
MouseWheelEventArgs wheel = (MouseWheelEventArgs)e;
//divide the value by 10 so that it is more smooth
double value = Math.Max(0, wheel.Delta / 10);
value = Math.Min(wheel.Delta, 10);
this.zoomSlider.Value += value;
}
private void InvalidateScale(out double scale, out double xOffset, out double yOffset)
{
double w = DesignerCanvas.ActualWidth * this.scaleTransform.ScaleX;
double h = DesignerCanvas.ActualHeight * this.scaleTransform.ScaleY;
// zoom canvas size
double x = this.zoomCanvas.ActualWidth;
double y = this.zoomCanvas.ActualHeight;
double scaleX = x / w;
double scaleY = y / h;
scale = (scaleX < scaleY) ? scaleX : scaleY;
xOffset = (x - scale * w) / 2;
yOffset = (y - scale * h) / 2;
}
}
}