Browse Source

Combo: simplified Combo() API uses a list clipper.

Wasn't as trivial before supporting IncludeItemByIndex().
pull/7637/head
ocornut 5 months ago
parent
commit
109a8632d7
  1. 2
      docs/CHANGELOG.txt
  2. 1
      docs/TODO.txt
  3. 37
      imgui_widgets.cpp

2
docs/CHANGELOG.txt

@ -47,6 +47,8 @@ Other changes:
responsible for honoring io.ConfigWindowsMoveFromTitleBarOnly. (#7576, #899)
- Scrollbar: made scrolling logic more standard: clicking above or below the
grab scrolls by one page, holding mouse button repeats scrolling. (#7328, #150)
- Combo: simplified Combo() API uses a list clipper (due to its api it wasn't
previously trivial before we added clipper.IncludeItemByIndex() function).
- Misc: made ImGuiDir and ImGuiSortDirection stronger-typed enums.

1
docs/TODO.txt

@ -151,7 +151,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- drag float: added leeway on edge (e.g. a few invisible steps past the clamp limits)
- combo: a way/helper to customize the combo preview (#1658) -> experimental BeginComboPreview()
- combo: Combo() helper could use clipper.
- combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox (pr #203)
- listbox: multiple selection (WIP range-select branch)
- listbox: unselect option (#1208)

37
imgui_widgets.cpp

@ -1952,28 +1952,30 @@ bool ImGui::Combo(const char* label, int* current_item, const char* (*getter)(vo
return false;
// Display items
// FIXME-OPT: Use clipper (but we need to disable it on the appearing frame to make sure our call to SetItemDefaultFocus() is processed)
bool value_changed = false;
for (int i = 0; i < items_count; i++)
{
const char* item_text = getter(user_data, i);
if (item_text == NULL)
item_text = "*Unknown item*";
PushID(i);
const bool item_selected = (i == *current_item);
if (Selectable(item_text, item_selected) && *current_item != i)
ImGuiListClipper clipper;
clipper.Begin(items_count);
clipper.IncludeItemByIndex(*current_item);
while (clipper.Step())
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
{
value_changed = true;
*current_item = i;
const char* item_text = getter(user_data, i);
if (item_text == NULL)
item_text = "*Unknown item*";
PushID(i);
const bool item_selected = (i == *current_item);
if (Selectable(item_text, item_selected) && *current_item != i)
{
value_changed = true;
*current_item = i;
}
if (item_selected)
SetItemDefaultFocus();
PopID();
}
if (item_selected)
SetItemDefaultFocus();
PopID();
}
EndCombo();
if (value_changed)
MarkItemEdited(g.LastItemData.ID);
@ -7011,6 +7013,7 @@ bool ImGui::ListBox(const char* label, int* current_item, const char* (*getter)(
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.
clipper.IncludeItemByIndex(*current_item);
while (clipper.Step())
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
{

Loading…
Cancel
Save