Bug 9866 - GridLayout does not handle wrapped Label properly
Summary: GridLayout does not handle wrapped Label properly
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 2.0   Edit
Hardware: PC Windows 2000
: P3 normal with 3 votes (vote)
Target Milestone: ---   Edit
Assignee: Veronika Irvine CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 4458 37592 45467 45475 (view as bug list)
Depends on: 46112 45475
Blocks: 14076
  Show dependency tree
 
Reported: 2002-02-14 16:31 EST by Veronika Irvine CLA
Modified: 2007-06-28 09:26 EDT (History)
12 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Veronika Irvine CLA 2002-02-14 16:31:06 EST
It should be possible to lay the following out with a GridLayout:

|----------------------------------|
| Label text Label text Label text |
| Label text                       |
| -----------------------------    |
| | ListBoxItem1              |    |
| | ListBoxItem2              |    |
| |                           |    |
| |___________________________|    |
|                                  |
|    Ok    Cancel                  |
|__________________________________|

However, it is not possible to the height of the label to vary as the shell 
resize and causes a wrap to be required.

Here is a temporary workaround.  However, the workaround should not be required.

public static void main(String[] args) {
	Display display = new Display();
	final Shell shell = new Shell(display);
	final GridLayout layout = new GridLayout();
	shell.setLayout(layout);
	Label label = new Label(shell, SWT.WRAP);
	final GridData data = new GridData();
	label.setLayoutData(data);
	shell.addControlListener(new ControlAdapter(){
		public void controlResized(ControlEvent e){
			data.widthHint = shell.getClientArea().width - 
2*layout.marginWidth;
			shell.layout(true);
		}
	});
	label.setText("asda sda sdasd asda sda sdada dadads asd adsad as dadsa 
dsad sada dsasda sd adsa sasd");
	List list = new List(shell, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
	list.setLayoutData(new GridData(GridData.FILL_BOTH));
	for (int i = 0; i < 100; i++) {
		list.add("asddas "+i);
	}
	shell.open();
	while (!shell.isDisposed()) {
		if (!display.readAndDispatch())
			display.sleep();
	}
	display.dispose();
}
Comment 1 Kevin Clark CLA 2003-03-04 14:01:08 EST
Hi, I'm experiencing this problem as well.

Currently using Eclipse 2.0.2 on Windows XP.
Comment 2 Steve Northover CLA 2003-03-04 14:40:20 EST
Use the work around for now.
Comment 3 Kevin Clark CLA 2003-03-04 16:45:37 EST
I've decided to go with FormLayout instead of GridLayout. So that's my work-
around.

I did notice that FormLayout was a little buggy on this issue too. The text 
wrap works, but only if you specify aFormLayout.bottom FormAttachment. If you 
just leave the bottom value blank, it will not wrap either.
Comment 4 Steve Northover CLA 2003-03-04 16:54:00 EST
Just to be clear, this isn't exactly a bug.

The preferred size of a label with or without wrapping as computed by 
computeSize(SWT.DEFAULT, SWT.DEFAULT) is always the non-wrapped size.  If you 
think about it, this makes sense.  Given infinite room, a wrapped label should 
never decide to wrap.

When computeSize() is called with a width hint, wrapping is taken into 
account.  The temporary work around code in this PR is doing exactly this.

We may still do something about this PR because the behavior is unexpected.
Comment 5 Steve Northover CLA 2003-09-18 10:38:39 EDT
*** Bug 4458 has been marked as a duplicate of this bug. ***
Comment 6 Steve Northover CLA 2003-10-21 10:38:09 EDT
*** Bug 37592 has been marked as a duplicate of this bug. ***
Comment 7 Grant Gayed CLA 2003-10-24 12:20:21 EDT
*** Bug 45467 has been marked as a duplicate of this bug. ***
Comment 8 Grant Gayed CLA 2003-10-24 12:21:22 EDT
Suggestion from duplicate bug 45467:

When laying out its children, GridLayout first calls computeSize(SWT.NONE,
SWT.NONE) on all controls, and caches the heights. It computes the column width
based on the widest control, then arranges the controls based on the cached
control height.

This is incorrect: once gridlayout knows the column widths, it should invoke
computeSize(actualColumnWidth, SWT.NONE) on all controls to determine the actual
control heights, since the height of some controls (in particular, wrapping
text) may have changed.
Comment 9 Stefan Xenos CLA 2003-10-24 15:40:56 EDT
Regarding comment 4, this bug is not suggesting that the default behavior of a
Control's computeSize(...) is in error. It says that GridLayout provides no
direct means for constructing layouts that contain wrapping text. 

If bug 45475 were fixed, it would be possible to create text that wraps after N
pixels (by default) by attaching a widthHint of N to the wrapping label (without
using any resize listeners).

If bug 45467 were fixed, then other layout types that do not suffer from the
same limitations as GridLayout would continue to work correctly when embedded in
a GridLayout.
Comment 10 paul moore CLA 2004-01-29 13:59:18 EST
Just to add my 10c worth. I have just spent 2 days arm wrestling with this 
behaviour. It is not the expected result. It seems that formlayout isnt any 
better; since you have to specify the bottom, it is not possible to flow blocks 
of text down a page (like the WelcomeEditor) without using resize listeners.
Comment 11 Stefan Xenos CLA 2004-01-29 14:56:40 EST
BTW, I've attached a grid-like layout class that handles wrapping text nicely to
bug 45833. I also have a much simpler variation in the works.

GridLayout's size hints do not offer enough possibilities. There are actually
three kinds of "hint"-type behaviors that are useful in gridlike layouts.

1. Override: the hint is used as the minimum column size instead of the
control's computeSize(...) method. This is useful for scrollable controls (like
listboxes, tree controls, and text controls) that should reserve the same amount
of space regardless of their current contents. This would also work for wrapping
text, although it would reserve too much space for single-line text.

2. Maximum: the hint is used as the maximum amount of space reserved for the
column (the control's computeSize(...) method is used if smaller). This is
useful for wrapping text, which should wrap at some point by default but should
be allowed to shrink if it requires less than one line.

3. Minimum: the hint is used as the minimum amount of space reserved for the
column (the control's computeSize(...) method is used if larger). This is useful
for buttons, which have a standard size but are allowed to grow if they contain
large labels.

In all cases, it is desirable to pass in the real column size to
computeSize(...) rather than the hint --- FILL-aligned controls (like wrapping
text) should be allowed to expand larger than their width hint. For FILL-aligned
controls, the hint should only affect the minimum column size and not the actual
 control size.

The current behavior of GridLayout is this:

4. Use the hint directly as the argument to computeSize(...), which has the
effect of computing the control's dimensions as though it had a fixed size
slightly larger than the hint values (to see what I mean by "slightly larger",
see bug 46112). 

This does not seem useful for any type of layout. From the JavaDoc on
GridLayout, it seems that (1) was the intended behavior. However, to ensure
compatibility I would propose the following solution:

- Add a hintType field to GridData that controls how hints are interpreted.
- The default hintType will select behavior 4 (above).
- To create wrapping text, select hintType 2, set the text control to FILL
alignment, and set the widthHint to the preferred point at which text should wrap.

Comment 12 Stefan Xenos CLA 2004-04-12 14:12:03 EDT
Note: the workaround attached to the original report will only work if the
GridLayout is attached directly to a Shell.

Bug 56892 was caused by attempting to use this workaround for a GridLayout
embedded within another composite. Even for Shells, this workaround should not
be used if the initial size of the Shell is being computed from its controls (as
described in bug 45467) -- for example, you should not use the workaround if you
intend to use Shell.pack().

For whoever is working on this: the classes
org.eclipse.ui.internal.layout.SizeCache and
org.eclipse.ui.internal.layout.LayoutCache may be helpful here. They implement a
caching strategy for computeSize that works correctly for wrapping controls
(this won't solve the wrapping problem, but it help make the solution efficient).

Comment 13 Steve Northover CLA 2004-04-12 15:30:07 EDT
The plan is to revisit layout issues in SWT post 3.0.  There are a number of 
outstanding problems of which wrapping is just one.
Comment 14 Steve Northover CLA 2004-04-12 15:35:53 EDT
>> Even for Shells, this workaround should not
>> be used if the initial size of the Shell is
>> being computed from its controls (as described
>> in bug 45467) -- for example, you should not
>> use the workaround if you

Stefan, not sure what this means.  Any control that can wrap should be given 
an initial size to avoid a default preferred size that is too large.  The 
preferred size of a controls that *can* wrap is its size without wrapping.
Comment 15 Steve Northover CLA 2004-04-12 15:40:29 EDT
*** Bug 45467 has been marked as a duplicate of this bug. ***
Comment 16 Steve Northover CLA 2004-04-12 15:41:33 EDT
*** Bug 45475 has been marked as a duplicate of this bug. ***
Comment 17 Steve Northover CLA 2004-04-12 15:43:45 EDT
*** Bug 46112 has been marked as a duplicate of this bug. ***
Comment 18 Stefan Xenos CLA 2004-08-03 14:14:00 EDT
Re: comment 14:

In other words, the workaround does not help with calls to Shell.pack().

Comment 19 Veronika Irvine CLA 2004-08-31 11:48:10 EDT
Fixed in 3.1 (see I20040831 or later).

The following example demonstrates how to have wrapping text in GridLayout:

public static void main(String[] args) {
	Display display = new Display();
	Shell shell = new Shell(display);
	GridLayout layout = new GridLayout();
	shell.setLayout(layout);
	Label label = new Label(shell, SWT.WRAP);
	final GridData data = new GridData(SWT.FILL, SWT.TOP, true, false, 1, 
1);
	label.setLayoutData(data);
	label.setText("asda sda sdasd asda sda sdada dadads asd adsad as dadsa 
sad sada dsasda sd adsa sasd");
	List list = new List(shell, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
	list.setLayoutData(new GridData(GridData.FILL_BOTH));
	for (int i = 0; i < 100; i++) {
		list.add("asddas "+i);
	}
	shell.open();
	while (!shell.isDisposed()) {
		if (!display.readAndDispatch())
			display.sleep();
	}
	display.dispose();
}
Comment 20 Dani Megert CLA 2007-06-28 09:26:14 EDT
As shown in comment 19 this bug is fixed if grabExcessVerticalSpace is 'false' but as soon as I set this to 'true' the label is cut vertically. I've filed bug 194758  for that case.