using OpenTap; using OpenTap.Addin.Annotation; using OpenTapEditor.UI; using System.ComponentModel; using System.Windows.Controls; using System.Windows.Data; using System.Xml.Serialization; namespace OpenTapEditor.Provider { public class DutControlProvider { private static ITypeData resourceTypeData = TypeData.FromType(typeof(IResource)); public static object? GetItemValue(AnnotationCollection x) { return (x.Get() as IStringReadOnlyValueAnnotation)?.Value ?? x.Get()?.Value ?? x.Get()?.Value ?? x.Get()?.SelectedValue?.Source?.ToString() ?? x.Get()?.Value; } public static AnnotationCollection[]? getMembers(AnnotationCollection annotations) { return annotations?.Get()?.Members .Where(x => { var member = x.Get().Member; if (member.DeclaringType.DescendsTo(TypeData.FromType(typeof(IResource))) && 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(); } public static StackPanel test(AnnotationCollection annotation) { var valueAnnotation = annotation.Get(); if (valueAnnotation == null) return null; StackPanel stack = new StackPanel() { Orientation = Orientation.Horizontal }; stack.Children.Add(new TextBlock { Text = annotation.Get().Name }); /// 列表 if (annotation.Get() is ICollectionAnnotation caa) { if (annotation.Get() != null) return null; var fixedSize = annotation.Get()?.IsFixedSize ?? false; var items = caa.AnnotatedElements.Select(a => a.Source).ToArray(); var dataType = caa.AnnotatedElements.GetType(); //Type genericArgument = dataType.GetGenericArguments()[0]; bool placeholderElementAdded = false; var dataGrid = new DataGrid(); if (annotation.Get() is BindingListAttribute bla) { BindingOperations.SetBinding(dataGrid, DataGrid.ItemsSourceProperty, new Binding(bla.BindingName) { Source = annotation.Source, Mode = BindingMode.TwoWay, }); dataGrid.CanUserAddRows = bla.CanAdd; dataGrid.AutoGenerateColumns = false; Type propertyType = annotation?.Source?.GetType()?.GetProperty(bla.BindingName)?.PropertyType; if (propertyType?.IsGenericType == true) { DataGridHelper.SetDataGridColumns(dataGrid, propertyType.GetGenericArguments()[0]); } else { DataGridHelper.SetDataGridColumns(dataGrid, propertyType); } } else { dataGrid.ItemsSource = items; } stack.Children.Add(dataGrid); return stack; } // StringValue是正常的输入 // IAvailableValuesAnnotation 是枚举 // IStringReadOnlyValueAnnotation是只读 var stringValueAnnotation = annotation.Get(); if (stringValueAnnotation == null) return null; var selectAnnotation = annotation.Get(); if (selectAnnotation != null) { var source = selectAnnotation.AvailableValues; var comboBox = new ComboBox { DisplayMemberPath = "Source.Name", ItemsSource = source }; BindingOperations.SetBinding(comboBox, ComboBox.SelectedItemProperty, new Binding(nameof(IAvailableValuesAnnotationProxy.SelectedValue)) { Source = selectAnnotation, Mode = BindingMode.TwoWay, NotifyOnSourceUpdated = true, }); comboBox.SourceUpdated += (sender, e) => { annotation.Write(); annotation.Read(); }; stack.Children.Add(comboBox); return stack; } if (annotation.Get() is FilePathAttribute fpa) { FileSelector fs = new FileSelector(); stack.Children.Add(fs); BindingOperations.SetBinding(fs, FileSelector.FilePathProperty, new Binding(nameof(IStringValueAnnotation.Value)) { Source = stringValueAnnotation, Mode = BindingMode.TwoWay, NotifyOnSourceUpdated = true }); fs.SourceUpdated += (sender, e) => { annotation.Write(); annotation.Read(); }; return stack; } if (annotation.Get() is DynamicSelectAttribute dsa) { ComboBox combox = new ComboBox(); stack.Children.Add(combox); BindingOperations.SetBinding(combox, ComboBox.ItemsSourceProperty, new Binding(dsa.SourceName) { Source = dsa, Mode = BindingMode.OneWay }); BindingOperations.SetBinding(combox, ComboBox.TextProperty, new Binding(nameof(stringValueAnnotation.Value)) { Source = stringValueAnnotation, Mode = BindingMode.TwoWay, NotifyOnSourceUpdated = true }); combox.SourceUpdated += (sender, e) => { annotation.Write(); annotation.Read(); }; return stack; } TextBox tb = new TextBox(); stack.Children.Add(tb); BindingOperations.SetBinding(tb, TextBox.TextProperty, new Binding(nameof(IStringValueAnnotation.Value)) { Source = stringValueAnnotation, Mode = BindingMode.TwoWay, NotifyOnSourceUpdated = true }); tb.SourceUpdated += (sender, e) => { annotation.Write(); annotation.Read(); }; //var update = annotation.Get(true); //if (update != null) //{ // update.RegisterSourceUpdated(tb, () => tb.GetBindingExpression(TextBox.TextProperty).UpdateTarget()); //} return stack; } 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; } public static StackPanel GetControl(AnnotationCollection annotation) { var stack = new StackPanel() { }; var groupCache = new Dictionary(); Expander GetExpander(List groups) { Expander groupNode = null; Expander lastGroup = null; string groupKey = null; foreach (var group in groups) { groupKey = string.IsNullOrEmpty(groupKey) ? group : (groupKey + "." + group); groupNode = null; if (groupCache.TryGetValue(groupKey, out groupNode) == false) { // add the group groupNode = new Expander { IsExpanded = true, Header = groupKey, Content = new StackPanel() }; groupCache[groupKey] = groupNode; if (lastGroup != null) { ((StackPanel)lastGroup.Content).Children.Add(groupNode); } else { stack.Children.Add(groupNode); } } lastGroup = groupNode; } return groupNode; } var members = getMembers(annotation); foreach (var ann in members) { var control = test(ann); if (control == null) continue; var _groups = ann?.Get().Group.ToList(); if (_groups == null || _groups.Count <= 0) { stack.Children.Add(control); } else { var expander = GetExpander(_groups); ((StackPanel)expander.Content).Children.Add(control); } } return stack; } } }