1
0
mirror of https://github.com/chylex/IntelliJ-Keyboard-Master.git synced 2025-04-22 08:15:43 +02:00

Implement vim-style navigation for menu popups

This commit is contained in:
chylex 2024-05-05 05:16:39 +02:00
parent d3989a0e87
commit 5ca46cf8b2
Signed by: chylex
GPG Key ID: 4DE42C8F19A80548
2 changed files with 42 additions and 4 deletions
src/main/kotlin/com/chylex/intellij/keyboardmaster
configuration
feature/vimNavigation

View File

@ -37,7 +37,7 @@ class PluginConfiguration : PersistentStateComponent<PluginConfiguration> {
private fun update(instance: PluginConfiguration) = with(instance) {
CodeCompletionPopupConfiguration.updateShortcuts(codeCompletionItemShortcuts, codeCompletionNextPageShortcut, codeCompletionPrevPageShortcut)
VimNavigation.isEnabled = enableVimNavigation
VimNavigation.setEnabled(enableVimNavigation)
}
}

View File

@ -4,18 +4,22 @@ import com.chylex.intellij.keyboardmaster.PluginDisposableService
import com.chylex.intellij.keyboardmaster.feature.vimNavigation.components.VimListNavigation
import com.chylex.intellij.keyboardmaster.feature.vimNavigation.components.VimTableNavigation
import com.chylex.intellij.keyboardmaster.feature.vimNavigation.components.VimTreeNavigation
import com.intellij.ide.ui.UISettings
import com.intellij.openapi.application.ApplicationManager
import com.intellij.ui.UiInterceptors
import com.intellij.util.ui.StartupUiUtil
import java.awt.AWTEvent
import java.awt.event.FocusEvent
import java.util.concurrent.atomic.AtomicBoolean
import javax.swing.JList
import javax.swing.JTable
import javax.swing.JTree
import javax.swing.KeyStroke
import javax.swing.UIManager
object VimNavigation {
@Volatile
var isEnabled = false
private val isEnabled = AtomicBoolean(false)
private var originalPopupBindings: Array<*>? = null
fun register() {
val disposable = ApplicationManager.getApplication().getService(PluginDisposableService::class.java)
@ -24,8 +28,42 @@ object VimNavigation {
UiInterceptors.registerPersistent(disposable, PopupInterceptor)
}
fun setEnabled(enabled: Boolean) {
if (!isEnabled.compareAndSet(!enabled, enabled)) {
return
}
ApplicationManager.getApplication().invokeLater {
if (enabled) {
val originalBindings = (UIManager.get("PopupMenu.selectedWindowInputMapBindings") as Array<*>).also { originalPopupBindings = it }
val updatedBindings = mutableListOf(*originalBindings)
updatedBindings.add(KeyStroke.getKeyStroke('h'))
updatedBindings.add("selectParent")
updatedBindings.add(KeyStroke.getKeyStroke('j'))
updatedBindings.add("selectNext")
updatedBindings.add(KeyStroke.getKeyStroke('k'))
updatedBindings.add("selectPrevious")
updatedBindings.add(KeyStroke.getKeyStroke('l'))
updatedBindings.add("selectChild")
updatedBindings.add(KeyStroke.getKeyStroke('q'))
updatedBindings.add("cancel")
UIManager.put("PopupMenu.selectedWindowInputMapBindings", updatedBindings.toTypedArray())
UISettings.getInstance().disableMnemonics = true
}
else {
UIManager.put("PopupMenu.selectedWindowInputMapBindings", originalPopupBindings)
}
}
}
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.get()) {
when (val source = event.source) {
is JList<*> -> VimListNavigation.install(source)
is JTree -> VimTreeNavigation.install(source)