WIP Menus: click again to toggle + allow hovering in same menuset even outside of a menubar (#126)

This commit is contained in:
ocornut 2015-05-18 19:12:36 +01:00
parent 75ec4841df
commit 9bdacaf08d

View File

@ -3018,18 +3018,33 @@ void ImGui::EndTooltip()
ImGui::End(); ImGui::End();
} }
static bool IsPopupOpen(ImGuiID id)
{
ImGuiState& g = *GImGui;
const bool opened = g.OpenedPopupStack.size() > g.CurrentPopupStack.size() && g.OpenedPopupStack[g.CurrentPopupStack.size()].PopupID == id;
return opened;
}
// One open popup per level of the popup hierarchy (NB: when assigning we reset the Window member of ImGuiPopupRef to NULL)
void ImGui::OpenPopup(const char* str_id) void ImGui::OpenPopup(const char* str_id)
{ {
ImGuiState& g = *GImGui; ImGuiState& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
const ImGuiID id = window->GetID(str_id); const ImGuiID id = window->GetID(str_id);
// One open popup per level of the popup hierarchy (NB: when assigning we reset the Window member of ImGuiPopupRef to NULL)
g.OpenedPopupStack.resize(g.CurrentPopupStack.size() + 1); g.OpenedPopupStack.resize(g.CurrentPopupStack.size() + 1);
if (g.OpenedPopupStack.back().PopupID != id) if (g.OpenedPopupStack.back().PopupID != id)
g.OpenedPopupStack.back() = ImGuiPopupRef(id, window, window->GetID("##menus")); g.OpenedPopupStack.back() = ImGuiPopupRef(id, window, window->GetID("##menus"));
} }
static void ClosePopup(const char* str_id) // not exposed because 'id' scope is misleading
{
ImGuiState& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow();
const ImGuiID id = window->GetID(str_id);
if (IsPopupOpen(id))
g.OpenedPopupStack.resize(g.CurrentPopupStack.size());
}
void ImGui::CloseCurrentPopup() void ImGui::CloseCurrentPopup()
{ {
ImGuiState& g = *GImGui; ImGuiState& g = *GImGui;
@ -3048,13 +3063,6 @@ static void CloseAllPopups()
g.OpenedPopupStack.resize(0); g.OpenedPopupStack.resize(0);
} }
static bool IsPopupOpen(ImGuiID id)
{
ImGuiState& g = *GImGui;
const bool opened = g.OpenedPopupStack.size() > g.CurrentPopupStack.size() && g.OpenedPopupStack[g.CurrentPopupStack.size()].PopupID == id;
return opened;
}
static bool BeginPopupEx(const char* str_id, ImGuiWindowFlags extra_flags) static bool BeginPopupEx(const char* str_id, ImGuiWindowFlags extra_flags)
{ {
ImGuiState& g = *GImGui; ImGuiState& g = *GImGui;
@ -3072,11 +3080,10 @@ static bool BeginPopupEx(const char* str_id, ImGuiWindowFlags extra_flags)
else else
ImFormatString(name, 20, "##popup_%08x", id); // Not recycling, so we can close/open during the same frame ImFormatString(name, 20, "##popup_%08x", id); // Not recycling, so we can close/open during the same frame
float alpha = 1.0f; float alpha = 1.0f;
bool opened = ImGui::Begin(name, NULL, ImVec2(0.0f, 0.0f), alpha, flags);
bool opened = ImGui::Begin(name, NULL, ImVec2(0.0f, 0.0f), alpha, flags);
if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) if (!(window->Flags & ImGuiWindowFlags_ShowBorders))
GetCurrentWindow()->Flags &= ~ImGuiWindowFlags_ShowBorders; GetCurrentWindow()->Flags &= ~ImGuiWindowFlags_ShowBorders;
if (!opened) // opened can be 'false' when the popup is completely clipped (e.g. zero size display) if (!opened) // opened can be 'false' when the popup is completely clipped (e.g. zero size display)
ImGui::EndPopup(); ImGui::EndPopup();
@ -7484,7 +7491,6 @@ void ImGui::EndMenuBar()
ImGui::PopID(); ImGui::PopID();
} }
// FIXME-WIP: v1.39 in development, API *WILL* change!
bool ImGui::BeginMenu(const char* label) bool ImGui::BeginMenu(const char* label)
{ {
ImGuiState& g = *GImGui; ImGuiState& g = *GImGui;
@ -7494,16 +7500,18 @@ bool ImGui::BeginMenu(const char* label)
const ImGuiStyle& style = g.Style; const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID(label); const ImGuiID id = window->GetID(label);
bool opened = IsPopupOpen(id);
ImVec2 pos; ImVec2 pos;
ImVec2 popup_pos; ImVec2 popup_pos;
ImVec2 backup_pos = window->DC.CursorPos;
ImVec2 label_size = CalcTextSize(label, NULL, true); ImVec2 label_size = CalcTextSize(label, NULL, true);
ImVec2 backup_pos = window->DC.CursorPos;
ImGuiWindow* backed_focused_window = g.FocusedWindow;
bool pressed; bool pressed;
bool active_menuset = false; bool opened = IsPopupOpen(id);
ImGuiWindow* focused_window_backup = g.FocusedWindow; bool menuset_opened = (g.OpenedPopupStack.size() > g.CurrentPopupStack.size() && g.OpenedPopupStack[g.CurrentPopupStack.size()].ParentMenuSet == window->GetID("##menus"));
if (menuset_opened)
g.FocusedWindow = window;
if (window->DC.MenuBarAppending) if (window->DC.MenuBarAppending)
{ {
@ -7511,14 +7519,8 @@ bool ImGui::BeginMenu(const char* label)
pos = window->DC.CursorPos = ImVec2(window->Pos.x + window->DC.MenuBarOffsetX, window->Pos.y + window->TitleBarHeight() + style.FramePadding.y); pos = window->DC.CursorPos = ImVec2(window->Pos.x + window->DC.MenuBarOffsetX, window->Pos.y + window->TitleBarHeight() + style.FramePadding.y);
popup_pos = ImVec2(pos.x - style.ItemSpacing.x, pos.y); popup_pos = ImVec2(pos.x - style.ItemSpacing.x, pos.y);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing * 2.0f); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing * 2.0f);
active_menuset = (g.OpenedPopupStack.size() > g.CurrentPopupStack.size() && g.OpenedPopupStack[g.CurrentPopupStack.size()].ParentMenuSet == window->GetID("##menus"));
if (active_menuset)
g.FocusedWindow = NULL;
float w = label_size.x; float w = label_size.x;
pressed = SelectableEx(label, opened, ImVec2(w, 0.0f), ImVec2(w, 0.0f), true); pressed = SelectableEx(label, opened, ImVec2(w, 0.0f), ImVec2(w, 0.0f), true);
window->DC.MenuBarOffsetX += (label_size.x + style.ItemSpacing.x); window->DC.MenuBarOffsetX += (label_size.x + style.ItemSpacing.x);
window->DC.CursorPos = backup_pos; window->DC.CursorPos = backup_pos;
ImGui::PopStyleVar(); ImGui::PopStyleVar();
@ -7534,8 +7536,8 @@ bool ImGui::BeginMenu(const char* label)
} }
bool hovered = IsHovered(window->DC.LastItemRect, id); bool hovered = IsHovered(window->DC.LastItemRect, id);
if (active_menuset) if (menuset_opened)
g.FocusedWindow = focused_window_backup; g.FocusedWindow = backed_focused_window;
if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu))
{ {
@ -7547,7 +7549,12 @@ bool ImGui::BeginMenu(const char* label)
} }
else else
{ {
if (active_menuset) if (menuset_opened && pressed)
{
ClosePopup(label);
opened = pressed = false;
}
else if (menuset_opened)
pressed |= hovered; pressed |= hovered;
else else
pressed |= (hovered && !g.OpenedPopupStack.empty() && g.OpenedPopupStack.back().PopupID != id && g.OpenedPopupStack.back().ParentWindow == window); pressed |= (hovered && !g.OpenedPopupStack.empty() && g.OpenedPopupStack.back().PopupID != id && g.OpenedPopupStack.back().ParentWindow == window);