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 children; public List Groups { get; set; } public AnnotationCollection Item { get; set; } } /// /// StepSettingView.xaml 的交互逻辑 /// [ObservableObject] public partial class StepSettingView : UserControl { [ObservableProperty] private ObservableCollection list; private object obj; private StackPanel panel = new StackPanel(); private AnnotationCollection annotations { get; set; } private List items { get; set; } static ITypeData resourceTypeData = TypeData.FromType(typeof(IResource)); public StepSettingView() { DataContext = this; InitializeComponent(); } public Dictionary Groups; public static bool FilterMember(IMemberData member) { if (member.DeclaringType.DescendsTo(resourceTypeData) && member.Name == nameof(Resource.Name)) return true; if (member.GetAttribute() is BrowsableAttribute attr) return attr.Browsable; if (member.HasAttribute()) return true; return member.Attributes.Any(a => a is XmlIgnoreAttribute) == false && member.Writable; } AnnotationCollection[] getMembers() { return annotations?.Get()?.Members .Where(x => { var member = x.Get().Member; if (member.DeclaringType.DescendsTo(resourceTypeData) && member.Name == nameof(Resource.Name)) return true; return x.Get()?.IsVisible ?? false; }) .Where(x => { var member = x.Get()?.Member; if (member == null || (member.GetAttribute() != null && x.Get() != null)) return false; return FilterMember(member); }) .ToArray(); } private SettingNode CreateNode(AnnotationCollection annotations) { string name = annotations.Get().Name; var node = new SettingNode(); node.Item = annotations; return node; } private object RenderControl(AnnotationCollection x) { if (x == null) return null; var multi = x.Get(); try { if (x.Get()?.Value is Action) return new Button() { Content = x.Get().Name }; var stack = new StackPanel { Orientation = Orientation.Horizontal }; var nameBuilder = new StringBuilder(); string value = ((x.Get() as IStringReadOnlyValueAnnotation)?.Value ?? x.Get()?.Value ?? x.Get()?.Value ?? x.Get()?.SelectedValue?.Source?.ToString() ?? x.Get()?.Value)?.ToString() ?? "..."; // replace new lines with spaces for viewing. value = value.Replace("\n", " ").Replace("\r", ""); var icons = x.GetAll().ToArray(); var icons2 = new HashSet(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()?.Member is IParameterMemberData) nameBuilder.Append("◊");// if (nameBuilder.Length > 0) nameBuilder.Append(" "); nameBuilder.Append(x.Get().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()?.Member.GetAttribute()?.Mode == LayoutMode.FullRow) return stack; // Check validation rules var step = x.Source as IValidatingObject; var propertyName = x.Get()?.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() as IStringReadOnlyValueAnnotation)?.Value ?? x.Get()?.Value ?? x.Get()?.Value ?? x.Get()?.SelectedValue?.Source?.ToString() ?? x.Get()?.Value)?.ToString() ?? "..."; // replace new lines with spaces for viewing. value = value.Replace("\n", " ").Replace("\r", ""); if (x.Get()?.Value is Action) return $"[ {x.Get().Name} ]"; // Don't show member name if layout is fullrow if (x.Get()?.Member.GetAttribute()?.Mode == LayoutMode.FullRow) return value; var icons = x.GetAll().ToArray(); var icons2 = new HashSet(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()?.Member is IParameterMemberData) nameBuilder.Append("◊");// if (nameBuilder.Length > 0) nameBuilder.Append(" "); nameBuilder.Append(x.Get().Name); nameBuilder.Append(": "); nameBuilder.Append(value); // Check validation rules var step = x.Source as IValidatingObject; var propertyName = x.Get()?.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(i, this)).ToList() ?? new List>(); //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 GetItemsToRenderWithGroup(bool noCache) { SettingNode node; var list = new ObservableCollection(); // Build groups tree foreach (var item in items) { var _groups = item?.Get().Group.ToList(); node = GetNodeFromItem(item); node.Groups = _groups ?? new List(); 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(); 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 props = new List(); List names = new List(); foreach (var prop in sssb) { var attr = prop.GetCustomAttribute(); 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(); // panel.Children.Clear(); // this.items = getMembers()?.ToList() ?? new List(); // RenderTreeView(); //} } }