How to ensure that my key bindings have priority over other definitions - eclipse

I am developing an RCP app. The app has an execution mode where I want to enable various key bindings to control Start, Stop, Continue, Repeat etc. The bindings will be enabled using an 'ExecutionContext' which is set when any of the relevant views are activated.
The context switching is done in each of the 'Execution' views.
#Override
public final void createPartControl(Composite parent)
{
addPartListener();
...
}
private void addPartListener()
{
this.getViewSite().getPage().addPartListener(new IPartListener2()
{
IContextActivation token = null;
#Override
public void partDeactivated(IWorkbenchPartReference partRef)
{
if (token != null)
{
System.out.println("End exec context");
IContextService contextService = (IContextService) PlatformUI.getWorkbench().getService(
IContextService.class);
contextService.deactivateContext(token);
token = null;
}
}
#Override
public void partActivated(IWorkbenchPartReference partRef)
{
System.out.println("Set exec context");
IContextService contextService = (IContextService) PlatformUI.getWorkbench().getService(
IContextService.class);
token = contextService.activateContext("AtfExecutionContext");
}
});
}
I can see via Console messages that my context is being set and some of the key bindings are working as expected.
However, if a key binding has already been assigned from another plugin, that binding has priority. E.g. I want to use Ctrl+F8 to stop but when that is pressed I get the 'Next perspective' action which is the workbench default.
The binding definition is
<extension
point="org.eclipse.ui.bindings">
<scheme
id="atfscheme"
name="atfscheme"
parentId="org.eclipse.ui.defaultAcceleratorConfiguration">
</scheme>
<key
commandId="com.xxx.atf.model.ui.commands.ExecKey.Start"
contextId="AtfExecutionContext"
schemeId="atfscheme"
sequence="M1+M2+F5">
<!-- F5 does not work but Ctrl-Shift-F5 does -->
</key>
</extension>
<extension
point="org.eclipse.ui.contexts">
<context
id="AtfExecutionContext"
name="AtfExecutionContext"
parentId="org.eclipse.debug.ui.debugging">
<!-- have tried various parentid values... -->
</context>
</extension>
It seems that only previously undefined accelerators work. What do I have to do to override existing definitions and activate mine when my context has been set?

There is a separate context service for each part, you must use the correct context service.
It isn't necessary to activate / deactivate the context on part activation / deactivation. The separate context services will deal with that automatically.
So activate in createPartControl with:
IContextService contextService = getSite().getService(IContextService.class);
token = contextService.activateContext("AtfExecutionContext");
and deactivate when the part closes.
You are also defining a new key binding scheme - that has to be activated separately and isn't what you want here. Just remove that and just use org.eclipse.ui.defaultAcceleratorConfiguration as the schemeId

Related

Eclipse RCP Content Assist not working with auto activated characters

I define my own editor and have completion proposals like this
public IContentAssistant getContentAssistant(ISourceViewer sv) {
ContentAssistant ca = new ContentAssistant();
IContentAssistProcessor pr = new TagCompletionProcessor();
ca.setContentAssistProcessor(pr, IDocument.DEFAULT_CONTENT_TYPE);
return ca;
}
#Override
public char[] getCompletionProposalAutoActivationCharacters() {
String str = "._abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
return str.toCharArray();
}
So when I am pressing ctrl-space enter it will work, but I want it should always trigger computeCompletionProposals when any of the above characters are entered.
<extension
point="org.eclipse.ui.editors">
<editor
id="testingpluginproject.editors.XMLEditor"
name="Sample XML Editor"
icon="icons/sample.png"
extensions="xxml"
class="testingpluginproject.editors.XMLEditor"
contributorClass="org.eclipse.ui.texteditor.BasicTextEditorActionContributor">
</editor>
</extension>
So what I am missing?
You must call the ContentAssistant enableAutoActivation method to enable auto activation:
ca.enableAutoActivation(true);
You might also want to look at implementing IContentAssistProcessorExtension rather than just IContentAssistProcessor as it provides a better isCompletionProposalAutoActivation method.

