imgui icon indicating copy to clipboard operation
imgui copied to clipboard

Range Selection / Multiple selection for TreeNode (Shift+click, Shift+arrows)

Open devkaiwang opened this issue 7 years ago • 10 comments

It's very straightforward to use Ctrl key to select multiple nodes in the tree. However, it seems when to the shift key multiple selection, the problem becomes complicated. The shift selection is very common in desktop applications.

Shift key selection logic is basically like this:

  1. we select some node(s)
  2. then press shift and keep it down
  3. mouse click some node below or above the node(s) we already selected in step 1
  4. the result is we added more selected or removed from selected based on different cases

Is there a way to achieve this feature?

devkaiwang avatar Jun 05 '18 15:06 devkaiwang

Hello,

I've actually been working on this in the past few weeks. It's not an easy problem to solve because there are various subtleties with how to handle CTRL/SHIFT combinations along with Mouse and Keyboard while still allow for clipping to be used.

Anyway. I've got a prototype version that I'll be iterating on (it doesn't work with TreeNode yet, only for Selectable) and hopefully can push something in the upcoming few weeks. Your feedback will be welcome then.

Here are some internals WIP gif I made along the way

20180518_rangeselectclipping

20180526_multiselect

ocornut avatar Jun 05 '18 15:06 ocornut

Thanks for the all the work! It seems to be more complicated for the tree nodes because of the hierarchy I guess? Looking forward to the new feature!

devkaiwang avatar Jun 06 '18 08:06 devkaiwang

It's not really a problem of hierarchy, but the current API require an extra parameter to pass it data that identify items (often an index). This identification is needed because at the beginning or end of a list imgui needs to communicate requests for range-selection. Considering the explosion of TreeNode API entry point we may need a different approach here.

Currently the WIP api use something like that for Selectable:

// Multi-selection system
// This enables 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.
// Read comments near ImGuiMultiSelectData for details.
ImGuiMultiSelectData* BeginMultiSelect(ImGuiMultiSelectFlags flags, void* range_ref, bool range_ref_is_selected);
ImGuiMultiSelectData* EndMultiSelect();
bool                  MultiSelectable(const char* label, bool selected, void* item_data, ImGuiSelectableFlags extra_flags = 0, ImVec2 size = ImVec2(0,0));  // return true when selection needs toggling

With the extra void* item_data. I already have a few things to improve with the current API and I will of course add TreeNode in the mix. Perhaps moving to a separate call SetNextMultiSelectData(void*) and use regular entry point (and remove MutliSelectable()).

ocornut avatar Jun 06 '18 09:06 ocornut

I reworked the range-select/multi-select API and made it work with TreeNode(). Here's a quick GIF.

20180613_multiselecttreenode

It's a little awkward looking because TreeNode don't have the same form of highlight as Selectable() so there is spacing with you range select multiple items.

This API is little quite early/experimental but I'll probably push it to a branch at some point. It would also be healthy to create a full-featured demo with TreeNode featuring Range-Selection, Drag and Drop, etc.

ocornut avatar Jun 13 '18 13:06 ocornut

Hi @ocornut. This prototype looks great!

But right now I have request to do multiselection for nested tree (powered by imGui::TreeNode) and there are two major issues:

  1. correct\fast clipping respecting that TreeNode may be nested
  2. multiselection itself (including the case when child TreeNodes require selection)

Maybe you have some ideas how to solve these issues?

bsviglo avatar Apr 17 '19 15:04 bsviglo

Hello @bsviglo, Your requests / issues are too vague and ambiguous. Please get into more specific details.

ocornut avatar Apr 17 '19 16:04 ocornut

Hi @ocornut. Sorry for being ambiguous in my explanation. I'll try to explain visually what I mean.

On this animated screen I have a world outliner which allows me to visualize and select any object in the scene hierarchy. So far I've managed to select each scene object indivudually but without clipping & range selection.

world_outliner

Basically I'd like to achieve the following:

  1. be able to select any object individually or by range select. And be able to combine selection where some object may be roots while others may be childred on other root tree nodes.
  2. Efficiently skip unnessecary calculations (they are pretty expensive) to visualize tree node (similar to Imgui clipper, but taking into account that we're clipping not a plain list of data but arbitrary deep tree).

Hopefully, it becomes more clear now.

bsviglo avatar Apr 18 '19 08:04 bsviglo

Hi @ocornut do you consider implementing ImGuiTreeClipper helper in the near future?

It looks like a first class citizen for any kind of tree visualization techniques (scene outliner, hierarchy view, tree like document structure, etc)

And having this helper builtin in library will be very convinient

bsviglo avatar Apr 28 '19 19:04 bsviglo

I'd like to have a solution for this implemented but probably won't have time in the near future. Feel free to try working on a solution.!

ocornut avatar Apr 28 '19 19:04 ocornut

2021 update To clarify, the range_select branch been maintained and rebased over master regularly, and designed to merge in docking.

It hasn't been merged because I was rather unhappy with the API. But YOU CAN USE THIS IF YOU NEED IT. If the API change I'll write things down here.

Recently I went through it and listed what I think I could do before "shipping" it:

  • [x] Could we replace RangeSrc/RangeDst to integer indices for simplicity? Technically less flexible but so more much obvious.... The current scheme was designed to allow user to manage clipping + range-select over uncontiguous but ordered data sets (e.g. arrays but also e.g. double linked list). Since there's likely a filtering indirection done by the user, switching to require random access and using int would make api simpler and terser to use.
  • [x] User having to store RangeRef is an UI artifact and generally undesirable, should aim to remove: means users needs to call another function to provide selected state.
  • [x] Possible confusion between user-stored selection and 'ImGuiMultiSelectData' name?
  • [ ] Introduce new style colors (currently interpolating). Probably generalize some extra concepts (focused/unfocused selection color).

ocornut avatar Nov 04 '21 10:11 ocornut

I know this sounds surreal but I've been working on this on and off since my original answer in 2018. It's been used in production on some project for years but I wasn't happy with the API and never formally released it.

I thought I was 80% done, but trying to finish the remaining 20% recently I've been going through countless hoops, redesign, improvements, and writing new demos (filters, trees, deletion, grid etc..) And trying to get the demos to a decent quality levels usually drags in a bunch of misc unrelated features (many of them have been incorporated over the years).

Anyhow. This is very alive and at some point I will open a new thread and ask for more public feedback.

ocornut avatar Aug 23 '23 19:08 ocornut

I have merged multi-select into master. See https://github.com/ocornut/imgui/wiki/Multi-Select for some details. Multi-Select

I will open a thread shortly to gather feedback/bugs so please post so that one thread instead.

ocornut avatar Jul 18 '24 16:07 ocornut

I need to clarify: this particular issue as worded is not fully solved as of today, because using multi-select for tree node is rather unobvious and and not easy currently. In fact, there's no demo for it yet (I'm working on one) and the multi-select branch is currently mostly demoing using Selectable() with multi-select.

Basically you need some sort of linear/random access to your tree, which may be emulated with some linear traversal code, but as it happens, a more advanced tree in a more advanced app is going to want to use a clipper and a filter, and those feature need the same sort of access that multi-select needs. I'm currently working on this.

ocornut avatar Jul 18 '24 16:07 ocornut