Merge branch 'features/range_select'
This commit is contained in:
commit
d7e605d430
@ -77,6 +77,57 @@ Other changes:
|
||||
Disabling this was previously possible for Selectable() via a direct flag but not for MenuItem().
|
||||
(#1379, #1468, #2200, #4936, #5216, #7302, #7573)
|
||||
- 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
|
||||
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
|
||||
|
61
imgui.cpp
61
imgui.cpp
@ -2558,6 +2558,7 @@ ImGuiStoragePair* ImLowerBound(ImGuiStoragePair* in_begin, ImGuiStoragePair* in_
|
||||
return in_p;
|
||||
}
|
||||
|
||||
IM_MSVC_RUNTIME_CHECKS_OFF
|
||||
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.
|
||||
@ -2571,6 +2572,7 @@ void ImGuiStorage::BuildSortByKey()
|
||||
{
|
||||
ImQsort(Data.Data, (size_t)Data.Size, sizeof(ImGuiStoragePair), PairComparerByID);
|
||||
}
|
||||
IM_MSVC_RUNTIME_CHECKS_RESTORE
|
||||
|
||||
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));
|
||||
|
||||
// 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_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
|
||||
@ -3818,6 +3838,9 @@ void ImGui::Shutdown()
|
||||
g.TablesTempData.clear_destruct();
|
||||
g.DrawChannelsTempMergeBuffer.clear();
|
||||
|
||||
g.MultiSelectStorage.Clear();
|
||||
g.MultiSelectTempData.clear_destruct();
|
||||
|
||||
g.ClipboardHandlerData.clear();
|
||||
g.MenusIdSubmittedThisFrame.clear();
|
||||
g.InputTextState.ClearFreeMemory();
|
||||
@ -3928,6 +3951,8 @@ void ImGui::GcCompactTransientMiscBuffers()
|
||||
ImGuiContext& g = *GImGui;
|
||||
g.ItemFlagsStack.clear();
|
||||
g.GroupStack.clear();
|
||||
g.MultiSelectTempDataStacked = 0;
|
||||
g.MultiSelectTempData.clear_destruct();
|
||||
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 '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);
|
||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
|
||||
@ -5446,9 +5471,15 @@ bool ImGui::IsItemToggledOpen()
|
||||
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()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(g.CurrentMultiSelect != NULL); // Can only be used inside a BeginMultiSelect()/EndMultiSelect()
|
||||
return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledSelection) ? true : false;
|
||||
}
|
||||
|
||||
@ -5508,7 +5539,8 @@ void ImGui::SetItemAllowOverlap()
|
||||
}
|
||||
#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()
|
||||
{
|
||||
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);
|
||||
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)
|
||||
{
|
||||
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)
|
||||
g.NavJustMovedToId = 0;
|
||||
g.NavJustMovedToFocusScopeId = g.NavJustMovedFromFocusScopeId = 0;
|
||||
if (g.NavInitResult.ID != 0)
|
||||
NavInitRequestApplyResult();
|
||||
g.NavInitRequest = false;
|
||||
@ -12403,6 +12441,7 @@ void ImGui::NavInitRequestApplyResult()
|
||||
ImGuiNavItemData* result = &g.NavInitResult;
|
||||
if (g.NavId != result->ID)
|
||||
{
|
||||
g.NavJustMovedFromFocusScopeId = g.NavFocusScopeId;
|
||||
g.NavJustMovedToId = result->ID;
|
||||
g.NavJustMovedToFocusScopeId = result->FocusScopeId;
|
||||
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.
|
||||
if ((g.NavId != result->ID || (g.NavMoveFlags & ImGuiNavMoveFlags_IsPageMove)) && (g.NavMoveFlags & ImGuiNavMoveFlags_NoSelect) == 0)
|
||||
{
|
||||
g.NavJustMovedFromFocusScopeId = g.NavFocusScopeId;
|
||||
g.NavJustMovedToId = result->ID;
|
||||
g.NavJustMovedToFocusScopeId = result->FocusScopeId;
|
||||
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()
|
||||
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.DragDropWithinTarget = true;
|
||||
return true;
|
||||
@ -14957,6 +14997,17 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
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
|
||||
#ifdef IMGUI_HAS_DOCK
|
||||
if (TreeNode("Docking"))
|
||||
@ -15799,7 +15850,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open)
|
||||
ShowDebugLogFlag("IO", ImGuiDebugLogFlags_EventIO);
|
||||
ShowDebugLogFlag("Nav", ImGuiDebugLogFlags_EventNav);
|
||||
ShowDebugLogFlag("Popup", ImGuiDebugLogFlags_EventPopup);
|
||||
//ShowDebugLogFlag("Selection", ImGuiDebugLogFlags_EventSelection);
|
||||
ShowDebugLogFlag("Selection", ImGuiDebugLogFlags_EventSelection);
|
||||
ShowDebugLogFlag("InputRouting", ImGuiDebugLogFlags_EventInputRouting);
|
||||
|
||||
if (SmallButton("Clear"))
|
||||
|
171
imgui.h
171
imgui.h
@ -28,7 +28,7 @@
|
||||
// Library Version
|
||||
// (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_NUM 19095
|
||||
#define IMGUI_VERSION_NUM 19096
|
||||
#define IMGUI_HAS_TABLE
|
||||
|
||||
/*
|
||||
@ -44,6 +44,7 @@ Index of this file:
|
||||
// [SECTION] ImGuiIO
|
||||
// [SECTION] Misc data structures (ImGuiInputTextCallbackData, ImGuiSizeCallbackData, ImGuiPayload)
|
||||
// [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] Font API (ImFontConfig, ImFontGlyph, ImFontGlyphRangesBuilder, ImFontAtlasFlags, ImFontAtlas, ImFont)
|
||||
// [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 ImGuiKeyData; // Storage for ImGuiIO and IsKeyDown(), IsKeyPressed() etc functions.
|
||||
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 ImGuiPayload; // User data payload for drag and drop operations
|
||||
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 ImGuiStorage; // Helper for key->value storage (container sorted by key)
|
||||
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 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 ImGuiMultiSelectFlags; // -> enum ImGuiMultiSelectFlags_// Flags: for BeginMultiSelect()
|
||||
typedef int ImGuiSelectableFlags; // -> enum ImGuiSelectableFlags_ // Flags: for Selectable()
|
||||
typedef int ImGuiSliderFlags; // -> enum ImGuiSliderFlags_ // Flags: for DragFloat(), DragInt(), SliderFloat(), SliderInt() etc.
|
||||
typedef int ImGuiTabBarFlags; // -> enum ImGuiTabBarFlags_ // Flags: for BeginTabBar()
|
||||
@ -262,6 +268,11 @@ typedef ImWchar32 ImWchar;
|
||||
typedef ImWchar16 ImWchar;
|
||||
#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
|
||||
typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data); // Callback function for ImGui::InputText()
|
||||
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* 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
|
||||
// - 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.
|
||||
@ -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); }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [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)
|
||||
// Hold a series of drawing commands. The user provides a renderer for ImDrawData which essentially contains an array of ImDrawList.
|
||||
|
1200
imgui_demo.cpp
1200
imgui_demo.cpp
File diff suppressed because it is too large
Load Diff
107
imgui_internal.h
107
imgui_internal.h
@ -22,6 +22,7 @@ Index of this file:
|
||||
// [SECTION] Navigation support
|
||||
// [SECTION] Typing-select support
|
||||
// [SECTION] Columns support
|
||||
// [SECTION] Box-select support
|
||||
// [SECTION] Multi-select support
|
||||
// [SECTION] Docking support
|
||||
// [SECTION] Viewport support
|
||||
@ -123,6 +124,7 @@ struct ImBitVector; // Store 1-bit per value
|
||||
struct ImRect; // An axis-aligned rectangle (2 points)
|
||||
struct ImDrawDataBuilder; // Helper to build a ImDrawData instance
|
||||
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 ImGuiContext; // Main Dear ImGui context
|
||||
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 ImGuiLocEntry; // A localization entry.
|
||||
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 ImGuiMetricsConfig; // Storage for ShowMetricsWindow() and DebugNodeXXX() 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 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 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 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; }
|
||||
@ -854,6 +859,7 @@ enum ImGuiItemFlagsPrivate_
|
||||
// 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_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.
|
||||
|
||||
@ -1201,10 +1207,6 @@ struct ImGuiNextWindowData
|
||||
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_
|
||||
{
|
||||
ImGuiNextItemDataFlags_None = 0,
|
||||
@ -1217,8 +1219,9 @@ enum ImGuiNextItemDataFlags_
|
||||
struct ImGuiNextItemData
|
||||
{
|
||||
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()
|
||||
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)
|
||||
float Width; // Set by SetNextItemWidth()
|
||||
ImGuiKeyChord Shortcut; // Set by SetNextItemShortcut()
|
||||
@ -1704,6 +1707,33 @@ struct ImGuiOldColumns
|
||||
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
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1711,9 +1741,45 @@ struct ImGuiOldColumns
|
||||
// We always assume that -1 is an invalid value (which works for indices and pointers)
|
||||
#define ImGuiSelectionUserData_Invalid ((ImGuiSelectionUserData)-1)
|
||||
|
||||
#ifdef IMGUI_HAS_MULTI_SELECT
|
||||
// <this is filled in 'range_select' branch>
|
||||
#endif // #ifdef IMGUI_HAS_MULTI_SELECT
|
||||
// Temporary storage for multi-select
|
||||
struct IMGUI_API ImGuiMultiSelectTempData
|
||||
{
|
||||
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
|
||||
@ -2011,7 +2077,7 @@ struct ImGuiContext
|
||||
ImGuiKeyOwnerData KeysOwnerData[ImGuiKey_NamedKey_COUNT];
|
||||
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)
|
||||
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.
|
||||
#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);'
|
||||
@ -2149,6 +2215,13 @@ struct ImGuiContext
|
||||
ImVector<ImGuiPtrOrIndex> CurrentTabBarStack;
|
||||
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
|
||||
ImGuiID HoverItemDelayId;
|
||||
ImGuiID HoverItemDelayIdPreviousFrame;
|
||||
@ -2389,6 +2462,8 @@ struct ImGuiContext
|
||||
CurrentTable = NULL;
|
||||
TablesTempDataStacked = 0;
|
||||
CurrentTabBar = NULL;
|
||||
CurrentMultiSelect = NULL;
|
||||
MultiSelectTempDataStacked = 0;
|
||||
|
||||
HoverItemDelayId = HoverItemDelayIdPreviousFrame = HoverItemUnlockedStationaryId = HoverWindowUnlockedStationaryId = 0;
|
||||
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 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 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
|
||||
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 float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
|
||||
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 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 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)
|
||||
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().
|
||||
@ -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 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 void SetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_data);
|
||||
|
||||
// Widgets: Tree Nodes
|
||||
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 DebugNodeInputTextState(ImGuiInputTextState* 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 DebugNodeWindowSettings(ImGuiWindowSettings* settings);
|
||||
IMGUI_API void DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows, const char* label);
|
||||
|
1026
imgui_widgets.cpp
1026
imgui_widgets.cpp
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user