Search Everywhere: Update renderer to reflect changes in IDEA
#KT-24812 Fixed
This commit is contained in:
@@ -16,66 +16,165 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.goto
|
package org.jetbrains.kotlin.idea.goto
|
||||||
|
|
||||||
import com.intellij.ide.util.DefaultPsiElementCellRenderer
|
import com.intellij.ide.util.PlatformModuleRendererFactory
|
||||||
|
import com.intellij.ide.util.PsiElementListCellRenderer
|
||||||
|
import com.intellij.ide.util.gotoByName.GotoFileCellRenderer
|
||||||
|
import com.intellij.navigation.NavigationItem
|
||||||
|
import com.intellij.openapi.util.Iconable
|
||||||
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
import com.intellij.openapi.util.text.StringUtil
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiFileSystemItem
|
||||||
import com.intellij.psi.presentation.java.SymbolPresentationUtil
|
import com.intellij.psi.presentation.java.SymbolPresentationUtil
|
||||||
|
import com.intellij.ui.ColoredListCellRenderer
|
||||||
|
import com.intellij.ui.JBColor
|
||||||
|
import com.intellij.ui.SimpleTextAttributes
|
||||||
|
import com.intellij.util.ui.FilePathSplittingPolicy
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
import org.jetbrains.kotlin.renderer.ParameterNameRenderingPolicy
|
import org.jetbrains.kotlin.renderer.ParameterNameRenderingPolicy
|
||||||
|
import java.awt.BorderLayout
|
||||||
|
import java.awt.Container
|
||||||
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import javax.swing.DefaultListCellRenderer
|
||||||
import javax.swing.JList
|
import javax.swing.JList
|
||||||
|
|
||||||
class KotlinSearchEverywherePsiRenderer(private val list: JList<*>) : DefaultPsiElementCellRenderer() {
|
// Mostly copied from com.intellij.ide.actions.SearchEverywherePsiRenderer
|
||||||
private val RENDERER = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_NO_ANNOTATIONS.withOptions {
|
// TODO: Drop copied code when SearchEverywherePsiRenderer becomes public
|
||||||
parameterNameRenderingPolicy = ParameterNameRenderingPolicy.NONE
|
internal class KotlinSearchEverywherePsiRenderer(private val myList: JList<*>) : PsiElementListCellRenderer<PsiElement>() {
|
||||||
modifiers = emptySet()
|
companion object {
|
||||||
startFromName = false
|
private val RENDERER = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_NO_ANNOTATIONS.withOptions {
|
||||||
|
parameterNameRenderingPolicy = ParameterNameRenderingPolicy.NONE
|
||||||
|
modifiers = emptySet()
|
||||||
|
startFromName = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getElementText(element: PsiElement?): String {
|
init {
|
||||||
if (element is KtNamedFunction) {
|
setFocusBorderEnabled(false)
|
||||||
val descriptor = element.resolveToDescriptorIfAny()
|
layout = object : BorderLayout() {
|
||||||
if (descriptor != null) {
|
override fun layoutContainer(target: Container) {
|
||||||
return buildString {
|
super.layoutContainer(target)
|
||||||
descriptor.extensionReceiverParameter?.let { append(RENDERER.renderType(it.type)).append('.') }
|
val right = getLayoutComponent(BorderLayout.EAST)
|
||||||
append(element.name)
|
val left = getLayoutComponent(BorderLayout.WEST)
|
||||||
descriptor.valueParameters.joinTo(this, prefix = "(", postfix = ")") { RENDERER.renderType(it.type) }
|
|
||||||
|
//IDEA-140824
|
||||||
|
if (right != null && left != null && left.bounds.x + left.bounds.width > right.bounds.x) {
|
||||||
|
val bounds = right.bounds
|
||||||
|
val newX = left.bounds.x + left.bounds.width
|
||||||
|
right.setBounds(newX, bounds.y, bounds.width - (newX - bounds.x), bounds.height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return super.getElementText(element)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mostly copied from SearchEverywherePsiRenderer
|
override fun getElementText(element: PsiElement?): String {
|
||||||
override fun getContainerText(element: PsiElement?, name: String?): String? {
|
if (element !is KtNamedFunction) return ""
|
||||||
var text = SymbolPresentationUtil.getSymbolContainerText(element) ?: return null
|
val descriptor = element.resolveToDescriptorIfAny() ?: return ""
|
||||||
if (list.width == 0) return text
|
return buildString {
|
||||||
|
descriptor.extensionReceiverParameter?.let { append(RENDERER.renderType(it.type)).append('.') }
|
||||||
|
append(element.name)
|
||||||
|
descriptor.valueParameters.joinTo(this, prefix = "(", postfix = ")") { RENDERER.renderType(it.type) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getContainerText(element: PsiElement, name: String): String? {
|
||||||
|
if (element is PsiFileSystemItem) {
|
||||||
|
val file = element.virtualFile
|
||||||
|
val parent = file?.parent
|
||||||
|
if (parent == null) {
|
||||||
|
if (file != null) { // use fallback from Switcher
|
||||||
|
val presentableUrl = file.presentableUrl
|
||||||
|
return FileUtil.getLocationRelativeToUserHome(presentableUrl)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
val relativePath = GotoFileCellRenderer.getRelativePath(parent, element.getProject()) ?: return "( " + File.separator + " )"
|
||||||
|
var width = myList.width
|
||||||
|
if (width == 0) width += 800
|
||||||
|
val path = FilePathSplittingPolicy.SPLIT_BY_SEPARATOR.getOptimalTextForComponent(
|
||||||
|
name,
|
||||||
|
File(relativePath),
|
||||||
|
this,
|
||||||
|
width - myRightComponentWidth - 16 - 10
|
||||||
|
)
|
||||||
|
return "($path)"
|
||||||
|
}
|
||||||
|
return getSymbolContainerText(name, element)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSymbolContainerText(name: String, element: PsiElement): String? {
|
||||||
|
var text = SymbolPresentationUtil.getSymbolContainerText(element)
|
||||||
|
|
||||||
|
if (myList.width == 0) return text
|
||||||
|
if (text == null) return null
|
||||||
|
|
||||||
if (text.startsWith("(") && text.endsWith(")")) {
|
if (text.startsWith("(") && text.endsWith(")")) {
|
||||||
text = text.substring(1, text.length - 1)
|
text = text.substring(1, text.length - 1)
|
||||||
}
|
}
|
||||||
|
val `in` = text.startsWith("in ")
|
||||||
val inIndex = text.indexOf("in ")
|
if (`in`) text = text.substring(3)
|
||||||
if (inIndex >= 0) text = text.substring(inIndex + 3)
|
val fm = myList.getFontMetrics(myList.font)
|
||||||
val fm = list.getFontMetrics(list.font)
|
val maxWidth = myList.width - fm.stringWidth(name) - 16 - myRightComponentWidth - 20
|
||||||
val maxWidth = list.width - fm.stringWidth(name) - 16 - myRightComponentWidth - 20
|
val left = if (`in`) "(in " else "("
|
||||||
val left = if (inIndex >= 0) "(in " else "("
|
|
||||||
val right = ")"
|
val right = ")"
|
||||||
|
|
||||||
if (fm.stringWidth(left + text + right) < maxWidth) return left + text + right
|
if (fm.stringWidth(left + text + right) < maxWidth) return left + text + right
|
||||||
val parts = LinkedList(StringUtil.split(text, "."))
|
val separator = if (text.contains(File.separator)) File.separator else "."
|
||||||
|
val parts = LinkedList(StringUtil.split(text, separator))
|
||||||
var index: Int
|
var index: Int
|
||||||
while (parts.size > 1) {
|
while (parts.size > 1) {
|
||||||
index = parts.size / 2 - 1
|
index = parts.size / 2 - 1
|
||||||
parts.removeAt(index)
|
parts.removeAt(index)
|
||||||
if (fm.stringWidth(StringUtil.join(parts, ".") + "...") < maxWidth) {
|
if (fm.stringWidth(StringUtil.join(parts, separator) + "...") < maxWidth) {
|
||||||
parts.add(index, if (index == 0) "..." else ".")
|
parts.add(index, "...")
|
||||||
return left + StringUtil.join(parts, ".") + right
|
return left + StringUtil.join(parts, separator) + right
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//todo
|
||||||
return left + "..." + right
|
return "$left...$right"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun customizeNonPsiElementLeftRenderer(
|
||||||
|
renderer: ColoredListCellRenderer<*>?,
|
||||||
|
list: JList<*>?,
|
||||||
|
value: Any?,
|
||||||
|
index: Int,
|
||||||
|
selected: Boolean,
|
||||||
|
hasFocus: Boolean
|
||||||
|
): Boolean {
|
||||||
|
if (value !is NavigationItem) return false
|
||||||
|
|
||||||
|
val item = value as NavigationItem?
|
||||||
|
|
||||||
|
val attributes = getNavigationItemAttributes(item)
|
||||||
|
|
||||||
|
var nameAttributes: SimpleTextAttributes? = if (attributes != null) SimpleTextAttributes.fromTextAttributes(attributes) else null
|
||||||
|
|
||||||
|
val color = list!!.foreground
|
||||||
|
if (nameAttributes == null) nameAttributes = SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, color)
|
||||||
|
|
||||||
|
renderer!!.append(item!!.toString() + " ", nameAttributes)
|
||||||
|
val itemPresentation = item.presentation!!
|
||||||
|
renderer.icon = itemPresentation.getIcon(true)
|
||||||
|
|
||||||
|
val locationString = itemPresentation.locationString
|
||||||
|
if (!StringUtil.isEmpty(locationString)) {
|
||||||
|
renderer.append(locationString!!, SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, JBColor.GRAY))
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getRightCellRenderer(value: Any): DefaultListCellRenderer? {
|
||||||
|
val rightRenderer = super.getRightCellRenderer(value)
|
||||||
|
return if (rightRenderer is PlatformModuleRendererFactory.PlatformModuleRenderer) {
|
||||||
|
// that renderer will display file path, but we're showing it ourselves - no need to show twice
|
||||||
|
null
|
||||||
|
} else rightRenderer
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getIconFlags() = Iconable.ICON_FLAG_READ_STATUS
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user