imgui icon indicating copy to clipboard operation
imgui copied to clipboard

Custom tab bar, and button in front of tabs.

Open Luci404 opened this issue 2 years ago • 5 comments

Version/Branch of Dear ImGui: Version: 1.88 Branch: docking

Back-end/Renderer/Compiler/OS: Back-ends: imgui_impl_glfw.cpp + imgui_impl_opengl3.cpp Compiler: Microsoft C++ compiler (CL.exe) Operating System: Windows 10

My Issue/Question: We are doing a UI overhaul on our internal game engine. The UI design folks came up with some pretty nice looking workspace tab bar design, but I have no idea how to implement it? We really like the default docking behavior of ImGui but we need a way to separate workspace. So what we want to do is, like unreal, having main workspace windows facilitating one workflow made up of multiple smaller tool windows.

My main question is how i style and draw this kind of menu bars, specifically, how do i get the red button in at the start of the bar and offset the tabs to make space for it? I believe the rest of the style can be obtained with setting imgui style setting, but where should this be done?

Luci404 avatar May 23 '22 18:05 Luci404

You can't currently customize the docking tab bar in this way.

What I'd probably do is modify DockNodeUpdateTabBar to replace the default dock menu button (pictured below) with your special button.

Screenshot of Dear ImGui's default dock menu button.

The button is specifically submitted here:

https://github.com/ocornut/imgui/blob/250333d895b1067533533dcfab137512745b9689/imgui.cpp#L15291-L15298

Given your mockup I'm assuming you'd be disabling this button either way. It'd be easier to replace the button rather than disable it and add your own since disabling it entirely means you have to fiddle with the layout stuff in DockNodeUpdateTabBar.

(If you want your logo button to appear everywhere you probably want to edit RenderWindowTitleBarContents too since it's still used for free-floating windows. Or hijack to CollapseButton submit your button instead and always return false.)

If you plan to disable the dock menu/collapse button everywhere else, set ImGuiStyle::WindowMenuButtonPosition to ImGuiDir_Left when you submit your ImGui::DockSpace and ImGuiDir_None otherwise.

PathogenDavid avatar May 23 '22 21:05 PathogenDavid

We have two mecanisms which could be eventually toward that:

  • It is possible to append to an existing tab bar using BeginTabBar()
  • BeginTabItem() has support for ImGuiTabItemFlags_Leading and ImGuiTabItemFlags_Trailing flag has well as there is a TabItemButton() function. I believe the later could be reworked into a way to request leading/trailing space.

ocornut avatar May 23 '22 21:05 ocornut

@PathogenDavid This is interesting, I haven't tough of hijacking CollapseButton - that might actually be the play here. It could properly be done with some #define overrides on include, I'll have to look into that.

How would you do it to avoid changing the ImGui source directly (I keep it as a git submodule)?

Luci404 avatar May 24 '22 11:05 Luci404

How would you do it to avoid changing the ImGui source directly (I keep it as a git submodule)?

I'd recommend just doing a fork via GitHub and pointing your submodule to that instead. GitHub makes it pretty easy to keep it up to date with upstream:

Screenshot of GitHub UI for fetching upstream changes in a fork.

I can think of ways to avoid the fork using preprocessor shenanigans, but they'd be pretty brittle and I think they'd just be a needless source of confusion down the line.

PathogenDavid avatar May 24 '22 13:05 PathogenDavid

We have two mecanisms which could be eventually toward that:

* It is possible to append to an existing tab bar using `BeginTabBar()`

* `BeginTabItem()` has support for `ImGuiTabItemFlags_Leading` and `ImGuiTabItemFlags_Trailing` flag has well as there is a `TabItemButton()` function. I believe the later could be reworked into a way to request leading/trailing space.

Would you be able to provide an example on how this would work in the context of a dockspace tab bar?

This looks promising, but input is not working.

ImGuiID dockspace_id = ImGui::GetID("DockSpace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags, window_class);

ImGuiDockNode* node = (ImGuiDockNode*)GImGui->DockContext.Nodes.GetVoidPtr(dockspace_id);
if (node && node->TabBar)
{
   ImGui::TabItemEx(node->TabBar, "X", nullptr, ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Button | ImGuiTabItemFlags_NoReorder, nullptr);
   ImGui::TabItemEx(node->TabBar, "Trailing", nullptr, ImGuiTabItemFlags_Trailing | ImGuiTabItemFlags_Button | ImGuiTabItemFlags_NoReorder, nullptr);
}

I don't really see how I would use BeginTabBar when I only have a ImGuiDockNode*, no string id. BeginTabBarEx crashes since I can't close it without setting an ID (tab_bar->ID = id;), it seems; and I'm not sure where to get ID from since it's locked behind the DockSpace's internal code?..

Luci404 avatar Jul 18 '22 18:07 Luci404

Would you be able to provide an example on how this would work in the context of a dockspace tab bar?

FYI I think you figured this out as per your post #5515 but to answer this: DockNodeBeginAmendTabBar()/``DockNodeEndAmendTabBar()` can be used.

ocornut avatar Jan 24 '23 18:01 ocornut