Combo() now using the popup facility. More consistent + when combo open hovering other widgets is disabled. (#241)

This commit is contained in:
ocornut 2015-06-09 12:35:55 -06:00
parent 6f1dd7a688
commit 8c86322068

View File

@ -1301,7 +1301,6 @@ struct ImGuiState
ImGuiTextEditState InputTextState;
ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc.
ImGuiStorage ColorEditModeStorage; // Store user selection of color edit mode
ImGuiID ActiveComboID;
ImVec2 ActiveClickDeltaToCenter;
float DragCurrentValue; // current dragged value, always float, not rounded by end-user precision settings
ImVec2 DragLastMouseDelta;
@ -1362,7 +1361,6 @@ struct ImGuiState
SetNextTreeNodeOpenedCond = 0;
ScalarAsInputTextId = 0;
ActiveComboID = 0;
ActiveClickDeltaToCenter = ImVec2(0.0f, 0.0f);
DragCurrentValue = 0.0f;
DragLastMouseDelta = ImVec2(0.0f, 0.0f);
@ -3126,6 +3124,14 @@ static void ClosePopupToLevel(int remaining)
g.OpenedPopupStack.resize(remaining);
}
static void ClosePopup(ImGuiID id)
{
if (!IsPopupOpen(id))
return;
ImGuiState& g = *GImGui;
ClosePopupToLevel(g.OpenedPopupStack.size() - 1);
}
// Close the popup we have begin-ed into.
void ImGui::CloseCurrentPopup()
{
@ -3156,7 +3162,7 @@ static bool BeginPopupEx(const char* str_id, ImGuiWindowFlags extra_flags)
}
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_ShowBorders|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize;
ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize;
char name[32];
if (flags & ImGuiWindowFlags_ChildMenu)
@ -3176,7 +3182,7 @@ static bool BeginPopupEx(const char* str_id, ImGuiWindowFlags extra_flags)
bool ImGui::BeginPopup(const char* str_id)
{
return BeginPopupEx(str_id, 0);
return BeginPopupEx(str_id, ImGuiWindowFlags_ShowBorders);
}
void ImGui::EndPopup()
@ -7288,7 +7294,7 @@ bool ImGui::Combo(const char* label, int* current_item, const char** items, int
bool ImGui::Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items)
{
int items_count = 0;
const char* p = items_separated_by_zeros; // FIXME-OPT: Avoid computing this
const char* p = items_separated_by_zeros; // FIXME-OPT: Avoid computing this, or at least only when combo is open
while (*p)
{
p += strlen(p) + 1;
@ -7320,7 +7326,6 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi
const float arrow_size = (g.FontSize + style.FramePadding.x * 2.0f);
const bool hovered = IsHovered(frame_bb, id);
bool value_changed = false;
const ImRect value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f));
RenderFrame(frame_bb.Min, frame_bb.Max, window->Color(ImGuiCol_FrameBg), true, style.FrameRounding);
RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, window->Color(hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING
@ -7336,42 +7341,45 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi
if (label_size.x > 0)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
ImGui::PushID((int)id);
bool menu_toggled = false;
if (hovered)
{
g.HoveredId = id;
if (g.IO.MouseClicked[0])
{
menu_toggled = true;
SetActiveId(0);
g.ActiveComboID = (g.ActiveComboID == id) ? 0 : id;
if (g.ActiveComboID)
if (IsPopupOpen(id))
{
ClosePopup(id);
}
else
{
FocusWindow(window);
ImGui::OpenPopup(label);
menu_toggled = true;
}
}
}
if (g.ActiveComboID == id)
bool value_changed = false;
if (IsPopupOpen(id))
{
// Size default to hold ~7 items
if (height_in_items < 0)
height_in_items = 7;
const ImVec2 backup_pos = ImGui::GetCursorPos();
const float popup_off_x = 0.0f;//style.ItemInnerSpacing.x;
const float popup_height = (label_size.y + style.ItemSpacing.y) * ImMin(items_count, height_in_items) + (style.FramePadding.y * 3);
const ImRect popup_rect(ImVec2(frame_bb.Min.x+popup_off_x, frame_bb.Max.y), ImVec2(frame_bb.Max.x+popup_off_x, frame_bb.Max.y + popup_height));
ImGui::SetCursorPos(popup_rect.Min - window->Pos);
const ImRect popup_rect(ImVec2(frame_bb.Min.x, frame_bb.Max.y), ImVec2(frame_bb.Max.x, frame_bb.Max.y + popup_height));
ImGui::SetNextWindowPos(popup_rect.Min);
ImGui::SetNextWindowSize(popup_rect.GetSize());
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding);
const ImGuiWindowFlags flags = ImGuiWindowFlags_ComboBox | ((window->Flags & ImGuiWindowFlags_ShowBorders) ? ImGuiWindowFlags_ShowBorders : 0);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding);
ImGui::BeginChild("#ComboBox", popup_rect.GetSize(), false, flags);
ImGui::Spacing();
bool combo_item_active = false;
combo_item_active |= (g.ActiveId == GetCurrentWindow()->GetID("#SCROLLY"));
if (BeginPopupEx(label, flags))
{
// Display items
ImGui::Spacing();
for (int i = 0; i < items_count; i++)
{
ImGui::PushID((void*)(intptr_t)i);
@ -7382,25 +7390,17 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi
if (ImGui::Selectable(item_text, item_selected))
{
SetActiveId(0);
g.ActiveComboID = 0;
value_changed = true;
*current_item = i;
}
if (item_selected && menu_toggled)
ImGui::SetScrollPosHere();
combo_item_active |= ImGui::IsItemActive();
ImGui::PopID();
}
ImGui::EndChild();
ImGui::EndPopup();
}
ImGui::PopStyleVar();
ImGui::SetCursorPos(backup_pos);
if (!combo_item_active && g.ActiveId != 0)
g.ActiveComboID = 0;
}
ImGui::PopID();
return value_changed;
}
@ -7769,7 +7769,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
if (opened)
{
ImGui::SetNextWindowPos(popup_pos, ImGuiSetCond_Always);
ImGuiWindowFlags flags = (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) ? ImGuiWindowFlags_ChildMenu|ImGuiWindowFlags_ChildWindow : ImGuiWindowFlags_ChildMenu;
ImGuiWindowFlags flags = ImGuiWindowFlags_ShowBorders | ((window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) ? ImGuiWindowFlags_ChildMenu|ImGuiWindowFlags_ChildWindow : ImGuiWindowFlags_ChildMenu);
opened = BeginPopupEx(label, flags); // opened can be 'false' when the popup is completely clipped (e.g. zero size display)
}