1
0
mirror of https://github.com/ocornut/imgui.git synced 2025-02-20 04:21:01 +01:00

Updated Multi Select (markdown)

omar 2024-06-06 12:39:26 +02:00
parent 947d01cc0d
commit 69a37f55b7

@ -8,10 +8,9 @@
- [Overview](#Overview)
- [Features](#Features)
- [Demo Code](#demo-code)
- [Principal APIs](#principal-apis)
- [Typical usage flow](#typical-usage-flow)
- [About ImGuiSelectionUserData](#about-imguiselectionuserdata)
- [Using ImGuiSelectionBasicStorage helper](#using-ImGuiSelectionBasicStorage-helper)
- [Main API](#main-api)
- [About ImGuiSelectionUserData](#about-imguiselectionuserdata)
- [Using ImGuiSelectionExternalStorage helper](#using-ImGuiSelectionExternalStorage-helper)
----
@ -40,7 +39,56 @@
Always refer to demo code for usage.
Demos are in `Demo->Widgets->Selection State & Multi-Select` and `Demo->Examples->Assets Browser`.
### Principal APIs
----
### Using ImGuiSelectionBasicStorage helper
:bulb: `ImGuiSelectionBasicStorage` is an optional helper to store multi-selection state + apply multi-selection requests.
- Used by our demos and provided as a convenience to easily implement basic multi-selection.
- USING THIS IS NOT MANDATORY. This is only a helper and not a required API.
Minimum pseudo-code example using this helper:
```cpp
static vector<MyItem> items; // Your items
static ImGuiSelectionBasicStorage selection; // Your selection
selection.AdapterData = (void*)&items; // Setup adapter so selection.ApplyRequests() function can convert indexes to identifiers.
selection.AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage* self, int idx) { return ((vector<MyItem>*)self->AdapterData))[idx].ID; };
ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_None, selection.Size, items.Size);
selection.ApplyRequests(ms_io);
for (int idx = 0; idx < items.Size; idx++)
{
bool item_is_selected = selection.Contains(items[idx].ID);
ImGui::SetNextItemSelectionUserData(idx);
ImGui::Selectable(label, item_is_selected);
}
ms_io = ImGui::EndMultiSelect();
selection.ApplyRequests(ms_io);
```
To store a multi-selection, in your real application you could:
- A) Use this helper as a convenience. We use our simple key->value ImGuiStorage as a std::set<ImGuiID> replacement.
- B) Use your own external storage: e.g. std::set<MyObjectId>, std::vector<MyObjectId>, interval trees, etc.
- C) Use intrusively stored selection (e.g. 'bool IsSelected' inside objects). Not recommended because you can't have multiple views over same objects. Also some features requires to provide selection _size_, which with this strategy requires additional work.
Our BeginMultiSelect() api/system doesn't make assumption about:
- how you want to identify items in multi-selection API? (Indices or Custom Ids or Pointers? Indices are better: easy to iterate/interpolate)
- how you want to store persistent selection data? (Indices or Custom Ids or Pointers? Custom Ids is better: as selection can persist)
In ImGuiSelectionBasicStorage we:
- always use indices in the multi-selection API (passed to SetNextItemSelectionUserData(), retrieved in ImGuiMultiSelectIO)
- use the AdapterIndexToStorageId() indirection layer to abstract how persistent selection data is derived from an index.
- in some cases we use Index as custom identifier (default implementation returns Index cast as Identifier): only valid for a never changing item list.
- in some cases we read an ID from some custom item data structure (better, and 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 may want to get rid of this indirection layer and do your own thing.
----
### Main API
:bulb: This is the low-level API. When using the `ImGuiSelectionBasicStorage` you may not need to care about details of `ImGuiMultiSelectIO` and `ImGuiSelectionRequest`.
```cpp
// Main API
@ -84,8 +132,7 @@ enum ImGuiSelectionRequestType
};
```
### Typical usage flow
TL;DR;
- Identify submitted items with `SetNextItemSelectionUserData()`, most likely using an index into your current data-set.
- Store and maintain actual selection data using persistent object identifiers.
- Usage Flow:
@ -117,51 +164,6 @@ enum ImGuiSelectionRequestType
----
### Using ImGuiSelectionBasicStorage helper
`ImGuiSelectionBasicStorage` is an optional helper to store multi-selection state + apply multi-selection requests.
- Used by our demos and provided as a convenience to easily implement basic multi-selection.
- USING THIS IS NOT MANDATORY. This is only a helper and not a required API. Advanced users are likely to implement their own.
Minimum pseudo-code example using this helper:
```cpp
static vector<MyItem> items; // Your items
static ImGuiSelectionBasicStorage selection; // Your selection
selection.AdapterData = (void*)&items; // Setup adapter so selection.ApplyRequests() function can convert indexes to identifiers.
selection.AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage* self, int idx) { return ((vector<MyItem>*)self->AdapterData))[idx].ID; };
ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_None, selection.Size, items.Size);
selection.ApplyRequests(ms_io);
for (int idx = 0; idx < items.Size; idx++)
{
bool item_is_selected = selection.Contains(items[idx].ID);
ImGui::SetNextItemSelectionUserData(idx);
ImGui::Selectable(label, item_is_selected);
}
ms_io = ImGui::EndMultiSelect();
selection.ApplyRequests(ms_io);
```
To store a multi-selection, in your real application you could:
- A) Use this helper as a convenience. We use our simple key->value ImGuiStorage as a std::set<ImGuiID> replacement.
- B) Use your own external storage: e.g. std::set<MyObjectId>, std::vector<MyObjectId>, interval trees, etc.
- C) Use intrusively stored selection (e.g. 'bool IsSelected' inside objects). Not recommended because you can't have multiple views over same objects. Also some features requires to provide selection _size_, which with this strategy requires additional work.
Our BeginMultiSelect() api/system doesn't make assumption about:
- how you want to identify items in multi-selection API? (Indices or Custom Ids or Pointers? Indices are better: easy to iterate/interpolate)
- how you want to store persistent selection data? (Indices or Custom Ids or Pointers? Custom Ids is better: as selection can persist)
In ImGuiSelectionBasicStorage we:
- always use indices in the multi-selection API (passed to SetNextItemSelectionUserData(), retrieved in ImGuiMultiSelectIO)
- use the AdapterIndexToStorageId() indirection layer to abstract how persistent selection data is derived from an index.
- in some cases we use Index as custom identifier (default implementation returns Index cast as Identifier): only valid for a never changing item list.
- in some cases we read an ID from some custom item data structure (better, and 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 may want to get rid of this indirection layer and do your own thing.
----
### Using ImGuiSelectionExernalStorage helper
Optional helper to apply multi-selection requests to existing randomly accessible storage.