Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 93977

Summary: SWT Tree computeSize is broken
Product: [Eclipse Project] Platform Reporter: Vitaliy Stulski <vitaliy.stulski>
Component: SWTAssignee: Veronika Irvine <veronika_irvine>
Status: RESOLVED DUPLICATE QA Contact:
Severity: normal    
Priority: P3 CC: grant_gayed, snorthov
Version: 3.0.1   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:

Description Vitaliy Stulski CLA 2005-05-06 14:41:52 EDT
Eclipse SWT Tree control does not include its visible children when computing
the control size. When a tree control is inside a section part and the tree node
is expanded the section part is not being resized properly. What happens after
tree node expansion - layout calls computeSize for the tree and computeSize for
the tree does not take into account newly expanded tree node(s). I attached an
interim fix for the problem we did in our application.


===============================================================================
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Tree;

public class SAPTree extends Tree {

    static boolean useBugFix = true;

    public SAPTree(Composite parent, int style) {
        super(parent, style);
    }

    public Point computeSize(int wHint, int hHint, boolean changed) {
        if (useBugFix) {
            try {
                checkWidget();
                return OSSAPTree.computeSize(this, wHint, hHint, changed);
            } catch (Throwable ignore) {
                useBugFix = false;
            }
        }
        return super.computeSize(wHint, hHint, changed);
    }
}
===============================================================================
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Tree;

import org.eclipse.swt.internal.win32.OS;
import org.eclipse.swt.internal.win32.RECT;

public class OSSAPTree {

    public OSSAPTree() {
        super();
    }

    /**
     * Recursivelly computes the size of the give item and it's visible children
     * 
     * @param hItem
     * @return
     */
    static Point internalComputeSize(Tree tree,int hItem) {
        int width = 0, height = 0;
        RECT rect = new RECT();
        Point childSize;
        while (hItem != 0) {
            rect.left = hItem;
            if (OS.SendMessage(tree.handle, OS.TVM_GETITEMRECT, 1, rect) != 0) {
                width = Math.max(width, rect.right);
                height += rect.bottom - rect.top;

                // compute children size
                int hChild = OS.SendMessage(tree.handle, OS.TVM_GETNEXTITEM,
OS.TVGN_CHILD, hItem);
                if (hChild != 0) {
                    childSize = internalComputeSize(tree, hChild);
                    width = Math.max(width, childSize.x);
                    height += childSize.y;
                }
            }
            hItem = OS.SendMessage(tree.handle, OS.TVM_GETNEXTITEM,
OS.TVGN_NEXT, hItem);
        }

        return new Point(width, height);
    }

    /* (non-Javadoc)
     * @see org.eclipse.swt.widgets.Control#computeSize(int, int, boolean)
     */
    static Point computeSize(Tree tree, int wHint, int hHint, boolean changed) {
        int width = 0, height = 0;
        int hItem = OS.SendMessage(tree.handle, OS.TVM_GETNEXTITEM,
OS.TVGN_ROOT, 0);

        // Compute the size of the root item and all visible children
        Point p = internalComputeSize(tree,  hItem);
        
        width = p.x;
        height = p.y;
        if (width == 0)
            width = 64;
        if (height == 0)
            height = 64;
        if (wHint != SWT.DEFAULT)
            width = wHint;
        if (hHint != SWT.DEFAULT)
            height = hHint;
        int border = tree.getBorderWidth();
        width += border * 2;
        height += border * 2;
        if ((tree.getStyle() & SWT.V_SCROLL) != 0) {
            width += OS.GetSystemMetrics(OS.SM_CXVSCROLL);
        }
        if ((tree.getStyle() & SWT.H_SCROLL) != 0) {
            height += OS.GetSystemMetrics(OS.SM_CYHSCROLL);
        }
        return new Point(width, height);
    }
}
===============================================================================
Comment 1 Vitaliy Stulski CLA 2005-05-06 14:44:10 EDT
It's not only 3.0.1 issue. The same issue exists in 3.0.2 and 3.1 (I checked it
with M6 build). More over our fix does not work with 3.1 because it's impossible
to inherit Tree class.
Comment 2 Steve Northover CLA 2005-05-09 10:07:11 EDT
SN, VI and GG to discuss.
Comment 3 Veronika Irvine CLA 2005-05-09 11:26:52 EDT
Sounds like a duplicate of bug 49724.
Comment 4 Vitaliy Stulski CLA 2005-05-09 14:54:38 EDT
I've read description of a 49724. I think this issue is not a duplicate. It is
different behavior because in the case I described tree is not being resized
vertically. So instead of taking whole screen like in 49724 it may take only one
line for the only root node (e.g. for XML file display) and this is not right in
my opinion.
Comment 5 Veronika Irvine CLA 2005-05-09 15:34:03 EDT
The first part of Bug 49724 is actually fixed.  I was referring to Bug 49724 
Comment #1: "Leaving bug open for the minute because there are platform 
differences in the behaviour of Tree.computeSize"

*** This bug has been marked as a duplicate of 49724 ***
Comment 6 Vitaliy Stulski CLA 2005-05-09 15:47:30 EDT
(In reply to comment #3)
> *** Bug 93977 has been marked as a duplicate of this bug. ***

Is behavior "Windows/Mac/Motif/Photon - width and height based on root items
only" is the right one? Let the container decide optimal size of the tree based
on a layout selected and correct children size returned by Tree control. This is
critical for us.