Retargetable editor actions
Recall that the
readmetool defines its own editor which contributes actions
to the workbench menu bar using its ReadmeEditorActionBarContributor.
<extension
point = "org.eclipse.ui.editors">
<editor
id = "org.eclipse.ui.examples.readmetool.ReadmeEditor"
name="%Editors.ReadmeEditor"
icon="icons/obj16/editor.png"
class="org.eclipse.ui.examples.readmetool.ReadmeEditor"
extensions="readme"
contributorClass="org.eclipse.ui.examples.readmetool.ReadmeEditorActionBarContributor">
</editor>
</extension>
Let's look closer at what happens in the contributor class.
public ReadmeEditorActionBarContributor() {
...
action2 = new RetargetAction(IReadmeConstants.RETARGET2, MessageUtil.getString("Editor_Action2"));
action2.setToolTipText(MessageUtil.getString("Readme_Editor_Action2"));
action2.setDisabledImageDescriptor(ReadmeImages.EDITOR_ACTION2_IMAGE_DISABLE);
action2.setImageDescriptor(ReadmeImages.EDITOR_ACTION2_IMAGE_ENABLE);
...
action3 = new LabelRetargetAction(IReadmeConstants.LABELRETARGET3, MessageUtil.getString("Editor_Action3"));
action3.setDisabledImageDescriptor(ReadmeImages.EDITOR_ACTION3_IMAGE_DISABLE);
action3.setImageDescriptor(ReadmeImages.EDITOR_ACTION3_IMAGE_ENABLE);
...
handler2 = new EditorAction(MessageUtil.getString("Editor_Action2"));
...
handler3 = new EditorAction(MessageUtil.getString("Editor_Action3"));
...
When the contributor is created, it creates two retargetable actions (one
that allows label update and one that does not). Creation of the actions
uses the same technique that the workbench uses. It also creates two
handlers that will be used for the actions when the editor is the active
part.
But where are the handlers for the actions registered? Setting the
global handlers is done a little differently when your editor defines the
retargeted actions. Why? Because your contributor is in charge of
tracking the active view and hooking different handlers as different views or
the editor itself becomes active. (The workbench does this for you when
you set a handler for one of its global actions). Here's how the ReadmeEditorActionBarContributor
sets things up:
public void init(IActionBars bars, IWorkbenchPage page) {
super.init(bars, page);
bars.setGlobalActionHandler(IReadmeConstants.RETARGET2, handler2);
bars.setGlobalActionHandler(IReadmeConstants.LABELRETARGET3, handler3);
...
First, the contributor registers its handlers for the retargeted
actions. This ensures that the contributor's actions will be run when the
editor itself is active. The next step is to register each
RetargetAction
as a part listener on the page.
...
// Hook retarget actions as page listeners
page.addPartListener(action2);
page.addPartListener(action3);
IWorkbenchPart activePart = page.getActivePart();
if (activePart != null) {
action2.partActivated(activePart);
action3.partActivated(activePart);
}
}
Adding each
RetargetAction
as a part listener means that it will be notified when the active part
changes. The action can get the correct global handler from the newly
activated part. (See the implementation of
RetargetAction
for all the details.) Note that to start, the action is seeded
with the currently active part.
When the editor contributor is disposed, it should unhook the retargetable
actions as page listeners.
public void dispose() {
// Remove retarget actions as page listeners
getPage().removePartListener(action2);
getPage().removePartListener(action3);
}
Finally, recall that action bar contributors are shared among instances of
the same editor class. For this reason, the handlers must be notified when
the active editor changes so that they can connect to the proper editor
instance.
public void setActiveEditor(IEditorPart editor) {
...
handler2.setActiveEditor(editor);
handler3.setActiveEditor(editor);
...
}
That completes the setup on the editor side. When the editor is open
and active, the handlers (and their labels) as defined by the ReadmeEditorActionBarContributor
will appear in the workbench menu bar.
Now that the editor's contributions are in place, what does a view do to register a handler? The code on the client side
is similar to registering a handler for a workbench action, except that the
action id is the one defined by the plug-in's editor. The ReadmeContentOutlinePage
registers a handler for these actions.
public void createControl(Composite parent) {
super.createControl(parent);
...
getSite().getActionBars().setGlobalActionHandler(
IReadmeConstants.RETARGET2,
new OutlineAction(MessageUtil.getString("Outline_Action2")));
OutlineAction action = new OutlineAction(MessageUtil.getString("Outline_Action3"));
action.setToolTipText(MessageUtil.getString("Readme_Outline_Action3"));
getSite().getActionBars().setGlobalActionHandler(
IReadmeConstants.LABELRETARGET3,
action);
...
Note that the outliner sets tool tip text and a label on the second action,
since it allows relabeling. When the readme outliner view is made active,
its handlers (and their labels) will now appear in the workbench menu bar.
Note that the relabeled action shows the new label.