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
{
///
/// StepTree.xaml 的交互逻辑
///
[ObservableObject]
public partial class StepTree : UserControl
{
public event RoutedPropertyChangedEventHandler SelectedItemChanged;
private static List 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 RefreshMenuItems(ITestStep selectedStep, bool addChild)
{
var allSteps = StepTypeLoader.Steps;
var StepMenuItems = new List(allSteps.Count);
Dictionary groupMap = new Dictionary();
Dictionary groupAdapMap = new Dictionary();
foreach (ITypeData stepType in allSteps)
{
var display = stepType.GetAttribute();
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 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);
}
}
///
/// 显示菜单
///
///
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
///
/// 添加同级Step
///
///
///
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);
}
}
///
/// 添加子Step
///
///
///
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
}
}