mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-CR-1488: Extend and improve API of PinToTop feature.
Type names were replaced with more flexible abstract tags. Now a member can provide parent tag itself which will be used instead of traversing to parent node. Members can provide custom name to use it instead of node name. Members can provide their pinned status itself. All checking logic (canBePinned, isPinned, getPinInfo) were extracted to a separate file. (cherry picked from commit 85b5c3796d3a61701bcf890645f4ed6b475e62cc) GitOrigin-RevId: 1f370966512f49c57ecf2332016712dffcfd0d64
This commit is contained in:
committed by
intellij-monorepo-bot
parent
f08d71239d
commit
5b2efaaa08
+23
@@ -6,4 +6,27 @@ import org.jetbrains.annotations.ApiStatus
|
||||
@ApiStatus.Experimental
|
||||
interface PinToTopMemberValue : PinToTopValue {
|
||||
fun canBePinned() : Boolean
|
||||
|
||||
/**
|
||||
* When not null the name will be used as member name in PinToTop instead of node name. May be useful in a case when
|
||||
* a value name presentation differs from its real name
|
||||
*/
|
||||
@JvmDefault
|
||||
val customMemberName: String?
|
||||
get() = null
|
||||
|
||||
/**
|
||||
* When not null this tag will be used instead of getting tag from parent node
|
||||
*/
|
||||
@JvmDefault
|
||||
val customParentTag: String?
|
||||
get() = null
|
||||
|
||||
/**
|
||||
* When not null the value will be used as 'pinned' status instead of checking the status inside [XDebuggerPinToTopManager] maps.
|
||||
* It may be useful if you want to implement pinning logic inside your values by listening [XDebuggerPinToTopListener]
|
||||
*/
|
||||
@JvmDefault
|
||||
val isPinned: Boolean?
|
||||
get() = null
|
||||
}
|
||||
+13
-1
@@ -5,5 +5,17 @@ import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Experimental
|
||||
interface PinToTopParentValue : PinToTopValue {
|
||||
fun getTypeName() : String?
|
||||
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "2021.1")
|
||||
@Deprecated("Implement property 'tag' instead", ReplaceWith("tag"))
|
||||
fun getTypeName() : String? = null
|
||||
|
||||
/**
|
||||
* Tag used as identifier of a parent node. Pinned status is determined by checking of presence a 'tag - member name' pair
|
||||
* in [XDebuggerPinToTopManager]
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
@JvmDefault
|
||||
val tag: String?
|
||||
get() = getTypeName()
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.intellij.xdebugger.impl.pinned.items
|
||||
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueContainerNode
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl
|
||||
|
||||
fun XValueNodeImpl?.isPinned(pinToTopManager: XDebuggerPinToTopManager): Boolean {
|
||||
val container = this?.valueContainer
|
||||
if (container is PinToTopMemberValue) {
|
||||
val pinned = container.isPinned
|
||||
if (pinned != null)
|
||||
return pinned
|
||||
|
||||
val pinInfo = this.getPinInfo()
|
||||
if (pinInfo != null)
|
||||
return pinToTopManager.isPinned(pinInfo)
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun XValueNodeImpl?.canBePinned(): Boolean {
|
||||
val container = this?.valueContainer
|
||||
if (container is PinToTopMemberValue) {
|
||||
return container.canBePinned() && this.getPinInfo() != null
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun XValueNodeImpl?.getPinInfo() : PinnedItemInfo? {
|
||||
val container = this?.valueContainer
|
||||
if (container is PinToTopMemberValue) {
|
||||
val parentTag = container.customParentTag ?: parentPinToTopValue?.tag
|
||||
val memberName = container.customMemberName ?: this?.name
|
||||
if (parentTag != null && memberName != null)
|
||||
return PinnedItemInfo(parentTag, memberName)
|
||||
return null
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
val XValueNodeImpl?.parentPinToTopValue: PinToTopParentValue? get() {
|
||||
return ((this?.parent as? XValueContainerNode<*>)?.valueContainer as? PinToTopParentValue)
|
||||
}
|
||||
+4
-4
@@ -4,15 +4,15 @@ package com.intellij.xdebugger.impl.pinned.items
|
||||
import com.intellij.util.xmlb.annotations.Attribute
|
||||
|
||||
data class PinnedItemInfo(
|
||||
@Attribute("typeName") var typeName: String,
|
||||
@Attribute("fieldName") var fieldName: String) {
|
||||
@Attribute("parentTag") var parentTag: String,
|
||||
@Attribute("memberName") var memberName: String) {
|
||||
|
||||
companion object {
|
||||
fun getKey(typeName: String, fieldName: String) = "$typeName:$fieldName"
|
||||
fun getKey(parentTag: String, memberName: String) = "$parentTag:$memberName"
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
constructor() : this("", "")
|
||||
|
||||
fun getKey() = getKey(typeName, fieldName)
|
||||
fun getKey() = getKey(parentTag, memberName)
|
||||
}
|
||||
+13
-21
@@ -26,7 +26,7 @@ open class XDebuggerPinToTopManager {
|
||||
|
||||
private var myNodeHoverLifetime : Disposable? = null
|
||||
private var myActiveNode: XDebuggerTreeNode? = null
|
||||
private var myPinnedMembers = HashMap<String, PinnedItemInfo>()
|
||||
private var myPinnedMembers = HashSet<PinnedItemInfo>()
|
||||
private val myPinToTopIconAlarm = Alarm()
|
||||
|
||||
val pinToTopComparator : Comparator<XValueNodeImpl> = Comparator.comparing<XValueNodeImpl, Boolean> { !isItemPinned(it) }
|
||||
@@ -51,12 +51,7 @@ open class XDebuggerPinToTopManager {
|
||||
}
|
||||
|
||||
val valueNode = node as? XValueNodeImpl ?: return
|
||||
val pinnedValue = node.valueContainer as? PinToTopMemberValue ?: return
|
||||
if ((valueNode.parent as? XValueNodeImpl)?.valueContainer !is PinToTopParentValue) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!pinnedValue.canBePinned() || isItemPinned(node)) {
|
||||
if (!valueNode.canBePinned() || node.isPinned(this)) {
|
||||
return
|
||||
}
|
||||
var oldIcon = valueNode.icon
|
||||
@@ -88,29 +83,26 @@ open class XDebuggerPinToTopManager {
|
||||
myListeners.remove(listener)
|
||||
}
|
||||
|
||||
fun getPinnedItemInfos() = myPinnedMembers.values.toList()
|
||||
fun getPinnedItemInfos() = myPinnedMembers.toList()
|
||||
|
||||
fun addItemInfo(typeName: String, fieldName: String) {
|
||||
val info = PinnedItemInfo(typeName, fieldName)
|
||||
myPinnedMembers[info.getKey()] = info
|
||||
fun addItemInfo(info: PinnedItemInfo) {
|
||||
myPinnedMembers.add(info)
|
||||
for (listener in myListeners) {
|
||||
listener.onPinnedItemAdded(info)
|
||||
}
|
||||
}
|
||||
|
||||
fun removeItemInfo(typeName: String, fieldName: String) {
|
||||
val key = PinnedItemInfo.getKey(typeName, fieldName)
|
||||
val info = myPinnedMembers[key] ?: return
|
||||
myPinnedMembers.remove(key)
|
||||
fun removeItemInfo(info: PinnedItemInfo) {
|
||||
myPinnedMembers.remove(info)
|
||||
for (listener in myListeners) {
|
||||
listener.onPinnedItemRemoved(info)
|
||||
}
|
||||
}
|
||||
|
||||
fun isItemPinned(node: XValueNodeImpl?) : Boolean {
|
||||
val typeName = ((node?.parent as? XValueContainerNode<*>)?.valueContainer as? PinToTopParentValue)?.getTypeName() ?: return false
|
||||
return myPinnedMembers.containsKey(
|
||||
PinnedItemInfo.getKey(typeName, node.name ?: ""))
|
||||
fun isItemPinned(node: XValueNodeImpl?) : Boolean = node.isPinned(this)
|
||||
|
||||
fun isPinned(pinnedItemInfo: PinnedItemInfo): Boolean {
|
||||
return myPinnedMembers.contains(pinnedItemInfo)
|
||||
}
|
||||
|
||||
private fun disposeCurrentNodeHoverSubscription() {
|
||||
@@ -119,11 +111,11 @@ open class XDebuggerPinToTopManager {
|
||||
}
|
||||
|
||||
fun saveState(state: PinToTopManagerState) {
|
||||
state.pinnedMembersList = myPinnedMembers.toList().map { it.second }.toMutableList()
|
||||
state.pinnedMembersList = myPinnedMembers.toMutableList()
|
||||
}
|
||||
|
||||
fun loadState(state: PinToTopManagerState) {
|
||||
myPinnedMembers.putAll(state.pinnedMembersList.map { Pair(it.getKey(), it) })
|
||||
myPinnedMembers.addAll(state.pinnedMembersList)
|
||||
}
|
||||
|
||||
fun isPinToTopSupported(node: XDebuggerTreeNode?) : Boolean {
|
||||
|
||||
+11
-23
@@ -2,12 +2,9 @@
|
||||
package com.intellij.xdebugger.impl.pinned.items.actions
|
||||
|
||||
import com.intellij.openapi.actionSystem.*
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.xdebugger.XDebuggerBundle
|
||||
import com.intellij.xdebugger.impl.XDebuggerUtilImpl
|
||||
import com.intellij.xdebugger.impl.pinned.items.PinToTopMemberValue
|
||||
import com.intellij.xdebugger.impl.pinned.items.PinToTopParentValue
|
||||
import com.intellij.xdebugger.impl.pinned.items.XDebuggerPinToTopManager
|
||||
import com.intellij.xdebugger.impl.pinned.items.*
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree
|
||||
import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl
|
||||
@@ -57,7 +54,7 @@ class XDebuggerPinToTopAction : XDebuggerTreeActionBase() {
|
||||
return
|
||||
}
|
||||
presentation.isVisible = true
|
||||
presentation.isEnabled = (node.parent as? XValueNodeImpl)?.valueContainer is PinToTopParentValue && valueContainer.canBePinned()
|
||||
presentation.isEnabled = node.canBePinned()
|
||||
presentation.icon = if (pinToTopManager.isItemPinned(node)) PlatformDebuggerImplIcons.PinToTop.UnpinnedItem else PlatformDebuggerImplIcons.PinToTop.PinnedItem
|
||||
presentation.text = if (pinToTopManager.isItemPinned(node)) XDebuggerBundle.message("xdebugger.unpin.action") else XDebuggerBundle.message("xdebugger.pin.to.top.action")
|
||||
|
||||
@@ -66,30 +63,21 @@ class XDebuggerPinToTopAction : XDebuggerTreeActionBase() {
|
||||
override fun perform(node: XValueNodeImpl?, nodeName: String, e: AnActionEvent) {
|
||||
node ?: return
|
||||
val project = e.project ?: return
|
||||
val nodeValue = node.valueContainer as? PinToTopMemberValue ?: return
|
||||
if (!nodeValue.canBePinned()) {
|
||||
return
|
||||
}
|
||||
val parentType = ((node.parent as? XValueNodeImpl)?.valueContainer as? PinToTopParentValue)?.getTypeName()
|
||||
|
||||
if (parentType.isNullOrEmpty()) {
|
||||
if (!node.canBePinned())
|
||||
return
|
||||
}
|
||||
|
||||
if (XDebuggerPinToTopManager.getInstance(project).isItemPinned(node)) {
|
||||
removePrioritizedItem(parentType, nodeName, project)
|
||||
val pinToTopManager = XDebuggerPinToTopManager.getInstance(project)
|
||||
|
||||
val pinInfo = node.getPinInfo()
|
||||
?: return
|
||||
|
||||
if (node.isPinned(pinToTopManager)) {
|
||||
pinToTopManager.removeItemInfo(pinInfo)
|
||||
} else {
|
||||
addPrioritizedItem(parentType, nodeName, project)
|
||||
pinToTopManager.addItemInfo(pinInfo)
|
||||
}
|
||||
|
||||
XDebuggerUtilImpl.rebuildTreeAndViews(node.tree)
|
||||
}
|
||||
|
||||
private fun addPrioritizedItem(parentType: String, nodeName: String, project: Project) {
|
||||
XDebuggerPinToTopManager.getInstance(project).addItemInfo(parentType, nodeName)
|
||||
}
|
||||
|
||||
private fun removePrioritizedItem(parentType: String, nodeName: String, project: Project) {
|
||||
XDebuggerPinToTopManager.getInstance(project).removeItemInfo(parentType, nodeName)
|
||||
}
|
||||
}
|
||||
+2
-14
@@ -24,6 +24,7 @@ import com.intellij.xdebugger.impl.frame.XValueWithInlinePresentation;
|
||||
import com.intellij.xdebugger.impl.frame.XVariablesView;
|
||||
import com.intellij.xdebugger.impl.pinned.items.PinToTopMemberValue;
|
||||
import com.intellij.xdebugger.impl.pinned.items.PinToTopParentValue;
|
||||
import com.intellij.xdebugger.impl.pinned.items.PinToTopUtilKt;
|
||||
import com.intellij.xdebugger.impl.pinned.items.actions.XDebuggerPinToTopAction;
|
||||
import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
|
||||
import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants;
|
||||
@@ -307,21 +308,8 @@ public class XValueNodeImpl extends XValueContainerNode<XValue> implements XValu
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!(myValueContainer instanceof PinToTopMemberValue)) {
|
||||
if (!PinToTopUtilKt.canBePinned(this))
|
||||
return null;
|
||||
}
|
||||
|
||||
final PinToTopMemberValue pinToTopMemberValue = (PinToTopMemberValue)myValueContainer;
|
||||
if (!pinToTopMemberValue.canBePinned()) {
|
||||
return null;
|
||||
}
|
||||
if(!(myParent instanceof XValueNodeImpl)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!(((XValueNodeImpl)myParent).myValueContainer instanceof PinToTopParentValue)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new XDebuggerTreeNodeHyperlink(XDebuggerBundle.message("xdebugger.pin.to.top.action")) {
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user