Bug 247180 - SelectEditPartTracker NullPointerException in handleButtonUp
Summary: SelectEditPartTracker NullPointerException in handleButtonUp
Status: NEW
Alias: None
Product: GEF
Classification: Tools
Component: GEF-Legacy GEF (MVC) (show other bugs)
Version: 3.3.1   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: gef-inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-09-12 12:09 EDT by Lisete CLA
Modified: 2008-10-23 08:12 EDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Lisete CLA 2008-09-12 12:09:37 EDT
Build ID: M20071023-1652

Steps To Reproduce:
1. Make a multiple selection (select several nodes) in your GEF editor
2. Click in one of the selected nodes
3. My application builds a ProgressBar to report the progress spent in a private task
4. NullPointerException is thrown


More information:
I get a NullPointerException in the method handleButtonUp, because getCurrentViewer() is null. I want to give the user some feedback about a task that's being performed, so to report the progress and allow the cancellation, I've used a ProgressMonitorDialog. This is the situation: when the user clicks a node in my editor I return some info about that node. This exception only happens when, after I select several nodes, I click in one of them... When I click in only one (without previous multiple selection), the progress bar and all the information are displayed.

I believe the problem would be solved with a correction provided in 'org.eclipse.gef.tools.SelectEditPartTracker' class. There is 'null' check missing.

Method 'handleButtonUp(int button)': 

protected boolean handleButtonUp(int button) {
	if (isInState(STATE_DRAG)) {
		performSelection();
		if (getFlag(FLAG_ENABLE_DIRECT_EDIT))
			performDirectEdit();
		if (button == 1 && getSourceEditPart().getSelected() != EditPart.SELECTED_NONE)
			getCurrentViewer().reveal(getSourceEditPart());  <-- before this line there should be check: 'getCurrentViewer()!=null'
		setState(STATE_TERMINAL);
		return true;
	}
	return false;
}
Comment 1 Randy Hudson CLA 2008-09-12 14:39:49 EDT
It's hard to guess what is happening without a stack trace, but it sounds like you've caused focus lost to occur while the mouse up event is still being processed.

This sounds like a simple fix in GEF, but how defensive would we have to make the code in GEF for things like this? Do you really want to disable the canvas while the user is clicking on it? I suspect that is what has happened here.

It sounds like you might benefit from something like a postSelection event, which doesn't exist yet in GEF, but does exist in some of the jface viewers.  You could wait to do your job "later" by using an asyncExec when you see that selection has changed, so that the buttonUp has time to finish.

Can you attach a stack trace and/or more info about what you mean by "builds a ProgressBar"?
Comment 2 Lisete CLA 2008-10-22 09:16:04 EDT
I'm sorry for my late reply.
Given the request for more information, here they are (I hope this helps):

The exception is thrown from GEF plugin. The variable "currentViewer" is set to null in GEF. Stack trace:

DragEditPartsTracker(SelectEditPartTracker).handleButtonUp(int) line: 115 > here getCurrentViewer() is null
DragEditPartsTracker.handleButtonUp(int) line: 336	
DragEditPartsTracker(AbstractTool).mouseUp(MouseEvent, EditPartViewer) line: 1053	
PanningSelectionTool(SelectionTool).mouseUp(MouseEvent, EditPartViewer) line: 544	
DefaultEditDomain(EditDomain).mouseUp(MouseEvent, EditPartViewer) line: 259	
DomainEventDispatcher.dispatchMouseReleased(MouseEvent) line: 374	
LightweightSystem$EventHandler.mouseUp(MouseEvent) line: 538	
TypedListener.handleEvent(Event) line: 206	
EventTable.sendEvent(Event) line: 66	
FigureCanvas(Widget).sendEvent(Event) line: 938	
Display.runDeferredEvents() line: 3682	
Display.readAndDispatch() line: 3293	
Workbench.runEventLoop(Window$IExceptionHandler, Display) line: 2389	
Workbench.runUI() line: 2353	
Workbench.access$4(Workbench) line: 2219	
Workbench$4.run() line: 466	
(…………)
DragEditPartsTracker(AbstractTool).setViewer(EditPartViewer) line: 1325 > here currentViewer is set to null
DragEditPartsTracker(AbstractTool).deactivate() line: 363	
DragEditPartsTracker(TargetingTool).deactivate() line: 81	
DragEditPartsTracker.deactivate() line: 207	
PanningSelectionTool(SelectionTool).setDragTracker(DragTracker) line: 583	
PanningSelectionTool(SelectionTool).handleFocusLost() line: 240	
PanningSelectionTool.handleFocusLost() line: 139	
PanningSelectionTool(AbstractTool).focusLost(FocusEvent, EditPartViewer) line: 423	
DefaultEditDomain(EditDomain).focusLost(FocusEvent, EditPartViewer) line: 95	
DomainEventDispatcher.dispatchFocusLost(FocusEvent) line: 232	
LightweightSystem$EventHandler.focusLost(FocusEvent) line: 353	
TypedListener.handleEvent(Event) line: 136	
EventTable.sendEvent(Event) line: 66	
FigureCanvas(Widget).sendEvent(Event) line: 938	
FigureCanvas(Widget).sendEvent(int, Event, boolean) line: 962	
FigureCanvas(Widget).sendEvent(int) line: 943	
FigureCanvas(Control).sendFocusEvent(int) line: 2352	
FigureCanvas(Widget).wmKillFocus(int, int, int) line: 1681	
FigureCanvas(Control).WM_KILLFOCUS(int, int) line: 4000	
FigureCanvas(Canvas).WM_KILLFOCUS(int, int) line: 337	
FigureCanvas(Control).windowProc(int, int, int, int) line: 3703	
FigureCanvas(Canvas).windowProc(int, int, int, int) line: 291	
Display.windowProc(int, int, int, int) line: 4364	
OS.BringWindowToTop(int) line: not available [native method]	
Shell(Decorations).bringToTop() line: 227	
Shell.open() line: 1068	
ProgressMonitorDialog(Window).open() line: 792	
ProgressMonitorDialog.open() line: 664	
ProgressMonitorDialog.aboutToRun() line: 567	
ProgressMonitorDialog.run(boolean, boolean, IRunnableWithProgress) line: 492	
……..calculate()……. line: 47 (This code is mine)	
	

