Bug 266189 - [Viewers] Calling TreeViewer.expandToLevel() in a virtual tree materializes all the expanded children.
Summary: [Viewers] Calling TreeViewer.expandToLevel() in a virtual tree materializes a...
Status: NEW
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.5   Edit
Hardware: PC Windows XP
: P3 enhancement (vote)
Target Milestone: ---   Edit
Assignee: Platform UI Triaged CLA
QA Contact:
URL:
Whiteboard:
Keywords: performance
: 324388 (view as bug list)
Depends on:
Blocks: 291267
  Show dependency tree
 
Reported: 2009-02-25 13:48 EST by Pawel Piech CLA
Modified: 2019-09-06 15:36 EDT (History)
5 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Pawel Piech CLA 2009-02-25 13:48:34 EST
This partly defeats the purpose of using the virtual tree and doesn't seem to have any obvious reason.  I believe the offending code is the call to virtualLazyUpdateWidget() for all the children (marked with ">>>") below.  

protected void createChildren(Widget widget) {
    if (contentProviderIsLazy) {
        Object element = widget.getData();
        if (element == null && widget instanceof TreeItem) {
            // parent has not been materialized
            virtualMaterializeItem((TreeItem) widget);
            // try getting the element now that updateElement was called
            element = widget.getData();
        }
        if (element ==  null) {
            // give up because the parent is still not materialized
            return;
        }
        Item[] children = getChildren(widget);
        if (children.length == 1 && children[0].getData() == null) {
            // found a dummy node
            virtualLazyUpdateChildCount(widget, children.length);
            children = getChildren(widget);
        }
        // touch all children to make sure they are materialized
        for (int i = 0; i < children.length; i++) {
            if (children[i].getData() == null) {
>>>             virtualLazyUpdateWidget(widget, i);
            }
        }
        return;
    }
    super.createChildren(widget);
}
Comment 1 Boris Bokowski CLA 2009-03-03 16:11:15 EST
Could you attach a snippet with which I can reproduce the problem? Isn't createChildren supposed to materialize all children?
Comment 2 Pawel Piech CLA 2009-03-03 16:34:20 EST
(In reply to comment #1)
> Could you attach a snippet with which I can reproduce the problem? 
I will, though I probably won't get to it this week.

> Isn't createChildren supposed to materialize all children?
For a regular tree this makes sense, but for virtual I don't see an obvious reason for it.  createChildren() is mostly called by AbstractTreeViewer methods related to expanding the tree, so that expanding several levels down will work.  But for a virtual tree expanding several levels down in a single call doesn't work anyway because the created children's elements are fetched asynchronously.  


Comment 3 Boris Bokowski CLA 2009-03-03 16:37:15 EST
(In reply to comment #2)
>  But for a virtual tree expanding several levels down in a single call doesn't
> work anyway because the created children's elements are fetched 
> asynchronously. 

Not necessarily - as far as I know, only Debug uses the virtual tree in this way.
Comment 4 Pawel Piech CLA 2009-03-03 16:54:51 EST
(In reply to comment #3)
> Not necessarily - as far as I know, only Debug uses the virtual tree in this
> way.
This may be true, and if you think that this bug should not be fixed, then I guess we still have the option to override createChildren() in the debug viewers only.  Although, I believe the performance problem applies to all virtual viewers.
Comment 5 Boris Bokowski CLA 2009-03-03 22:00:41 EST
(In reply to comment #4)
> This may be true, and if you think that this bug should not be fixed,

No - I was just responding to your comment. Let's see what I can do when I get your snippet.
Comment 6 Pawel Piech CLA 2009-10-05 19:36:42 EDT
Following is the snippet to reproduce this bug.   

public class Test266189 {

    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display, SWT.SHELL_TRIM);
        shell.setLayout(new GridLayout());
        GridData data = new GridData(GridData.FILL_BOTH);
        shell.setLayoutData(data);

        Font font = new Font(display, "Courier", 10, SWT.NORMAL);

        final TreeViewer treeViewer = new TreeViewer(shell, SWT.VIRTUAL | SWT.BORDER);
        treeViewer.getControl().setLayoutData(data);

        final ContentProvider contentProvider = new ContentProvider(treeViewer);
        treeViewer.setUseHashlookup(true);
        treeViewer.setContentProvider(contentProvider);
        treeViewer.setInput(contentProvider.fRoot);

        shell.open();

        while (!shell.isDisposed()) {
            if (!display.readAndDispatch())
                break;
        }
        
        // Comment out and expand manually in the window to see the difference 
        treeViewer.expandToLevel("Element", 1);

        while (!shell.isDisposed()) {
            if (!display.readAndDispatch())
                display.sleep();
        }
        font.dispose();
    }

    public static class ContentProvider implements ILazyTreePathContentProvider
    {
            Object fRoot = "Root";
            Object fElement = "Element";
            Object[] fChildren = new Object[1000];
            {
                for (int i = 0; i < fChildren.length; i++) {
                    fChildren[i] = Integer.toString(i);
                }
            }
            TreeViewer fViewer;
    
            ContentProvider(TreeViewer viewer) {
                fViewer = viewer;
            }
    
            public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
            }
    
            public void updateHasChildren(TreePath path) {
                if (path.getSegmentCount() == 0 || path.getSegmentCount() == 1) {
                    fViewer.setHasChildren(path, true);
                } else {
                    fViewer.setHasChildren(path, true);
                }
            }
    
            public void updateChildCount(TreePath path, int currentChildCount) {
                if (path.getSegmentCount() == 0) {
                    fViewer.setChildCount(path, 1);
                } else if (path.getSegmentCount() == 1) {
                    fViewer.setChildCount(path, fChildren.length);
                } else {
                    fViewer.setChildCount(path, 0);
                }
            }
    
            public void updateElement(TreePath path, int index) {
                if (path.getSegmentCount() == 0) {
                    fViewer.replace(path, index, fElement);
                    updateHasChildren(path.createChildPath(fElement));
                } else if (path.getSegmentCount() == 1) {
                    fViewer.replace(path, index, fChildren[index]);
                    System.out.println("Updated child at index = " + index); 
                }
            }
    
    
            public TreePath[] getParents(Object element) {
                return new TreePath[0];
            }
    
            public void dispose() {}
    
        }
    }
Comment 7 Pawel Piech CLA 2009-11-05 13:18:42 EST
ping
Comment 8 Pawel Piech CLA 2009-11-11 16:11:20 EST
FYI, I added a workaround for this bug in the debugger views.
Comment 9 Ben Vitale CLA 2009-11-11 16:34:58 EST
(In reply to comment #8)
> FYI, I added a workaround for this bug in the debugger views.

Any idea if that will that resolve bug 283441?
Comment 10 Boris Bokowski CLA 2009-11-11 17:17:45 EST
Hitesh, can you please have a look at this?
Comment 11 Hitesh CLA 2009-11-12 01:01:34 EST
(In reply to comment #10)
> Hitesh, can you please have a look at this?

Sure Boris.
Comment 12 Boris Bokowski CLA 2009-11-26 09:55:15 EST
Hitesh is now responsible for watching bugs in the [Viewers] component area.
Comment 13 Hitesh CLA 2010-09-03 06:42:30 EDT
*** Bug 324388 has been marked as a duplicate of this bug. ***
Comment 14 Eclipse Webmaster CLA 2019-09-06 15:36:26 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.