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

Bug 356596

Summary: [Forms] GridLayout Bug in combination with Forms
Product: [Eclipse Project] Platform Reporter: Phil F. <phil.m.fischer>
Component: SWTAssignee: Platform-SWT-Inbox <platform-swt-inbox>
Status: CLOSED INVALID QA Contact:
Severity: normal    
Priority: P3 CC: eclipse.felipe, elaskavaia.cdt, phil.m.fischer, psuzzi, remy.suen, sxenos
Version: 3.7.1   
Target Milestone: ---   
Hardware: PC   
OS: Windows 7   
Whiteboard:
Attachments:
Description Flags
The View with correct GridLayout
none
The View with wrong Layout
none
Example project containing a view with wrong layout none

Description Phil F. CLA 2011-09-02 09:38:20 EDT
Build Identifier: 

Hi All,

I am currently facing a layout problem with the GridLayout in Forms. It looks like a bug to me

The following code shows a little example, that works as expected. It creates a View containing a Form with some Widgets:

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.widgets.Form;
import org.eclipse.ui.forms.widgets.Section;

public class SampleView extends ViewPart {

	private FormToolkit toolkit;
	
	@Override
	public void createPartControl(Composite parent) {
		// Get the toolkit
		Display display = parent.getDisplay();
		toolkit = new FormToolkit(display);
		
		// Add the Form as container for all other widgets
		Form form = toolkit.createForm(parent);
		
		// Set a GridLayout with just one Column to the Form
		GridLayout layout = new GridLayout(1, true);
		layout.horizontalSpacing = 2;
		layout.verticalSpacing = 2;
		form.getBody().setLayout(layout);
		
		// Add the sections to the form
		createImageGeneral(form.getBody());
	}
	
	/**
	 * Creates the images's general-information Section
	 * @param parent The parent Composite to which to attach the section
	 */
	private void createImageGeneral(Composite parent) {
		// Create the Section and attach the LayoutData so that the form can
		// place it correctly. The Section is supposed to take all vertical space
		Section section = toolkit.createSection(parent, Section.TITLE_BAR);
		section.setText("Image General IInformations");
		Composite composite = toolkit.createComposite(section);
		section.setClient(composite);
		section.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));
	
		// The client Composite of the section will get a three Column Grid Layout
		final int THREE_COLUMNS = 3;
		composite.setLayout(new GridLayout(THREE_COLUMNS, false));

		// Place the widgets
		Label labelColor = toolkit.createLabel(composite, "Select Color:");
		Text  textColor = toolkit.createText(composite, "OxFFFFFF", SWT.READ_ONLY);
		Button buttonColor = toolkit.createButton(composite, "...", SWT.NONE);

		Label labelReset = toolkit.createLabel(composite, "Reset Data:");
		Button buttonReset = toolkit.createButton(composite, "Reset", SWT.NONE);

		Label labelTrans = toolkit.createLabel(composite, "Color Gradient Order:");
		Text comboTrans = toolkit.createText(composite, "Test");
	
		// Do the Layout
		GridData gridDataBeg = new GridData(GridData.BEGINNING, GridData.CENTER, false, false);
		GridData gridDataEnd = new GridData(GridData.END, GridData.CENTER, false, false);
		GridData gridDataMid = new GridData(GridData.FILL, GridData.CENTER, true, false);
		GridData gridDataSpan2 = new GridData(GridData.FILL, GridData.CENTER, false, false);
		gridDataSpan2.horizontalSpan = 2;
	
		labelTrans.setLayoutData(gridDataBeg);
		comboTrans.setLayoutData(gridDataSpan2);
		
		labelColor.setLayoutData(gridDataBeg);
		textColor.setLayoutData(gridDataMid);
		buttonColor.setLayoutData(gridDataEnd);
		
		labelReset.setLayoutData(gridDataBeg);
		buttonReset.setLayoutData(gridDataSpan2);
	}

	@Override
	public void setFocus() {
	}
}

This code comes up with a correct layout of the View as you can see in the attached image. Changing the following lines of code, will result in a wrong layout of the View as shown in the second picture:

Label labelTrans = toolkit.createLabel(composite, "Color Gradient Order:");
		Text comboTrans = toolkit.createText(composite, "Test");

		Label labelReset = toolkit.createLabel(composite, "Reset Data:");
		Button buttonReset = toolkit.createButton(composite, "Reset", SWT.NONE);



Reproducible: Always

