Community
Participate
Working Groups
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
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.
>> 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.