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); } }