RangeSelect/MultiSelect: Maintain NavIdSelected for user. Simplify deletion demo.
diff --git a/imgui.h b/imgui.h
index a85f4de..c606c4a 100644
--- a/imgui.h
+++ b/imgui.h
@@ -2516,6 +2516,7 @@
bool RangeSelected; // / / ms:w, app:r // End: parameter from RequestSetRange request. true = Select Range, false = Unselect Range.
bool RangeSrcPassedBy; // / ms:rw app:w / ms:r // (If using clipper) Need to be set by app/user if RangeSrcItem was part of the clipped set before submitting the visible items. Ignore if not clipping.
bool RangeSrcReset; // / app:w / ms:r // (If using deletion) Set before EndMultiSelect() to reset ResetSrcItem (e.g. if deleted selection).
+ bool NavIdSelected; // ms:w, app:r / / // (If using deletion) Last known selection state for NavId (if part of submitted items).
void* NavIdItem; // ms:w, app:r / / ms:w app:r // (If using deletion) Last known SetNextItemSelectionData() value for NavId (if part of submitted items)
ImGuiMultiSelectIO() { Clear(); }
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index 7ac0d9c..fb8b7e7 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -2668,8 +2668,7 @@
template<typename ITEM_TYPE>
int CalcNextFocusIdxForBeforeDeletion(ImGuiMultiSelectIO* ms_io, ImVector<ITEM_TYPE>& items)
{
- // FIXME-MULTISELECT: Need to avoid auto-select, aka SetKeyboardFocusHere() into public facing FocusItem() that doesn't activate.
- if (!GetSelected((int)(intptr_t)ms_io->NavIdItem))
+ if (ms_io->NavIdSelected == false)
return (int)(intptr_t)ms_io->NavIdItem;
// Return first unselected item after RangeSrcItem
@@ -2843,6 +2842,7 @@
// FIXME-MULTISELECT: Shortcut(). Hard to demo this? May be helpful to send a helper/optional "delete" signal.
// FIXME-MULTISELECT: may turn into 'ms_io->RequestDelete' -> need HasSelection passed.
// FIXME-MULTISELECT: Test with intermediary modal dialog.
+ // FIXME-MULTISELECT: If pressing Delete + another key we have slightly ambiguous behavior.
const bool want_delete = (selection.GetSize() > 0) && ImGui::IsWindowFocused() && ImGui::IsKeyPressed(ImGuiKey_Delete);
const int next_focus_item_idx = want_delete ? selection.CalcNextFocusIdxForBeforeDeletion(ms_io, items) : -1;
//if (want_delete) { IMGUI_DEBUG_LOG("next_focus_item_idx = %d\n", next_focus_item_idx); }
@@ -2864,34 +2864,13 @@
ImGui::SetKeyboardFocusHere(-1); // FIXME-MULTISELECT: Need to avoid selection.
}
-#if 0
- bool nav_id_was_selected = selection.GetSelected((int)(intptr_t)ms_io->NavIdData);
- if (want_delete && !nav_id_was_selected) // FIXME: would work without '&& !nav_id_was_selected' just take an extra frame to recover RangeSrc
+ // Apply multi-select requests
+ if (want_delete && ms_io->NavIdSelected == false) // FIXME: would work without '&& !NavIdSelected' just take an extra frame to recover RangeSrc
ms_io->RangeSrcReset = true;
ms_io = ImGui::EndMultiSelect();
selection.ApplyRequests(ms_io, items.Size);
if (want_delete)
- selection.ApplyDeletion(ms_io, items, nav_id_was_selected ? next_focus_item_idx : -1);
-#else
- // Apply multi-select requests
- if (want_delete)
- {
- // When deleting: this handle details for scrolling/focus/selection to be updated correctly without any glitches.
- bool nav_id_was_selected = selection.GetSelected((int)(intptr_t)ms_io->NavIdItem);
- if (!nav_id_was_selected) // FIXME: would work without '&& !nav_id_was_selected' just take an extra frame to recover RangeSrc
- ms_io->RangeSrcReset = true;
- ms_io = ImGui::EndMultiSelect();
- selection.ApplyRequests(ms_io, items.Size);
- selection.ApplyDeletion(ms_io, items, nav_id_was_selected ? next_focus_item_idx : -1);
- }
- else
- {
- // Simple version
- ms_io = ImGui::EndMultiSelect();
- selection.ApplyRequests(ms_io, items.Size);
- }
-#endif
-
+ selection.ApplyDeletion(ms_io, items, ms_io->NavIdSelected ? next_focus_item_idx : -1);
ImGui::EndListBox();
}
@@ -3114,21 +3093,12 @@
}
// Apply multi-select requests
-#if 1
- // full correct
- bool nav_id_was_selected = selection.GetSelected((int)(intptr_t)ms_io->NavIdItem);
- if (want_delete && !nav_id_was_selected)
+ if (want_delete && ms_io->NavIdSelected == false)
ms_io->RangeSrcReset = true;
ms_io = ImGui::EndMultiSelect();
selection.ApplyRequests(ms_io, items.Size);
if (want_delete)
- selection.ApplyDeletion(ms_io, items, nav_id_was_selected ? next_focus_item_idx : -1);
-#else
- ms_io = ImGui::EndMultiSelect();
- selection.ApplyRequests(ms_io, items.Size);
- if (want_delete)
- selection.ApplyDeletion(ms_io, items, nav_id_was_selected ? next_focus_item_idx : -1);
-#endif
+ selection.ApplyDeletion(ms_io, items, ms_io->NavIdSelected ? next_focus_item_idx : -1);
if (widget_type == WidgetType_TreeNode)
ImGui::PopStyleVar();
diff --git a/imgui_internal.h b/imgui_internal.h
index ef2c857..52988d7 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1613,11 +1613,12 @@
ImGuiID ID;
int LastFrameActive; // Last used frame-count, for GC.
ImS8 RangeSelected; // -1 (don't have) or true/false
+ ImS8 NavIdSelected; // -1 (don't have) or true/false
void* RangeSrcItem; //
void* NavIdItem; // SetNextItemSelectionData() value for NavId (if part of submitted items)
ImGuiMultiSelectState() { Init(0); }
- void Init(ImGuiID id) { Window = NULL; ID = id; LastFrameActive = 0; RangeSelected = -1; RangeSrcItem = NavIdItem = (void*)-1; }
+ void Init(ImGuiID id) { Window = NULL; ID = id; LastFrameActive = 0; RangeSelected = NavIdSelected = -1; RangeSrcItem = NavIdItem = (void*)-1; }
};
#endif // #ifdef IMGUI_HAS_MULTI_SELECT
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 5f97697..526cd09 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -6694,8 +6694,10 @@
// FIXME-MULTISELECT: Set for the purpose of user calling RangeSrcPassedBy
// FIXME-MULTISELECT: Index vs Pointers.
- ms->BeginIO.RangeSrcItem = storage->RangeSrcItem;
- ms->BeginIO.NavIdItem = storage->NavIdItem;
+ // We want EndIO's NavIdItem/NavIdSelected to match BeginIO's one, so the value never changes after EndMultiSelect()
+ ms->BeginIO.RangeSrcItem = ms->EndIO.RangeSrcItem = storage->RangeSrcItem;
+ ms->BeginIO.NavIdItem = ms->EndIO.NavIdItem = storage->NavIdItem;
+ ms->BeginIO.NavIdSelected = ms->EndIO.NavIdSelected = (storage->NavIdSelected == 1) ? true : false;
if (!ms->IsFocused)
return &ms->BeginIO; // This is cleared at this point.
@@ -6750,13 +6752,14 @@
{
if (ms->BeginIO.RangeSrcReset || (ms->BeginIO.RangeSrcPassedBy == false && ms->BeginIO.RangeSrcItem != (void*)-1))
{
- IMGUI_DEBUG_LOG_SELECTION("[selection] EndMultiSelect: Reset RangeSrc.\n"); // Will set be to NavId.
+ IMGUI_DEBUG_LOG_SELECTION("[selection] EndMultiSelect: Reset RangeSrcItem.\n"); // Will set be to NavId.
ms->Storage->RangeSrcItem = (void*)-1;
}
if (ms->NavIdPassedBy == false && ms->Storage->NavIdItem != (void*)-1)
{
- IMGUI_DEBUG_LOG_SELECTION("[selection] EndMultiSelect: Reset NavIdData.\n");
+ IMGUI_DEBUG_LOG_SELECTION("[selection] EndMultiSelect: Reset NavIdItem.\n");
ms->Storage->NavIdItem = (void*)-1;
+ ms->Storage->NavIdSelected = -1;
}
}
@@ -6857,11 +6860,7 @@
ImGuiMultiSelectTempData* ms = g.CurrentMultiSelect;
ImGuiMultiSelectState* storage = ms->Storage;
if (pressed)
- {
ms->IsFocused = true;
- //if (storage->Id != ms->FocusScopeId)
- // storage->Init(ms->FocusScopeId);
- }
if (!ms->IsFocused)
return;
@@ -6872,15 +6871,11 @@
bool is_ctrl = (ms->KeyMods & ImGuiMod_Ctrl) != 0;
bool is_shift = (ms->KeyMods & ImGuiMod_Shift) != 0;
- if (g.NavId == id)
- storage->NavIdItem = item_data;
if (g.NavId == id && storage->RangeSrcItem == (void*)-1)
{
storage->RangeSrcItem = item_data;
storage->RangeSelected = selected; // Will be updated at the end of this function anyway.
}
- if (storage->NavIdItem == item_data)
- ms->NavIdPassedBy = true;
// Auto-select as you navigate a list
if (g.NavJustMovedToId == id)
@@ -6976,6 +6971,15 @@
ms->EndIO.RangeSelected = selected;
}
+ // Update/store the selection state of focused item
+ if (g.NavId == id)
+ {
+ storage->NavIdItem = item_data;
+ storage->NavIdSelected = selected ? 1 : 0;
+ }
+ if (storage->NavIdItem == item_data)
+ ms->NavIdPassedBy = true;
+
*p_selected = selected;
*p_pressed = pressed;
}
@@ -6991,7 +6995,7 @@
return;
Text("ID = 0x%08X", storage->ID);
Text("RangeSrcItem = %p, RangeSelected = %d", storage->RangeSrcItem, storage->RangeSelected);
- Text("NavIdItem = %p", storage->NavIdItem);
+ Text("NavIdData = %p, NavIdSelected = %d", storage->NavIdItem, storage->NavIdSelected);
TreePop();
#else
IM_UNUSED(storage);