Procházet zdrojové kódy

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

Wasn't as trivial before supporting IncludeItemByIndex().
ocornut před 1 rokem
rodič
revize
109a8632d7
3 změnil soubory, kde provedl 22 přidání a 18 odebrání
  1. 2 0
      docs/CHANGELOG.txt
  2. 0 1
      docs/TODO.txt
  3. 20 17
      imgui_widgets.cpp

+ 2 - 0
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.
 
 

+ 0 - 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)

+ 20 - 17
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++)
         {