Bug 562315 - Wrong composite height computed for ExpandableComposite with text client
Summary: Wrong composite height computed for ExpandableComposite with text client
Status: NEW
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 4.16   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Platform-SWT-Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-04-20 07:45 EDT by Simeon Andreev CLA
Modified: 2020-05-13 10:55 EDT (History)
3 users (show)

See Also:


Attachments
Screenshot showing the problem with the snippet from the description. Compare left and right side of the shell. (7.85 KB, image/png)
2020-04-20 07:45 EDT, Simeon Andreev CLA
no flags Details
Video showing the same problematic behaviour but when resizing. (226.40 KB, video/mp4)
2020-04-21 03:08 EDT, Simeon Andreev CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Simeon Andreev CLA 2020-04-20 07:45:36 EDT
Created attachment 282515 [details]
Screenshot showing the problem with the snippet from the description. Compare left and right side of the shell.

To reproduce, execute the following snippet:

package test;

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.forms.widgets.ExpandableComposite;

public class TestExtensibleComposite {

	public static void main(String[] args) {
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setSize(600, 300);
		shell.setLayout(new FillLayout());

		{
			ExpandableComposite parent = new ExpandableComposite(shell, SWT.BORDER);
			parent.setLayout(new GridLayout());
			parent.setText("ExpandableComposite with text client");
	
			Composite child = new Composite(parent, SWT.BORDER);
			parent.setTextClient(child);
			
			parent.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
		}
		{
			ExpandableComposite parent = new ExpandableComposite(shell, SWT.BORDER);
			parent.setLayout(new FillLayout());
			parent.setText("ExpandableComposite without text client");
			parent.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
		}

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

(MANIFEST.MF should require bundles org.eclipse.jface and org.eclipse.ui.forms)
Comment 1 Simeon Andreev CLA 2020-04-20 08:08:39 EDT
In our product, the code is more complicated than the snippet from the description; I'm working on reproducing it more accurately. We have a form (ExpandableComposite) with a toolbar manager in the text client. Adding widgets via ControlContribution to the toolbar results in an abnormally large header, as seen in the attached screenshot.
Comment 2 Simeon Andreev CLA 2020-04-21 03:08:08 EDT
Created attachment 282523 [details]
Video showing the same problematic behaviour but when resizing.

This snippet is closer to what we have in an editor from our product, I think it should be used instead of the one from the description:

package test;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ControlContribution;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.Section;

public class TestExpandableComposite {

	public static void main(String[] args) {
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setSize(600, 400);
		shell.setLayout(new FillLayout());
		Composite composite = new Composite(shell, SWT.NONE);
		composite.setLayout(new FillLayout(SWT.VERTICAL));

		Section section = new Section(composite, ExpandableComposite.TITLE_BAR);
		section.setLayout(new GridLayout(3, false));
		section.setText("Section long name");

		Composite client = new Composite(section, SWT.BORDER);
		client.setLayout(new GridLayout());
		client.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		Text text = new Text(client, SWT.BORDER);
		text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		text.setText("Section text");
		text.setEditable(false);
		section.setClient(client);

		ToolBarManager manager = new ToolBarManager(SWT.BORDER);
		ToolBar toolbar = manager.createControl(section);
		Cursor handCursor = section.getDisplay().getSystemCursor(SWT.CURSOR_HAND);
		toolbar.setCursor(handCursor);
		manager.add(new ControlContribution("some id") {
			@Override
			protected Control createControl(Composite parent) {
				Composite child = new Composite(parent, SWT.BORDER);
				child.setLayout(new GridLayout(2, true));
				child.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
				Button b1 = new Button(child, SWT.RADIO | SWT.BORDER);
				b1.setText("long name 1");
				b1.setLayoutData(new GridData(110, 20));
				b1.setSelection(true);
				Button b2 = new Button(child, SWT.RADIO | SWT.BORDER);
				b2.setText("long name 2");
				b2.setLayoutData(new GridData(110, 20));
				return child;
			}
		});
		manager.add(new Action() {});
		manager.add(new Action() {});
		manager.add(new Action() {});
		manager.update(true);
		section.setTextClient(toolbar);

		Label label = new Label(composite, SWT.BORDER);
		label.setText("outside of section label text");

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

I see the behaviour when forcefully resizing the shell to cause wrapping. In our case, this is not necessary. Maybe our editor is shrunk and then resized by some platform UI, or maybe there are other ways to run into the problem.

I do not see the problem with this change:

diff --git a/bundles/org.eclipse.ui.forms/src/org/eclipse/ui/forms/widgets/ExpandableComposite.java b/bundles/org.eclipse.ui.forms/src/org/eclipse/ui/forms/widgets/ExpandableComposite.java                                                 
index 8edbcb3453..b0b69300bb 100644                                                                                                                                                                                                          
--- a/bundles/org.eclipse.ui.forms/src/org/eclipse/ui/forms/widgets/ExpandableComposite.java                                                                                                                                                 
+++ b/bundles/org.eclipse.ui.forms/src/org/eclipse/ui/forms/widgets/ExpandableComposite.java                                                                                                                                                 
@@ -631,7 +631,7 @@ public class ExpandableComposite extends Canvas {                                                                                                                                                                        
                        }
                }
                if ((expansionStyle & FOCUS_TITLE) != 0) {
-                       Hyperlink link = new Hyperlink(this, SWT.WRAP);
+                       Hyperlink link = new Hyperlink(this, SWT.NONE);
                        link.addHyperlinkListener(new HyperlinkAdapter() {
                                @Override
                                public void linkActivated(HyperlinkEvent e) {
@@ -640,7 +640,7 @@ public class ExpandableComposite extends Canvas {
                        });
                        textLabel = link;
                } else if ((expansionStyle & NO_TITLE) == 0) {
-                       final Label label = new Label(this, SWT.WRAP);
+                       final Label label = new Label(this, SWT.NONE);
                        if (!isFixedStyle()) {
                                label.setCursor(FormsResources.getHandCursor());
                                Listener listener = e -> {

I observe the same in our product, removing the SWT.WRAP flag prevents the problem from occurring.

Also note that after increasing the shell width to the original size, the toolbar is still with the wrong dimensions, only its clipped. In our product its not clipped, bloats the ExpandableComposite instead. IMO both behaviours are bad. Removing the ControlContribution from the ToolBarManager *mostly* hides the problem.

In the snippet above, I expect that increasing the shell size would lead to a normal ExpandableComposite size and a normal size for its text client child.
Comment 3 Alexander Kurtakov CLA 2020-05-13 10:35:19 EDT
So the issue happens on Gtk only? Not on win/mac? I want to be sure that the problem is in swt and not in ui.forms.
Comment 4 Simeon Andreev CLA 2020-05-13 10:55:47 EDT
At least with the snippet from comment 2, I don't see the issue with Eclipse 4.15 M1 on Windows 10. Unfortunately our product runs only on Linux, so no way of validating whether the actual code we have has problems on Windows 10 (without spending a lot of effort in a better snippet).

In our product we replaced the problematic children of ToolbarManager with actual buttons, to avoid the problem.