blob: 5aee21f2e21327efc975c2b42631c69a04ae86a7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2004 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
* Jens Lukowski/Innoopract - initial renaming/restructuring
*
*******************************************************************************/
package org.eclipse.wst.xml.ui.doubleclick;
import org.eclipse.jface.text.DefaultTextDoubleClickStrategy;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.swt.graphics.Point;
import org.eclipse.wst.sse.core.IStructuredModel;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.text.ITextRegion;
import org.eclipse.wst.sse.ui.StructuredTextViewer;
import org.eclipse.wst.xml.core.parser.XMLRegionContext;
import org.w3c.dom.Node;
public class XMLDoubleClickStrategy extends DefaultTextDoubleClickStrategy {
protected static final char DOUBLE_QUOTE = '\"';
protected static final char SINGLE_QUOTE = '\'';
protected static final char SPACE = ' ';
protected int fCaretPosition = -1;
protected int fDoubleClickCount = 0;
protected Node fNode = null;
protected IStructuredDocumentRegion fStructuredDocumentRegion = null;
protected String fStructuredDocumentRegionText = ""; //$NON-NLS-1$
protected IStructuredModel fStructuredModel = null;
protected StructuredTextViewer fStructuredTextViewer;
protected ITextRegion fTextRegion = null;
public void doubleClicked(ITextViewer textViewer) {
if (textViewer instanceof StructuredTextViewer) {
fStructuredTextViewer = (StructuredTextViewer) textViewer;
try {
fStructuredModel = StructuredModelManager.getModelManager().getExistingModelForRead(fStructuredTextViewer.getDocument());
if (fStructuredModel != null) {
int caretPosition = textViewer.getSelectedRange().x;
if (caretPosition < 0)
return;
fNode = (Node) fStructuredModel.getIndexedRegion(caretPosition);
if (fNode == null)
return;
updateDoubleClickCount(caretPosition);
updateStructuredDocumentRegion();
updateTextRegion();
if (fNode.getNodeType() == Node.TEXT_NODE)
processTextDoubleClicked();
else
processElementDoubleClicked();
}
} finally {
if (fStructuredModel != null)
fStructuredModel.releaseFromRead();
}
}
}
protected Point getWord(String string, int cursor) {
if (string == null)
return null;
int wordStart = 0;
int wordEnd = string.length();
wordStart = string.lastIndexOf(SPACE, cursor - 1);
int temp = string.lastIndexOf(SINGLE_QUOTE, cursor - 1);
wordStart = Math.max(wordStart, temp);
temp = string.lastIndexOf(DOUBLE_QUOTE, cursor - 1);
wordStart = Math.max(wordStart, temp);
if (wordStart == -1)
wordStart = cursor;
else
wordStart++;
wordEnd = string.indexOf(SPACE, cursor);
if (wordEnd == -1)
wordEnd = string.length();
temp = string.indexOf(SINGLE_QUOTE, cursor);
if (temp == -1)
temp = string.length();
wordEnd = Math.min(wordEnd, temp);
temp = string.indexOf(DOUBLE_QUOTE, cursor);
if (temp == -1)
temp = string.length();
wordEnd = Math.min(wordEnd, temp);
if (wordEnd == string.length())
wordEnd = cursor;
if ((wordStart == wordEnd) && !isQuoted(string)) {
wordStart = 0;
wordEnd = string.length();
}
return new Point(wordStart, wordEnd);
}
protected boolean isQuoted(String string) {
if ((string == null) || (string.length() < 2))
return false;
int lastIndex = string.length() - 1;
char firstChar = string.charAt(0);
char lastChar = string.charAt(lastIndex);
return (((firstChar == SINGLE_QUOTE) && (lastChar == SINGLE_QUOTE)) || ((firstChar == DOUBLE_QUOTE) && (lastChar == DOUBLE_QUOTE)));
}
protected void processElementAttrEqualsDoubleClicked2Times() {
int prevRegionOffset = fStructuredDocumentRegion.getStartOffset(fTextRegion) - 1;
ITextRegion prevRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(prevRegionOffset);
int nextRegionOffset = fStructuredDocumentRegion.getEndOffset(fTextRegion);
ITextRegion nextRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(nextRegionOffset);
if ((prevRegion != null) && (prevRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME) && (nextRegion != null) && (nextRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE)) {
fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(prevRegion), nextRegion.getTextEnd() - prevRegion.getStart());
}
}
protected void processElementAttrNameDoubleClicked2Times() {
int nextRegionOffset = fStructuredDocumentRegion.getEndOffset(fTextRegion);
ITextRegion nextRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(nextRegionOffset);
if (nextRegion != null) {
nextRegionOffset = fStructuredDocumentRegion.getEndOffset(nextRegion);
nextRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(nextRegionOffset);
if ((nextRegion != null) && (nextRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE)) {
fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(fTextRegion), nextRegion.getTextEnd() - fTextRegion.getStart());
} else {
// attribute has no value
fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart(), fStructuredDocumentRegion.getLength());
fDoubleClickCount = 0;
}
}
}
protected void processElementAttrValueDoubleClicked() {
String regionText = fStructuredDocumentRegion.getText(fTextRegion);
if (fDoubleClickCount == 1) {
Point word = getWord(regionText, fCaretPosition - fStructuredDocumentRegion.getStartOffset(fTextRegion));
if (word.x == word.y) { // no word found; select whole region
fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(fTextRegion), regionText.length());
fDoubleClickCount++;
} else
fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(fTextRegion) + word.x, word.y - word.x);
} else if (fDoubleClickCount == 2) {
if (isQuoted(regionText)) {
// ==> // Point word = getWord(regionText, fCaretPosition -
// fStructuredDocumentRegion.getStartOffset(fTextRegion));
fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(fTextRegion), regionText.length());
} else
processElementAttrValueDoubleClicked2Times();
} else if (fDoubleClickCount == 3) {
if (isQuoted(regionText))
processElementAttrValueDoubleClicked2Times();
else {
fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart(), fStructuredDocumentRegion.getLength());
fDoubleClickCount = 0;
}
} else { // fDoubleClickCount == 4
fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart(), fStructuredDocumentRegion.getLength());
fDoubleClickCount = 0;
}
}
protected void processElementAttrValueDoubleClicked2Times() {
int prevRegionOffset = fStructuredDocumentRegion.getStartOffset(fTextRegion) - 1;
ITextRegion prevRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(prevRegionOffset);
if (prevRegion != null) {
prevRegionOffset = fStructuredDocumentRegion.getStartOffset(prevRegion) - 1;
prevRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(prevRegionOffset);
if ((prevRegion != null) && (prevRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME)) {
fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(prevRegion), fTextRegion.getTextEnd() - prevRegion.getStart());
}
}
}
protected void processElementDoubleClicked() {
if (fTextRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE)
processElementAttrValueDoubleClicked(); // special handling for
// XML_TAG_ATTRIBUTE_VALUE
else {
if (fDoubleClickCount == 1) {
fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart() + fTextRegion.getStart(), fTextRegion.getTextLength());
} else if (fDoubleClickCount == 2) {
if (fTextRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME)
processElementAttrNameDoubleClicked2Times();
else if (fTextRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_EQUALS)
processElementAttrEqualsDoubleClicked2Times();
else {
fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart(), fStructuredDocumentRegion.getLength());
fDoubleClickCount = 0;
}
} else { // fDoubleClickCount == 3
fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart(), fStructuredDocumentRegion.getLength());
fDoubleClickCount = 0;
}
}
}
protected void processTextDoubleClicked() {
if (fDoubleClickCount == 1) {
super.doubleClicked(fStructuredTextViewer);
Point selectedRange = fStructuredTextViewer.getSelectedRange();
if ((selectedRange.x == fStructuredDocumentRegion.getStartOffset(fTextRegion)) && (selectedRange.y == fTextRegion.getTextLength()))
// only one word in region, skip one level of double click
// selection
fDoubleClickCount++;
} else if (fDoubleClickCount == 2) {
if (fTextRegion.getType() == XMLRegionContext.UNDEFINED) {
fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart(), fStructuredDocumentRegion.getLength());
fDoubleClickCount = 0;
} else {
if (isQuoted(fStructuredDocumentRegion.getFullText(fTextRegion)))
fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(fTextRegion) + 1, fTextRegion.getTextLength() - 2);
else
fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(fTextRegion), fTextRegion.getTextLength());
}
} else {
if ((fDoubleClickCount == 3) && isQuoted(fStructuredDocumentRegion.getFullText(fTextRegion)))
fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(fTextRegion), fTextRegion.getTextLength());
else {
if ((fDoubleClickCount == 3) && isQuoted(fStructuredDocumentRegionText))
fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart() + 1, fStructuredDocumentRegion.getLength() - 2);
else {
fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart(), fStructuredDocumentRegion.getLength());
fDoubleClickCount = 0;
}
}
}
}
public void setModel(IStructuredModel structuredModel) {
fStructuredModel = structuredModel;
}
protected void updateDoubleClickCount(int caretPosition) {
if (fCaretPosition == caretPosition) {
if (fStructuredDocumentRegion != null)
fDoubleClickCount++;
else
fDoubleClickCount = 1;
} else {
fCaretPosition = caretPosition;
fDoubleClickCount = 1;
}
}
protected void updateStructuredDocumentRegion() {
fStructuredDocumentRegion = fStructuredModel.getStructuredDocument().getRegionAtCharacterOffset(fCaretPosition);
if (fStructuredDocumentRegion != null)
fStructuredDocumentRegionText = fStructuredDocumentRegion.getText();
else
fStructuredDocumentRegionText = ""; //$NON-NLS-1$
}
protected void updateTextRegion() {
if (fStructuredDocumentRegion != null) {
fTextRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(fCaretPosition);
// if fTextRegion is null, it means we are at just past the last
// fStructuredDocumentRegion,
// at the very end of the document, so we'll use the last text
// region in the document
if (fTextRegion == null) {
fTextRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(fCaretPosition - 1);
}
} else
fTextRegion = null;
}
}