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

Bug 373191

Summary: Closing Viewpart containing a Zest GraphViewer showing Scrollbars throws SWTException: Widget is disposed
Product: [Tools] GEF Reporter: <h1055071>
Component: GEF-Legacy ZestAssignee: gef-inbox <gef-inbox>
Status: RESOLVED FIXED QA Contact:
Severity: major    
Priority: P3 CC: steeg
Version: 3.7.1   
Target Milestone: ---   
Hardware: PC   
OS: Windows 7   
Whiteboard:

Description CLA 2012-03-03 16:33:01 EST
I have a Viewpart that contains a Zest GraphViewer. It has a IGraphContentProvider and a LabelProvider. It has a SpringLayoutAlgorithm.

This all works fine except when the GraphViewer show either a horizontal or vertical scrollbar. When I close the Viewpart it throws an SWTException:

!ENTRY org.eclipse.ui 4 0 2012-03-03 20:12:55.302
!MESSAGE Unhandled event loop exception
!STACK 0
org.eclipse.swt.SWTException: Failed to execute runnable (org.eclipse.swt.SWTException: Widget is disposed)
	at org.eclipse.swt.SWT.error(SWT.java:4282)
	at org.eclipse.swt.SWT.error(SWT.java:4197)
	at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:138)
	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.runEventLoop(Workbench.java:2701)
	at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2665)
	at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2499)
	at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:679)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:668)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
	at uk.ac.bolton.archimate.editor.Application.start(Application.java:59)
	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(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	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)
Caused by: org.eclipse.swt.SWTException: Widget is disposed
	at org.eclipse.swt.SWT.error(SWT.java:4282)
	at org.eclipse.swt.SWT.error(SWT.java:4197)
	at org.eclipse.swt.SWT.error(SWT.java:4168)
	at org.eclipse.swt.widgets.Widget.error(Widget.java:468)
	at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:340)
	at org.eclipse.swt.widgets.Scrollable.getHorizontalBar(Scrollable.java:197)
	at org.eclipse.draw2d.FigureCanvas$1.propertyChange(FigureCanvas.java:90)
	at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:339)
	at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:276)
	at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:297)
	at org.eclipse.draw2d.DefaultRangeModel.firePropertyChange(DefaultRangeModel.java:63)
	at org.eclipse.draw2d.DefaultRangeModel.setAll(DefaultRangeModel.java:122)
	at org.eclipse.draw2d.FreeformViewport.readjustScrollBars(FreeformViewport.java:76)
	at org.eclipse.draw2d.Viewport.validate(Viewport.java:381)
	at org.eclipse.draw2d.Figure.validate(Figure.java:1898)
	at org.eclipse.draw2d.DeferredUpdateManager.performValidation(DeferredUpdateManager.java:218)
	at org.eclipse.draw2d.Animation.doRun(Animation.java:118)
	at org.eclipse.draw2d.Animation.run(Animation.java:278)
	at org.eclipse.zest.core.widgets.Graph.applyLayoutInternal(Graph.java:1134)
	at org.eclipse.zest.core.widgets.Graph.access$6(Graph.java:1090)
	at org.eclipse.zest.core.widgets.Graph$6.run(Graph.java:421)
	at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
	at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
Comment 1 CLA 2012-03-03 16:40:11 EST
The widget that is complaining of being disposed is the Graph control.

The strange thing is that if I do not use a Content Provider and instead add GraphNodes and Connections manually (like the Zest snippet examples) the exception does not occur.

Additionally, if I dispose of the Graph control explicitly in the dispose() method of my ViewPart the exception does not occur.

Interestingly, setting a breakpoint for when the "Widget is disposed" error occurs shows that the Graph control has not really been disposed but its display field is null causing checkWidget() to throw the error.
Comment 2 CLA 2012-03-03 17:28:20 EST
I guess you could boil it down to org.eclipse.zest.core.widgets.Graph#dispose() is not being invoked when the Viewpart is closed. This gives rise to the problem.
Comment 3 Fabian Steeg CLA 2012-03-09 20:08:43 EST
Thanks for the bug. I can't reproduce this in master on Mac. Could you try it with the latest nightly build (from the update site below), and attach another stack trace if you get the same error?

https://hudson.eclipse.org/hudson/job/gef-zest-nightly/lastSuccessfulBuild/artifact/targetPlatform/
Comment 4 CLA 2012-03-24 14:23:15 EDT
I've tried this on the latest nightly build and so far I've not seen this crash.

However, org.eclipse.zest.core.widgets.Graph#dispose() never gets called by any code. Is this correct? I have a GraphViewer in an Eclipse ViewPart, but when I close the Viewpart containing the GraphViewer I would expect the Graph Control to be disposed by its parent?
Comment 5 Fabian Steeg CLA 2012-03-25 17:47:51 EDT
Yes, that doesn't seem right. We have tests that check if the graph control is disposed when the parent is disposed, but indeed Graph#dispose was not actually called. I added a DisposeListener to the Graph constructor in Zest 1.x and 2.x (which is described in the Javadoc of Widget#dispose), and added another test:

http://git.eclipse.org/c/gef/org.eclipse.zest.git/commit/?id=f4efb390782df744ba