| /******************************************************************************* |
| * Copyright (c) 2000, 2015 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<StatusFieldDef, StatusLineContributionItem> 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)); |
| if (editor instanceof AbstractTextEditor && ((AbstractTextEditor)editor).isWordWrapSupported()) |
| actionBars.setGlobalActionHandler(ITextEditorActionDefinitionIds.WORD_WRAP, getAction(editor, ITextEditorActionConstants.WORD_WRAP)); |
| |
| 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= 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} |
| */ |
| @Override |
| public void setActiveEditor(IEditorPart part) { |
| doSetActiveEditor(part); |
| } |
| |
| @Override |
| 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); |
| } |
| |
| @Override |
| public void contributeToStatusLine(IStatusLineManager statusLineManager) { |
| super.contributeToStatusLine(statusLineManager); |
| for (int i= 0; i < STATUS_FIELD_DEFS.length; i++) |
| statusLineManager.add(fStatusFields.get(STATUS_FIELD_DEFS[i])); |
| } |
| |
| @Override |
| public void dispose() { |
| doSetActiveEditor(null); |
| super.dispose(); |
| } |
| } |