// Our multi-selection system doesn't make assumption about:
// - how you want to identify items in multi-selection API? Indices(*) / Custom Identifiers / Pointers ?
// - how you want to store persistent selection data? Indices / Custom Identifiers(*) / Pointers ?
// (*) This is the suggested solution: pass indices to API (because easy to iterate/interpolate) + persist your custom identifiers inside selection data.
// In this demo we:
// - always use indices in the multi-selection API (passed to SetNextItemSelectionUserData(), retrieved in ImGuiMultiSelectIO)
// - use a little extra indirection layer in order to abstract how persistent selection data is derived from an index.
// - in some cases we use Index as custom identifier, in some cases we read from some custom item data structure.
// Many combinations are possible depending on how you prefer to store your items and how you prefer to store your selection.
// WHEN YOUR APPLICATION SETTLES ON A CHOICE, YOU WILL PROBABLY PREFER TO GET RID OF THIS UNNECESSARY 'ExampleSelectionAdapter' INDIRECTION LOGIC.
// In theory, for maximum abstraction, this class could contains IndexToUserData() and UserDataToIndex() functions,
// but because we always use indices in SetNextItemSelectionUserData() in the demo, we omit that for clarify.
structExampleSelectionAdapter
{
void*Data=NULL;
ImGuiID(*IndexToStorage)(ExampleSelectionAdapter*self,intidx);// Function to convert item index to data stored in persistent selection
// [Advanced] Helper class to store multi-selection state, used by the BeginMultiSelect() demos.
// Provide an abstraction layer for the purpose of the demo showcasing different forms of underlying selection data.
// To store a single-selection:
// - You only need a single variable and don't need any of this!
// To store a multi-selection, in your real application you could:
// - A) Use external storage: e.g. std::set<index>, std::set<MyObjectId>, std::vector<MyObjectId>, interval trees, etc.
// - A) Use external storage: e.g. std::set<MyObjectId>, std::vector<MyObjectId>, std::set<index>, interval trees, etc.
// are generally appropriate. Even a large array of bool might work for you...
// This code here use ImGuiStorage (a simple key->value storage) as a std::set replacement to avoid external dependencies.
// - B) Or use intrusively stored selection (e.g. 'bool IsSelected' inside your object).
// - It is simple, but it means you cannot have multiple simultaneous views over your objects.
// - Some of our features requires you to provide the selection _size_, which with this specific strategy require additional work:
// either you maintain it (which requires storage outside of objects) either you recompute (which may be costly for large sets).
// - That means you cannot have multiple simultaneous views over your objects.
// - Some of our features requires you to provide the selection _size_, which with this specific strategy require additional work.
// - So we suggest using intrusive selection for multi-select is not really adequate.
// Our multi-selection system doesn't make assumption about:
// - how you want to identify items in multi-selection API? Indices(*) / Custom Identifiers / Pointers ?
// - how you want to store persistent selection data? Indices / Custom Identifiers(*) / Pointers ?
// (*) This is the suggested solution: pass indices to API (because easy to iterate/interpolate) + persist your custom identifiers inside selection data.
// In this demo we:
// - always use indices in the multi-selection API (passed to SetNextItemSelectionUserData(), retrieved in ImGuiMultiSelectIO)
// - use a little extra indirection layer in order to abstract how persistent selection data is derived from an index.
// - in some cases we use Index as custom identifier
// - in some cases we read an ID from some custom item data structure (this is closer to what you would do in your codebase)
// Many combinations are possible depending on how you prefer to store your items and how you prefer to store your selection.
// WHEN YOUR APPLICATION SETTLES ON A CHOICE, YOU WILL PROBABLY PREFER TO GET RID OF THE UNNECESSARY 'AdapterIndexToStorageId()' INDIRECTION LOGIC.
// In theory, for maximum abstraction, this class could contains AdapterIndexToUserData() and AdapterUserDataToIndex() functions as well,
// but because we always use indices in SetNextItemSelectionUserData() in the demo, we omit that for clarify.
structExampleSelection
{
// Data
ImGuiStorageStorage;// Selection set
ImGuiStorageStorage;// Selection set (think of this as similar to e.g. std::set<ImGuiID>)
intSize;// Number of selected items (== number of 1 in the Storage, maintained by this class).
// Apply requests coming from BeginMultiSelect() and EndMultiSelect().
// - Must be done in this order! Clear->SelectAll->SetRange. Enable 'Demo->Tools->Debug Log->Selection' to see selection requests as they happen.
// - Honoring RequestSetRange requires that you can iterate/interpolate between RangeFirstItem and RangeLastItem.
// - Enable 'Demo->Tools->Debug Log->Selection' to see selection requests as they happen.
// - Honoring SetRange requests requires that you can iterate/interpolate between RangeFirstItem and RangeLastItem.
// - In this demo we often submit indices to SetNextItemSelectionUserData() + store the same indices in persistent selection.
// - Your code may do differently. If you store pointers or objects ID in ImGuiSelectionUserData you may need to perform
// a lookup in order to have some way to iterate/interpolate between two items.
@ -2824,34 +2820,34 @@ struct ExampleSelection
// 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); } }