Bug 103420 - [Forms] ScrolledForm does not scroll anymore
Summary: [Forms] ScrolledForm does not scroll anymore
Status: RESOLVED INVALID
Alias: None
Product: Platform
Classification: Eclipse Project
Component: User Assistance (show other bugs)
Version: 3.1   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Adam Archer CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-07-11 18:56 EDT by Andrew Wright CLA
Modified: 2016-08-03 08:17 EDT (History)
7 users (show)

See Also:


Attachments
EditPart with a ScrolledForm which will not scroll around a Large Label. (2.31 KB, text/java)
2005-07-11 18:57 EDT, Andrew Wright CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Wright CLA 2005-07-11 18:56:18 EDT
Broken from 3.0.2 to 3.1.  ScrolledForm will not scroll anymore.  I will attach
source code for a simple EditPart which will not scroll on 3.1, but will scroll
on 3.0.2.
Comment 1 Andrew Wright CLA 2005-07-11 18:57:24 EDT
Created attachment 24580 [details]
EditPart with a ScrolledForm which will not scroll around a Large Label.
Comment 2 Konrad Kolosowski CLA 2005-07-25 16:52:48 EDT
It is UI Forms.
Comment 3 Andrew Wright CLA 2005-09-29 19:14:29 EDT
This bug blocks me from migrating to eclipse 3.1 for my company's RCP
application.  I really need to migrate for some of the features we need, but
these unscrolled forms are not going to work.
Comment 4 David Graham CLA 2005-09-29 19:17:38 EDT
I can see the scrollbars flash in the UI while I resize the editor.  When the
resize is finished the scrollbars disappear.  So, it seems like they are trying
to render but are finally cancelled.
Comment 5 David Graham CLA 2005-11-07 17:27:24 EST
After some investigation I found a couple interesting things:
1.  If you set the form's layout to TableWrapLayout the scrollbars work.  Set
the layout to GridLayout and the scrollbars disappear.

2.  To get scrollbars to work with a GridLayout you need to tell the
ScrolledForm to reflow() when it's resized like this:

final Runnable reflow = new Runnable() {
    public void run() {
        form.reflow(true);
    }
};
parent.addControlListener(new ControlAdapter() {
    public void controlResized(ControlEvent e) {
        form.getDisplay().asyncExec(reflow);                
    }
});

This causes quite a bit of flashing because the ControlListener is updated many
times during a drag resize.  You can alter the Runnable a bit to only call
reflow() if it wasn't called in the last 100 ms to prevent some of the flashing.

Obviously this is quite a piece of strategery just to get something as simple as
scrollbars to work.
Comment 6 Paul E. Keyser CLA 2006-01-23 16:16:05 EST
In my case, neither solution works: 
a) using TableWrapLayout results in a *tiny* scrollbar (about 4 pixels high); 
b) using the Runnable does nothing at all (the scroll-bar just slides up and down without causing an effect on the contained control at all) 

Comment 7 Dejan Glozic CLA 2006-04-17 18:57:40 EDT
There seems to be a bug somewhere with the cached value of preferred size being used before the label has been added to the body composite.

A single call to 'form.reflow(true)' at the end of the attached editor's method 'createPartControl(Composite)' worked in case of GridLayout with no flashing.

Leaving the defect in to further trace the caching bug but reducing severity since workaround has been provided.
Comment 8 Angel Vera CLA 2006-07-24 17:44:12 EDT
Dejan, 

I assumed there is no impact of me leaving that 'form.reflow(true)' after this defect gets fixed correct?
Comment 9 Angel Vera CLA 2006-07-24 17:46:51 EDT
Dejan, 

