org.eclipse.ui.texteditor.BasicTextEditorActionContributor.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.ui.texteditor.BasicTextEditorActionContributor.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2009 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Tom Eicher (Avaloq Evolution AG) - block selection mode
 *******************************************************************************/

package org.eclipse.ui.texteditor;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.runtime.Assert;

import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IContributionManager;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.Separator;

import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.part.EditorActionBarContributor;

/**
 * Manages the installation and removal of global actions for
 * the same type of editors.
 * <p>
 * If instantiated and used as-is, this contributor connects to all of the workbench defined
 * global editor actions the corresponding actions of the current editor. It also adds addition
 * actions for searching and navigation (go to line) as well as a set of status fields.</p>
 * <p>
 * Subclasses may override the following methods:
 * <ul>
 *   <li><code>contributeToMenu</code> - extend to contribute to menu</li>
 *   <li><code>contributeToToolBar</code> - reimplement to contribute to tool bar</li>
 *   <li><code>contributeToStatusLine</code> - reimplement to contribute to status line</li>
 *   <li><code>setActiveEditor</code> - extend to react to editor changes</li>
 * </ul>
 * </p>
 * @see org.eclipse.ui.texteditor.ITextEditorActionConstants
 */
public class BasicTextEditorActionContributor extends EditorActionBarContributor {

    /** The global actions to be connected with editor actions */
    private final static String[] ACTIONS = { ITextEditorActionConstants.UNDO, ITextEditorActionConstants.REDO,
            ITextEditorActionConstants.CUT, ITextEditorActionConstants.COPY, ITextEditorActionConstants.PASTE,
            ITextEditorActionConstants.DELETE, ITextEditorActionConstants.SELECT_ALL,
            ITextEditorActionConstants.FIND, ITextEditorActionConstants.PRINT,
            ITextEditorActionConstants.PROPERTIES, ITextEditorActionConstants.REVERT };

    /**
     * Status field definition.
     * @since 3.0
     */
    private static class StatusFieldDef {

        private String category;
        private String actionId;
        private boolean visible;
        private int widthInChars;

        private StatusFieldDef(String category, String actionId, boolean visible, int widthInChars) {
            Assert.isNotNull(category);
            this.category = category;
            this.actionId = actionId;
            this.visible = visible;
            this.widthInChars = widthInChars;
        }
    }

    /**
     * The status fields to be set to the editor
     * @since 3.0
     */
    private final static StatusFieldDef[] STATUS_FIELD_DEFS = {
            new StatusFieldDef(ITextEditorActionConstants.STATUS_CATEGORY_FIND_FIELD, null, false,
                    EditorMessages.Editor_FindIncremental_reverse_name.length() + 15),
            new StatusFieldDef(ITextEditorActionConstants.STATUS_CATEGORY_ELEMENT_STATE, null, true,
                    StatusLineContributionItem.DEFAULT_WIDTH_IN_CHARS + 1),
            new StatusFieldDef(ITextEditorActionConstants.STATUS_CATEGORY_INPUT_MODE,
                    ITextEditorActionDefinitionIds.TOGGLE_OVERWRITE, true,
                    StatusLineContributionItem.DEFAULT_WIDTH_IN_CHARS),
            new StatusFieldDef(ITextEditorActionConstants.STATUS_CATEGORY_INPUT_POSITION,
                    ITextEditorActionConstants.GOTO_LINE, true,
                    StatusLineContributionItem.DEFAULT_WIDTH_IN_CHARS) };

    /**
     * The active editor part.
     */
    private IEditorPart fActiveEditorPart;
    /**
     * The find next action.
     * @since 2.0
     */
    private RetargetTextEditorAction fFindNext;
    /**
     * The find previous action.
     * @since 2.0
     */
    private RetargetTextEditorAction fFindPrevious;
    /**
     * The incremental find action.
     * @since 2.0
     */
    private RetargetTextEditorAction fIncrementalFind;
    /**
     * The reverse incremental find action.
     * @since 2.1
     */
    private RetargetTextEditorAction fIncrementalFindReverse;
    /**
     * The go to line action.
     */
    private RetargetTextEditorAction fGotoLine;
    /**
     * The word completion action.
     * @since 3.1
     */
    private RetargetTextEditorAction fHippieCompletion;
    /**
     * The map of status fields.
     * @since 2.0
     */
    private Map fStatusFields;

