Package org.eclipse.wst.xml.ui.internal.contentassist

Source Code of org.eclipse.wst.xml.ui.internal.contentassist.MarkupCompletionProposal

/*******************************************************************************
* Copyright (c) 2012 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.wst.xml.ui.internal.contentassist;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
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.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.ui.texteditor.link.EditorLinkedModeUI;
import org.eclipse.wst.sse.ui.internal.contentassist.CustomCompletionProposal;
import org.eclipse.wst.xml.ui.internal.Logger;

/**
* A completion proposal that is capable of establishing linked positions within
* inserted markup.
*
*/
public class MarkupCompletionProposal extends CustomCompletionProposal {

  private IRegion fSelectedRegion = null;

  public MarkupCompletionProposal(String replacementString, int replacementOffset, int replacementLength, int cursorPosition, Image image, String displayString, IContextInformation contextInformation, String additionalProposalInfo, int relevance) {
    super(replacementString, replacementOffset, replacementLength, cursorPosition, image, displayString, contextInformation, additionalProposalInfo, relevance);
  }

  public MarkupCompletionProposal(String replacementString, int replacementOffset, int replacementLength, int cursorPosition, Image image, String displayString, IContextInformation contextInformation, String additionalProposalInfo, int relevance, boolean updateReplacementLengthOnValidate) {
    super(replacementString, replacementOffset, replacementLength, cursorPosition, image, displayString, null, contextInformation, additionalProposalInfo, relevance, updateReplacementLengthOnValidate);
  }

  public MarkupCompletionProposal(String replacementString, int replacementOffset, int replacementLength, int cursorPosition, Image image, String displayString, String alternateMatch, IContextInformation contextInformation, String additionalProposalInfo, int relevance, boolean updateReplacementLengthOnValidate) {
    super(replacementString, replacementOffset, replacementLength, cursorPosition, image, displayString, alternateMatch, contextInformation, additionalProposalInfo, relevance, updateReplacementLengthOnValidate);
  }

  public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {
    super.apply(viewer, trigger, stateMask, offset);

    getLinkedPositions(viewer);
  }

  /**
   * Sets up linked positions and installs them on the viewer.
   *
   */
  protected void getLinkedPositions(ITextViewer viewer) {
    final String replacement = getReplacementString();
    final IDocument document = viewer.getDocument();
    final int length = replacement.length();
    boolean inAttribute = false, hasGroup = false, inEndTag = false;
    int offset = 0;
    char attType = 0;
    int exitPosition = -1;
    LinkedModeModel model = new LinkedModeModel();

    try {
      for (int i = 0; i < length; i++) {
        final char c = replacement.charAt(i);
        switch (c) {
          case '=':
            break;
          case '\'':
          case '\"':
            if (!inAttribute) {
              offset = i;
              attType = c;
              inAttribute = true;
            }
            else {
              // Found matching quotes establishing an attribute value region
              if (attType == c && replacement.charAt(i - 1) != '\\') {
                inAttribute = false; // Record position length
                addPosition(model, document, getReplacementOffset() + offset + 1, i - offset - 1);
                hasGroup = true;
              }
            }
            break;
          case '/':
              if (!inAttribute) {
                inEndTag = i > 0 && replacement.charAt(i - 1) == '<';
              }
            break;
          case '>':
            if (!inAttribute) {
              if (i == length - 1) {
                exitPosition = getReplacementOffset() + i + 1;
                if (!inEndTag) { // Don't add a position within the end-tag
                  addPosition(model, document, getReplacementOffset() + i, 0); // position within start tag
                  hasGroup = true;
                }
              }
              else {
                addPosition(model, document, getReplacementOffset() + i, 0); // position within start tag
                addPosition(model, document, getReplacementOffset() + i + 1, 0); // position after start tag
                hasGroup = true;
              }
            }
            break;
        }
      }
      if (hasGroup) {
        model.forceInstall();
        final LinkedModeUI ui= new EditorLinkedModeUI(model, viewer);
        ui.setExitPosition(viewer, exitPosition < 0 ? getReplacementOffset() + getReplacementLength() + replacement.length() - 1 : exitPosition, 0, Integer.MAX_VALUE);
        ui.setCyclingMode(LinkedModeUI.CYCLE_WHEN_NO_PARENT);
        ui.setDoContextInfo(true);
        ui.enter();
        fSelectedRegion = ui.getSelectedRegion();
      }
    }
    catch (BadLocationException e) {
      Logger.logException(e);
    }
  }

  /**
   * Adds a {@link LinkedPosition} to its own position group. This group is then added to the model
   * @param model the linked model for this proposal
   * @param document the document the content assist is operating upon
   * @param offset the offset to establish the {@link LinkedPosition}
   * @param length the length of the {@link LinkedPosition}
   * @throws BadLocationException
   */
  private void addPosition(LinkedModeModel model, IDocument document, int offset, int length) throws BadLocationException {
    final LinkedPositionGroup group = new LinkedPositionGroup();
    group.addPosition(new LinkedPosition(document, offset, length, LinkedPositionGroup.NO_STOP));
    model.addGroup(group);
  }

  public Point getSelection(IDocument document) {
    // Attempt to return the selection based on the selected region from the LinkedModeUI
    if (fSelectedRegion == null)
      return super.getSelection(document);
    return new Point(fSelectedRegion.getOffset(), fSelectedRegion.getLength());
  }
}
TOP

Related Classes of org.eclipse.wst.xml.ui.internal.contentassist.MarkupCompletionProposal

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.