Bug 157999 - [Tool] Tools need Esc key handler override
Summary: [Tool] Tools need Esc key handler override
Status: NEW
Alias: None
Product: GEF
Classification: Tools
Component: GEF-Legacy GEF (MVC) (show other bugs)
Version: 3.1.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: 2006-09-20 10:39 EDT by Scott Barkley CLA
Modified: 2010-11-04 06:39 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Scott Barkley CLA 2006-09-20 10:39:31 EDT
With a GEF application displayed in an RCP ViewPart (not an EditorPart) and the view open in detached mode (torn away from the rest of the workbench window), pressing the Esc key dismisses the view.  This is normal behavior for a view, but inappropriate *when the user is in the middle of a create operation from the GEF palette or drag-and-drop move in a GEF application*.  In these cases, the Esc key should abort the operation in progress (as it does when the view part is attached to the workbench window), but not dismiss the view.

I attempted to subclass ScrollingGraphicalViewer and FigureCanvas to include an override, but the createControl(Composite) method on ScrollingGraphicalViewer is declared final, so I can't have a subclass of the one make a subclass of the other.

A stack trace captured from the ViewPart's dispose method is included for reference.  The method FigureCanvas.translateTraversal(MSG) is in the stack prior to the shell being closed, so it should be possible to prevent the shell from being closed at this point.  

Possible solutions to explore include: (a) modify FigureCanvas to override Control.translateTraversal(MSG) to ignore the Esc key when such an operation is in progress (b) modify FigureCanvas to allow application developers to hook in an event override function that can decide how to handle certain events, and override to call that function from translateTraversal(MSG) (c) override Control.translateTraversal(MSG) to simply ignore the Esc key.

Thread [main] (Suspended (breakpoint at line 281 in MyGEFView))
	MyGEFView.dispose() line: 281
	ViewReference(WorkbenchPartReference).doDisposePart() line: 659
	ViewReference.doDisposePart() line: 94
	ViewReference(WorkbenchPartReference).dispose() line: 628
	WorkbenchPage.disposePart(WorkbenchPartReference) line: 1439
	WorkbenchPage.partRemoved(WorkbenchPartReference) line: 1431
	ViewFactory.releaseView(IViewReference) line: 237
	Perspective.hideView(IViewReference) line: 498
	WorkbenchPage.hideView(IViewReference) line: 2023
	DetachedWindow.handleClose() line: 202
	DetachedWindow.access$0(DetachedWindow) line: 194
	DetachedWindow$1.shellClosed(ShellEvent) line: 65
	ShellPool$2.shellClosed(ShellEvent) line: 67
	TypedListener.handleEvent(Event) line: 159
	EventTable.sendEvent(Event) line: 66
	Shell(Widget).sendEvent(Event) line: 843
	Shell(Widget).sendEvent(int, Event, boolean) line: 867
	Shell(Widget).sendEvent(int, Event) line: 852
	Shell(Decorations).closeWidget() line: 257
	Shell.close() line: 430
	Shell.traverseEscape() line: 1318
	Shell(Control).traverse(Event) line: 2783
***
	FigureCanvas(Control).translateTraversal(MSG) line: 2759
	FigureCanvas(Composite).translateTraversal(MSG) line: 840
***
	Display.translateTraversal(MSG, Control) line: 3577
	Display.filterMessage(MSG) line: 933
	Display.readAndDispatch() line: 2754
	Workbench.runEventLoop(Window$IExceptionHandler, Display) line: 1699
	Workbench.runUI() line: 1663
	Workbench.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 367
	PlatformUI.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 143
	Application.run(Object) line: 18
	PlatformActivator$1.run(Object) line: 226
	EclipseStarter.run(Object) line: 376
	EclipseStarter.run(String[], Runnable) line: 163
	NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
	NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
	DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
	Method.invoke(Object, Object[]) line: 324
	Main.invokeFramework(String[], URL[]) line: 334
	Main.basicRun(String[]) line: 278
	Main.run(String[]) line: 973
	Main.main(String[]) line: 948
Comment 1 Randy Hudson CLA 2006-09-20 10:56:29 EDT
FigureCanvas is a Control.  Add a traverse listener to the control. Set doit = false. The shell will not close. See SWT snippets for more info.

I don't see how behavior could be changed at FigureCanvas. But maybe some of the tools could change. Tools should already be receiving the traversal event, which could be "consumed" (doit=false) if it is ESC. Try extending DragEditPartsTracker and see if you can fix the case for MOVE.
Comment 2 Scott Barkley CLA 2006-09-21 13:17:47 EDT
>> But maybe some of the tools could change.

Following this tip, I ended up overriding PanningSelectionTool (for the drag and drop case) and copying and adding to the internal class PaletteSelectionTool (for the creation case).  These changes are a sufficient band-aid for my case, but the tools in GEF should include similar handling.

Currently, the TargetingTool -> SelectionTool -> PanningSelectionTool and TargetingTool -> SelectionTool -> PaletteSelectionTool hierarchies do not provide implementations of AbstractTool.handleKeyTraversed(TraverseEvent), so the tools are receiving the event but only doing the no-op provided by AbstractTool.

For the PanningSelectionTool case, I think it would be appropriate for PanningSelectionTool to provide an implementation that either (a) sets event.doit to false if the event represents ESC and the tool is in its initial, terminal, or (perhaps) invalid state or (b) permits the current drag tracker to have some say in the decision.

For the PaletteSelectionTool case, I think it would be appropriate for the implementation to set event.doit to false if the event represents ESC and the palette viewer's active tool is not its palette root's default entry.