ocornut / imgui

Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
MIT License
60.84k stars 10.28k forks source link

ImGuiTabItemFlags_SetSelected only affects the next frame, always renders first tab once. #6681

Open aardappel opened 1 year ago

aardappel commented 1 year ago
Dear ImGui 1.89.7 (18971)
--------------------------------
sizeof(size_t): 8, sizeof(ImDrawIdx): 2, sizeof(ImDrawVert): 20
define: __cplusplus=199711
define: _WIN32
define: _WIN64
define: _MSC_VER=1936
define: _MSVC_LANG=202004
define: IMGUI_HAS_VIEWPORT
define: IMGUI_HAS_DOCK
--------------------------------
io.BackendPlatformName: imgui_impl_sdl2
io.BackendRendererName: imgui_impl_opengl3
io.ConfigFlags: 0x00000040
 DockingEnable
io.ConfigViewportsNoDecoration
io.ConfigInputTextCursorBlink
io.ConfigWindowsResizeFromEdges
io.ConfigMemoryCompactTimer = 60.0
io.BackendFlags: 0x00001C0E
 HasMouseCursors
 HasSetMousePos
 PlatformHasViewports
 HasMouseHoveredViewport
 RendererHasVtxOffset
 RendererHasViewports
--------------------------------
io.Fonts: 1 fonts, Flags: 0x00000000, TexSize: 512,256
io.DisplaySize: 1600.00,1280.00
io.DisplayFramebufferScale: 1.00,1.00
--------------------------------
style.WindowPadding: 8.00,8.00
style.WindowBorderSize: 1.00
style.FramePadding: 4.00,3.00
style.FrameRounding: 3.00
style.FrameBorderSize: 0.00
style.ItemSpacing: 8.00,4.00
style.ItemInnerSpacing: 4.00,4.00

My Issue/Question:

ImGuiTabItemFlags_SetSelected on a tab doesn't apply to the frame it is specified on, but gets Q-ed up for the next one.

When my app starts, I am trying to show tab 3, but instead it flashes tab 1 for 1 frame, which is very visible because these tabs may contained color images. It looks a bit like a "rendering glitch".

It's super minor, and completely understandable way to implement tab selection, but if at all possible, switching to the tab on the frame it is requested would result in a more slick looking UI, especially in cases where the tabs come into view as a consequence of wanting to show a tab that's not the first one.

Or, maybe there is a way to force the active tab before they come into view?

GamingMinds-DanielC commented 1 year ago

The problem is most likely that your first tab is open when it is committed (ImGui doesn't know about the third one ahead of time), gets its items committed and then you switch to the third tab when you send that one for the first time.

Take a look at SetTabItemClosed, that should solve your issue.

ocornut commented 1 year ago

switching to the tab on the frame it is requested would result in a more slick looking UI,

It's not possible via this exact ImGuiTabItemFlags_SetSelected mechanism as previous tabs that were already submitted prior to the one with ImGuiTabItemFlags_SetSelected may have already returned true and emitted logic/output into the window.

Internally we have a TabBarQueueFocus(ImGuiTabBar* tab_bar, ImGuiTabItem* tab) but that requires the tab to have been created already which doesn't work in your case. I think we can come up with a function that does the right thing if called right after BeginTabBar(), using logic similar to SetTabItemClosed() to calculate tab_id based on name alone and queueing that so it gets processed in TabBarLayout(). Requires some work but it's not a priority at the moment.

aardappel commented 1 year ago

Yes, simply specifying the tab index ahead of submitting them is the kind of API I was wanting all along :)

ocornut commented 1 year ago

It wouldn’t be by index but by identifier and needs to work before the first creation of the tab.

Are you always selecting the third tab or are you actually attempting to save/restore tab-bar state in eg the ini file?

aardappel commented 1 year ago

Identifier would work too.

I am currently always selecting a fixed tab on startup. This is the "help" tab so while it should be shown the first time, I want it to be the last tab in normal usage (otherwise making it the first tab would have been an easy solution).

ocornut commented 4 weeks ago

I have pushed a variant of TabBarQueueFocus() that takes a name: 655fcf8 It doesn't work on docking tab-bar created by the docking system, only manual tab bar so far.