/*******************************************************************************
* Copyright (c) 2009, 2010 Innovation Gate GmbH.
* 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:
* Innovation Gate GmbH - initial API and implementation
******************************************************************************/
package de.innovationgate.eclipse.editors.tml;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.core.resources.IFile;
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.TextSelection;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import org.eclipse.jface.viewers.ISelection;
import de.innovationgate.eclipse.editors.Plugin;
import de.innovationgate.eclipse.editors.config.TMLTag;
import de.innovationgate.eclipse.editors.config.TMLTagAttribute;
import de.innovationgate.eclipse.editors.config.TMLTagDefinitions;
import de.innovationgate.eclipse.editors.tmlscript.TMLScriptPartitionScanner;
import de.innovationgate.eclipse.utils.wga.WGADesignStructureHelper;
import de.innovationgate.wga.model.VersionCompliance;
public class TMLContentAssistProcessor implements IContentAssistProcessor {
private String _errorMessage;
private CloseTagContentAssistProcessor _closeTagProcessor;
private ITextViewer _viewer;
private TMLScriptContentAssistProcessor _tmlScriptProcessor;
public TMLContentAssistProcessor() {
_closeTagProcessor = new CloseTagContentAssistProcessor();
_tmlScriptProcessor = new TMLScriptContentAssistProcessor();
}
public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
List<ICompletionProposal> proposals = new ArrayList<ICompletionProposal>();
_viewer = viewer;
setErrorMessage(null);
IDocument document = viewer.getDocument();
try {
IRegion region = determineRelatedRegion(offset, document);
if (document.getContentType(region.getOffset()).equals(TMLPartitionScanner.TML_TAG_START)) {
TMLRegion tmlRegion = TMLRegion.parse(region, document, offset);
ICompletionProposal[] tmlProposals = tmlRegion.createProposals(viewer, Plugin.getDefault().getActiveFile());
if (tmlProposals != null) {
proposals.addAll(Arrays.asList(tmlProposals));
}
// already called in tmlRegion
/*
if (!tmlRegion.isCursorInAttributeValue()) {
ICompletionProposal[] closeProposals = _closeTagProcessor.computeCompletionProposals(viewer, offset);
if (closeProposals != null) {
proposals.addAll(Arrays.asList(closeProposals));
}
}*/
} else {
// workaround for tmlscript partitions with length 1: <tml:script>c[raisecodecompletion]</tml:script>
if (offset > 0 && document.getContentType(offset - 1).equals(TMLScriptPartitionScanner.TMLSCRIPT)) {
return _tmlScriptProcessor.computeCompletionProposals(viewer, offset);
} else {
return _closeTagProcessor.computeCompletionProposals(viewer, offset);
}
}
} catch (ParseException e) {
setErrorMessage(e.getMessage());
} catch (BadLocationException e) {
setErrorMessage(e.getMessage());
}
return proposals.toArray(new ICompletionProposal[0]);
}
public static IRegion determineRelatedRegion(int offset, IDocument document) throws BadLocationException {
IRegion region = document.getPartition(offset);
// partition length might be 0 - try previous region
if (region.getLength() == 0) {
region = document.getPartition(offset - 1);
}
// fallback to current edit line if partition has length 0 - for e.g. end of document
if (region.getLength() == 0) {
region = document.getLineInformationOfOffset(offset);
}
return region;
}
private void setErrorMessage(String message) {
_errorMessage = message;
}
public IContextInformation[] computeContextInformation(ITextViewer viewer,
int offset) {
return null;
}
public char[] getCompletionProposalAutoActivationCharacters() {
char [] alphaNumericControls = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '<', '>', '/', ':', ' ', '\r'};
char [] alphaNumericControlsNoEnter = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '<', '>', '/', ':', ' '};
/**
* in tml-start-tag partionions 'ENTER' and ' ' will be a valid auto activation char
*/
if (_viewer != null) {
try {
IDocument document = _viewer.getDocument();
ISelection selection =_viewer.getSelectionProvider().getSelection();
if (selection instanceof TextSelection) {
TextSelection textSelection = (TextSelection) selection;
int offset = textSelection.getOffset();
IRegion region = document.getPartition(offset);
boolean sameLine = document.getLineOfOffset(region.getOffset()) == document.getLineOfOffset(offset);
if (document.getContentType(region.getOffset()).equals(TMLPartitionScanner.TML_TAG_START)) {
TMLRegion tmlInfo = TMLRegion.parse(region, document, offset);
if (tmlInfo.isCursorInTagName()) {
return alphaNumericControlsNoEnter;
} else if (tmlInfo.isCursorInAttributeValue()) {
// check if attribute is tmlscript expression
IFile activeFile = Plugin.getDefault().getActiveFile();
String tagName = tmlInfo.getTagName();
if (activeFile != null && tagName != null) {
VersionCompliance versionCompliance = WGADesignStructureHelper.getWGAVersionCompliance(activeFile);
if (versionCompliance != null) {
TMLTag tag = TMLTagDefinitions.getInstance(versionCompliance).getTagByName(tagName);
if (tag != null) {
String attributeAtCursor = tmlInfo.getAttributeAtCursor();
if (attributeAtCursor != null) {
TMLTagAttribute attribute = tag.getAttribute(attributeAtCursor);
if (attribute != null && attribute.isTmlscriptExpression()) {
return _tmlScriptProcessor.getCompletionProposalAutoActivationCharacters();
}
}
}
}
}
return alphaNumericControls;
} else {
return alphaNumericControls;
}
} else if (document.getContentType(region.getOffset()).equals(IDocument.DEFAULT_CONTENT_TYPE) && sameLine) {
return alphaNumericControlsNoEnter;
}
}
} catch (BadLocationException e) {
} catch (ParseException e) {
}
}
return new char[] { ':'};
}
public char[] getContextInformationAutoActivationCharacters() {
return null;
}
public IContextInformationValidator getContextInformationValidator() {
return null;
}
public String getErrorMessage() {
return _errorMessage;
}
}