RangeSelect/MultiSelect: Demo: rework ExampleSelection with an ExampleSelectionAdapter layer, allowing to share more code accross examples using different storage systems.
// [Advanced] Helper class to simulate storage of a multi-selection state, used by the BeginMultiSelect() demos.
// We use a little extra indirection layer here in order to use and demonstrate different ways to
// We use ImGuiStorage (simple key->value storage) to avoid external dependencies but it's probably not optimal.
// - identify items in the multi-selection system (using index? using identifiers? using pointers?)
// - store our persistent selection data (using index? using identifiers? using pointers?)
// 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 we could add a IndexToUserData() function which would be used when calling SetNextItemSelectionUserData(), but omitting it makes things clearer.
structExampleSelectionAdapter
{
void*Data=NULL;
int(*UserDataToIndex)(ExampleSelectionAdapter*self,ImGuiSelectionUserDataitem_data);// Function to convert item ImGuiSelectionUserData to item index
ImGuiID(*IndexToStorage)(ExampleSelectionAdapter*self,intidx);// Function to convert item index to data stored in persistent selection
// Example for the simplest case: UserData==Index==SelectionStorage (this adapter doesn't even need to use the item data field)
voidSetupForDirectIndexes()
{
UserDataToIndex=[](ExampleSelectionAdapter*,ImGuiSelectionUserDataitem_data){return(int)item_data;};// No transform: Pass indices to SetNextItemSelectionUserData()
IndexToStorage=[](ExampleSelectionAdapter*,intidx){return(ImGuiID)idx;};// No transform: Store indices inside persistent selection storage
}
};
// [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:
// To store a single-selection:
// - You only need a single variable and don't need any of this!
// - You only need a single variable and don't need any of this!
// To store a multi-selection, in your real application you could:
// To store a multi-selection, in your real application you could:
// - Use external storage: e.g. unordered_set/set/hash/map/interval trees (storing indices, objects id, etc.)
// - A) Use external storage: e.g. std::set<index>, std::set<MyObjectId>, std::vector<MyObjectId>, interval trees, etc.
// are generally appropriate. Even a large array of bool might work for you... This is what we are doing here.
// are generally appropriate. Even a large array of bool might work for you...
// - Use intrusively stored selection (e.g. 'bool IsSelected' inside your object).
// This code here use ImGuiStorage (a simple key->value storage) as a std::set replacement to avoid external dependencies.
// - This is simple, but it means you cannot have multiple simultaneous views over your objects.
// - B) Or use intrusively stored selection (e.g. 'bool IsSelected' inside your object).
// - This is what many of the simpler demos in other sections of this file are using (so they are not using this class).
// - 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:
// - 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).
// either you maintain it (which requires storage outside of objects) either you recompute (which may be costly for large sets).
// - So I would suggest that using intrusive selection for multi-select is not the most adequate.
// - So we suggest using intrusive selection for multi-select is not really adequate.
// 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); } }