mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[ui] IJPL-195407 Reduce flickering of the completion popup by rendering more items in advance.
GitOrigin-RevId: 38d14378affb5237cbec40a6b5dc2366324e4da8
This commit is contained in:
committed by
intellij-monorepo-bot
parent
011a5f6bc9
commit
b0ae2e409f
@@ -52,6 +52,7 @@ import org.jetbrains.annotations.Nls
|
||||
import org.jetbrains.annotations.VisibleForTesting
|
||||
import java.awt.*
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import java.util.function.Supplier
|
||||
import javax.swing.*
|
||||
import javax.swing.border.EmptyBorder
|
||||
@@ -91,6 +92,7 @@ class LookupCellRenderer(lookup: LookupImpl, editorComponent: JComponent) : List
|
||||
private val presentationUpdateRequests = MutableSharedFlow<Unit>(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||
private val forceRefreshUi = AtomicBoolean(false)
|
||||
private val isUnitTestMode = ApplicationManager.getApplication().isUnitTestMode
|
||||
private val itemAddedCount = AtomicInteger()
|
||||
|
||||
init {
|
||||
val scheme = lookup.topLevelEditor.colorsScheme
|
||||
@@ -166,8 +168,10 @@ class LookupCellRenderer(lookup: LookupImpl, editorComponent: JComponent) : List
|
||||
|
||||
@JvmField
|
||||
val MATCHED_FOREGROUND_COLOR: Color = JBColor.namedColor("CompletionPopup.matchForeground", JBUI.CurrentTheme.Link.Foreground.ENABLED)
|
||||
|
||||
@JvmField
|
||||
val SELECTED_BACKGROUND_COLOR: Color = JBColor.namedColor("CompletionPopup.selectionBackground", JBColor(0xc5dffc, 0x113a5c))
|
||||
|
||||
@JvmField
|
||||
val SELECTED_NON_FOCUSED_BACKGROUND_COLOR: Color = JBColor.namedColor("CompletionPopup.selectionInactiveBackground",
|
||||
JBColor(0xE0E0E0, 0x515457))
|
||||
@@ -500,17 +504,16 @@ class LookupCellRenderer(lookup: LookupImpl, editorComponent: JComponent) : List
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Update lookup width due to visible in lookup items
|
||||
*/
|
||||
private fun updateLookupWidthFromVisibleItems() {
|
||||
if (lookup.isLookupDisposed) return
|
||||
scheduleVisibleItemsExpensiveRendering()
|
||||
val visibleItems = lookup.visibleItems
|
||||
|
||||
var maxWidth = if (shrinkLookup) 0 else lookupTextWidth
|
||||
for (item in visibleItems) {
|
||||
scheduleForRenderingIfNeeded(item)
|
||||
|
||||
val presentation = asyncRendering.getLastComputed(item)
|
||||
|
||||
item.putUserData(CUSTOM_NAME_FONT, getFontAbleToDisplay(presentation.itemText))
|
||||
@@ -541,10 +544,15 @@ class LookupCellRenderer(lookup: LookupImpl, editorComponent: JComponent) : List
|
||||
}
|
||||
}
|
||||
|
||||
private fun scheduleForRenderingIfNeeded(element: LookupElement) {
|
||||
if (element.getUserData(SCHEDULED_FOR_RENDERING) != true) {
|
||||
element.putUserData(SCHEDULED_FOR_RENDERING, true)
|
||||
updateItemPresentation(element)
|
||||
@ApiStatus.Internal
|
||||
fun scheduleVisibleItemsExpensiveRendering() {
|
||||
// Ensure that all visible items plus a range of invisible items have been
|
||||
// scheduled for async rendering.
|
||||
for (item in lookup.getItemsForAsyncRendering()) {
|
||||
if (item.getUserData(SCHEDULED_FOR_RENDERING) != true) {
|
||||
item.putUserData(SCHEDULED_FOR_RENDERING, true)
|
||||
updateItemPresentation(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -566,6 +574,12 @@ class LookupCellRenderer(lookup: LookupImpl, editorComponent: JComponent) : List
|
||||
updateIconWidth(fastPresentation.icon)
|
||||
scheduleUpdateLookupWidthFromVisibleItems()
|
||||
AsyncRendering.rememberPresentation(element, fastPresentation)
|
||||
|
||||
// Fast path for the first 20 matched items to
|
||||
// avoid initial lookup flickering as much as possible
|
||||
if (itemAddedCount.incrementAndGet() < 20 && lookup.arranger.matchingItems.contains(element)) {
|
||||
updateItemPresentation(element)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateItemPresentation(element: LookupElement) {
|
||||
|
||||
@@ -311,10 +311,10 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable,
|
||||
return false;
|
||||
}
|
||||
|
||||
cellRenderer.itemAdded(item, presentation);
|
||||
LookupArranger arranger = myArranger;
|
||||
arranger.registerMatcher(item, matcher);
|
||||
arranger.addElement(item, presentation);
|
||||
cellRenderer.itemAdded(item, presentation);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -522,6 +522,8 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable,
|
||||
}
|
||||
});
|
||||
|
||||
cellRenderer.scheduleVisibleItemsExpensiveRendering();
|
||||
|
||||
updateListHeight(listModel);
|
||||
|
||||
list.setSelectedIndex(toSelect);
|
||||
@@ -1206,6 +1208,23 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable,
|
||||
}
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public List<LookupElement> getItemsForAsyncRendering() {
|
||||
ThreadingAssertions.assertEventDispatchThread();
|
||||
|
||||
var itemsCount = list.getItemsCount();
|
||||
if (itemsCount == 0) return Collections.emptyList();
|
||||
|
||||
synchronized (uiLock) {
|
||||
int lowerItemIndex = list.getFirstVisibleIndex();
|
||||
int higherItemIndex = list.getLastVisibleIndex();
|
||||
if (lowerItemIndex < 0 || higherItemIndex < 0) return Collections.emptyList();
|
||||
|
||||
int delta = 15;
|
||||
var items = getListModel().toList();
|
||||
return items.subList(Math.max(lowerItemIndex - delta, 0), Math.min(higherItemIndex + 1 + delta, itemsCount));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Unmodifiable List<String> getAdvertisements() {
|
||||
|
||||
Reference in New Issue
Block a user