using AddInPlugin;
|
using AddInPlugin.Setting;
|
using AddInPlugin.Util;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
using Microsoft.Win32;
|
using OpenTap;
|
using OpenTap.Addin;
|
using OpenTap.Addin.Listener;
|
using OpenTap.Addin.Reader;
|
using OpenTap.Addin.Util;
|
using OpenTap.Diagnostic;
|
using OpenTap.Plugins.BasicSteps;
|
using SeqEditor.UI;
|
using SeqEditor.Util;
|
using System.Collections.ObjectModel;
|
using System.ComponentModel;
|
using System.IO;
|
using System.Windows;
|
using System.Windows.Controls;
|
using System.Windows.Input;
|
using UtilLib;
|
using ViHelper;
|
|
namespace OpenTapEditor;
|
|
/// <summary>
|
/// Interaction logic for MainWindow.xaml
|
/// </summary>
|
[ObservableObject]
|
public partial class SeqEditorUI : UserControl, IUserInputInterface, IUserInterface
|
{
|
public static readonly TraceSource Log = OpenTap.Log.CreateSource("Editor");
|
|
[ObservableProperty]
|
private ObservableCollection<MenuItem> fileItems;
|
|
[ObservableProperty]
|
private ObservableCollection<TabItemData> tabItems = new ObservableCollection<TabItemData>();
|
|
[ObservableProperty]
|
private ObservableCollection<MenuItem> fileMenuItems = new ObservableCollection<MenuItem>();
|
|
[ObservableProperty]
|
private TabItemData selectedTab;
|
|
public static SeqEditorUI Instance { get; private set; }
|
|
public LogControl LogControl { get => logControl; }
|
|
public PostUIMessageHandler uiMessageHandler { get; private set; }
|
|
public SeqEditorUI()
|
{
|
InitializeComponent();
|
RefreshFileMenuItems();
|
OpenTap.Log.AddListener(logControl);
|
uiMessageHandler = PostUIMessageHandler.Get();
|
uiMessageHandler.OnPostUIMsg += PostUIMsgHandler_OnPostUIMsg;
|
//PostUIMsgHandler.OnPostUIMsg += PostUIMsgHandler_OnPostUIMsg;
|
StationGlobalsManager.Register(UIStationGlobalsManager.Instance);
|
VariableResolverFactory.Register(new DefaultVariableResolverFactory());
|
PropertyInfoCache.Refresh(typeof(LabViHelper), typeof(MethodVariable));
|
ResultSettings.Current.Add(uiMessageHandler);
|
|
UserInput.SetInterface(this);
|
Instance = this;
|
}
|
|
public void PostUIMsgHandler_OnPostUIMsg(object? sender, PostUIMsg e)
|
{
|
logControl.EventsLogged(new List<Event>
|
{
|
new Event{
|
Message = $"string:{e.StringData} bool:{e.BoolData} number:{e.NumberData}"
|
}
|
});
|
}
|
|
private void LoadRecentFiles()
|
{
|
historyFile.Clear();
|
try
|
{
|
var list = XmlHelper.DeserializeFromXml<List<string>>(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config", "RecentFiles.xml"));
|
if (list != null)
|
{
|
foreach (var file in list)
|
{
|
historyFile.Enqueue(file);
|
}
|
}
|
}
|
catch
|
{
|
historyFile = new Queue<string>(10);
|
}
|
}
|
|
private void RefreshFileMenuItems()
|
{
|
FileMenuItems.Clear();
|
var child = new MenuItem()
|
{
|
Tag = "新建"
|
};
|
child.SetValue(MenuItem.HeaderProperty, new DynamicResourceExtension("新建").ProvideValue(null));
|
child.Click += (sender, e) =>
|
{
|
var testPlan = new TestPlan() { VisualPath = new Guid().ToString() };
|
var tabItem = new TabItemData
|
{
|
Content = new SequencePanel(testPlan)
|
{
|
HasChanged = true
|
},
|
TestPlan = testPlan
|
};
|
TabItems.Add(tabItem);
|
SelectedTab = tabItem;
|
};
|
FileMenuItems.Add(child);
|
|
child = new MenuItem()
|
{
|
Tag = "打开"
|
};
|
child.SetValue(MenuItem.HeaderProperty, new DynamicResourceExtension("打开").ProvideValue(null));
|
|
child.Click += MenuItem_Click;
|
FileMenuItems.Add(child);
|
var panel = SelectedTab?.Content as SequencePanel;
|
|
if (panel != null)
|
{
|
child = new MenuItem()
|
{
|
Header = $"保存{panel.TabName}",
|
InputGestureText = "Ctrl + S"
|
};
|
child.Click += (sender, e) =>
|
{
|
if (panel.TrySaveTestStep(this.CheckCanSaveAs))
|
{
|
|
}
|
StationGlobalsManager.WriteToLocal(UIStationGlobalsManager.Instance.Datasource);
|
};
|
FileMenuItems.Add(child);
|
}
|
else
|
{
|
child = new MenuItem()
|
{
|
Header = $"保存",
|
IsEnabled = false
|
};
|
}
|
|
if (panel != null)
|
{
|
child = new MenuItem()
|
{
|
Header = $"另存{panel.TabName}",
|
};
|
child.Click += (sender, e) =>
|
{
|
panel.TrySaveAs(this.CheckCanSaveAs);
|
StationGlobalsManager.WriteToLocal(UIStationGlobalsManager.Instance.Datasource);
|
};
|
FileMenuItems.Add(child);
|
}
|
else
|
{
|
child = new MenuItem()
|
{
|
Header = $"另存",
|
IsEnabled = false
|
};
|
}
|
}
|
|
private bool CheckCanSaveAs(string fileName)
|
{
|
var item = TabItems.FirstOrDefault(i => i.TestPlan.Path == fileName);
|
if (item != null)
|
{
|
MessageBox.Show($"文件 {fileName} 已经打开,无法另存为同名文件", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
return false;
|
}
|
return true;
|
}
|
|
private void SaveRecentFiles()
|
{
|
var dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config");
|
if (!Directory.Exists(dir))
|
{
|
Directory.CreateDirectory(dir);
|
}
|
var path = Path.Combine(dir, "RecentFiles.xml");
|
XmlHelper.SerializeToXml(path, historyFile);
|
}
|
|
private Queue<string> historyFile = new Queue<string>(10);
|
|
|
public static Type GetEnumerableElementType(Type enumType)
|
{
|
if (enumType.IsArray)
|
return enumType.GetElementType();
|
|
var ienumInterface = enumType.GetInterface("IEnumerable`1") ?? enumType;
|
if (ienumInterface != null)
|
return ienumInterface.GetGenericArguments().FirstOrDefault();
|
|
return typeof(object);
|
}
|
|
private void OpenStepSettingWin()
|
{
|
var win = new StepWindow()
|
{
|
Owner = Window.GetWindow(this)
|
};
|
if (win.ShowDialog() == true)
|
{
|
|
}
|
}
|
|
private void RefreshUI()
|
{
|
Application.Current.Resources["GlobalFontSize"] = StationSettings.Current.FontSize;
|
LangUtil.LoadLang();
|
}
|
|
private void TryOpenStationSetting()
|
{
|
|
try
|
{
|
var setting = TypeData.GetDerivedTypes<ComponentSettings>()
|
.Where(x => x.CanCreateInstance && (x.GetAttribute<BrowsableAttribute>()?.Browsable ?? true))
|
.OfType<TypeData>()
|
.FirstOrDefault(x => x.Name == typeof(StationSettings).FullName);
|
if (setting == null)
|
{
|
return;
|
}
|
|
ComponentSettings obj = null;
|
|
obj = ComponentSettings.GetCurrent(setting.Load());
|
|
setting = TypeData.GetDerivedTypes<ComponentSettings>()
|
.Where(x => x.CanCreateInstance && (x.GetAttribute<BrowsableAttribute>()?.Browsable ?? true))
|
.OfType<TypeData>()
|
.FirstOrDefault(x => x.Name == typeof(StationGlobalsSetting).FullName);
|
var sss = ComponentSettings.GetCurrent(setting.Load());
|
|
var setgroup = setting.GetAttribute<SettingsGroupAttribute>()?.GroupName ?? "Settings";
|
var name = setting.GetDisplayAttribute().Name;
|
|
StationSettingWin win = new StationSettingWin
|
{
|
Owner = Window.GetWindow(this)
|
};
|
if (win.Open(obj) == true)
|
{
|
ComponentSettings.SaveAllCurrentSettings();
|
RefreshUI();
|
}
|
}
|
catch (Exception ex)
|
{
|
MessageBox.Show(ex.Message);
|
}
|
|
//UISettiingWin win = new UISettiingWin
|
//{
|
// Owner = this
|
//};
|
//win.ShowDialog();
|
}
|
|
private void MenuItem_Click(object sender, RoutedEventArgs e)
|
{
|
var item = sender as MenuItem;
|
if (item?.Tag?.ToString() == "UISetting")
|
{
|
TryOpenStationSetting();
|
return;
|
}
|
|
switch (item?.Tag)
|
{
|
case "打开":
|
TryOpenTestPlanNew();
|
break;
|
case "保存":
|
// TrySaveTestStep();
|
break;
|
case "另存":
|
break;
|
case "自定义测试步骤":
|
OpenStepSettingWin();
|
break;
|
case "openSetting":
|
var setting = new SettingWin()
|
{
|
Owner = Window.GetWindow(this)
|
};
|
setting.ShowDialog();
|
break;
|
default:
|
break;
|
}
|
}
|
|
private void self_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
{
|
/// 保存一下StationGlobals变量
|
UIStationGlobalsManager.Instance.WriteToLocal(UIStationGlobalsManager.Instance.Datasource);
|
}
|
|
private void CloseTabItem_Click(object sender, RoutedEventArgs e)
|
{
|
try
|
{
|
if (sender is Button button && button.Tag is TabItemData tabItem)
|
{
|
if (tabItem.Content is SequencePanel editor)
|
{
|
if (editor.HasChanged)
|
{
|
if (SelectedTab != tabItem)
|
{
|
SelectedTab = tabItem;
|
}
|
var res = MessageBox.Show("是否保存?", "提示", MessageBoxButton.YesNoCancel);
|
if (res == MessageBoxResult.Cancel)
|
{
|
return;
|
}
|
if (res == MessageBoxResult.Yes)
|
{
|
if (!editor.TrySaveTestStep(this.CheckCanSaveAs))
|
{
|
return;
|
}
|
}
|
}
|
editor.Close();
|
TabItems.Remove(tabItem);
|
}
|
else if (tabItem.Content is ExecutionPanel executiion)
|
{
|
if (executiion.IsRunning)
|
{
|
if (SelectedTab != tabItem)
|
{
|
SelectedTab = tabItem;
|
}
|
var res = MessageBox.Show("运行中是否终止?", "提示", MessageBoxButton.YesNo);
|
if (res == MessageBoxResult.No)
|
{
|
return;
|
}
|
if (res == MessageBoxResult.Yes)
|
{
|
executiion.StopRunTestPlan();
|
}
|
}
|
executiion.Close();
|
TabItems.Remove(tabItem);
|
}
|
|
|
}
|
}
|
catch (Exception ex)
|
{
|
|
}
|
}
|
|
//private Dictionary<string, TabItemData> OpendPlanItem = new Dictionary<string, TabItemData>();
|
|
private void TryOpenTestPlanNew()
|
{
|
OpenFileDialog ofd = new OpenFileDialog()
|
{
|
Filter = "Test Plan|*.TapPlan",
|
DefaultExt = ".TapPlan"
|
};
|
if (ofd.ShowDialog() == true)
|
{
|
try
|
{
|
var item = TabItems.FirstOrDefault(i => i.TestPlan.Path == ofd.FileName);
|
if (item != null)
|
{
|
SelectedTab = item;
|
}
|
else
|
{
|
//var testPlan = TestPlan.Load(ofd.FileName);
|
var testPlan = TestPlanReader.ReadTestPlan(ofd.FileName);
|
BreakConditionProperty.SetBreakCondition(testPlan, BreakCondition.BreakOnFail);
|
var tabItem = new TabItemData
|
{
|
Content = new SequencePanel(testPlan),
|
TestPlan = testPlan
|
};
|
TabItems.Add(tabItem);
|
SelectedTab = tabItem;
|
}
|
// historyFile.Enqueue(ofd.FileName);
|
// SaveRecentFiles();
|
}
|
catch (Exception ex)
|
{
|
Log.Error("Open TestPlan Error! {0}", ex);
|
MessageBox.Show($"打开测试计划失败: {ex.Message} {ex.StackTrace}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
}
|
}
|
}
|
|
partial void OnSelectedTabChanged(TabItemData value)
|
{
|
RefreshFileMenuItems();
|
}
|
|
public void RequestUserInput(object dataObject, TimeSpan Timeout, bool modal)
|
{
|
if (dataObject is DialogRequest req)
|
{
|
Dispatcher.BeginInvoke(() =>
|
{
|
if (req.Buttons == InputButtons.OkCancel)
|
{
|
var res = MessageBox.Show(req.Message, req.Name, MessageBoxButton.OKCancel);
|
req.Input2 = res == MessageBoxResult.OK ? WaitForInputResult2.Ok : WaitForInputResult2.Cancel;
|
}
|
else
|
{
|
var res = MessageBox.Show(req.Message, req.Name, MessageBoxButton.YesNo);
|
req.Input1 = res == MessageBoxResult.Yes ? WaitForInputResult1.Yes : WaitForInputResult1.No;
|
}
|
}).Wait();
|
}
|
else if (dataObject is OpenTap.TestPlan.PlanLoadError err)
|
{
|
Dispatcher.BeginInvoke(() =>
|
{
|
var res = MessageBox.Show(err.Message, err.Name, MessageBoxButton.OKCancel);
|
err.Response = res == MessageBoxResult.OK ? TestPlan.PlanLoadErrorResponse.Ignore : TestPlan.PlanLoadErrorResponse.Abort;
|
}).Wait();
|
}
|
}
|
|
public void NotifyChanged(object obj, string property)
|
{
|
Dispatcher.BeginInvoke(() =>
|
{
|
if (obj is TestPlan plan)
|
{
|
if (SelectedTab?.Content is SequencePanel currentTab && plan == currentTab.Plan && property != "Path" && property != "Name")
|
{
|
currentTab.HasChanged = true;
|
}
|
}
|
else if (obj is ITestStep step)
|
{
|
if (SelectedTab?.Content is SequencePanel currentTab && step == currentTab.settingView.Step)
|
{
|
currentTab.HasChanged = true;
|
}
|
}
|
});
|
}
|
|
public void RunTestPlan(TestPlan plan, string seqName, RuningMode mode)
|
{
|
var runningPlan = plan.DeepClone();
|
var exe = new ExecutionPanel(runningPlan, seqName);
|
var tabItem = new TabItemData
|
{
|
Content = exe,
|
TestPlan = runningPlan
|
};
|
TabItems.Add(tabItem);
|
SelectedTab = tabItem;
|
exe.RunTestPlan(mode);
|
}
|
|
private void self_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
|
{
|
if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.S)
|
{
|
if (SelectedTab?.Content is SequencePanel panel && panel.TrySaveTestStep(this.CheckCanSaveAs))
|
{
|
StationGlobalsManager.WriteToLocal(UIStationGlobalsManager.Instance.Datasource);
|
}
|
}
|
}
|
|
private void self_Loaded(object sender, RoutedEventArgs e)
|
{
|
try
|
{
|
LvlibpLoader.PreLoad();
|
Log.Debug("PreLoad completed.");
|
}
|
catch (Exception ex)
|
{
|
Log.Error("PreLoad error. {0}", ex);
|
}
|
}
|
|
private void MenuItem_Click_1(object sender, RoutedEventArgs e)
|
{
|
GC.Collect();
|
}
|
}
|