How to redirect key presses to another shell in an Eclipse-based app? - eclipse

I'm working on a way to maximise an EditorPart in my Eclipse-based RCP app to be absolutely full-screen, no trim, no menu, and so on. Actually, it's a GEF Editor. It's a bit of a hack, but it kind of works:
GraphicalViewer viewer = (GraphicalViewer)getWorkbenchPart().getAdapter(GraphicalViewer.class);
Control control = viewer.getControl();
Composite oldParent = control.getParent();
Shell shell = new Shell(SWT.APPLICATION_MODAL);
shell.setFullScreen(true);
shell.setMaximized(true);
// Some code here to listen to Esc key to dispose Shell and return...
shell.setLayout(new FillLayout());
control.setParent(shell);
shell.open();
Basically it sets the parent of the GraphicalViewer control to the newly created, maximised Shell. Pressing escape will return the control to it's original parent (code not shown for brevity).
The only thing that doesn't work is receiving global key presses (Del, Ctrl+Z, Ctrl+A) the ones that are declared for the Workbench and forwarded to the EditorPart. Is there any way I can hook into these or redirect them from the EditorPart to forward them on to the GraphicalViewer?
Thanks in advance

The short answer is you can't do that. Once you re-parent that composite out of the workbench window, it's totally busted. The system won't correctly deal with the part, as events (like activation, focus, setBounds(*)) aren't being processed.
The only supported way would be to open a new Workbench window with a perspective that only contained the editor area, and extending your org.eclipse.ui.application.WorkbenchWindowAdvisor.createWindowContents(Shell) method for that window+perspective combination to hide all of the trim you don't want, using org.eclipse.ui.application.IWorkbenchWindowConfigurer.
ex, in MyWorkbenchWindowAdvisor:
public void createWindowContents(Shell shell) {
if (isCreatingSpecialPerspective()) {
final IWorkbenchWindowConfigurer config = getWindowConfigurer();
config.setShowCoolBar(false);
config.setShowFastViewBars(false);
config.setShowMenuBar(false);
config.setShowPerspectiveBar(false);
config.setShowProgressIndicator(false);
config.setShowStatusLine(false);
}
super.createWindowContents(shell);
}
Also check out http://code.google.com/p/eclipse-fullscreen/ which has EPLed code in it concerned with running an RCP program with fullscreen support.

My suggestion is to try to approach this problem from another angle. Instead of listening for keystrokes in your code and acting upon them, define your own key binding scheme and then create commands and make them use this scheme. This would mean that you no longer have to listen for the key strokes in your code, but instead do whatever needs to be done through commands executed by these key strokes.

Related

Is there a way to avoid holding the ALT key when cycling through input fields within a SAPUI5 table?

I have a SAPUI5 table which contains input fields. I have prepared an example at http://jsfiddle.net/bgerth/x8h92mz8/.
When you press ALT+TAB you can cycle through the input fields within the table (I only found that out by looking at sap.m.ListBase.prototype._startItemNavigation).
Only pressing TAB focuses the first element outside the table.
I consider that rather non-intuitive. Is there a way to make TAB alone work the same way?
Update:
Alt+Tab works in Chrome and Safari, but not Firefox (45.0.2) on my Mac. It doesn't work at all on Windows, as that combination is reserved to toggle through open application windows.
There are two solutions I discovered so far to address this problem
Proposal 1: Adapt tab key handling
I have found the blog SAPUI5 Table Navigation with Tab Key by Klaus Kronawetter which adds extra keyboard handling to a sap.ui.table.Table. I adapted his code for a sap.m.Table which you can find at http://jsfiddle.net/bgerth/os6r096y.
Unfortunately, the code is rather lenghty.
Proposal 2: Enable up/down arrow keys
After further investigation, I decided that the solution from proposal 1 above is too much hassle.
Instead, I adapted the class sap.ui.core.delegate.ItemNavigationmentioned above, which is internally employed by sap.m.ListBase. In essence, you can cycle through the input fields with up and down arrow keys.
I have prepared an example at http://jsfiddle.net/bgerth/0r9L30wd. The relevant code is
var fnPatchedItemNavigationsetItemDomRefs = sap.ui.core.delegate.ItemNavigation.prototype.setItemDomRefs;
sap.ui.core.delegate.ItemNavigation.prototype.setItemDomRefs = function setItemDomRefsPatched(aItemDomRefs) {
// 'this' is now the instance of sap.ui.core.delegate.ItemNavigation
jQuery.sap.log.debug("Patched version of sap.ui.core.delegate.ItemNavigation.setItemDomRefs");
var aInputFields = $(aItemDomRefs).find("input:enabled").get();
if (aInputFields[0]) {
// There is at least one enabled input field in this table
return fnPatchedItemNavigationsetItemDomRefs.call(this, aInputFields);
} else {
return fnPatchedItemNavigationsetItemDomRefs.call(this, aItemDomRefs);
}
}

