package org.simantics.scl.ui.editor.completion; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.DefaultInformationControl; import org.eclipse.jface.text.DocumentEvent; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IInformationControl; import org.eclipse.jface.text.IInformationControlCreator; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.text.contentassist.ICompletionProposalExtension; import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2; import org.eclipse.jface.text.contentassist.ICompletionProposalExtension3; import org.eclipse.jface.text.contentassist.ICompletionProposalExtension4; import org.eclipse.jface.text.contentassist.ICompletionProposalExtension5; import org.eclipse.jface.text.contentassist.IContextInformation; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Shell; import org.simantics.scl.compiler.elaboration.modules.SCLValue; import org.simantics.scl.ui.Activator; public class SCLCompletionProposal implements ICompletionProposal, ICompletionProposalExtension, ICompletionProposalExtension2, ICompletionProposalExtension3, ICompletionProposalExtension4, ICompletionProposalExtension5 { private static final Image PRIVATE = Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/private_co.gif").createImage(); //$NON-NLS-1$ //$NON-NLS-2$ private static final Image PUBLIC = Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/public_co.gif").createImage(); //$NON-NLS-1$ //$NON-NLS-2$ private static final Image CONST = Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/container_obj.gif").createImage(); //$NON-NLS-1$ //$NON-NLS-2$ private static final Image TYPE = Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/typedef_obj.gif").createImage(); //$NON-NLS-1$ //$NON-NLS-2$ private final String content; private final String name; private final String module; private final String documentation; private int replacementOffset; private String prefix; private final SCLCompletionType completionType; public SCLCompletionProposal(SCLValue value, int replacementOffset, String prefix) { String tempName = value.getName().name; String tempModule = value.getName().module; int p = tempName.lastIndexOf('.'); if(p >= 0) { tempModule = tempModule + "." + tempName.substring(0, p); //$NON-NLS-1$ tempName = tempName.substring(p+1); } this.name = tempName; this.module = tempModule; this.documentation = value.getDocumentation(); this.content = name + " :: " + value.getType() + " (" + module + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ this.replacementOffset = replacementOffset; this.prefix = prefix; // System.out.println(prefix); if (value.isPrivate()) this.completionType = SCLCompletionType.PRIVATE; else this.completionType = SCLCompletionType.PUBLIC; } public SCLCompletionProposal(String name, String module, SCLCompletionType completionType, int replacementOffset, String prefix) { this.name = name; this.module = module; this.content = name + " (" + module + ")"; //$NON-NLS-1$ //$NON-NLS-2$ this.documentation = null; this.replacementOffset = replacementOffset; this.prefix = prefix; this.completionType = completionType; } @Override public void apply(IDocument document) { } @Override public Point getSelection(IDocument document) { return new Point(replacementOffset + getName().length(), 0); } @Override public String getAdditionalProposalInfo() { return documentation; } @Override public String getDisplayString() { return content; } @Override public Image getImage() { switch (completionType) { case PRIVATE: return PRIVATE; case PUBLIC: return PUBLIC; case CONST: return CONST; case TYPE: return TYPE; default: return null; } } @Override public IContextInformation getContextInformation() { return null; } @Override public void apply(IDocument document, char trigger, int offset) { } @Override public boolean isValidFor(IDocument document, int offset) { return validate(document, offset, null); } @Override public char[] getTriggerCharacters() { return null; } @Override public int getContextInformationPosition() { return 0; } @Override public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) { try { // String replacement = getName().substring(offset - replacementOffset); IDocument doc = viewer.getDocument(); Point p = viewer.getSelectedRange(); // System.out.println("selectedRange : " + p); // System.out.println("prefix : " + prefix); // int start = offset - prefix.length(); // int end = prefix.length(); // System.out.println("start : " + start + ", end : " + end); // String sadd = doc.get(start, end); // System.out.println("toReplace : " + sadd); if (p.y > 0) { doc.replace(p.x, p.y, ""); //$NON-NLS-1$ doc.replace(offset, 0, getName()); } else { String currentText = doc.get(offset - prefix.length(), prefix.length()); if (currentText.equals(getName())) return; doc.replace(offset - prefix.length(), prefix.length(), ""); //$NON-NLS-1$ doc.replace(offset - prefix.length(), 0, getName()); } } catch (BadLocationException x) { x.printStackTrace(); } } @Override public void selected(ITextViewer viewer, boolean smartToggle) { } @Override public void unselected(ITextViewer viewer) { } @Override public boolean validate(IDocument document, int offset, DocumentEvent event) { try { String n = getName(); //System.out.println(n + " (" + n.length() + ") " + replacementOffset + " " + offset); boolean a = offset >= replacementOffset; boolean b = offset <= replacementOffset + n.length(); String s = document.get(replacementOffset, offset - replacementOffset); prefix = s; //System.out.println("prefix: " + s + " - " + prefix); boolean c = n.toLowerCase().startsWith(s.toLowerCase()); //System.out.println("matches: " + a + " " + b + " " + c); return a && b && c; } catch (BadLocationException x) { //x.printStackTrace(); return false; } } @Override public IInformationControlCreator getInformationControlCreator() { return CREATOR; } private static final IInformationControlCreator CREATOR = new IInformationControlCreator() { @Override public IInformationControl createInformationControl(Shell parent) { return new DefaultInformationControl(parent); } }; @Override public CharSequence getPrefixCompletionText(IDocument document, int completionOffset) { return getName(); } @Override public int getPrefixCompletionStart(IDocument document, int completionOffset) { return replacementOffset - prefix.length(); } @Override public boolean isAutoInsertable() { return true; } @Override public Object getAdditionalProposalInfo(IProgressMonitor monitor) { return documentation; } public String getName() { return name; } public boolean isPrivate() { return SCLCompletionType.PRIVATE == completionType; } public String getModule() { return module; } }