How to manage key conflict handler of different commands in multipage editor

I have multipage editor and i'm using different commands in two pages with same key sequence 'M3+O'. I am getting key conflicting handlers.
Error:
!MESSAGE A conflict occurred for ALT+O:
Binding(ALT+O,
ParameterizedCommand(Command(adt.tools.wda_com.sap.adt.wda.controller.ui.addmethcommand,Add Method,
,
Category(org.eclipse.core.commands.categories.autogenerated,Uncategorized,Commands that were either auto-generated or have no category,true),
org.eclipse.ui.internal.MakeHandlersGo#2f2e3d,
,,true),null),
org.eclipse.ui.defaultAcceleratorConfiguration,
com.sap.adt.wda.controller.ui.contextTabScope,,,system)
Binding(ALT+O,
ParameterizedCommand(Command(adt.tools.wda_com.sap.adt.wda.controller.ui.addnodecommand,Add Node,
,
Category(org.eclipse.core.commands.categories.autogenerated,Uncategorized,Commands that were either auto-generated or have no category,true),
org.eclipse.ui.internal.MakeHandlersGo#184af18,
,,true),null),
org.eclipse.ui.defaultAcceleratorConfiguration,
com.sap.adt.wda.controller.ui.contextTabScope,,,system)
Extensions:
<extension
point="org.eclipse.ui.bindings">
<key
commandId="adt.tools.wda_com.sap.adt.wda.controller.ui.addmethcommand"
contextId="com.sap.adt.wda.controller.ui.contextScope"
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
sequence="M3+O">
</key>
<key
commandId="adt.tools.wda_com.sap.adt.wda.controller.ui.addnodecommand"
contextId="com.sap.adt.wda.controller.ui.contextScope"
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
sequence="M3+O">
</key>
</extension>
My own Context:
<extension
point="org.eclipse.ui.contexts">
<context
description="context scope"
id="com.sap.adt.wda.controller.ui.contextScope"
name="context scope"
parentId="org.eclipse.ui.contexts.window">
</context>
</extension>
Activation and deactivation: It is done through activation and deactivation of context. Below is the code snippet on page change.
Activation in 1st Page:
private void activateHandlers() {
IContextService contextService = (IContextService) (PlatformUI.getWorkbench().getService(IContextService.class));
if (contextService != null) {
activation = contextService.activateContext(IControllerConstants.CONTEXT_TAB_ECLIPSE_CONTEXT_ID);
}
IEditorSite site = getEditor().getEditorSite();
IHandlerService service = (IHandlerService) site.getService(IHandlerService.class);
IHandlerActivation nodeActivation = service.activateHandler(AddNodeHandler.COMMAND_ID, new AddNodeHandler());
activatedHandlers = new ArrayList<IHandlerActivation>();
activatedHandlers.add(nodeActivation );
}
Activation in 2nd Page:
private void activateHandlers() {
IContextService contextService = (IContextService) (PlatformUI.getWorkbench().getService(IContextService.class));
if (contextService != null) {
activation = contextService.activateContext(IControllerConstants.CONTEXT_TAB_ECLIPSE_CONTEXT_ID);
}
IEditorSite site = getEditor().getEditorSite();
IHandlerService service = (IHandlerService) site.getService(IHandlerService.class);
IHandlerActivation methodActivation = service.activateHandler(AddMethodHandler.COMMAND_ID, new AddMethodHandler());
activatedHandlers = new ArrayList<IHandlerActivation>();
activatedHandlers.add(methodActivation );
}
Deactivation similar in respective page:
public void deactivateHandlers() {
IContextService contextService = (IContextService) (PlatformUI.getWorkbench().getService(IContextService.class));
contextService.deactivateContext(activation);
IHandlerService service = (IHandlerService) getEditor().getEditorSite().getService(IHandlerService.class);
if (activatedHandlers != null) {
service.deactivateHandlers(activatedHandlers);
activatedHandlers = null;
}
}
Even after deactivation / activation on page change, the conflict appears.
Please let me know if there is a better approach.
Thanks.
Use a different context id for each page. You could make your main com.sap.adt.wda.controller.ui.contextScope the parent of each page context.

