add global menu

This commit is contained in:
2026-02-22 18:42:14 -05:00
parent 2d08a1dd54
commit ace71a6725
3 changed files with 138 additions and 14 deletions

View File

@@ -3,6 +3,54 @@
#include "imgui.h"
#include "imgui_internal.h"
enum MenuCmd {
MENU_NONE = 0,
MENU_FILE_NEW,
MENU_FILE_OPEN,
MENU_FILE_SAVE,
MENU_FILE_SAVE_AS,
MENU_FILE_EXIT,
MENU_IMPORT_AUDIO,
MENU_IMPORT_MIDI,
MENU_VIEW_BROWSER,
MENU_VIEW_PROPERTIES,
MENU_VIEW_LOG,
MENU_VIEW_DEMO,
};
static void setup_menus(PlatformWindow *window)
{
PlatformMenuItem file_items[] = {
{ "New", MENU_FILE_NEW },
{ "Open...", MENU_FILE_OPEN },
{ "Save", MENU_FILE_SAVE },
{ "Save As...", MENU_FILE_SAVE_AS },
{ nullptr, 0 },
{ "Exit", MENU_FILE_EXIT },
};
PlatformMenuItem import_items[] = {
{ "Audio...", MENU_IMPORT_AUDIO },
{ "MIDI...", MENU_IMPORT_MIDI },
};
PlatformMenuItem view_items[] = {
{ "Browser", MENU_VIEW_BROWSER },
{ "Properties", MENU_VIEW_PROPERTIES },
{ "Log", MENU_VIEW_LOG },
{ nullptr, 0 },
{ "Demo", MENU_VIEW_DEMO },
};
PlatformMenu menus[] = {
{ "File", file_items, sizeof(file_items) / sizeof(file_items[0]) },
{ "Import", import_items, sizeof(import_items) / sizeof(import_items[0]) },
{ "View", view_items, sizeof(view_items) / sizeof(view_items[0]) },
};
platform_set_menu(window, menus, sizeof(menus) / sizeof(menus[0]));
}
static void build_default_layout(ImGuiID dockspace_id)
{
ImGui::DockBuilderRemoveNode(dockspace_id);
@@ -45,11 +93,25 @@ int main(int argc, char **argv)
return 1;
}
setup_menus(window);
int32_t last_w = w, last_h = h;
bool show_demo = true;
bool first_frame = true;
bool show_demo = true;
bool show_browser = true;
bool show_props = true;
bool show_log = true;
bool first_frame = true;
while (platform_poll_events(window)) {
int32_t menu_cmd = platform_poll_menu_command(window);
switch (menu_cmd) {
case MENU_FILE_EXIT: platform_destroy_window(window); return 0;
case MENU_VIEW_BROWSER: show_browser = !show_browser; break;
case MENU_VIEW_PROPERTIES:show_props = !show_props; break;
case MENU_VIEW_LOG: show_log = !show_log; break;
case MENU_VIEW_DEMO: show_demo = !show_demo; break;
default: break;
}
platform_get_size(window, &w, &h);
if (w != last_w || h != last_h) {
renderer_resize(renderer, w, h);
@@ -70,10 +132,12 @@ int main(int argc, char **argv)
}
// Left panel
ImGui::Begin("Browser");
ImGui::Text("Instruments");
ImGui::Separator();
ImGui::End();
if (show_browser) {
ImGui::Begin("Browser", &show_browser);
ImGui::Text("Instruments");
ImGui::Separator();
ImGui::End();
}
// Main content
ImGui::Begin("Main");
@@ -81,16 +145,20 @@ int main(int argc, char **argv)
ImGui::End();
// Right panel
ImGui::Begin("Properties");
ImGui::Text("Details");
ImGui::Separator();
ImGui::End();
if (show_props) {
ImGui::Begin("Properties", &show_props);
ImGui::Text("Details");
ImGui::Separator();
ImGui::End();
}
// Bottom panel
ImGui::Begin("Log");
ImGui::Text("Output / Log");
ImGui::Separator();
ImGui::End();
if (show_log) {
ImGui::Begin("Log", &show_log);
ImGui::Text("Output / Log");
ImGui::Separator();
ImGui::End();
}
// Demo window
if (show_demo)

View File

@@ -11,8 +11,22 @@ struct PlatformWindowDesc {
int32_t height = 720;
};
struct PlatformMenuItem {
const char *label; // nullptr = separator
int32_t id; // command ID (ignored for separators)
};
struct PlatformMenu {
const char *label;
PlatformMenuItem *items;
int32_t item_count;
};
PlatformWindow *platform_create_window(PlatformWindowDesc *desc);
void platform_destroy_window(PlatformWindow *window);
bool platform_poll_events(PlatformWindow *window);
void platform_get_size(PlatformWindow *window, int32_t *w, int32_t *h);
void *platform_get_native_handle(PlatformWindow *window);
void platform_set_menu(PlatformWindow *window, PlatformMenu *menus, int32_t menu_count);
int32_t platform_poll_menu_command(PlatformWindow *window);

View File

@@ -15,6 +15,7 @@ struct PlatformWindow {
bool should_close;
int32_t width;
int32_t height;
int32_t pending_menu_cmd;
};
static PlatformWindow *g_current_window = nullptr;
@@ -31,6 +32,10 @@ static LRESULT CALLBACK win32_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
g_current_window->height = (int32_t)HIWORD(lparam);
}
return 0;
case WM_COMMAND:
if (g_current_window && HIWORD(wparam) == 0)
g_current_window->pending_menu_cmd = (int32_t)LOWORD(wparam);
return 0;
case WM_CLOSE:
if (g_current_window)
g_current_window->should_close = true;
@@ -133,3 +138,40 @@ void *platform_get_native_handle(PlatformWindow *window)
{
return (void *)window->hwnd;
}
void platform_set_menu(PlatformWindow *window, PlatformMenu *menus, int32_t menu_count)
{
HMENU menu_bar = CreateMenu();
for (int32_t i = 0; i < menu_count; i++) {
HMENU submenu = CreatePopupMenu();
for (int32_t j = 0; j < menus[i].item_count; j++) {
PlatformMenuItem *item = &menus[i].items[j];
if (!item->label) {
AppendMenuW(submenu, MF_SEPARATOR, 0, nullptr);
} else {
int wchar_count = MultiByteToWideChar(CP_UTF8, 0, item->label, -1, nullptr, 0);
wchar_t *wlabel = (wchar_t *)_malloca(wchar_count * sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, item->label, -1, wlabel, wchar_count);
AppendMenuW(submenu, MF_STRING, (UINT_PTR)item->id, wlabel);
_freea(wlabel);
}
}
int wchar_count = MultiByteToWideChar(CP_UTF8, 0, menus[i].label, -1, nullptr, 0);
wchar_t *wlabel = (wchar_t *)_malloca(wchar_count * sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, menus[i].label, -1, wlabel, wchar_count);
AppendMenuW(menu_bar, MF_POPUP, (UINT_PTR)submenu, wlabel);
_freea(wlabel);
}
SetMenu(window->hwnd, menu_bar);
}
int32_t platform_poll_menu_command(PlatformWindow *window)
{
int32_t cmd = window->pending_menu_cmd;
window->pending_menu_cmd = 0;
return cmd;
}