inspector: clean up page

This commit is contained in:
Mitchell Hashimoto
2026-01-29 10:25:48 -08:00
parent 51ce210833
commit 3ac4f70e48
2 changed files with 42 additions and 134 deletions

View File

@@ -10,6 +10,9 @@ const Page = terminal.Page;
pub fn inspector(page: *const terminal.Page) void {
cimgui.c.ImGui_SeparatorText("Managed Memory");
managedMemory(page);
cimgui.c.ImGui_SeparatorText("Rows");
rowsTable(page);
}
/// Draw a tree node header with metadata about this page. Returns if
@@ -103,7 +106,7 @@ pub fn managedMemory(page: *const Page) void {
if (cimgui.c.ImGui_BeginTable(
"##managed",
3,
4,
cimgui.c.ImGuiTableFlags_BordersInnerV |
cimgui.c.ImGuiTableFlags_RowBg |
cimgui.c.ImGuiTableFlags_SizingFixedFit,
@@ -111,6 +114,7 @@ pub fn managedMemory(page: *const Page) void {
defer cimgui.c.ImGui_EndTable();
cimgui.c.ImGui_TableSetupColumn("Resource", cimgui.c.ImGuiTableColumnFlags_WidthFixed);
cimgui.c.ImGui_TableSetupColumn("", cimgui.c.ImGuiTableColumnFlags_WidthFixed);
cimgui.c.ImGui_TableSetupColumn("Used", cimgui.c.ImGuiTableColumnFlags_WidthFixed);
cimgui.c.ImGui_TableSetupColumn("Capacity", cimgui.c.ImGuiTableColumnFlags_WidthFixed);
cimgui.c.ImGui_TableHeadersRow();
@@ -121,186 +125,89 @@ pub fn managedMemory(page: *const Page) void {
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
cimgui.c.ImGui_Text("Columns");
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
cimgui.c.ImGui_Text("%d", size.cols);
widgets.helpMarker("Number of columns in the terminal grid.");
_ = cimgui.c.ImGui_TableSetColumnIndex(2);
cimgui.c.ImGui_Text("%d", size.cols);
_ = cimgui.c.ImGui_TableSetColumnIndex(3);
cimgui.c.ImGui_Text("%d", cap.cols);
cimgui.c.ImGui_TableNextRow();
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
cimgui.c.ImGui_Text("Rows");
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
cimgui.c.ImGui_Text("%d", size.rows);
widgets.helpMarker("Number of rows in this page.");
_ = cimgui.c.ImGui_TableSetColumnIndex(2);
cimgui.c.ImGui_Text("%d", size.rows);
_ = cimgui.c.ImGui_TableSetColumnIndex(3);
cimgui.c.ImGui_Text("%d", cap.rows);
cimgui.c.ImGui_TableNextRow();
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
cimgui.c.ImGui_Text("Styles");
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
cimgui.c.ImGui_Text("%d", page.styles.count());
widgets.helpMarker("Unique text styles (colors, attributes) currently in use.");
_ = cimgui.c.ImGui_TableSetColumnIndex(2);
cimgui.c.ImGui_Text("%d", page.styles.count());
_ = cimgui.c.ImGui_TableSetColumnIndex(3);
cimgui.c.ImGui_Text("%d", page.styles.layout.cap);
cimgui.c.ImGui_TableNextRow();
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
cimgui.c.ImGui_Text("Graphemes");
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
cimgui.c.ImGui_Text("%d", page.graphemeCount());
widgets.helpMarker("Extended grapheme clusters for multi-codepoint characters.");
_ = cimgui.c.ImGui_TableSetColumnIndex(2);
cimgui.c.ImGui_Text("%d", page.graphemeCount());
_ = cimgui.c.ImGui_TableSetColumnIndex(3);
cimgui.c.ImGui_Text("%d", page.graphemeCapacity());
cimgui.c.ImGui_TableNextRow();
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
cimgui.c.ImGui_Text("Strings (bytes)");
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
cimgui.c.ImGui_Text("%d", page.string_alloc.usedBytes(page.memory));
widgets.helpMarker("String storage for hyperlink URIs and other text data.");
_ = cimgui.c.ImGui_TableSetColumnIndex(2);
cimgui.c.ImGui_Text("%d", page.string_alloc.usedBytes(page.memory));
_ = cimgui.c.ImGui_TableSetColumnIndex(3);
cimgui.c.ImGui_Text("%d", page.string_alloc.capacityBytes());
{
const hyperlink_map = page.hyperlink_map.map(page.memory);
cimgui.c.ImGui_TableNextRow();
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
cimgui.c.ImGui_Text("Hyperlink Map");
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
cimgui.c.ImGui_Text("%d", hyperlink_map.count());
_ = cimgui.c.ImGui_TableSetColumnIndex(2);
cimgui.c.ImGui_Text("%d", hyperlink_map.capacity());
}
const hyperlink_map = page.hyperlink_map.map(page.memory);
cimgui.c.ImGui_TableNextRow();
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
cimgui.c.ImGui_Text("Hyperlink Map");
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
widgets.helpMarker("Maps cell positions to hyperlink IDs.");
_ = cimgui.c.ImGui_TableSetColumnIndex(2);
cimgui.c.ImGui_Text("%d", hyperlink_map.count());
_ = cimgui.c.ImGui_TableSetColumnIndex(3);
cimgui.c.ImGui_Text("%d", hyperlink_map.capacity());
cimgui.c.ImGui_TableNextRow();
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
cimgui.c.ImGui_Text("Hyperlink IDs");
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
cimgui.c.ImGui_Text("%d", page.hyperlink_set.count());
widgets.helpMarker("Unique hyperlink definitions (URI + optional ID).");
_ = cimgui.c.ImGui_TableSetColumnIndex(2);
cimgui.c.ImGui_Text("%d", page.hyperlink_set.count());
_ = cimgui.c.ImGui_TableSetColumnIndex(3);
cimgui.c.ImGui_Text("%d", page.hyperlink_set.layout.cap);
}
}
pub const Context = struct {
page_node: *const PageList.List.Node,
index: usize,
row_start: usize,
row_end: usize,
active_node: *const PageList.List.Node,
viewport_node: *const PageList.List.Node,
};
pub const InspectorState = struct {
open: bool,
rows_with_text: usize,
};
const PageStats = struct {
rows_with_text: usize,
};
fn pageStats(page: *const terminal.Page) PageStats {
var stats: PageStats = .{ .rows_with_text = 0 };
const rows = page.rows.ptr(page.memory)[0..page.size.rows];
for (rows) |*row| {
const cells = page.getCells(row);
for (cells) |cell| {
if (cell.hasText()) {
stats.rows_with_text += 1;
break;
}
}
}
return stats;
}
pub fn draw(page: *const terminal.Page) void {
cimgui.c.ImGui_PushIDPtr(page);
defer cimgui.c.ImGui_PopID();
cimgui.c.ImGui_SeparatorText("Memory");
memoryTable(page);
cimgui.c.ImGui_SeparatorText("Grid");
gridTable(page);
cimgui.c.ImGui_SeparatorText("Rows");
cimgui.c.ImGui_SameLine();
widgets.helpMarker("Per-row metadata. Cells are coming next.");
rowsTable(page);
}
fn memoryTable(page: *const terminal.Page) void {
if (!cimgui.c.ImGui_BeginTable(
"##page_memory",
2,
cimgui.c.ImGuiTableFlags_BordersInnerV |
cimgui.c.ImGuiTableFlags_RowBg |
cimgui.c.ImGuiTableFlags_SizingFixedFit,
)) return;
defer cimgui.c.ImGui_EndTable();
cimgui.c.ImGui_TableNextRow();
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
cimgui.c.ImGui_Text("Memory Size");
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
cimgui.c.ImGui_Text(
"%d bytes (%d KiB)",
page.memory.len,
units.toKibiBytes(page.memory.len),
);
cimgui.c.ImGui_TableNextRow();
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
cimgui.c.ImGui_Text("VM Pages");
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
cimgui.c.ImGui_Text("%d", page.memory.len / std.heap.page_size_min);
}
fn gridTable(page: *const terminal.Page) void {
if (!cimgui.c.ImGui_BeginTable(
"##page_grid",
3,
cimgui.c.ImGuiTableFlags_BordersInnerV |
cimgui.c.ImGuiTableFlags_RowBg |
cimgui.c.ImGuiTableFlags_SizingFixedFit,
)) return;
defer cimgui.c.ImGui_EndTable();
cimgui.c.ImGui_TableSetupColumn("Dimension", cimgui.c.ImGuiTableColumnFlags_WidthFixed);
cimgui.c.ImGui_TableSetupColumn("Used", cimgui.c.ImGuiTableColumnFlags_WidthFixed);
cimgui.c.ImGui_TableSetupColumn("Capacity", cimgui.c.ImGuiTableColumnFlags_WidthFixed);
cimgui.c.ImGui_TableHeadersRow();
const size = page.size;
const cap = page.capacity;
cimgui.c.ImGui_TableNextRow();
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
cimgui.c.ImGui_Text("Columns");
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
cimgui.c.ImGui_Text("%d", size.cols);
_ = cimgui.c.ImGui_TableSetColumnIndex(2);
cimgui.c.ImGui_Text("%d", cap.cols);
cimgui.c.ImGui_TableNextRow();
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
cimgui.c.ImGui_Text("Rows");
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
cimgui.c.ImGui_Text("%d", size.rows);
_ = cimgui.c.ImGui_TableSetColumnIndex(2);
cimgui.c.ImGui_Text("%d", cap.rows);
}
fn rowsTable(page: *const terminal.Page) void {
const visible_rows: usize = @min(page.size.rows, 12);
const row_height: f32 = cimgui.c.ImGui_GetTextLineHeightWithSpacing();
const child_height: f32 = row_height * (@as(f32, @floatFromInt(visible_rows)) + 2.0);
_ = cimgui.c.ImGui_BeginChild(
// Child window so scrolling is separate.
// This defer first is not a bug, EndChild always needs to be called.
defer cimgui.c.ImGui_EndChild();
if (!cimgui.c.ImGui_BeginChild(
"##page_rows",
.{ .x = 0.0, .y = child_height },
cimgui.c.ImGuiChildFlags_Borders,
cimgui.c.ImGuiWindowFlags_None,
);
defer cimgui.c.ImGui_EndChild();
)) return;
if (!cimgui.c.ImGui_BeginTable(
"##page_rows_table",
@@ -311,6 +218,7 @@ fn rowsTable(page: *const terminal.Page) void {
)) return;
defer cimgui.c.ImGui_EndTable();
cimgui.c.ImGui_TableSetupScrollFreeze(0, 1);
cimgui.c.ImGui_TableSetupColumn("Row", cimgui.c.ImGuiTableColumnFlags_WidthFixed);
cimgui.c.ImGui_TableSetupColumn("Text", cimgui.c.ImGuiTableColumnFlags_WidthFixed);
cimgui.c.ImGui_TableSetupColumn("Dirty", cimgui.c.ImGuiTableColumnFlags_WidthFixed);

View File

@@ -61,9 +61,9 @@ pub const Inspector = struct {
row_offset -= page.size.rows;
index -= 1;
// Use our node pointer, which is guaranteed to be unique
// in this hierarchy, as the ID.
cimgui.c.ImGui_PushIDPtr(node);
// We use our location as the ID so that even if reallocations
// happen we remain open if we're open already.
cimgui.c.ImGui_PushIDInt(@intCast(index));
defer cimgui.c.ImGui_PopID();
// Open up the tree node.