using AddInPlugin;
|
using AddInPlugin.Entity;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
using GongSolutions.Wpf.DragDrop;
|
using OpenTap;
|
using OpenTapEditor.UI;
|
using OpenTapEditor.Util;
|
using System.Collections.ObjectModel;
|
using System.IO;
|
using System.Text;
|
using System.Windows;
|
using System.Windows.Controls;
|
using UILib;
|
|
namespace OpenTapEditor
|
{
|
/// <summary>
|
/// StepTree.xaml 的交互逻辑
|
/// </summary>
|
[ObservableObject]
|
public partial class StepTree : UserControl
|
{
|
public event RoutedPropertyChangedEventHandler<object> SelectedItemChanged;
|
|
private static List<MenuItem> StepMenuItems;
|
|
[ObservableProperty]
|
private TestStepList datasource;
|
|
[ObservableProperty]
|
private Guid currentId;
|
|
public TestPlan Plan { get; set; }
|
|
public IDropTarget DragHandler { get; set; } = new StepTreeDragHandler();
|
|
public StepTree()
|
{
|
DataContext = this;
|
InitializeComponent();
|
}
|
|
public List<object> RefreshMenuItems(ITestStep selectedStep, bool addChild)
|
{
|
var allSteps = StepTypeLoader.Steps;
|
var StepMenuItems = new List<object>(allSteps.Count);
|
Dictionary<string, MenuItem> groupMap = new Dictionary<string, MenuItem>();
|
Dictionary<string, MenuItem> groupAdapMap = new Dictionary<string, MenuItem>();
|
|
foreach (ITypeData stepType in allSteps)
|
{
|
var display = stepType.GetAttribute<DisplayAttribute>();
|
if (display == null)
|
{
|
continue;
|
}
|
MenuItem groupItem = null;
|
|
var groups = display.Group;
|
if (groups.Length > 0)
|
{
|
var group = groups[groups.Length - 1];
|
if (!string.IsNullOrEmpty(group))
|
{
|
if (!groupMap.ContainsKey(group))
|
{
|
groupMap[group] = new MenuItem() { Header = group};
|
StepMenuItems.Add(groupMap[group]);
|
}
|
groupItem = groupMap[group];
|
}
|
}
|
|
|
TypeData data = stepType as TypeData;
|
StepTypeMenuItem menuItem = new StepTypeMenuItem();
|
string des = string.IsNullOrEmpty(display.Description) ? "" : $" ({display.Description})";
|
menuItem.Header = $"{display.Name}{des}";
|
menuItem.Click += addChild ? Add_Child_Step_Click : Add_Generaic_Step_Click;
|
menuItem.TypeData = stepType;
|
menuItem.Tag = selectedStep;
|
|
if (!addChild)
|
{
|
var parent = selectedStep?.Parent?.GetType() ?? typeof(TestPlan);
|
menuItem.IsEnabled = parent == null || TestStepList.AllowChild(parent, data.Type);
|
}
|
else
|
{
|
menuItem.IsEnabled = (selectedStep != null && TestStepList.AllowChild(selectedStep.GetType(), data.Type));
|
}
|
if (groupItem != null)
|
{
|
groupItem.Items.Add(menuItem);
|
}
|
else {
|
StepMenuItems.Add(menuItem);
|
}
|
}
|
|
if (StepTypeLoader.CustomSteps != null && StepTypeLoader.CustomSteps.Count > 0)
|
{
|
StepMenuItems.Add(new Separator { });
|
|
foreach (AdapterData stepType in StepTypeLoader.CustomSteps)
|
{
|
MenuItem groupItem = null;
|
if (!string.IsNullOrEmpty(stepType.Group))
|
{
|
if (!groupAdapMap.ContainsKey(stepType.Group))
|
{
|
groupAdapMap[stepType.Group] = new MenuItem
|
{
|
Header = stepType.Group
|
};
|
StepMenuItems.Add(groupAdapMap[stepType.Group]);
|
}
|
groupItem = groupAdapMap[stepType.Group];
|
}
|
|
|
StepTypeMenuItem menuItem = new StepTypeMenuItem();
|
menuItem.Header = stepType.Name;
|
menuItem.Click += addChild ? Add_Child_Step_Click : Add_Generaic_Step_Click;
|
menuItem.TypeData = stepType;
|
menuItem.Tag = selectedStep;
|
|
menuItem.IsEnabled = !addChild || (selectedStep != null && TestStepList.AllowChild(selectedStep?.GetType(), typeof(AdapterData)));
|
|
if (groupItem != null)
|
{
|
groupItem.Items.Add(menuItem);
|
}
|
else
|
{
|
StepMenuItems.Add(menuItem);
|
}
|
}
|
}
|
return StepMenuItems;
|
}
|
|
private void treeList_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
{
|
SelectedItemChanged?.Invoke(sender, e);
|
}
|
|
private void treeList_PreviewMouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
{
|
DependencyObject source = e.OriginalSource as DependencyObject;
|
while (source != null && source.GetType() != typeof(TreeListViewItem))
|
{
|
source = System.Windows.Media.VisualTreeHelper.GetParent(source);
|
}
|
|
if (source != null)
|
{
|
TreeListViewItem item = source as TreeListViewItem;
|
item.Focus();
|
var step = item.DataContext as ITestStep;
|
CreateContextMenu(step);
|
}
|
else
|
{
|
CreateContextMenu(null);
|
}
|
}
|
|
/// <summary>
|
/// 显示菜单
|
/// </summary>
|
/// <param name="positionItem"></param>
|
private void CreateContextMenu(ITestStep obj)
|
{
|
ContextMenu contextMenu = new ContextMenu();
|
MenuItem menuItem = new MenuItem();
|
menuItem.Header = "插入Step";
|
menuItem.Tag = obj;
|
foreach (var item in RefreshMenuItems(obj, false))
|
{
|
menuItem.Items.Add(item);
|
}
|
contextMenu.Items.Add(menuItem);
|
|
menuItem = new MenuItem();
|
menuItem.Header = "插入子Step";
|
menuItem.Tag = obj;
|
foreach (var item in RefreshMenuItems(obj, true))
|
{
|
menuItem.Items.Add(item);
|
}
|
contextMenu.Items.Add(menuItem);
|
|
menuItem = new MenuItem();
|
menuItem.Header = "复制";
|
menuItem.Click += Copy_Step_Click;
|
menuItem.Tag = obj;
|
contextMenu.Items.Add(menuItem);
|
|
menuItem = new MenuItem();
|
menuItem.Header = "粘贴";
|
menuItem.Click += Paste_Step_Click;
|
menuItem.Tag = obj;
|
contextMenu.Items.Add(menuItem);
|
|
menuItem = new MenuItem();
|
menuItem.Header = "删除";
|
menuItem.Click += Delete_Step_Click;
|
menuItem.Tag = obj;
|
contextMenu.Items.Add(menuItem);
|
|
this.treeList.ContextMenu = contextMenu;
|
}
|
|
private void AddStep2Plan(ITestStep newStep, ITestStep insertAfter, TestPlan plan)
|
{
|
if (insertAfter != null)
|
{
|
var parent = insertAfter.Parent;
|
if (parent is TestPlan pplan)
|
{
|
pplan.InsertStep(Datasource.SequenceName,
|
pplan.GetStepsByName(Datasource.SequenceName).IndexOf(insertAfter) + 1, newStep);
|
}
|
else
|
{
|
parent.InsertStep(Datasource.SequenceName, parent.ChildTestSteps.IndexOf(insertAfter) + 1, newStep);
|
}
|
}
|
else
|
{
|
plan.AddStep(Datasource.SequenceName, newStep);
|
}
|
}
|
|
|
#region add
|
|
/// <summary>
|
/// 添加同级Step
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void Add_Generaic_Step_Click(object sender, RoutedEventArgs e)
|
{
|
ITestStep step = ((StepTypeMenuItem)sender).Tag as ITestStep;
|
ITestStep newStep = null;
|
if (((StepTypeMenuItem)sender).TypeData is ITypeData type)
|
{
|
newStep = type.CreateInstance() as ITestStep;
|
}
|
else if (((StepTypeMenuItem)sender).TypeData is AdapterData data)
|
{
|
newStep = new AdapterStep()
|
{
|
Name = data.Name,
|
XmlString = data.Xml
|
};
|
}
|
if (newStep != null)
|
{
|
AddStep2Plan(newStep, step, Plan);
|
}
|
}
|
|
/// <summary>
|
/// 添加子Step
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void Add_Child_Step_Click(object sender, RoutedEventArgs e)
|
{
|
ITestStep step = ((StepTypeMenuItem)sender).Tag as ITestStep;
|
if (step == null)
|
{
|
return;
|
}
|
ITestStep newStep = null;
|
if (((StepTypeMenuItem)sender).TypeData is ITypeData type)
|
{
|
newStep = type.CreateInstance() as ITestStep;
|
}
|
else if (((StepTypeMenuItem)sender).TypeData is AdapterData data)
|
{
|
newStep = new AdapterStep()
|
{
|
Name = data.Name,
|
XmlString = data.Xml
|
};
|
}
|
if (newStep != null)
|
{
|
step.ChildTestSteps.Add(newStep);
|
}
|
}
|
|
private void Delete_Step_Click(object sender, RoutedEventArgs e)
|
{
|
ITestStep step = ((MenuItem)sender).Tag as ITestStep;
|
if (step.Parent is ITestStep)
|
{
|
step.Parent.ChildTestSteps.Remove(step);
|
}
|
else
|
{
|
Datasource.Remove(step);
|
}
|
}
|
|
private void Copy_Step_Click(object sender, RoutedEventArgs e)
|
{
|
|
ITestStep step = ((MenuItem)sender).Tag as ITestStep;
|
|
TapSerializer serializer = new TapSerializer();
|
using (var str = new MemoryStream())
|
{
|
serializer.Serialize(str, step);
|
Clipboard.SetText(Encoding.UTF8.GetString(str.ToArray()));
|
}
|
}
|
|
private void Paste_Step_Click(object sender, RoutedEventArgs e)
|
{
|
try
|
{
|
ITestStep step = ((MenuItem)sender).Tag as ITestStep;
|
TapSerializer serializer = new TapSerializer();
|
ITestStep newStep = (ITestStep)serializer.DeserializeFromString(Clipboard.GetText(), TypeData.FromType(typeof(ITestStep)));
|
newStep.Id = Guid.NewGuid();
|
foreach (var child in newStep.RecursivelyGetChildSteps(TestStepSearch.All))
|
{
|
child.Id = Guid.NewGuid();
|
}
|
AddStep2Plan(newStep, step, Plan);
|
}
|
catch
|
{
|
|
}
|
}
|
|
|
#endregion
|
}
|
}
|