Skip to content

MultiSelect + DragDrop + TreeNode: Hovering over an open TreeNode with DragDrop active causes MultiSelect selection to be cleared and replaced by only the hovered TreeNode #7850

Closed
@bratpilz

Description

Version/Branch of Dear ImGui:

Version 1.91.1 WIP, Branch: master

Back-ends:

imgui_impl_glfw.cpp + imgui_impl_opengl3.cpp

Compiler, OS:

Linux + GCC

Full config/build information:

Dear ImGui 1.91.1 WIP (19101)
--------------------------------
sizeof(size_t): 8, sizeof(ImDrawIdx): 2, sizeof(ImDrawVert): 20
define: __cplusplus=201103
define: __linux__
define: __GNUC__=12
--------------------------------
io.BackendPlatformName: imgui_impl_glfw
io.BackendRendererName: imgui_impl_opengl3
io.ConfigFlags: 0x00000003
 NavEnableKeyboard
 NavEnableGamepad
io.ConfigInputTextCursorBlink
io.ConfigWindowsResizeFromEdges
io.ConfigMemoryCompactTimer = 60.0
io.BackendFlags: 0x0000000E
 HasMouseCursors
 HasSetMousePos
 RendererHasVtxOffset
--------------------------------
io.Fonts: 1 fonts, Flags: 0x00000000, TexSize: 512,64
io.DisplaySize: 1280.00,720.00
io.DisplayFramebufferScale: 1.00,1.00
--------------------------------
style.WindowPadding: 8.00,8.00
style.WindowBorderSize: 1.00
style.FramePadding: 4.00,3.00
style.FrameRounding: 0.00
style.FrameBorderSize: 0.00
style.ItemSpacing: 8.00,4.00
style.ItemInnerSpacing: 4.00,4.00

Details:

My Issue/Question:

Hello again! I know MultiSelect in combination with trees is still experimental, but I tried it anyway and ran into the issue described in the title.
Using the various MultiSelect features like Ctrl/Shift clicking works fine on TreeNodes. But now I wanted to be able to drag all selected nodes at once. For this, I call Begin(/End)DragDropSource after each TreeNode, which also works well. But when I have this DragDrop active and hover over a TreeNode that's currently open, the selection gets overwritten by just that single node I'm hovering. I'm guessing this has something to do with the fact that TreeNodes get automatically opened on hover while DragDrop is active. Relatedly, passing ImGuiDragDropFlags_SourceNoHoldToOpenOthers to BeginDragDropSource prevents this issue from occurring.

Screenshots/Video:

multi-select-treenode-open-issue.mp4

Minimal, Complete and Verifiable Example code:

// Here's some code anyone can copy and paste to reproduce your issue
	{
	  using namespace ImGui;
	  SetNextWindowSize (ImVec2 (400.0f, 300.0f), ImGuiCond_Appearing);
	  Begin ("Test");
	  static ImGuiSelectionBasicStorage selection;
	  static unsigned const N = 3;
	  auto ms = BeginMultiSelect (ImGuiMultiSelectFlags_BoxSelect1d, selection.Size, N * (N+1));
	  selection.ApplyRequests (ms);
	  auto dnd_source = [&]() {
	    if (!BeginDragDropSource()) // Workaround: Pass ImGuiDragDropFlags_SourceNoHoldToOpenOthers here to prevent the issue from occurring.
	      return;
	    SetDragDropPayload ("test", 0, 0);
	    Text ("Dragging %u selected node%s:", selection.Size, selection.Size == 1 ? "" : "s");
	    void *it = 0;
	    ImGuiID id;
	    while (selection.GetNextSelectedItem (&it, &id))
	      {
		unsigned id_i = id / (N+1);
		unsigned rest = id - id_i * (N+1);
		if (rest == 0)
		  Text ("- Top level %u", id_i);
		else
		  Text ("- Top level %u / Leaf %u", id_i, rest-1);
	      }
	    EndDragDropSource(); };
	  for (unsigned i = 0; i < N; ++i)
	    {
	      char label[32];
	      snprintf (label, sizeof label, "Top level %u", i);
	      int base_flags = ImGuiTreeNodeFlags_SpanFullWidth;
	      int flags = base_flags;
	      unsigned base_id = i * (N+1);
	      if (selection.Contains (base_id))
		flags |= ImGuiTreeNodeFlags_Selected;
	      SetNextItemSelectionUserData (base_id);
	      bool top_level_open = TreeNodeEx (label, flags);
	      dnd_source();
	      if (!top_level_open)
		continue;
	      for (unsigned j = 0; j < N; ++j)
		{
		  int flags = base_flags | ImGuiTreeNodeFlags_Leaf;
		  unsigned leaf_id = base_id + 1 + j;
		  if (selection.Contains (leaf_id))
		    flags |= ImGuiTreeNodeFlags_Selected;
		  snprintf (label, sizeof label, "Leaf %u", j);
		  SetNextItemSelectionUserData (leaf_id);
		  bool leaf_open = TreeNodeEx (label, flags);
		  dnd_source();
		  if (leaf_open)
		    TreePop();
		}
	      TreePop();
	    }
	  ms = EndMultiSelect();
	  selection.ApplyRequests (ms);
	  End();
	}

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions