-
Notifications
You must be signed in to change notification settings - Fork 193
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
TreeViewer: auto expansion for elements with single children #1072
TreeViewer: auto expansion for elements with single children #1072
Conversation
I still need to address a few points as part of this PR
|
For auto expand there are only getAutoExpandLevel/setAutoExpandLevel with 0 and -1 having special meaning so it's seems a little strange/confusing four methods for this new feature... |
Test Results 917 files - 1 917 suites - 1 36m 44s ⏱️ - 12m 44s For more details on these failures, see this check. Results for commit 8e0452b. ± Comparison against base commit 7572bd4. This pull request removes 7 and adds 62 tests. Note that renamed tests count towards both.
♻️ This comment has been updated with latest results. |
edc9dd8
to
82fb58e
Compare
Good catch, I changed my proposal to be more consistent with the existing behaviour @merks |
I think this will be a cool feature! |
ade0788
to
4f7651d
Compare
2486211
to
1a49af7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the proposed change in general, still I have two major remarks (and some fine-grained ones made as code comments):
Functionality:
The changes to AbstractTreeViewer
are currently API breaking: the new methods for setting the auto expansion (such as setAutoExpandTrivialPathsLevel
) claim that when setting the expansion level, the instance will perform auto-expansion. The current implementation does, however, not guarantee that but relies on implementations of that class (such as TreeViewer
) to provide the according behavior. I would propose to change the implementation such that AbstractTreeViewer
already provides the claimed functionality by changing the according methods handling changes of the expansion state of a node and adding a listener that reacts to expansion state changes (like now done in the TreeViewer
.
Naming:
I am not in favor of the current naming, as I don't think that there is a common understanding of what "trivial paths" are. This requires every method related to the functionality to explain what is meant. I would suggest to change the naming to something more self-explaning. This could be something like autoExpandOnSingleChild
or the like (better proposals are welcome).
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java
Outdated
Show resolved
Hide resolved
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java
Outdated
Show resolved
Hide resolved
setExpanded((Item) w, true); | ||
createChildren(w); | ||
return getChildren(w); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to reimplement the essential expansion functionality as already implemented in setExpandedState
. Is there a necessity for this additional method?
if (expanded) { | ||
createChildren(item); | ||
if (expandAndCreateChildren(item).length == 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would expect the additional extension to happen after the "ordinary" extension has happended completely, i.e., after creating childen and setting the expand state has happened. First performing the recusive extension and then setting the expand state does not look to be the right order to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have changed the order in which both operations happen, I suspect that this does not correctly reflect what you actually intended by your comment. If that is the case, can you please specify what exactly you have in mind?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Recursive expansion should happen by completely expanding an items before starting the expansion of a child. The state change of an auto expansion should be equal to manually extending levels one-by-one, i.e., before expanding a child, the parent expansion should be finished in terms of creating all its children, settings it expanded state (and maybe further state changes I am not aware of). Currently, the logic is quite convoluted, as this method sets the expanded state and then calls expandAndCreateChildren
, which sets the state again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (item instanceof Item) {
setExpanded((Item) item, expanded);
if (expanded) {
if (expandAndCreateChildren(item).length == 1) {
expandPathOfSingleChildren(getChildren(item)[0], getAutoExpandOnSingleChildLevel());
}
}
}
What currently happens:
- set the expanded state (calls the winapi, doesn't add the children)
if the expanded state is expanded: - set the expanded state again (doesn't do anything new)
- create the children
- return the amount of children
- check: does my parent only have one child? If so, start the recursive routine that expands trivial paths and keeps track of how many levels it has recursed
Steps 1-4 expand the node and do not yet add any behaviour. Step 5 is the actual expansion of paths of singular children - just as you had described in your comment, I first perform the existing behaviour and then simulatie "clicking" through the children to consecutively open them.
From what I understood in your comment, your issue boils down to 1) and 2) being duplicates of eachother. A rather obvious solution would be to check for the expanded state so that I only set it once
if (!expanded) {
setExpanded((Item) item, false);
} else {
if (expandAndCreateChildren(item).length == 1) {
expandPathOfSingleChildren(getChildren(item)[0], getAutoExpandOnSingleChildLevel());
}
}
I am a bit hesitant about making this change as it introduces additional control flow and complexity. However, setExpanded
performs a call to winapi (... and probably to cocoa and gtk too), hence I can understand why we would want to limit it's use.
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/TreeViewer.java
Outdated
Show resolved
Hide resolved
...g.eclipse.ui.navigator.resources/src/org/eclipse/ui/navigator/resources/ProjectExplorer.java
Outdated
Show resolved
Hide resolved
tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/viewers/AbstractTreeViewerTest.java
Outdated
Show resolved
Hide resolved
1a49af7
to
c049882
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like that you were able to move functionality completely into AbstractTreeViewer
. That makes my previous concerns with respect to API compatibility obsolete.
Please consider my unanswered comment from last review.
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java
Outdated
Show resolved
Hide resolved
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java
Outdated
Show resolved
Hide resolved
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java
Outdated
Show resolved
Hide resolved
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java
Outdated
Show resolved
Hide resolved
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java
Outdated
Show resolved
Hide resolved
if (expanded) { | ||
createChildren(item); | ||
if (expandAndCreateChildren(item).length == 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Recursive expansion should happen by completely expanding an items before starting the expansion of a child. The state change of an auto expansion should be equal to manually extending levels one-by-one, i.e., before expanding a child, the parent expansion should be finished in terms of creating all its children, settings it expanded state (and maybe further state changes I am not aware of). Currently, the logic is quite convoluted, as this method sets the expanded state and then calls expandAndCreateChildren
, which sets the state again.
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/TreeViewer.java
Outdated
Show resolved
Hide resolved
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java
Outdated
Show resolved
Hide resolved
c049882
to
ced49bd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have taken a deeper look into the overall design of the expand mechanism in the AbstractTreeViewer
. I would like to make some proposals to improve this PR by reusing existing functionality and the insights behind.
internalExpandToLevel
already has a sophisticated implementation for expanding a certain amount of levels, including some performance improvements. I would propose to let the recursive expansion when only having a single child use this functionality by generalizing it to some kind ofinternalConditionalExpandToLevel
that additionally accepts ashouldExpand
function (Widget -> boolean) that is used to calculate whether the next recursion of expansion shall be performed. Then the existinginternalExpandToLevel
method can use this method with a function always returning true, while the expand on single child functionality will pass a condition based on the number of childs of the widget.- The
expandToLevel(...)
methods disable the redraw of the tree viewer while expanding (to avoid flickering). That may not be a severe problem with recursive expansion when only having one child, as this should be quite fast, still the functionality is already there and I would thus propose to reuse it. You could, for example, encapsulate the transaction that ensures proper disablement and re-enablement of redraw into a functional that can be used by both the existingexpandToLevel
as well as theexpandOnSingleChild
. It could look something like this:
private void excuteWithRedrawDisabled(Runnable toExecute) {
Control control = getControl();
try {
control.setRedraw(false);
toExecute.run();
} finally {
control.setRedraw(true);
}
}
After Review by @HeikoKlare in eclipse-platform#1072, this method allows for other methods to perform costly operations on an undrawn tree without manually dis- and re-enabling the tree.
ced49bd
to
87a47e2
Compare
After Review by @HeikoKlare in eclipse-platform#1072, this method allows for other methods to perform costly operations on an undrawn tree without manually dis- and re-enabling the tree.
87a47e2
to
5c61e61
Compare
After Review by @HeikoKlare in eclipse-platform#1072, this method allows for other methods to perform costly operations on an undrawn tree without manually dis- and re-enabling the tree.
5c61e61
to
8af421c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought that the refactoring of the temporary redraw disablement would be rather local and thus proposed to do it in this PR or extract it to another that is merged before. Since a reasonable refactoring will probably be a bit larger (see #1191) and should not prevent this PR from being merged, So feel free to change the code back to the original sequence of manual setRedraw(false) and setRedraw(true), which will then be refactored together with all other analogous places in the code in an according refactoring. Sorry for the back and forth, but I was not aware that the issue is a more general one when proposing the refactoring.
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java
Outdated
Show resolved
Hide resolved
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java
Outdated
Show resolved
Hide resolved
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java
Outdated
Show resolved
Hide resolved
99adede
to
393e4ce
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have two major remarks (and requests for change) and some minor detailed comments:
- The current changes break public API (
setExpandedState
). This needs to be adapted. - The tests should cover all different usage scenarios of the different methods. In particular, they should cover the different ways in which auto-expansion can happen, i.e., not only via
setExpandedState
but also via SWT events. I'd propose to relate the tests to the different added or changed methods. For example, there should also be trivial tests, such asget...Level
returning what has been set byset...Level
to easy debugging in case only the setter is broken, as currently the tests for the expand behavior would break although it's state may simply not be represented as expected after calling the setter.
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java
Outdated
Show resolved
Hide resolved
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java
Outdated
Show resolved
Hide resolved
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java
Outdated
Show resolved
Hide resolved
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java
Outdated
Show resolved
Hide resolved
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java
Outdated
Show resolved
Hide resolved
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java
Outdated
Show resolved
Hide resolved
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java
Outdated
Show resolved
Hide resolved
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java
Outdated
Show resolved
Hide resolved
tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/viewers/AbstractTreeViewerTest.java
Outdated
Show resolved
Hide resolved
tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/viewers/AbstractTreeViewerTest.java
Outdated
Show resolved
Hide resolved
924e16b
to
f1f2c47
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes work and look good now.
I propose to target the merge for 2024-06 M1. The change affects the TreeViewer
as a rather central component, so I would propose to not risk a potentially undetected regression now that we are already quite late in 2024-03 development.
f1f2c47
to
f02caaa
Compare
0eab3bd
to
c4040b2
Compare
This commit addresses the need to automatically expand paths which consist of chained singular nodes, eg: com.wittmaxi.plugin └─src └─org.foo.com └─Bar.java It introduces two new methods to the API of TreeViewer -setAutoExpandOnSingleChildLevel -getAutoExpandOnSingleChildLevel Also includes a version bump for AbstractTreeViewer Autoexpand
Tests for virtual lazy tree viewers that access the data of a tree items have been disabled because of some bug in according Mac implementation. This also disables a test case for the auto-expand on single child functionality that relies on accessing the item data. Also removes unused API problem filters.
c4040b2
to
8e0452b
Compare
Failing test is pre-existing and already documented: #1005. |
The API filter added for the AbstractTreeViewer for the 4.32 release became obsolete when moving to the 4.33 stream. This change removes the now obsolete filter. See eclipse-platform#1072
The API filter added for the AbstractTreeViewer for the 4.32 release became obsolete when moving to the 4.33 stream. This change removes the now obsolete filter. See #1072
As implementation of #1063, This PR addresses the need to automatically expand paths which consist of chained singular nodes, eg:
It introduces two new API-Methods into TreeViewer:
-setAutoExpandTrivialPathsLevel
-getAutoExpandTrivialPathsLevel
The PR also uses the new features in the Project Explorer, thus resolving #1063