Custom content assist for default java editor in Eclipse

I'm currently trying to develop an Eclipse Plugin to support code replacement, like what the default content assist in Eclipse do. What I want to implement is something like "insert argument names automatically on method completion with visualized box around the argument" and I can "use the Tab key to navigate between the inserted names" and "while navigating, list of optional variables for current argument can be displayed and be chosen".
In short, it comes to two questions:
How to add the visualized box around the already existed variable or even Java keywords that need replacement? And at the meanwhile I can use Tab key to switch between these boxes.
How to display a list of candidates to select from when I trigger on the box?
By now I only figure out the extension point : org.eclipse.jdt.ui.javaCompletionProposalComputer may be useful, but I have no idea where to start at? Thanks in advance.
Oh, finally I've solved it myself...
For the 'box', it should be the LinkedModeModel, this class should work with LinkedPositionGroup and LinkedPosition to add mutiple boxes. And we should use LinkedModeUI to set it up.
For the content assistant, there's no need to use the extension point. There is a ProposalPosition class which extends LinkedPosition for you to add your proposals for the 'box' in its constructor. And we can simply use the CompletionProposal to construct a ICompletionProposal array as the argument of ProposalPosition's constructor.

contexts for copy and paste in eclipse for own plugin

I want to use copy and paste within my own view. Therefore I defined commands with a special context and activated it during the creation of the view.
The problem I'm now facing is that copy and paste is workin within my view but no longer within the normal eclipse world.
The context has a parent id into org.eclipse.ui.window.
Any hints how to seperate these contexs right so corresponding action is called at the right time.
I also turned on the key bind tracing within the debug options of org.eclipse.ui.
basic idea: How to override an existing key binding?
http://rcpexperiments.blogspot.de/2009/07/commands-key-bindings-and-contexts-in.html
key tracing: http://eclipsesource.com/blogs/2009/07/08/tip-tracing-keybindings-in-rcp/
You shouldn't need to use a context. You just provide an action handler for the global copy / paste actions:
IActionBars actionBars = getViewSite().getActionBars();
actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), copyAction);
actionBars.setGlobalActionHandler(ActionFactory.PASTE.getId(), pasteAction);

Eclipse: Perform an action any time an editor receives input

I'm wondering if it is possible to determine what input was just entered inside of an editor in Eclipse - I'm currently working off of the example JDT editor - and then perform an action based on that input.
e.g.: I have a file example.jav open in my editor window. I push the 'a' key. 'a' would appear in the editor window per normal, but 'a' would also print out to the console.
Obviously the operation I'll be performing will be more complicated than a System.out.println() statement, but if someone could help show me where the change gets detected by the editor itself, I can take it from there.
A few notes:
I'm working in Eclipse 3.7.2 with Java 1.7
If you cannot find the JDT example editor, go to Help > Welcome > Samples and click on "Java Editor".
Thanks in advance!
Figured it out!
As the Editor API is so vast in eclipse that it is difficult to know where to start, I focused on adding a KeyListener to my Shell. Turns out that is slightly problematic in SWT, as when an item inside the Shell gains focus, the Shell itself looses focus. After a bit of searching though, I stumbled across someone else who had the same problem. By adding a filter to the Shell's display, you can add a Listener object which works for the entire application. Such as:
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
Shell shell = window.getShell();
shell.getDisplay().addFilter(SWT.KeyDown, new Listener()
{
public void handleEvent(Event event)
{
System.out.println("" + event.character);
}
});
To further this and only worry about keys pressed in a specific non-widget part (otherwise you could just add a KeyListener to that part) you can add a check to make sure that the currently active part is the same as whatever part you wish to perform the actions for by using a simple if check.
final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
Shell shell = window.getShell();
shell.getDisplay().addFilter(SWT.KeyDown, new Listener()
{
public void handleEvent(Event event)
{
IWorkbenchPage page = window.getActivePage();
IWorkbenchPart part = page.getActivePart();
IEditorPart editor = page.getActiveEditor();
if(part.equals(editor))
{
System.out.println("" + event.character);
}
}
});
Here is hoping that this helps someone else have an easier time than I had finding the solution!

