Preview in the editor of the approximate insertion result of the currently selected lookup suggestion

This commit is contained in:
peter
2016-10-18 16:59:49 +02:00
parent bdb404ed1d
commit c9dfdab0c9
3 changed files with 119 additions and 1 deletions
@@ -105,6 +105,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
private final List<LookupListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private PrefixChangeListener myPrefixChangeListener = new PrefixChangeListener.Adapter() {};
private final LookupPreview myPreview = new LookupPreview(this);
private long myStampShown = 0;
private boolean myShown = false;
@@ -853,6 +854,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
listener.currentItemChanged(event);
}
}
myPreview.updatePreview(currentItem);
}
public boolean fillInCommonPrefix(boolean explicitlyInvoked) {
@@ -0,0 +1,113 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.lookup.impl;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementPresentation;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorFontType;
import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.JBColor;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.FList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
/**
* @author peter
*/
class LookupPreview {
private final List<Inlay> myInlays = new ArrayList<>();
private final LookupImpl myLookup;
LookupPreview(LookupImpl lookup) {
myLookup = lookup;
}
void updatePreview(@Nullable LookupElement item) {
if (!Registry.is("ide.lookup.preview.insertion")) return;
myInlays.forEach(Disposer::dispose);
myInlays.clear();
String suffix = getSuffixText(item);
if (!suffix.isEmpty() && myLookup.getTopLevelEditor() instanceof EditorImpl) {
myLookup.getTopLevelEditor().getCaretModel().runForEachCaret(caret -> {
ensureCaretBeforeInlays(caret);
addInlay(suffix, caret.getOffset());
});
}
}
private static void ensureCaretBeforeInlays(Caret caret) {
LogicalPosition position = caret.getLogicalPosition();
if (position.leansForward) {
caret.moveToLogicalPosition(position.leanForward(false));
}
}
private String getSuffixText(@Nullable LookupElement item) {
if (item != null) {
String itemText = StringUtil.notNullize(LookupElementPresentation.renderElement(item).getItemText());
FList<TextRange> fragments = LookupCellRenderer.getMatchingFragments(myLookup.itemPattern(item), itemText);
if (fragments != null && !fragments.isEmpty()) {
List<TextRange> list = ContainerUtil.newArrayList(fragments);
return itemText.substring(list.get(list.size() - 1).getEndOffset(), itemText.length());
}
}
return "";
}
private void addInlay(String suffix, int caretOffset) {
Inlay inlay = myLookup.getTopLevelEditor().getInlayModel().addInlineElement(caretOffset, createGrayRenderer(suffix));
if (inlay != null) {
myInlays.add(inlay);
Disposer.register(myLookup, inlay);
}
}
@NotNull
private static EditorCustomElementRenderer createGrayRenderer(final String suffix) {
return new EditorCustomElementRenderer() {
@Override
public int calcWidthInPixels(@NotNull Editor editor) {
return editor.getContentComponent().getFontMetrics(getFont(editor)).stringWidth(suffix);
}
@Override
public void paint(@NotNull Editor editor, @NotNull Graphics g, @NotNull Rectangle r) {
g.setColor(editor.getColorsScheme().getColor(EditorColors.CARET_ROW_COLOR));
g.fillRect(r.x, r.y, r.width, r.height);
g.setColor(JBColor.GRAY);
g.setFont(getFont(editor));
g.drawString(suffix, r.x, r.y + ((EditorImpl)editor).getAscent());
}
private Font getFont(@NotNull Editor editor) {
return editor.getColorsScheme().getFont(EditorFontType.PLAIN);
}
};
}
}
@@ -381,6 +381,9 @@ ide.completion.show.lower.case.classes.description=Show non-imported classes sta
ide.completion.delay.autopopup.until.completed=false
ide.completion.delay.autopopup.until.completed.description=Controls if completion autopopup is shown immediately and populated in background, or delayed until all suggestion are calculated
ide.lookup.preview.insertion=false
ide.lookup.preview.insertion.description=Preview in the editor of the approximate insertion result of the currently selected lookup suggestion
ide.completion.middle.matching=true
ide.completion.middle.matching.description=Suggest items in completion that contain the entered string somewhere in the middle.
@@ -888,4 +891,4 @@ ide.projectView.globalOptions.description=Make Project View options such as auto
compiler.ref.index=false
compiler.ref.index.description=Enables find usages using references from compiler indices
compiler.ref.index.restartRequired=true
compiler.ref.index.restartRequired=true