Skip to content

Commit 011d475

Browse files
committed
TreeNode: The collapsing arrow accepts click even if modifier keys are being held, facilitating interactions with multi-select patterns. (ocornut#2886, ocornut#1896, ocornut#1861)
1 parent 037126e commit 011d475

File tree

3 files changed

+15
-7
lines changed

3 files changed

+15
-7
lines changed

docs/CHANGELOG.txt

+2
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ Other Changes:
6666
- ColorPicker: Fixed SV triangle gradient to block (broken in 1.73). (#2864, #2711). [@lewa-j]
6767
- TreeNode: Fixed combination of ImGuiTreeNodeFlags_SpanFullWidth and ImGuiTreeNodeFlags_OpenOnArrow
6868
incorrectly locating the arrow hit position to the left of the frame. (#2451, #2438, #1897)
69+
- TreeNode: The collapsing arrow accepts click even if modifier keys are being held, facilitating
70+
interactions with multi-select patterns. (#2886, #1896, #1861)
6971
- DragScalar, SliderScalar, InputScalar: Added p_ prefix to parameter that are pointers to the data
7072
to clarify how they are used, and more comments redirecting to the demo code. (#2844)
7173
- Misc: Optimized storage of window settings data (reducing allocation count).

imgui_internal.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ enum ImGuiButtonFlags_
365365
ImGuiButtonFlags_DontClosePopups = 1 << 7, // disable automatically closing parent popup on press // [UNUSED]
366366
ImGuiButtonFlags_Disabled = 1 << 8, // disable interactions
367367
ImGuiButtonFlags_AlignTextBaseLine = 1 << 9, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine
368-
ImGuiButtonFlags_NoKeyModifiers = 1 << 10, // disable interaction if a key modifier is held
368+
ImGuiButtonFlags_NoKeyModifiers = 1 << 10, // disable mouse interaction if a key modifier is held
369369
ImGuiButtonFlags_NoHoldingActiveID = 1 << 11, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only)
370370
ImGuiButtonFlags_PressedOnDragDropHold = 1 << 12, // press when held into while we are drag and dropping another item (used by e.g. tree nodes, collapsing headers)
371371
ImGuiButtonFlags_NoNavFocus = 1 << 13, // don't override navigation focus when activated

imgui_widgets.cpp

+12-6
Original file line numberDiff line numberDiff line change
@@ -5269,14 +5269,23 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
52695269
// - OpenOnDoubleClick .............. double-click anywhere to open
52705270
// - OpenOnArrow .................... single-click on arrow to open
52715271
// - OpenOnDoubleClick|OpenOnArrow .. single-click on arrow or double-click anywhere to open
5272-
ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers;
5272+
ImGuiButtonFlags button_flags = 0;
52735273
if (flags & ImGuiTreeNodeFlags_AllowItemOverlap)
52745274
button_flags |= ImGuiButtonFlags_AllowItemOverlap;
52755275
if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick)
52765276
button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0);
52775277
if (!is_leaf)
52785278
button_flags |= ImGuiButtonFlags_PressedOnDragDropHold;
52795279

5280+
// We allow clicking on the arrow section with keyboard modifiers held, in order to easily
5281+
// allow browsing a tree while preserving selection with code implementing multi-selection patterns.
5282+
// When clicking on the rest of the tree node we always disallow keyboard modifiers.
5283+
const float hit_padding_x = style.TouchExtraPadding.x;
5284+
const float arrow_hit_x1 = (text_pos.x - text_offset_x) - hit_padding_x;
5285+
const float arrow_hit_x2 = (text_pos.x - text_offset_x) + (g.FontSize + padding.x * 2.0f) + hit_padding_x;
5286+
if (window != g.HoveredWindow || !(g.IO.MousePos.x >= arrow_hit_x1 && g.IO.MousePos.x < arrow_hit_x2))
5287+
button_flags |= ImGuiButtonFlags_NoKeyModifiers;
5288+
52805289
bool selected = (flags & ImGuiTreeNodeFlags_Selected) != 0;
52815290
const bool was_selected = selected;
52825291

@@ -5287,13 +5296,10 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
52875296
{
52885297
if (pressed)
52895298
{
5290-
const float hit_padding_x = style.TouchExtraPadding.x;
5291-
const float arrow_hit_x1 = (text_pos.x - text_offset_x) - hit_padding_x;
5292-
const float arrow_hit_x2 = (text_pos.x - text_offset_x) + (g.FontSize + padding.x * 2.0f) + hit_padding_x;
5293-
if (flags & ImGuiTreeNodeFlags_OpenOnArrow)
5294-
toggled |= (g.IO.MousePos.x >= arrow_hit_x1 && g.IO.MousePos.x < arrow_hit_x2) && (!g.NavDisableMouseHover); // Lightweight equivalent of IsMouseHoveringRect() since ButtonBehavior() already did the job
52955299
if ((flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)) == 0 || (g.NavActivateId == id))
52965300
toggled = true;
5301+
if (flags & ImGuiTreeNodeFlags_OpenOnArrow)
5302+
toggled |= (g.IO.MousePos.x >= arrow_hit_x1 && g.IO.MousePos.x < arrow_hit_x2) && (!g.NavDisableMouseHover); // Lightweight equivalent of IsMouseHoveringRect() since ButtonBehavior() already did the job
52975303
if ((flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) && g.IO.MouseDoubleClicked[0])
52985304
toggled = true;
52995305
if (g.DragDropActive && is_open) // When using Drag and Drop "hold to open" we keep the node highlighted after opening, but never close it again.

0 commit comments

Comments
 (0)