using OpenTap.Addin;
|
using OpenTapEditor.Util;
|
using SeqEditor.SubWin;
|
using SeqEditor.Util;
|
using System.Collections.ObjectModel;
|
using System.Globalization;
|
using System.Windows;
|
using System.Windows.Controls;
|
using System.Windows.Data;
|
using UILib;
|
|
namespace OpenTapEditor
|
{
|
public class MultiTestVariableConverter : IMultiValueConverter
|
{
|
public static MultiTestVariableConverter Instance = new MultiTestVariableConverter();
|
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
{
|
if (values[0] is TestVariable tv && values[1] is TreeListViewItem item)
|
{
|
if (parameter?.ToString() == "NameCanEdit")
|
{
|
var parent = item?.parent?.DataContext as TestVariable;
|
return tv.NameCanEdit ? (parent != null && !parent.IsArray) : false;
|
}
|
|
if (parameter?.ToString() == "ChangeButton")
|
{
|
var parent = item?.parent?.DataContext as TestVariable;
|
if (!tv.NameCanEdit)
|
{
|
return Visibility.Collapsed;
|
}
|
|
if (parent?.IsArray == true && parent.Type != TestVariableType.Container)
|
{
|
return Visibility.Collapsed;
|
}
|
|
return Visibility.Visible;
|
}
|
}
|
return null;
|
}
|
|
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
{
|
return null;
|
}
|
}
|
|
public class TestVariableConverter : IValueConverter
|
{
|
public static TestVariableConverter Instance = new TestVariableConverter();
|
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
{
|
if (value is TestVariable tv)
|
{
|
if (parameter?.ToString() == "TypeName")
|
{
|
return tv.IsArray ? $"{tv.Type}[]" : tv.Type.ToString();
|
}
|
if (parameter?.ToString() == "StringFormat")
|
{
|
return tv.IsArray || tv.Type != TestVariableType.String ? false : true;
|
}
|
if (parameter?.ToString() == "CanEdit")
|
{
|
return !tv.IsArray && tv.Type != TestVariableType.Container && tv.Type != TestVariableType.Refrence;
|
}
|
if (parameter?.ToString() == "EditType")
|
{
|
return tv.Type == TestVariableType.Bool ? EditBoxType.Bool : EditBoxType.String;
|
}
|
}
|
else if (value is RunningVar rv)
|
{
|
if (parameter?.ToString() == "TypeName")
|
{
|
return rv.IsArray ? $"{rv.Type}[]" : rv.Type.ToString();
|
}
|
if (parameter?.ToString() == "StringFormat")
|
{
|
return rv.IsArray || rv.Type != TestVariableType.String ? false : true;
|
}
|
if (parameter?.ToString() == "CanEdit")
|
{
|
return !rv.IsArray && rv.Type != TestVariableType.Container && rv.Type != TestVariableType.Refrence;
|
}
|
if (parameter?.ToString() == "EditType")
|
{
|
return rv.Type == TestVariableType.Bool ? EditBoxType.Bool : EditBoxType.String;
|
}
|
}
|
return value;
|
}
|
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
{
|
return value;
|
}
|
}
|
|
public class TestVariableMenuItem : MenuItem
|
{
|
public IEnumerable<TestVariable> Source { get; set; }
|
public TestVariable Variable { get; set; }
|
public TestVariable Parent { get; set; }
|
|
public TreeListViewItem SourceItem { get; set; }
|
|
public bool TargetIsArray { get; set; }
|
public TestVariableType TargetType { get; set; }
|
}
|
|
/// <summary>
|
/// VariableTree.xaml 的交互逻辑
|
/// </summary>
|
public partial class VariableTree : UserControl
|
{
|
public VariableTree()
|
{
|
InitializeComponent();
|
BindingOperations.SetBinding(treeView, TreeListView.ItemsSourceProperty,
|
new Binding(nameof(Datasource))
|
{
|
Source = this,
|
Mode = BindingMode.TwoWay,
|
});
|
}
|
|
public static DependencyProperty DatasourceProperty = DependencyProperty.Register(
|
"Datasource",
|
typeof(ObservableCollection<TestVariable>),
|
typeof(VariableTree),
|
new PropertyMetadata(null)
|
);
|
|
public string Prefix { get; set; }
|
|
public ObservableCollection<TestVariable> Datasource
|
{
|
get => (ObservableCollection<TestVariable>)GetValue(DatasourceProperty);
|
set
|
{
|
SetValue(DatasourceProperty, value);
|
}
|
}
|
|
private void OnPreviewMouseRightButtonDown(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 variable = item.DataContext;
|
CreateContextMenu(item, variable);
|
}
|
else
|
{
|
CreateContextMenu(null, null);
|
}
|
}
|
|
public List<object> RefreshMenuItems(TreeListViewItem parentItem, TestVariable parent, TestVariable source)
|
{
|
var allSteps = StepTypeLoader.Steps;
|
var StepMenuItems = new List<object>(allSteps.Count);
|
|
foreach (TestVariableType type in Enum.GetValues(typeof(TestVariableType)))
|
{
|
TestVariableMenuItem menuItem = new TestVariableMenuItem();
|
menuItem.Header = type.ToString();
|
menuItem.SourceItem = parentItem;
|
menuItem.Variable = source;
|
|
menuItem.Click += MenuItem_Click;
|
menuItem.TargetIsArray = false;
|
menuItem.TargetType = type;
|
menuItem.Parent = parent;
|
StepMenuItems.Add(menuItem);
|
}
|
|
var arrItem = new MenuItem();
|
arrItem.Header = "Array Of...";
|
foreach (TestVariableType type in Enum.GetValues(typeof(TestVariableType)))
|
{
|
TestVariableMenuItem menuItem = new TestVariableMenuItem();
|
menuItem.Header = type.ToString();
|
menuItem.SourceItem = parentItem;
|
menuItem.Variable = source;
|
|
menuItem.Click += ArrayMenuItem_Click;
|
menuItem.TargetIsArray = true;
|
menuItem.TargetType = type;
|
menuItem.Parent = parent;
|
arrItem.Items.Add(menuItem);
|
}
|
StepMenuItems.Add(arrItem);
|
return StepMenuItems;
|
}
|
|
/// <summary>
|
/// 显示菜单
|
/// </summary>
|
/// <param name="positionItem"></param>
|
private void CreateContextMenu(TreeListViewItem item, object obj)
|
{
|
var v = obj as TestVariable;
|
|
ContextMenu contextMenu = new ContextMenu();
|
contextMenu.Closed += ContextMenu_Closed;
|
var parentItem = item?.parent as TreeListViewItem;
|
var parent = item?.parent?.DataContext as TestVariable;
|
|
|
TestVariableMenuItem menuItem = new TestVariableMenuItem();
|
if (v == null)
|
{
|
return;
|
//menuItem.SetValue(TestVariableMenuItem.HeaderProperty, new DynamicResourceExtension("插入").ProvideValue(null));
|
|
//foreach (var i in RefreshMenuItems(item, null))
|
//{
|
// menuItem.Items.Add(i);
|
//}
|
//contextMenu.Items.Add(menuItem);
|
}
|
|
if (v.IsArray)
|
{
|
menuItem.SetValue(TestVariableMenuItem.HeaderProperty, new DynamicResourceExtension("添加元素").ProvideValue(null));
|
menuItem.Parent = v;
|
menuItem.Click += MenuItem_Click;
|
menuItem.SourceItem = item;
|
contextMenu.Items.Add(menuItem);
|
}
|
else if (v.Type == TestVariableType.Container)
|
{
|
menuItem.SetValue(TestVariableMenuItem.HeaderProperty, new DynamicResourceExtension("添加").ProvideValue(null));
|
foreach (var i in RefreshMenuItems(item, v, null))
|
{
|
menuItem.Items.Add(i);
|
}
|
contextMenu.Items.Add(menuItem);
|
}
|
|
if (parent != null)
|
{
|
if (parent.IsArray)
|
{
|
menuItem = new TestVariableMenuItem();
|
menuItem.SetValue(TestVariableMenuItem.HeaderProperty, new DynamicResourceExtension("插入元素").ProvideValue(null));
|
menuItem.SourceItem = parentItem;
|
menuItem.Parent = parent;
|
menuItem.Variable = v;
|
menuItem.Click += MenuItem_Click;
|
contextMenu.Items.Add(menuItem);
|
}
|
else
|
{
|
menuItem = new TestVariableMenuItem();
|
menuItem.SetValue(TestVariableMenuItem.HeaderProperty, new DynamicResourceExtension("插入").ProvideValue(null));
|
foreach (var i in RefreshMenuItems(parentItem, parent, v))
|
{
|
menuItem.Items.Add(i);
|
}
|
contextMenu.Items.Add(menuItem);
|
}
|
}
|
|
if (v.NameCanEdit)
|
{
|
menuItem = new TestVariableMenuItem();
|
menuItem.SetValue(TestVariableMenuItem.HeaderProperty, new DynamicResourceExtension("删除").ProvideValue(null));
|
menuItem.Click += Delete_Click;
|
menuItem.Variable = v;
|
menuItem.Tag = item;
|
contextMenu.Items.Add(menuItem);
|
}
|
|
menuItem = new TestVariableMenuItem();
|
menuItem.SetValue(TestVariableMenuItem.HeaderProperty, new DynamicResourceExtension("复制名称").ProvideValue(null));
|
menuItem.Click += CopyName_Click;
|
menuItem.Tag = item;
|
contextMenu.Items.Add(menuItem);
|
|
this.treeView.ContextMenu = contextMenu;
|
}
|
|
private void ContextMenu_Closed(object sender, RoutedEventArgs e)
|
{
|
this.treeView.ContextMenu = null;
|
}
|
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void MenuItem_Click(object sender, RoutedEventArgs e)
|
{
|
TestVariableMenuItem item = sender as TestVariableMenuItem;
|
TestVariable parent = item.Parent;
|
TestVariable newOne = null;
|
TestVariable source = item.Variable;
|
TreeListViewItem parentItem = item.SourceItem;
|
|
if (parent == null)
|
{
|
return;
|
}
|
|
if (parent.IsArray)
|
{
|
newOne = new TestVariable
|
{
|
Name = $"[{parent.Children.Count}]",
|
IsArray = false,
|
Type = parent.Type,
|
Value = TestVariable.DefaultValue(parent.Type)
|
};
|
if (source == null)
|
{
|
parent.Children.Add(newOne);
|
}
|
else
|
{
|
parent.Children.Insert(parent.Children.IndexOf(source) + 1, newOne);
|
}
|
|
for (int i = 0; i < parent.Children.Count; i++)
|
{
|
parent.Children[i].Name = $"[{i}]";
|
}
|
goto End;
|
}
|
|
if (parent.Type == TestVariableType.Container)
|
{
|
newOne = new TestVariable
|
{
|
IsArray = item.TargetIsArray,
|
Type = item.TargetType,
|
Value = item.TargetIsArray ? null : TestVariable.DefaultValue(item.TargetType)
|
};
|
if (source == null)
|
{
|
parent.Children.Add(newOne);
|
}
|
else
|
{
|
parent.Children.Insert(parent.Children.IndexOf(source) + 1, newOne);
|
}
|
goto End;
|
}
|
|
End:
|
parentItem.IsExpanded = true;
|
DispatcherHelper.WaitForPriority();
|
var scroll = treeView.Template.FindName("scroll", treeView) as ScrollViewer;
|
var tvi = parentItem.ItemContainerGenerator.ContainerFromIndex(parent.Children.IndexOf(newOne)) as TreeListViewItem;
|
if (!DispatcherHelper.IsElementVisibleInScrollViewer(scroll, tvi))
|
{
|
Point offset = tvi.TransformToAncestor(scroll).Transform(new Point(0, 0));
|
scroll.ScrollToVerticalOffset(offset.Y);
|
}
|
var eb = DispatcherHelper.FindVisualChild<EditBox>(tvi);
|
eb?.TryEdit(null);
|
tvi.IsSelected = true;
|
}
|
|
/// <summary>
|
/// 添加Array
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void ArrayMenuItem_Click(object sender, RoutedEventArgs e)
|
{
|
TestVariableMenuItem item = sender as TestVariableMenuItem;
|
TestVariable parent = item.Parent;
|
TestVariable newOne = null;
|
TestVariable source = item.Variable;
|
TreeListViewItem parentItem = item.SourceItem;
|
|
if (parent == null)
|
{
|
return;
|
}
|
string ValidateName(string name)
|
{
|
var target = parent.Children?.FirstOrDefault(e => e.Name == name);
|
if (target != null)
|
{
|
return LangUtil.Format("参数名称重复2", name, parent.Name);
|
}
|
return null;
|
}
|
|
var win = new ArrayVarConfig(ValidateName)
|
{
|
VarType = item.TargetType,
|
Owner = Window.GetWindow(this),
|
};
|
|
if (win.ShowDialog() != true)
|
{
|
return;
|
}
|
|
newOne = new TestVariable
|
{
|
Name = win.VarName,
|
IsArray = item.TargetIsArray,
|
Type = win.VarType,
|
Value = null
|
};
|
for (int i = 0; i < win.Length; i++)
|
{
|
TestVariable child = new TestVariable
|
{
|
IsArray = false,
|
Type = newOne.Type,
|
Name = $"[{i}]",
|
Value = TestVariable.DefaultValue(newOne.Type)
|
};
|
newOne.Children.Add(child);
|
}
|
|
if (source == null)
|
{
|
parent.Children.Add(newOne);
|
}
|
else
|
{
|
parent.Children.Insert(parent.Children.IndexOf(source) + 1, newOne);
|
}
|
goto End;
|
|
End:
|
parentItem.IsExpanded = true;
|
DispatcherHelper.WaitForPriority();
|
var scroll = treeView.Template.FindName("scroll", treeView) as ScrollViewer;
|
var tvi = parentItem.ItemContainerGenerator.ContainerFromIndex(parent.Children.IndexOf(newOne)) as TreeListViewItem;
|
if (!DispatcherHelper.IsElementVisibleInScrollViewer(scroll, tvi))
|
{
|
Point offset = tvi.TransformToAncestor(scroll).Transform(new Point(0, 0));
|
scroll.ScrollToVerticalOffset(offset.Y);
|
}
|
if (string.IsNullOrEmpty(newOne.Name))
|
{
|
var eb = DispatcherHelper.FindVisualChild<EditBox>(tvi);
|
eb?.TryEdit(null);
|
}
|
tvi.IsSelected = true;
|
}
|
|
private void Delete_Click(object sender, RoutedEventArgs e)
|
{
|
var tv = ((TestVariableMenuItem)sender).Variable;
|
var item = ((TestVariableMenuItem)sender).Tag as TreeListViewItem;
|
if (item.parent == null)
|
{
|
Datasource.Remove(tv);
|
}
|
else
|
{
|
var parentData = item.parent.DataContext as TestVariable;
|
parentData.Children.Remove(tv);
|
if (parentData.IsArray)
|
{
|
for (int i = 0; i < parentData.Children.Count; i++)
|
{
|
parentData.Children[i].Name = $"[{i}]";
|
}
|
}
|
}
|
}
|
|
private void CopyName_Click(object sender, RoutedEventArgs e)
|
{
|
var item = ((TestVariableMenuItem)sender).Tag as TreeListViewItem;
|
var tv = item?.DataContext as TestVariable;
|
|
string name = "";
|
while (tv != null)
|
{
|
if (tv.IsArray)
|
{
|
name = tv.Name + name;
|
}
|
else
|
{
|
name = tv.Name + (string.IsNullOrEmpty(name) ? "" : $".{name}");
|
}
|
item = item.parent;
|
tv = item?.DataContext as TestVariable;
|
}
|
Clipboard.SetText(string.IsNullOrEmpty(Prefix) ? name : $"{Prefix}.{name}");
|
}
|
|
private bool VariableNamePreSubmit(object sender, object value, object source)
|
{
|
EditBox eb = (EditBox)sender;
|
TreeListViewItem item = (TreeListViewItem)eb.Tag;
|
var parentItem = item.parent;
|
if (parentItem == null)
|
{
|
return false;
|
}
|
if (string.IsNullOrEmpty(value.ToString()))
|
{
|
MessageBox.Show(LangUtil.Get("参数名称不能为空"));
|
return false;
|
}
|
|
TestVariable parent = (TestVariable)parentItem.DataContext;
|
var target = parent.Children.FirstOrDefault(c => c.Name == value.ToString());
|
if (target != null && target != source)
|
{
|
MessageBox.Show(LangUtil.Format("参数名称重复", value));
|
return false;
|
}
|
return true;
|
}
|
|
private void ChangeButton_Click(object sender, RoutedEventArgs e)
|
{
|
Button btn = (Button)sender;
|
var menu = new ContextMenu();
|
btn.ContextMenu = menu;
|
TestVariable source = (TestVariable)btn.DataContext;
|
TreeListViewItem sourceItem = (TreeListViewItem)btn.Tag;
|
TreeListViewItem parentItem = sourceItem.parent;
|
|
void Menu_Closed(object sender, RoutedEventArgs e)
|
{
|
btn.ContextMenu = null;
|
}
|
|
void MenuItem_Click1(object sender, RoutedEventArgs e)
|
{
|
if (parentItem == null)
|
{
|
return;
|
}
|
TestVariable parent = (TestVariable)parentItem.DataContext;
|
int index = parent.Children.IndexOf(source);
|
if (index < 0)
|
{
|
return;
|
}
|
|
TestVariableMenuItem item = (TestVariableMenuItem)sender;
|
|
|
|
if (item.TargetIsArray)
|
{
|
string ValidateName(string name)
|
{
|
if (string.IsNullOrEmpty(name))
|
{
|
return LangUtil.Get("参数名称不能为空");
|
}
|
var target = parent.Children?.FirstOrDefault(e => e.Name == name);
|
if (target != null && target != source)
|
{
|
return LangUtil.Format("参数名称重复2", name, parent.Name);
|
}
|
return null;
|
}
|
|
var win = new ArrayVarConfig(ValidateName)
|
{
|
VarName = source.Name,
|
VarType = item.TargetType,
|
Length = source.Children.Count,
|
Owner = Window.GetWindow(this),
|
};
|
|
if (win.ShowDialog() != true)
|
{
|
return;
|
}
|
|
if (source.IsArray && source.Type == win.VarType && source.Children.Count == win.Length)
|
{
|
return;
|
}
|
|
ObservableCollection<TestVariable> olds = new ObservableCollection<TestVariable>();
|
if (source.IsArray && source.Type == win.VarType)
|
{
|
olds = source.Children;
|
}
|
|
TestVariable newOne = new TestVariable
|
{
|
IsArray = true,
|
Name = win.VarName,
|
Type = win.VarType
|
};
|
|
for (int i = 0; i < win.Length; i++)
|
{
|
TestVariable child = new TestVariable
|
{
|
IsArray = false,
|
Type = newOne.Type,
|
Name = $"[{i}]",
|
Value = i < olds.Count ? olds[i].Value : TestVariable.DefaultValue(newOne.Type)
|
};
|
newOne.Children.Add(child);
|
}
|
parent.Children[index] = newOne;
|
}
|
else
|
{
|
if (!source.IsArray && source.Type == item.TargetType)
|
{
|
return;
|
}
|
TestVariable newOne = new TestVariable
|
{
|
IsArray = false,
|
Name = source.Name,
|
Type = item.TargetType,
|
Value = TestVariable.DefaultValue(item.TargetType)
|
};
|
parent.Children[index] = newOne;
|
}
|
}
|
|
foreach (TestVariableType type in Enum.GetValues(typeof(TestVariableType)))
|
{
|
TestVariableMenuItem menuItem = new TestVariableMenuItem();
|
menuItem.Header = type.ToString();
|
menuItem.Variable = source;
|
|
menuItem.Click += MenuItem_Click1; ;
|
menuItem.TargetIsArray = false;
|
menuItem.TargetType = type;
|
menu.Items.Add(menuItem);
|
}
|
|
var arrItem = new MenuItem();
|
arrItem.Header = "Array Of...";
|
foreach (TestVariableType type in Enum.GetValues(typeof(TestVariableType)))
|
{
|
TestVariableMenuItem menuItem = new TestVariableMenuItem();
|
menuItem.Header = type.ToString();
|
menuItem.Variable = source;
|
|
menuItem.Click += MenuItem_Click1;
|
menuItem.TargetIsArray = true;
|
menuItem.TargetType = type;
|
arrItem.Items.Add(menuItem);
|
}
|
menu.Items.Add(arrItem);
|
menu.IsOpen = true;
|
}
|
}
|
}
|