inspector: fix up detachable headers to dock

This commit is contained in:
Mitchell Hashimoto
2026-01-27 13:53:28 -08:00
parent 1d7def0d2e
commit 4c2ea6a9d8
2 changed files with 48 additions and 42 deletions

View File

@@ -20,12 +20,12 @@ pub const Window = struct {
/// Whether the palette window is open.
show_palette: bool = false,
/// Whether sections are shown in their own windows.
show_misc_window: bool = false,
show_layout_window: bool = false,
show_mouse_window: bool = false,
show_color_window: bool = false,
show_modes_window: bool = false,
/// State for detachable headers.
misc_state: widgets.DetachableHeaderState = .{},
layout_state: widgets.DetachableHeaderState = .{},
mouse_state: widgets.DetachableHeaderState = .{},
color_state: widgets.DetachableHeaderState = .{},
modes_state: widgets.DetachableHeaderState = .{},
// Render
pub fn render(self: *Window, t: *Terminal) void {
@@ -53,36 +53,11 @@ pub const Window = struct {
}
const ctx: RenderContext = .{ .window = self, .terminal = t };
widgets.collapsingHeaderDetachable(
"Misc",
&self.show_misc_window,
ctx,
renderMiscContent,
);
widgets.collapsingHeaderDetachable(
"Layout",
&self.show_layout_window,
ctx,
renderLayoutContent,
);
widgets.collapsingHeaderDetachable(
"Mouse",
&self.show_mouse_window,
ctx,
renderMouseContent,
);
widgets.collapsingHeaderDetachable(
"Color",
&self.show_color_window,
ctx,
renderColorContent,
);
widgets.collapsingHeaderDetachable(
"Modes",
&self.show_modes_window,
ctx,
renderModesContent,
);
widgets.detachableHeader("Misc", &self.misc_state, ctx, renderMiscContent);
widgets.detachableHeader("Layout", &self.layout_state, ctx, renderLayoutContent);
widgets.detachableHeader("Mouse", &self.mouse_state, ctx, renderMouseContent);
widgets.detachableHeader("Color", &self.color_state, ctx, renderColorContent);
widgets.detachableHeader("Modes", &self.modes_state, ctx, renderModesContent);
if (self.show_palette) {
defer cimgui.c.ImGui_End();

View File

@@ -13,32 +13,63 @@ pub fn helpMarker(text: [:0]const u8) void {
cimgui.c.ImGui_TextUnformatted(text.ptr);
}
pub const DetachableHeaderState = struct {
show_window: bool = false,
/// Internal state. Don't touch.
first_show: bool = false,
};
/// Render a collapsing header that can be detached into its own window.
/// When detached, renders as a separate window with a close button.
/// When attached, renders as a collapsing header with a pop-out button.
pub fn collapsingHeaderDetachable(
pub fn detachableHeader(
label: [:0]const u8,
show: *bool,
state: *DetachableHeaderState,
ctx: anytype,
comptime contentFn: fn (@TypeOf(ctx)) void,
) void {
cimgui.c.ImGui_PushID(label);
defer cimgui.c.ImGui_PopID();
if (show.*) {
if (state.show_window) {
// On first show, dock this window to the right of the parent window's dock.
// We only do this once so the user can freely reposition the window afterward
// without it snapping back to the right on every frame.
if (!state.first_show) {
state.first_show = true;
const current_dock_id = cimgui.c.ImGui_GetWindowDockID();
if (current_dock_id != 0) {
var dock_id_right: cimgui.c.ImGuiID = 0;
var dock_id_left: cimgui.c.ImGuiID = 0;
_ = cimgui.ImGui_DockBuilderSplitNode(
current_dock_id,
cimgui.c.ImGuiDir_Right,
0.3,
&dock_id_right,
&dock_id_left,
);
cimgui.ImGui_DockBuilderDockWindow(label, dock_id_right);
cimgui.ImGui_DockBuilderFinish(current_dock_id);
}
}
defer cimgui.c.ImGui_End();
if (cimgui.c.ImGui_Begin(
label,
show,
&state.show_window,
cimgui.c.ImGuiWindowFlags_NoFocusOnAppearing,
)) contentFn(ctx);
return;
}
// Reset first_show when window is closed so next open docks again
state.first_show = false;
cimgui.c.ImGui_SetNextItemAllowOverlap();
const is_open = cimgui.c.ImGui_CollapsingHeader(
label,
cimgui.c.ImGuiTreeNodeFlags_DefaultOpen,
cimgui.c.ImGuiTreeNodeFlags_None,
);
// Place pop-out button inside the header bar
@@ -61,7 +92,7 @@ pub fn collapsingHeaderDetachable(
">>##detach",
.{ .x = button_size, .y = button_size },
)) {
show.* = true;
state.show_window = true;
}
cimgui.c.ImGui_PopStyleVar();
if (cimgui.c.ImGui_IsItemHovered(cimgui.c.ImGuiHoveredFlags_DelayShort)) {