-
Notifications
You must be signed in to change notification settings - Fork 29.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Selection and expansion state is lost after tree node label change #40018
Comments
After discussions with @sandy081 I tried this workaround: Instead of implementing a In the former case VS Code uses the With this approach selection and expansion state was preserved after tree item changes. Since this workaround exists, I've removed the "Important" label. However, this workaround uncovered another bug #40179. |
After discussions with @weinand following is implemented Make sure UI state of a node is retained until the handle is not changed. A tree provider provides Another implementation detail is that, |
So a tree provider implementation will be able to supply the |
@eamodio It already exists. I refer Element of type export interface TreeDataProvider<T> {
/**
* An optional event to signal that an element or root has changed.
* To signal that root has changed, do not pass any argument or pass `undefined` or `null`.
*/
onDidChangeTreeData?: Event<T | undefined | null>;
/**
* Get [TreeItem](#TreeItem) representation of the `element`
*
* @param element The element for which [TreeItem](#TreeItem) representation is asked for.
* @return [TreeItem](#TreeItem) representation of the element
*/
getTreeItem(element: T): TreeItem | Thenable<TreeItem>;
/**
* Get the children of `element` or root if no element is passed.
*
* @param element The element from which the provider gets children. Can be `undefined`.
* @return Children of `element` or root if no element is passed.
*/
getChildren(element?: T): ProviderResult<T[]>;
} It is up to Tree provider to decide what kind of handle it wants to provide. It can be a string or Basically, there is no change in the API and the contract. The underlying implementation got changed to retain the state of an element/handle until it is not changed. |
Ah, so you can't use a |
I find the statement "to retain the state of an element/handle until it is not changed" confusing because it still sounds like the state is lost if the element/handle changes. I think it should read: "the UI preserves the selection and expansion state for a tree node based on the node's handle. If the handle disappears the state is lost." In addition I do not understand why you mention how the internal handle "ID" is calculated. First I think the calculation is wrong because it takes the child index into account which ties the retained state to a child index and not to a child identity. And secondly I do not understand how this calculation could help authors in any way. |
I think it just speaks to the stability (or instability) of how the state will be preserved. Personally I would like to be able to still use But it is totally optional and no behavior changes if it is not there. For example, for most things in GitLens, using the label of a |
You can continue to use the TreeItem as the handle. The only thing that has changed is that the ID of the TreeItem is not based on its label anymore. So you cannot change the ID of a TreeItem. |
Oh, so state will be preserved even if the label changes. Got it. Thanks! |
@weinand Thanks for the wordings and for making it clear.
I mentioned that as just as an implementation detail. This should not impact the above behaviour as ID remains same always for the given handle. But, I see including index might be an issue if the children are shuffled. I will look into that.
Advantage it has is when the extension authors create new handles for the same TreeItem then this tries to preserves the selection and expansion state which I thought is good. Thanks. |
Trying to match new handles to old handles (based on the TreeItem) is wrong because it takes away control from the TreeDataProvider and makes the whole story non-deterministic. How do you detect that the new handle should take over the retained state from the old handle? Just because the new handle sits at the same position as the old handle? I firmly believe that the underlying model should be only this:
|
@weinand Yes, the disadvantage of that approach is causing non-deterministic. It's good to have deterministic behaviour. I will change the implementation to have a unmodifiable unique ID per handle. |
Wait, so now with this change when using a I feel strongly now that with this change there should be a way to an extension to provide that unique id (still can be unmodifiable and at creation of the TreeItem), but without some sort of extension provided correlation key (label or specifically provided id) this is a HUGE step backward. |
@eamodio Right, I was using the initial label and index to generate an ID for the The right solution for this is to have an optional |
@sandy081 with your proposal to introduce an 'id' attribute are the following statements correct?
|
Here is the strategy we concluded: If |
The custom explorer's selection and expansion state is only retained, if the label of the tree node does not change.
If the label changes (e.g. because one part of it reflects a dynamically changing status), the selection and expansion state is lost.
Please note that in my TreeDataProvider implementation I'm returning the same TreeItem instance for the same tree node, so I'm not deleting a TreeItem and I'm not creating a new in its place. In this case the VS Code custom tree should have no problem to preserve the selection because the TreeNode instance does not change (only its label). It should not use the label as a unique ID but assign a unique ID to the TreeItems on its own.
And even when using a TreeDataProvider implementation that returns new TreeItems on every refresh it should be possible that the selection is preserved. For this the TreeItem could support an
id
attribute that could be overwritten if necessary.Since the lost selection makes a dynamic tree very difficult to use for users, I think this is an "important" bug.
The text was updated successfully, but these errors were encountered: