LinkedNamesAssistProposal.java :  » IDE-Eclipse » jdt » org » eclipse » jdt » internal » ui » text » correction » proposals » Java Open Source

Java Open Source » IDE Eclipse » jdt 
jdt » org » eclipse » jdt » internal » ui » text » correction » proposals » LinkedNamesAssistProposal.java
/*******************************************************************************
 * 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
 *******************************************************************************/
package org.eclipse.jdt.internal.ui.text.correction.proposals;

import java.util.Arrays;
import java.util.Comparator;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;

import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.StyledString;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension6;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.link.LinkedModeModel;
import org.eclipse.jface.text.link.LinkedModeUI;
import org.eclipse.jface.text.link.LinkedPosition;
import org.eclipse.jface.text.link.LinkedPositionGroup;
import org.eclipse.jface.text.link.LinkedModeUI.ExitFlags;
import org.eclipse.jface.text.link.LinkedModeUI.IExitPolicy;

import org.eclipse.ui.IEditorPart;

import org.eclipse.ui.texteditor.link.EditorLinkedModeUI;

import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.SimpleName;

import org.eclipse.jdt.internal.corext.dom.LinkedNodeFinder;
import org.eclipse.jdt.internal.corext.dom.NodeFinder;
import org.eclipse.jdt.internal.corext.util.Messages;

import org.eclipse.jdt.ui.SharedASTProvider;
import org.eclipse.jdt.ui.text.java.IInvocationContext;
import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal;

import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.JavaPluginImages;
import org.eclipse.jdt.internal.ui.javaeditor.EditorHighlightingSynchronizer;
import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
import org.eclipse.jdt.internal.ui.text.correction.AssistContext;
import org.eclipse.jdt.internal.ui.text.correction.CorrectionCommandHandler;
import org.eclipse.jdt.internal.ui.text.correction.CorrectionMessages;
import org.eclipse.jdt.internal.ui.text.correction.ICommandAccess;


/**
 * A template proposal.
 */
public class LinkedNamesAssistProposal implements IJavaCompletionProposal, ICompletionProposalExtension2, ICompletionProposalExtension6, ICommandAccess {

  /**
   * An exit policy that skips Backspace and Delete at the beginning and at the end
   * of a linked position, respectively.
   *
   * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=183925 .
   */
  public static class DeleteBlockingExitPolicy implements IExitPolicy {
    private IDocument fDocument;

    public DeleteBlockingExitPolicy(IDocument document) {
      fDocument= document;
    }

    public ExitFlags doExit(LinkedModeModel model, VerifyEvent event, int offset, int length) {
      if (length == 0 && (event.character == SWT.BS || event.character == SWT.DEL)) {
        LinkedPosition position= model.findPosition(new LinkedPosition(fDocument, offset, 0, LinkedPositionGroup.NO_STOP));
        if (position != null) {
          if (event.character == SWT.BS) {
            if (offset - 1 < position.getOffset()) {
              //skip backspace at beginning of linked position
              event.doit= false;
            }
          } else /* event.character == SWT.DEL */ {
            if (offset + 1 > position.getOffset() + position.getLength()) {
              //skip delete at end of linked position
              event.doit= false;
            }
          }
        }
      }

      return null; // don't change behavior
    }
  }


  public static final String ASSIST_ID= "org.eclipse.jdt.ui.correction.renameInFile.assist"; //$NON-NLS-1$

  private SimpleName fNode;
  private IInvocationContext fContext;
  private String fLabel;
  private String fValueSuggestion;
  private int fRelevance;

  public LinkedNamesAssistProposal(IInvocationContext context, SimpleName node) {
    this(CorrectionMessages.LinkedNamesAssistProposal_description, context, node, null);
  }

  public LinkedNamesAssistProposal(String label, IInvocationContext context, SimpleName node, String valueSuggestion) {
    fLabel= label;
    fNode= node;
    fContext= context;
    fValueSuggestion= valueSuggestion;
    fRelevance= 8;
  }

