From 0d56140b4a71f3e68643d1af9139c8d61a8857c1 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 25 Sep 2017 21:45:34 +0200 Subject: [PATCH] BeginCombo(): rework internals a little to make it easier to provide custom combo-like elements relying in BeginCombo(). BeginPopupEx() doesn't enforce AlwaysAutoResize flag anymore. --- TODO.txt | 3 ++- imgui.cpp | 31 +++++++++++++++++++------------ imgui_internal.h | 2 +- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/TODO.txt b/TODO.txt index bddf473c5..0369c6374 100644 --- a/TODO.txt +++ b/TODO.txt @@ -99,7 +99,8 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - plot: option/feature: draw unit - plot: add a helper e.g. Plot(char* label, float value, float time_span=2.0f) that stores values and Plot them for you - probably another function name. and/or automatically allow to plot ANY displayed value (more reliance on stable ID) - - clipper: ability to force display 1 item in the list would be convenient. + - clipper: ability to force display 1 item in the list would be convenient (for patterns where we need to set active id etc.) + - clipper: ability to disable the clipping through a simple flag/bool. - clipper: ability to run without knowing full count in advance. - splitter/separator: formalize the splitter idiom into an official api (we want to handle n-way split) (#319) diff --git a/imgui.cpp b/imgui.cpp index f7cda6712..88d0fcbbd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3569,7 +3569,7 @@ bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags) } PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); - ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize; + ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings; char name[20]; if (flags & ImGuiWindowFlags_ChildMenu) @@ -3594,7 +3594,7 @@ bool ImGui::BeginPopup(const char* str_id) ClearSetNextWindowData(); // We behave like Begin() and need to consume those values return false; } - return BeginPopupEx(g.CurrentWindow->GetID(str_id), ImGuiWindowFlags_ShowBorders); + return BeginPopupEx(g.CurrentWindow->GetID(str_id), ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_AlwaysAutoResize); } bool ImGui::IsPopupOpen(ImGuiID id) @@ -8602,7 +8602,7 @@ bool ImGui::Combo(const char* label, int* current_item, const char* items_separa return value_changed; } -bool ImGui::BeginCombo(const char* label, const char* preview_value, float popup_opened_height) +bool ImGui::BeginCombo(const char* label, const char* preview_value, ImVec2 popup_size) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -8662,17 +8662,24 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, float popup if (!popup_open) return false; + if (popup_size.x == 0.0f) + popup_size.x = w; + float popup_y1 = frame_bb.Max.y; - float popup_y2 = ImClamp(popup_y1 + popup_opened_height, popup_y1, g.IO.DisplaySize.y - style.DisplaySafeAreaPadding.y); - if ((popup_y2 - popup_y1) < ImMin(popup_opened_height, frame_bb.Min.y - style.DisplaySafeAreaPadding.y)) + float popup_y2 = ImClamp(popup_y1 + popup_size.y, popup_y1, g.IO.DisplaySize.y - style.DisplaySafeAreaPadding.y); + if ((popup_y2 - popup_y1) < ImMin(popup_size.y, frame_bb.Min.y - style.DisplaySafeAreaPadding.y)) { // Position our combo ABOVE because there's more space to fit! (FIXME: Handle in Begin() or use a shared helper. We have similar code in Begin() for popup placement) - popup_y1 = ImClamp(frame_bb.Min.y - popup_opened_height, style.DisplaySafeAreaPadding.y, frame_bb.Min.y); + popup_y1 = ImClamp(frame_bb.Min.y - popup_size.y, style.DisplaySafeAreaPadding.y, frame_bb.Min.y); popup_y2 = frame_bb.Min.y; + SetNextWindowPos(ImVec2(frame_bb.Min.x, frame_bb.Min.y), ImGuiCond_Always, ImVec2(0.0f, 1.0f)); } - ImRect popup_rect(ImVec2(frame_bb.Min.x, popup_y1), ImVec2(frame_bb.Max.x, popup_y2)); - SetNextWindowPos(popup_rect.Min); - SetNextWindowSize(popup_rect.GetSize()); + else + { + // Position our combo below + SetNextWindowPos(ImVec2(frame_bb.Min.x, frame_bb.Max.y), ImGuiCond_Always, ImVec2(0.0f, 0.0f)); + } + SetNextWindowSize(ImVec2(popup_size.x, popup_y2 - popup_y1), ImGuiCond_Appearing); PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding); const ImGuiWindowFlags flags = ImGuiWindowFlags_ComboBox | ((window->Flags & ImGuiWindowFlags_ShowBorders) ? ImGuiWindowFlags_ShowBorders : 0); @@ -8705,9 +8712,9 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi // Size default to hold ~7 items if (height_in_items < 0) height_in_items = 7; - float popup_opened_height = (g.FontSize + style.ItemSpacing.y) * ImMin(items_count, height_in_items) + (style.FramePadding.y * 3); + float popup_height = (g.FontSize + style.ItemSpacing.y) * ImMin(items_count, height_in_items) + (style.FramePadding.y * 3); - if (!BeginCombo(label, preview_text, popup_opened_height)) + if (!BeginCombo(label, preview_text, ImVec2(0.0f, popup_height))) return false; // Display items @@ -9119,7 +9126,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) if (menu_is_open) { SetNextWindowPos(popup_pos, ImGuiCond_Always); - ImGuiWindowFlags flags = ImGuiWindowFlags_ShowBorders | ((window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) ? ImGuiWindowFlags_ChildMenu|ImGuiWindowFlags_ChildWindow : ImGuiWindowFlags_ChildMenu); + ImGuiWindowFlags flags = ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_AlwaysAutoResize | ((window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) ? ImGuiWindowFlags_ChildMenu|ImGuiWindowFlags_ChildWindow : ImGuiWindowFlags_ChildMenu); menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) } diff --git a/imgui_internal.h b/imgui_internal.h index 8f6762bde..63bbb0437 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -788,7 +788,7 @@ namespace ImGui IMGUI_API void PushColumnClipRect(int column_index = -1); // FIXME-WIP: New Combo API - IMGUI_API bool BeginCombo(const char* label, const char* preview_value, float popup_opened_height); + IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImVec2 popup_size = ImVec2(0.0f,0.0f)); IMGUI_API void EndCombo(); // NB: All position are in absolute pixels coordinates (never using window coordinates internally)