#### Retargetable editor actions

Recall that the readme tool 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.