Merge branch 'features/range_select'

This commit is contained in:
ocornut 2024-07-18 18:21:31 +02:00
commit d7e605d430
6 changed files with 2535 additions and 81 deletions

View File

@ -77,6 +77,57 @@ Other changes:
Disabling this was previously possible for Selectable() via a direct flag but not for MenuItem(). Disabling this was previously possible for Selectable() via a direct flag but not for MenuItem().
(#1379, #1468, #2200, #4936, #5216, #7302, #7573) (#1379, #1468, #2200, #4936, #5216, #7302, #7573)
- This was mostly all previously in imgui_internal.h. - This was mostly all previously in imgui_internal.h.
- Multi-Select: added multi-select API and demos. (#1861)
- This system implements standard multi-selection idioms (CTRL+mouse click, CTRL+keyboard moves,
SHIFT+mouse click, SHIFT+keyboard moves, etc.) with support for clipper (not submitting non-visible
items), box-selection with scrolling, and many other details.
- In the spirit of Dear ImGui design, your code owns both items and actual selection data.
This is designed to allow all kinds of selection storage you may use in your application
(e.g. set/map/hash, intrusive selection, interval trees, up to you).
- The supported widgets are Selectable(), Checkbox(). TreeNode() is also technically supported but...
using this correctly is more complicated (you need some sort of linear/random access to your tree,
which is suited to advanced trees setups already implementing filters and clipper.
We will work toward simplifying and demoing this later.
- A helper ImGuiSelectionBasicStorage is provided to facilitate getting started in a typical app.
- Documentation:
- Wiki page https://github.com/ocornut/imgui/wiki/Multi-Select for API overview.
- Demo code.
- Headers are well commented.
- Added BeginMultiSelect(), EndMultiSelect(), SetNextItemSelectionUserData().
- Added IsItemToggledSelection() for use if you need latest selection update during currnet iteration.
- Added ImGuiMultiSelectIO and ImGuiSelectionRequest structures:
- BeginMultiSelect() and EndMultiSelect() return a ImGuiMultiSelectIO structure, which
is mostly an array of ImGuiSelectionRequest actions (clear, select all, set range, etc.)
- Other fields are helpful when using a clipper, or wanting to handle deletion nicely.
- Added ImGuiSelectionBasicStorage helper to store and maintain a selection (optional):
- This is similar to if you used e.g. a std::set<ID> to store a selection, with all the right
glue to honor ImGuiMultiSelectIO requests. Most applications can use that.
- Added ImGuiSelectionExternalStorage helper to maintain an externally stored selection (optional):
- Helpful to easily bind multi-selection to e.g. an array of checkboxes.
- Added ImGuiMultiSelectFlags options:
- ImGuiMultiSelectFlags_SingleSelect
- ImGuiMultiSelectFlags_NoSelectAll
- ImGuiMultiSelectFlags_NoRangeSelect
- ImGuiMultiSelectFlags_NoAutoSelect
- ImGuiMultiSelectFlags_NoAutoClear
- ImGuiMultiSelectFlags_NoAutoClearOnReselect (#7424)
- ImGuiMultiSelectFlags_BoxSelect1d
- ImGuiMultiSelectFlags_BoxSelect2d
- ImGuiMultiSelectFlags_BoxSelectNoScroll
- ImGuiMultiSelectFlags_ClearOnEscape
- ImGuiMultiSelectFlags_ClearOnClickVoid
- ImGuiMultiSelectFlags_ScopeWindow (default), ImGuiMultiSelectFlags_ScopeRect
- ImGuiMultiSelectFlags_SelectOnClick (default), ImGuiMultiSelectFlags_SelectOnClickRelease
- ImGuiMultiSelectFlags_NavWrapX
- Demo: Added "Examples->Assets Browser" demo.
- Demo: Added "Widgets->Selection State & Multi-Select" section, with:
- Multi-Select
- Multi-Select (with clipper)
- Multi-Select (with deletion)
- Multi-Select (dual list box) (#6648)
- Multi-Select (checkboxes)
- Multi-Select (multiple scopes)
- Multi-Select (advanced)
- Clipper: added SeekCursorForItem() function. When using ImGuiListClipper::Begin(INT_MAX) you can - Clipper: added SeekCursorForItem() function. When using ImGuiListClipper::Begin(INT_MAX) you can
can use the clipper without knowing the amount of items beforehand. (#1311) can use the clipper without knowing the amount of items beforehand. (#1311)
In this situation, call ImGuiListClipper::SeekCursorForItem(items_count) as the end of your iteration In this situation, call ImGuiListClipper::SeekCursorForItem(items_count) as the end of your iteration

View File

@ -2558,6 +2558,7 @@ ImGuiStoragePair* ImLowerBound(ImGuiStoragePair* in_begin, ImGuiStoragePair* in_
return in_p; return in_p;
} }
IM_MSVC_RUNTIME_CHECKS_OFF
static int IMGUI_CDECL PairComparerByID(const void* lhs, const void* rhs) static int IMGUI_CDECL PairComparerByID(const void* lhs, const void* rhs)
{ {
// We can't just do a subtraction because qsort uses signed integers and subtracting our ID doesn't play well with that. // We can't just do a subtraction because qsort uses signed integers and subtracting our ID doesn't play well with that.
@ -2571,6 +2572,7 @@ void ImGuiStorage::BuildSortByKey()
{ {
ImQsort(Data.Data, (size_t)Data.Size, sizeof(ImGuiStoragePair), PairComparerByID); ImQsort(Data.Data, (size_t)Data.Size, sizeof(ImGuiStoragePair), PairComparerByID);
} }
IM_MSVC_RUNTIME_CHECKS_RESTORE
int ImGuiStorage::GetInt(ImGuiID key, int default_val) const int ImGuiStorage::GetInt(ImGuiID key, int default_val) const
{ {
@ -3079,9 +3081,27 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper)
data->Ranges.push_back(ImGuiListClipperRange::FromPositions(nav_rect_abs.Min.y, nav_rect_abs.Max.y, 0, 0)); data->Ranges.push_back(ImGuiListClipperRange::FromPositions(nav_rect_abs.Min.y, nav_rect_abs.Max.y, 0, 0));
// Add visible range // Add visible range
float min_y = window->ClipRect.Min.y;
float max_y = window->ClipRect.Max.y;
// Add box selection range
ImGuiBoxSelectState* bs = &g.BoxSelectState;
if (bs->IsActive && bs->Window == window)
{
// FIXME: Selectable() use of half-ItemSpacing isn't consistent in matter of layout, as ItemAdd(bb) stray above ItemSize()'s CursorPos.
// RangeSelect's BoxSelect relies on comparing overlap of previous and current rectangle and is sensitive to that.
// As a workaround we currently half ItemSpacing worth on each side.
min_y -= g.Style.ItemSpacing.y;
max_y += g.Style.ItemSpacing.y;
// Box-select on 2D area requires different clipping.
if (bs->UnclipMode)
data->Ranges.push_back(ImGuiListClipperRange::FromPositions(bs->UnclipRect.Min.y, bs->UnclipRect.Max.y, 0, 0));
}
const int off_min = (is_nav_request && g.NavMoveClipDir == ImGuiDir_Up) ? -1 : 0; const int off_min = (is_nav_request && g.NavMoveClipDir == ImGuiDir_Up) ? -1 : 0;
const int off_max = (is_nav_request && g.NavMoveClipDir == ImGuiDir_Down) ? 1 : 0; const int off_max = (is_nav_request && g.NavMoveClipDir == ImGuiDir_Down) ? 1 : 0;
data->Ranges.push_back(ImGuiListClipperRange::FromPositions(window->ClipRect.Min.y, window->ClipRect.Max.y, off_min, off_max)); data->Ranges.push_back(ImGuiListClipperRange::FromPositions(min_y, max_y, off_min, off_max));
} }
// Convert position ranges to item index ranges // Convert position ranges to item index ranges
@ -3818,6 +3838,9 @@ void ImGui::Shutdown()
g.TablesTempData.clear_destruct(); g.TablesTempData.clear_destruct();
g.DrawChannelsTempMergeBuffer.clear(); g.DrawChannelsTempMergeBuffer.clear();
g.MultiSelectStorage.Clear();
g.MultiSelectTempData.clear_destruct();
g.ClipboardHandlerData.clear(); g.ClipboardHandlerData.clear();
g.MenusIdSubmittedThisFrame.clear(); g.MenusIdSubmittedThisFrame.clear();
g.InputTextState.ClearFreeMemory(); g.InputTextState.ClearFreeMemory();
@ -3928,6 +3951,8 @@ void ImGui::GcCompactTransientMiscBuffers()
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
g.ItemFlagsStack.clear(); g.ItemFlagsStack.clear();
g.GroupStack.clear(); g.GroupStack.clear();
g.MultiSelectTempDataStacked = 0;
g.MultiSelectTempData.clear_destruct();
TableGcCompactSettings(); TableGcCompactSettings();
} }
@ -4052,7 +4077,7 @@ void ImGui::MarkItemEdited(ImGuiID id)
// We accept a MarkItemEdited() on drag and drop targets (see https://github.com/ocornut/imgui/issues/1875#issuecomment-978243343) // We accept a MarkItemEdited() on drag and drop targets (see https://github.com/ocornut/imgui/issues/1875#issuecomment-978243343)
// We accept 'ActiveIdPreviousFrame == id' for InputText() returning an edit after it has been taken ActiveId away (#4714) // We accept 'ActiveIdPreviousFrame == id' for InputText() returning an edit after it has been taken ActiveId away (#4714)
IM_ASSERT(g.DragDropActive || g.ActiveId == id || g.ActiveId == 0 || g.ActiveIdPreviousFrame == id); IM_ASSERT(g.DragDropActive || g.ActiveId == id || g.ActiveId == 0 || g.ActiveIdPreviousFrame == id || (g.CurrentMultiSelect != NULL && g.BoxSelectState.IsActive));
//IM_ASSERT(g.CurrentWindow->DC.LastItemId == id); //IM_ASSERT(g.CurrentWindow->DC.LastItemId == id);
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited; g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
@ -5446,9 +5471,15 @@ bool ImGui::IsItemToggledOpen()
return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledOpen) ? true : false; return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledOpen) ? true : false;
} }
// Call after a Selectable() or TreeNode() involved in multi-selection.
// Useful if you need the per-item information before reaching EndMultiSelect(), e.g. for rendering purpose.
// This is only meant to be called inside a BeginMultiSelect()/EndMultiSelect() block.
// (Outside of multi-select, it would be misleading/ambiguous to report this signal, as widgets
// return e.g. a pressed event and user code is in charge of altering selection in ways we cannot predict.)
bool ImGui::IsItemToggledSelection() bool ImGui::IsItemToggledSelection()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(g.CurrentMultiSelect != NULL); // Can only be used inside a BeginMultiSelect()/EndMultiSelect()
return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledSelection) ? true : false; return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledSelection) ? true : false;
} }
@ -5508,7 +5539,8 @@ void ImGui::SetItemAllowOverlap()
} }
#endif #endif
// FIXME: It might be undesirable that this will likely disable KeyOwner-aware shortcuts systems. Consider a more fine-tuned version for the two users of this function. // This is a shortcut for not taking ownership of 100+ keys, frequently used by drag operations.
// FIXME: It might be undesirable that this will likely disable KeyOwner-aware shortcuts systems. Consider a more fine-tuned version if needed?
void ImGui::SetActiveIdUsingAllKeyboardKeys() void ImGui::SetActiveIdUsingAllKeyboardKeys()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -10060,6 +10092,11 @@ void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, vo
if (log_callback) log_callback(user_data, "Recovered from missing EndTabBar() in '%s'", window->Name); if (log_callback) log_callback(user_data, "Recovered from missing EndTabBar() in '%s'", window->Name);
EndTabBar(); EndTabBar();
} }
while (g.CurrentMultiSelect != NULL && g.CurrentMultiSelect->Storage->Window == window)
{
if (log_callback) log_callback(user_data, "Recovered from missing EndMultiSelect() in '%s'", window->Name);
EndMultiSelect();
}
while (window->DC.TreeDepth > 0) while (window->DC.TreeDepth > 0)
{ {
if (log_callback) log_callback(user_data, "Recovered from missing TreePop() in '%s'", window->Name); if (log_callback) log_callback(user_data, "Recovered from missing TreePop() in '%s'", window->Name);
@ -12251,6 +12288,7 @@ static void ImGui::NavUpdate()
// Process navigation init request (select first/default focus) // Process navigation init request (select first/default focus)
g.NavJustMovedToId = 0; g.NavJustMovedToId = 0;
g.NavJustMovedToFocusScopeId = g.NavJustMovedFromFocusScopeId = 0;
if (g.NavInitResult.ID != 0) if (g.NavInitResult.ID != 0)
NavInitRequestApplyResult(); NavInitRequestApplyResult();
g.NavInitRequest = false; g.NavInitRequest = false;
@ -12403,6 +12441,7 @@ void ImGui::NavInitRequestApplyResult()
ImGuiNavItemData* result = &g.NavInitResult; ImGuiNavItemData* result = &g.NavInitResult;
if (g.NavId != result->ID) if (g.NavId != result->ID)
{ {
g.NavJustMovedFromFocusScopeId = g.NavFocusScopeId;
g.NavJustMovedToId = result->ID; g.NavJustMovedToId = result->ID;
g.NavJustMovedToFocusScopeId = result->FocusScopeId; g.NavJustMovedToFocusScopeId = result->FocusScopeId;
g.NavJustMovedToKeyMods = 0; g.NavJustMovedToKeyMods = 0;
@ -12661,6 +12700,7 @@ void ImGui::NavMoveRequestApplyResult()
// PageUp/PageDown however sets always set NavJustMovedTo (vs Home/End which doesn't) mimicking Windows behavior. // PageUp/PageDown however sets always set NavJustMovedTo (vs Home/End which doesn't) mimicking Windows behavior.
if ((g.NavId != result->ID || (g.NavMoveFlags & ImGuiNavMoveFlags_IsPageMove)) && (g.NavMoveFlags & ImGuiNavMoveFlags_NoSelect) == 0) if ((g.NavId != result->ID || (g.NavMoveFlags & ImGuiNavMoveFlags_IsPageMove)) && (g.NavMoveFlags & ImGuiNavMoveFlags_NoSelect) == 0)
{ {
g.NavJustMovedFromFocusScopeId = g.NavFocusScopeId;
g.NavJustMovedToId = result->ID; g.NavJustMovedToId = result->ID;
g.NavJustMovedToFocusScopeId = result->FocusScopeId; g.NavJustMovedToFocusScopeId = result->FocusScopeId;
g.NavJustMovedToKeyMods = g.NavMoveKeyMods; g.NavJustMovedToKeyMods = g.NavMoveKeyMods;
@ -13419,7 +13459,7 @@ bool ImGui::BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id)
IM_ASSERT(g.DragDropWithinTarget == false && g.DragDropWithinSource == false); // Can't nest BeginDragDropSource() and BeginDragDropTarget() IM_ASSERT(g.DragDropWithinTarget == false && g.DragDropWithinSource == false); // Can't nest BeginDragDropSource() and BeginDragDropTarget()
g.DragDropTargetRect = bb; g.DragDropTargetRect = bb;
g.DragDropTargetClipRect = window->ClipRect; // May want to be overriden by user depending on use case? g.DragDropTargetClipRect = window->ClipRect; // May want to be overridden by user depending on use case?
g.DragDropTargetId = id; g.DragDropTargetId = id;
g.DragDropWithinTarget = true; g.DragDropWithinTarget = true;
return true; return true;
@ -14957,6 +14997,17 @@ void ImGui::ShowMetricsWindow(bool* p_open)
TreePop(); TreePop();
} }
// Details for MultiSelect
if (TreeNode("MultiSelect", "MultiSelect (%d)", g.MultiSelectStorage.GetAliveCount()))
{
ImGuiBoxSelectState* bs = &g.BoxSelectState;
BulletText("BoxSelect ID=0x%08X, Starting = %d, Active %d", bs->ID, bs->IsStarting, bs->IsActive);
for (int n = 0; n < g.MultiSelectStorage.GetMapSize(); n++)
if (ImGuiMultiSelectState* state = g.MultiSelectStorage.TryGetMapData(n))
DebugNodeMultiSelectState(state);
TreePop();
}
// Details for Docking // Details for Docking
#ifdef IMGUI_HAS_DOCK #ifdef IMGUI_HAS_DOCK
if (TreeNode("Docking")) if (TreeNode("Docking"))
@ -15799,7 +15850,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open)
ShowDebugLogFlag("IO", ImGuiDebugLogFlags_EventIO); ShowDebugLogFlag("IO", ImGuiDebugLogFlags_EventIO);
ShowDebugLogFlag("Nav", ImGuiDebugLogFlags_EventNav); ShowDebugLogFlag("Nav", ImGuiDebugLogFlags_EventNav);
ShowDebugLogFlag("Popup", ImGuiDebugLogFlags_EventPopup); ShowDebugLogFlag("Popup", ImGuiDebugLogFlags_EventPopup);
//ShowDebugLogFlag("Selection", ImGuiDebugLogFlags_EventSelection); ShowDebugLogFlag("Selection", ImGuiDebugLogFlags_EventSelection);
ShowDebugLogFlag("InputRouting", ImGuiDebugLogFlags_EventInputRouting); ShowDebugLogFlag("InputRouting", ImGuiDebugLogFlags_EventInputRouting);
if (SmallButton("Clear")) if (SmallButton("Clear"))

171
imgui.h
View File

@ -28,7 +28,7 @@
// Library Version // Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.91.0 WIP" #define IMGUI_VERSION "1.91.0 WIP"
#define IMGUI_VERSION_NUM 19095 #define IMGUI_VERSION_NUM 19096
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
/* /*
@ -44,6 +44,7 @@ Index of this file:
// [SECTION] ImGuiIO // [SECTION] ImGuiIO
// [SECTION] Misc data structures (ImGuiInputTextCallbackData, ImGuiSizeCallbackData, ImGuiPayload) // [SECTION] Misc data structures (ImGuiInputTextCallbackData, ImGuiSizeCallbackData, ImGuiPayload)
// [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, Math Operators, ImColor) // [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, Math Operators, ImColor)
// [SECTION] Multi-Select API flags and structures (ImGuiMultiSelectFlags, ImGuiMultiSelectIO, ImGuiSelectionRequest, ImGuiSelectionBasicStorage, ImGuiSelectionExternalStorage)
// [SECTION] Drawing API (ImDrawCallback, ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawFlags, ImDrawListFlags, ImDrawList, ImDrawData) // [SECTION] Drawing API (ImDrawCallback, ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawFlags, ImDrawListFlags, ImDrawList, ImDrawData)
// [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontGlyphRangesBuilder, ImFontAtlasFlags, ImFontAtlas, ImFont) // [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontGlyphRangesBuilder, ImFontAtlasFlags, ImFontAtlas, ImFont)
// [SECTION] Viewports (ImGuiViewportFlags, ImGuiViewport) // [SECTION] Viewports (ImGuiViewportFlags, ImGuiViewport)
@ -174,9 +175,13 @@ struct ImGuiIO; // Main configuration and I/O between your a
struct ImGuiInputTextCallbackData; // Shared state of InputText() when using custom ImGuiInputTextCallback (rare/advanced use) struct ImGuiInputTextCallbackData; // Shared state of InputText() when using custom ImGuiInputTextCallback (rare/advanced use)
struct ImGuiKeyData; // Storage for ImGuiIO and IsKeyDown(), IsKeyPressed() etc functions. struct ImGuiKeyData; // Storage for ImGuiIO and IsKeyDown(), IsKeyPressed() etc functions.
struct ImGuiListClipper; // Helper to manually clip large list of items struct ImGuiListClipper; // Helper to manually clip large list of items
struct ImGuiMultiSelectIO; // Structure to interact with a BeginMultiSelect()/EndMultiSelect() block
struct ImGuiOnceUponAFrame; // Helper for running a block of code not more than once a frame struct ImGuiOnceUponAFrame; // Helper for running a block of code not more than once a frame
struct ImGuiPayload; // User data payload for drag and drop operations struct ImGuiPayload; // User data payload for drag and drop operations
struct ImGuiPlatformImeData; // Platform IME data for io.PlatformSetImeDataFn() function. struct ImGuiPlatformImeData; // Platform IME data for io.PlatformSetImeDataFn() function.
struct ImGuiSelectionBasicStorage; // Optional helper to store multi-selection state + apply multi-selection requests.
struct ImGuiSelectionExternalStorage;//Optional helper to apply multi-selection requests to existing randomly accessible storage.
struct ImGuiSelectionRequest; // A selection request (stored in ImGuiMultiSelectIO)
struct ImGuiSizeCallbackData; // Callback data when using SetNextWindowSizeConstraints() (rare/advanced use) struct ImGuiSizeCallbackData; // Callback data when using SetNextWindowSizeConstraints() (rare/advanced use)
struct ImGuiStorage; // Helper for key->value storage (container sorted by key) struct ImGuiStorage; // Helper for key->value storage (container sorted by key)
struct ImGuiStoragePair; // Helper for key->value storage (pair) struct ImGuiStoragePair; // Helper for key->value storage (pair)
@ -227,6 +232,7 @@ typedef int ImGuiInputTextFlags; // -> enum ImGuiInputTextFlags_ // Flags: f
typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag(), shared by all items typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag(), shared by all items
typedef int ImGuiKeyChord; // -> ImGuiKey | ImGuiMod_XXX // Flags: for IsKeyChordPressed(), Shortcut() etc. an ImGuiKey optionally OR-ed with one or more ImGuiMod_XXX values. typedef int ImGuiKeyChord; // -> ImGuiKey | ImGuiMod_XXX // Flags: for IsKeyChordPressed(), Shortcut() etc. an ImGuiKey optionally OR-ed with one or more ImGuiMod_XXX values.
typedef int ImGuiPopupFlags; // -> enum ImGuiPopupFlags_ // Flags: for OpenPopup*(), BeginPopupContext*(), IsPopupOpen() typedef int ImGuiPopupFlags; // -> enum ImGuiPopupFlags_ // Flags: for OpenPopup*(), BeginPopupContext*(), IsPopupOpen()
typedef int ImGuiMultiSelectFlags; // -> enum ImGuiMultiSelectFlags_// Flags: for BeginMultiSelect()
typedef int ImGuiSelectableFlags; // -> enum ImGuiSelectableFlags_ // Flags: for Selectable() typedef int ImGuiSelectableFlags; // -> enum ImGuiSelectableFlags_ // Flags: for Selectable()
typedef int ImGuiSliderFlags; // -> enum ImGuiSliderFlags_ // Flags: for DragFloat(), DragInt(), SliderFloat(), SliderInt() etc. typedef int ImGuiSliderFlags; // -> enum ImGuiSliderFlags_ // Flags: for DragFloat(), DragInt(), SliderFloat(), SliderInt() etc.
typedef int ImGuiTabBarFlags; // -> enum ImGuiTabBarFlags_ // Flags: for BeginTabBar() typedef int ImGuiTabBarFlags; // -> enum ImGuiTabBarFlags_ // Flags: for BeginTabBar()
@ -262,6 +268,11 @@ typedef ImWchar32 ImWchar;
typedef ImWchar16 ImWchar; typedef ImWchar16 ImWchar;
#endif #endif
// Multi-Selection item index or identifier when using BeginMultiSelect()
// - Used by SetNextItemSelectionUserData() + and inside ImGuiMultiSelectIO structure.
// - Most users are likely to use this store an item INDEX but this may be used to store a POINTER/ID as well. Read comments near ImGuiMultiSelectIO for details.
typedef ImS64 ImGuiSelectionUserData;
// Callback and functions types // Callback and functions types
typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data); // Callback function for ImGui::InputText() typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data); // Callback function for ImGui::InputText()
typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); // Callback function for ImGui::SetNextWindowSizeConstraints() typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); // Callback function for ImGui::SetNextWindowSizeConstraints()
@ -661,6 +672,18 @@ namespace ImGui
IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool selected" carry the selection state (read-only). Selectable() is clicked is returns true so you can modify your selection state. size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool selected" carry the selection state (read-only). Selectable() is clicked is returns true so you can modify your selection state. size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height
IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper. IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper.
// Multi-selection system for Selectable(), Checkbox() functions*
// - This enables standard multi-selection/range-selection idioms (CTRL+Mouse/Keyboard, SHIFT+Mouse/Keyboard, etc.) in a way that also allow a clipper to be used.
// - ImGuiSelectionUserData is often used to store your item index within the current view (but may store something else).
// - Read comments near ImGuiMultiSelectIO for instructions/details and see 'Demo->Widgets->Selection State & Multi-Select' for demo.
// - (*) TreeNode() is technically supported but... using this correctly is more complicate: you need some sort of linear/random access to your tree,
// which is suited to advanced trees setups already implementing filters and clipper. We will work toward simplifying and demoing this.
// - 'selection_size' and 'items_count' parameters are optional and used by a few features. If they are costly for you to compute, you may avoid them.
IMGUI_API ImGuiMultiSelectIO* BeginMultiSelect(ImGuiMultiSelectFlags flags, int selection_size = -1, int items_count = -1);
IMGUI_API ImGuiMultiSelectIO* EndMultiSelect();
IMGUI_API void SetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_data);
IMGUI_API bool IsItemToggledSelection(); // Was the last item selection state toggled? Useful if you need the per-item information _before_ reaching EndMultiSelect(). We only returns toggle _event_ in order to handle clipping correctly.
// Widgets: List Boxes // Widgets: List Boxes
// - This is essentially a thin wrapper to using BeginChild/EndChild with the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label. // - This is essentially a thin wrapper to using BeginChild/EndChild with the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label.
// - You can submit contents and manage your selection state however you want it, by creating e.g. Selectable() or any other items. // - You can submit contents and manage your selection state however you want it, by creating e.g. Selectable() or any other items.
@ -2702,6 +2725,152 @@ struct ImColor
static ImColor HSV(float h, float s, float v, float a = 1.0f) { float r, g, b; ImGui::ColorConvertHSVtoRGB(h, s, v, r, g, b); return ImColor(r, g, b, a); } static ImColor HSV(float h, float s, float v, float a = 1.0f) { float r, g, b; ImGui::ColorConvertHSVtoRGB(h, s, v, r, g, b); return ImColor(r, g, b, a); }
}; };
//-----------------------------------------------------------------------------
// [SECTION] Multi-Select API flags and structures (ImGuiMultiSelectFlags, ImGuiSelectionRequestType, ImGuiSelectionRequest, ImGuiMultiSelectIO, ImGuiSelectionBasicStorage)
//-----------------------------------------------------------------------------
// Multi-selection system
// Documentation at: https://github.com/ocornut/imgui/wiki/Multi-Select
// - Refer to 'Demo->Widgets->Selection State & Multi-Select' for demos using this.
// - This system implements standard multi-selection idioms (CTRL+Mouse/Keyboard, SHIFT+Mouse/Keyboard, etc)
// with support for clipper (skipping non-visible items), box-select and many other details.
// - Selectable(), Checkbox() are supported but custom widgets may use it as well.
// - TreeNode() is technically supported but... using this correctly is more complicated: you need some sort of linear/random access to your tree,
// which is suited to advanced trees setups also implementing filters and clipper. We will work toward simplifying and demoing it.
// - In the spirit of Dear ImGui design, your code owns actual selection data.
// This is designed to allow all kinds of selection storage you may use in your application e.g. set/map/hash.
// About ImGuiSelectionBasicStorage:
// - This is an optional helper to store a selection state and apply selection requests.
// - It is used by our demos and provided as a convenience to quickly implement multi-selection.
// Usage:
// - 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:
// BEGIN - (1) Call BeginMultiSelect() and retrieve the ImGuiMultiSelectIO* result.
// - (2) Honor request list (SetAll/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.IncludeItemByIndex(). If storing indices in ImGuiSelectionUserData, a simple clipper.IncludeItemByIndex(ms_io->RangeSrcItem) call will work.
// LOOP - (4) Submit your items with SetNextItemSelectionUserData() + Selectable()/TreeNode() calls.
// END - (5) Call EndMultiSelect() and retrieve the ImGuiMultiSelectIO* result.
// - (6) Honor request list (SetAll/SetRange requests) by updating your selection data. Same code as Step 2.
// If you submit all items (no clipper), Step 2 and 3 are optional and will be handled by each item themselves. It is fine to always honor those steps.
// About ImGuiSelectionUserData:
// - This can store an application-defined identifier (e.g. index or pointer) submitted via SetNextItemSelectionUserData().
// - In return we store them into RangeSrcItem/RangeFirstItem/RangeLastItem and other fields in ImGuiMultiSelectIO.
// - Most applications will store an object INDEX, hence the chosen name and type. Storing an index is natural, because
// SetRange requests will give you two end-points and you will need to iterate/interpolate between them to update your selection.
// - However it is perfectly possible to store a POINTER or another IDENTIFIER inside ImGuiSelectionUserData.
// Our system never assume that you identify items by indices, it never attempts to interpolate between two values.
// - As most users will want to store an index, for convenience and to reduce confusion we use ImS64 instead of void*,
// being syntactically easier to downcast. Feel free to reinterpret_cast and store a pointer inside.
// Flags for BeginMultiSelect()
enum ImGuiMultiSelectFlags_
{
ImGuiMultiSelectFlags_None = 0,
ImGuiMultiSelectFlags_SingleSelect = 1 << 0, // Disable selecting more than one item. This is available to allow single-selection code to share same code/logic if desired. It essentially disables the main purpose of BeginMultiSelect() tho!
ImGuiMultiSelectFlags_NoSelectAll = 1 << 1, // Disable CTRL+A shortcut to select all.
ImGuiMultiSelectFlags_NoRangeSelect = 1 << 2, // Disable Shift+selection mouse/keyboard support (useful for unordered 2D selection).
ImGuiMultiSelectFlags_NoAutoSelect = 1 << 3, // Disable selecting items when navigating (useful for e.g. supporting range-select in a list of checkboxes)
ImGuiMultiSelectFlags_NoAutoClear = 1 << 4, // Disable clearing selection when navigating or selecting another one (generally used with ImGuiMultiSelectFlags_NoAutoSelect. useful for e.g. supporting range-select in a list of checkboxes)
ImGuiMultiSelectFlags_NoAutoClearOnReselect = 1 << 5, // Disable clearing selection when clicking/selecting an already selected item
ImGuiMultiSelectFlags_BoxSelect1d = 1 << 6, // Enable box-selection with same width and same x pos items (e.g. only full row Selectable()). Box-selection works better with little bit of spacing between items hit-box in order to be able to aim at empty space.
ImGuiMultiSelectFlags_BoxSelect2d = 1 << 7, // Enable box-selection with varying width or varying x pos items support (e.g. different width labels, or 2D layout/grid). This is slower: alters clipping logic so that e.g. horizontal movements will update selection of normally clipped items.
ImGuiMultiSelectFlags_BoxSelectNoScroll = 1 << 8, // Disable scrolling when box-selecting near edges of scope.
ImGuiMultiSelectFlags_ClearOnEscape = 1 << 9, // Clear selection when pressing Escape while scope is focused.
ImGuiMultiSelectFlags_ClearOnClickVoid = 1 << 10, // Clear selection when clicking on empty location within scope.
ImGuiMultiSelectFlags_ScopeWindow = 1 << 11, // Scope for _BoxSelect and _ClearOnClickVoid is whole window (Default). Use if BeginMultiSelect() covers a whole window or used a single time in same window.
ImGuiMultiSelectFlags_ScopeRect = 1 << 12, // Scope for _BoxSelect and _ClearOnClickVoid is rectangle encompassing BeginMultiSelect()/EndMultiSelect(). Use if BeginMultiSelect() is called multiple times in same window.
ImGuiMultiSelectFlags_SelectOnClick = 1 << 13, // Apply selection on mouse down when clicking on unselected item. (Default)
ImGuiMultiSelectFlags_SelectOnClickRelease = 1 << 14, // Apply selection on mouse release when clicking an unselected item. Allow dragging an unselected item without altering selection.
//ImGuiMultiSelectFlags_RangeSelect2d = 1 << 15, // Shift+Selection uses 2d geometry instead of linear sequence, so possible to use Shift+up/down to select vertically in grid. Analogous to what BoxSelect does.
ImGuiMultiSelectFlags_NavWrapX = 1 << 16, // [Temporary] Enable navigation wrapping on X axis. Provided as a convenience because we don't have a design for the general Nav API for this yet. When the more general feature be public we may obsolete this flag in favor of new one.
};
// Main IO structure returned by BeginMultiSelect()/EndMultiSelect().
// This mainly contains a list of selection requests.
// - Use 'Demo->Tools->Debug Log->Selection' to see requests as they happen.
// - Some fields are only useful if your list is dynamic and allows deletion (getting post-deletion focus/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.
struct ImGuiMultiSelectIO
{
//------------------------------------------// BeginMultiSelect / EndMultiSelect
ImVector<ImGuiSelectionRequest> Requests; // ms:w, app:r / ms:w app:r // Requests to apply to your selection data.
ImGuiSelectionUserData RangeSrcItem; // ms:w app:r / // (If using clipper) Begin: Source item (often the first selected item) must never be clipped: use clipper.IncludeItemByIndex() to ensure it is submitted.
ImGuiSelectionUserData NavIdItem; // ms:w, app:r / // (If using deletion) Last known SetNextItemSelectionUserData() value for NavId (if part of submitted items).
bool NavIdSelected; // ms:w, app:r / app:r // (If using deletion) Last known selection state for NavId (if part of submitted items).
bool RangeSrcReset; // app:w / ms:r // (If using deletion) Set before EndMultiSelect() to reset ResetSrcItem (e.g. if deleted selection).
int ItemsCount; // ms:w, app:r / app:r // 'int items_count' parameter to BeginMultiSelect() is copied here for convenience, allowing simpler calls to your ApplyRequests handler. Not used internally.
};
// Selection request type
enum ImGuiSelectionRequestType
{
ImGuiSelectionRequestType_None = 0,
ImGuiSelectionRequestType_SetAll, // Request app to clear selection (if Selected==false) or select all items (if Selected==true). We cannot set RangeFirstItem/RangeLastItem as its contents is entirely up to user (not necessarily an index)
ImGuiSelectionRequestType_SetRange, // Request app to select/unselect [RangeFirstItem..RangeLastItem] items (inclusive) based on value of Selected. Only EndMultiSelect() request this, app code can read after BeginMultiSelect() and it will always be false.
};
// Selection request item
struct ImGuiSelectionRequest
{
//------------------------------------------// BeginMultiSelect / EndMultiSelect
ImGuiSelectionRequestType Type; // ms:w, app:r / ms:w, app:r // Request type. You'll most often receive 1 Clear + 1 SetRange with a single-item range.
bool Selected; // ms:w, app:r / ms:w, app:r // Parameter for SetAll/SetRange requests (true = select, false = unselect)
ImS8 RangeDirection; // / ms:w app:r // Parameter for SetRange request: +1 when RangeFirstItem comes before RangeLastItem, -1 otherwise. Useful if you want to preserve selection order on a backward Shift+Click.
ImGuiSelectionUserData RangeFirstItem; // / ms:w, app:r // Parameter for SetRange request (this is generally == RangeSrcItem when shift selecting from top to bottom).
ImGuiSelectionUserData RangeLastItem; // / ms:w, app:r // Parameter for SetRange request (this is generally == RangeSrcItem when shift selecting from bottom to top). Inclusive!
};
// 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.
// - Iterate selection with 'void* it = NULL; ImGuiID id; while (selection.GetNextSelectedItem(&it, &id)) { ... }'
// Or you can check 'if (Contains(id)) { ... }' for each possible object if their number is not too high to iterate.
// - USING THIS IS NOT MANDATORY. This is only a helper and not a required API.
// To store a multi-selection, in your application you could:
// - Use this helper as a convenience. We use our simple key->value ImGuiStorage as a std::set<ImGuiID> replacement.
// - Use your own external storage: e.g. std::set<MyObjectId>, std::vector<MyObjectId>, interval trees, intrusively stored selection etc.
// 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.
// - use decently optimized logic to allow queries and insertion of very large selection sets.
// - do not preserve selection order.
// Many combinations are possible depending on how you prefer to store your items and how you prefer to store your selection.
// Large applications are likely to eventually want to get rid of this indirection layer and do their own thing.
// See https://github.com/ocornut/imgui/wiki/Multi-Select for details and pseudo-code using this helper.
struct ImGuiSelectionBasicStorage
{
// Members
int Size; // // Number of selected items, maintained by this helper.
bool PreserveOrder; // = false // GetNextSelectedItem() will return ordered selection (currently implemented by two additional sorts of selection. Could be improved)
void* UserData; // = NULL // User data for use by adapter function // e.g. selection.UserData = (void*)my_items;
ImGuiID (*AdapterIndexToStorageId)(ImGuiSelectionBasicStorage* self, int idx); // e.g. selection.AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage* self, int idx) { return ((MyItems**)self->UserData)[idx]->ID; };
int _SelectionOrder;// [Internal] Increasing counter to store selection order
ImGuiStorage _Storage; // [Internal] Selection set. Think of this as similar to e.g. std::set<ImGuiID>. Prefer not accessing directly: iterate with GetNextSelectedItem().
// Methods
ImGuiSelectionBasicStorage();
IMGUI_API void ApplyRequests(ImGuiMultiSelectIO* ms_io); // Apply selection requests coming from BeginMultiSelect() and EndMultiSelect() functions. It uses 'items_count' passed to BeginMultiSelect()
IMGUI_API bool Contains(ImGuiID id) const; // Query if an item id is in selection.
IMGUI_API void Clear(); // Clear selection
IMGUI_API void Swap(ImGuiSelectionBasicStorage& r); // Swap two selections
IMGUI_API void SetItemSelected(ImGuiID id, bool selected); // Add/remove an item from selection (generally done by ApplyRequests() function)
IMGUI_API bool GetNextSelectedItem(void** opaque_it, ImGuiID* out_id); // Iterate selection with 'void* it = NULL; ImGuiId id; while (selection.GetNextSelectedItem(&it, &id)) { ... }'
inline ImGuiID GetStorageIdFromIndex(int idx) { return AdapterIndexToStorageId(this, idx); } // Convert index to item id based on provided adapter.
};
// Optional helper to apply multi-selection requests to existing randomly accessible storage.
// Convenient if you want to quickly wire multi-select API on e.g. an array of bool or items storing their own selection state.
struct ImGuiSelectionExternalStorage
{
// Members
void* UserData; // User data for use by adapter function // e.g. selection.UserData = (void*)my_items;
void (*AdapterSetItemSelected)(ImGuiSelectionExternalStorage* self, int idx, bool selected); // e.g. AdapterSetItemSelected = [](ImGuiSelectionExternalStorage* self, int idx, bool selected) { ((MyItems**)self->UserData)[idx]->Selected = selected; }
// Methods
IMGUI_API ImGuiSelectionExternalStorage();
IMGUI_API void ApplyRequests(ImGuiMultiSelectIO* ms_io); // Apply selection requests by using AdapterSetItemSelected() calls
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Drawing API (ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawListFlags, ImDrawList, ImDrawData) // [SECTION] Drawing API (ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawListFlags, ImDrawList, ImDrawData)
// Hold a series of drawing commands. The user provides a renderer for ImDrawData which essentially contains an array of ImDrawList. // Hold a series of drawing commands. The user provides a renderer for ImDrawData which essentially contains an array of ImDrawList.

File diff suppressed because it is too large Load Diff

View File

@ -22,6 +22,7 @@ Index of this file:
// [SECTION] Navigation support // [SECTION] Navigation support
// [SECTION] Typing-select support // [SECTION] Typing-select support
// [SECTION] Columns support // [SECTION] Columns support
// [SECTION] Box-select support
// [SECTION] Multi-select support // [SECTION] Multi-select support
// [SECTION] Docking support // [SECTION] Docking support
// [SECTION] Viewport support // [SECTION] Viewport support
@ -123,6 +124,7 @@ struct ImBitVector; // Store 1-bit per value
struct ImRect; // An axis-aligned rectangle (2 points) struct ImRect; // An axis-aligned rectangle (2 points)
struct ImDrawDataBuilder; // Helper to build a ImDrawData instance struct ImDrawDataBuilder; // Helper to build a ImDrawData instance
struct ImDrawListSharedData; // Data shared between all ImDrawList instances struct ImDrawListSharedData; // Data shared between all ImDrawList instances
struct ImGuiBoxSelectState; // Box-selection state (currently used by multi-selection, could potentially be used by others)
struct ImGuiColorMod; // Stacked color modifier, backup of modified data so we can restore it struct ImGuiColorMod; // Stacked color modifier, backup of modified data so we can restore it
struct ImGuiContext; // Main Dear ImGui context struct ImGuiContext; // Main Dear ImGui context
struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine
@ -134,6 +136,8 @@ struct ImGuiInputTextDeactivateData;// Short term storage to backup text of a de
struct ImGuiLastItemData; // Status storage for last submitted items struct ImGuiLastItemData; // Status storage for last submitted items
struct ImGuiLocEntry; // A localization entry. struct ImGuiLocEntry; // A localization entry.
struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only
struct ImGuiMultiSelectState; // Multi-selection persistent state (for focused selection).
struct ImGuiMultiSelectTempData; // Multi-selection temporary state (while traversing).
struct ImGuiNavItemData; // Result of a gamepad/keyboard directional navigation move query result struct ImGuiNavItemData; // Result of a gamepad/keyboard directional navigation move query result
struct ImGuiMetricsConfig; // Storage for ShowMetricsWindow() and DebugNodeXXX() functions struct ImGuiMetricsConfig; // Storage for ShowMetricsWindow() and DebugNodeXXX() functions
struct ImGuiNextWindowData; // Storage for SetNextWindow** functions struct ImGuiNextWindowData; // Storage for SetNextWindow** functions
@ -488,6 +492,7 @@ static inline int ImModPositive(int a, int b)
static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; } static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); } static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
static inline float ImLinearSweep(float current, float target, float speed) { if (current < target) return ImMin(current + speed, target); if (current > target) return ImMax(current - speed, target); return current; } static inline float ImLinearSweep(float current, float target, float speed) { if (current < target) return ImMin(current + speed, target); if (current > target) return ImMax(current - speed, target); return current; }
static inline float ImLinearRemapClamp(float s0, float s1, float d0, float d1, float x) { return ImSaturate((x - s0) / (s1 - s0)) * (d1 - d0) + d0; }
static inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); } static inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
static inline bool ImIsFloatAboveGuaranteedIntegerPrecision(float f) { return f <= -16777216 || f >= 16777216; } static inline bool ImIsFloatAboveGuaranteedIntegerPrecision(float f) { return f <= -16777216 || f >= 16777216; }
static inline float ImExponentialMovingAverage(float avg, float sample, int n) { avg -= avg / n; avg += sample / n; return avg; } static inline float ImExponentialMovingAverage(float avg, float sample, int n) { avg -= avg / n; avg += sample / n; return avg; }
@ -854,6 +859,7 @@ enum ImGuiItemFlagsPrivate_
// Controlled by widget code // Controlled by widget code
ImGuiItemFlags_Inputable = 1 << 20, // false // [WIP] Auto-activate input mode when tab focused. Currently only used and supported by a few items before it becomes a generic feature. ImGuiItemFlags_Inputable = 1 << 20, // false // [WIP] Auto-activate input mode when tab focused. Currently only used and supported by a few items before it becomes a generic feature.
ImGuiItemFlags_HasSelectionUserData = 1 << 21, // false // Set by SetNextItemSelectionUserData() ImGuiItemFlags_HasSelectionUserData = 1 << 21, // false // Set by SetNextItemSelectionUserData()
ImGuiItemFlags_IsMultiSelect = 1 << 22, // false // Set by SetNextItemSelectionUserData()
ImGuiItemFlags_Default_ = ImGuiItemFlags_AutoClosePopups, // Please don't change, use PushItemFlag() instead. ImGuiItemFlags_Default_ = ImGuiItemFlags_AutoClosePopups, // Please don't change, use PushItemFlag() instead.
@ -1201,10 +1207,6 @@ struct ImGuiNextWindowData
inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; } inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; }
}; };
// Multi-Selection item index or identifier when using SetNextItemSelectionUserData()/BeginMultiSelect()
// (Most users are likely to use this store an item INDEX but this may be used to store a POINTER as well.)
typedef ImS64 ImGuiSelectionUserData;
enum ImGuiNextItemDataFlags_ enum ImGuiNextItemDataFlags_
{ {
ImGuiNextItemDataFlags_None = 0, ImGuiNextItemDataFlags_None = 0,
@ -1217,8 +1219,9 @@ enum ImGuiNextItemDataFlags_
struct ImGuiNextItemData struct ImGuiNextItemData
{ {
ImGuiNextItemDataFlags Flags; ImGuiNextItemDataFlags Flags;
ImGuiItemFlags ItemFlags; // Currently only tested/used for ImGuiItemFlags_AllowOverlap. ImGuiItemFlags ItemFlags; // Currently only tested/used for ImGuiItemFlags_AllowOverlap and ImGuiItemFlags_HasSelectionUserData.
// Non-flags members are NOT cleared by ItemAdd() meaning they are still valid during NavProcessItem() // Non-flags members are NOT cleared by ItemAdd() meaning they are still valid during NavProcessItem()
ImGuiID FocusScopeId; // Set by SetNextItemSelectionUserData()
ImGuiSelectionUserData SelectionUserData; // Set by SetNextItemSelectionUserData() (note that NULL/0 is a valid value, we use -1 == ImGuiSelectionUserData_Invalid to mark invalid values) ImGuiSelectionUserData SelectionUserData; // Set by SetNextItemSelectionUserData() (note that NULL/0 is a valid value, we use -1 == ImGuiSelectionUserData_Invalid to mark invalid values)
float Width; // Set by SetNextItemWidth() float Width; // Set by SetNextItemWidth()
ImGuiKeyChord Shortcut; // Set by SetNextItemShortcut() ImGuiKeyChord Shortcut; // Set by SetNextItemShortcut()
@ -1704,6 +1707,33 @@ struct ImGuiOldColumns
ImGuiOldColumns() { memset(this, 0, sizeof(*this)); } ImGuiOldColumns() { memset(this, 0, sizeof(*this)); }
}; };
//-----------------------------------------------------------------------------
// [SECTION] Box-select support
//-----------------------------------------------------------------------------
struct ImGuiBoxSelectState
{
// Active box-selection data (persistent, 1 active at a time)
ImGuiID ID;
bool IsActive;
bool IsStarting;
bool IsStartedFromVoid; // Starting click was not from an item.
bool RequestClear;
ImGuiKeyChord KeyMods : 16; // Latched key-mods for box-select logic.
ImVec2 StartPosRel; // Start position in window-contents relative space (to support scrolling)
ImVec2 EndPosRel; // End position in window-contents relative space
ImVec2 ScrollAccum; // Scrolling accumulator (to behave at high-frame spaces)
ImGuiWindow* Window;
// Temporary/Transient data
bool UnclipMode; // (Temp/Transient, here in hot area). Set/cleared by the BeginMultiSelect()/EndMultiSelect() owning active box-select.
ImRect UnclipRect; // Rectangle where ItemAdd() clipping may be temporarily disabled. Need support by multi-select supporting widgets.
ImRect BoxSelectRectPrev; // Selection rectangle in absolute coordinates (derived every frame from BoxSelectStartPosRel and MousePos)
ImRect BoxSelectRectCurr;
ImGuiBoxSelectState() { memset(this, 0, sizeof(*this)); }
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Multi-select support // [SECTION] Multi-select support
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1711,9 +1741,45 @@ struct ImGuiOldColumns
// We always assume that -1 is an invalid value (which works for indices and pointers) // We always assume that -1 is an invalid value (which works for indices and pointers)
#define ImGuiSelectionUserData_Invalid ((ImGuiSelectionUserData)-1) #define ImGuiSelectionUserData_Invalid ((ImGuiSelectionUserData)-1)
#ifdef IMGUI_HAS_MULTI_SELECT // Temporary storage for multi-select
// <this is filled in 'range_select' branch> struct IMGUI_API ImGuiMultiSelectTempData
#endif // #ifdef IMGUI_HAS_MULTI_SELECT {
ImGuiMultiSelectIO IO; // MUST BE FIRST FIELD. Requests are set and returned by BeginMultiSelect()/EndMultiSelect() + written to by user during the loop.
ImGuiMultiSelectState* Storage;
ImGuiID FocusScopeId; // Copied from g.CurrentFocusScopeId (unless another selection scope was pushed manually)
ImGuiMultiSelectFlags Flags;
ImVec2 ScopeRectMin;
ImVec2 BackupCursorMaxPos;
ImGuiID BoxSelectId;
ImGuiKeyChord KeyMods;
ImS8 LoopRequestSetAll; // -1: no operation, 0: clear all, 1: select all.
bool IsEndIO; // Set when switching IO from BeginMultiSelect() to EndMultiSelect() state.
bool IsFocused; // Set if currently focusing the selection scope (any item of the selection). May be used if you have custom shortcut associated to selection.
bool IsKeyboardSetRange; // Set by BeginMultiSelect() when using Shift+Navigation. Because scrolling may be affected we can't afford a frame of lag with Shift+Navigation.
bool NavIdPassedBy;
bool RangeSrcPassedBy; // Set by the item that matches RangeSrcItem.
bool RangeDstPassedBy; // Set by the item that matches NavJustMovedToId when IsSetRange is set.
ImGuiSelectionUserData BoxSelectLastitem; // Copy of last submitted item data, used to merge output ranges.
ImGuiMultiSelectTempData() { Clear(); }
void Clear() { size_t io_sz = sizeof(IO); ClearIO(); memset((void*)(&IO + 1), 0, sizeof(*this) - io_sz); } // Zero-clear except IO as we preserve IO.Requests[] buffer allocation.
void ClearIO() { IO.Requests.resize(0); IO.RangeSrcItem = IO.NavIdItem = ImGuiSelectionUserData_Invalid; IO.NavIdSelected = IO.RangeSrcReset = false; }
};
// Persistent storage for multi-select (as long as selection is alive)
struct IMGUI_API ImGuiMultiSelectState
{
ImGuiWindow* Window;
ImGuiID ID;
int LastFrameActive; // Last used frame-count, for GC.
int LastSelectionSize; // Set by BeginMultiSelect() based on optional info provided by user. May be -1 if unknown.
ImS8 RangeSelected; // -1 (don't have) or true/false
ImS8 NavIdSelected; // -1 (don't have) or true/false
ImGuiSelectionUserData RangeSrcItem; //
ImGuiSelectionUserData NavIdItem; // SetNextItemSelectionUserData() value for NavId (if part of submitted items)
ImGuiMultiSelectState() { Window = NULL; ID = 0; LastFrameActive = LastSelectionSize = 0; RangeSelected = NavIdSelected = -1; RangeSrcItem = NavIdItem = ImGuiSelectionUserData_Invalid; }
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Docking support // [SECTION] Docking support
@ -2011,7 +2077,7 @@ struct ImGuiContext
ImGuiKeyOwnerData KeysOwnerData[ImGuiKey_NamedKey_COUNT]; ImGuiKeyOwnerData KeysOwnerData[ImGuiKey_NamedKey_COUNT];
ImGuiKeyRoutingTable KeysRoutingTable; ImGuiKeyRoutingTable KeysRoutingTable;
ImU32 ActiveIdUsingNavDirMask; // Active widget will want to read those nav move requests (e.g. can activate a button and move away from it) ImU32 ActiveIdUsingNavDirMask; // Active widget will want to read those nav move requests (e.g. can activate a button and move away from it)
bool ActiveIdUsingAllKeyboardKeys; // Active widget will want to read all keyboard keys inputs. (FIXME: This is a shortcut for not taking ownership of 100+ keys but perhaps best to not have the inconsistency) bool ActiveIdUsingAllKeyboardKeys; // Active widget will want to read all keyboard keys inputs. (this is a shortcut for not taking ownership of 100+ keys, frequently used by drag operations)
ImGuiKeyChord DebugBreakInShortcutRouting; // Set to break in SetShortcutRouting()/Shortcut() calls. ImGuiKeyChord DebugBreakInShortcutRouting; // Set to break in SetShortcutRouting()/Shortcut() calls.
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
ImU32 ActiveIdUsingNavInputMask; // If you used this. Since (IMGUI_VERSION_NUM >= 18804) : 'g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel);' becomes 'SetKeyOwner(ImGuiKey_Escape, g.ActiveId) and/or SetKeyOwner(ImGuiKey_NavGamepadCancel, g.ActiveId);' ImU32 ActiveIdUsingNavInputMask; // If you used this. Since (IMGUI_VERSION_NUM >= 18804) : 'g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel);' becomes 'SetKeyOwner(ImGuiKey_Escape, g.ActiveId) and/or SetKeyOwner(ImGuiKey_NavGamepadCancel, g.ActiveId);'
@ -2149,6 +2215,13 @@ struct ImGuiContext
ImVector<ImGuiPtrOrIndex> CurrentTabBarStack; ImVector<ImGuiPtrOrIndex> CurrentTabBarStack;
ImVector<ImGuiShrinkWidthItem> ShrinkWidthBuffer; ImVector<ImGuiShrinkWidthItem> ShrinkWidthBuffer;
// Multi-Select state
ImGuiBoxSelectState BoxSelectState;
ImGuiMultiSelectTempData* CurrentMultiSelect;
int MultiSelectTempDataStacked; // Temporary multi-select data size (because we leave previous instances undestructed, we generally don't use MultiSelectTempData.Size)
ImVector<ImGuiMultiSelectTempData> MultiSelectTempData;
ImPool<ImGuiMultiSelectState> MultiSelectStorage;
// Hover Delay system // Hover Delay system
ImGuiID HoverItemDelayId; ImGuiID HoverItemDelayId;
ImGuiID HoverItemDelayIdPreviousFrame; ImGuiID HoverItemDelayIdPreviousFrame;
@ -2389,6 +2462,8 @@ struct ImGuiContext
CurrentTable = NULL; CurrentTable = NULL;
TablesTempDataStacked = 0; TablesTempDataStacked = 0;
CurrentTabBar = NULL; CurrentTabBar = NULL;
CurrentMultiSelect = NULL;
MultiSelectTempDataStacked = 0;
HoverItemDelayId = HoverItemDelayIdPreviousFrame = HoverItemUnlockedStationaryId = HoverWindowUnlockedStationaryId = 0; HoverItemDelayId = HoverItemDelayIdPreviousFrame = HoverItemUnlockedStationaryId = HoverWindowUnlockedStationaryId = 0;
HoverItemDelayTimer = HoverItemDelayClearTimer = 0.0f; HoverItemDelayTimer = HoverItemDelayClearTimer = 0.0f;
@ -3043,6 +3118,7 @@ namespace ImGui
inline ImRect WindowRectAbsToRel(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x - off.x, r.Min.y - off.y, r.Max.x - off.x, r.Max.y - off.y); } inline ImRect WindowRectAbsToRel(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x - off.x, r.Min.y - off.y, r.Max.x - off.x, r.Max.y - off.y); }
inline ImRect WindowRectRelToAbs(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x + off.x, r.Min.y + off.y, r.Max.x + off.x, r.Max.y + off.y); } inline ImRect WindowRectRelToAbs(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x + off.x, r.Min.y + off.y, r.Max.x + off.x, r.Max.y + off.y); }
inline ImVec2 WindowPosRelToAbs(ImGuiWindow* window, const ImVec2& p) { ImVec2 off = window->DC.CursorStartPos; return ImVec2(p.x + off.x, p.y + off.y); } inline ImVec2 WindowPosRelToAbs(ImGuiWindow* window, const ImVec2& p) { ImVec2 off = window->DC.CursorStartPos; return ImVec2(p.x + off.x, p.y + off.y); }
inline ImVec2 WindowPosAbsToRel(ImGuiWindow* window, const ImVec2& p) { ImVec2 off = window->DC.CursorStartPos; return ImVec2(p.x - off.x, p.y - off.y); }
// Windows: Display Order and Focus Order // Windows: Display Order and Focus Order
IMGUI_API void FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags = 0); IMGUI_API void FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags = 0);
@ -3144,7 +3220,6 @@ namespace ImGui
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h); IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h);
IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
IMGUI_API void PushMultiItemsWidths(int components, float width_full); IMGUI_API void PushMultiItemsWidths(int components, float width_full);
IMGUI_API bool IsItemToggledSelection(); // Was the last item selection toggled? (after Selectable(), TreeNode() etc. We only returns toggle _event_ in order to handle clipping correctly)
IMGUI_API ImVec2 GetContentRegionMaxAbs(); IMGUI_API ImVec2 GetContentRegionMaxAbs();
IMGUI_API void ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess); IMGUI_API void ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess);
@ -3325,6 +3400,16 @@ namespace ImGui
IMGUI_API int TypingSelectFindNextSingleCharMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx); IMGUI_API int TypingSelectFindNextSingleCharMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx);
IMGUI_API int TypingSelectFindBestLeadingMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data); IMGUI_API int TypingSelectFindBestLeadingMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data);
// Box-Select API
IMGUI_API bool BeginBoxSelect(ImGuiWindow* window, ImGuiID box_select_id, ImGuiMultiSelectFlags ms_flags);
IMGUI_API void EndBoxSelect(const ImRect& scope_rect, ImGuiMultiSelectFlags ms_flags);
// Multi-Select API
IMGUI_API void MultiSelectItemHeader(ImGuiID id, bool* p_selected, ImGuiButtonFlags* p_button_flags);
IMGUI_API void MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed);
inline ImGuiBoxSelectState* GetBoxSelectState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.BoxSelectState.ID == id && g.BoxSelectState.IsActive) ? &g.BoxSelectState : NULL; }
inline ImGuiMultiSelectState* GetMultiSelectState(ImGuiID id) { ImGuiContext& g = *GImGui; return g.MultiSelectStorage.GetByKey(id); }
// Internal Columns API (this is not exposed because we will encourage transitioning to the Tables API) // Internal Columns API (this is not exposed because we will encourage transitioning to the Tables API)
IMGUI_API void SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect); IMGUI_API void SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect);
IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiOldColumnFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns(). IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiOldColumnFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns().
@ -3461,7 +3546,6 @@ namespace ImGui
IMGUI_API bool DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags); IMGUI_API bool DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags);
IMGUI_API bool SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* p_v, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb); IMGUI_API bool SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* p_v, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb);
IMGUI_API bool SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f, float hover_visibility_delay = 0.0f, ImU32 bg_col = 0); IMGUI_API bool SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f, float hover_visibility_delay = 0.0f, ImU32 bg_col = 0);
IMGUI_API void SetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_data);
// Widgets: Tree Nodes // Widgets: Tree Nodes
IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiID storage_id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL); IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiID storage_id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL);
@ -3543,6 +3627,7 @@ namespace ImGui
IMGUI_API void DebugNodeTableSettings(ImGuiTableSettings* settings); IMGUI_API void DebugNodeTableSettings(ImGuiTableSettings* settings);
IMGUI_API void DebugNodeInputTextState(ImGuiInputTextState* state); IMGUI_API void DebugNodeInputTextState(ImGuiInputTextState* state);
IMGUI_API void DebugNodeTypingSelectState(ImGuiTypingSelectState* state); IMGUI_API void DebugNodeTypingSelectState(ImGuiTypingSelectState* state);
IMGUI_API void DebugNodeMultiSelectState(ImGuiMultiSelectState* state);
IMGUI_API void DebugNodeWindow(ImGuiWindow* window, const char* label); IMGUI_API void DebugNodeWindow(ImGuiWindow* window, const char* label);
IMGUI_API void DebugNodeWindowSettings(ImGuiWindowSettings* settings); IMGUI_API void DebugNodeWindowSettings(ImGuiWindowSettings* settings);
IMGUI_API void DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows, const char* label); IMGUI_API void DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows, const char* label);

File diff suppressed because it is too large Load Diff