I assumed there is no impact of me leaving that 'form.reflow(true)' after this defect gets fixed correct?
(In reply to comment #7)
> There seems to be a bug somewhere with the cached value of preferred size being
> used before the label has been added to the body composite.
> A single call to 'form.reflow(true)' at the end of the attached editor's method
> 'createPartControl(Composite)' worked in case of GridLayout with no flashing.
> Leaving the defect in to further trace the caching bug but reducing severity
> since workaround has been provided.

Dejan, 

I assumed there is no impact of me leaving that 'form.reflow(true)' after this
defect gets fixed correct?
Comment 10 Curtis d'Entremont CLA 2006-07-24 17:58:57 EDT
(Dejan on vacation)

I believe that's a safe assumption to make.
Comment 11 Ketan Padegaonkar CLA 2007-11-20 04:05:56 EST
Anything on when this is going to be fixed ? I'm having issues with the following code snippet not working:

As mentioned in comment #4, the scrollbars seem to flicker when the shell is resized but they do not show up.

public static void main(String[] args) {
    Display display = new Display();
    Shell parent = new Shell(display, SWT.DIALOG_TRIM | SWT.RESIZE);
    parent.setLayout(new FillLayout());

    FormToolkit formToolkit = new FormToolkit(parent.getDisplay());

    final ScrolledForm form = new ScrolledForm(parent, SWT.V_SCROLL);
    form.setBackground(formToolkit.getColors().getBackground());
    form.setForeground(formToolkit.getColors().getColor(IFormColors.TITLE));
    form.setExpandHorizontal(true);
    form.setExpandVertical(true);
    form.setFont(JFaceResources.getHeaderFont());
    form.getBody().setLayout(new RowLayout());
    form.setText("Hello, Eclipse Forms");

    for (int i = 0; i < 200; i++)
        formToolkit.createHyperlink(form.getBody(), "hyperlink-" + i, SWT.NONE);

    parent.open();

    while (!parent.isDisposed()) {
        if (!display.readAndDispatch())
            display.sleep();
    }
    display.dispose();
}
Comment 12 Dejan Glozic CLA 2007-11-20 07:33:48 EST
Adam, here is some post-M4 fun :-).
Comment 13 Konrad Anton CLA 2008-02-04 09:21:25 EST
I'm experiencing the same problem here (Eclipse Europa, Linux-GTK).
Resizing causes a short and transient appearance of scrollbars, but they are
usually gone except when I reduce the window to a size where even the title
text would be only partially visible.

The essence of my program is:

  ScrolledForm form;
  form.setText("Titledeedoo");      // remove this to fix scrollbar problem
  Composite body = form.getBody();
  body.setLayout(new GridLayout());
  // then add widgets to body.

The form.reflow(true) trick fixed the scrollbar problem. Alternatively, so did removing the call to setText.
Comment 14 Adam Archer CLA 2008-02-22 15:21:37 EST
After investigating a potential caching bug as mentioned in comment 7 I have determined that no such bug exists. The SizeCache gets a reflow call on resizes and it correctly checks if the control has changed. If it has not, then it correctly assumes that its cache is still valid.

The reason that this appears to be broken to so many people is that there is no way for the cache to know when children of the form's control have changed. It is up to the client to tell the form that the cache is no longer valid with a call to reflow(true). The boolean parameter indicates that something has changed and the cache is invalid.

The reason that removing calls to setText seems to make everything work is actually a total fluke. ScrolledForm#setText() is calling reflow(true) at the end, as it should, to tell the form that the cache is invalid and should be recomputed. In all of the cases discussed in this bug, the call to setText is actually resulting in the first reflow the form receives and is therefore causing the cache to be populated for the first time. This means that after the body of the form is populated, there is already a cache sitting there ready to be reused. If the client does not tell the form that its children have changed and that its cache is invalid then it will gladly use the cache that it computed in the setText call. You will find that with all example in this bug, the scrollbar issue can be corrected by:

a) removing the call to setText
b) placing the call to setText at the end of the code that populates the form
c) calling reflow(true) after populating the form

(a) and (b) are both incorrect solutions as they rely on somebody else to invalidate the cache. It is up to clients to call reflow(true) any time they change the content of the form as this is the only way for the form to know that its cache is no longer valid. Thus, (c) is the correct approach here.

Closing the bug as INVALID.

I realize that this explanation is very complicated, so feel free to ask questions if I have not made the reasoning clear.