This is essentially a thin wrapper to using BeginChild/EndChild with the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label. This handle some subtleties with capturing info from the label. If you don't need a label you can pretty much directly use ImGui::BeginChild() with ImGuiChildFlags_FrameStyle. Tip: To have a list filling the entire window width, use size.x = -FLT_MIN
| 8780 | // Tip: To have a list filling the entire window width, use size.x = -FLT_MIN and pass an non-visible label e.g. "##empty" |
| 8781 | // Tip: If your vertical size is calculated from an item count (e.g. 10 * item_height) consider adding a fractional part to facilitate seeing scrolling boundaries (e.g. 10.5f * item_height). |
| 8782 | bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg) |
| 8783 | { |
| 8784 | ImGuiContext& g = *GImGui; |
| 8785 | ImGuiWindow* window = GetCurrentWindow(); |
| 8786 | if (window->SkipItems) |
| 8787 | return false; |
| 8788 | |
| 8789 | const ImGuiStyle& style = g.Style; |
| 8790 | const ImGuiID id = GetID(label); |
| 8791 | const char* label_end = FindRenderedTextEnd(label); |
| 8792 | const ImVec2 label_size = CalcTextSize(label, label_end, false); |
| 8793 | |
| 8794 | // Size default to hold ~7.25 items. |
| 8795 | // Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar. |
| 8796 | ImVec2 size = ImTrunc(CalcItemSize(size_arg, CalcItemWidth(), GetTextLineHeightWithSpacing() * 7.25f + style.FramePadding.y * 2.0f)); |
| 8797 | ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y)); |
| 8798 | ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size); |
| 8799 | ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); |
| 8800 | g.NextItemData.ClearFlags(); |
| 8801 | |
| 8802 | if (!IsRectVisible(bb.Min, bb.Max)) |
| 8803 | { |
| 8804 | ItemSize(bb.GetSize(), style.FramePadding.y); |
| 8805 | ItemAdd(bb, 0, &frame_bb); |
| 8806 | g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values |
| 8807 | return false; |
| 8808 | } |
| 8809 | |
| 8810 | // FIXME-OPT: We could omit the BeginGroup() if label_size.x == 0.0f but would need to omit the EndGroup() as well. |
| 8811 | BeginGroup(); |
| 8812 | if (label_size.x > 0.0f) |
| 8813 | { |
| 8814 | ImVec2 label_pos = ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y); |
| 8815 | RenderText(label_pos, label, label_end, false); |
| 8816 | window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, label_pos + label_size); |
| 8817 | AlignTextToFramePadding(); |
| 8818 | } |
| 8819 | |
| 8820 | BeginChild(id, frame_bb.GetSize(), ImGuiChildFlags_FrameStyle); |
| 8821 | return true; |
| 8822 | } |
| 8823 | |
| 8824 | void ImGui::EndListBox() |
| 8825 | { |
nothing calls this directly
no test coverage detected