using System.Collections.Generic; using Pf2eViewer.EntityTreeViewer; namespace Pf2eViewer.EntityTreeViewer; public sealed partial class EntityTreeViewerControl : UserControl public partial class EntityTreeViewerControl : UserControl { private int _itemHeight = 20; private EntityView? _entityView; private int _depthSize = 20; public int ItemHeight { get => _itemHeight; set { _itemHeight = value; UpdateView(); } } public EntityView? EntityView { get => _entityView; set { _entityView = value; UpdateData(); } } public int DepthSize { get => _depthSize; set { _depthSize = value; UpdateView(); } } public int NameWidth { get; private set; } = 200; private readonly List _rows = []; private List _viewerRows = []; public EntityTreeViewerControl() { InitializeComponent(); DoubleBuffered = true; ContentPanel.AutoScroll = false; ContentPanel.HorizontalScroll.Maximum = 0; ContentPanel.HorizontalScroll.Visible = false; ContentPanel.AutoScroll = true; } public void UpdateData() { ContentPanel.Controls.Clear(); if (EntityView?.Entity is null) { return; } _rows.Clear(); StructureBuilder builder = new(); _rows.Add(builder.Create("Entity", EntityView.Entity)); if (EntityView.SubEntity is not null) { string typeName = EntityView.SubEntity.GetType().Name; _rows.Add(builder.Create(typeName, EntityView.SubEntity)); } UpdateRows(); UpdateView(); } public void UpdateRows() { _viewerRows = _rows.SelectMany(r => r.GetTextRows(this)).ToList(); ContentPanel.Controls.Clear(); ContentPanel.Controls.AddRange(_viewerRows.ToArray()); ContentPanel.Controls.AddRange(ViewerRows.ToArray()); UpdateView(); } public void UpdateView() { foreach (EntityTreeViewerRow row in _viewerRows) { row.Visible = row.Item.Visible; } List rows = _viewerRows.Where(r => r.Item.Visible).ToList(); int maxNameWidth = -1; int viewRow = 0; foreach (EntityTreeViewerRow row in rows) { row.ViewIndex = viewRow++; int nameWidth = row.NameWidth + row.Item.Depth * DepthSize; maxNameWidth = Math.Max(maxNameWidth, nameWidth); } NameWidth = maxNameWidth; BuildLadder(rows); foreach (EntityTreeViewerRow row in rows) { row.Refresh(); } } private void BuildLadder(List rows) List lastLadder = []; ContentPanel.VerticalScroll.Visible = true; for (int i = rows.Count - 1; i >= 0; i--) { EntityTreeViewerRow row = rows[i]; List ladder; if (row.Depth == 0) { ladder = []; } else if (row.Depth < lastLadder.Count) { ladder = [ .. lastLadder[..(row.Depth - 1)], lastLadder[row.Depth - 1] == LadderType.Empty ? LadderType.Last : LadderType.Through, ]; } else if (row.Depth == lastLadder.Count) { ladder = lastLadder; } else { ladder = [ .. lastLadder, .. Enumerable.Repeat(LadderType.Empty, row.Depth - lastLadder.Count - 1), LadderType.Last, ]; } row.Ladder = ladder; lastLadder = ladder .Select(l => (l == LadderType.Last) ? LadderType.Through : l) .ToList(); } } // Events private void ContentPanel_Resize(object sender, EventArgs e) { UpdateView(); } }