[0.1.37] Settings and Debug Panel buttons in the main panel's top right; window buttons on their own row

This commit is contained in:
Musa Mahmood 2026-10-18 17:29:31 -04:00
parent 5dd62ac201
commit 35b7290e3b
4 changed files with 81 additions and 7 deletions

View File

@ -52,7 +52,7 @@ APP_NAME :: "mcap";
APP_FOLDER_NAME :: "mcap";
GIT_BRANCH :: "check";
GIT_HASH :: "-";
VERSION :: "0.1.35";
VERSION :: "0.1.37";
BUILD_DATE :: "-";
DEBUG :: true;
COMPILE_TESTS :: true;

View File

@ -8,7 +8,7 @@ APP_NAME :: "mcap";
APP_FOLDER_NAME :: "mcap";
APP_BUNDLE_IDENTIFIER :: "com.example.mcap";
VERSION :: "0.1.35";
VERSION :: "0.1.37";
// Where everything goes: bin/, or bin-headless/ for builds made with no_crash_dialog, so automated
// builds never write over the ones you run by hand.
build_directory := "bin";

View File

@ -1097,6 +1097,10 @@ viewer_ui :: () { using ImGui;
viewer_watch_frame(); // files added or deleted outside the app
viewer_frame_gpu_work();
start := GetCursorPos();
viewer_corner_buttons(start);
SetCursorPos(start);
if viewer.scan_error {
TextColored(app_theme.palette.warning, "%", viewer.scan_error);
SameLine();
@ -1141,7 +1145,7 @@ viewer_ui :: () { using ImGui;
SameLine();
SetNextItemWidth(160);
SliderFloat("Size", *viewer.thumb_size, 64, MCAP_PREVIEW_MAX_SIDE, "%.0f px");
SameLine();
// The window buttons, on the row under the search.
// The OCR window (app/ocr_ui.jai): the model, GPU or CPU, and the library scan.
if Button("OCR") ocr_ui.window_open = !ocr_ui.window_open;
SameLine();
@ -1186,6 +1190,35 @@ viewer_ui :: () { using ImGui;
viewer_full_window();
}
// The settings and Debug Panel buttons in the top right corner, on the search's row, sized to its text.
viewer_corner_buttons :: (start: Vector2) { using ImGui;
size := floor(GetTextLineHeight());
gap := floor(imgui_scale(4.0));
x := GetWindowContentRegionMax().x - TOP_RIGHT_PADDING - 2 * size - gap;
y := start.y + GetStyle().FramePadding.y; // level with the text in the row's frames
draw := GetWindowDrawList();
text := GetColorU32(.Text);
SetCursorPos(.{x, y});
settings_clicked, settings_min := imgui_icon_button("##mcap_open_settings", size);
settings_path := app_user_settings_path();
ButtonTooltip(tprint("Opens %", settings_path));
imgui_draw_gear(draw, settings_min, size, text);
if settings_clicked {
if !file_exists(settings_path) app_save_user_settings_file();
app_open_config_file(settings_path);
}
SetCursorPos(.{x + size + gap, y});
debug_clicked, debug_min := imgui_icon_button("##mcap_toggle_debug_panel", size);
hotkey := to_string(toggle_debug_panel_hotkey);
tooltip := ifx app.show_debug_panel then "Hides the Debug Panel" else "Shows the Debug Panel";
ButtonTooltip(ifx hotkey.count then tprint("% (%)", tooltip, hotkey) else tooltip);
// In the accent while the panel shows.
imgui_draw_bug(draw, debug_min, size, ifx app.show_debug_panel then GetColorU32(app_theme.palette.accent) else text);
if debug_clicked app.show_debug_panel = !app.show_debug_panel;
}
// The trash button's square in a thumbnail whose top left is at top_left.
viewer_trash_rect :: (top_left: ImGui.ImVec2, cell: float) -> ImGui.ImVec2, ImGui.ImVec2 {
size := clamp(cell * 0.16, 18, 30);

View File

@ -180,8 +180,6 @@ imgui_text_top_right :: (text: string, text_color: Vector4) {
original_cursor_pos := GetCursorPos();
windowRegionMax := GetWindowContentRegionMax();
text_size := CalcTextSize(text);
TOP_RIGHT_PADDING : float32 : 10;
cursorX: float32 = windowRegionMax.x - text_size.x - TOP_RIGHT_PADDING;
cursorY: float32 = 0 + TOP_RIGHT_PADDING;
@ -242,13 +240,13 @@ CenteredButton :: (label: string) -> bool { using ImGui;
return Button(label_c);
}
TOP_RIGHT_PADDING : float32 : 10;
RightAlignedText :: (text: string, text_color: Vector4) {
using ImGui;
text_size := CalcTextSize(text);
available := GetWindowContentRegionMax().x;
TOP_RIGHT_PADDING : float32 : 10;
// cursorX: float32 = available.x - text_size.x - TOP_RIGHT_PADDING;
// cursorY: float32 = 0 + TOP_RIGHT_PADDING;
@ -261,6 +259,49 @@ RightAlignedText :: (text: string, text_color: Vector4) {
TextColored(text_color, "%", text);
}
// A small square button with a glyph drawn in it, at the cursor: the item's frame color behind it
// while hovered or held. The glyph is the caller's to draw, from the returned rect.
imgui_icon_button :: (id: *u8, size: float) -> clicked: bool, min: Vector2 {
using ImGui;
clicked := InvisibleButton(id, .{size, size});
min := GetItemRectMin();
if IsItemHovered() {
draw := GetWindowDrawList();
background := ifx IsItemActive() then Col.ButtonActive else Col.ButtonHovered;
draw.AddRectFilled(draw, min, .{min.x + size, min.y + size}, GetColorU32(background), GetStyle().FrameRounding);
}
return clicked, min;
}
// A gear in the size × size square at min: eight teeth round a ring.
imgui_draw_gear :: (draw: *ImGui.ImDrawList, min: Vector2, size: float, color: u32) {
r := size * 0.5;
c := Vector2.{min.x + r, min.y + r};
tooth := max(r * 0.28, 1.0);
for 0..7 {
angle := it * TAU / 8;
d := Vector2.{cos(angle), sin(angle)};
draw.AddLine(draw, .{c.x + d.x * r * 0.45, c.y + d.y * r * 0.45}, .{c.x + d.x * r * 0.9, c.y + d.y * r * 0.9}, color, tooth);
}
draw.AddCircle(draw, c, r * 0.5, color, 0, max(r * 0.26, 1.0));
}
// A bug in the size × size square at min: a body, a head, antennae and three legs a side.
imgui_draw_bug :: (draw: *ImGui.ImDrawList, min: Vector2, size: float, color: u32) {
r := size * 0.5;
c := Vector2.{min.x + r, min.y + r};
stroke := max(r * 0.13, 1.0);
draw.AddEllipseFilled(draw, .{c.x, c.y + r * 0.18}, .{r * 0.4, r * 0.55}, color);
draw.AddCircleFilled(draw, .{c.x, c.y - r * 0.5}, r * 0.24, color);
for side: float.[-1, 1] {
draw.AddLine(draw, .{c.x + side * r * 0.12, c.y - r * 0.68}, .{c.x + side * r * 0.38, c.y - r * 0.95}, color, stroke);
for leg: 0..2 {
y := c.y + r * (-0.1 + 0.3 * leg);
draw.AddLine(draw, .{c.x + side * r * 0.3, y}, .{c.x + side * r * 0.85, y + r * (-0.2 + 0.2 * leg)}, color, stroke);
}
}
}
RightAlignedButton :: (label: string) -> bool #expand { using ImGui;
// start := GetCursorPos();
label_c := to_c_string(label,, temp);