mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
fix completion extender blinking
This commit is contained in:
+35
-101
@@ -15,122 +15,56 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.lookup.impl;
|
||||
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.ui.HintHint;
|
||||
import com.intellij.ui.LightweightHint;
|
||||
import com.intellij.ui.ScreenUtil;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.ui.ListExpandableItemsHandler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.*;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class CompletionExtender extends LightweightHint {
|
||||
private LookupElement myElement;
|
||||
private LookupImpl myLookup;
|
||||
private int myIndex;
|
||||
public class CompletionExtender extends ListExpandableItemsHandler {
|
||||
|
||||
public CompletionExtender(@NotNull LookupElement element, @NotNull LookupImpl lookup) {
|
||||
super(createComponent(element, lookup));
|
||||
setForceHideShadow(true);
|
||||
myElement = element;
|
||||
myLookup = lookup;
|
||||
myIndex = myLookup.getList().getSelectedIndex();
|
||||
myLookup.getComponent().addComponentListener(new ComponentAdapter() {
|
||||
public CompletionExtender(@NotNull final JList list) {
|
||||
super(list);
|
||||
list.addComponentListener(new ComponentAdapter() {
|
||||
@Override
|
||||
public void componentResized(ComponentEvent e) {
|
||||
recalculateLocation();
|
||||
}
|
||||
public void componentShown(ComponentEvent e) {
|
||||
if (myComponent.getParent() != null && myComponent.getParent().getParent() instanceof JScrollPane) {
|
||||
final JScrollBar verticalScrollBar = ((JScrollPane)myComponent.getParent().getParent()).getVerticalScrollBar();
|
||||
final JScrollBar horizontalScrollBar = ((JScrollPane)myComponent.getParent().getParent()).getVerticalScrollBar();
|
||||
final AdjustmentListener listener = new AdjustmentListener() {
|
||||
@Override
|
||||
public void adjustmentValueChanged(AdjustmentEvent e) {
|
||||
updateCurrentSelection();
|
||||
}
|
||||
};
|
||||
if (verticalScrollBar != null) verticalScrollBar.addAdjustmentListener(listener);
|
||||
if (horizontalScrollBar != null) horizontalScrollBar.addAdjustmentListener(listener);
|
||||
|
||||
@Override
|
||||
public void componentMoved(ComponentEvent e) {
|
||||
recalculateLocation();
|
||||
list.removeComponentListener(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public LookupElement getLookupElement() {
|
||||
return myElement;
|
||||
}
|
||||
|
||||
public boolean sameAsFor(LookupElement item) {
|
||||
return getLookupElement().equals(item)
|
||||
&& myIndex == myLookup.getList().getSelectedIndex();
|
||||
}
|
||||
|
||||
private static JComponent createComponent(LookupElement element, LookupImpl lookup) {
|
||||
final LookupCellRenderer renderer = ((LookupCellRenderer)lookup.getList().getCellRenderer()).createExtenderRenderer();
|
||||
final JComponent component = (JComponent)renderer.getListCellRendererComponent(lookup.getList(), element,
|
||||
lookup.getList().getSelectedIndex(),
|
||||
true, false);
|
||||
component.setSize(component.getPreferredSize());
|
||||
return component;
|
||||
}
|
||||
|
||||
public boolean show() {
|
||||
if (SystemInfo.isUnix) {
|
||||
//TODO[kb]: fix shadow. This hint is always heavyweight window and has a shadow
|
||||
hide();
|
||||
return false;
|
||||
}
|
||||
if (!checkComponentBounds()) {
|
||||
hide();
|
||||
return false;
|
||||
}
|
||||
final JList list = myLookup.getList();
|
||||
if (getComponent().getWidth() > list.getWidth()) {
|
||||
final JComponent rootPane = myLookup.myLayeredPane;
|
||||
|
||||
final Point p = list.getLocationOnScreen();
|
||||
p.y += list.indexToLocation(list.getSelectedIndex()).y;
|
||||
SwingUtilities.convertPointFromScreen(p, rootPane);
|
||||
|
||||
if (rootPane != null) {
|
||||
final HintHint hint = new HintHint();
|
||||
show(rootPane, p.x, p.y, null, hint);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean checkComponentBounds() {
|
||||
final Dimension size = getComponent().getPreferredSize();
|
||||
final JList list = myLookup.getList();
|
||||
final Point p = list.getLocationOnScreen();
|
||||
p.y += list.indexToLocation(list.getSelectedIndex()).y;
|
||||
final Rectangle rectangle = new Rectangle(p, size);
|
||||
return !ScreenUtil.isOutsideOnTheRightOFScreen(rectangle);
|
||||
}
|
||||
|
||||
void recalculateLocation() {
|
||||
if (!isVisible()) return;
|
||||
final JList list = myLookup.getList();
|
||||
final Point p = list.getLocationOnScreen();
|
||||
final Point point = list.indexToLocation(list.getSelectedIndex());
|
||||
if (point != null) {
|
||||
p.y += point.y;
|
||||
final JComponent rootPane = UIUtil.getRootPane(myLookup.getEditor().getContentComponent());
|
||||
if (rootPane != null) {
|
||||
SwingUtilities.convertPointFromScreen(p, rootPane);
|
||||
setLocation(new RelativePoint(rootPane, p));
|
||||
return;
|
||||
}
|
||||
}
|
||||
hide();
|
||||
@Override
|
||||
protected void handleSelectionChange(Integer selected, boolean processIfUnfocused) {
|
||||
super.handleSelectionChange(myComponent.getSelectedIndex(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() {
|
||||
super.hide();
|
||||
myLookup = null;
|
||||
myElement = null;
|
||||
protected void onFocusLost() {
|
||||
//don't hide hint
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleMouseEvent(MouseEvent e, boolean forceUpdate) {
|
||||
// don't show or hide hint on mouse events
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPaintBorder() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+41
-15
@@ -37,6 +37,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import java.awt.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
@@ -68,15 +70,13 @@ public class LookupCellRenderer implements ListCellRenderer {
|
||||
private final SimpleColoredComponent myNameComponent;
|
||||
private final SimpleColoredComponent myTailComponent;
|
||||
private final SimpleColoredComponent myTypeLabel;
|
||||
private final JPanel myPanel;
|
||||
private final LookupPanel myPanel;
|
||||
private final Map<Integer, Boolean> mySelected = new HashMap<Integer, Boolean>();
|
||||
|
||||
private static final String ELLIPSIS = "\u2026";
|
||||
private final boolean myFullSize;
|
||||
private int myMaxWidth = -1;
|
||||
|
||||
public LookupCellRenderer(LookupImpl lookup, boolean fullSize) {
|
||||
myFullSize = fullSize;
|
||||
|
||||
public LookupCellRenderer(LookupImpl lookup) {
|
||||
EditorColorsScheme scheme = lookup.getEditor().getColorsScheme();
|
||||
myNormalFont = scheme.getFont(EditorFontType.PLAIN);
|
||||
myBoldFont = scheme.getFont(EditorFontType.BOLD);
|
||||
@@ -124,7 +124,7 @@ public class LookupCellRenderer implements ListCellRenderer {
|
||||
final Color background = isSelected ? SELECTED_BACKGROUND_COLOR : BACKGROUND_COLOR;
|
||||
|
||||
int allowedWidth = list.getWidth() - AFTER_TAIL - AFTER_TYPE - getIconIndent();
|
||||
final LookupElementPresentation presentation = new RealLookupElementPresentation(myFullSize ? getMaxWidth() : allowedWidth, myNormalMetrics, myBoldMetrics, myLookup);
|
||||
final LookupElementPresentation presentation = new RealLookupElementPresentation(isSelected ? getMaxWidth() : allowedWidth, myNormalMetrics, myBoldMetrics, myLookup);
|
||||
if (item.isValid()) {
|
||||
item.renderElement(presentation);
|
||||
} else {
|
||||
@@ -139,13 +139,37 @@ public class LookupCellRenderer implements ListCellRenderer {
|
||||
|
||||
myTypeLabel.clear();
|
||||
if (allowedWidth > 0) {
|
||||
allowedWidth -= setTypeTextLabel(item, background, foreground, presentation, myFullSize ? getMaxWidth() : allowedWidth, isSelected);
|
||||
allowedWidth -= setTypeTextLabel(item, background, foreground, presentation, isSelected ? getMaxWidth() : allowedWidth, isSelected);
|
||||
}
|
||||
|
||||
myTailComponent.clear();
|
||||
myTailComponent.setBackground(background);
|
||||
if (myFullSize || allowedWidth >= 0) {
|
||||
setTailTextLabel(isSelected, presentation, foreground, myFullSize ? getMaxWidth() : allowedWidth);
|
||||
if (isSelected || allowedWidth >= 0) {
|
||||
setTailTextLabel(isSelected, presentation, foreground, isSelected ? getMaxWidth() : allowedWidth);
|
||||
}
|
||||
|
||||
if (mySelected.containsKey(index)) {
|
||||
if (!isSelected && mySelected.get(index)) {
|
||||
myPanel.setUpdateExtender(true);
|
||||
}
|
||||
}
|
||||
mySelected.put(index, isSelected);
|
||||
|
||||
final double w = myNameComponent.getPreferredSize().getWidth() +
|
||||
myTailComponent.getPreferredSize().getWidth() +
|
||||
myTypeLabel.getPreferredSize().getWidth();
|
||||
|
||||
myPanel.removeAll();
|
||||
if (isSelected && w > list.getWidth()) {
|
||||
myPanel.setLayout(new BoxLayout(myPanel, BoxLayout.X_AXIS));
|
||||
myPanel.add(myNameComponent);
|
||||
myPanel.add(myTailComponent);
|
||||
myPanel.add(myTypeLabel);
|
||||
} else {
|
||||
myPanel.setLayout(new BorderLayout());
|
||||
myPanel.add(myNameComponent, BorderLayout.WEST);
|
||||
myPanel.add(myTailComponent, BorderLayout.CENTER);
|
||||
myPanel.add(myTypeLabel, BorderLayout.EAST);
|
||||
}
|
||||
|
||||
return myPanel;
|
||||
@@ -327,12 +351,6 @@ public class LookupCellRenderer implements ListCellRenderer {
|
||||
return RealLookupElementPresentation.calculateWidth(p, myNormalMetrics, myBoldMetrics) + AFTER_TAIL + AFTER_TYPE;
|
||||
}
|
||||
|
||||
public LookupCellRenderer createExtenderRenderer() {
|
||||
LookupCellRenderer renderer = new LookupCellRenderer(myLookup, true);
|
||||
renderer.myEmptyIcon = myEmptyIcon;
|
||||
return renderer;
|
||||
}
|
||||
|
||||
public int getIconIndent() {
|
||||
return myNameComponent.getIconTextGap() + myEmptyIcon.getIconWidth();
|
||||
}
|
||||
@@ -350,15 +368,23 @@ public class LookupCellRenderer implements ListCellRenderer {
|
||||
}
|
||||
|
||||
private class LookupPanel extends JPanel {
|
||||
boolean myUpdateExtender;
|
||||
public LookupPanel() {
|
||||
super(new BorderLayout());
|
||||
}
|
||||
|
||||
public void setUpdateExtender(boolean updateExtender) {
|
||||
myUpdateExtender = updateExtender;
|
||||
}
|
||||
|
||||
public void paint(Graphics g){
|
||||
if (!myLookup.isFocused() && myLookup.isCompletion()) {
|
||||
((Graphics2D)g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f));
|
||||
}
|
||||
super.paint(g);
|
||||
//if (myUpdateExtender) {
|
||||
// myLookup.updateExtender();
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.event.*;
|
||||
import com.intellij.openapi.editor.event.DocumentAdapter;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
@@ -56,9 +57,7 @@ import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.impl.DebugUtil;
|
||||
import com.intellij.ui.LightweightHint;
|
||||
import com.intellij.ui.ListScrollingUtil;
|
||||
import com.intellij.ui.ScreenUtil;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.components.JBList;
|
||||
import com.intellij.ui.components.JBScrollPane;
|
||||
@@ -97,12 +96,11 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
|
||||
|
||||
private final Project myProject;
|
||||
private final Editor myEditor;
|
||||
private CompletionExtender extender;
|
||||
private String myInitialPrefix;
|
||||
|
||||
private boolean myStableStart;
|
||||
private RangeMarker myLookupStartMarker;
|
||||
private final JList myList = new JBList(new DefaultListModel()) {
|
||||
private final JBList myList = new JBList(new DefaultListModel()) {
|
||||
@Override
|
||||
protected void processKeyEvent(final KeyEvent e) {
|
||||
final char keyChar = e.getKeyChar();
|
||||
@@ -118,6 +116,13 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
|
||||
|
||||
super.processKeyEvent(e);
|
||||
}
|
||||
|
||||
ExpandableItemsHandler<Integer> myExtender = new CompletionExtender(this);
|
||||
@NotNull
|
||||
@Override
|
||||
public ExpandableItemsHandler<Integer> getExpandableItemsHandler() {
|
||||
return myExtender;
|
||||
}
|
||||
};
|
||||
private final LookupCellRenderer myCellRenderer;
|
||||
private Boolean myPositionedAbove = null;
|
||||
@@ -165,7 +170,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
|
||||
myPresentableArranger = arranger;
|
||||
|
||||
myIconPanel.setVisible(false);
|
||||
myCellRenderer = new LookupCellRenderer(this, false);
|
||||
myCellRenderer = new LookupCellRenderer(this);
|
||||
myList.setCellRenderer(myCellRenderer);
|
||||
|
||||
myList.setFocusable(false);
|
||||
@@ -174,6 +179,8 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
|
||||
myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
myList.setBackground(LookupCellRenderer.BACKGROUND_COLOR);
|
||||
|
||||
myList.getExpandableItemsHandler();
|
||||
|
||||
myScrollBarIncreaseButton = new JButton();
|
||||
myScrollBarIncreaseButton.setFocusable(false);
|
||||
myScrollBarIncreaseButton.setRequestFocusEnabled(false);
|
||||
@@ -188,7 +195,6 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
|
||||
return myScrollBarIncreaseButton;
|
||||
}
|
||||
});
|
||||
|
||||
getComponent().add(myLayeredPane, BorderLayout.CENTER);
|
||||
|
||||
//IDEA-82111
|
||||
@@ -886,16 +892,6 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
|
||||
updateHint(item);
|
||||
}
|
||||
oldItem = item;
|
||||
|
||||
if (item != null && LookupImpl.this.isVisible() && LookupImpl.this.isFocused()) {
|
||||
if (extender == null || !extender.isVisible() || !extender.sameAsFor(item)) {
|
||||
if (extender != null) extender.hide();
|
||||
extender = new CompletionExtender(item, LookupImpl.this);
|
||||
if (!extender.show()) {
|
||||
extender.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1231,9 +1227,6 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
|
||||
}
|
||||
Disposer.dispose(myProcessIcon);
|
||||
Disposer.dispose(myHintAlarm);
|
||||
if (extender != null) {
|
||||
extender.hide();
|
||||
}
|
||||
myDisposed = true;
|
||||
disposeTrace = DebugUtil.currentStackTrace() + "\n============";
|
||||
//noinspection AssignmentToStaticFieldFromInstanceMethod
|
||||
@@ -1458,5 +1451,4 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
|
||||
return myPresentableArranger.getRelevanceStrings();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ abstract public class AbstractExpandableItemsHandler<KeyType, ComponentType exte
|
||||
myComponent.addFocusListener(
|
||||
new FocusAdapter() {
|
||||
public void focusLost(FocusEvent e) {
|
||||
hideHint();
|
||||
onFocusLost();
|
||||
}
|
||||
|
||||
public void focusGained(FocusEvent e) {
|
||||
@@ -134,6 +134,12 @@ abstract public class AbstractExpandableItemsHandler<KeyType, ComponentType exte
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected void onFocusLost() {
|
||||
hideHint();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -160,7 +166,7 @@ abstract public class AbstractExpandableItemsHandler<KeyType, ComponentType exte
|
||||
handleMouseEvent(e, true);
|
||||
}
|
||||
|
||||
private void handleMouseEvent(MouseEvent e, boolean forceUpdate) {
|
||||
protected void handleMouseEvent(MouseEvent e, boolean forceUpdate) {
|
||||
KeyType selected = getCellKeyForPoint(e.getPoint());
|
||||
if (forceUpdate || !Comparing.equal(myKey, selected)) {
|
||||
handleSelectionChange(selected, true);
|
||||
@@ -307,14 +313,16 @@ abstract public class AbstractExpandableItemsHandler<KeyType, ComponentType exte
|
||||
g.translate(-(visibleRect.x + visibleRect.width - cellBounds.x), 0);
|
||||
doPaintTooltipImage(renderer, cellBounds, height, g, key);
|
||||
|
||||
// paint border
|
||||
g.translate((visibleRect.x + visibleRect.width - cellBounds.x), 0);
|
||||
g.setColor(Color.GRAY);
|
||||
int rightX = myImage.getWidth() - 1;
|
||||
final int h = myImage.getHeight();
|
||||
UIUtil.drawLine(g, 0, 0, rightX, 0);
|
||||
UIUtil.drawLine(g, rightX, 0, rightX, h);
|
||||
UIUtil.drawLine(g, 0, h - 1, rightX, h - 1);
|
||||
|
||||
if (isPaintBorder()) {
|
||||
g.translate((visibleRect.x + visibleRect.width - cellBounds.x), 0);
|
||||
g.setColor(getBorderColor());
|
||||
int rightX = myImage.getWidth() - 1;
|
||||
final int h = myImage.getHeight();
|
||||
UIUtil.drawLine(g, 0, 0, rightX, 0);
|
||||
UIUtil.drawLine(g, rightX, 0, rightX, h);
|
||||
UIUtil.drawLine(g, 0, h - 1, rightX, h - 1);
|
||||
}
|
||||
|
||||
g.dispose();
|
||||
myRendererPane.remove(renderer);
|
||||
@@ -322,6 +330,14 @@ abstract public class AbstractExpandableItemsHandler<KeyType, ComponentType exte
|
||||
return new Point(visibleRect.x + visibleRect.width, cellBounds.y);
|
||||
}
|
||||
|
||||
protected boolean isPaintBorder() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected Color getBorderColor() {
|
||||
return Color.GRAY;
|
||||
}
|
||||
|
||||
protected BufferedImage createImage(final int height, final int width) {
|
||||
return new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user