using CommunityToolkit.Mvvm.ComponentModel;
|
using OpenTap;
|
using OpenTapEditor.Provider;
|
using System.Collections.ObjectModel;
|
using System.ComponentModel;
|
using System.Reflection;
|
using System.Text;
|
using System.Windows;
|
using System.Windows.Controls;
|
using System.Xml.Serialization;
|
|
namespace OpenTapEditor
|
{
|
[ObservableObject]
|
public partial class SettingNode
|
{
|
[ObservableProperty]
|
private string title;
|
|
[ObservableProperty]
|
private ObservableCollection<SettingNode> children;
|
public List<string> Groups { get; set; }
|
public AnnotationCollection Item { get; set; }
|
|
}
|
|
/// <summary>
|
/// StepSettingView.xaml 的交互逻辑
|
/// </summary>
|
[ObservableObject]
|
public partial class StepSettingView : UserControl
|
{
|
[ObservableProperty]
|
private ObservableCollection<SettingNode> list;
|
|
private object obj;
|
private StackPanel panel = new StackPanel();
|
|
private AnnotationCollection annotations { get; set; }
|
private List<AnnotationCollection> items { get; set; }
|
|
static ITypeData resourceTypeData = TypeData.FromType(typeof(IResource));
|
public StepSettingView()
|
{
|
DataContext = this;
|
InitializeComponent();
|
}
|
|
public Dictionary<string, Expander> Groups;
|
|
public static bool FilterMember(IMemberData member)
|
{
|
if (member.DeclaringType.DescendsTo(resourceTypeData) && member.Name == nameof(Resource.Name))
|
return true;
|
if (member.GetAttribute<BrowsableAttribute>() is BrowsableAttribute attr)
|
return attr.Browsable;
|
if (member.HasAttribute<OutputAttribute>())
|
return true;
|
return member.Attributes.Any(a => a is XmlIgnoreAttribute) == false && member.Writable;
|
}
|
|
AnnotationCollection[] getMembers()
|
{
|
return annotations?.Get<IMembersAnnotation>()?.Members
|
.Where(x =>
|
{
|
var member = x.Get<IMemberAnnotation>().Member;
|
if (member.DeclaringType.DescendsTo(resourceTypeData) && member.Name == nameof(Resource.Name))
|
return true;
|
|
return x.Get<IAccessAnnotation>()?.IsVisible ?? false;
|
})
|
.Where(x =>
|
{
|
var member = x.Get<IMemberAnnotation>()?.Member;
|
if (member == null || (member.GetAttribute<SubmitAttribute>() != null && x.Get<IAvailableValuesAnnotationProxy>() != null)) return false;
|
return FilterMember(member);
|
})
|
.ToArray();
|
}
|
|
private SettingNode CreateNode(AnnotationCollection annotations)
|
{
|
string name = annotations.Get<DisplayAttribute>().Name;
|
var node = new SettingNode();
|
node.Item = annotations;
|
return node;
|
}
|
|
private object RenderControl(AnnotationCollection x) {
|
if (x == null)
|
return null;
|
var multi = x.Get<IMultiSelectAnnotationProxy>();
|
|
|
|
try
|
{
|
if (x.Get<IObjectValueAnnotation>()?.Value is Action)
|
return new Button() { Content = x.Get<DisplayAttribute>().Name };
|
|
var stack = new StackPanel { Orientation = Orientation.Horizontal };
|
|
|
var nameBuilder = new StringBuilder();
|
string value = ((x.Get<IAvailableValuesAnnotation>() as IStringReadOnlyValueAnnotation)?.Value
|
?? x.Get<IStringValueAnnotation>()?.Value
|
?? x.Get<IStringReadOnlyValueAnnotation>()?.Value
|
?? x.Get<IAvailableValuesAnnotationProxy>()?.SelectedValue?.Source?.ToString()
|
?? x.Get<IObjectValueAnnotation>()?.Value)?.ToString()
|
?? "...";
|
// replace new lines with spaces for viewing.
|
value = value.Replace("\n", " ").Replace("\r", "");
|
|
var icons = x.GetAll<IIconAnnotation>().ToArray();
|
var icons2 = new HashSet<string>(icons.Select(y => y.IconName));
|
bool icon(string name) => icons2.Contains(name);
|
nameBuilder.Clear();
|
if (icon(IconNames.OutputAssigned))
|
nameBuilder.Append('●'); //
|
else if (icon(IconNames.Output))
|
nameBuilder.Append(" ⃝"); //
|
if (icon(IconNames.Input))
|
{
|
nameBuilder.Append("●"); // ●
|
nameBuilder.Append("→"); //
|
}
|
if (icon(IconNames.Parameterized))
|
nameBuilder.Append("♦");//
|
if (x.Get<IMemberAnnotation>()?.Member is IParameterMemberData)
|
nameBuilder.Append("◊");//
|
|
if (nameBuilder.Length > 0)
|
nameBuilder.Append(" ");
|
|
nameBuilder.Append(x.Get<DisplayAttribute>().Name);
|
|
stack.Children.Add(new TextBlock { Text = nameBuilder.ToString() });
|
stack.Children.Add(new TextBox { Text = value });
|
//nameBuilder.Append(": ");
|
//nameBuilder.Append(value);
|
|
|
|
// Don't show member name if layout is fullrow
|
if (x.Get<IMemberAnnotation>()?.Member.GetAttribute<LayoutAttribute>()?.Mode == LayoutMode.FullRow)
|
return stack;
|
|
|
// Check validation rules
|
var step = x.Source as IValidatingObject;
|
var propertyName = x.Get<IMemberAnnotation>()?.Member?.Name;
|
var rule = step?.Rules.FirstOrDefault(r => r.PropertyName == propertyName && r?.IsValid() == false);
|
if (rule != null)
|
stack.Children.Add(new TextBlock { Text = "!" });
|
|
return stack;
|
}
|
catch
|
{
|
return null;
|
}
|
}
|
|
string getTitle(AnnotationCollection x)
|
{
|
if (x == null)
|
return "";
|
|
try
|
{
|
var nameBuilder = new StringBuilder();
|
string value = ((x.Get<IAvailableValuesAnnotation>() as IStringReadOnlyValueAnnotation)?.Value
|
?? x.Get<IStringValueAnnotation>()?.Value
|
?? x.Get<IStringReadOnlyValueAnnotation>()?.Value
|
?? x.Get<IAvailableValuesAnnotationProxy>()?.SelectedValue?.Source?.ToString()
|
?? x.Get<IObjectValueAnnotation>()?.Value)?.ToString()
|
?? "...";
|
// replace new lines with spaces for viewing.
|
value = value.Replace("\n", " ").Replace("\r", "");
|
|
if (x.Get<IObjectValueAnnotation>()?.Value is Action)
|
return $"[ {x.Get<DisplayAttribute>().Name} ]";
|
|
// Don't show member name if layout is fullrow
|
if (x.Get<IMemberAnnotation>()?.Member.GetAttribute<LayoutAttribute>()?.Mode == LayoutMode.FullRow)
|
return value;
|
var icons = x.GetAll<IIconAnnotation>().ToArray();
|
var icons2 = new HashSet<string>(icons.Select(y => y.IconName));
|
bool icon(string name) => icons2.Contains(name);
|
nameBuilder.Clear();
|
if (icon(IconNames.OutputAssigned))
|
nameBuilder.Append('●'); //
|
else if (icon(IconNames.Output))
|
nameBuilder.Append(" ⃝"); //
|
if (icon(IconNames.Input))
|
{
|
nameBuilder.Append("●"); // ●
|
nameBuilder.Append("→"); //
|
}
|
if (icon(IconNames.Parameterized))
|
nameBuilder.Append("♦");//
|
if (x.Get<IMemberAnnotation>()?.Member is IParameterMemberData)
|
nameBuilder.Append("◊");//
|
|
if (nameBuilder.Length > 0)
|
nameBuilder.Append(" ");
|
|
nameBuilder.Append(x.Get<DisplayAttribute>().Name);
|
nameBuilder.Append(": ");
|
nameBuilder.Append(value);
|
|
// Check validation rules
|
var step = x.Source as IValidatingObject;
|
var propertyName = x.Get<IMemberAnnotation>()?.Member?.Name;
|
var rule = step?.Rules.FirstOrDefault(r => r.PropertyName == propertyName && r?.IsValid() == false);
|
if (rule != null)
|
nameBuilder.Append(" !");
|
|
return nameBuilder.ToString();
|
}
|
catch
|
{
|
return "";
|
}
|
}
|
|
public SettingNode GetNodeFromItem(AnnotationCollection item)
|
{
|
SettingNode node = CreateNode(item);
|
node.Title = getTitle(item);
|
//node.Children = getChildren?.Invoke(item).Select(i => new TreeViewNode<T>(i, this)).ToList() ?? new List<TreeViewNode<T>>();
|
|
//if (getParent != null)
|
//{
|
// var parent = getParent(item);
|
// if (parent != null && nodes.ContainsKey(parent))
|
// node.Parent = nodes[parent];
|
// else
|
// node.Parent = null;
|
//}
|
|
return node;
|
}
|
|
private Expander BuildGroupTree(SettingNode node)
|
{
|
Expander groupNode = null;
|
Expander lastGroup = null;
|
string groupKey = null;
|
foreach (var group in node.Groups)
|
{
|
groupKey = string.IsNullOrEmpty(groupKey) ? group : (groupKey + "." + group);
|
groupNode = null;
|
if (Groups.TryGetValue(groupKey, out groupNode) == false)
|
{
|
// add the group
|
groupNode = new Expander
|
{
|
Header = groupKey,
|
Content = new StackPanel()
|
};
|
Groups[groupKey] = groupNode;
|
|
if (lastGroup != null)
|
{
|
((StackPanel)lastGroup.Content).Children.Add(groupNode);
|
}
|
else
|
{
|
panel.Children.Add(groupNode);
|
}
|
}
|
lastGroup = groupNode;
|
}
|
return groupNode;
|
//if (lastGroup != null)
|
//{
|
// node.Parent = lastGroup;
|
// if (lastGroup.Children.Contains(node) == false)
|
// lastGroup.Children.Add(node);
|
//}
|
}
|
|
|
ObservableCollection<SettingNode> GetItemsToRenderWithGroup(bool noCache)
|
{
|
SettingNode node;
|
var list = new ObservableCollection<SettingNode>();
|
// Build groups tree
|
foreach (var item in items)
|
{
|
var _groups = item?.Get<DisplayAttribute>().Group.ToList();
|
node = GetNodeFromItem(item);
|
node.Groups = _groups ?? new List<string>();
|
var expander = BuildGroupTree(node);
|
var control = RenderControl(item);
|
if (control == null) continue;
|
if (expander == null)
|
{
|
panel.Children.Add((UIElement)control);
|
}
|
else {
|
((StackPanel)expander.Content).Children.Add((UIElement)control);
|
}
|
|
list.Add(node);
|
}
|
|
//foreach (var item in items)
|
//{
|
// var node = nodes[item];
|
// if (node.Groups.Any())
|
// {
|
// var firstGroup = groups[node.Groups.First()];
|
// if (list.Contains(firstGroup))
|
// continue;
|
|
// list.Add(firstGroup);
|
// list.AddRange(printGroup(firstGroup));
|
// }
|
// else
|
// list.Add(node);
|
//}
|
|
return list;
|
}
|
|
public void RenderTreeView(bool noCache = false)
|
{
|
if (items == null)
|
return;
|
|
var list = new ObservableCollection<SettingNode>();
|
list = GetItemsToRenderWithGroup(noCache);
|
this.List = list;
|
}
|
|
public void UpdateSource(object obj)
|
{
|
this.obj = obj ?? new object();
|
if (obj is TestStep step) {
|
var sss = BreakConditionProperty.GetBreakCondition(step);
|
|
|
}
|
|
|
|
var sb = obj.GetType().GetProperties(BindingFlags.Instance|BindingFlags.DeclaredOnly |BindingFlags.Static| BindingFlags.Public | BindingFlags.NonPublic);
|
|
|
var sssb = obj.GetType().GetProperties(BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
|
List<PropertyInfo> props = new List<PropertyInfo>();
|
List<string> names = new List<string>();
|
foreach (var prop in sssb) {
|
var attr = prop.GetCustomAttribute<DisplayAttribute>();
|
if (attr == null) {
|
continue;
|
}
|
names.Add(attr.Name ?? prop.Name);
|
props.Add(prop);
|
}
|
annotations = AnnotationCollection.Annotate(obj);
|
view.Children.Clear();
|
//view.Children.Add(DutControlProvider.GetControl(annotations));
|
view.Children.Add(GridControlProvider.GetControl(obj));
|
}
|
|
//public void UpdateSource(object obj)
|
//{
|
// this.obj = obj ?? new object();
|
// annotations = AnnotationCollection.Annotate(obj);
|
// Groups = new Dictionary<string, Expander>();
|
// panel.Children.Clear();
|
|
// this.items = getMembers()?.ToList() ?? new List<AnnotationCollection>();
|
// RenderTreeView();
|
//}
|
}
|
}
|