Internals: Rename ImGuiSelectableFlags_PressedOnXXX to ImGuiSelectableFlags_SelectOnXXX, ImGuiButtonFlags_NoHoveredOnNav to ImGuiButtonFlags_NoHoveredOnFocus.
Rebased 2023/05/20 (reworked demo locations), 2023/05/23 (rename some local to reduce noise in future commits)
Major rebase 2023/09/12 since master added ImGuiSelectionUserData + SetNextItemSelectionUserData() + add ImGuiItemFlags_IsMultiSelect.
TableAngledHeadersTextAlign=ImVec2(0.5f,0.0f);// Alignment of angled headers within the cell
TableAngledHeadersTextAlign=ImVec2(0.5f,0.0f);// Alignment of angled headers within the cell
ColorButtonPosition=ImGuiDir_Right;// Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
ColorButtonPosition=ImGuiDir_Right;// Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
ButtonTextAlign=ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text.
ButtonTextAlign=ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text.
SelectableSpacing=ImVec2(0.0f,0.0f);// Horizontal and vertical spacing between selectables (by default they are canceling out the effect of ItemSpacing).
SelectableTextAlign=ImVec2(0.0f,0.0f);// Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
SelectableTextAlign=ImVec2(0.0f,0.0f);// Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
SeparatorTextBorderSize=3.0f;// Thickkness of border in SeparatorText()
SeparatorTextBorderSize=3.0f;// Thickkness of border in SeparatorText()
SeparatorTextAlign=ImVec2(0.0f,0.5f);// Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center).
SeparatorTextAlign=ImVec2(0.0f,0.5f);// Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center).
@ -174,6 +175,7 @@ struct ImGuiIO; // Main configuration and I/O between your a
structImGuiInputTextCallbackData;// Shared state of InputText() when using custom ImGuiInputTextCallback (rare/advanced use)
structImGuiInputTextCallbackData;// Shared state of InputText() when using custom ImGuiInputTextCallback (rare/advanced use)
structImGuiKeyData;// Storage for ImGuiIO and IsKeyDown(), IsKeyPressed() etc functions.
structImGuiKeyData;// Storage for ImGuiIO and IsKeyDown(), IsKeyPressed() etc functions.
structImGuiListClipper;// Helper to manually clip large list of items
structImGuiListClipper;// Helper to manually clip large list of items
structImGuiMultiSelectData;// State for a BeginMultiSelect() block
structImGuiOnceUponAFrame;// Helper for running a block of code not more than once a frame
structImGuiOnceUponAFrame;// Helper for running a block of code not more than once a frame
structImGuiPayload;// User data payload for drag and drop operations
structImGuiPayload;// User data payload for drag and drop operations
structImGuiPlatformImeData;// Platform IME data for io.SetPlatformImeDataFn() function.
structImGuiPlatformImeData;// Platform IME data for io.SetPlatformImeDataFn() function.
@ -226,6 +228,7 @@ typedef int ImGuiInputFlags; // -> enum ImGuiInputFlags_ // Flags: f
typedefintImGuiInputTextFlags;// -> enum ImGuiInputTextFlags_ // Flags: for InputText(), InputTextMultiline()
typedefintImGuiInputTextFlags;// -> enum ImGuiInputTextFlags_ // Flags: for InputText(), InputTextMultiline()
typedefintImGuiKeyChord;// -> ImGuiKey | ImGuiMod_XXX // Flags: for IsKeyChordPressed(), Shortcut() etc. an ImGuiKey optionally OR-ed with one or more ImGuiMod_XXX values.
typedefintImGuiKeyChord;// -> ImGuiKey | ImGuiMod_XXX // Flags: for IsKeyChordPressed(), Shortcut() etc. an ImGuiKey optionally OR-ed with one or more ImGuiMod_XXX values.
typedefintImGuiPopupFlags;// -> enum ImGuiPopupFlags_ // Flags: for OpenPopup*(), BeginPopupContext*(), IsPopupOpen()
typedefintImGuiPopupFlags;// -> enum ImGuiPopupFlags_ // Flags: for OpenPopup*(), BeginPopupContext*(), IsPopupOpen()
typedefintImGuiMultiSelectFlags;// -> enum ImGuiMultiSelectFlags_// Flags: for BeginMultiSelect()
typedefintImGuiSelectableFlags;// -> enum ImGuiSelectableFlags_ // Flags: for Selectable()
typedefintImGuiSelectableFlags;// -> enum ImGuiSelectableFlags_ // Flags: for Selectable()
typedefintImGuiSliderFlags;// -> enum ImGuiSliderFlags_ // Flags: for DragFloat(), DragInt(), SliderFloat(), SliderInt() etc.
typedefintImGuiSliderFlags;// -> enum ImGuiSliderFlags_ // Flags: for DragFloat(), DragInt(), SliderFloat(), SliderInt() etc.
typedefintImGuiTabBarFlags;// -> enum ImGuiTabBarFlags_ // Flags: for BeginTabBar()
typedefintImGuiTabBarFlags;// -> enum ImGuiTabBarFlags_ // Flags: for BeginTabBar()
@ -261,6 +264,10 @@ typedef ImWchar32 ImWchar;
typedefImWchar16ImWchar;
typedefImWchar16ImWchar;
#endif
#endif
// 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.)
typedefImS64ImGuiSelectionUserData;
// Callback and functions types
// Callback and functions types
typedefint(*ImGuiInputTextCallback)(ImGuiInputTextCallbackData*data);// Callback function for ImGui::InputText()
typedefint(*ImGuiInputTextCallback)(ImGuiInputTextCallbackData*data);// Callback function for ImGui::InputText()
typedefvoid(*ImGuiSizeCallback)(ImGuiSizeCallbackData*data);// Callback function for ImGui::SetNextWindowSizeConstraints()
typedefvoid(*ImGuiSizeCallback)(ImGuiSizeCallbackData*data);// Callback function for ImGui::SetNextWindowSizeConstraints()
@ -660,6 +667,14 @@ namespace ImGui
IMGUI_APIboolSelectable(constchar*label,boolselected=false,ImGuiSelectableFlagsflags=0,constImVec2&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_APIboolSelectable(constchar*label,boolselected=false,ImGuiSelectableFlagsflags=0,constImVec2&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_APIboolSelectable(constchar*label,bool*p_selected,ImGuiSelectableFlagsflags=0,constImVec2&size=ImVec2(0,0));// "bool* p_selected" point to the selection state (read-write), as a convenient helper.
IMGUI_APIboolSelectable(constchar*label,bool*p_selected,ImGuiSelectableFlagsflags=0,constImVec2&size=ImVec2(0,0));// "bool* p_selected" point to the selection state (read-write), as a convenient helper.
// Multi-selection system for Selectable() and TreeNode() functions.
// This enables standard multi-selection/range-selection idioms (CTRL+Click/Arrow, SHIFT+Click/Arrow, etc) in a way that allow items to be fully clipped (= not submitted at all) when not visible.
// Read comments near ImGuiMultiSelectData for details.
// When enabled, Selectable() and TreeNode() functions will return true when selection needs toggling.
// - 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.
@ -890,6 +905,7 @@ namespace ImGui
IMGUI_APIboolIsItemDeactivated();// was the last item just made inactive (item was previously active). Useful for Undo/Redo patterns with widgets that require continuous editing.
IMGUI_APIboolIsItemDeactivated();// was the last item just made inactive (item was previously active). Useful for Undo/Redo patterns with widgets that require continuous editing.
IMGUI_APIboolIsItemDeactivatedAfterEdit();// was the last item just made inactive and made a value change when it was active? (e.g. Slider/Drag moved). Useful for Undo/Redo patterns with widgets that require continuous editing. Note that you may get false positives (some widgets such as Combo()/ListBox()/Selectable() will return true even when clicking an already selected item).
IMGUI_APIboolIsItemDeactivatedAfterEdit();// was the last item just made inactive and made a value change when it was active? (e.g. Slider/Drag moved). Useful for Undo/Redo patterns with widgets that require continuous editing. Note that you may get false positives (some widgets such as Combo()/ListBox()/Selectable() will return true even when clicking an already selected item).
IMGUI_APIboolIsItemToggledOpen();// was the last item open state toggled? set by TreeNode().
IMGUI_APIboolIsItemToggledOpen();// was the last item open state toggled? set by TreeNode().
IMGUI_APIboolIsItemToggledSelection();// was the last item selection state toggled? (after Selectable(), TreeNode() etc. We only returns toggle _event_ in order to handle clipping correctly)
IMGUI_APIboolIsAnyItemHovered();// is any item hovered?
IMGUI_APIboolIsAnyItemHovered();// is any item hovered?
IMGUI_APIboolIsAnyItemActive();// is any item active?
IMGUI_APIboolIsAnyItemActive();// is any item active?
IMGUI_APIboolIsAnyItemFocused();// is any item focused?
IMGUI_APIboolIsAnyItemFocused();// is any item focused?
ImVec2TableAngledHeadersTextAlign;// Alignment of angled headers within the cell
ImVec2TableAngledHeadersTextAlign;// Alignment of angled headers within the cell
ImGuiDirColorButtonPosition;// Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
ImGuiDirColorButtonPosition;// Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
ImVec2ButtonTextAlign;// Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered).
ImVec2ButtonTextAlign;// Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered).
ImVec2SelectableSpacing;// Horizontal and vertical spacing between selectables (by default they are canceling out the effect of ItemSpacing).
ImVec2SelectableTextAlign;// Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
ImVec2SelectableTextAlign;// Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
floatSeparatorTextBorderSize;// Thickkness of border in SeparatorText()
floatSeparatorTextBorderSize;// Thickkness of border in SeparatorText()
ImVec2SeparatorTextAlign;// Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center).
ImVec2SeparatorTextAlign;// Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center).
// This system is designed to allow mouse/keyboard multi-selection, including support for range-selection (SHIFT + click) which is difficult to re-implement manually.
// If you disable multi-selection with ImGuiMultiSelectFlags_NoMultiSelect (which is provided for consistency and flexibility), the whole BeginMultiSelect() system
// becomes largely overkill as you can handle single-selection in a simpler manner by just calling Selectable() and reacting on clicks yourself.
enumImGuiMultiSelectFlags_
{
ImGuiMultiSelectFlags_NoMultiSelect=1<<0,
ImGuiMultiSelectFlags_NoUnselect=1<<1,// Disable unselecting items with CTRL+Click, CTRL+Space etc.
ImGuiMultiSelectFlags_NoSelectAll=1<<2,// Disable CTRL+A shortcut to set RequestSelectAll
};
// Abstract:
// - This system implements standard multi-selection idioms (CTRL+Click/Arrow, SHIFT+Click/Arrow, etc) in a way that allow items to be
// fully clipped (= not submitted at all) when not visible. Clipping is typically provided by ImGuiListClipper.
// Handling all of this in a single pass imgui is a little tricky, and this is why we provide those functionalities.
// Note however that if you don't need SHIFT+Click/Arrow range-select, you can handle a simpler form of multi-selection yourself,
// by reacting to click/presses on Selectable() items and checking keyboard modifiers.
// The complexity of this system here is mostly caused by the handling of range-select while optionally allowing to clip elements.
// - The work involved to deal with multi-selection differs whether you want to only submit visible items (and clip others) or submit all items
// regardless of their visibility. Clipping items is more efficient and will allow you to deal with large lists (1k~100k items) with near zero
// performance penalty, but requires a little more work on the code. If you only have a few hundreds elements in your possible selection set,
// you may as well not bother with clipping, as the cost should be negligible (as least on imgui side).
// If you are not sure, always start without clipping and you can work your way to the more optimized version afterwards.
// - The void* Src/Dst value represent a selectable object. They are the values you pass to SetNextItemMultiSelectData().
// Storing an integer index is the easiest thing to do, as SetRange requests will give you two end points. But the code never assume that sortable integers are used.
// - In the spirit of imgui design, your code own the selection data. So this is designed to handle all kind of selection data: instructive (store a bool inside each object),
// external array (store an array aside from your objects), set (store only selected items in a hash/map/set), using intervals (store indices in an interval tree), etc.
// Usage flow:
// 1) Call BeginMultiSelect() with the last saved value of ->RangeSrc and its selection status. As a default value for the initial frame or when,
// resetting your selection state: you may use the value for your first item or a "null" value that matches the type stored in your void*.
// 2) Honor Clear/SelectAll requests by updating your selection data. [Only required if you are using a clipper in step 4]
// 3) Set RangeSrcPassedBy=true if the RangeSrc item is part of the items clipped before the first submitted/visible item. [Only required if you are using a clipper in step 4]
// This is because for range-selection we need to know if we are currently "inside" or "outside" the range.
// If you are using integer indices everywhere, this is easy to compute: if (clipper.DisplayStart > (int)data->RangeSrc) { data->RangeSrcPassedBy = true; }
// 4) Submit your items with SetNextItemMultiSelectData() + Selectable()/TreeNode() calls.
// Call IsItemSelectionToggled() to query with the selection state has been toggled, in which you need the info immediately (before EndMultiSelect()) for your display.
// When cannot reliably return a "IsItemSelected()" value because we need to consider clipped (unprocessed) item, this is why we return a toggle event instead.
// 5) Call EndMultiSelect(). Save the value of ->RangeSrc for the next frame (you may convert the value in a format that is safe for persistance)
// 6) Honor Clear/SelectAll/SetRange requests by updating your selection data. Always process them in this order (as you will receive Clear+SetRange request simultaneously)
// If you submit all items (no clipper), Step 2 and 3 and will be handled by Selectable() on a per-item basis.
structImGuiMultiSelectData
{
boolRequestClear;// Begin, End // Request user to clear selection
boolRequestSelectAll;// Begin, End // Request user to select all
boolRequestSetRange;// End // Request user to set or clear selection in the [RangeSrc..RangeDst] range
boolRangeSrcPassedBy;// After Begin // Need to be set by user is RangeSrc was part of the clipped set before submitting the visible items. Ignore if not clipping.
boolRangeValue;// End // End: parameter from RequestSetRange request. True = Select Range, False = Unselect range.
void*RangeSrc;// Begin, End // End: parameter from RequestSetRange request + you need to save this value so you can pass it again next frame. / Begin: this is the value you passed to BeginMultiSelect()
void*RangeDst;// End // End: parameter from RequestSetRange request.
intRangeDirection;// End // End: parameter from RequestSetRange request. +1 if RangeSrc came before RangeDst, -1 otherwise. Available as an indicator in case you cannot infer order from the void* values.
ImGui::SameLine();HelpMarker("Selectable cancel out the regular spacing between items by extending itself by ItemSpacing/2 in each direction.\nThis has two purposes:\n- Avoid the gap between items so the mouse is always hitting something.\n- Avoid the gap between items so range-selected item looks connected.\nBy changing SelectableSpacing we can enforce spacing between selectables.");
// Demonstrate holding/updating multi-selection data and using the BeginMultiSelect/EndMultiSelect API to support range-selection and clipping.
// In this demo we use ImGuiStorage (simple key->value storage) to avoid external dependencies but it's probably not optimal.
// In your real code you could use e.g std::unordered_set<> or your own data structure for storing selection.
// If you don't mind being limited to one view over your objects, the simplest way is to use an intrusive selection (e.g. store bool inside object, as used in examples above).
// Otherwise external set/hash/map/interval trees (storing indices, etc.) may be appropriate.
ImGui::SliderFloat2("SelectableSpacing",(float*)&style.SelectableSpacing,0.0f,20.0f,"%.0f");ImGui::SameLine();HelpMarker("SelectableSpacing must be < ItemSpacing.\nSelectables display their highlight after canceling out the effect of ItemSpacing, so they can be look tightly packed. This setting allows to enforce spacing between them.");
@ -134,6 +134,7 @@ struct ImGuiInputTextDeactivateData;// Short term storage to backup text of a de
structImGuiLastItemData;// Status storage for last submitted items
structImGuiLastItemData;// Status storage for last submitted items
structImGuiLocEntry;// A localization entry.
structImGuiLocEntry;// A localization entry.
structImGuiMenuColumns;// Simple column measurement, currently used for MenuItem() only
structImGuiMenuColumns;// Simple column measurement, currently used for MenuItem() only
structImGuiMultiSelectState;// Multi-selection state
structImGuiNavItemData;// Result of a gamepad/keyboard directional navigation move query result
structImGuiNavItemData;// Result of a gamepad/keyboard directional navigation move query result
structImGuiNavTreeNodeData;// Temporary storage for last TreeNode() being a Left arrow landing candidate.
structImGuiNavTreeNodeData;// Temporary storage for last TreeNode() being a Left arrow landing candidate.
structImGuiMetricsConfig;// Storage for ShowMetricsWindow() and DebugNodeXXX() functions
structImGuiMetricsConfig;// Storage for ShowMetricsWindow() and DebugNodeXXX() functions
@ -862,6 +863,7 @@ enum ImGuiItemFlags_
// Controlled by widget code
// Controlled by widget code
ImGuiItemFlags_Inputable=1<<10,// 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<<10,// 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<<11,// false // Set by SetNextItemSelectionUserData()
ImGuiItemFlags_HasSelectionUserData=1<<11,// false // Set by SetNextItemSelectionUserData()
ImGuiItemFlags_IsMultiSelect=1<<12,// false // Set by SetNextItemSelectionUserData()
ImGuiMultiSelectDataIn;// The In requests are set and returned by BeginMultiSelect()
ImGuiMultiSelectDataOut;// The Out requests are finalized and returned by EndMultiSelect()
boolInRangeDstPassedBy;// (Internal) set by the the item that match NavJustMovedToId when InRequestRangeSetNav is set.
boolInRequestSetRangeNav;// (Internal) set by BeginMultiSelect() when using Shift+Navigation. Because scrolling may be affected we can't afford a frame of lag with Shift+Navigation.
IMGUI_APIboolIsItemToggledSelection();// Was the last item selection toggled? (after Selectable(), TreeNode() etc. We only returns toggle _event_ in order to handle clipping correctly)
IMGUI_APIvoidBeginColumns(constchar*str_id,intcount,ImGuiOldColumnFlagsflags=0);// setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns().
IMGUI_APIvoidBeginColumns(constchar*str_id,intcount,ImGuiOldColumnFlagsflags=0);// setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns().
@ -3453,7 +3476,6 @@ namespace ImGui
IMGUI_APIvoidTreePushOverrideID(ImGuiIDid);
IMGUI_APIvoidTreePushOverrideID(ImGuiIDid);
IMGUI_APIvoidTreeNodeSetOpen(ImGuiIDid,boolopen);
IMGUI_APIvoidTreeNodeSetOpen(ImGuiIDid,boolopen);
IMGUI_APIboolTreeNodeUpdateNextOpen(ImGuiIDid,ImGuiTreeNodeFlagsflags);// Return open state. Consume previous SetNextItemOpen() data, if any. May return true when logging.
IMGUI_APIboolTreeNodeUpdateNextOpen(ImGuiIDid,ImGuiTreeNodeFlagsflags);// Return open state. Consume previous SetNextItemOpen() data, if any. May return true when logging.
// Template functions are instantiated in imgui_widgets.cpp for a finite number of types.
// Template functions are instantiated in imgui_widgets.cpp for a finite number of types.
// To use them externally (for custom widget) you may need an "extern template" statement in your code in order to link to existing instances and silence Clang warnings (see #2036).
// To use them externally (for custom widget) you may need an "extern template" statement in your code in order to link to existing instances and silence Clang warnings (see #2036).
// To handle drag and drop of multiple items we need to avoid clearing selection on click.
// Enabling this test makes actions using CTRL+SHIFT delay their effect on the mouse release which is annoying, but it allows drag and drop of multiple items.
// To handle drag and drop of multiple items we need to avoid clearing selection on click.
// Enabling this test makes actions using CTRL+SHIFT delay their effect on the mouse release which is annoying, but it allows drag and drop of multiple items.
IM_ASSERT((g.NextItemData.SelectionUserData!=ImGuiSelectionUserData_Invalid)&&"Forgot to call SetNextItemMultiSelectData() prior to item, required in BeginMultiSelect()/EndMultiSelect() scope");
// Apply Clear/SelectAll requests requested by BeginMultiSelect().
// This is only useful if the user hasn't processed them already, and this only works if the user isn't using the clipper.
// If you are using a clipper (aka not submitting every element of the list) you need to process the Clear/SelectAll request after calling BeginMultiSelect()
// When using SHIFT+Nav: because it can incur scrolling we cannot afford a frame of lag with the selection highlight (otherwise scrolling would happen before selection)
// For this to work, IF the user is clipping items, they need to set RangeSrcPassedBy = true to notify the system.
if(ms->InRequestSetRangeNav)
{
IM_ASSERT(id!=0);
IM_ASSERT(g.IO.KeyShift);
constboolis_range_dst=!ms->InRangeDstPassedBy&&g.NavJustMovedToId==id;// Assume that g.NavJustMovedToId is not clipped.