mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2025-02-26 05:46:00 +01:00
Better widget
This commit is contained in:
parent
c12082affc
commit
52cf10cb2e
src/main/java/com/maddyhome/idea/vim
@ -94,10 +94,10 @@ import com.maddyhome.idea.vim.newapi.vim
|
||||
import com.maddyhome.idea.vim.state.mode.inSelectMode
|
||||
import com.maddyhome.idea.vim.state.mode.mode
|
||||
import com.maddyhome.idea.vim.state.mode.selectionType
|
||||
import com.maddyhome.idea.vim.ui.widgets.macro.MacroWidgetListener
|
||||
import com.maddyhome.idea.vim.ui.ShowCmdOptionChangeListener
|
||||
import com.maddyhome.idea.vim.ui.widgets.mode.ModeWidgetListener
|
||||
import com.maddyhome.idea.vim.ui.ex.ExEntryPanel
|
||||
import com.maddyhome.idea.vim.ui.widgets.macro.macroWidgetOptionListener
|
||||
import com.maddyhome.idea.vim.ui.widgets.mode.modeWidgetOptionListener
|
||||
import com.maddyhome.idea.vim.vimDisposable
|
||||
import java.awt.event.MouseAdapter
|
||||
import java.awt.event.MouseEvent
|
||||
@ -160,10 +160,10 @@ internal object VimListenerManager {
|
||||
optionGroup.addGlobalOptionChangeListener(Options.showcmd, ShowCmdOptionChangeListener)
|
||||
|
||||
// This code is executed after ideavimrc execution, so we trigger onGlobalOptionChanged just in case
|
||||
optionGroup.addGlobalOptionChangeListener(IjOptions.showmodewidget, ModeWidgetListener)
|
||||
optionGroup.addGlobalOptionChangeListener(IjOptions.showmodewidget, MacroWidgetListener)
|
||||
ModeWidgetListener.onGlobalOptionChanged()
|
||||
MacroWidgetListener.onGlobalOptionChanged()
|
||||
optionGroup.addGlobalOptionChangeListener(IjOptions.showmodewidget, modeWidgetOptionListener)
|
||||
optionGroup.addGlobalOptionChangeListener(IjOptions.showmodewidget, macroWidgetOptionListener)
|
||||
modeWidgetOptionListener.onGlobalOptionChanged()
|
||||
macroWidgetOptionListener.onGlobalOptionChanged()
|
||||
|
||||
optionGroup.addEffectiveOptionValueChangeListener(Options.guicursor, GuicursorChangeListener)
|
||||
|
||||
@ -184,8 +184,8 @@ internal object VimListenerManager {
|
||||
optionGroup.removeEffectiveOptionValueChangeListener(Options.relativenumber, EditorGroup.NumberChangeListener.INSTANCE)
|
||||
optionGroup.removeEffectiveOptionValueChangeListener(Options.scrolloff, ScrollGroup.ScrollOptionsChangeListener)
|
||||
optionGroup.removeGlobalOptionChangeListener(Options.showcmd, ShowCmdOptionChangeListener)
|
||||
optionGroup.removeGlobalOptionChangeListener(IjOptions.showmodewidget, ModeWidgetListener)
|
||||
optionGroup.removeGlobalOptionChangeListener(IjOptions.showmodewidget, MacroWidgetListener)
|
||||
optionGroup.removeGlobalOptionChangeListener(IjOptions.showmodewidget, modeWidgetOptionListener)
|
||||
optionGroup.removeGlobalOptionChangeListener(IjOptions.showmodewidget, macroWidgetOptionListener)
|
||||
optionGroup.removeEffectiveOptionValueChangeListener(Options.guicursor, GuicursorChangeListener)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2003-2024 The IdeaVim authors
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE.txt file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
|
||||
package com.maddyhome.idea.vim.ui.widgets
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.ProjectManager
|
||||
import com.intellij.openapi.wm.StatusBarWidgetFactory
|
||||
import com.intellij.openapi.wm.impl.status.widget.StatusBarWidgetsManager
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.common.VimPluginListener
|
||||
import com.maddyhome.idea.vim.options.GlobalOptionChangeListener
|
||||
|
||||
public class VimWidgetListener(private val widgetFactory: Class<out StatusBarWidgetFactory>) : GlobalOptionChangeListener, VimPluginListener {
|
||||
init {
|
||||
injector.listenersNotifier.vimPluginListeners.add(this)
|
||||
}
|
||||
|
||||
override fun onGlobalOptionChanged() {
|
||||
updateWidget()
|
||||
}
|
||||
|
||||
override fun turnedOn() {
|
||||
updateWidget()
|
||||
}
|
||||
|
||||
override fun turnedOff() {
|
||||
updateWidget()
|
||||
}
|
||||
|
||||
private fun updateWidget() {
|
||||
val factory = StatusBarWidgetFactory.EP_NAME.findExtension(widgetFactory) ?: return
|
||||
for (project in ProjectManager.getInstance().openProjects) {
|
||||
val statusBarWidgetsManager = project.service<StatusBarWidgetsManager>()
|
||||
statusBarWidgetsManager.updateWidget(factory)
|
||||
}
|
||||
}
|
||||
}
|
@ -8,36 +8,33 @@
|
||||
|
||||
package com.maddyhome.idea.vim.ui.widgets.macro
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.ProjectManager
|
||||
import com.intellij.openapi.wm.StatusBarWidget
|
||||
import com.intellij.openapi.wm.StatusBarWidgetFactory
|
||||
import com.intellij.openapi.wm.WindowManager
|
||||
import com.intellij.openapi.wm.impl.status.widget.StatusBarWidgetsManager
|
||||
import com.maddyhome.idea.vim.VimPlugin
|
||||
import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.common.MacroRecordingListener
|
||||
import com.maddyhome.idea.vim.common.VimPluginListener
|
||||
import com.maddyhome.idea.vim.newapi.globalIjOptions
|
||||
import com.maddyhome.idea.vim.options.GlobalOptionChangeListener
|
||||
import com.maddyhome.idea.vim.newapi.ij
|
||||
import com.maddyhome.idea.vim.ui.widgets.VimWidgetListener
|
||||
import com.maddyhome.idea.vim.ui.widgets.mode.VimStatusBarWidget
|
||||
import java.awt.Component
|
||||
|
||||
private const val ID = "IdeaVim::Macro"
|
||||
|
||||
internal class MacroWidgetFactory : StatusBarWidgetFactory {
|
||||
internal class MacroWidgetFactory : StatusBarWidgetFactory, VimStatusBarWidget {
|
||||
private var content: String = ""
|
||||
|
||||
private val macroRecordingListener = object : MacroRecordingListener {
|
||||
override fun recordingStarted(editor: VimEditor, register: Char) {
|
||||
content = "recording @$register"
|
||||
updateWidget()
|
||||
updateWidgetInStatusBar(ID, editor.ij.project)
|
||||
}
|
||||
|
||||
override fun recordingFinished(editor: VimEditor, register: Char) {
|
||||
content = ""
|
||||
updateWidget()
|
||||
updateWidgetInStatusBar(ID, editor.ij.project)
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,14 +55,6 @@ internal class MacroWidgetFactory : StatusBarWidgetFactory {
|
||||
return VimPlugin.isEnabled() && injector.globalIjOptions().showmodewidget
|
||||
}
|
||||
|
||||
private fun updateWidget() {
|
||||
val windowManager = WindowManager.getInstance()
|
||||
ProjectManager.getInstance().openProjects.forEach {
|
||||
val statusBar = windowManager.getStatusBar(it)
|
||||
statusBar.updateWidget(ID)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class VimMacroWidget : StatusBarWidget {
|
||||
override fun ID(): String {
|
||||
return ID
|
||||
@ -91,28 +80,4 @@ internal class MacroWidgetFactory : StatusBarWidgetFactory {
|
||||
}
|
||||
}
|
||||
|
||||
internal object MacroWidgetListener : GlobalOptionChangeListener, VimPluginListener {
|
||||
init {
|
||||
injector.listenersNotifier.vimPluginListeners.add(this)
|
||||
}
|
||||
|
||||
override fun onGlobalOptionChanged() {
|
||||
updateWidget()
|
||||
}
|
||||
|
||||
override fun turnedOn() {
|
||||
updateWidget()
|
||||
}
|
||||
|
||||
override fun turnedOff() {
|
||||
updateWidget()
|
||||
}
|
||||
|
||||
private fun updateWidget() {
|
||||
val factory = StatusBarWidgetFactory.EP_NAME.findExtension(MacroWidgetFactory::class.java) ?: return
|
||||
for (project in ProjectManager.getInstance().openProjects) {
|
||||
val statusBarWidgetsManager = project.service<StatusBarWidgetsManager>()
|
||||
statusBarWidgetsManager.updateWidget(factory)
|
||||
}
|
||||
}
|
||||
}
|
||||
public val macroWidgetOptionListener: VimWidgetListener = VimWidgetListener(MacroWidgetFactory::class.java)
|
@ -8,17 +8,13 @@
|
||||
|
||||
package com.maddyhome.idea.vim.ui.widgets.mode
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.ProjectManager
|
||||
import com.intellij.openapi.wm.StatusBarWidget
|
||||
import com.intellij.openapi.wm.StatusBarWidgetFactory
|
||||
import com.intellij.openapi.wm.impl.status.widget.StatusBarWidgetsManager
|
||||
import com.maddyhome.idea.vim.VimPlugin
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.common.VimPluginListener
|
||||
import com.maddyhome.idea.vim.newapi.globalIjOptions
|
||||
import com.maddyhome.idea.vim.options.GlobalOptionChangeListener
|
||||
import com.maddyhome.idea.vim.ui.widgets.VimWidgetListener
|
||||
|
||||
public class ModeWidgetFactory : StatusBarWidgetFactory {
|
||||
public companion object {
|
||||
@ -42,28 +38,4 @@ public class ModeWidgetFactory : StatusBarWidgetFactory {
|
||||
}
|
||||
}
|
||||
|
||||
internal object ModeWidgetListener : GlobalOptionChangeListener, VimPluginListener {
|
||||
init {
|
||||
injector.listenersNotifier.vimPluginListeners.add(this)
|
||||
}
|
||||
|
||||
override fun onGlobalOptionChanged() {
|
||||
updateWidget()
|
||||
}
|
||||
|
||||
override fun turnedOn() {
|
||||
updateWidget()
|
||||
}
|
||||
|
||||
override fun turnedOff() {
|
||||
updateWidget()
|
||||
}
|
||||
|
||||
private fun updateWidget() {
|
||||
val factory = StatusBarWidgetFactory.EP_NAME.findExtension(ModeWidgetFactory::class.java) ?: return
|
||||
for (project in ProjectManager.getInstance().openProjects) {
|
||||
val statusBarWidgetsManager = project.service<StatusBarWidgetsManager>()
|
||||
statusBarWidgetsManager.updateWidget(factory)
|
||||
}
|
||||
}
|
||||
}
|
||||
public val modeWidgetOptionListener: VimWidgetListener = VimWidgetListener(ModeWidgetFactory::class.java)
|
||||
|
@ -12,7 +12,6 @@ import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.wm.CustomStatusBarWidget
|
||||
import com.intellij.openapi.wm.WindowManager
|
||||
import com.intellij.ui.components.JBLabel
|
||||
import com.intellij.ui.util.width
|
||||
import com.intellij.util.ui.UIUtil
|
||||
@ -29,7 +28,7 @@ import java.awt.Dimension
|
||||
import javax.swing.JComponent
|
||||
import kotlin.math.max
|
||||
|
||||
public class VimModeWidget(public val project: Project) : CustomStatusBarWidget {
|
||||
public class VimModeWidget(public val project: Project) : CustomStatusBarWidget, VimStatusBarWidget {
|
||||
private companion object {
|
||||
private const val INSERT = "INSERT"
|
||||
private const val NORMAL = "NORMAL"
|
||||
@ -72,9 +71,7 @@ public class VimModeWidget(public val project: Project) : CustomStatusBarWidget
|
||||
|
||||
public fun updateWidget(mode: Mode?) {
|
||||
updateLabel(mode)
|
||||
val windowManager = WindowManager.getInstance()
|
||||
val statusBar = windowManager.getStatusBar(project)
|
||||
statusBar.updateWidget(ModeWidgetFactory.ID)
|
||||
updateWidgetInStatusBar(ModeWidgetFactory.ID, project)
|
||||
}
|
||||
|
||||
private fun updateLabel(mode: Mode?) {
|
||||
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2003-2024 The IdeaVim authors
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE.txt file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
|
||||
package com.maddyhome.idea.vim.ui.widgets.mode
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.wm.WindowManager
|
||||
import java.util.*
|
||||
|
||||
public interface VimStatusBarWidget {
|
||||
public fun updateWidgetInStatusBar(widgetID: String, project: Project?) {
|
||||
if (project == null) return
|
||||
val updateWidgetTask = TimerWithRetriesTask(500L, 50) {
|
||||
val windowManager = WindowManager.getInstance()
|
||||
val statusBar = windowManager.getStatusBar(project) ?: return@TimerWithRetriesTask
|
||||
statusBar.updateWidget(widgetID)
|
||||
}
|
||||
updateWidgetTask.execute()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A task that may be used to address issues with initialization in the Platform, executing code with a reasonable number of retries and a reasonable period.
|
||||
* Clearly, this is a workaround and its use should be avoided when possible.
|
||||
*
|
||||
* Why is it needed for widgets?
|
||||
* In a single project environment, it is not necessary since the status bar is initialized before the editor opens.
|
||||
* However, in multi-project setups, the editor window is opened before the status bar initialization.
|
||||
* And this tasks tries to loops until status bar creation in order to notify it about opened editor.
|
||||
*/
|
||||
private class TimerWithRetriesTask(
|
||||
private val period: Long,
|
||||
private val retriesLimit: Int,
|
||||
private val block: () -> Unit
|
||||
) {
|
||||
private val timer = Timer()
|
||||
|
||||
fun execute() {
|
||||
timer.schedule(object : TimerTask() {
|
||||
private var counter = 0
|
||||
|
||||
override fun run() {
|
||||
if (counter >= retriesLimit) {
|
||||
timer.cancel()
|
||||
} else {
|
||||
this@TimerWithRetriesTask.block()
|
||||
counter++
|
||||
}
|
||||
}
|
||||
}, 0L, period)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user