diff --git a/Pf2eDataScrapper.sln.DotSettings b/Pf2eDataScrapper.sln.DotSettings
new file mode 100644
index 0000000..06f6382
--- /dev/null
+++ b/Pf2eDataScrapper.sln.DotSettings
@@ -0,0 +1,49 @@
+
+ True
+ DO_NOT_SHOW
+ DO_NOT_SHOW
+ DO_NOT_SHOW
+ DO_NOT_SHOW
+ DO_NOT_SHOW
+ DO_NOT_SHOW
+ DO_NOT_SHOW
+ DO_NOT_SHOW
+ DO_NOT_SHOW
+ TargetTyped
+ True
+ False
+ False
+ 137
+ True
+ E:\proj\pf2e\Pf2eDataScrapper\Pf2eDataScrapper.sln.DotSettings
+
+ True
+ 1
+ False
+ 12
+ dotCover_2025.1
+ ReSharper_2025.1
+ ReSharperAI_2025.1
+ 05/05/2025 08:54:55
+ 05/02/2025 05:43:20
+ 04/26/2025 06:45:16
+ 05/05/2025 08:58:37
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ [-407,3](1107,1026)
+ 0,-126
+ 422
+ 268.5
+ 211
+ 89.5
+ True
+ CodeInspectionSettings
+ True
+ True
+ 2025.1.0.0
+ 2025.1.0.0
\ No newline at end of file
diff --git a/Pf2eViewer/EntityTreeViewer/EntityTreeViewerControl.Designer.cs b/Pf2eViewer/EntityTreeViewer/EntityTreeViewerControl.Designer.cs
index d27033b..a0d535f 100644
--- a/Pf2eViewer/EntityTreeViewer/EntityTreeViewerControl.Designer.cs
+++ b/Pf2eViewer/EntityTreeViewer/EntityTreeViewerControl.Designer.cs
@@ -28,28 +28,33 @@ sealed partial class EntityTreeViewerControl
///
private void InitializeComponent()
{
- ContentPanel = new Panel();
+ ContentPanel = new PictureBox();
+ ((System.ComponentModel.ISupportInitialize)ContentPanel).BeginInit();
SuspendLayout();
//
// ContentPanel
//
- ContentPanel.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
ContentPanel.Location = new Point(0, 0);
ContentPanel.Name = "ContentPanel";
ContentPanel.Size = new Size(400, 500);
- ContentPanel.TabIndex = 2;
- ContentPanel.Resize += ContentPanel_Resize;
+ ContentPanel.TabIndex = 0;
+ ContentPanel.TabStop = false;
+ ContentPanel.MouseMove += ContentPanel_MouseMove;
//
// EntityTreeViewerControl
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
+ AutoScroll = true;
Controls.Add(ContentPanel);
Name = "EntityTreeViewerControl";
Size = new Size(400, 500);
+ Resize += EntityTreeViewerControl_Resize;
+ ((System.ComponentModel.ISupportInitialize)ContentPanel).EndInit();
ResumeLayout(false);
}
#endregion
- public Panel ContentPanel;
+
+ public PictureBox ContentPanel;
}
diff --git a/Pf2eViewer/EntityTreeViewer/EntityTreeViewerControl.cs b/Pf2eViewer/EntityTreeViewer/EntityTreeViewerControl.cs
index b3823d0..07793ce 100644
--- a/Pf2eViewer/EntityTreeViewer/EntityTreeViewerControl.cs
+++ b/Pf2eViewer/EntityTreeViewer/EntityTreeViewerControl.cs
@@ -1,18 +1,13 @@
-using System.Collections.Generic;
-using System.ComponentModel;
-using Pf2eViewer.EntityTreeViewer;
+using System.ComponentModel;
+using System.Diagnostics;
namespace Pf2eViewer.EntityTreeViewer;
public sealed partial class EntityTreeViewerControl : UserControl
{
- private int _itemHeight = 20;
-
- private EntityView? _entityView;
-
- private int _depthSize = 20;
-
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
+ [Category("Entity Render")]
+ [Description("The height of each item in the tree view.")]
public int ItemHeight
{
get => _itemHeight;
@@ -22,8 +17,11 @@ public sealed partial class EntityTreeViewerControl : UserControl
UpdateView();
}
}
+ private int _itemHeight = 20;
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ [Browsable(false)]
+ [EditorBrowsable(EditorBrowsableState.Never)]
public EntityView? EntityView
{
get => _entityView;
@@ -33,8 +31,11 @@ public sealed partial class EntityTreeViewerControl : UserControl
UpdateData();
}
}
+ private EntityView? _entityView;
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
+ [Category("Entity Render")]
+ [Description("The size of tab.")]
public int DepthSize
{
get => _depthSize;
@@ -44,35 +45,76 @@ public sealed partial class EntityTreeViewerControl : UserControl
UpdateView();
}
}
+ private int _depthSize = 20;
+
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
+ [Category("Entity Render")]
+ [Description("The size of plus/minus button.")]
+ public int ButtonSize
+ {
+ get => _buttonSize;
+ set
+ {
+ _buttonSize = value;
+ UpdateView();
+ }
+ }
+ private int _buttonSize = 20;
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ [Browsable(false)]
+ [EditorBrowsable(EditorBrowsableState.Never)]
public int NameWidth { get; private set; } = 200;
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
+ [Category("Entity Render")]
+ [Description("Color on item hover.")]
+ public Color HoverColor
+ {
+ get => _hoverColor;
+ set
+ {
+ _hoverColor = value;
+ UpdateView();
+ }
+ }
+ private Color _hoverColor = SystemColors.ControlDark;
+
+ [Browsable(false)]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public int ContentWidth => Width - SystemInformation.VerticalScrollBarWidth - 2;
+
private readonly List _rows = [];
- private List _viewerRows = [];
+ private List _viewerRows = [];
+
+ private bool _rendering;
+
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ [Browsable(false)]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public Bitmap ContentImage { get; set; }
public EntityTreeViewerControl()
{
InitializeComponent();
+ ContentImage = new(ContentWidth, Height);
DoubleBuffered = true;
+ VerticalScroll.Visible = true;
+ HorizontalScroll.Visible = false;
- ContentPanel.AutoScroll = false;
- ContentPanel.HorizontalScroll.Maximum = 0;
- ContentPanel.HorizontalScroll.Visible = false;
- ContentPanel.AutoScroll = true;
+ ContentPanel.MouseWheel += ContentPanel_MouseWheel;
}
public void UpdateData()
{
- ContentPanel.Controls.Clear();
-
if (EntityView?.Entity is null)
{
return;
}
_rows.Clear();
+ ContentPanel.Controls.Clear();
StructureBuilder builder = new();
@@ -85,57 +127,75 @@ public sealed partial class EntityTreeViewerControl : UserControl
_rows.Add(builder.Create(typeName, EntityView.SubEntity));
}
- UpdateRows();
- UpdateView();
+ _viewerRows = _rows
+ .SelectMany(r => r.GetRows(row => new EntityTreeViewerControlRow(this, row)))
+ .ToList();
+
+ UpdateRenders();
}
- public void UpdateRows()
+ public void UpdateRenders()
{
- _viewerRows = _rows.SelectMany(r => r.GetTextRows(this)).ToList();
+ int maxNameWidth = -1;
- ContentPanel.Controls.Clear();
- ContentPanel.Controls.AddRange(_viewerRows.ToArray());
+ foreach (EntityTreeViewerControlRow row in _viewerRows)
+ {
+ int nameWidth = row.NameWidth + row.Item.Depth * DepthSize;
+ maxNameWidth = Math.Max(maxNameWidth, nameWidth);
+ }
+
+ NameWidth = maxNameWidth + 3;
+
+ Debug.WriteLine($@"Height Inner {ContentWidth} / Outer {Width}");
+ Debug.WriteLine($@"Name {NameWidth} / Full {ContentWidth}");
+
+ foreach (EntityTreeViewerControlRow row in _viewerRows)
+ {
+ row.UpdateCache();
+ }
UpdateView();
}
public void UpdateView()
{
- foreach (EntityTreeViewerRow row in _viewerRows)
+ _viewerRows.ForEach(row => row.UpdateButton());
+
+ List rows = _viewerRows.Where(r => r.Item.Visible).ToList();
+ if (rows.Count == 0)
{
- row.Visible = row.Item.Visible;
+ return;
}
- 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)
+ _rendering = true;
+ ContentImage = new(ContentWidth, rows.Count * ItemHeight);
+ Graphics g = Graphics.FromImage(ContentImage);
+
+ int viewRow = 0;
+ foreach (EntityTreeViewerControlRow row in rows)
{
- row.Refresh();
+ row.ViewIndex = viewRow++;
+ row.Invalidate(g);
}
+
+ g.Save();
+
+ ContentPanel.Image = ContentImage;
+ ContentPanel.Width = ContentImage.Width;
+ ContentPanel.Height = ContentImage.Height;
+
+ _rendering = false;
}
- private void BuildLadder(List rows)
+ private void BuildLadder(List rows)
{
List lastLadder = [];
- ContentPanel.VerticalScroll.Visible = true;
for (int i = rows.Count - 1; i >= 0; i--)
{
- EntityTreeViewerRow row = rows[i];
+ EntityTreeViewerControlRow row = rows[i];
List ladder;
if (row.Depth == 0)
@@ -176,8 +236,53 @@ public sealed partial class EntityTreeViewerControl : UserControl
// Events
- private void ContentPanel_Resize(object sender, EventArgs e)
+ private void EntityTreeViewerControl_Resize(object sender, EventArgs e)
{
- UpdateView();
+ if (_rendering)
+ {
+ return;
+ }
+
+ ContentPanel.Width = Width;
+
+ UpdateRenders();
+ }
+
+ private void ContentPanel_MouseWheel(object? sender, MouseEventArgs e)
+ {
+ /*
+ int initValue = VerticalScroll.Value;
+ int delta = -e.Delta / 120;
+
+ VerticalScroll.Value = Math.Clamp(
+ initValue + delta,
+ VerticalScrollBar.Minimum,
+ VerticalScrollBar.Maximum - VerticalScrollBar.LargeChange + 1
+ );
+
+ if (VerticalScrollBar.Value != initValue)
+ {
+ ContentPanel.Invalidate();
+ }
+ */
+ }
+
+ private void ContentPanel_MouseMove(object sender, MouseEventArgs e)
+ {
+ PointF p = new(e.X, e.Y);
+
+ foreach (EntityTreeViewerControlRow row in _viewerRows)
+ {
+ bool contained = row.Target.Contains(p);
+
+ if (contained != row.Hovered)
+ {
+ Rectangle r = new();
+ row.RealTarget.Intersect(r);
+ ContentPanel.Invalidate(r);
+ }
+
+ row.Hovered = contained;
+ }
}
}
diff --git a/Pf2eViewer/EntityTreeViewer/EntityTreeViewerControlRow.cs b/Pf2eViewer/EntityTreeViewer/EntityTreeViewerControlRow.cs
new file mode 100644
index 0000000..031a00e
--- /dev/null
+++ b/Pf2eViewer/EntityTreeViewer/EntityTreeViewerControlRow.cs
@@ -0,0 +1,385 @@
+using FontAwesome.Sharp;
+using Font = System.Drawing.Font;
+using FontStyle = System.Drawing.FontStyle;
+using Image = System.Drawing.Image;
+
+namespace Pf2eViewer.EntityTreeViewer;
+
+internal class EntityTreeViewerControlRow
+{
+ public readonly EntityTreeViewerControl ParentControl;
+
+ public readonly StructureField Item;
+
+ // Local fields
+ public Image Cache
+ {
+ get
+ {
+ if (_cache == null)
+ {
+ UpdateCache();
+ }
+ return _cache!;
+ }
+ set => _cache = value;
+ }
+ private Image? _cache;
+
+ public List Ladder
+ {
+ get => _ladder;
+ set
+ {
+ _ladder = value;
+ _cache = null;
+ }
+ }
+ private List _ladder = [];
+
+ public bool Hovered
+ {
+ get => _hovered;
+ set
+ {
+ if (value != _hovered)
+ {
+ _hovered = value;
+ Invalidate();
+ }
+ }
+ }
+ private bool _hovered = false;
+
+ public int ViewIndex { get; set; } // = -1;
+
+ public IconButton? Button { get; set; } = null;
+
+ // Inherited fields
+
+ public Font Font
+ {
+ get => ParentControl.Font;
+ set => ParentControl.Font = value;
+ }
+ public Color ForeColor
+ {
+ get => ParentControl.ForeColor;
+ set => ParentControl.ForeColor = value;
+ }
+ public Color BackColor
+ {
+ get => ParentControl.BackColor;
+ set => ParentControl.BackColor = value;
+ }
+ public Color HoverColor
+ {
+ get => ParentControl.HoverColor;
+ set => ParentControl.HoverColor = value;
+ }
+ public int ItemHeight
+ {
+ get => ParentControl.ItemHeight;
+ set => ParentControl.ItemHeight = value;
+ }
+ public int DepthSize
+ {
+ get => ParentControl.DepthSize;
+ set => ParentControl.DepthSize = value;
+ }
+ public int ButtonSize
+ {
+ get => ParentControl.ButtonSize;
+ set => ParentControl.ButtonSize = value;
+ }
+
+ // ValueText functions
+
+ public int Width => ParentControl.ContentWidth;
+ public int Height => ItemHeight;
+ public bool HasButton => Item.FieldType == StructureFieldType.Complex;
+ public int Depth => Item.Depth;
+ public int NameWidth
+ {
+ get
+ {
+ Graphics g = Graphics.FromImage(Cache);
+ return Convert.ToInt32(g.MeasureString(Item.Name, Font).Width + DepthSize);
+ }
+ }
+
+ public string TypeText
+ {
+ get
+ {
+ string result = Item.GetTypeString();
+ if (result != "")
+ {
+ result = $@"({result})";
+ }
+ return result;
+ }
+ }
+ public Font TypeFont => new(Font.FontFamily, Font.Size * 0.6f, FontStyle.Italic);
+
+ public string ValueText => Item.GetValueString();
+ public Font ValueFont =>
+ new(
+ Font.FontFamily,
+ Font.Size,
+ Item.FieldType == StructureFieldType.Complex ? FontStyle.Italic : FontStyle.Regular
+ );
+
+ public RectangleF Target => new(0, ViewIndex * Height, Width, Height);
+ public RectangleF RealTarget =>
+ new(0, ViewIndex * Height - ParentControl.VerticalScroll.Value, Width, Height);
+
+ // Simple fields
+
+ private readonly List _renderData = [];
+
+ // Main methods
+
+ public EntityTreeViewerControlRow(EntityTreeViewerControl parent, StructureField item)
+ {
+ ParentControl = parent;
+ Item = item;
+ ApplyItem();
+ UpdateCache();
+
+ UpdateButton();
+ }
+
+ private void ApplyItem()
+ {
+ _renderData.Clear();
+
+ _renderData.Add(new(Item.Name, Font, ForeColor));
+ _renderData.Add(new(TypeText, TypeFont, GetValueColor()));
+ _renderData.Add(
+ new(ValueText.Replace("\r", "").Replace('\n', ' '), ValueFont, GetValueColor())
+ );
+
+ if (HasButton)
+ {
+ Button = new()
+ {
+ Width = ButtonSize,
+ Height = ButtonSize,
+ IconSize = ButtonSize,
+ IconChar = IconChar.MinusSquare,
+ ImageAlign = ContentAlignment.MiddleCenter,
+ TextAlign = ContentAlignment.MiddleCenter,
+ Visible = false,
+ };
+
+ Button.Click += Button_Click;
+
+ ParentControl.ContentPanel.Controls.Add(Button);
+ }
+ }
+
+ public void UpdateCache()
+ {
+ Cache = new Bitmap(Width, Height);
+ Graphics g = Graphics.FromImage(Cache);
+
+ RenderLadder(g);
+ RenderContent(g);
+
+ g.Save();
+ }
+
+ public void Invalidate(Graphics? g = null)
+ {
+ g ??= Graphics.FromImage(ParentControl.ContentImage);
+
+ g.FillRectangle(new SolidBrush(Hovered ? HoverColor : BackColor), Target);
+ g.DrawImage(Cache, Target);
+
+ UpdateButton();
+ }
+
+ // Button
+
+ public void UpdateButton()
+ {
+ if (Button is null)
+ {
+ return;
+ }
+
+ int cx = Convert.ToInt32((0.5 + Depth) * DepthSize - 0.5 * ButtonSize);
+ int cy = Convert.ToInt32((0.5 + ViewIndex) * ItemHeight - 0.5 * ButtonSize);
+
+ Button.Left = cx;
+ Button.Top = cy;
+
+ Button!.IconChar = ((StructureFieldComplex)Item).Collapsed
+ ? IconChar.PlusSquare
+ : IconChar.MinusSquare;
+ Button.Visible = Item.Visible;
+ }
+
+ private void Button_Click(object? sender, EventArgs e)
+ {
+ if (Item is StructureFieldComplex complex)
+ {
+ complex.Collapsed = !complex.Collapsed;
+ ParentControl.UpdateView();
+ }
+ }
+
+ // Render
+
+ private void RenderLadder(Graphics g)
+ {
+ int n = Depth;
+ int h = ItemHeight;
+ int w = DepthSize;
+
+ if (_ladder.Count < Depth)
+ {
+ return;
+ }
+
+ Pen pen = new(Color.FromArgb(127, ForeColor.R, ForeColor.G, ForeColor.B), 1);
+ pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
+
+ float cy = 0.5f * h;
+
+ for (int i = 0; i < n; i++)
+ {
+ float cx = (i + 1.5f) * w;
+
+ switch (_ladder[i])
+ {
+ case LadderType.Last:
+ g.DrawLine(pen, cx, 0, cx, cy);
+ break;
+ case LadderType.Through:
+ g.DrawLine(pen, cx, 0, cx, h);
+ break;
+ case LadderType.Empty:
+ default:
+ break;
+ }
+
+ if (i == n - 1)
+ {
+ g.DrawLine(pen, cx, cy, (i + 2) * w, cy);
+ }
+ }
+ }
+
+ private void RenderContent(Graphics g)
+ {
+ float[] xs =
+ [
+ DepthSize * (Item.Depth + 1),
+ ParentControl.NameWidth,
+ ParentControl.NameWidth + g.MeasureString(TypeText, TypeFont).Width + 3,
+ Width,
+ ];
+
+ Pen p = new(Color.Aqua, 1);
+
+ for (int i = 0; i < 3; i++)
+ {
+ StringRenderData item = _renderData[i];
+
+ item.Left = xs[i];
+ item.Width = xs[i + 1] - xs[i];
+ item.Height = ItemHeight;
+
+ // g.DrawRectangle(p, item.Rect);
+ item.Draw(g);
+ }
+ }
+
+ // Helper functions
+
+ private Color BlendColor(Color color, double rate = 0.5)
+ {
+ return BlendColor(ForeColor, color, rate);
+ }
+
+ private Color BlendColor(Color color1, Color color2, double rate)
+ {
+ return Color.FromArgb(
+ Mix(color1.A, color2.A),
+ Mix(color1.R, color2.R),
+ Mix(color1.G, color2.G),
+ Mix(color1.B, color2.B)
+ );
+
+ int Mix(int a, int b) => Convert.ToInt32(Math.Round(a * rate + b * (1 - rate)));
+ }
+
+ public Color GetValueColor()
+ {
+ return Item switch
+ {
+ StructureFieldPrimitive primitive => Type.GetTypeCode(primitive.Type) switch
+ {
+ TypeCode.Boolean => BlendColor(Color.DarkGoldenrod),
+ TypeCode.Int32 => BlendColor(Color.Blue),
+ TypeCode.Double => BlendColor(Color.Aqua),
+ TypeCode.String => BlendColor(Color.Green),
+ _ => ForeColor,
+ },
+ StructureFieldEnum => BlendColor(Color.Red),
+ _ => ForeColor,
+ };
+ }
+
+ private class StringRenderData(string text, Font font, Color color)
+ {
+ public string Text { get; } = text;
+ public Font Font { get; } = font;
+ public Color Color { get; } = color;
+
+ public float Left { get; set; }
+ public float Width { get; set; }
+ public float Height { get; set; }
+
+ public RectangleF Rect => new(Left, 0, Width, Height);
+
+ private string Fit(Graphics g, RectangleF rect)
+ {
+ if (Text.Length == 0 || g.MeasureString(Text, Font).Width <= rect.Width)
+ {
+ return Text;
+ }
+
+ string txt = Text.Length > 100 ? Text[..100] : Text;
+
+ int i = txt.Length;
+
+ while (g.MeasureString(txt + "...", Font).Width > rect.Width)
+ {
+ txt = txt[..--i];
+ if (i == 0)
+ break;
+ }
+
+ return txt + "...";
+ }
+
+ public void Draw(Graphics g)
+ {
+ g.DrawString(
+ Fit(g, Rect),
+ Font,
+ new SolidBrush(Color),
+ Rect,
+ new StringFormat
+ {
+ Alignment = StringAlignment.Near,
+ LineAlignment = StringAlignment.Center,
+ FormatFlags = StringFormatFlags.NoWrap,
+ }
+ );
+ }
+ }
+}
diff --git a/Pf2eViewer/EntityTreeViewer/EntityTreeViewerRow.Designer.cs b/Pf2eViewer/EntityTreeViewer/EntityTreeViewerRow.Designer.cs
index 8836e52..05f782b 100644
--- a/Pf2eViewer/EntityTreeViewer/EntityTreeViewerRow.Designer.cs
+++ b/Pf2eViewer/EntityTreeViewer/EntityTreeViewerRow.Designer.cs
@@ -91,7 +91,7 @@ sealed partial class EntityTreeViewerRow
TypeLabel.Name = "TypeLabel";
TypeLabel.Size = new Size(57, 38);
TypeLabel.TabIndex = 3;
- TypeLabel.Text = "Type";
+ TypeLabel.Text = "TypeText";
TypeLabel.TextAlign = ContentAlignment.MiddleLeft;
//
// ValueLabel
@@ -102,7 +102,7 @@ sealed partial class EntityTreeViewerRow
ValueLabel.Name = "ValueLabel";
ValueLabel.Size = new Size(288, 38);
ValueLabel.TabIndex = 4;
- ValueLabel.Text = "Value";
+ ValueLabel.Text = "ValueText";
ValueLabel.TextAlign = ContentAlignment.MiddleLeft;
//
// EntityTreeViewerRow
diff --git a/Pf2eViewer/EntityTreeViewer/EntityTreeViewerRow.cs b/Pf2eViewer/EntityTreeViewer/EntityTreeViewerRow.cs
index 1f30723..3d3eafe 100644
--- a/Pf2eViewer/EntityTreeViewer/EntityTreeViewerRow.cs
+++ b/Pf2eViewer/EntityTreeViewer/EntityTreeViewerRow.cs
@@ -76,7 +76,7 @@ internal sealed partial class EntityTreeViewerRow : UserControl
set => ParentControl.ItemHeight = value;
}
- // Value functions
+ // ValueText functions
public bool HasButton => Item.FieldType == StructureFieldType.Complex;
public int Depth => Item.Depth;
@@ -122,7 +122,7 @@ internal sealed partial class EntityTreeViewerRow : UserControl
Left = 0;
Top = ViewIndex * ParentControl.ItemHeight;
- Width = ParentControl.ContentPanel.Width - Left - SystemInformation.VerticalScrollBarWidth;
+ Width = ParentControl.ContentWidth - Left - SystemInformation.VerticalScrollBarWidth;
Height = ParentControl.ItemHeight;
// Name Panel
@@ -135,7 +135,7 @@ internal sealed partial class EntityTreeViewerRow : UserControl
NameLabel.Left = IconPictureBox.Width;
NameLabel.Width = NamePanel.Width - NameLabel.Left;
- // Value Panel
+ // ValueText Panel
ValuePanel.Left = NamePanel.Left + NamePanel.Width;
ValuePanel.Width = Width - ValuePanel.Left;
diff --git a/Pf2eViewer/EntityTreeViewer/StructureBuilder.cs b/Pf2eViewer/EntityTreeViewer/StructureBuilder.cs
index c2ef7ed..427d00d 100644
--- a/Pf2eViewer/EntityTreeViewer/StructureBuilder.cs
+++ b/Pf2eViewer/EntityTreeViewer/StructureBuilder.cs
@@ -36,7 +36,7 @@ internal class StructureBuilder
public void CompleteProcessed(object value, StructureFieldComplex field)
{
- var q = _processedObjects.FirstOrDefault(p => p.Value == value);
+ StructureProcessedObject? q = _processedObjects.FirstOrDefault(p => p.Value == value);
if (q == null)
{
@@ -59,6 +59,9 @@ internal class StructureBuilder
case StructureFieldType.Enum:
return new StructureFieldEnum(this, value!, name, depth);
+ case StructureFieldType.Reference:
+ break;
+
case StructureFieldType.Complex:
default:
@@ -66,15 +69,22 @@ internal class StructureBuilder
p.Value == value
);
- if (processed is not null)
+ if (processed is null)
{
- var reference = new StructureFieldReference(this, name, null, depth);
- processed.AddReference(reference);
- return reference;
+ return Create(name, value!, depth);
}
- return Create(name, value!, depth);
+ StructureFieldReference reference = new StructureFieldReference(
+ this,
+ name,
+ null,
+ depth
+ );
+ processed.AddReference(reference);
+ return reference;
}
+
+ throw new("Impossible");
}
public static StructureFieldType GetFieldType(object? value)
@@ -112,7 +122,7 @@ internal class StructureProcessedObject(object value)
set
{
_field = value;
- foreach (var reference in _references)
+ foreach (StructureFieldReference reference in _references)
{
reference.Reference = Field;
}
@@ -158,7 +168,7 @@ internal abstract class StructureField(StructureBuilder builder, string name, in
public virtual bool Visible { get; set; } = true;
- public int Depth = depth;
+ public readonly int Depth = depth;
public abstract string GetTypeString();
@@ -166,7 +176,13 @@ internal abstract class StructureField(StructureBuilder builder, string name, in
public virtual ICollection GetTextRows(EntityTreeViewerControl control)
{
- return [new EntityTreeViewerRow(control, this)];
+ return [new(control, this)];
+ }
+
+ public virtual ICollection GetRows(Func func)
+ {
+ StructureField[] q = [this];
+ return q.Select(func).ToList();
}
}
@@ -189,7 +205,7 @@ internal class StructureFieldPrimitive(
{
public override StructureFieldType FieldType => StructureFieldType.Primitive;
- public object Value = value;
+ public readonly object Value = value;
public readonly Type Type = value.GetType();
@@ -221,7 +237,7 @@ internal class StructureFieldEnum(StructureBuilder builder, object value, string
{
public override StructureFieldType FieldType => StructureFieldType.Enum;
- public object Value = value;
+ public readonly object Value = value;
public readonly Type Type = value.GetType();
@@ -238,8 +254,6 @@ internal class StructureFieldComplex : StructureField
public readonly Type Type;
- private bool _collapsed = false;
-
public bool Collapsed
{
get => _collapsed;
@@ -249,16 +263,7 @@ internal class StructureFieldComplex : StructureField
UpdateFieldVisibility();
}
}
-
- private bool _visible = true;
-
- public StructureFieldComplex(StructureBuilder builder, object value, string name, int depth)
- : base(builder, name, depth)
- {
- Type = value.GetType();
-
- SetFields((dynamic)value);
- }
+ private bool _collapsed = false;
public override bool Visible
{
@@ -269,10 +274,19 @@ internal class StructureFieldComplex : StructureField
UpdateFieldVisibility();
}
}
+ private bool _visible = true;
+
+ public StructureFieldComplex(StructureBuilder builder, object value, string name, int depth)
+ : base(builder, name, depth)
+ {
+ Type = value.GetType();
+
+ SetFields((dynamic)value);
+ }
private void UpdateFieldVisibility()
{
- foreach (var field in Fields)
+ foreach (StructureField field in Fields)
{
field.Visible = Visible && !Collapsed;
}
@@ -280,24 +294,22 @@ internal class StructureFieldComplex : StructureField
private void SetFields(LocaleString localeString)
{
- List records = [];
-
- foreach (var field in localeString)
- {
- records.Add(new FieldRecord(field.Locale.ToString(), field.Value));
- }
-
- SetFieldsFromRecords(records);
+ SetFieldsFromRecords(
+ localeString
+ .Select(field => new FieldRecord(field.Locale.ToString(), field.Value))
+ .ToList()
+ );
}
- private void SetFields(IEnumerable enumrable)
+ private void SetFields(IEnumerable enumerable)
{
int i = 0;
+
List records = [];
- foreach (var item in enumrable)
+ foreach (object? item in enumerable)
{
- records.Add(new FieldRecord($"[{i++}]", item));
+ records.Add(new($"[{i++}]", item));
}
SetFieldsFromRecords(records);
@@ -320,24 +332,22 @@ internal class StructureFieldComplex : StructureField
private void SetFieldsFromRecords(List records)
{
- foreach (FieldRecord record in records)
+ foreach (
+ FieldRecord record in records.Where(record =>
+ record.FieldType == StructureFieldType.Complex
+ )
+ )
{
- if (record.FieldType == StructureFieldType.Complex)
- {
- record.Allowed = Builder.RegisterProcessed(record.Value!);
- }
+ record.Allowed = Builder.RegisterProcessed(record.Value!);
}
- foreach (var record in records)
+ foreach (FieldRecord record in records)
{
- if (record.FieldType == StructureFieldType.Complex && record.Allowed)
- {
- Fields.Add(Builder.Create(record.Name, record.Value!, Depth + 1));
- }
- else
- {
- Fields.Add(Builder.Resolve(record.Name, record.Value!, Depth + 1));
- }
+ Fields.Add(
+ record is { FieldType: StructureFieldType.Complex, Allowed: true }
+ ? Builder.Create(record.Name, record.Value!, Depth + 1)
+ : Builder.Resolve(record.Name, record.Value!, Depth + 1)
+ );
}
}
@@ -350,11 +360,16 @@ internal class StructureFieldComplex : StructureField
return rows;
}
+ public override ICollection GetRows(Func func)
+ {
+ return [.. base.GetRows(func), .. Fields.SelectMany(f => f.GetRows(func)).ToList()];
+ }
+
private class FieldRecord(string name, object? value)
{
- public string Name = name;
+ public readonly string Name = name;
- public object? Value = value;
+ public readonly object? Value = value;
public StructureFieldType FieldType => StructureBuilder.GetFieldType(Value);
diff --git a/Pf2eViewer/Program.cs b/Pf2eViewer/Program.cs
index 7e3bb13..a9482a2 100644
--- a/Pf2eViewer/Program.cs
+++ b/Pf2eViewer/Program.cs
@@ -18,7 +18,7 @@ internal static class Program
Application.SetColorMode(SystemColorMode.System);
#pragma warning restore WFO5001
- Application.Run(new MainViewForm() { StartPosition = FormStartPosition.CenterScreen });
- // Application.Run(new TestForm() { StartPosition = FormStartPosition.CenterScreen });
+ // Application.Run(new MainViewForm() { StartPosition = FormStartPosition.CenterScreen });
+ Application.Run(new TestForm() { StartPosition = FormStartPosition.CenterScreen });
}
}
diff --git a/Pf2eViewer/TestForm.Designer.cs b/Pf2eViewer/TestForm.Designer.cs
index 50d3864..e1deba6 100644
--- a/Pf2eViewer/TestForm.Designer.cs
+++ b/Pf2eViewer/TestForm.Designer.cs
@@ -49,13 +49,16 @@ partial class TestForm
// entityTreeViewerControl1
//
entityTreeViewerControl1.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
- entityTreeViewerControl1.DepthSize = 20;
- entityTreeViewerControl1.EntityView = null;
+ entityTreeViewerControl1.AutoScroll = true;
+ entityTreeViewerControl1.ButtonSize = 15;
+ entityTreeViewerControl1.DepthSize = 15;
entityTreeViewerControl1.Font = new Font("Consolas", 9F);
+ entityTreeViewerControl1.HoverColor = SystemColors.ControlLight;
entityTreeViewerControl1.ItemHeight = 20;
- entityTreeViewerControl1.Location = new Point(12, 38);
+ entityTreeViewerControl1.Location = new Point(14, 46);
+ entityTreeViewerControl1.Margin = new Padding(3, 4, 3, 4);
entityTreeViewerControl1.Name = "entityTreeViewerControl1";
- entityTreeViewerControl1.Size = new Size(426, 606);
+ entityTreeViewerControl1.Size = new Size(424, 597);
entityTreeViewerControl1.TabIndex = 1;
//
// TestForm