#define IMGUI_HAS_MULTI_SELECT // Multi-Select/Range-Select WIP branch // <-- This is currently _not_ in the top of imgui.h to prevent merge conflicts.
// - If you need to wrap this API for another language/framework, feel free to expose this as 'int' if simpler.
// Usage flow:
// BEGIN - (1) Call BeginMultiSelect() and retrieve the ImGuiMultiSelectIO* result.
// - (2) [If using clipper] Honor Clear/SelectAll/SetRange requests by updating your selection data. Same code as Step 6.
// - (2) [If using clipper] Honor request list (Clear/SelectAll/SetRange requests) by updating your selection data. Same code as Step 6.
// - (3) [If using clipper] You need to make sure RangeSrcItem is always submitted. Calculate its index and pass to clipper.IncludeIndex(). If already using indices in ImGuiSelectionUserData, it is as simple as clipper.IncludeIndex((int)ms_io->RangeSrcItem);
// LOOP - (4) Submit your items with SetNextItemSelectionUserData() + Selectable()/TreeNode() calls.
// END - (5) Call EndMultiSelect() and retrieve the ImGuiMultiSelectIO* result.
// - (6) Honor Clear/SelectAll/SetRange requests by updating your selection data. Same code as Step 2.
// - (6) Honor request list (Clear/SelectAll/SetRange requests) by updating your selection data. Same code as Step 2.
// If you submit all items (no clipper), Step 2 and 3 and will be handled by Selectable()/TreeNode on a per-item basis.
// However it is perfectly fine to honor all steps even if you don't use a clipper.
// Advanced:
// - Deletion: If you need to handle items deletion a little more work if needed for post-deletion focus and scrolling to be correct.
// refer to 'Demo->Widgets->Selection State' for demos supporting deletion.
enumImGuiSelectionRequestType
{
ImGuiSelectionRequestType_None=0,
ImGuiSelectionRequestType_Clear,// Request app to clear selection.
ImGuiSelectionRequestType_SelectAll,// Request app to select all.
ImGuiSelectionRequestType_SetRange,// Request app to select/unselect [RangeFirstItem..RangeLastItem] items based on 'bool RangeSelected'. Only EndMultiSelect() request this, app code can read after BeginMultiSelect() and it will always be false.
};
// List of requests stored in ImGuiMultiSelectIO
// - Use 'Demo->Tools->Debug Log->Selection' to see requests as they happen.
// - Some fields are only necessary if your list is dynamic and allows deletion (handling deletion and getting "post-deletion" state right is shown in the demo)
// - Below: who reads/writes each fields? 'r'=read, 'w'=write, 'ms'=multi-select code, 'app'=application/user code, 'BEGIN'=BeginMultiSelect() and after, 'END'=EndMultiSelect() and after.
ImGuiSelectionUserDataRangeFirstItem;// / ms:w, app:r // Parameter for SetRange request (this is generally == RangeSrcItem when shift selecting from top to bottom)
ImGuiSelectionUserDataRangeLastItem;// / ms:w, app:r // Parameter for SetRange request (this is generally == RangeSrcItem when shift selecting from bottom to top)
// - Always process requests in this order: Clear, SelectAll, SetRange. Use 'Demo->Tools->Debug Log->Selection' to see requests as they happen.
// - Some fields are only necessary if your list is dynamic and allows deletion (getting "post-deletion" state right is shown in the demo)
// - Below: who reads/writes each fields? 'r'=read, 'w'=write, 'ms'=multi-select code, 'app'=application/user code, 'BEGIN'=BeginMultiSelect() and after, 'END'=EndMultiSelect() and after.
// REQUESTS --------------------------------// BEGIN / END
boolRequestSelectAll;// ms:w, app:r / ms:w, app:r // 2. Request app/user to select all.
boolRequestSetRange;// / ms:w, app:r // 3. Request app/user to select/unselect [RangeFirstItem..RangeLastItem] items based on 'bool RangeSelected'. Only EndMultiSelect() request this, app code can read after BeginMultiSelect() and it will always be false.
// STATE/ARGUMENTS -------------------------// BEGIN / END
ImGuiSelectionUserDataRangeSrcItem;// ms:w app:r / // (If using clipper) Begin: Source item (generally the first selected item when multi-selecting, which is used as a reference point) must never be clipped!
ImGuiSelectionUserDataRangeFirstItem;// / ms:w, app:r // End: parameter for RequestSetRange request (this is generally == RangeSrcItem when shift selecting from top to bottom)
ImGuiSelectionUserDataRangeLastItem;// / ms:w, app:r // End: parameter for RequestSetRange request (this is generally == RangeSrcItem when shift selecting from bottom to top)
boolRangeSrcReset;// app:w / ms:r // (If using deletion) Set before EndMultiSelect() to reset ResetSrcItem (e.g. if deleted selection).
boolNavIdSelected;// ms:w, app:r / app:r // (If using deletion) Last known selection state for NavId (if part of submitted items).
ImGuiSelectionUserDataNavIdItem;// ms:w, app:r / // (If using deletion) Last known SetNextItemSelectionUserData() value for NavId (if part of submitted items).
ImGuiSelectionUserDataRangeSrcItem;// ms:w app:r / // (If using clipper) Begin: Source item (generally the first selected item when multi-selecting, which is used as a reference point) must never be clipped!
ImGuiSelectionUserDataNavIdItem;// ms:w, app:r / // (If using deletion) Last known SetNextItemSelectionUserData() value for NavId (if part of submitted items).
boolNavIdSelected;// ms:w, app:r / app:r // (If using deletion) Last known selection state for NavId (if part of submitted items).
boolRangeSrcReset;// app:w / ms:r // (If using deletion) Set before EndMultiSelect() to reset ResetSrcItem (e.g. if deleted selection).
// WHEN YOUR APPLICATION SETTLES ON A CHOICE, YOU WILL PROBABLY PREFER TO GET RID OF THIS UNNECESSARY 'ExampleSelectionAdapter' INDIRECTION LOGIC.
// Notice that with the simplest adapter (using indices everywhere), all functions return their parameters.
// The most simple implementation (using indices everywhere) would look like:
// if (ms_io->RequestClear) { Clear(); }
// if (ms_io->RequestSelectAll) { Clear(); for (int n = 0; n < items_count; n++) { AddItem(n); } }
// if (ms_io->RequestSetRange) { for (int n = (int)ms_io->RangeFirstItem; n <= (int)ms_io->RangeLastItem; n++) { UpdateItem(n, ms_io->RangeSelected); } }
// for (ImGuiSelectionRequest& req : ms_io->Requests)
// {
// if (req.Type == ImGuiSelectionRequestType_Clear) { Clear(); }
// if (req.Type == ImGuiSelectionRequestType_SelectAll) { Clear(); for (int n = 0; n < items_count; n++) { AddItem(n); } }
// if (req.Type == ImGuiSelectionRequestType_SetRange) { for (int n = (int)ms_io->RangeFirstItem; n <= (int)ms_io->RangeLastItem; n++) { UpdateItem(n, ms_io->RangeSelected); } }
ImGuiMultiSelectIOBeginIO;// Requests are set and returned by BeginMultiSelect(), written to by user during the loop.
ImGuiMultiSelectIOEndIO;// Requests are set during the loop and returned by EndMultiSelect().
boolLoopRequestClear;
boolLoopRequestSelectAll;
boolIsFocused;// Set if currently focusing the selection scope (any item of the selection). May be used if you have custom shortcut associated to selection.
boolIsSetRange;// Set by BeginMultiSelect() when using Shift+Navigation. Because scrolling may be affected we can't afford a frame of lag with Shift+Navigation.
// Apply Clear/SelectAll requests requested by BeginMultiSelect().
// This is only useful if the user hasn't processed them already, and this only works if the user isn't using the clipper.
// If you are using a clipper (aka not submitting every element of the list) you need to process the Clear/SelectAll request after calling BeginMultiSelect()
if(ms->BeginIO.RequestClear)
if(ms->LoopRequestClear)
selected=false;
elseif(ms->BeginIO.RequestSelectAll)
elseif(ms->LoopRequestSelectAll)
selected=true;
// When using SHIFT+Nav: because it can incur scrolling we cannot afford a frame of lag with the selection highlight (otherwise scrolling would happen before selection)