1
0
mirror of https://github.com/ocornut/imgui.git synced 2025-01-18 01:06:45 +01:00

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; ImGuiTextEditState InputTextState;
ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc. ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc.
ImGuiStorage ColorEditModeStorage; // Store user selection of color edit mode ImGuiStorage ColorEditModeStorage; // Store user selection of color edit mode
ImGuiID ActiveComboID;
ImVec2 ActiveClickDeltaToCenter; ImVec2 ActiveClickDeltaToCenter;
float DragCurrentValue; // current dragged value, always float, not rounded by end-user precision settings float DragCurrentValue; // current dragged value, always float, not rounded by end-user precision settings
ImVec2 DragLastMouseDelta; ImVec2 DragLastMouseDelta;
@ -1362,7 +1361,6 @@ struct ImGuiState
SetNextTreeNodeOpenedCond = 0; SetNextTreeNodeOpenedCond = 0;
ScalarAsInputTextId = 0; ScalarAsInputTextId = 0;
ActiveComboID = 0;
ActiveClickDeltaToCenter = ImVec2(0.0f, 0.0f); ActiveClickDeltaToCenter = ImVec2(0.0f, 0.0f);
DragCurrentValue = 0.0f; DragCurrentValue = 0.0f;
DragLastMouseDelta = ImVec2(0.0f, 0.0f); DragLastMouseDelta = ImVec2(0.0f, 0.0f);
@ -3126,6 +3124,14 @@ static void ClosePopupToLevel(int remaining)
g.OpenedPopupStack.resize(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. // Close the popup we have begin-ed into.
void ImGui::CloseCurrentPopup() void ImGui::CloseCurrentPopup()
{ {
@ -3156,7 +3162,7 @@ static bool BeginPopupEx(const char* str_id, ImGuiWindowFlags extra_flags)
} }
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); 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]; char name[32];
if (flags & ImGuiWindowFlags_ChildMenu) 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) bool ImGui::BeginPopup(const char* str_id)
{ {
return BeginPopupEx(str_id, 0); return BeginPopupEx(str_id, ImGuiWindowFlags_ShowBorders);
} }
void ImGui::EndPopup() 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) bool ImGui::Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items)
{ {
int items_count = 0; 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) while (*p)
{ {
p += strlen(p) + 1; 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 float arrow_size = (g.FontSize + style.FramePadding.x * 2.0f);
const bool hovered = IsHovered(frame_bb, id); 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)); 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(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 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,71 +7341,66 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi
if (label_size.x > 0) if (label_size.x > 0)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); 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; bool menu_toggled = false;
if (hovered) if (hovered)
{ {
g.HoveredId = id; g.HoveredId = id;
if (g.IO.MouseClicked[0]) if (g.IO.MouseClicked[0])
{ {
menu_toggled = true;
SetActiveId(0); SetActiveId(0);
g.ActiveComboID = (g.ActiveComboID == id) ? 0 : id; if (IsPopupOpen(id))
if (g.ActiveComboID) {
FocusWindow(window); 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 // Size default to hold ~7 items
if (height_in_items < 0) if (height_in_items < 0)
height_in_items = 7; height_in_items = 7;
const ImVec2 backup_pos = ImGui::GetCursorPos(); 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 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)); 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::SetCursorPos(popup_rect.Min - window->Pos); 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); const ImGuiWindowFlags flags = ImGuiWindowFlags_ComboBox | ((window->Flags & ImGuiWindowFlags_ShowBorders) ? ImGuiWindowFlags_ShowBorders : 0);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding); if (BeginPopupEx(label, flags))
ImGui::BeginChild("#ComboBox", popup_rect.GetSize(), false, flags);
ImGui::Spacing();
bool combo_item_active = false;
combo_item_active |= (g.ActiveId == GetCurrentWindow()->GetID("#SCROLLY"));
// Display items
for (int i = 0; i < items_count; i++)
{ {
ImGui::PushID((void*)(intptr_t)i); // Display items
const bool item_selected = (i == *current_item); ImGui::Spacing();
const char* item_text; for (int i = 0; i < items_count; i++)
if (!items_getter(data, i, &item_text))
item_text = "*Unknown item*";
if (ImGui::Selectable(item_text, item_selected))
{ {
SetActiveId(0); ImGui::PushID((void*)(intptr_t)i);
g.ActiveComboID = 0; const bool item_selected = (i == *current_item);
value_changed = true; const char* item_text;
*current_item = i; if (!items_getter(data, i, &item_text))
item_text = "*Unknown item*";
if (ImGui::Selectable(item_text, item_selected))
{
SetActiveId(0);
value_changed = true;
*current_item = i;
}
if (item_selected && menu_toggled)
ImGui::SetScrollPosHere();
ImGui::PopID();
} }
if (item_selected && menu_toggled) ImGui::EndPopup();
ImGui::SetScrollPosHere();
combo_item_active |= ImGui::IsItemActive();
ImGui::PopID();
} }
ImGui::EndChild();
ImGui::PopStyleVar(); ImGui::PopStyleVar();
ImGui::SetCursorPos(backup_pos);
if (!combo_item_active && g.ActiveId != 0)
g.ActiveComboID = 0;
} }
ImGui::PopID();
return value_changed; return value_changed;
} }
@ -7769,7 +7769,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
if (opened) if (opened)
{ {
ImGui::SetNextWindowPos(popup_pos, ImGuiSetCond_Always); 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) opened = BeginPopupEx(label, flags); // opened can be 'false' when the popup is completely clipped (e.g. zero size display)
} }