添加"切换评论"拥有Eclipse Editor插件的操作

时间:2016-07-14 10:06:42

标签: java eclipse eclipse-plugin eclipse-rcp

我想将Toggle Comment Action添加到我自己的Eclipse Editor插件中。应该可以通过按下Eclipse JDT中的键序列CTRL + 7来切换对所选代码部分的注释。我已经尝试过像这样修改plugin.xml:

<command
        categoryId="org.eclipse.ui.category.textEditor"
        id="org.eclipse.jdt.ui.edit.text.java.toggle.comment"
        name="Toggle comment">
</command>

<extension
         point="org.eclipse.ui.bindings">
      <key
            commandId="org.eclipse.jdt.ui.edit.text.java.toggle.comment"
            schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
            sequence="CTRL+7">
      </key>
  </extension>

我还将其添加到我的TextEditor实现中:

@Override
  protected void createActions(){
    super.createActions();

    IAction action= new ToggleCommentAction(ResourceBundle.getBundle(LangeditorMessages.getBundleName()), "ToggleComment.", this); //$NON-NLS-1$
    action.setActionDefinitionId(IJavaEditorActionDefinitionIds.TOGGLE_COMMENT);
    setAction(IJavaEditorActionDefinitionIds.TOGGLE_COMMENT, action);
    markAsStateDependentAction(IJavaEditorActionDefinitionIds.TOGGLE_COMMENT, true);
    PlatformUI.getWorkbench().getHelpSystem().setHelp(action, IJavaHelpContextIds.TOGGLE_COMMENT_ACTION);
    configureToggleCommentAction();
  }


  private void configureToggleCommentAction() {
    IAction action= getAction(IJavaEditorActionDefinitionIds.TOGGLE_COMMENT);
    if (action instanceof ToggleCommentAction) {
      ISourceViewer sourceViewer= getSourceViewer();
      SourceViewerConfiguration configuration= getSourceViewerConfiguration();
      ((ToggleCommentAction)action).configure(sourceViewer, configuration);
    }
  }

但下拉菜单中的选项都不会出现,也不能按键序列来切换评论。有什么想法吗?

我的另一个解决方案是自己实现ToggleCommentAction:

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

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextOperationTarget;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.texteditor.TextEditorAction;

/**
 * TODO: Write me!
 *
 * @author (last commit) $Author$
 * @version $Revision$, $Date$
 * @since TODO: add version number
 */
public final class ToggleCommentAction extends TextEditorAction {

  /** The text operation target */
  private ITextOperationTarget fOperationTarget;

  /** The document partitioning */
  private String fDocumentPartitioning;

  /** The comment prefixes */
  private Map<String, String[]> fPrefixesMap;

  /**
   * Creates and initializes the action for the given text editor. The action
   * configures its visual representation from the given resource bundle.
   * 
   * @param bundle the resource bundle
   * @param prefix a prefix to be prepended to the various resource keys, or
   * <code>null</code> if none
   * @param editor the text editor
   * @see ResourceAction#ResourceAction(ResourceBundle, String, int)
   */
  public ToggleCommentAction(ResourceBundle bundle, String prefix, ITextEditor editor) {
    super(bundle, prefix, editor);
  }

  /**
   * Checks if the selected lines are all commented or not and
   * uncomments/comments them respectively.
   */
  @Override
  public void run() {
    if (fOperationTarget == null || fDocumentPartitioning == null || fPrefixesMap == null)
      return;

    ITextEditor editor = getTextEditor();
    if (editor == null)
      return;

    if (!validateEditorInputState())
      return;

    final int operationCode;
    if (isSelectionCommented(editor.getSelectionProvider().getSelection()))
      operationCode = ITextOperationTarget.STRIP_PREFIX;
    else
      operationCode = ITextOperationTarget.PREFIX;

    Shell shell = editor.getSite().getShell();

    Display display = null;
    if (shell != null && !shell.isDisposed())
      display = shell.getDisplay();

    BusyIndicator.showWhile(display, new Runnable() {
      public void run() {
        fOperationTarget.doOperation(operationCode);
      }
    });
  }