  /* (non-Javadoc)
   * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer, char, int, int)
   */
  public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {
    try {
      Point seletion= viewer.getSelectedRange();

      // get full ast
      CompilationUnit root= SharedASTProvider.getAST(fContext.getCompilationUnit(), SharedASTProvider.WAIT_YES, null);

      ASTNode nameNode= NodeFinder.perform(root, fNode.getStartPosition(), fNode.getLength());
      final int pos= fNode.getStartPosition();

      ASTNode[] sameNodes;
      if (nameNode instanceof SimpleName) {
        sameNodes= LinkedNodeFinder.findByNode(root, (SimpleName) nameNode);
      } else {
        sameNodes= new ASTNode[] { nameNode };
      }

      // sort for iteration order, starting with the node @ offset
      Arrays.sort(sameNodes, new Comparator() {

        public int compare(Object o1, Object o2) {
          return rank((ASTNode) o1) - rank((ASTNode) o2);
        }

        /**
         * Returns the absolute rank of an <code>ASTNode</code>. Nodes
         * preceding <code>offset</code> are ranked last.
         *
         * @param node the node to compute the rank for
         * @return the rank of the node with respect to the invocation offset
         */
        private int rank(ASTNode node) {
          int relativeRank= node.getStartPosition() + node.getLength() - pos;
          if (relativeRank < 0)
            return Integer.MAX_VALUE + relativeRank;
          else
            return relativeRank;
        }

      });

      IDocument document= viewer.getDocument();
      LinkedPositionGroup group= new LinkedPositionGroup();
      for (int i= 0; i < sameNodes.length; i++) {
        ASTNode elem= sameNodes[i];
        group.addPosition(new LinkedPosition(document, elem.getStartPosition(), elem.getLength(), i));
      }

      LinkedModeModel model= new LinkedModeModel();
      model.addGroup(group);
      model.forceInstall();
      if (fContext instanceof AssistContext) {
        IEditorPart editor= ((AssistContext)fContext).getEditor();
        if (editor instanceof JavaEditor) {
          model.addLinkingListener(new EditorHighlightingSynchronizer((JavaEditor) editor));
        }
      }

      LinkedModeUI ui= new EditorLinkedModeUI(model, viewer);
      ui.setExitPolicy(new DeleteBlockingExitPolicy(document));
      ui.setExitPosition(viewer, offset, 0, LinkedPositionGroup.NO_STOP);
      ui.enter();

      if (fValueSuggestion != null) {
        document.replace(nameNode.getStartPosition(), nameNode.getLength(), fValueSuggestion);
        IRegion selectedRegion= ui.getSelectedRegion();
        seletion= new Point(selectedRegion.getOffset(), fValueSuggestion.length());
      }

      viewer.setSelectedRange(seletion.x, seletion.y); // by default full word is selected, restore original selection

    } catch (BadLocationException e) {
      JavaPlugin.log(e);
    }
  }

  /*
   * @see ICompletionProposal#apply(IDocument)
   */
  public void apply(IDocument document) {
    // can't do anything
  }

  /*
   * @see ICompletionProposal#getSelection(IDocument)
   */
  public Point getSelection(IDocument document) {
    return null;
  }

  /*
   * @see ICompletionProposal#getAdditionalProposalInfo()
   */
  public String getAdditionalProposalInfo() {
    return CorrectionMessages.LinkedNamesAssistProposal_proposalinfo;
  }

  /*
   * @see ICompletionProposal#getDisplayString()
   */
  public String getDisplayString() {
    String shortCutString= CorrectionCommandHandler.getShortCutString(getCommandId());
    if (shortCutString != null) {
      return Messages.format(CorrectionMessages.ChangeCorrectionProposal_name_with_shortcut, new String[] { fLabel, shortCutString });
    }
    return fLabel;
  }

  /* (non-Javadoc)
   * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension6#getStyledDisplayString()
   */
  public StyledString getStyledDisplayString() {
    StyledString str= new StyledString(fLabel);

    String shortCutString= CorrectionCommandHandler.getShortCutString(getCommandId());
    if (shortCutString != null) {
      String decorated= Messages.format(CorrectionMessages.ChangeCorrectionProposal_name_with_shortcut, new String[] { fLabel, shortCutString });
      return StyledCellLabelProvider.styleDecoratedString(decorated, StyledString.QUALIFIER_STYLER, str);
    }
    return str;
  }

  /*
   * @see ICompletionProposal#getImage()
   */
  public Image getImage() {
    return JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_LINKED_RENAME);
  }

  /*
   * @see ICompletionProposal#getContextInformation()
   */
  public IContextInformation getContextInformation() {
    return null;
  }

  /*
   * @see IJavaCompletionProposal#getRelevance()
   */
  public int getRelevance() {
    return fRelevance;
  }


  /* (non-Javadoc)
   * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(org.eclipse.jface.text.ITextViewer, boolean)
   */
  public void selected(ITextViewer textViewer, boolean smartToggle) {
  }

  /* (non-Javadoc)
   * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected(org.eclipse.jface.text.ITextViewer)
   */
  public void unselected(ITextViewer textViewer) {
  }

  /* (non-Javadoc)
   * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate(org.eclipse.jface.text.IDocument, int, org.eclipse.jface.text.DocumentEvent)
   */
  public boolean validate(IDocument document, int offset, DocumentEvent event) {
    return false;
  }

  /* (non-Javadoc)
   * @see org.eclipse.jdt.internal.ui.text.correction.IShortcutProposal#getProposalId()
   */
  public String getCommandId() {
    return ASSIST_ID;
  }

  public void setRelevance(int relevance) {
    fRelevance= relevance;
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.