namespace Pf2eViewer.EntityTreeViewer; public sealed partial class EntityTreeViewerControl : UserControl { private int _itemHeight = 20; private EntityView? _entityView = null; 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 DarkModeCS? DarkMode; public EntityTreeViewerControl() { InitializeComponent(); DoubleBuffered = true; ContentPanel.AutoScroll = false; ContentPanel.VerticalScroll.Enabled = true; ContentPanel.VerticalScroll.Visible = true; ContentPanel.MouseWheel += ContentPanel_MouseWheel; } private int _visibleRows; public int ScrollPosition { get => ContentPanel.VerticalScroll.Value / ItemHeight; set { VScrollProperties scrollBar = ContentPanel.VerticalScroll; int oldValue = scrollBar.Value / ItemHeight; int visibleItems = scrollBar.LargeChange / ItemHeight; int scrollValue = Math.Min(Math.Max(value, 0), _visibleRows - visibleItems); if (oldValue != scrollValue) { ContentPanel.VerticalScroll.Value = scrollValue * ItemHeight; UpdateScroll(); } } } 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()); 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.GetNameWidth() + row.Item.Depth * DepthSize; maxNameWidth = Math.Max(maxNameWidth, nameWidth); } NameWidth = maxNameWidth; foreach (EntityTreeViewerRow row in rows) { row.Refresh(); } UpdateScroll(); } public void UpdateScroll() { List rows = _viewerRows.Where(r => r.Item.Visible).ToList(); _visibleRows = rows.Count; ContentPanel.VerticalScroll.Enabled = true; ContentPanel.VerticalScroll.Visible = true; ContentPanel.VerticalScroll.SmallChange = ItemHeight; ContentPanel.VerticalScroll.LargeChange = ContentPanel.Height; ContentPanel.VerticalScroll.Minimum = 0; ContentPanel.VerticalScroll.Maximum = _visibleRows * ItemHeight; // ContentPanel.VerticalScroll.Value = VerticalScrollBar.Value * ItemHeight; /* ContentPanel.Top = -VerticalScrollBar.Value * ItemHeight; ContentPanel.Invalidate(); */ } // Events private void VerticalScrollBar_Scroll(object sender, ScrollEventArgs e) { UpdateScroll(); } private void ContentPanel_MouseWheel(object? sender, MouseEventArgs e) { Focus(); // ScrollPosition -= e.Delta / 120; } private void ContentPanel_Resize(object sender, EventArgs e) { UpdateView(); } }