2022-12-02 23:06:31 +08:00
|
|
|
|
using System;
|
2022-12-08 20:54:45 +08:00
|
|
|
|
using System.CodeDom.Compiler;
|
2022-12-02 23:06:31 +08:00
|
|
|
|
using System.Collections.Generic;
|
2022-12-04 23:07:20 +08:00
|
|
|
|
using System.Collections.ObjectModel;
|
2022-12-02 23:06:31 +08:00
|
|
|
|
using System.ComponentModel;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.Windows;
|
|
|
|
|
|
using System.Windows.Controls;
|
2022-12-08 20:54:45 +08:00
|
|
|
|
using System.Windows.Input;
|
2022-12-02 23:06:31 +08:00
|
|
|
|
using AIStudio.Wpf.DiagramDesigner;
|
|
|
|
|
|
using AIStudio.Wpf.Flowchart.Models;
|
|
|
|
|
|
|
|
|
|
|
|
namespace AIStudio.Wpf.Flowchart.Controls
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// FlowchartEditor.xaml 的交互逻辑
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[TemplatePart(Name = PART_DiagramControl, Type = typeof(DiagramControl))]
|
|
|
|
|
|
public partial class FlowchartEditor : UserControl
|
|
|
|
|
|
{
|
|
|
|
|
|
public const string PART_DiagramControl = "PART_DiagramControl";
|
|
|
|
|
|
private DiagramControl _diagramControl;
|
|
|
|
|
|
|
2022-12-04 23:07:20 +08:00
|
|
|
|
private IDiagramViewModel _diagramViewModel;
|
2022-12-02 23:06:31 +08:00
|
|
|
|
|
|
|
|
|
|
static FlowchartEditor()
|
|
|
|
|
|
{
|
|
|
|
|
|
DefaultStyleKeyProperty.OverrideMetadata(typeof(FlowchartEditor), new FrameworkPropertyMetadata(typeof(FlowchartEditor)));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public FlowchartEditor()
|
2022-12-04 23:07:20 +08:00
|
|
|
|
{
|
|
|
|
|
|
_diagramViewModel = new DiagramViewModel();
|
|
|
|
|
|
_diagramViewModel.SetScreenScale();
|
|
|
|
|
|
_diagramViewModel.ShowGrid = true;
|
|
|
|
|
|
_diagramViewModel.GridCellSize = new Size(125 / _diagramViewModel.ScreenScale, 125 / _diagramViewModel.ScreenScale);
|
|
|
|
|
|
_diagramViewModel.GridMargin = 0d;
|
|
|
|
|
|
_diagramViewModel.CellHorizontalAlignment = CellHorizontalAlignment.Center;
|
|
|
|
|
|
_diagramViewModel.CellVerticalAlignment = CellVerticalAlignment.Center;
|
|
|
|
|
|
_diagramViewModel.PageSizeType = PageSizeType.Custom;
|
|
|
|
|
|
_diagramViewModel.PageSize = new Size(double.NaN, double.NaN);
|
2022-12-06 21:28:42 +08:00
|
|
|
|
_diagramViewModel.ColorViewModel = new ColorViewModel() { LineWidth = 2 };
|
2022-12-12 22:33:17 +08:00
|
|
|
|
//_diagramViewModel.DrawModeViewModel = new DrawModeViewModel() { VectorLineDrawMode = DrawMode.BoundaryConnectingLine };
|
2022-12-04 23:07:20 +08:00
|
|
|
|
|
2022-12-02 23:06:31 +08:00
|
|
|
|
_diagramViewModel.PropertyChanged += DiagramViewModel_PropertyChanged;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override void OnApplyTemplate()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnApplyTemplate();
|
|
|
|
|
|
|
|
|
|
|
|
_diagramControl = GetTemplateChild(PART_DiagramControl) as DiagramControl;
|
|
|
|
|
|
_diagramControl.HorizontalAlignment = HorizontalAlignment.Stretch;
|
|
|
|
|
|
_diagramControl.VerticalAlignment = VerticalAlignment.Stretch;
|
|
|
|
|
|
_diagramControl.DataContext = _diagramViewModel;
|
2022-12-04 23:07:20 +08:00
|
|
|
|
|
|
|
|
|
|
GetDataFunc = GetData;
|
2022-12-02 23:06:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void DiagramViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (e.PropertyName == "IsSelected")
|
|
|
|
|
|
{
|
|
|
|
|
|
SelectedObject = _diagramViewModel.SelectedItems?.FirstOrDefault();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//一点要绑定不为空的FlowchartModel才能用,即便为空的也要new一个再来绑定
|
2022-12-04 23:07:20 +08:00
|
|
|
|
public static readonly DependencyProperty DataProperty =
|
|
|
|
|
|
DependencyProperty.Register(nameof(Data),
|
|
|
|
|
|
typeof(string),
|
2022-12-02 23:06:31 +08:00
|
|
|
|
typeof(FlowchartEditor),
|
2022-12-04 23:07:20 +08:00
|
|
|
|
new FrameworkPropertyMetadata(null, OnDataChanged));
|
2022-12-02 23:06:31 +08:00
|
|
|
|
|
2022-12-04 23:07:20 +08:00
|
|
|
|
public string Data
|
2022-12-02 23:06:31 +08:00
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
2022-12-04 23:07:20 +08:00
|
|
|
|
return (string)GetValue(DataProperty);
|
2022-12-02 23:06:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
2022-12-04 23:07:20 +08:00
|
|
|
|
SetValue(DataProperty, value);
|
2022-12-02 23:06:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-12-04 23:07:20 +08:00
|
|
|
|
private static void OnDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
2022-12-02 23:06:31 +08:00
|
|
|
|
{
|
|
|
|
|
|
var view = d as FlowchartEditor;
|
2022-12-04 23:07:20 +08:00
|
|
|
|
var json = e.NewValue as string;
|
|
|
|
|
|
if (json != null)
|
2022-12-02 23:06:31 +08:00
|
|
|
|
{
|
2022-12-04 23:07:20 +08:00
|
|
|
|
view.CreateFlowchartModel(json);
|
2022-12-02 23:06:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-12-04 23:07:20 +08:00
|
|
|
|
private void CreateFlowchartModel(string json)
|
2022-12-02 23:06:31 +08:00
|
|
|
|
{
|
2022-12-05 22:48:00 +08:00
|
|
|
|
_diagramViewModel.IsLoading = true;
|
2022-12-02 23:06:31 +08:00
|
|
|
|
_diagramViewModel.Items.Clear();
|
2022-12-04 23:07:20 +08:00
|
|
|
|
_diagramViewModel.ToObject(json);
|
2022-12-05 22:48:00 +08:00
|
|
|
|
_diagramViewModel.IsLoading = false;
|
2022-12-04 23:07:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static readonly DependencyProperty GetDataFuncProperty =
|
|
|
|
|
|
DependencyProperty.Register(nameof(GetDataFunc),
|
|
|
|
|
|
typeof(Func<string>),
|
|
|
|
|
|
typeof(FlowchartEditor),
|
|
|
|
|
|
new FrameworkPropertyMetadata(null));
|
|
|
|
|
|
public Func<string> GetDataFunc
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return (Func<string>)this.GetValue(GetDataFuncProperty);
|
|
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
this.SetValue(GetDataFuncProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public Func<string> GetData
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return new Func<string>(() => _diagramViewModel.ToJson());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static readonly DependencyProperty ModeProperty =
|
|
|
|
|
|
DependencyProperty.Register(nameof(Mode),
|
|
|
|
|
|
typeof(string),
|
|
|
|
|
|
typeof(FlowchartEditor),
|
|
|
|
|
|
new FrameworkPropertyMetadata("Edit", OnModeChanged));
|
|
|
|
|
|
|
|
|
|
|
|
public string Mode
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return (string)GetValue(ModeProperty);
|
|
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
SetValue(ModeProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static void OnModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
var view = d as FlowchartEditor;
|
|
|
|
|
|
var mode = e.NewValue as string;
|
|
|
|
|
|
if (mode != "Edit")
|
|
|
|
|
|
{
|
|
|
|
|
|
view._diagramViewModel.IsReadOnly = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
2022-12-02 23:06:31 +08:00
|
|
|
|
{
|
2022-12-04 23:07:20 +08:00
|
|
|
|
view._diagramViewModel.IsReadOnly = false;
|
2022-12-02 23:06:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#region ToolBox
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 附加组件模板
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static readonly DependencyProperty ToolBoxProperty = DependencyProperty.Register(
|
|
|
|
|
|
nameof(ToolBox), typeof(ControlTemplate), typeof(FlowchartEditor), new FrameworkPropertyMetadata(default(ControlTemplate)));
|
|
|
|
|
|
|
|
|
|
|
|
public ControlTemplate ToolBox
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return (ControlTemplate)GetValue(ToolBoxProperty);
|
|
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
SetValue(ToolBoxProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2022-12-10 20:21:06 +08:00
|
|
|
|
#region PropertiesBox
|
2022-12-02 23:06:31 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 附加组件模板
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static readonly DependencyProperty PropertiesBoxProperty = DependencyProperty.Register(
|
|
|
|
|
|
nameof(PropertiesBox), typeof(ControlTemplate), typeof(FlowchartEditor), new FrameworkPropertyMetadata(default(ControlTemplate)));
|
|
|
|
|
|
|
|
|
|
|
|
public ControlTemplate PropertiesBox
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return (ControlTemplate)GetValue(PropertiesBoxProperty);
|
|
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
SetValue(PropertiesBoxProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region SelectedObject
|
|
|
|
|
|
|
|
|
|
|
|
public static readonly DependencyProperty SelectedObjectProperty = DependencyProperty.Register(nameof(SelectedObject), typeof(object), typeof(FlowchartEditor), new UIPropertyMetadata(default(object)));
|
|
|
|
|
|
public object SelectedObject
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return (object)GetValue(SelectedObjectProperty);
|
|
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
SetValue(SelectedObjectProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Users
|
|
|
|
|
|
public static readonly DependencyProperty UsersProperty
|
|
|
|
|
|
= DependencyProperty.Register(nameof(Users), typeof(List<SelectOption>), typeof(FlowchartEditor), new UIPropertyMetadata(default(List<SelectOption>)));
|
|
|
|
|
|
public List<SelectOption> Users
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return (List<SelectOption>)GetValue(UsersProperty);
|
|
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
SetValue(UsersProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Roles
|
|
|
|
|
|
public static readonly DependencyProperty RolesProperty
|
|
|
|
|
|
= DependencyProperty.Register(nameof(Roles), typeof(List<SelectOption>), typeof(FlowchartEditor), new UIPropertyMetadata(default(List<SelectOption>)));
|
|
|
|
|
|
public List<SelectOption> Roles
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return (List<SelectOption>)GetValue(RolesProperty);
|
|
|
|
|
|
}
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
SetValue(RolesProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2022-12-08 20:54:45 +08:00
|
|
|
|
protected override void OnPreviewKeyDown(KeyEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnPreviewKeyDown(e);
|
|
|
|
|
|
|
|
|
|
|
|
bool executed = true;
|
|
|
|
|
|
var para = e.KeyboardDevice.Modifiers == ModifierKeys.None ? e.Key.ToString() : e.KeyboardDevice.Modifiers.ToString() + "+" + e.Key.ToString();
|
|
|
|
|
|
|
|
|
|
|
|
switch (para)
|
|
|
|
|
|
{
|
|
|
|
|
|
case "Control+A": _diagramViewModel.SelectAllCommand.Execute(null); break;
|
|
|
|
|
|
case "Control+C": _diagramViewModel.CopyCommand.Execute(null); break;
|
|
|
|
|
|
case "Control+V": _diagramViewModel.PasteCommand.Execute(null); break;
|
|
|
|
|
|
case "Control+X": _diagramViewModel.CutCommand.Execute(null); break;
|
|
|
|
|
|
case "Control+Z": _diagramViewModel.UndoCommand.Execute(null); break;
|
|
|
|
|
|
case "Control+Y": _diagramViewModel.RedoCommand.Execute(null); break;
|
|
|
|
|
|
case "Delete": _diagramViewModel.DeleteCommand.Execute(null); break;
|
|
|
|
|
|
case "Left": _diagramViewModel.LeftMoveCommand.Execute(null); break;
|
|
|
|
|
|
case "Right": _diagramViewModel.RightMoveCommand.Execute(null); break;
|
|
|
|
|
|
case "Up": _diagramViewModel.UpMoveCommand.Execute(null); break;
|
|
|
|
|
|
case "Down": _diagramViewModel.DownMoveCommand.Execute(null); break;
|
|
|
|
|
|
default: executed = false; break;
|
|
|
|
|
|
}
|
|
|
|
|
|
e.Handled = executed;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-12-02 23:06:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|