Implementation AbstractPreferenceInitializer won't get called in my Eclipse RCP

I want to use the Eclipse mechanism to set default preferences in my RCP application. Therefore I extended the class AbstractPreferenceInitializer to set my default preferences:
public class PreferenceInitializer extends AbstractPreferenceInitializer {
#Override
public void initializeDefaultPreferences() {
IPreferenceStore preferenceStore = PlatformUI.getPreferenceStore();
preferenceStore.setDefault("xyz", xyz);
preferenceStore.setDefault("abc", false);
}
}
Then I defined the extension point:
<extension point="org.eclipse.core.runtime.preferences">
<initializer class="com.abc.PreferenceInitializer">
</initializer>
</extension>
But unfortunately, the initializer won't get called during startup (whereas Eclipse's WorkbenchPreferenceInitializer will be called).
Can someone give me a hint, what to do, to get this run?
Your preference initializer code won't get called until those default values are needed (rather than on application startup, which I'm guessing was your expectation).
If you have yourself a preference page that contains some FieldEditors using your preference names, your preference initializer will get called when you go to the Preferences dialog and select that preference page.
Something along the lines of:
public class MyPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
public void createFieldEditors() {
Composite parent = getFieldEditorParent();
addField(new StringFieldEditor(Constants.PREFERENCES.FILE_COMPARE_TOOL_LOCATION, "File compare tool location", parent));
addField(new StringFieldEditor("xyz", "XYZ Value", parent));
addField(new BooleanFieldEditor("abc", "Enable the ABC widget", parent));
}
}
And of course, an extension point for the page:
<extension point="org.eclipse.ui.preferencePages">
<page
class="whatever.package.MyPreferencePage"
id="whatever.package.MyPreferencePage"
name="MyPrefs">
</page>
</extension>

Handling drag and drop of files inside Eclipse Package Explorer

I'm trying to create an Eclipse plugin to support a proprietary project file format. My goal is to be able to drag and drop a file in the Project Explorer (any type of file) onto a file of the type I support, and have the name of the file being dragged appended to the end of the proprietary file.
Right now, I have a custom editor that can parse out some data from an existing file in a manageable way. This means that I have an editor associated with the file type, such that my special icon shows up next to it. I don't know if that's relevant.
I'm attempting to use the extension point "org.eclipse.ui.dropActions" but I'm not sure how to register my DropActionDelegate (implements org.eclipse.ui.part.IDropActionDelegate) such that it will be called when a file is dropped onto one of my type within the Project Explorer.
Anybody have any ideas? Am I even on the right track with the DropActionDelegate?
You are on the right track implementing an IDropActionDelegate:
class DropActionDelegate implements IDropActionDelegate {
#Override
public boolean run(Object source, Object target) {
String transferredData (String) target; // whatever type is needed
return true; // if drop successful
}
}
The purpose of the extension point org.eclipse.ui.dropActions is to provide drop behaviour to views which you don't have defined yourself (like the Project Explorer).
You register the drop action extension like this:
<extension point="org.eclipse.ui.dropActions">
<action
id="my_drop_action"
class="com.xyz.DropActionDelegate">
</action>
</extension>
Don't forget to attach an adequate listener to your editor in your plugin code:
class DragListener implements DragSourceListener {
#Override
public void dragStart(DragSourceEvent event) {
}
#Override
public void dragSetData(DragSourceEvent event) {
PluginTransferData p;
p = new PluginTransferData(
"my_drop_action", // must be id of registered drop action
"some_data" // may be of arbitrary type
);
event.data = p;
}
#Override
public void dragFinished(DragSourceEvent event) {
}
}

