/*=============================================================================#
# Copyright (c) 2009-2016 Stephan Wahlbrink (WalWare.de) 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:
# Stephan Wahlbrink - initial API and implementation
#=============================================================================*/
package de.walware.statet.r.internal.ui.editors;
import java.util.List;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension6;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import de.walware.jcommons.collections.CollectionUtils;
import de.walware.ecommons.ltk.ui.sourceediting.assist.SimpleCompletionProposal;
import de.walware.statet.r.core.RSymbolComparator;
import de.walware.statet.r.core.source.RHeuristicTokenScanner;
import de.walware.statet.r.ui.RUI;
import de.walware.statet.r.ui.sourceediting.RAssistInvocationContext;
public class RSimpleCompletionProposal extends SimpleCompletionProposal {
public static class RHelpTopicCompletionProposal extends RSimpleCompletionProposal
implements ICompletionProposalExtension6 {
private final int relevance;
private Object packages;
public RHelpTopicCompletionProposal(final RAssistInvocationContext context,
final String replacementString, final Object packages, final int replacementOffset,
final int relevance) {
super(context, replacementString, replacementOffset);
this.relevance= relevance;
this.packages= packages;
}
@Override
public int getRelevance() {
return this.relevance;
}
@Override
public Image getImage() {
return RUI.getImage(RUI.IMG_OBJ_R_HELP_TOPIC);
}
@Override
public StyledString getStyledDisplayString() {
final StyledString s= new StyledString(getReplacementString());
if (this.packages != null) {
if (this.packages instanceof List) {
this.packages= CollectionUtils.toString((List<String>) this.packages, ", "); //$NON-NLS-1$
}
s.append(QUALIFIER_SEPARATOR, StyledString.QUALIFIER_STYLER);
s.append((String) this.packages, StyledString.QUALIFIER_STYLER);
}
return s;
}
}
public RSimpleCompletionProposal(final RAssistInvocationContext context,
final String replacementString, final int replacementOffset) {
super(context, replacementString, replacementOffset);
}
@Override
protected String getPluginId() {
return RUI.PLUGIN_ID;
}
@Override
protected int computeReplacementLength(final int replacementOffset, final Point selection, final int caretOffset, final boolean overwrite) {
// keep in synch with RElementCompletionProposal
final int end= Math.max(caretOffset, selection.x + selection.y);
if (overwrite) {
final RElementCompletionProposal.ApplyData data= new RElementCompletionProposal.ApplyData(
(RAssistInvocationContext) getInvocationContext() );
final RHeuristicTokenScanner scanner= data.getScanner();
scanner.configure(data.getDocument());
final IRegion word= scanner.findRWord(end, false, true);
if (word != null) {
return (word.getOffset() + word.getLength() - replacementOffset);
}
}
return (end - replacementOffset);
}
@Override
public boolean isAutoInsertable() {
return false;
}
@Override
public boolean validate(final IDocument document, final int offset, final DocumentEvent event) {
// keep in synch with RElementCompletionProposal
try {
int start= getReplacementOffset();
int length= offset - getReplacementOffset();
if (length > 0 && document.getChar(start) == '`') {
start++;
length--;
}
if (length > 0 && document.getChar(start+length-1) == '`') {
length--;
}
final String prefix= document.get(start, length);
final String replacement= getReplacementString();
if (new RSymbolComparator.PrefixPattern(prefix).matches(replacement)) {
return true;
}
}
catch (final BadLocationException e) {
// ignore concurrently modified document
}
return false;
}
}