blob: 5754b153d279cd5c851f4e6322cb219664938c3b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012 NumberFour AG
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* NumberFour AG - initial API and Implementation (Alex Panchenko)
*******************************************************************************/
package org.eclipse.dltk.ui.text.completion;
import org.eclipse.dltk.core.CompletionProposal;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.link.LinkedModeModel;
import org.eclipse.jface.text.link.LinkedModeUI;
import org.eclipse.jface.text.link.LinkedPosition;
import org.eclipse.jface.text.link.LinkedPositionGroup;
import org.eclipse.swt.graphics.Point;
import org.eclipse.ui.texteditor.link.EditorLinkedModeUI;
/**
* @since 4.0
*/
public abstract class LinkedModeScriptCompletionProposal extends
LazyScriptCompletionProposal {
public LinkedModeScriptCompletionProposal(CompletionProposal proposal,
ScriptContentAssistInvocationContext context) {
super(proposal, context);
}
private IRegion fSelectedRegion; // initialized by apply()
@Override
public void apply(IDocument document, char trigger, int offset) {
if (trigger == ' ' || trigger == getOpenTrigger())
trigger = '\0';
super.apply(document, trigger, offset);
final int replacementOffset = getReplacementOffset();
final int exit = replacementOffset + getReplacementString().length();
if (replacementBuffer != null && replacementBuffer.hasArguments()
&& getTextViewer() != null) {
final int cursor = getCursorPosition();
try {
LinkedModeModel model = new LinkedModeModel();
for (ReplacementBuffer.Argument region : replacementBuffer.arguments) {
LinkedPositionGroup group = new LinkedPositionGroup();
int argOffset = replacementOffset + region.offset;
if (region.relativeToCursor)
argOffset += cursor;
group.addPosition(new LinkedPosition(document, argOffset,
region.length, LinkedPositionGroup.NO_STOP));
model.addGroup(group);
}
model.forceInstall();
LinkedModeUI ui = new EditorLinkedModeUI(model, getTextViewer());
ui.setExitPosition(getTextViewer(), exit, 0, Integer.MAX_VALUE);
char exitTrigger = getExitTrigger();
if (exitTrigger != 0) {
ui.setExitPolicy(new ExitPolicy(exitTrigger, document));
}
final char[] exitTriggers = getExitTriggers();
if (exitTriggers != null) {
for (int i = 0; i < exitTriggers.length; ++i) {
ui.setExitPolicy(new ExitPolicy(exitTriggers[i],
document));
}
}
ui.setCyclingMode(LinkedModeUI.CYCLE_WHEN_NO_PARENT);
ui.enter();
fSelectedRegion = ui.getSelectedRegion();
} catch (BadLocationException e) {
}
} else {
fSelectedRegion = new Region(replacementOffset
+ getCursorPosition(), 0);
}
}
protected abstract char getOpenTrigger();
protected char getExitTrigger() {
return 0;
}
protected char[] getExitTriggers() {
return null;
}
/**
* @see org.eclipse.dltk.ui.text.completion.AbstractScriptCompletionProposal#getSelection(org.eclipse.jface.text.IDocument)
*/
@Override
public Point getSelection(IDocument document) {
if (fSelectedRegion == null)
return new Point(getReplacementOffset(), 0);
return new Point(fSelectedRegion.getOffset(),
fSelectedRegion.getLength());
}
private ReplacementBuffer replacementBuffer;
/**
* Override {@link #computeReplacement(IReplacementBuffer)}
*/
@Override
protected final String computeReplacementString() {
replacementBuffer = new ReplacementBuffer();
computeReplacement(replacementBuffer);
return replacementBuffer.toString();
}
protected abstract void computeReplacement(ReplacementBuffer buffer);
}