ListBox: renamed ListBoxHeader>BeginListBox, ListBoxFooter>EndListBox. Added demo bits.

This commit is contained in:
ocornut 2021-02-03 16:30:23 +01:00
parent 6f6d4e0b70
commit 03d74a293d
6 changed files with 96 additions and 37 deletions

View File

@ -37,9 +37,15 @@ HOW TO UPDATE?
Breaking Changes:
- ListBox helpers:
- Renamed ListBoxHeader(const char* label, ImVec2 size) to BeginListBox().
- Renamed ListBoxFooter() to EndListBox().
- Removed ListBoxHeader(const char* label, int items_count, int height_in_items = -1) in favor of specifying size.
In the redirection function, made vertical padding consistent regardless of (items_count <= height_in_items) or not.
- Kept inline redirection function for all threes (will obsolete).
- imgui_freetype:
- Removed ImGuiFreeType::BuildFontAtlas(). Kept inline redirection function.
Prefer using '#define IMGUI_ENABLE_FREETYPE', but there's a runtime selection path available too.
Prefer using '#define IMGUI_ENABLE_FREETYPE', but there's a runtime selection path available too.
- The shared extra flags parameters (very rarely used) are now stored in ImFontAtlas::FontBuilderFlags.
- Renamed ImFontConfig::RasterizerFlags (used by FreeType) to ImFontConfig::FontBuilderFlags.
- Renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API.
@ -56,8 +62,6 @@ Other Changes:
- InputText: Multiline: Fixed padding/cliprect not precisely matching single-line version. (#3781)
- InputText: Multiline: Fixed FramePadding.y worth of vertical offset when aiming with mouse.
- ListBox: Tweaked default height calculation.
- ListBoxHeader: In version taking height in number of items, made vertical padding consistent regardless
of if (items_count <= height_in_items) or not.
- Fonts: imgui_freetype: Facilitated using FreeType integration: [@Xipiryon, @ocornut]
- Use '#define IMGUI_ENABLE_FREETYPE' in imconfig.h should make it work with no other modifications
other than compiling misc/freetype/imgui_freetype.cpp and linking with FreeType.

View File

@ -185,12 +185,11 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- combo: flag for BeginCombo to not return true when unchanged (#1182)
- combo: a way/helper to customize the combo preview (#1658)
- combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox (pr #203)
- listbox: refactor and clean the begin/end api
- listbox: multiple selection.
- listbox: unselect option (#1208)
- listbox: make it easier/more natural to implement range-select (need some sort of info/ref about the last clicked/focused item that user can translate to an index?) (wip stash)
- listbox: user may want to initial scroll to focus on the one selected value?
- listbox: expose hovered item for a basic ListBox
- listbox: expose hovered item for a simplified ListBox api
- listbox: keyboard navigation.
- listbox: disable capturing mouse wheel if the listbox has no scrolling. (#1681)
- listbox: scrolling should track modified selection.

View File

@ -373,6 +373,9 @@ CODE
When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
You can read releases logs https://github.com/ocornut/imgui/releases for more details.
- 2021/02/03 (1.81) - renamed ListBoxHeader(const char* label, ImVec2 size) to BeginListBox(). Kept inline redirection function (will obsolete).
- removed ListBoxHeader(const char* label, int items_count, int height_in_items = -1) in favor of specifying size. Kept inline redirection function (will obsolete).
- renamed ListBoxFooter() to EndListBox(). Kept inline redirection function (will obsolete).
- 2021/01/26 (1.81) - removed ImGuiFreeType::BuildFontAtlas(). Kept inline redirection function. Prefer using '#define IMGUI_ENABLE_FREETYPE', but there's a runtime selection path available too. The shared extra flags parameters (very rarely used) are now stored in ImFontAtlas::FontBuilderFlags.
- renamed ImFontConfig::RasterizerFlags (used by FreeType) to ImFontConfig::FontBuilderFlags.
- renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API.

17
imgui.h
View File

@ -472,7 +472,7 @@ namespace ImGui
// Widgets: Combo Box
// - The BeginCombo()/EndCombo() api allows you to manage your contents and selection state however you want it, by creating e.g. Selectable() items.
// - The old Combo() api are helpers over BeginCombo()/EndCombo() which are kept available for convenience purpose.
// - The old Combo() api are helpers over BeginCombo()/EndCombo() which are kept available for convenience purpose. This is analogous to how ListBox are created.
IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0);
IMGUI_API void EndCombo(); // only call EndCombo() if BeginCombo() returns true!
IMGUI_API bool Combo(const char* label, int* current_item, const char* const items[], int items_count, int popup_max_height_in_items = -1);
@ -579,12 +579,15 @@ namespace ImGui
IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper.
// Widgets: List Boxes
// - FIXME: To be consistent with all the newer API, ListBoxHeader/ListBoxFooter should in reality be called BeginListBox/EndListBox. Will rename them.
// - This is essentially a thin wrapper to using BeginChild/EndChild with some stylistic changes.
// - The BeginListBox()/EndListBox() api allows you to manage your contents and selection state however you want it, by creating e.g. Selectable() or any items.
// - The simplified/old ListBox() api are helpers over BeginListBox()/EndListBox() which are kept available for convenience purpose. This is analoguous to how Combos are created.
// - Choose frame width: size.x > 0.0f: custom / size.x < 0.0f or -FLT_MIN: right-align / size.x = 0.0f (default): use current ItemWidth
// - Choose frame height: size.y > 0.0f: custom / size.y < 0.0f or -FLT_MIN: bottom-align / size.y = 0.0f (default): arbitrary default height which can fit ~7 items
IMGUI_API bool BeginListBox(const char* label, const ImVec2& size = ImVec2(0, 0)); // open a framed scrolling region
IMGUI_API void EndListBox(); // only call EndListBox() if BeginListBox() returned true!
IMGUI_API bool ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items = -1);
IMGUI_API bool ListBox(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1);
IMGUI_API bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0, 0)); // use if you want to reimplement ListBox() will custom data or interactions. if the function return true, you can output elements then call ListBoxFooter() afterwards.
IMGUI_API bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1); // "
IMGUI_API void ListBoxFooter(); // terminate the scrolling region. only call ListBoxFooter() if ListBoxHeader() returned true!
// Widgets: Data Plotting
// - Consider using ImPlot (https://github.com/epezent/implot)
@ -1961,6 +1964,10 @@ struct ImGuiTableSortSpecs
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
namespace ImGui
{
// OBSOLETED in 1.81 (from February 2021)
IMGUI_API bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1); // Helper to calculate size from items_count and height_in_items
static inline bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0, 0)) { return BeginListBox(label, size); }
static inline void ListBoxFooter() { EndListBox(); }
// OBSOLETED in 1.79 (from August 2020)
static inline void OpenPopupContextItem(const char* str_id = NULL, ImGuiMouseButton mb = 1) { OpenPopupOnItemClick(str_id, mb); } // Bool return value removed. Use IsWindowAppearing() in BeginPopup() instead. Renamed in 1.77, renamed back in 1.79. Sorry!
// OBSOLETED in 1.78 (from June 2020)