Eclipse RCP: how to observe the states of the cut/copy/paste commands?

I'm currently struggling with the following Eclipse RCP commands:
org.eclipse.ui.edit.cut
org.eclipse.ui.edit.copy
org.eclipse.ui.edit.paste
I'm using them as command contributions in the toolbar, but the UIElements (toolbar items) are not updated when the 'handled' state of those commands changes.
For testing I used a polling mechanism to verify that the state of those commands really changes depending on the currently focussed element, and I found out that the handler remains the same but the handler's 'handled' state changes properly, causing the commands 'handled' state to also change properly.
The only problem is, that neither one of those state changes causes a notification (neither on the command's ICommandListener, nor on the handler's IHandlerListener), so the UIElements won't get updated.
Here's some testing code to observe the states of a Command:
ICommandService commandService = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class);
final String commandId="org.eclipse.ui.edit.copy";
Command command = commandService.getCommand(commandId);
command.addCommandListener(new ICommandListener() {
public void commandChanged (CommandEvent commandEvent) {
System.out.println(">> Command changed: " + commandId);
}
});
Am I missing something, or is this an bug in the cut/copy/paste handler implementations?
Any insights?
EDIT:
The commands are enabled all the time, and the handler is never exchanged, only the handler's 'handled' state (and thus also the commmand's 'handled' state) changes depending on which ui element has the focus. There is however no notification when this state changes.
This results in the toolbar buttons always being enabled, and pressing them will cause a org.eclipse.core.commands.NotHandledException: There is no handler to execute for command.
The handler which is registered for the cut/copy/paste commands is org.eclipse.ui.internal.handlers.WidgetMethodHandler. This handler checks if a given method is declared on the current display's focus control. When executed, that handler will invoke the method using reflection.
Snippet from WidgetMethodHandler:
public final boolean isHandled() {
return getMethodToExecute() != null;
}
The getMethodToExecute() will locate the current focus control using Display.getCurrent().getFocusControl(), and then check if the given trigger method is declared on it.
Widgets such as org.eclipse.swt.widgets.Text have cut(), copy() and paste() methods, so when the focus is on such a widget, the handler will return 'true' for isHandled().
This handler is however not aware when the current focus control changes (I think there isn't even a way to observe this on the Display), and thus can't notify about changes on its dynamic 'isHandled' state.
This results in the cut/copy/paste commands being fine for popup menus, but they're quite problematic when used in toolbars, as their UI elements can't be updated properly when the handler does no notifications.
This leaves me with either not using those commands in the toolbar, or having a polling mechansim to update the ui elements (which is also bad and error prone). :-(
Your problem is that you need to register a handler for anything that is not a text because Eclipse needs to know how to copy the currently selected "something" to the clipboard. That's what a handler does. This article in the Eclipse wiki will get you started how to create and register a handler.
I could be wrong, but the source of the problem is that the handler is always enabled.
See Platform Plug-in Developer Guide > Programmer's Guide > Plugging into the workbench > Basic workbench extension points using commands > Handlers.
The <activeWhen/> expressions in the
plugin.xml and programmatic core
expressions are used to help determine
the scope of a handlers activation.
For example, a specific window, a
specific Shell, an active part type or
active part.
<extension
point="org.eclipse.ui.handlers">
...
<handler
class="org.eclipse.ui.examples.contributions.view.SwapInfoHandler"
commandId="org.eclipse.ui.examples.contributions.view.swap">
<activeWhen>
<reference
definitionId="org.eclipse.ui.examples.contributions.view.inView">
</reference>
</activeWhen>
<enabledWhen>
<count
value="2">
</count>
</enabledWhen>
</handler>
...