mirror of
https://github.com/chylex/IntelliJ-Keyboard-Master.git
synced 2025-10-16 17:39:37 +02:00
Compare commits
6 Commits
2d0570de1a
...
main
Author | SHA1 | Date | |
---|---|---|---|
46657f2f7e
|
|||
48b342644b
|
|||
5c7e20fd78
|
|||
ce7ec24d3a
|
|||
9fb1774f6d
|
|||
90372acdfe
|
@@ -6,7 +6,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "com.chylex.intellij.keyboardmaster"
|
group = "com.chylex.intellij.keyboardmaster"
|
||||||
version = "0.6.2"
|
version = "0.6.4"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@@ -1,19 +0,0 @@
|
|||||||
package com.chylex.intellij.keyboardmaster.feature.vimNavigation
|
|
||||||
|
|
||||||
import com.chylex.intellij.keyboardmaster.feature.vimNavigation.components.VimListNavigation
|
|
||||||
import com.intellij.ui.UiInterceptors.PersistentUiInterceptor
|
|
||||||
import com.intellij.ui.awt.RelativePoint
|
|
||||||
import com.intellij.ui.popup.AbstractPopup
|
|
||||||
import com.intellij.ui.popup.list.ListPopupImpl
|
|
||||||
|
|
||||||
internal object PopupInterceptor : PersistentUiInterceptor<AbstractPopup>(AbstractPopup::class.java) {
|
|
||||||
override fun shouldIntercept(component: AbstractPopup): Boolean {
|
|
||||||
if (component is ListPopupImpl && VimNavigation.isEnabled) {
|
|
||||||
VimListNavigation.install(component.list, component)
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun doIntercept(component: AbstractPopup, owner: RelativePoint?) {}
|
|
||||||
}
|
|
@@ -6,11 +6,15 @@ import com.chylex.intellij.keyboardmaster.feature.vimNavigation.components.VimTa
|
|||||||
import com.chylex.intellij.keyboardmaster.feature.vimNavigation.components.VimTreeNavigation
|
import com.chylex.intellij.keyboardmaster.feature.vimNavigation.components.VimTreeNavigation
|
||||||
import com.intellij.ide.ui.UISettings
|
import com.intellij.ide.ui.UISettings
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
import com.intellij.ui.UiInterceptors
|
import com.intellij.openapi.ui.getUserData
|
||||||
|
import com.intellij.openapi.ui.popup.util.PopupUtil
|
||||||
|
import com.intellij.openapi.ui.putUserData
|
||||||
|
import com.intellij.openapi.util.Key
|
||||||
import com.intellij.util.ui.StartupUiUtil
|
import com.intellij.util.ui.StartupUiUtil
|
||||||
import java.awt.AWTEvent
|
import java.awt.AWTEvent
|
||||||
import java.awt.event.FocusEvent
|
import java.awt.event.FocusEvent
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
import javax.swing.JComponent
|
||||||
import javax.swing.JList
|
import javax.swing.JList
|
||||||
import javax.swing.JTable
|
import javax.swing.JTable
|
||||||
import javax.swing.JTree
|
import javax.swing.JTree
|
||||||
@@ -18,6 +22,8 @@ import javax.swing.KeyStroke
|
|||||||
import javax.swing.UIManager
|
import javax.swing.UIManager
|
||||||
|
|
||||||
object VimNavigation {
|
object VimNavigation {
|
||||||
|
private val KEY_INSTALLED = Key.create<Boolean>("KeyboardMaster-VimNavigation-Installed")
|
||||||
|
|
||||||
private val isEnabledFlag = AtomicBoolean(false)
|
private val isEnabledFlag = AtomicBoolean(false)
|
||||||
private var originalPopupBindings: Array<*>? = null
|
private var originalPopupBindings: Array<*>? = null
|
||||||
|
|
||||||
@@ -28,7 +34,6 @@ object VimNavigation {
|
|||||||
val disposable = ApplicationManager.getApplication().getService(PluginDisposableService::class.java)
|
val disposable = ApplicationManager.getApplication().getService(PluginDisposableService::class.java)
|
||||||
|
|
||||||
StartupUiUtil.addAwtListener(AWTEvent.FOCUS_EVENT_MASK, disposable, ::handleEvent)
|
StartupUiUtil.addAwtListener(AWTEvent.FOCUS_EVENT_MASK, disposable, ::handleEvent)
|
||||||
UiInterceptors.registerPersistent(disposable, PopupInterceptor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setEnabled(enabled: Boolean) {
|
fun setEnabled(enabled: Boolean) {
|
||||||
@@ -66,9 +71,19 @@ object VimNavigation {
|
|||||||
private fun handleEvent(event: AWTEvent) {
|
private fun handleEvent(event: AWTEvent) {
|
||||||
if (event is FocusEvent && event.id == FocusEvent.FOCUS_GAINED && isEnabled) {
|
if (event is FocusEvent && event.id == FocusEvent.FOCUS_GAINED && isEnabled) {
|
||||||
when (val source = event.source) {
|
when (val source = event.source) {
|
||||||
is JList<*> -> VimListNavigation.install(source)
|
is JList<*> -> installTo(source, VimListNavigation::install)
|
||||||
is JTree -> VimTreeNavigation.install(source)
|
is JTree -> installTo(source, VimTreeNavigation::install)
|
||||||
is JTable -> VimTableNavigation.install(source)
|
is JTable -> installTo(source, VimTableNavigation::install)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun <T : JComponent> installTo(component: T, installer: (T) -> Unit) {
|
||||||
|
if (component.getUserData(KEY_INSTALLED) == null) {
|
||||||
|
component.putUserData(KEY_INSTALLED, true)
|
||||||
|
|
||||||
|
if (PopupUtil.getPopupContainerFor(component) == null) {
|
||||||
|
installer(component)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -22,11 +22,7 @@ internal object VimListNavigation {
|
|||||||
|
|
||||||
private val ROOT_NODE = VimCommonNavigation.commonRootNode<JList<*>>() + Parent(
|
private val ROOT_NODE = VimCommonNavigation.commonRootNode<JList<*>>() + Parent(
|
||||||
mapOf(
|
mapOf(
|
||||||
KeyStroke.getKeyStroke('g') to Parent(
|
KeyStroke.getKeyStroke('g') to IdeaAction("List-selectFirstRow"),
|
||||||
mapOf(
|
|
||||||
KeyStroke.getKeyStroke('g') to IdeaAction("List-selectFirstRow"),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
KeyStroke.getKeyStroke('G') to IdeaAction("List-selectLastRow"),
|
KeyStroke.getKeyStroke('G') to IdeaAction("List-selectLastRow"),
|
||||||
KeyStroke.getKeyStroke('h') to IdeaAction("List-selectPreviousColumn"),
|
KeyStroke.getKeyStroke('h') to IdeaAction("List-selectPreviousColumn"),
|
||||||
KeyStroke.getKeyStroke('H') to IdeaAction("List-selectPreviousColumnExtendSelection"),
|
KeyStroke.getKeyStroke('H') to IdeaAction("List-selectPreviousColumnExtendSelection"),
|
||||||
|
@@ -14,11 +14,7 @@ internal object VimTableNavigation {
|
|||||||
|
|
||||||
private val ROOT_NODE = VimCommonNavigation.commonRootNode<JTable>() + Parent(
|
private val ROOT_NODE = VimCommonNavigation.commonRootNode<JTable>() + Parent(
|
||||||
mapOf(
|
mapOf(
|
||||||
KeyStroke.getKeyStroke('g') to Parent(
|
KeyStroke.getKeyStroke('g') to IdeaAction("Table-selectFirstRow"),
|
||||||
mapOf(
|
|
||||||
KeyStroke.getKeyStroke('g') to IdeaAction("Table-selectFirstRow"),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
KeyStroke.getKeyStroke('G') to IdeaAction("Table-selectLastRow"),
|
KeyStroke.getKeyStroke('G') to IdeaAction("Table-selectLastRow"),
|
||||||
KeyStroke.getKeyStroke('h') to IdeaAction("Table-selectPreviousColumn"),
|
KeyStroke.getKeyStroke('h') to IdeaAction("Table-selectPreviousColumn"),
|
||||||
KeyStroke.getKeyStroke('H') to IdeaAction("Table-selectPreviousColumnExtendSelection"),
|
KeyStroke.getKeyStroke('H') to IdeaAction("Table-selectPreviousColumnExtendSelection"),
|
||||||
|
@@ -13,6 +13,7 @@ import com.intellij.ui.tree.ui.DefaultTreeUI
|
|||||||
import java.awt.event.KeyEvent
|
import java.awt.event.KeyEvent
|
||||||
import javax.swing.JTree
|
import javax.swing.JTree
|
||||||
import javax.swing.KeyStroke
|
import javax.swing.KeyStroke
|
||||||
|
import javax.swing.tree.TreeModel
|
||||||
import javax.swing.tree.TreePath
|
import javax.swing.tree.TreePath
|
||||||
|
|
||||||
internal object VimTreeNavigation {
|
internal object VimTreeNavigation {
|
||||||
@@ -20,31 +21,36 @@ internal object VimTreeNavigation {
|
|||||||
|
|
||||||
private val ROOT_NODE = VimCommonNavigation.commonRootNode<JTree>() + Parent(
|
private val ROOT_NODE = VimCommonNavigation.commonRootNode<JTree>() + Parent(
|
||||||
mapOf(
|
mapOf(
|
||||||
|
KeyStroke.getKeyStroke('a') to Parent(
|
||||||
|
mapOf(
|
||||||
|
KeyStroke.getKeyStroke('o') to ExpandAll,
|
||||||
|
KeyStroke.getKeyStroke('x') to CollapseAll,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
KeyStroke.getKeyStroke('f') to SelectFirstSibling,
|
||||||
|
KeyStroke.getKeyStroke('F') to SelectLastSibling,
|
||||||
KeyStroke.getKeyStroke('g') to Parent(
|
KeyStroke.getKeyStroke('g') to Parent(
|
||||||
mapOf(
|
mapOf(
|
||||||
KeyStroke.getKeyStroke('g') to IdeaAction("Tree-selectFirst"),
|
KeyStroke.getKeyStroke('g') to IdeaAction("Tree-selectFirst"),
|
||||||
KeyStroke.getKeyStroke('j') to SelectLastSibling,
|
KeyStroke.getKeyStroke('j') to IdeaAction("Tree-selectNextSibling"),
|
||||||
KeyStroke.getKeyStroke('k') to SelectFirstSibling,
|
KeyStroke.getKeyStroke('k') to IdeaAction("Tree-selectPreviousSibling"),
|
||||||
KeyStroke.getKeyStroke('o') to ExpandChildrenToNextLevel,
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
KeyStroke.getKeyStroke('G') to IdeaAction("Tree-selectLast"),
|
KeyStroke.getKeyStroke('G') to IdeaAction("Tree-selectLast"),
|
||||||
KeyStroke.getKeyStroke('h') to CollapseSelfOrMoveToParentNode,
|
KeyStroke.getKeyStroke('h') to CollapseSelfOrMoveToParentNode,
|
||||||
KeyStroke.getKeyStroke('H') to CollapseUntilRootNode,
|
KeyStroke.getKeyStroke('H') to CollapseUntilRootNode,
|
||||||
KeyStroke.getKeyStroke('j') to IdeaAction("Tree-selectNext"),
|
KeyStroke.getKeyStroke('j') to IdeaAction("Tree-selectNext"),
|
||||||
KeyStroke.getKeyStroke('j', KeyEvent.ALT_DOWN_MASK) to IdeaAction("Tree-selectNextSibling"),
|
|
||||||
KeyStroke.getKeyStroke('J') to IdeaAction("Tree-selectNextExtendSelection"),
|
KeyStroke.getKeyStroke('J') to IdeaAction("Tree-selectNextExtendSelection"),
|
||||||
KeyStroke.getKeyStroke('k') to IdeaAction("Tree-selectPrevious"),
|
KeyStroke.getKeyStroke('k') to IdeaAction("Tree-selectPrevious"),
|
||||||
KeyStroke.getKeyStroke('k', KeyEvent.ALT_DOWN_MASK) to IdeaAction("Tree-selectPreviousSibling"),
|
|
||||||
KeyStroke.getKeyStroke('K') to IdeaAction("Tree-selectPreviousExtendSelection"),
|
KeyStroke.getKeyStroke('K') to IdeaAction("Tree-selectPreviousExtendSelection"),
|
||||||
KeyStroke.getKeyStroke('l') to ExpandSelfOrMoveToFirstChildNode,
|
KeyStroke.getKeyStroke('l') to ExpandSelfOrMoveToFirstChildNode,
|
||||||
KeyStroke.getKeyStroke('L') to ExpandUntilFirstLeafNode,
|
KeyStroke.getKeyStroke('L') to ExpandUntilFirstLeafNode,
|
||||||
KeyStroke.getKeyStroke('o') to ExpandOrCollapseTreeNode,
|
KeyStroke.getKeyStroke('o') to ExpandChildrenToNextLevel,
|
||||||
KeyStroke.getKeyStroke('O') to IdeaAction("FullyExpandTreeNode"),
|
KeyStroke.getKeyStroke('O') to IdeaAction("FullyExpandTreeNode"),
|
||||||
KeyStroke.getKeyStroke('p') to IdeaAction("Tree-selectParentNoCollapse"),
|
KeyStroke.getKeyStroke('p') to IdeaAction("Tree-selectParentNoCollapse"),
|
||||||
KeyStroke.getKeyStroke('P') to IdeaAction("Tree-selectFirst"),
|
KeyStroke.getKeyStroke('P') to IdeaAction("Tree-selectFirst"),
|
||||||
KeyStroke.getKeyStroke('x') to CollapseSelfOrParentNode,
|
KeyStroke.getKeyStroke('x') to CollapseChildrenToPreviousLevel,
|
||||||
KeyStroke.getKeyStroke('X') to CollapseAll,
|
KeyStroke.getKeyStroke('X') to CollapseSelf,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -54,20 +60,138 @@ internal object VimTreeNavigation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private data object ExpandOrCollapseTreeNode : ActionNode<VimNavigationDispatcher<JTree>> {
|
private data object CollapseSelf : ActionNode<VimNavigationDispatcher<JTree>> {
|
||||||
|
override fun performAction(holder: VimNavigationDispatcher<JTree>, actionEvent: AnActionEvent, keyEvent: KeyEvent) {
|
||||||
|
val tree = holder.component
|
||||||
|
val path = tree.selectionPath ?: return
|
||||||
|
|
||||||
|
collapseAndScroll(tree, path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private data object CollapseSelfOrMoveToParentNode : ActionNode<VimNavigationDispatcher<JTree>> {
|
||||||
override fun performAction(holder: VimNavigationDispatcher<JTree>, actionEvent: AnActionEvent, keyEvent: KeyEvent) {
|
override fun performAction(holder: VimNavigationDispatcher<JTree>, actionEvent: AnActionEvent, keyEvent: KeyEvent) {
|
||||||
val tree = holder.component
|
val tree = holder.component
|
||||||
val path = tree.selectionPath ?: return
|
val path = tree.selectionPath ?: return
|
||||||
|
|
||||||
if (tree.isExpanded(path)) {
|
if (tree.isExpanded(path)) {
|
||||||
tree.collapsePath(path)
|
collapseAndScroll(tree, path)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
runWithoutAutoExpand(tree) { tree.expandPath(path) }
|
withParentPath(tree, path) { selectRow(tree, it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private data object CollapseUntilRootNode : ActionNode<VimNavigationDispatcher<JTree>> {
|
||||||
|
override fun performAction(holder: VimNavigationDispatcher<JTree>, actionEvent: AnActionEvent, keyEvent: KeyEvent) {
|
||||||
|
val tree = holder.component
|
||||||
|
val path = tree.selectionPath ?: return
|
||||||
|
|
||||||
|
var parentPath = path
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
parentPath = parentPath.parentPath.takeUnless { isInvisibleRoot(tree, it) } ?: break
|
||||||
|
}
|
||||||
|
|
||||||
|
collapseAndScroll(tree, parentPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private data object CollapseAll : ActionNode<VimNavigationDispatcher<JTree>> {
|
||||||
|
override fun performAction(holder: VimNavigationDispatcher<JTree>, actionEvent: AnActionEvent, keyEvent: KeyEvent) {
|
||||||
|
val tree = holder.component
|
||||||
|
|
||||||
|
var row = 0
|
||||||
|
|
||||||
|
while (row < tree.rowCount) {
|
||||||
|
tree.collapseRow(row)
|
||||||
|
row++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private data object CollapseChildrenToPreviousLevel : ActionNode<VimNavigationDispatcher<JTree>> {
|
||||||
|
override fun performAction(holder: VimNavigationDispatcher<JTree>, actionEvent: AnActionEvent, keyEvent: KeyEvent) {
|
||||||
|
val tree = holder.component
|
||||||
|
val model = tree.model
|
||||||
|
val path = tree.selectionPath?.takeIf(tree::isExpanded) ?: return
|
||||||
|
|
||||||
|
var currentLevel = mutableListOf(path)
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
val nextLevel = mutableListOf<TreePath>()
|
||||||
|
|
||||||
|
for (parentPath in currentLevel) {
|
||||||
|
forEachChild(model, parentPath) {
|
||||||
|
val childPath = parentPath.pathByAddingChild(it)
|
||||||
|
if (tree.isExpanded(childPath)) {
|
||||||
|
nextLevel.add(childPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextLevel.isNotEmpty()) {
|
||||||
|
currentLevel = nextLevel
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (parentPath in currentLevel) {
|
||||||
|
tree.collapsePath(parentPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private data object ExpandAll : ActionNode<VimNavigationDispatcher<JTree>> {
|
||||||
|
override fun performAction(holder: VimNavigationDispatcher<JTree>, actionEvent: AnActionEvent, keyEvent: KeyEvent) {
|
||||||
|
val tree = holder.component
|
||||||
|
|
||||||
|
var row = 0
|
||||||
|
|
||||||
|
while (row < tree.rowCount) {
|
||||||
|
tree.expandRow(row)
|
||||||
|
row++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private data object ExpandChildrenToNextLevel : ActionNode<VimNavigationDispatcher<JTree>> {
|
||||||
|
override fun performAction(holder: VimNavigationDispatcher<JTree>, actionEvent: AnActionEvent, keyEvent: KeyEvent) {
|
||||||
|
val tree = holder.component
|
||||||
|
val model = tree.model
|
||||||
|
val path = tree.selectionPath?.takeUnless { isLeaf(tree, it) } ?: return
|
||||||
|
|
||||||
|
var pathsToExpand = mutableListOf(path)
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (pathsToExpand.any(tree::isCollapsed)) {
|
||||||
|
runWithoutAutoExpand(tree) { pathsToExpand.forEach(tree::expandPath) }
|
||||||
|
|
||||||
|
for (path in pathsToExpand) {
|
||||||
|
forEachChild(model, path) { tree.collapsePath(path.pathByAddingChild(it)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
val nextPathsToExpand = mutableListOf<TreePath>()
|
||||||
|
|
||||||
|
for (parentPath in pathsToExpand) {
|
||||||
|
forEachChild(model, parentPath) {
|
||||||
|
if (!model.isLeaf(it)) {
|
||||||
|
nextPathsToExpand.add(parentPath.pathByAddingChild(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pathsToExpand = nextPathsToExpand
|
||||||
|
} while (pathsToExpand.isNotEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private data object ExpandSelfOrMoveToFirstChildNode : ActionNode<VimNavigationDispatcher<JTree>> {
|
private data object ExpandSelfOrMoveToFirstChildNode : ActionNode<VimNavigationDispatcher<JTree>> {
|
||||||
override fun performAction(holder: VimNavigationDispatcher<JTree>, actionEvent: AnActionEvent, keyEvent: KeyEvent) {
|
override fun performAction(holder: VimNavigationDispatcher<JTree>, actionEvent: AnActionEvent, keyEvent: KeyEvent) {
|
||||||
val tree = holder.component
|
val tree = holder.component
|
||||||
@@ -98,96 +222,6 @@ internal object VimTreeNavigation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private data object CollapseSelfOrMoveToParentNode : ActionNode<VimNavigationDispatcher<JTree>> {
|
|
||||||
override fun performAction(holder: VimNavigationDispatcher<JTree>, actionEvent: AnActionEvent, keyEvent: KeyEvent) {
|
|
||||||
val tree = holder.component
|
|
||||||
val path = tree.selectionPath ?: return
|
|
||||||
|
|
||||||
if (tree.isExpanded(path)) {
|
|
||||||
collapseAndScroll(tree, path)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
withParentPath(tree, path) { selectRow(tree, it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private data object CollapseSelfOrParentNode : ActionNode<VimNavigationDispatcher<JTree>> {
|
|
||||||
override fun performAction(holder: VimNavigationDispatcher<JTree>, actionEvent: AnActionEvent, keyEvent: KeyEvent) {
|
|
||||||
val tree = holder.component
|
|
||||||
val path = tree.selectionPath ?: return
|
|
||||||
|
|
||||||
if (tree.isExpanded(path)) {
|
|
||||||
collapseAndScroll(tree, path)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
withParentPath(tree, path) { collapseAndScroll(tree, it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private data object CollapseUntilRootNode : ActionNode<VimNavigationDispatcher<JTree>> {
|
|
||||||
override fun performAction(holder: VimNavigationDispatcher<JTree>, actionEvent: AnActionEvent, keyEvent: KeyEvent) {
|
|
||||||
val tree = holder.component
|
|
||||||
val path = tree.selectionPath ?: return
|
|
||||||
|
|
||||||
var parentPath = path
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
parentPath = parentPath.parentPath.takeUnless { isInvisibleRoot(tree, it) } ?: break
|
|
||||||
}
|
|
||||||
|
|
||||||
collapseAndScroll(tree, parentPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private data object CollapseAll : ActionNode<VimNavigationDispatcher<JTree>> {
|
|
||||||
override fun performAction(holder: VimNavigationDispatcher<JTree>, actionEvent: AnActionEvent, keyEvent: KeyEvent) {
|
|
||||||
val tree = holder.component
|
|
||||||
|
|
||||||
CollapseUntilRootNode.performAction(holder, actionEvent, keyEvent)
|
|
||||||
|
|
||||||
var row = 0
|
|
||||||
|
|
||||||
while (row < tree.rowCount) {
|
|
||||||
tree.collapseRow(row)
|
|
||||||
row++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private data object ExpandChildrenToNextLevel : ActionNode<VimNavigationDispatcher<JTree>> {
|
|
||||||
override fun performAction(holder: VimNavigationDispatcher<JTree>, actionEvent: AnActionEvent, keyEvent: KeyEvent) {
|
|
||||||
val tree = holder.component
|
|
||||||
val model = tree.model
|
|
||||||
val path = tree.selectionPath?.takeUnless { isLeaf(tree, it) } ?: return
|
|
||||||
|
|
||||||
var pathsToExpand = mutableListOf(path)
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (pathsToExpand.any(tree::isCollapsed)) {
|
|
||||||
runWithoutAutoExpand(tree) { pathsToExpand.forEach(tree::expandPath) }
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
val nextPathsToExpand = mutableListOf<TreePath>()
|
|
||||||
|
|
||||||
for (parentPath in pathsToExpand) {
|
|
||||||
val lastPathComponent = parentPath.lastPathComponent
|
|
||||||
|
|
||||||
for (i in 0 until model.getChildCount(lastPathComponent)) {
|
|
||||||
val child = model.getChild(lastPathComponent, i)
|
|
||||||
if (!model.isLeaf(child)) {
|
|
||||||
nextPathsToExpand.add(parentPath.pathByAddingChild(child))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pathsToExpand = nextPathsToExpand
|
|
||||||
} while (pathsToExpand.isNotEmpty())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private data object SelectFirstSibling : ActionNode<VimNavigationDispatcher<JTree>> {
|
private data object SelectFirstSibling : ActionNode<VimNavigationDispatcher<JTree>> {
|
||||||
override fun performAction(holder: VimNavigationDispatcher<JTree>, actionEvent: AnActionEvent, keyEvent: KeyEvent) {
|
override fun performAction(holder: VimNavigationDispatcher<JTree>, actionEvent: AnActionEvent, keyEvent: KeyEvent) {
|
||||||
val tree = holder.component
|
val tree = holder.component
|
||||||
@@ -226,6 +260,14 @@ internal object VimTreeNavigation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inline fun forEachChild(model: TreeModel, path: TreePath, action: (Any) -> Unit) {
|
||||||
|
val lastPathComponent = path.lastPathComponent
|
||||||
|
|
||||||
|
for (i in 0 until model.getChildCount(lastPathComponent)) {
|
||||||
|
action(model.getChild(lastPathComponent, i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private inline fun runWithoutAutoExpand(tree: JTree, action: () -> Unit) {
|
private inline fun runWithoutAutoExpand(tree: JTree, action: () -> Unit) {
|
||||||
val previousAutoExpandValue = ClientProperty.get(tree, DefaultTreeUI.AUTO_EXPAND_ALLOWED)
|
val previousAutoExpandValue = ClientProperty.get(tree, DefaultTreeUI.AUTO_EXPAND_ALLOWED)
|
||||||
ClientProperty.put(tree, DefaultTreeUI.AUTO_EXPAND_ALLOWED, false)
|
ClientProperty.put(tree, DefaultTreeUI.AUTO_EXPAND_ALLOWED, false)
|
||||||
|
Reference in New Issue
Block a user