Steps to Reproduce:
See Details.
Comment 1 Phil F. CLA 2011-09-02 09:40:10 EDT
Created attachment 202671 [details]
The View with correct GridLayout
Comment 2 Phil F. CLA 2011-09-02 09:40:54 EDT
Created attachment 202672 [details]
The View with wrong Layout
Comment 3 Felipe Heidrich CLA 2011-09-02 10:43:32 EDT
I don't think I understand the bug, what is wrong ?


note that the order you create the controls does matters.
Comment 4 Phil F. CLA 2011-09-04 14:20:22 EDT
(In reply to comment #3)
> I don't think I understand the bug, what is wrong ?
> 
> 
> note that the order you create the controls does matters.

Well, in my opinion the layout should account the sizes of the contained text in the left hand labels in the form. Otherwise you cannot abstract the layout from the content. As you can see, that in the picture "wrong layout", some of the texts in the labels get truncated and unreadable to the user. Just changing the order of the controls handles the label sizes correctly.
Comment 5 Felipe Heidrich CLA 2011-09-08 10:43:45 EDT
Sorry, I didn't notice that.

my guess: one of these calls to create widget is causing a layout to happen.
could you add a resize listener to the parent and from the handleEvent() print a stackdump ?
 
parent.addListener(SWT.Resize, new Listener() {
  public void handleEvent(Event event) {
    Thread.dumpStack();
  }
});

Does it get call at different times when the code is changed ?
Comment 6 Phil F. CLA 2011-09-12 03:25:37 EDT
Created attachment 203132 [details]
Example project containing a view with wrong layout
Comment 7 Phil F. CLA 2011-09-12 03:32:52 EDT
No worries,

Maybe i was not precise enough with my description. Anyway, i added an example project and placed the listener as you requested. Attached is the stack dump:

java.lang.Exception: Stack trace
	at java.lang.Thread.dumpStack(Unknown Source)
	at de.bug.grid.layout.views.SampleView$1.handleEvent(SampleView.java:73)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1077)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1058)
	at org.eclipse.swt.widgets.Control.sendResize(Control.java:2931)
	at org.eclipse.swt.widgets.Composite.sendResize(Composite.java:976)
	at org.eclipse.swt.widgets.Composite.setBounds(Composite.java:1025)
	at org.eclipse.swt.widgets.Control.setBounds(Control.java:3085)
	at org.eclipse.swt.widgets.Control.setBounds(Control.java:3081)
	at org.eclipse.ui.forms.widgets.SizeCache.setBounds(SizeCache.java:508)
	at org.eclipse.ui.forms.widgets.ExpandableComposite$ExpandableLayout.layout(ExpandableComposite.java:388)
	at org.eclipse.swt.widgets.Composite.updateLayout(Composite.java:1263)
	at org.eclipse.swt.widgets.Composite.WM_SIZE(Composite.java:1673)
	at org.eclipse.swt.widgets.Canvas.WM_SIZE(Canvas.java:454)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:4603)
	at org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:341)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:4972)
	at org.eclipse.swt.internal.win32.OS.DefWindowProcW(Native Method)
	at org.eclipse.swt.internal.win32.OS.DefWindowProc(OS.java:2525)
	at org.eclipse.swt.widgets.Scrollable.callWindowProc(Scrollable.java:80)
	at org.eclipse.swt.widgets.Control.WM_WINDOWPOSCHANGED(Control.java:5408)
	at org.eclipse.swt.widgets.Canvas.WM_WINDOWPOSCHANGED(Canvas.java:460)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:4616)
	at org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:341)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:4972)
	at org.eclipse.swt.internal.win32.OS.SetWindowPos(Native Method)
	at org.eclipse.swt.widgets.Widget.SetWindowPos(Widget.java:1457)
	at org.eclipse.swt.widgets.Control.setBounds(Control.java:3124)
	at org.eclipse.swt.widgets.Composite.setBounds(Composite.java:1019)
	at org.eclipse.swt.widgets.Control.setBounds(Control.java:3085)
	at org.eclipse.swt.widgets.Control.setBounds(Control.java:3081)
	at org.eclipse.swt.layout.GridLayout.layout(GridLayout.java:690)
	at org.eclipse.swt.layout.GridLayout.layout(GridLayout.java:194)
	at org.eclipse.swt.widgets.Composite.updateLayout(Composite.java:1263)
	at org.eclipse.swt.widgets.Composite.WM_SIZE(Composite.java:1673)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:4603)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:4972)
	at org.eclipse.swt.internal.win32.OS.DefWindowProcW(Native Method)
	at org.eclipse.swt.internal.win32.OS.DefWindowProc(OS.java:2525)
	at org.eclipse.swt.widgets.Scrollable.callWindowProc(Scrollable.java:80)
	at org.eclipse.swt.widgets.Control.WM_WINDOWPOSCHANGED(Control.java:5408)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:4616)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:4972)
	at org.eclipse.swt.internal.win32.OS.SetWindowPos(Native Method)
	at org.eclipse.swt.widgets.Widget.SetWindowPos(Widget.java:1457)
	at org.eclipse.swt.widgets.Control.forceResize(Control.java:1121)
	at org.eclipse.swt.widgets.Control.getSize(Control.java:1575)
	at org.eclipse.ui.forms.widgets.SizeCache.layoutIfNecessary(SizeCache.java:524)
	at org.eclipse.ui.forms.widgets.SizeCache.setBounds(SizeCache.java:511)
	at org.eclipse.ui.forms.widgets.Form$FormLayout.layout(Form.java:159)
	at org.eclipse.swt.widgets.Composite.updateLayout(Composite.java:1263)
	at org.eclipse.swt.widgets.Composite.WM_SIZE(Composite.java:1673)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:4603)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:4972)
	at org.eclipse.swt.internal.win32.OS.DefWindowProcW(Native Method)
	at org.eclipse.swt.internal.win32.OS.DefWindowProc(OS.java:2525)
	at org.eclipse.swt.widgets.Scrollable.callWindowProc(Scrollable.java:80)
	at org.eclipse.swt.widgets.Control.WM_WINDOWPOSCHANGED(Control.java:5408)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:4616)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:4972)
	at org.eclipse.swt.internal.win32.OS.SetWindowPos(Native Method)
	at org.eclipse.swt.widgets.Widget.SetWindowPos(Widget.java:1457)
	at org.eclipse.swt.widgets.Control.setBounds(Control.java:3124)
	at org.eclipse.swt.widgets.Composite.setBounds(Composite.java:1019)
	at org.eclipse.swt.widgets.Control.setBounds(Control.java:3085)
	at org.eclipse.swt.widgets.Control.setBounds(Control.java:3081)
	at org.eclipse.swt.layout.FillLayout.layout(FillLayout.java:201)
	at org.eclipse.swt.widgets.Composite.updateLayout(Composite.java:1263)
	at org.eclipse.swt.widgets.Composite.WM_SIZE(Composite.java:1673)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:4603)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:4972)
	at org.eclipse.swt.internal.win32.OS.DefWindowProcW(Native Method)
	at org.eclipse.swt.internal.win32.OS.DefWindowProc(OS.java:2525)
	at org.eclipse.swt.widgets.Scrollable.callWindowProc(Scrollable.java:80)
	at org.eclipse.swt.widgets.Control.WM_WINDOWPOSCHANGED(Control.java:5408)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:4616)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:4972)
	at org.eclipse.swt.internal.win32.OS.SetWindowPos(Native Method)
	at org.eclipse.swt.widgets.Widget.SetWindowPos(Widget.java:1457)
	at org.eclipse.swt.widgets.Control.setBounds(Control.java:3124)
	at org.eclipse.swt.widgets.Composite.setBounds(Composite.java:1019)
	at org.eclipse.swt.widgets.Control.setBounds(Control.java:3085)
	at org.eclipse.swt.widgets.Control.setBounds(Control.java:3081)
	at org.eclipse.swt.layout.FillLayout.layout(FillLayout.java:201)
	at org.eclipse.swt.widgets.Composite.updateLayout(Composite.java:1263)
	at org.eclipse.swt.widgets.Composite.WM_SIZE(Composite.java:1673)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:4603)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:4972)
	at org.eclipse.swt.internal.win32.OS.DefWindowProcW(Native Method)
	at org.eclipse.swt.internal.win32.OS.DefWindowProc(OS.java:2525)
	at org.eclipse.swt.widgets.Scrollable.callWindowProc(Scrollable.java:80)
	at org.eclipse.swt.widgets.Control.WM_WINDOWPOSCHANGED(Control.java:5408)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:4616)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:4972)
	at org.eclipse.swt.internal.win32.OS.SetWindowPos(Native Method)
	at org.eclipse.swt.widgets.Widget.SetWindowPos(Widget.java:1457)
	at org.eclipse.swt.widgets.Control.setBounds(Control.java:3124)
	at org.eclipse.swt.widgets.Composite.setBounds(Composite.java:1019)
	at org.eclipse.swt.widgets.Control.setBounds(Control.java:3085)
	at org.eclipse.swt.widgets.Control.setBounds(Control.java:3081)
	at org.eclipse.swt.widgets.Control.setBounds(Control.java:3148)
	at org.eclipse.ui.internal.LayoutPart.setBounds(LayoutPart.java:300)
	at org.eclipse.ui.internal.presentations.PresentablePart.setBounds(PresentablePart.java:170)
	at org.eclipse.ui.internal.presentations.util.PresentablePartFolder.layoutContent(PresentablePartFolder.java:131)
	at org.eclipse.ui.internal.presentations.util.PresentablePartFolder.layout(PresentablePartFolder.java:412)
	at org.eclipse.ui.internal.presentations.util.PresentablePartFolder.setBounds(PresentablePartFolder.java:260)
	at org.eclipse.ui.internal.presentations.util.TabbedStackPresentation.setBounds(TabbedStackPresentation.java:231)
	at org.eclipse.ui.internal.PartStack.setBounds(PartStack.java:1187)
	at org.eclipse.ui.internal.LayoutTree.doSetBounds(LayoutTree.java:547)
	at org.eclipse.ui.internal.LayoutTree.setBounds(LayoutTree.java:538)
	at org.eclipse.ui.internal.LayoutTreeNode.doSetBounds(LayoutTreeNode.java:536)
	at org.eclipse.ui.internal.LayoutTree.setBounds(LayoutTree.java:538)
	at org.eclipse.ui.internal.LayoutTreeNode.doSetBounds(LayoutTreeNode.java:500)
	at org.eclipse.ui.internal.LayoutTree.setBounds(LayoutTree.java:538)
	at org.eclipse.ui.internal.LayoutTreeNode.doSetBounds(LayoutTreeNode.java:536)
	at org.eclipse.ui.internal.LayoutTree.setBounds(LayoutTree.java:538)
	at org.eclipse.ui.internal.LayoutTreeNode.doSetBounds(LayoutTreeNode.java:537)
	at org.eclipse.ui.internal.LayoutTree.setBounds(LayoutTree.java:538)
	at org.eclipse.ui.internal.LayoutTreeNode.doSetBounds(LayoutTreeNode.java:505)
	at org.eclipse.ui.internal.LayoutTree.setBounds(LayoutTree.java:538)
	at org.eclipse.ui.internal.PartSashContainer.resizeSashes(PartSashContainer.java:811)
	at org.eclipse.ui.internal.PartSashContainer.setActive(PartSashContainer.java:529)
	at org.eclipse.ui.internal.PerspectiveHelper.activate(PerspectiveHelper.java:273)
	at org.eclipse.ui.internal.Perspective.onActivate(Perspective.java:981)
	at org.eclipse.ui.internal.WorkbenchPage.onActivate(WorkbenchPage.java:2714)
	at org.eclipse.ui.internal.WorkbenchWindow$27.run(WorkbenchWindow.java:3023)
	at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
	at org.eclipse.ui.internal.WorkbenchWindow.setActivePage(WorkbenchWindow.java:3004)
	at org.eclipse.ui.internal.WorkbenchWindow$20.runWithException(WorkbenchWindow.java:2290)
	at org.eclipse.ui.internal.StartupThreading$StartupRunnable.run(StartupThreading.java:31)
	at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
	at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
	at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:4140)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3757)
	at org.eclipse.ui.application.WorkbenchAdvisor.openWindows(WorkbenchAdvisor.java:803)
	at org.eclipse.ui.internal.Workbench$33.runWithException(Workbench.java:1595)
	at org.eclipse.ui.internal.StartupThreading$StartupRunnable.run(StartupThreading.java:31)
	at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
	at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
	at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:4140)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3757)
	at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2604)
	at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2494)
	at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:674)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:667)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1410)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1386)

Cheers Phil
Comment 8 Stefan Xenos CLA 2016-01-28 11:50:50 EST

*** This bug has been marked as a duplicate of bug 196692 ***
Comment 9 Elena Laskavaia CLA 2016-01-29 16:27:14 EST
(In reply to Stefan Xenos from comment #8)
> 
> *** This bug has been marked as a duplicate of bug 196692 ***

This bug 196692 is invalid. It uses same layoutData objects set on multiple controls,
if I fix that in test case it works as expected.

I.e. this is not a valid usage of GridData objects

		labelTrans.setLayoutData(gridDataBeg);
		
		labelColor.setLayoutData(gridDataBeg);
		
		labelReset.setLayoutData(gridDataBeg);

Documentation:

NOTE: Do not reuse GridData objects. Every control in a Composite that is managed by a GridLayout must have a unique GridData object.
Comment 10 Stefan Xenos CLA 2016-01-29 22:27:47 EST
Agreed. Thanks for looking at it, Elena.