View File

@ -584,13 +584,12 @@ static void ShowDemoWindowWidgets()
{
// Using the _simplified_ one-liner Combo() api here
// See "Combo" section for examples of how to use the more complete BeginCombo()/EndCombo() api.
// See "Combo" section for examples of how to use the more flexible BeginCombo()/EndCombo() api.
const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIIIIII", "JJJJ", "KKKKKKK" };
static int item_current = 0;
ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items));
ImGui::SameLine(); HelpMarker(
"Refer to the \"Combo\" section below for an explanation of the full BeginCombo/EndCombo API, "
"and demonstration of various flags.\n");
"Using the simplified one-liner Combo API here.\nRefer to the \"Combo\" section below for an explanation of how to use the more flexible and general BeginCombo/EndCombo API.");
}
{
@ -689,14 +688,13 @@ static void ShowDemoWindowWidgets()
}
{
// List box
// Using the _simplified_ one-liner ListBox() api here
// See "List boxes" section for examples of how to use the more flexible BeginListBox()/EndListBox() api.
const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" };
static int item_current = 1;
ImGui::ListBox("listbox\n(single select)", &item_current, items, IM_ARRAYSIZE(items), 4);
//static int listbox_item_current2 = 2;
//ImGui::SetNextItemWidth(-FLT_MIN);
//ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
ImGui::ListBox("listbox", &item_current, items, IM_ARRAYSIZE(items), 4);
ImGui::SameLine(); HelpMarker(
"Using the simplified one-liner ListBox API here.\nRefer to the \"List boxes\" section below for an explanation of how to use the more flexible and general BeginListBox/EndListBox API.");
}
ImGui::TreePop();
@ -1009,7 +1007,7 @@ static void ShowDemoWindowWidgets()
// (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively
// stored in the object itself, etc.)
const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
static int item_current_idx = 0; // Here our selection data is an index.
static int item_current_idx = 0; // Here we store our selection data as an index.
const char* combo_label = items[item_current_idx]; // Label to preview before opening the combo (technically it could be anything)
if (ImGui::BeginCombo("combo 1", combo_label, flags))
{
@ -1042,6 +1040,48 @@ static void ShowDemoWindowWidgets()
ImGui::TreePop();
}
if (ImGui::TreeNode("List boxes"))
{
// Using the generic BeginListBox() API, you have full control over how to display the combo contents.
// (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively
// stored in the object itself, etc.)
const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
static int item_current_idx = 0; // Here we store our selection data as an index.
if (ImGui::BeginListBox("listbox 1"))
{
for (int n = 0; n < IM_ARRAYSIZE(items); n++)
{
const bool is_selected = (item_current_idx == n);
if (ImGui::Selectable(items[n], is_selected))
item_current_idx = n;
// Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
if (is_selected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndListBox();
}
// Custom size: use all width, 5 items tall
ImGui::Text("Full-width:");
if (ImGui::BeginListBox("##listbox 2", ImVec2(-FLT_MIN, 5 * ImGui::GetTextLineHeightWithSpacing())))
{
for (int n = 0; n < IM_ARRAYSIZE(items); n++)
{
const bool is_selected = (item_current_idx == n);
if (ImGui::Selectable(items[n], is_selected))
item_current_idx = n;
// Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
if (is_selected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndListBox();
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Selectables"))
{
// Selectable() has 2 overloads:
@ -2557,11 +2597,11 @@ static void ShowDemoWindowLayout()
ImGui::Button("LEVERAGE\nBUZZWORD", size);
ImGui::SameLine();
if (ImGui::ListBoxHeader("List", size))
if (ImGui::BeginListBox("List", size))
{
ImGui::Selectable("Selected", true);
ImGui::Selectable("Not Selected", false);
ImGui::ListBoxFooter();
ImGui::EndListBox();
}
ImGui::TreePop();

View File

@ -6124,18 +6124,14 @@ bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags
//-------------------------------------------------------------------------
// [SECTION] Widgets: ListBox
//-------------------------------------------------------------------------
// - BeginListBox()
// - EndListBox()
// - ListBox()
// - ListBoxHeader()
// - ListBoxFooter()
//-------------------------------------------------------------------------
// FIXME: This is an old API. We should redesign some of it, rename ListBoxHeader->BeginListBox, ListBoxFooter->EndListBox
// and promote using them over existing ListBox() functions, similarly to how we now use combo boxes.
//-------------------------------------------------------------------------
// FIXME: In principle this function should be called BeginListBox(). We should rename it after re-evaluating if we want to keep the same signature.
// Tip: To have a list filling the entire window width, use size.x = -FLT_MIN and pass an non-visible label e.g. "##empty"
// 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.25 * item_height).
bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg)
bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow();
@ -6174,7 +6170,8 @@ bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg)
return true;
}
// FIXME: In principle this function should be called BeginListBox(). We should rename it after re-evaluating if we want to keep the same signature.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
// OBSOLETED in 1.81 (from February 2021)
bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_items)
{
// If height_in_items == -1, default height is maximum 7.
@ -6183,15 +6180,15 @@ bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_item
ImVec2 size;
size.x = 0.0f;
size.y = GetTextLineHeightWithSpacing() * height_in_items_f + g.Style.FramePadding.y * 2.0f;
return ListBoxHeader(label, size);
return BeginListBox(label, size);
}
#endif
// FIXME: In principle this function should be called EndListBox(). We should rename it after re-evaluating if we want to keep the same signature.
void ImGui::ListBoxFooter()
void ImGui::EndListBox()
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
IM_ASSERT((window->Flags & ImGuiWindowFlags_ChildWindow) && "Mismatched ListBoxHeader/ListBoxFooter calls. Did you test the return value of ListBoxHeader()?");
IM_ASSERT((window->Flags & ImGuiWindowFlags_ChildWindow) && "Mismatched BeginListBox/EndListBox calls. Did you test the return value of BeginListBox?");
EndChildFrame();
EndGroup(); // This is only required to be able to do IsItemXXX query on the whole ListBox including label
@ -6203,14 +6200,23 @@ bool ImGui::ListBox(const char* label, int* current_item, const char* const item
return value_changed;
}
// This is merely a helper around BeginListBox(), EndListBox().
// Considering using those directly to submit custom data or store selection differently.
bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int height_in_items)
{
if (!ListBoxHeader(label, items_count, height_in_items))
ImGuiContext& g = *GImGui;
// Calculate size from "height_in_items"
if (height_in_items < 0)
height_in_items = ImMin(items_count, 7);
float height_in_items_f = height_in_items + 0.25f;
ImVec2 size(0.0f, ImFloor(GetTextLineHeightWithSpacing() * height_in_items_f + g.Style.FramePadding.y * 2.0f));
if (!BeginListBox(label, size))
return false;
// Assume all items have even height (= 1 line of text). If you need items of different height,
// you can create a custom version of ListBox() in your code without using the clipper.
ImGuiContext& g = *GImGui;
bool value_changed = false;
ImGuiListClipper clipper;
clipper.Begin(items_count, GetTextLineHeightWithSpacing()); // We know exactly our line height here so we pass it as a minor optimization, but generally you don't need to.
@ -6232,7 +6238,7 @@ bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(v
SetItemDefaultFocus();
PopID();
}
ListBoxFooter();
EndListBox();
if (value_changed)
MarkItemEdited(g.CurrentWindow->DC.LastItemId);