How to handle property sheet from customized editor in eclipse plugin development?

I have to bind my editor widget objects in property sheet.So that i can the property of my widget from property view.
Please help me on this, if possible provide me some code snippets.
You have a good example in the Getting started with Properties
Using the Properties view is simple enough.
Since it shows properties for the selected object, the first step to using it is to make sure that the workbench selection service knows about the object selected in your view. There’s an entire Eclipse Corner article written on the subject of the selection service
public void createPartControl(Composite parent) {
viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
viewer.setContentProvider(new ViewContentProvider());
viewer.setLabelProvider(new ViewLabelProvider());
getSite().setSelectionProvider(viewer);
viewer.setInput(getViewSite());
}
Once you have your view contributing to the workbench selection, you need to make sure that the objects that your view is selecting contribute properties
(extract)
public class Person implements IPropertySource {
private String name;
private Object street;
private Object city;
public Person(String name) {
this.name = name;
this.street = "";
this.city = "";
}
public Object getEditableValue() {
return this;
}
public IPropertyDescriptor[] getPropertyDescriptors() {
return new IPropertyDescriptor[] {
new TextPropertyDescriptor("name", "Name"),
new TextPropertyDescriptor("street", "Street"),
new TextPropertyDescriptor("city", "City")
};
}
I indicated earlier that this solution is “not necessarily [the] most correct”. This is because, for this to work, my domain object needs to know about the very view-centric (and Eclipse-centric) notion of being a property source; in short, there is a tight-coupling between the model and view and this not a good thing™.
Using adapter is a better approach, as described in this article:
Person should implement IAdaptable.
See also this recent article on how to create a custom property view
how to hack the Properties View to listen only to a specific view.
The isImportant() method is the one which decides whether to create an IPage for the specific IWorkbenchPart or not.
The idea is to override that method and return false for all the workbenchPart that we are not interested in. Lets create the view first:
<view
class="com.eclipse_tips.views.CustomPropertiesView"
icon="icons/sample.gif"
id="com.eclipse-tips.views.customePropertiesView"
name="My Properties View">
</view>
The CustomPropertiesView should extend PropertySheet and override the isImportant():
public class CustomPropertiesView extends PropertySheet {
#Override
protected boolean isImportant(IWorkbenchPart part) {
if (part.getSite().getId().equals(IPageLayout.ID_PROJECT_EXPLORER))
return true;
return false;
}
}
In this case, I'm making the view only to respond to Project Explorer and ignore other views
According to this thread, the same principle should be valid for an Editor instead of a View.
The property sheet listens to the workbench page selection provider.
The selection provider depends on what viewer/editor is active.
Each editor/viewer provides their own selection provider to use when that editor/viewer is active.
This way the property sheet doesn't care who is active, it just listens to the selection provider.
That way depending upon the view, a different set of properties are displayed.
For example, the Navigator view provides IResource selections, so the property sheet then displays IResource properties when the Navigator is active.
The Workbench Selection mechanism is illustrated in this article
The ISelectionListener is a simple interface with just one method.
A typical implementation looks like this:
private ISelectionListener mylistener = new ISelectionListener() {
public void selectionChanged(IWorkbenchPart sourcepart, ISelection selection) {
if (sourcepart != MyView.this && // 1
selection instanceof IStructuredSelection) { // 2
doSomething(((IStructuredSelection) selection).toList()); // 3
}
}
};
Depending on your requirements your listener implementation probably needs to deal with the following issues as shown in the code snippet above:
In case we also provide selections (e.g. a view or editor) we should exclude our own selection events from processing. This avoids unexpected results when the user selects elements within our part (1).
Check whether we can handle this kind of selection (2).
Get the selected content from the selection and process it (3).