mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-31 13:11:05 +01:00 
			
		
		
		
	Internals: Combo: Extracted into a BeginComboPopup() function. (#4168)
Renamed frame_bb > bb locally.
This commit is contained in:
		| @@ -1537,7 +1537,9 @@ void ImGui::ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_exc | ||||
| //------------------------------------------------------------------------- | ||||
| // [SECTION] Widgets: ComboBox | ||||
| //------------------------------------------------------------------------- | ||||
| // - CalcMaxPopupHeightFromItemCount() [Internal] | ||||
| // - BeginCombo() | ||||
| // - BeginComboPopup() [Internal] | ||||
| // - EndCombo() | ||||
| // - Combo() | ||||
| //------------------------------------------------------------------------- | ||||
| @@ -1552,78 +1554,91 @@ static float CalcMaxPopupHeightFromItemCount(int items_count) | ||||
|  | ||||
| bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags) | ||||
| { | ||||
|     // Always consume the SetNextWindowSizeConstraint() call in our early return paths | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     bool has_window_size_constraint = (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint) != 0; | ||||
|     g.NextWindowData.Flags &= ~ImGuiNextWindowDataFlags_HasSizeConstraint; | ||||
|  | ||||
|     ImGuiWindow* window = GetCurrentWindow(); | ||||
|  | ||||
|     ImGuiNextWindowDataFlags backup_next_window_data_flags = g.NextWindowData.Flags; | ||||
|     g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values | ||||
|     if (window->SkipItems) | ||||
|         return false; | ||||
|  | ||||
|     IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together | ||||
|  | ||||
|     const ImGuiStyle& style = g.Style; | ||||
|     const ImGuiID id = window->GetID(label); | ||||
|     IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together | ||||
|  | ||||
|     const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight(); | ||||
|     const ImVec2 label_size = CalcTextSize(label, NULL, true); | ||||
|     const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : CalcItemWidth(); | ||||
|     const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f)); | ||||
|     const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); | ||||
|     const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f)); | ||||
|     const ImRect total_bb(bb.Min, bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); | ||||
|     ItemSize(total_bb, style.FramePadding.y); | ||||
|     if (!ItemAdd(total_bb, id, &frame_bb)) | ||||
|     if (!ItemAdd(total_bb, id, &bb)) | ||||
|         return false; | ||||
|  | ||||
|     // Open on click | ||||
|     bool hovered, held; | ||||
|     bool pressed = ButtonBehavior(frame_bb, id, &hovered, &held); | ||||
|  | ||||
|     bool pressed = ButtonBehavior(bb, id, &hovered, &held); | ||||
|     const ImGuiID popup_id = ImHashStr("##ComboPopup", 0, id); | ||||
|     bool popup_open = IsPopupOpen(popup_id, ImGuiPopupFlags_None); | ||||
|  | ||||
|     const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); | ||||
|     const float value_x2 = ImMax(frame_bb.Min.x, frame_bb.Max.x - arrow_size); | ||||
|     RenderNavHighlight(frame_bb, id); | ||||
|     if (!(flags & ImGuiComboFlags_NoPreview)) | ||||
|         window->DrawList->AddRectFilled(frame_bb.Min, ImVec2(value_x2, frame_bb.Max.y), frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersLeft); | ||||
|     if (!(flags & ImGuiComboFlags_NoArrowButton)) | ||||
|     { | ||||
|         ImU32 bg_col = GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button); | ||||
|         ImU32 text_col = GetColorU32(ImGuiCol_Text); | ||||
|         window->DrawList->AddRectFilled(ImVec2(value_x2, frame_bb.Min.y), frame_bb.Max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersRight); | ||||
|         if (value_x2 + arrow_size - style.FramePadding.x <= frame_bb.Max.x) | ||||
|             RenderArrow(window->DrawList, ImVec2(value_x2 + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), text_col, ImGuiDir_Down, 1.0f); | ||||
|     } | ||||
|     RenderFrameBorder(frame_bb.Min, frame_bb.Max, style.FrameRounding); | ||||
|     if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview)) | ||||
|     { | ||||
|         ImVec2 preview_pos = frame_bb.Min + style.FramePadding; | ||||
|         if (g.LogEnabled) | ||||
|             LogSetNextTextDecoration("{", "}"); | ||||
|         RenderTextClipped(preview_pos, ImVec2(value_x2, frame_bb.Max.y), preview_value, NULL, NULL, ImVec2(0.0f, 0.0f)); | ||||
|     } | ||||
|     if (label_size.x > 0) | ||||
|         RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); | ||||
|  | ||||
|     if ((pressed || g.NavActivateId == id) && !popup_open) | ||||
|     { | ||||
|         OpenPopupEx(popup_id, ImGuiPopupFlags_None); | ||||
|         popup_open = true; | ||||
|     } | ||||
|  | ||||
|     // Render shape | ||||
|     const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); | ||||
|     const float value_x2 = ImMax(bb.Min.x, bb.Max.x - arrow_size); | ||||
|     RenderNavHighlight(bb, id); | ||||
|     if (!(flags & ImGuiComboFlags_NoPreview)) | ||||
|         window->DrawList->AddRectFilled(bb.Min, ImVec2(value_x2, bb.Max.y), frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersLeft); | ||||
|     if (!(flags & ImGuiComboFlags_NoArrowButton)) | ||||
|     { | ||||
|         ImU32 bg_col = GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button); | ||||
|         ImU32 text_col = GetColorU32(ImGuiCol_Text); | ||||
|         window->DrawList->AddRectFilled(ImVec2(value_x2, bb.Min.y), bb.Max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersRight); | ||||
|         if (value_x2 + arrow_size - style.FramePadding.x <= bb.Max.x) | ||||
|             RenderArrow(window->DrawList, ImVec2(value_x2 + style.FramePadding.y, bb.Min.y + style.FramePadding.y), text_col, ImGuiDir_Down, 1.0f); | ||||
|     } | ||||
|     RenderFrameBorder(bb.Min, bb.Max, style.FrameRounding); | ||||
|  | ||||
|     // Render preview and label | ||||
|     if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview)) | ||||
|     { | ||||
|         if (g.LogEnabled) | ||||
|             LogSetNextTextDecoration("{", "}"); | ||||
|         RenderTextClipped(bb.Min + style.FramePadding, ImVec2(value_x2, bb.Max.y), preview_value, NULL, NULL); | ||||
|     } | ||||
|     if (label_size.x > 0) | ||||
|         RenderText(ImVec2(bb.Max.x + style.ItemInnerSpacing.x, bb.Min.y + style.FramePadding.y), label); | ||||
|  | ||||
|     if (!popup_open) | ||||
|         return false; | ||||
|  | ||||
|     if (has_window_size_constraint) | ||||
|     g.NextWindowData.Flags = backup_next_window_data_flags; | ||||
|     return BeginComboPopup(popup_id, bb, flags); | ||||
| } | ||||
|  | ||||
| bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags flags) | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     if (!IsPopupOpen(popup_id, ImGuiPopupFlags_None)) | ||||
|     { | ||||
|         g.NextWindowData.ClearFlags(); | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     // Set popup size | ||||
|     float w = bb.GetWidth(); | ||||
|     if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint) | ||||
|     { | ||||
|         g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSizeConstraint; | ||||
|         g.NextWindowData.SizeConstraintRect.Min.x = ImMax(g.NextWindowData.SizeConstraintRect.Min.x, w); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         if ((flags & ImGuiComboFlags_HeightMask_) == 0) | ||||
|             flags |= ImGuiComboFlags_HeightRegular; | ||||
|         IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiComboFlags_HeightMask_));    // Only one | ||||
|         IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiComboFlags_HeightMask_)); // Only one | ||||
|         int popup_max_height_in_items = -1; | ||||
|         if (flags & ImGuiComboFlags_HeightRegular)     popup_max_height_in_items = 8; | ||||
|         else if (flags & ImGuiComboFlags_HeightSmall)  popup_max_height_in_items = 4; | ||||
| @@ -1631,11 +1646,13 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF | ||||
|         SetNextWindowSizeConstraints(ImVec2(w, 0.0f), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items))); | ||||
|     } | ||||
|  | ||||
|     // This is essentially a specialized version of BeginPopupEx() | ||||
|     char name[16]; | ||||
|     ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth | ||||
|  | ||||
|     // Position the window given a custom constraint (peak into expected window size so we can position it) | ||||
|     // This might be easier to express with an hypothetical SetNextWindowPosConstraints() function. | ||||
|     // Set position given a custom constraint (peak into expected window size so we can position it) | ||||
|     // FIXME: This might be easier to express with an hypothetical SetNextWindowPosConstraints() function? | ||||
|     // FIXME: This might be moved to Begin() or at least around the same spot where Tooltips and other Popups are calling FindBestWindowPosForPopupEx()? | ||||
|     if (ImGuiWindow* popup_window = FindWindowByName(name)) | ||||
|         if (popup_window->WasActive) | ||||
|         { | ||||
| @@ -1643,15 +1660,13 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF | ||||
|             ImVec2 size_expected = CalcWindowNextAutoFitSize(popup_window); | ||||
|             popup_window->AutoPosLastDirection = (flags & ImGuiComboFlags_PopupAlignLeft) ? ImGuiDir_Left : ImGuiDir_Down; // Left = "Below, Toward Left", Down = "Below, Toward Right (default)" | ||||
|             ImRect r_outer = GetPopupAllowedExtentRect(popup_window); | ||||
|             ImVec2 pos = FindBestWindowPosForPopupEx(frame_bb.GetBL(), size_expected, &popup_window->AutoPosLastDirection, r_outer, frame_bb, ImGuiPopupPositionPolicy_ComboBox); | ||||
|             ImVec2 pos = FindBestWindowPosForPopupEx(bb.GetBL(), size_expected, &popup_window->AutoPosLastDirection, r_outer, bb, ImGuiPopupPositionPolicy_ComboBox); | ||||
|             SetNextWindowPos(pos); | ||||
|         } | ||||
|  | ||||
|     // We don't use BeginPopupEx() solely because we have a custom name string, which we could make an argument to BeginPopupEx() | ||||
|     ImGuiWindowFlags window_flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoMove; | ||||
|  | ||||
|     // Horizontally align ourselves with the framed text | ||||
|     PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(style.FramePadding.x, style.WindowPadding.y)); | ||||
|     PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(g.Style.FramePadding.x, g.Style.WindowPadding.y)); // Horizontally align ourselves with the framed text | ||||
|     bool ret = Begin(name, NULL, window_flags); | ||||
|     PopStyleVar(); | ||||
|     if (!ret) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user