using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Reflection; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Windows.Forms.VisualStyles; using Microsoft.EntityFrameworkCore.Metadata.Internal; namespace Pf2eViewer; public partial class EntityTreeViewerControl : UserControl { private int _itemHeight = 20; private EntityView? _entityView = null; public int ItemHeight { get => _itemHeight; set { _itemHeight = value; UpdateView(); } } public EntityView? EntityView { get => _entityView; set { _entityView = value; UpdateView(); } } public EntityTreeViewerControl() { InitializeComponent(); } public void UpdateView() { ContentPanel.Controls.Clear(); if (EntityView?.Entity is null) { return; } Rows.Clear(); Rows.Add(new HeaderRow("Entity")); Rows.Add(new ObjectComplex(null, EntityView.Entity)); Rows.Add(new HeaderRow(EntityView.SubEntity?.GetType().ToString() ?? "SubEntity")); Rows.Add(new ObjectComplex(null, EntityView.SubEntity)); List displayRows = Rows.SelectMany(r => r.GetTextRows()).ToList(); for (int i = 0; i < displayRows.Count; i++) { DisplayRow dr = displayRows[i]; TextBox tb = new() { Top = i * ItemHeight, Left = 0, Width = ContentPanel.Width, Height = ItemHeight, Font = Font, Text = string.Join( "", [new(' ', dr.Depth * 2), dr.Name, dr.Value != "" ? " : " : "", dr.Value] ), Margin = new(0), }; ContentPanel.Controls.Add(tb); } } private Panel GetObjectPanel(object obj) { Panel result = new(); Type type = obj.GetType(); PropertyInfo[] properties = type.GetProperties(); /* FieldInfo[] fields = type.GetFields( BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public ); */ for (int i = 0; i < properties.Length; i++) { PropertyInfo property = properties[i]; TextBox tb = new() { Top = i * ItemHeight, Left = 0, Width = ContentPanel.Width, Height = ItemHeight, Font = Font, Text = property.Name, Margin = new(0), }; result.Controls.Add(tb); } result.Width = ContentPanel.Width; result.Height = properties.Length * ItemHeight * 2; return result; } private List Rows = []; private class DisplayRow { public string Name = ""; public string Value = ""; public int Depth = 0; } private abstract class Row { public abstract ICollection GetTextRows(); public int Depth = 0; } private class HeaderRow(string name) : Row { public readonly string Name = name; public override ICollection GetTextRows() { return [new() { Name = Name, Depth = Depth }]; } } private abstract class ObjectField(PropertyInfo property, object? parent) : Row { public readonly PropertyInfo? Property = property; public readonly string Name = property.Name; public readonly Type Type = property.PropertyType; public abstract int Rows { get; } public static ObjectField Resolve(PropertyInfo property, object? parent) { return property.PropertyType.IsPrimitive ? new ObjectPrimitive(property, parent) : new ObjectComplex(property, parent); } } private class ObjectPrimitive : ObjectField { public readonly object? Value; public override int Rows => 1; public ObjectPrimitive(PropertyInfo? property, object? parent) : base(property, parent) { Value = Property.GetValue(parent, null); } public override ICollection GetTextRows() { return [ new() { Name = Name, Value = Value?.ToString() ?? "null", Depth = Depth, }, ]; } } private class ObjectComplex : ObjectField { public readonly List Fields; public bool Collapsed = false; public override int Rows => 1 + Fields.Select(f => f.Rows).Sum(); public ObjectComplex(PropertyInfo? property, object? parent) : base(property, parent) { PropertyInfo[] properties = Type.GetProperties(); object? value = Property?.GetValue(parent, null) ?? parent; Fields = properties.Select(f => Resolve(f, value)).ToList(); } public override ICollection GetTextRows() { List rows = [new() { Name = Name, Depth = Depth }]; if (!Collapsed) { rows.AddRange(Fields.SelectMany(f => f.GetTextRows()).ToList()); } return rows; } } }