1
0
mirror of https://github.com/chylex/IntelliJ-Keyboard-Master.git synced 2024-10-17 07:42:48 +02:00

Compare commits

..

4 Commits

5 changed files with 60 additions and 15 deletions

View File

@ -8,7 +8,7 @@ plugins {
}
group = "com.chylex.intellij.keyboardmaster"
version = "0.5.4"
version = "0.5.5"
repositories {
mavenCentral()

View File

@ -8,7 +8,7 @@ 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) {
if (component is ListPopupImpl && VimNavigation.isEnabled) {
VimListNavigation.install(component.list, component)
}

View File

@ -18,9 +18,12 @@ import javax.swing.KeyStroke
import javax.swing.UIManager
object VimNavigation {
private val isEnabled = AtomicBoolean(false)
private val isEnabledFlag = AtomicBoolean(false)
private var originalPopupBindings: Array<*>? = null
val isEnabled
get() = isEnabledFlag.get()
fun register() {
val disposable = ApplicationManager.getApplication().getService(PluginDisposableService::class.java)
@ -29,7 +32,7 @@ object VimNavigation {
}
fun setEnabled(enabled: Boolean) {
if (!isEnabled.compareAndSet(!enabled, enabled)) {
if (!isEnabledFlag.compareAndSet(!enabled, enabled)) {
return
}
@ -61,7 +64,7 @@ object VimNavigation {
}
private fun handleEvent(event: AWTEvent) {
if (event is FocusEvent && event.id == FocusEvent.FOCUS_GAINED && isEnabled.get()) {
if (event is FocusEvent && event.id == FocusEvent.FOCUS_GAINED && isEnabled) {
when (val source = event.source) {
is JList<*> -> VimListNavigation.install(source)
is JTree -> VimTreeNavigation.install(source)

View File

@ -1,6 +1,7 @@
package com.chylex.intellij.keyboardmaster.feature.vimNavigation
import com.chylex.intellij.keyboardmaster.PluginDisposableService
import com.chylex.intellij.keyboardmaster.feature.vimNavigation.VimNavigationDispatcher.WrappedAction.ForKeyListener
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
@ -20,15 +21,18 @@ import java.awt.event.ActionListener
import java.awt.event.KeyEvent
import java.beans.PropertyChangeEvent
import java.util.concurrent.atomic.AtomicBoolean
import javax.swing.Action
import javax.swing.JComponent
import javax.swing.KeyStroke
internal open class VimNavigationDispatcher<T : JComponent>(final override val component: T, private val rootNode: KeyStrokeNode.Parent<VimNavigationDispatcher<T>>) : DumbAwareAction(), ComponentHolder {
companion object {
private val DISPOSABLE = ApplicationManager.getApplication().getService(PluginDisposableService::class.java)
private val ENTER_KEY = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)
private fun findOriginalEnterAction(component: JComponent): WrappedAction? {
@JvmStatic
protected val ENTER_KEY: KeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)
private fun findOriginalEnterAction(component: JComponent): WrappedAction {
var originalEnterAction: WrappedAction? = null
for (container in JBIterable.generate<Container>(component) { it.parent }) {
@ -36,7 +40,7 @@ internal open class VimNavigationDispatcher<T : JComponent>(final override val c
continue
}
container.getActionForKeyStroke(ENTER_KEY)?.let {
container.getActionForKeyStroke(ENTER_KEY)?.takeUnless(::isIgnoredEnterAction)?.let {
originalEnterAction = WrappedAction.ForActionListener(container, it)
}
@ -47,7 +51,11 @@ internal open class VimNavigationDispatcher<T : JComponent>(final override val c
}
}
return originalEnterAction
return originalEnterAction ?: ForKeyListener(component)
}
private fun isIgnoredEnterAction(action: ActionListener): Boolean {
return action is Action && action.getValue(Action.NAME) == "toggle"
}
@Suppress("UnstableApiUsage")
@ -100,15 +108,23 @@ internal open class VimNavigationDispatcher<T : JComponent>(final override val c
}
private fun handleEnterKeyPress(actionEvent: AnActionEvent, keyEvent: KeyEvent) {
handleEnterKeyPress { originalEnterAction.perform(actionEvent, keyEvent) }
}
protected inline fun handleEnterKeyPress(originalAction: () -> Unit) {
if (isSearching.compareAndSet(true, false)) {
when (val supply = SpeedSearchSupply.getSupply(component)) {
is SpeedSearchBase<*> -> supply.hidePopup()
is SpeedSearch -> supply.reset()
}
stopSpeedSearch()
}
else {
currentNode = rootNode
originalEnterAction?.perform(actionEvent, keyEvent)
originalAction()
}
}
protected open fun stopSpeedSearch() {
when (val supply = SpeedSearchSupply.getSupply(component)) {
is SpeedSearchBase<*> -> supply.hidePopup()
is SpeedSearch -> supply.reset()
}
}
@ -132,7 +148,7 @@ internal open class VimNavigationDispatcher<T : JComponent>(final override val c
private sealed interface WrappedAction {
fun perform(actionEvent: AnActionEvent, keyEvent: KeyEvent)
class ForActionListener(val component: JComponent, val listener: ActionListener) : WrappedAction {
class ForActionListener(private val component: JComponent, private val listener: ActionListener) : WrappedAction {
override fun perform(actionEvent: AnActionEvent, keyEvent: KeyEvent) {
listener.actionPerformed(ActionEvent(component, ActionEvent.ACTION_PERFORMED, "Enter", keyEvent.`when`, keyEvent.modifiersEx))
}
@ -143,5 +159,12 @@ internal open class VimNavigationDispatcher<T : JComponent>(final override val c
action.actionPerformed(actionEvent)
}
}
class ForKeyListener(private val component: JComponent) : WrappedAction {
override fun perform(actionEvent: AnActionEvent, keyEvent: KeyEvent) {
val unconsumedKeyEvent = KeyEvent(component, keyEvent.id, keyEvent.`when`, keyEvent.modifiersEx, keyEvent.keyCode, keyEvent.keyChar, keyEvent.keyLocation)
component.dispatchEvent(unconsumedKeyEvent)
}
}
}
}

View File

@ -8,6 +8,7 @@ import com.intellij.openapi.ui.getUserData
import com.intellij.openapi.ui.putUserData
import com.intellij.openapi.util.Key
import com.intellij.ui.popup.WizardPopup
import com.intellij.ui.popup.list.ListPopupImpl
import com.intellij.ui.speedSearch.SpeedSearch
import com.intellij.ui.speedSearch.SpeedSearchSupply
import java.awt.event.ActionEvent
@ -85,6 +86,24 @@ internal object VimListNavigation {
// WizardPopup only checks key codes against its input map, but key codes may be undefined for some characters.
popup.registerAction("KeyboardMaster-VimListNavigation-PauseSpeedSearch", KeyStroke.getKeyStroke(KeyEvent.CHAR_UNDEFINED, 0), pauseAction)
popup.registerAction("KeyboardMaster-VimListNavigation-PauseSpeedSearch", KeyStroke.getKeyStroke(KeyEvent.CHAR_UNDEFINED, KeyEvent.SHIFT_DOWN_MASK), pauseAction)
if (popup is ListPopupImpl) {
popup.registerAction("KeyboardMaster-VimListNavigation-Enter", ENTER_KEY, object : AbstractAction() {
override fun actionPerformed(e: ActionEvent) {
handleEnterKeyPress { popup.handleSelect(true, createEnterEvent(e)) }
}
private fun createEnterEvent(e: ActionEvent): KeyEvent {
return KeyEvent(component, KeyEvent.KEY_PRESSED, e.`when`, e.modifiers, KeyEvent.VK_ENTER, KeyEvent.CHAR_UNDEFINED)
}
})
}
}
override fun stopSpeedSearch() {
val selectedValue = component.selectedValue
super.stopSpeedSearch()
component.setSelectedValue(selectedValue, true)
}
private class PauseSpeedSearchAction(private val dispatcher: VimNavigationDispatcher<JList<*>>, private val speedSearch: SpeedSearch) : AbstractAction() {