window->DC.CursorPos.x+=(float)(int)(style.ItemSpacing.x*(-1.0f+0.5f));// -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
// We don't clip with current window clipping rectangle as it is already set to the area below. However we clip with window full rect.
// We remove 1 worth of rounding to Max.x to that text in long menus and small windows don't tend to display over the lower-right rounded area, which looks particularly glitchy.
// To do so we claim focus back, restore NavId and then process the movement request for yet another frame.
// This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth the hassle/cost)
window->DC.MenuBarOffset.x=window->DC.CursorPos.x-window->MenuBarRect().Min.x;// Save horizontal position so next append can reuse it. This is kinda equivalent to a per-layer CursorPos.
g.NavWindow=window;// Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent)
// The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu (using FindBestWindowPosForPopup).
window->DC.CursorPos.x+=(float)(int)(style.ItemSpacing.x*(-1.0f+0.5f));// -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
floatextra=ImClamp(ImFabs(ta.x-tb.x)*0.30f,5.0f,30.0f);// add a bit of extra slack.
ta.x+=(window->Pos.x<next_window->Pos.x)?-0.5f:+0.5f;// to avoid numerical issues
tb.y=ta.y+ImMax((tb.y-extra)-ta.y,-100.0f);// triangle is maximum 200 high to limit the slope and the bias toward large sub-menus // FIXME: Multiply by fb_scale?
if(g.NavId==id&&g.NavMoveRequest&&g.NavMoveDir==ImGuiDir_Right)// Nav-Right to open
{
want_open=true;
NavMoveRequestCancel();
}
}
else
{
// Menu bar
if(menu_is_open&&pressed&&menuset_is_open)// Click an open menu again to close it
{
want_close=true;
want_open=menu_is_open=false;
}
elseif(pressed||(hovered&&menuset_is_open&&!menu_is_open))// First click to open, then hover to open others
{
want_open=true;
}
elseif(g.NavId==id&&g.NavMoveRequest&&g.NavMoveDir==ImGuiDir_Down)// Nav-Down to open
{
want_open=true;
NavMoveRequestCancel();
}
}
if(!enabled)// explicitly close if an open menu becomes disabled, facilitate users code a lot in pattern such as 'if (BeginMenu("options", has_object)) { ..use object.. }'
// Don't recycle same menu level in the same frame, first close the other menu and yield for a frame.
OpenPopup(label);
returnfalse;
}
menu_is_open|=want_open;
if(want_open)
OpenPopup(label);
if(menu_is_open)
{
// Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu)
// We don't clip with current window clipping rectangle as it is already set to the area below. However we clip with window full rect.
// We remove 1 worth of rounding to Max.x to that text in long menus and small windows don't tend to display over the lower-right rounded area, which looks particularly glitchy.
// To do so we claim focus back, restore NavId and then process the movement request for yet another frame.
// This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth the hassle/cost)
window->DC.MenuBarOffset.x=window->DC.CursorPos.x-window->MenuBarRect().Min.x;// Save horizontal position so next append can reuse it. This is kinda equivalent to a per-layer CursorPos.
g.NavWindow=window;// Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent)
// The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu (using FindBestWindowPosForPopup).
window->DC.CursorPos.x+=(float)(int)(style.ItemSpacing.x*(-1.0f+0.5f));// -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
floatextra=ImClamp(ImFabs(ta.x-tb.x)*0.30f,5.0f,30.0f);// add a bit of extra slack.
ta.x+=(window->Pos.x<next_window->Pos.x)?-0.5f:+0.5f;// to avoid numerical issues
tb.y=ta.y+ImMax((tb.y-extra)-ta.y,-100.0f);// triangle is maximum 200 high to limit the slope and the bias toward large sub-menus // FIXME: Multiply by fb_scale?
if(g.NavId==id&&g.NavMoveRequest&&g.NavMoveDir==ImGuiDir_Right)// Nav-Right to open
{
want_open=true;
NavMoveRequestCancel();
}
}
else
{
// Menu bar
if(menu_is_open&&pressed&&menuset_is_open)// Click an open menu again to close it
{
want_close=true;
want_open=menu_is_open=false;
}
elseif(pressed||(hovered&&menuset_is_open&&!menu_is_open))// First click to open, then hover to open others
{
want_open=true;
}
elseif(g.NavId==id&&g.NavMoveRequest&&g.NavMoveDir==ImGuiDir_Down)// Nav-Down to open
{
want_open=true;
NavMoveRequestCancel();
}
}
if(!enabled)// explicitly close if an open menu becomes disabled, facilitate users code a lot in pattern such as 'if (BeginMenu("options", has_object)) { ..use object.. }'
// Don't recycle same menu level in the same frame, first close the other menu and yield for a frame.
OpenPopup(label);
returnfalse;
}
menu_is_open|=want_open;
if(want_open)
OpenPopup(label);
if(menu_is_open)
{
// Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu)
window->DC.CursorPos.x+=(float)(int)(style.ItemSpacing.x*(-1.0f+0.5f));// -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().