diff --git a/ZuneUIXTools/Converters/CastValueConverter.cs b/ZuneUIXTools/Converters/CastValueConverter.cs new file mode 100644 index 0000000..0a11259 --- /dev/null +++ b/ZuneUIXTools/Converters/CastValueConverter.cs @@ -0,0 +1,18 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace ZuneUIXTools.Converters; + +public class CastValueConverter : IValueConverter +{ + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return value; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return value; + } +} diff --git a/ZuneUIXTools/Modules/Inspectors/EnumerableEditorView.xaml b/ZuneUIXTools/Modules/Inspectors/EnumerableEditorView.xaml new file mode 100644 index 0000000..e547d24 --- /dev/null +++ b/ZuneUIXTools/Modules/Inspectors/EnumerableEditorView.xaml @@ -0,0 +1,22 @@ + + + + + + + + + + + diff --git a/ZuneUIXTools/Modules/Inspectors/EnumerableEditorView.xaml.cs b/ZuneUIXTools/Modules/Inspectors/EnumerableEditorView.xaml.cs new file mode 100644 index 0000000..4bb8a60 --- /dev/null +++ b/ZuneUIXTools/Modules/Inspectors/EnumerableEditorView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace ZuneUIXTools.Modules.Inspectors +{ + /// + /// Interaction logic for EnumerableEditorView.xaml + /// + public partial class EnumerableEditorView : UserControl + { + public EnumerableEditorView() + { + InitializeComponent(); + } + } +} diff --git a/ZuneUIXTools/Modules/Inspectors/EnumerableEditorViewModel.cs b/ZuneUIXTools/Modules/Inspectors/EnumerableEditorViewModel.cs new file mode 100644 index 0000000..0937061 --- /dev/null +++ b/ZuneUIXTools/Modules/Inspectors/EnumerableEditorViewModel.cs @@ -0,0 +1,34 @@ +using Gemini.Modules.Inspector; +using Gemini.Modules.Inspector.Inspectors; +using Gemini.Modules.Inspector.ViewModels; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace ZuneUIXTools.Modules.Inspectors; + +public class EnumerableEditorViewModel : EditorBase, ILabelledInspector +{ + public EnumerableEditorViewModel() : this(null) { } + + public EnumerableEditorViewModel(Func builder) + { + Builder = builder ?? DefaultBuilder; + } + + public Func Builder { get; } + + public override bool IsReadOnly => Value is IList collection && collection.IsReadOnly; + + public IEnumerable Inspectables => Value + .Cast() + .Select(inst => new InspectorViewModel() { SelectedObject = Builder(inst) }); + + private static InspectableObject DefaultBuilder(object instance) + { + return new InspectableObjectBuilder() + .WithObjectProperties(instance, _ => true) + .ToInspectableObject(); + } +} diff --git a/ZuneUIXTools/Modules/Inspectors/EnumerablePropertyEditorBuilder.cs b/ZuneUIXTools/Modules/Inspectors/EnumerablePropertyEditorBuilder.cs new file mode 100644 index 0000000..f730b88 --- /dev/null +++ b/ZuneUIXTools/Modules/Inspectors/EnumerablePropertyEditorBuilder.cs @@ -0,0 +1,12 @@ +using System.Collections; +using System.ComponentModel; + +namespace ZuneUIXTools.Modules.Inspectors; + +public class EnumerablePropertyEditorBuilder : InheritablePropertyEditorBuilder +{ + public override bool IsApplicable(PropertyDescriptor propertyDescriptor) + { + return base.IsApplicable(propertyDescriptor) && propertyDescriptor.PropertyType != typeof(string); + } +} diff --git a/ZuneUIXTools/Modules/Inspectors/InheritablePropertyEditorBuilder.cs b/ZuneUIXTools/Modules/Inspectors/InheritablePropertyEditorBuilder.cs new file mode 100644 index 0000000..6e09421 --- /dev/null +++ b/ZuneUIXTools/Modules/Inspectors/InheritablePropertyEditorBuilder.cs @@ -0,0 +1,19 @@ +using Gemini.Modules.Inspector.Conventions; +using Gemini.Modules.Inspector.Inspectors; +using System.ComponentModel; + +namespace ZuneUIXTools.Modules.Inspectors; + +public class InheritablePropertyEditorBuilder : PropertyEditorBuilder + where TEditor : IEditor, new() +{ + public override bool IsApplicable(PropertyDescriptor propertyDescriptor) + { + return propertyDescriptor.PropertyType.IsAssignableTo(typeof(T)); + } + + public override IEditor BuildEditor(PropertyDescriptor propertyDescriptor) + { + return new TEditor(); + } +} diff --git a/ZuneUIXTools/Modules/UIXCompiled/UIBDisassemblyView.xaml.cs b/ZuneUIXTools/Modules/UIXCompiled/UIBDisassemblyView.xaml.cs index 1355126..21f4d68 100644 --- a/ZuneUIXTools/Modules/UIXCompiled/UIBDisassemblyView.xaml.cs +++ b/ZuneUIXTools/Modules/UIXCompiled/UIBDisassemblyView.xaml.cs @@ -1,17 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; +using Microsoft.Iris.Debug.Data; using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; namespace ZuneUIXTools.Modules.UIXCompiled { @@ -32,7 +20,7 @@ namespace ZuneUIXTools.Modules.UIXCompiled if (e.AddedItems.Count <= 0) return; - ViewModel.SetInspector(e.AddedItems[0]); + ViewModel.SetInspector(e.AddedItems[0] as InterpreterEntry); } } } diff --git a/ZuneUIXTools/Modules/UIXCompiled/UIBDisassemblyViewModel.cs b/ZuneUIXTools/Modules/UIXCompiled/UIBDisassemblyViewModel.cs index 11395b7..ca3bb86 100644 --- a/ZuneUIXTools/Modules/UIXCompiled/UIBDisassemblyViewModel.cs +++ b/ZuneUIXTools/Modules/UIXCompiled/UIBDisassemblyViewModel.cs @@ -2,13 +2,22 @@ using Gemini.Framework; using Gemini.Framework.Services; using Gemini.Modules.Inspector; +using Gemini.Modules.Inspector.Conventions; +using Gemini.Modules.Inspector.Inspectors; using Microsoft.Iris.Debug.Data; using System; +using System.Collections; +using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.ComponentModel.Composition; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; using System.Windows.Threading; using WpfHexaEditor.Core.MethodExtention; +using ZuneUIXTools.Converters; +using ZuneUIXTools.Modules.Inspectors; using ZuneUIXTools.Modules.UIX; namespace ZuneUIXTools.Modules.UIXCompiled; @@ -48,15 +57,58 @@ public class UIBDisassemblyViewModel : Document _view = (UIBDisassemblyView)view; } - public void SetInspector(object objToInspect) + public void SetInspector(InterpreterEntry entry) { + var props = (from PropertyDescriptor x in TypeDescriptor.GetProperties(entry) where x.IsBrowsable select x).ToList(); + + DefaultPropertyInspectors.InspectorBuilders.Add(new EnumerablePropertyEditorBuilder()); + var inspector = IoC.Get(); inspector.SelectedObject = new InspectableObjectBuilder() - .WithObjectProperties(objToInspect, _ => true) + .WithObjectProperties(entry, obj => !(obj.Name == nameof(entry.Parameters) || obj.Name == nameof(entry.ReturnValues))) + .WithCollapsibleGroup("Parameters", + b => b.WithEditor(entry, e => e.Parameters, new EnumerableEditorViewModel(InterpreterObjectBuilder))) + .WithCollapsibleGroup("Return values", + b => b.WithEditor(entry, e => e.ReturnValues, new EnumerableEditorViewModel(InterpreterObjectBuilder))) .ToInspectableObject(); - // TODO: Create IEditor for collections - _shell.ShowTool(inspector); } + + private static InspectableObject InterpreterObjectBuilder(object obj) + { + if (obj is not InterpreterObject instance) + throw new ArgumentException(null, nameof(obj)); + + bool filter(PropertyDescriptor prop) + { + if (prop.Name == nameof(instance.TableIndex) && instance.TableIndex == -1) + return false; + else if (prop.Name == nameof(instance.Value)) + return false; + + return prop.GetValue(instance) != null; + } + + InspectableObjectBuilder builder = new InspectableObjectBuilder() + .WithObjectProperties(instance, filter); + + var valueProperty = TypeDescriptor.CreateProperty(typeof(InterpreterObject), "Value", instance.Value?.GetType()); + IEditor editor = DefaultPropertyInspectors.CreateEditor(valueProperty); + if (editor is null) + { + builder = builder.WithCollapsibleGroup(nameof(instance.Value), b => + b.WithObjectProperties(instance.Value, _ => true)); + } + else + { + var converterProp = editor.GetType().GetProperty("Converter"); + converterProp?.SetValue(editor, new CastValueConverter()); + + editor.BoundPropertyDescriptor = new BoundPropertyDescriptor(instance, valueProperty); + builder = builder.WithEditor(instance, i => i.Value, editor); + } + + return builder.ToInspectableObject(); + } }