  /**
   * Is the given selection single-line commented
   */
  private boolean isSelectionCommented(ISelection selection) {
    if (!(selection instanceof ITextSelection))
      return false;

    ITextSelection textSelection = (ITextSelection) selection;
    if (textSelection.getStartLine() < 0 || textSelection.getEndLine() < 0)
      return false;

    IDocument document = getTextEditor().getDocumentProvider()
        .getDocument(getTextEditor().getEditorInput());

    try {

      IRegion block = getTextBlockFromSelection(textSelection, document);
      ITypedRegion[] regions = TextUtilities.computePartitioning(document, fDocumentPartitioning,
          block.getOffset(), block.getLength(), false);

      int[] lines = new int[regions.length * 2]; // [startline, endline,
                                                 // startline, endline,
                                                 // ...]
      for (int i = 0, j = 0; i < regions.length; i++, j += 2) {
        // start line of region
        lines[j] = getFirstCompleteLineOfRegion(regions[i], document);
        // end line of region
        int length = regions[i].getLength();
        int offset = regions[i].getOffset() + length;
        if (length > 0)
          offset--;
        lines[j + 1] = (lines[j] == -1 ? -1 : document.getLineOfOffset(offset));
      }

      // Perform the check
      for (int i = 0, j = 0; i < regions.length; i++, j += 2) {
        String[] prefixes = fPrefixesMap.get(regions[i].getType());
        if (prefixes != null && prefixes.length > 0 && lines[j] >= 0 && lines[j + 1] >= 0)
          if (!isBlockCommented(lines[j], lines[j + 1], prefixes, document))
            return false;
      }

      return true;

    }
    catch (BadLocationException x) {
    }

    return false;
  }

  /**
   * Creates a region describing the text block (something that starts at the
   * beginning of a line) completely containing the current selection.
   */
  private IRegion getTextBlockFromSelection(ITextSelection selection, IDocument document) {

    try {
      IRegion line = document.getLineInformationOfOffset(selection.getOffset());
      int length = selection.getLength() == 0 ? line.getLength() : selection.getLength()
          + (selection.getOffset() - line.getOffset());
      return new Region(line.getOffset(), length);

    }
    catch (BadLocationException x) {
    }

    return null;
  }

  /**
   * Returns the index of the first line whose start offset is in the given text
   * range.
   */
  private int getFirstCompleteLineOfRegion(IRegion region, IDocument document) {

    try {

      final int startLine = document.getLineOfOffset(region.getOffset());

      int offset = document.getLineOffset(startLine);
      if (offset >= region.getOffset())
        return startLine;

      final int nextLine = startLine + 1;
      if (nextLine == document.getNumberOfLines())
        return -1;

      offset = document.getLineOffset(nextLine);
      return (offset > region.getOffset() + region.getLength() ? -1 : nextLine);

    }
    catch (BadLocationException x) {
    }

    return -1;
  }

  /**
   * Determines whether each line is prefixed by one of the prefixes.
   * 
   * @param prefixes Possible comment prefixes
   */
  private boolean isBlockCommented(int startLine, int endLine, String[] prefixes,
      IDocument document) {

    try {

      // check for occurrences of prefixes in the given lines
      for (int i = startLine; i <= endLine; i++) {

        IRegion line = document.getLineInformation(i);
        String text = document.get(line.getOffset(), line.getLength());

        int[] found = TextUtilities.indexOf(prefixes, text, 0);

        if (found[0] == -1)
          // found a line which is not commented
          return false;

        String s = document.get(line.getOffset(), found[0]);
        s = s.trim();
        if (s.length() != 0)
          // found a line which is not commented
          return false;

      }

      return true;

    }
    catch (BadLocationException x) {
    }

    return false;
  }

