mirror of
https://github.com/ocornut/imgui.git
synced 2024-11-27 16:29:02 +08:00
MultiSelect: Maintain NavIdSelected for user. Simplify deletion demo.
This commit is contained in:
parent
9223ffc255
commit
df1eeb9a20
1
imgui.h
1
imgui.h
@ -2784,6 +2784,7 @@ struct ImGuiMultiSelectIO
|
||||
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 SetNextItemSelectionUserData() value for NavId (if part of submitted items)
|
||||
|
||||
ImGuiMultiSelectIO() { Clear(); }
|
||||
|
@ -2821,8 +2821,7 @@ struct ExampleSelection
|
||||
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
|
||||
@ -2996,6 +2995,7 @@ static void ShowDemoWindowMultiSelect()
|
||||
// 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); }
|
||||
@ -3017,34 +3017,13 @@ static void ShowDemoWindowMultiSelect()
|
||||
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();
|
||||
}
|
||||
@ -3267,21 +3246,12 @@ static void ShowDemoWindowMultiSelect()
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
@ -1740,11 +1740,12 @@ struct IMGUI_API ImGuiMultiSelectState
|
||||
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; // SetNextItemSelectionUserData() 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
|
||||
|
@ -7160,8 +7160,10 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags)
|
||||
|
||||
// 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.
|
||||
@ -7216,13 +7218,14 @@ ImGuiMultiSelectIO* ImGui::EndMultiSelect()
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -7328,11 +7331,7 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
||||
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;
|
||||
|
||||
@ -7342,15 +7341,11 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
||||
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)
|
||||
@ -7446,6 +7441,15 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
||||
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;
|
||||
}
|
||||
@ -7461,7 +7465,7 @@ void ImGui::DebugNodeMultiSelectState(ImGuiMultiSelectState* storage)
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user