blob: 700d15986e9621fda4809175bbcee5fe3afec2f0 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2010 Soyatec (http://www.soyatec.com) 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:
* Soyatec - initial API and implementation
*******************************************************************************/
package org.eclipse.xwt.vex;
import java.lang.reflect.Method;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Point;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
import org.eclipse.xwt.vex.toolpalette.ContextType;
import org.w3c.dom.Node;
public class VEXTextEditorHelper {
public static int getOffsetAtPoint(ITextViewer textViewer, Point absolutePosition) {
StyledText styledText = textViewer.getTextWidget();
Point relativePosition = styledText.toControl(absolutePosition);
try {
Method method = StyledText.class.getDeclaredMethod("getOffsetAtPoint", int.class, int.class, int[].class, boolean.class);
method.setAccessible(true);
int[] trailing = new int[1];
int widgetOffset = (Integer) method.invoke(styledText, relativePosition.x, relativePosition.y, trailing, false);
widgetOffset += trailing[0];
return widgetOffset;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static IDOMNode getCurrentNode(ITextViewer textViewer, Point absolutePosition) {
return getNode(textViewer, getOffsetAtPoint(textViewer, absolutePosition));
}
public static IDOMNode getNode(ITextViewer textViewer, int documentPosition) {
return (IDOMNode) ContentAssistUtils.getNodeAt(textViewer, documentPosition);
}
/**
* find the car
*
* @param textViewer
* @param contextType
* @return
*/
public static int findContextTypeOffset(ITextViewer textViewer, ContextType contextType) {
int documentPosition = textViewer.getTextWidget().getCaretOffset();
return findContextTypeOffset(textViewer, documentPosition, contextType);
}
public static int findContextTypeOffset(ITextViewer textViewer, int documentPosition, ContextType contextType) {
Node node = getNode(textViewer, documentPosition);
ITextRegion completionRegion = getCompletionRegion(documentPosition, node);
System.out.println(completionRegion.getStart() + ", " + completionRegion.getEnd() + ", " + completionRegion.getLength());
String regionType = completionRegion.getType();
return documentPosition;
}
public static ContextType getCurrentContextType(ITextViewer textViewer) {
int documentPosition = textViewer.getTextWidget().getCaretOffset();
return getContextType(textViewer, documentPosition);
}
public static ContextType getContextType(ITextViewer textViewer, int documentPosition) {
Node node = getNode(textViewer, documentPosition);
ITextRegion completionRegion = getCompletionRegion(documentPosition, node);
System.out.println(completionRegion.getStart() + ", " + completionRegion.getEnd() + ", " + completionRegion.getLength());
String regionType = completionRegion.getType();
IStructuredDocumentRegion sdRegion = ContentAssistUtils.getStructuredDocumentRegion(textViewer, documentPosition);
return ContextType.NONE;
}
static public ITextRegion getCompletionRegion(int documentPosition, Node domnode) {
if (domnode == null) {
return null;
}
ITextRegion region = null;
int offset = documentPosition;
IStructuredDocumentRegion flatNode = null;
IDOMNode node = (IDOMNode) domnode;
if (node.getNodeType() == Node.DOCUMENT_NODE) {
if (node.getStructuredDocument().getLength() == 0) {
return null;
}
ITextRegion result = node.getStructuredDocument().getRegionAtCharacterOffset(offset).getRegionAtCharacterOffset(offset);
while (result == null) {
offset--;
result = node.getStructuredDocument().getRegionAtCharacterOffset(offset).getRegionAtCharacterOffset(offset);
}
return result;
}
IStructuredDocumentRegion startTag = node.getStartStructuredDocumentRegion();
IStructuredDocumentRegion endTag = node.getEndStructuredDocumentRegion();
// Determine if the offset is within the start
// IStructuredDocumentRegion, end IStructuredDocumentRegion, or
// somewhere within the Node's XML content.
if ((startTag != null) && (startTag.getStartOffset() <= offset) && (offset < startTag.getStartOffset() + startTag.getLength())) {
flatNode = startTag;
} else if ((endTag != null) && (endTag.getStartOffset() <= offset) && (offset < endTag.getStartOffset() + endTag.getLength())) {
flatNode = endTag;
}
if (flatNode != null) {
// the offset is definitely within the start or end tag, continue
// on and find the region
region = getCompletionRegion(offset, flatNode);
} else {
// the docPosition is neither within the start nor the end, so it
// must be content
flatNode = node.getStructuredDocument().getRegionAtCharacterOffset(offset);
// (pa) ITextRegion refactor
// if (flatNode.contains(documentPosition)) {
if ((flatNode.getStartOffset() <= documentPosition) && (flatNode.getEndOffset() >= documentPosition)) {
// we're interesting in completing/extending the previous
// IStructuredDocumentRegion if the current
// IStructuredDocumentRegion isn't plain content or if it's
// preceded by an orphan '<'
if ((offset == flatNode.getStartOffset()) && (flatNode.getPrevious() != null) && (((flatNode.getRegionAtCharacterOffset(documentPosition) != null) && (flatNode.getRegionAtCharacterOffset(documentPosition).getType() != DOMRegionContext.XML_CONTENT)) || (flatNode.getPrevious().getLastRegion().getType() == DOMRegionContext.XML_TAG_OPEN) || (flatNode.getPrevious().getLastRegion().getType() == DOMRegionContext.XML_END_TAG_OPEN))) {
// Is the region also the start of the node? If so, the
// previous IStructuredDocumentRegion is
// where to look for a useful region.
region = flatNode.getPrevious().getLastRegion();
} else if (flatNode.getEndOffset() == documentPosition) {
region = flatNode.getLastRegion();
} else {
region = flatNode.getFirstRegion();
}
} else {
// catch end of document positions where the docPosition isn't
// in a IStructuredDocumentRegion
region = flatNode.getLastRegion();
}
}
return region;
}
static protected ITextRegion getCompletionRegion(int offset, IStructuredDocumentRegion sdRegion) {
ITextRegion region = sdRegion.getRegionAtCharacterOffset(offset);
if (region == null) {
return null;
}
if (sdRegion.getStartOffset(region) == offset) {
// The offset is at the beginning of the region
if ((sdRegion.getStartOffset(region) == sdRegion.getStartOffset()) && (sdRegion.getPrevious() != null) && (!sdRegion.getPrevious().isEnded())) {
// Is the region also the start of the node? If so, the
// previous IStructuredDocumentRegion is
// where to look for a useful region.
region = sdRegion.getPrevious().getRegionAtCharacterOffset(offset - 1);
} else {
// Is there no separating whitespace from the previous region?
// If not,
// then that region is the important one
ITextRegion previousRegion = sdRegion.getRegionAtCharacterOffset(offset - 1);
if ((previousRegion != null) && (previousRegion != region) && (previousRegion.getTextLength() == previousRegion.getLength())) {
region = previousRegion;
}
}
} else {
// The offset is NOT at the beginning of the region
if (offset > sdRegion.getStartOffset(region) + region.getTextLength()) {
// Is the offset within the whitespace after the text in this
// region?
// If so, use the next region
ITextRegion nextRegion = sdRegion.getRegionAtCharacterOffset(sdRegion.getStartOffset(region) + region.getLength());
if (nextRegion != null) {
region = nextRegion;
}
} else {
// Is the offset within the important text for this region?
// If so, then we've already got the right one.
}
}
// valid WHITE_SPACE region handler (#179924)
if ((region != null) && (region.getType() == DOMRegionContext.WHITE_SPACE)) {
ITextRegion previousRegion = sdRegion.getRegionAtCharacterOffset(sdRegion.getStartOffset(region) - 1);
if (previousRegion != null) {
region = previousRegion;
}
}
return region;
}
}