  @Override
  public void update() {
    super.update();

    if (!canModifyEditor()) {
      setEnabled(false);
      return;
    }

    ITextEditor editor = getTextEditor();
    if (fOperationTarget == null && editor != null)
      fOperationTarget = (ITextOperationTarget) editor.getAdapter(ITextOperationTarget.class);

    boolean isEnabled = (fOperationTarget != null
        && fOperationTarget.canDoOperation(ITextOperationTarget.PREFIX) && fOperationTarget
            .canDoOperation(ITextOperationTarget.STRIP_PREFIX));
    setEnabled(isEnabled);
  }

  /* @see TextEditorAction#setEditor(ITextEditor) */
  @Override
  public void setEditor(ITextEditor editor) {
    super.setEditor(editor);
    fOperationTarget = null;
  }

  public void configure(ISourceViewer sourceViewer, SourceViewerConfiguration configuration) {
    fPrefixesMap = null;

    String[] types = configuration.getConfiguredContentTypes(sourceViewer);
    Map<String, String[]> prefixesMap = new HashMap<String, String[]>(types.length);
    for (int i = 0; i < types.length; i++) {
      String type = types[i];
      String[] prefixes = configuration.getDefaultPrefixes(sourceViewer, type);
      if (prefixes != null && prefixes.length > 0) {
        int emptyPrefixes = 0;
        for (int j = 0; j < prefixes.length; j++)
          if (prefixes[j].length() == 0)
            emptyPrefixes++;

        if (emptyPrefixes > 0) {
          String[] nonemptyPrefixes = new String[prefixes.length - emptyPrefixes];
          for (int j = 0, k = 0; j < prefixes.length; j++) {
            String prefix = prefixes[j];
            if (prefix.length() != 0) {
              nonemptyPrefixes[k] = prefix;
              k++;
            }
          }
          prefixes = nonemptyPrefixes;
        }

        prefixesMap.put(type, prefixes);
      }
    }
    fDocumentPartitioning = configuration.getConfiguredDocumentPartitioning(sourceViewer);
    fPrefixesMap = prefixesMap;
  }

  /* (non-Javadoc)
   * @see org.eclipse.jface.action.Action#isEnabled() */
  @Override
  public boolean isEnabled() {
    return super.isEnabled();

  }

  /* (non-Javadoc)
   * @see org.eclipse.jface.action.Action#isHandled() */
  @Override
  public boolean isHandled() {
    return super.isHandled();
  }
}

将TextEditor实现中的方法更改为

@Override
  protected void createActions() {
    super.createActions();

    IAction action = new ToggleCommentAction(
        ResourceBundle.getBundle(LangeditorMessages.getBundleName()), "ToggleComment.", this); //$NON-NLS-1$
    action.setActionDefinitionId(ActionDefinitionIDs.TOGGLE_COMMENT);
    setAction(ActionDefinitionIDs.TOGGLE_COMMENT, action);
    markAsStateDependentAction(ActionDefinitionIDs.TOGGLE_COMMENT, true);
    configureToggleCommentAction();
  }

  private void configureToggleCommentAction() {
    IAction action = getAction(ActionDefinitionIDs.TOGGLE_COMMENT);
    if (action instanceof ToggleCommentAction) {
      ISourceViewer sourceViewer = getSourceViewer();
      SourceViewerConfiguration configuration = getSourceViewerConfiguration();
      ((ToggleCommentAction) action).configure(sourceViewer, configuration);
    }
  }

和plugin.xml:

<command
            categoryId="org.eclipse.ui.category.textEditor"
            id="de.se_rwth.langeditor.commands.ToggleCommentAction"
            name="Toggle comment">
      </command>



<extension
         point="org.eclipse.ui.bindings">
      <key
            commandId="de.se_rwth.langeditor.commands.ToggleCommentAction"
            schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
            sequence="CTRL+7">
      </key>
  </extension>

0 个答案:

没有答案