package tk.eclipse.plugin.csseditor.editors;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.CompletionProposal;
import org.eclipse.jface.text.contentassist.ContextInformation;
import org.eclipse.jface.text.contentassist.ContextInformationValidator;
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 tk.eclipse.plugin.htmleditor.HTMLPlugin;
import tk.eclipse.plugin.htmleditor.HTMLUtil;
/**
* The implementaion of IContentAssistProcessor for the CSS Editor.
*
* @author Naoki Takezoe
*/
public class CSSAssistProcessor implements IContentAssistProcessor {
public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
List<ICompletionProposal> proposals = new LinkedList<ICompletionProposal>();
try {
IDocument document = viewer.getDocument();
// state 0 = selector
// state 1 = property name
// state 2 = property value
int colonIndex = -1;
boolean done = false;
int state = 0;
for (int currentOffset = offset - 1; !done && currentOffset > 0; currentOffset--) {
char ch = document.getChar(currentOffset);
if (ch == '}') {
state = 0;
done = true;
}
else if (ch == ':') {
colonIndex = currentOffset;
state = 2;
done = true;
}
else if (ch == ';') {
state = 1;
done = true;
}
else if (ch == '{') {
state = 1;
done = true;
}
}
if (state == 0) {
// we can't do anything right now for selector completion
}
else if (state == 1) {
int lineNumber = document.getLineOfOffset(offset);
int lineOffset = document.getLineOffset(lineNumber);
String propertyName = document.get(lineOffset, offset - lineOffset);
int replacementOffset;
for (replacementOffset = 0; replacementOffset < propertyName.length(); replacementOffset++) {
if (!Character.isWhitespace(propertyName.charAt(replacementOffset))) {
break;
}
}
String trimmedPropertyName = propertyName.trim();
if (trimmedPropertyName.length() == 0 || !propertyName.endsWith(" ")) {
char lastChar = document.getChar(offset - 1);
String lowercasePropertyName = propertyName.trim().toLowerCase();
for (CSSProperty property : CSSDefinition.PROPERTIES) {
String displayPropertyName = property.getName();
String replacementPropertyName = displayPropertyName + ": ";
if (displayPropertyName.startsWith(lowercasePropertyName)) {
proposals.add(new CompletionProposal(replacementPropertyName, lineOffset + replacementOffset, trimmedPropertyName.length(), replacementPropertyName.length(), null, displayPropertyName, null, null));
}
}
}
}
else if (state == 2) {
int lineNumber = document.getLineOfOffset(offset);
int lineOffset = document.getLineOffset(lineNumber);
String propertyName = document.get(lineOffset, colonIndex - lineOffset).trim();
CSSProperty matchingProperty = null;
for (CSSProperty property : CSSDefinition.PROPERTIES) {
if (property.getName().equalsIgnoreCase(propertyName)) {
matchingProperty = property;
}
}
if (matchingProperty != null) {
String propertyValue = document.get(colonIndex + 1, offset - colonIndex - 1);
int replacementOffset;
for (replacementOffset = 0; replacementOffset < propertyValue.length(); replacementOffset++) {
if (!Character.isWhitespace(propertyValue.charAt(replacementOffset))) {
break;
}
}
String trimmedPropertyValue = propertyValue.substring(replacementOffset);
Set<String> valueProposals = new HashSet<String>();
matchingProperty.fillInProposals(trimmedPropertyValue, valueProposals);
for (String valueProposal : valueProposals) {
String displayValueProposal = valueProposal;
String replacementValueProposal = valueProposal;
proposals.add(new CompletionProposal(replacementValueProposal, colonIndex + replacementOffset + 1, trimmedPropertyValue.length(), replacementValueProposal.length(), null, displayValueProposal, null, null));
}
}
}
// String text = getSource(viewer).substring(0, offset);
// String word = getLastWord(text);
//
// ArrayList list = new ArrayList();
// if (word != null) {
// for (int i = 0; i < CSSDefinition.CSS_KEYWORDS.length; i++) {
// if (CSSDefinition.CSS_KEYWORDS[i].getReplaceString().startsWith(word)) {
// list.add(new CompletionProposal(CSSDefinition.CSS_KEYWORDS[i].getReplaceString(), offset - word.length(), word.length(), CSSDefinition.CSS_KEYWORDS[i].getReplaceString().length(), HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_CSS_PROP), CSSDefinition.CSS_KEYWORDS[i].getDisplayString(), null, null));
// }
// }
// }
// sort
HTMLUtil.sortCompilationProposal(proposals);
// ICompletionProposal[] prop = (ICompletionProposal[]) list.toArray(new ICompletionProposal[list.size()]);
}
catch (BadLocationException e) {
HTMLPlugin.logException(e);
}
return proposals.toArray(new ICompletionProposal[proposals.size()]);
}
protected String getSource(ITextViewer viewer) {
return viewer.getDocument().get();
}
private String getLastWord(String text) {
text = HTMLUtil.cssComment2space(text);
int index1 = text.lastIndexOf(';');
int index2 = text.lastIndexOf('{');
if (index1 >= 0 && index1 > index2) {
return text.substring(index1 + 1).trim();
}
else if (index2 >= 0) {
return text.substring(index2 + 1).trim();
}
return null;
}
public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
ContextInformation[] info = new ContextInformation[0];
return info;
}
public char[] getCompletionProposalAutoActivationCharacters() {
return new char[0];
}
public char[] getContextInformationAutoActivationCharacters() {
return new char[0];
}
public String getErrorMessage() {
return "error";
}
public IContextInformationValidator getContextInformationValidator() {
return new ContextInformationValidator(this);
}
}