Improve inspector compatibility with InterpreterEntry and InterpreterObject

This commit is contained in:
Yoshi Askharoun
2023-05-29 17:05:46 -05:00
parent 6f838ce763
commit cc03eace5e
8 changed files with 191 additions and 18 deletions
@@ -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;
}
}
@@ -0,0 +1,22 @@
<UserControl x:Class="ZuneUIXTools.Modules.Inspectors.EnumerableEditorView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ZuneUIXTools.Modules.Inspectors"
xmlns:inspector="clr-namespace:Gemini.Modules.Inspector;assembly=Gemini.Modules.Inspector"
xmlns:inspectorViews="clr-namespace:Gemini.Modules.Inspector.Views;assembly=Gemini.Modules.Inspector"
xmlns:inspectorViewModels="clr-namespace:Gemini.Modules.Inspector.ViewModels;assembly=Gemini.Modules.Inspector"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance local:EnumerableEditorViewModel}">
<ItemsControl ItemsSource="{Binding Inspectables}" IsTabStop="False">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="inspectorViewModels:InspectorViewModel">
<inspectorViews:InspectorView DataContext="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</UserControl>
@@ -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
{
/// <summary>
/// Interaction logic for EnumerableEditorView.xaml
/// </summary>
public partial class EnumerableEditorView : UserControl
{
public EnumerableEditorView()
{
InitializeComponent();
}
}
}
@@ -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<IEnumerable>, ILabelledInspector
{
public EnumerableEditorViewModel() : this(null) { }
public EnumerableEditorViewModel(Func<object, IInspectableObject> builder)
{
Builder = builder ?? DefaultBuilder;
}
public Func<object, IInspectableObject> Builder { get; }
public override bool IsReadOnly => Value is IList collection && collection.IsReadOnly;
public IEnumerable<InspectorViewModel> Inspectables => Value
.Cast<object>()
.Select(inst => new InspectorViewModel() { SelectedObject = Builder(inst) });
private static InspectableObject DefaultBuilder(object instance)
{
return new InspectableObjectBuilder()
.WithObjectProperties(instance, _ => true)
.ToInspectableObject();
}
}
@@ -0,0 +1,12 @@
using System.Collections;
using System.ComponentModel;
namespace ZuneUIXTools.Modules.Inspectors;
public class EnumerablePropertyEditorBuilder : InheritablePropertyEditorBuilder<IEnumerable, EnumerableEditorViewModel>
{
public override bool IsApplicable(PropertyDescriptor propertyDescriptor)
{
return base.IsApplicable(propertyDescriptor) && propertyDescriptor.PropertyType != typeof(string);
}
}
@@ -0,0 +1,19 @@
using Gemini.Modules.Inspector.Conventions;
using Gemini.Modules.Inspector.Inspectors;
using System.ComponentModel;
namespace ZuneUIXTools.Modules.Inspectors;
public class InheritablePropertyEditorBuilder<T, TEditor> : 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();
}
}
@@ -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);
}
}
}
@@ -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<IInspectorTool>();
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();
}
}