And this is the “my” exception:

Caused by: java.lang.NullPointerException
	at org.eclipse.gef.tools.SelectEditPartTracker.handleButtonUp(SelectEditPartTracker.java:115)
	at org.eclipse.gef.tools.DragEditPartsTracker.handleButtonUp(DragEditPartsTracker.java:336)
	at org.eclipse.gef.tools.AbstractTool.mouseUp(AbstractTool.java:1053)
	at org.eclipse.gef.tools.SelectionTool.mouseUp(SelectionTool.java:544)
	at org.eclipse.gef.EditDomain.mouseUp(EditDomain.java:259)
	at org.eclipse.gef.ui.parts.DomainEventDispatcher.dispatchMouseReleased(DomainEventDispatcher.java:374)
	at org.eclipse.draw2d.LightweightSystem$EventHandler.mouseUp(LightweightSystem.java:538)
	at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:206)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:66)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:938)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3682)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3293)
	at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2389)
Comment 3 Randy Hudson CLA 2008-10-22 12:28:33 EDT
I'm not sure I follow... is that one stack trace? Is mouseUp dispatched by SWT twice? Why does setViewer(null) cause the event loop to run? What caused the progress monitor dialog to open? Can you provide the whole trace, or at least the parts of it that involve eclipse code?  The log file might get truncated, so you'll probably have to catch the exception in the debugger.
Comment 4 Lisete CLA 2008-10-23 08:12:08 EDT
Hi, Randy.
Indeed the log file didn't help much so I decided to give you a stack trace truncated (obtained with the debugger's help). I thought this would help...

About your questions:
Is mouseUp dispatched by SWT twice? 
--> Yes. Once when I select several nodes and after when I "pick" one in the group that I've selected before.

Why does setViewer(null) cause the event loop to run? 
--> It doesn't... It seems that way because I've truncated the stack. Sorry...
Once I select several nodes, currentViewer is set to null (setViewer(null)). Then inside that selection, I select one node. The progress monitor dialog is opened and the exception is caught.

What caused the progress monitor dialog to open? 
--> I have in my code this method:
private void calculateWithProgressBar() {
   ProgressMonitorDialog pd = new ProgressMonitorDialog(GuiHelper.getShell());
   try {
        pd.run(true, true, new aRunnable(node));
       }
   catch (Exception e) {
       }
}
where aRunnable implements IRunnableWithProgress (which belongs to the package org.eclipse.jface.operation).


I don't know if the stack below helps you... It's the stack I've obtained with the debugger to catch the null exception (this isn't complete... after this, the exception is handled by the code inside my project): 

at org.eclipse.ui.internal.ExceptionHandler.handleException(ExceptionHandler.java:62)
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2393)
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2353)
at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2219)
at org.eclipse.ui.internal.Workbench$4.run(Workbench.java:466)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:289)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:461)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
at de.siemens.spt.application.Application.run(Application.java:45)
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.internal.app.EclipseAppContainer.callMethod(EclipseAppContainer.java:572)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:171)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:106)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:76)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:363)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:176)
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:508)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:447)
at org.eclipse.equinox.launcher.Main.run(Main.java:1173)
at org.eclipse.equinox.launcher.Main.main(Main.java:1148)