    /**
     * Creates an empty editor action bar contributor. The action bars are
     * furnished later via the <code>init</code> method.
     *
     * @see org.eclipse.ui.IEditorActionBarContributor#init(org.eclipse.ui.IActionBars, org.eclipse.ui.IWorkbenchPage)
     */
    public BasicTextEditorActionContributor() {

        fFindNext = new RetargetTextEditorAction(EditorMessages.getBundleForConstructedKeys(), "Editor.FindNext."); //$NON-NLS-1$
        fFindNext.setActionDefinitionId(IWorkbenchActionDefinitionIds.FIND_NEXT);
        fFindPrevious = new RetargetTextEditorAction(EditorMessages.getBundleForConstructedKeys(),
                "Editor.FindPrevious."); //$NON-NLS-1$
        fFindPrevious.setActionDefinitionId(IWorkbenchActionDefinitionIds.FIND_PREVIOUS);
        fIncrementalFind = new RetargetTextEditorAction(EditorMessages.getBundleForConstructedKeys(),
                "Editor.FindIncremental."); //$NON-NLS-1$
        fIncrementalFind.setActionDefinitionId(IWorkbenchActionDefinitionIds.FIND_INCREMENTAL);
        fIncrementalFindReverse = new RetargetTextEditorAction(EditorMessages.getBundleForConstructedKeys(),
                "Editor.FindIncrementalReverse."); //$NON-NLS-1$
        fIncrementalFindReverse.setActionDefinitionId(IWorkbenchActionDefinitionIds.FIND_INCREMENTAL_REVERSE);
        fGotoLine = new RetargetTextEditorAction(EditorMessages.getBundleForConstructedKeys(), "Editor.GotoLine."); //$NON-NLS-1$
        fGotoLine.setActionDefinitionId(ITextEditorActionDefinitionIds.LINE_GOTO);
        fHippieCompletion = new RetargetTextEditorAction(EditorMessages.getBundleForConstructedKeys(),
                "Editor.HippieCompletion."); //$NON-NLS-1$
        fHippieCompletion.setActionDefinitionId(ITextEditorActionDefinitionIds.HIPPIE_COMPLETION);

        fStatusFields = new HashMap(3);
        for (int i = 0; i < STATUS_FIELD_DEFS.length; i++) {
            StatusFieldDef fieldDef = STATUS_FIELD_DEFS[i];
            fStatusFields.put(fieldDef,
                    new StatusLineContributionItem(fieldDef.category, fieldDef.visible, fieldDef.widthInChars));
        }
    }

    /**
     * Returns the active editor part.
     *
     * @return the active editor part
     */
    protected final IEditorPart getActiveEditorPart() {
        return fActiveEditorPart;
    }

    /**
     * Returns the action registered with the given text editor.
     *
     * @param editor the editor, or <code>null</code>
     * @param actionId the action id
     * @return the action, or <code>null</code> if none
     */
    protected final IAction getAction(ITextEditor editor, String actionId) {
        return (editor == null || actionId == null ? null : editor.getAction(actionId));
    }

    /**
     * The method installs the global action handlers for the given text editor.
     * <p>
     * This method cannot be overridden by subclasses.</p>
     *
     * @param part the active editor part
     * @since 2.0
     */
    private void doSetActiveEditor(IEditorPart part) {

        if (fActiveEditorPart == part)
            return;

        if (fActiveEditorPart instanceof ITextEditorExtension) {
            ITextEditorExtension extension = (ITextEditorExtension) fActiveEditorPart;
            for (int i = 0; i < STATUS_FIELD_DEFS.length; i++)
                extension.setStatusField(null, STATUS_FIELD_DEFS[i].category);
        }

        fActiveEditorPart = part;
        ITextEditor editor = (part instanceof ITextEditor) ? (ITextEditor) part : null;

        IActionBars actionBars = getActionBars();
        for (int i = 0; i < ACTIONS.length; i++)
            actionBars.setGlobalActionHandler(ACTIONS[i], getAction(editor, ACTIONS[i]));
        actionBars.setGlobalActionHandler(ITextEditorActionDefinitionIds.SHOW_WHITESPACE_CHARACTERS,
                getAction(editor, ITextEditorActionConstants.SHOW_WHITESPACE_CHARACTERS));
        actionBars.setGlobalActionHandler(ITextEditorActionDefinitionIds.BLOCK_SELECTION_MODE,
                getAction(editor, ITextEditorActionConstants.BLOCK_SELECTION_MODE));

        fFindNext.setAction(getAction(editor, ITextEditorActionConstants.FIND_NEXT));
        fFindPrevious.setAction(getAction(editor, ITextEditorActionConstants.FIND_PREVIOUS));
        fIncrementalFind.setAction(getAction(editor, ITextEditorActionConstants.FIND_INCREMENTAL));
        fIncrementalFindReverse.setAction(getAction(editor, ITextEditorActionConstants.FIND_INCREMENTAL_REVERSE));
        fGotoLine.setAction(getAction(editor, ITextEditorActionConstants.GOTO_LINE));
        fHippieCompletion.setAction(getAction(editor, ITextEditorActionConstants.HIPPIE_COMPLETION));

        for (int i = 0; i < STATUS_FIELD_DEFS.length; i++) {
            if (fActiveEditorPart instanceof ITextEditorExtension) {
                StatusLineContributionItem statusField = (StatusLineContributionItem) fStatusFields
                        .get(STATUS_FIELD_DEFS[i]);
                statusField.setActionHandler(getAction(editor, STATUS_FIELD_DEFS[i].actionId));
                ITextEditorExtension extension = (ITextEditorExtension) fActiveEditorPart;
                extension.setStatusField(statusField, STATUS_FIELD_DEFS[i].category);
            }
        }
    }

    /**
     * The <code>BasicTextEditorActionContributor</code> implementation of this
     * <code>IEditorActionBarContributor</code> method installs the global
     * action handler for the given text editor by calling a private helper
     * method.
     * <p>
     * Subclasses may extend.</p>
     *
     * @param part {@inheritDoc}
     */
    public void setActiveEditor(IEditorPart part) {
        doSetActiveEditor(part);
    }

    /*
     * @see EditorActionBarContributor#contributeToMenu(IMenuManager)
     */
    public void contributeToMenu(IMenuManager menu) {

        IMenuManager editMenu = menu.findMenuUsingPath(IWorkbenchActionConstants.M_EDIT);
        if (editMenu != null) {
            editMenu.prependToGroup(IWorkbenchActionConstants.FIND_EXT, fIncrementalFindReverse);
            editMenu.prependToGroup(IWorkbenchActionConstants.FIND_EXT, fIncrementalFind);
            editMenu.prependToGroup(IWorkbenchActionConstants.FIND_EXT, fFindPrevious);
            editMenu.prependToGroup(IWorkbenchActionConstants.FIND_EXT, fFindNext);

            addOrInsert(editMenu, new Separator(ITextEditorActionConstants.GROUP_OPEN));
            addOrInsert(editMenu, new Separator(ITextEditorActionConstants.GROUP_INFORMATION));
            addOrInsert(editMenu, new Separator(ITextEditorActionConstants.GROUP_ASSIST));
            addOrInsert(editMenu, new Separator(ITextEditorActionConstants.GROUP_GENERATE));
            addOrInsert(editMenu, new Separator(IWorkbenchActionConstants.MB_ADDITIONS));

            editMenu.appendToGroup(ITextEditorActionConstants.GROUP_ASSIST, fHippieCompletion);
        }

        IMenuManager navigateMenu = menu.findMenuUsingPath(IWorkbenchActionConstants.M_NAVIGATE);
        if (navigateMenu != null) {
            navigateMenu.appendToGroup(IWorkbenchActionConstants.MB_ADDITIONS, fGotoLine);
        }
    }

    /**
     * The <code>item</code> is {@link IContributionManager#add(IContributionItem) added} to
     * <code>menu</code> if no item with the same id currently exists. If there already is an
     * contribution item with the same id, the new item gets
     * {@link IContributionManager#insertAfter(String, IContributionItem) inserted after} it.
     *
     * @param menu the contribution manager
     * @param item the contribution item
     * @since 3.2
     */
    private void addOrInsert(IContributionManager menu, IContributionItem item) {
        String id = item.getId();
        if (menu.find(id) == null)
            menu.add(item);
        else
            menu.insertAfter(id, item);
    }

    /*
     * @see EditorActionBarContributor#contributeToStatusLine(org.eclipse.jface.action.IStatusLineManager)
     * @since 2.0
     */
    public void contributeToStatusLine(IStatusLineManager statusLineManager) {
        super.contributeToStatusLine(statusLineManager);
        for (int i = 0; i < STATUS_FIELD_DEFS.length; i++)
            statusLineManager.add((IContributionItem) fStatusFields.get(STATUS_FIELD_DEFS[i]));
    }

    /*
     * @see org.eclipse.ui.IEditorActionBarContributor#dispose()
     * @since 2.0
     */
    public void dispose() {
        doSetActiveEditor(null);
        super.dispose();
    }
}