diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ca2009..15c3819 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,12 +6,18 @@ ### Attention -- The current version is not compatible with previous plugin settings +- The current version is not compatible with previous plugin settings! + +### Added + +- Binary executable files of lsp-server are embedded +- Automatic restart of the LSP-server if it crashed or shutdown +- New action for manually restarting the LSP-server +- Widget for indicating the LSP-server current status ### Fixed - Fixed ternary expressions -- Binary executable files of lsp-server are embedded ## [0.3.1] - 2023-12-16 diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/actions/RestartLspAction.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/actions/RestartLspAction.kt new file mode 100644 index 0000000..32e36e6 --- /dev/null +++ b/src/main/kotlin/dev/slint/ideaplugin/ide/actions/RestartLspAction.kt @@ -0,0 +1,19 @@ +package dev.slint.ideaplugin.ide.actions + +import com.intellij.openapi.actionSystem.AnAction +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.components.service +import com.intellij.openapi.project.DumbAware +import dev.slint.ideaplugin.ide.services.SlintServerService + +class RestartLspAction: AnAction(), DumbAware { + override fun actionPerformed(e: AnActionEvent) { + val project = e.project ?: return + val slintServerService = project.service() + slintServerService.restartServer() + } + + companion object { + const val ID: String = "Slint.RestartLspAction" + } +} \ No newline at end of file diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/CommandLineHandler.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/CommandLineHandler.kt new file mode 100644 index 0000000..36da42e --- /dev/null +++ b/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/CommandLineHandler.kt @@ -0,0 +1,94 @@ +package dev.slint.ideaplugin.ide.lsp + +import com.intellij.execution.configurations.GeneralCommandLine +import com.intellij.ide.plugins.PluginManager +import com.intellij.openapi.extensions.PluginId +import com.intellij.openapi.util.SystemInfo +import dev.slint.ideaplugin.ide.settings.SlintBackend +import dev.slint.ideaplugin.ide.settings.SlintSettingsState +import dev.slint.ideaplugin.ide.settings.SlintStyle +import java.nio.file.Path + +object CommandLineHandler { + fun createCommandLine(): GeneralCommandLine { + val settingState = SlintSettingsState.getInstance().lspSettings + + val parameters = mutableListOf() + if (settingState.args.isNotEmpty()) { + val args = settingState.args.split("\\s+".toRegex()) + parameters.addAll(args) + } + + if (settingState.includePaths.isNotEmpty()) { + parameters.add("-I") + settingState.includePaths.forEach { + parameters.add("'${it}'") + } + } + + if (settingState.backend != SlintBackend.DEFAULT) { + parameters.add("--backend") + parameters.add(settingState.backend.toString()) + } + + if (settingState.style != SlintStyle.DEFAULT) { + parameters.add("--style") + parameters.add(settingState.style.toString()) + } + + if (settingState.noToolbar) { + parameters.add("--no-toolbar") + } + + val path = if (settingState.useExternalLsp) { + settingState.path + } else { + getEmbeddedLspPath().toString() + } + + return GeneralCommandLine(path).apply { + addParameters(parameters) + withParentEnvironmentType(GeneralCommandLine.ParentEnvironmentType.CONSOLE) + withCharset(Charsets.UTF_8) + } + } + + private fun getEmbeddedLspPath(): Path? { + val pluginPath = PluginManager + .getInstance() + .findEnabledPlugin(PluginId.getId(dev.slint.ideaplugin.SLINT_PLUGIN_ID)) + ?.pluginPath + + val programName: String + + if (SystemInfo.isMac) { + programName = "Slint Live Preview.app/Contents/MacOS/slint-lsp" + } else if (SystemInfo.isLinux) { + programName = when (SystemInfo.OS_ARCH) { + "x64" -> { + "slint-lsp-x86_64-unknown-linux-gnu" + } + + "arm" -> { + "slint-lsp-armv7-unknown-linux-gnueabihf" + } + + "arm64" -> { + "slint-lsp-aarch64-unknown-linux-gnu" + } + + else -> { + return null + } + } + } else if (SystemInfo.isWindows) { + programName = "slint-lsp-x86_64-pc-windows-msvc.exe" + } else { + return null + } + + return pluginPath + ?.resolve("language-server/bin") + ?.resolve(programName) + } +} diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/LspLanguageClient.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/LspLanguageClient.kt index 0bc5d9e..207b88f 100644 --- a/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/LspLanguageClient.kt +++ b/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/LspLanguageClient.kt @@ -18,33 +18,34 @@ class LspLanguageClient( private val project: Project ) : Lsp4jClient(serverNotificationsHandler) { - @JsonNotification("experimental/serverStatus") - fun serverStatus(status: ServerStatus) { - when (status.health) { - Health.WARNING -> { - NotificationGroupManager.getInstance() - .getNotificationGroup("Slint") - .createNotification( - SlintBundle.message("slint.language.server.status"), - status.message, - NotificationType.WARNING - ) - .notify(project) - } - Health.ERROR -> { - NotificationGroupManager.getInstance() - .getNotificationGroup("Slint") - .createNotification( - SlintBundle.message("slint.language.server.status"), - status.message, - NotificationType.ERROR - ) - .notify(project) - } - - Health.OK -> {} - } - } + // when editing, it flaps with notifications +// @JsonNotification("experimental/serverStatus") +// fun serverStatus(status: ServerStatus) { +// when (status.health) { +// Health.WARNING -> { +// NotificationGroupManager.getInstance() +// .getNotificationGroup("Slint") +// .createNotification( +// SlintBundle.message("slint.language.server.status"), +// status.message, +// NotificationType.WARNING +// ) +// .notify(project) +// } +// Health.ERROR -> { +// NotificationGroupManager.getInstance() +// .getNotificationGroup("Slint") +// .createNotification( +// SlintBundle.message("slint.language.server.status"), +// status.message, +// NotificationType.ERROR +// ) +// .notify(project) +// } +// +// Health.OK -> {} +// } +// } data class ServerStatus( @JsonAdapter(EnumDeserializer::class) diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/ServerProcessHandler.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/ServerProcessHandler.kt new file mode 100644 index 0000000..090ba70 --- /dev/null +++ b/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/ServerProcessHandler.kt @@ -0,0 +1,93 @@ +package dev.slint.ideaplugin.ide.lsp + +import com.intellij.execution.process.OSProcessHandler +import com.intellij.execution.process.ProcessAdapter +import com.intellij.execution.process.ProcessEvent +import com.intellij.openapi.components.service +import com.intellij.openapi.project.Project +import dev.slint.ideaplugin.ide.services.SlintServerService +import dev.slint.ideaplugin.ide.settings.SlintSettingsState +import java.util.* +import kotlin.concurrent.schedule + +object ServerProcessHandler { + fun addListeners(handler: OSProcessHandler, project: Project): OSProcessHandler { + handler.addProcessListener(object : ProcessAdapter() { + override fun processTerminated(event: ProcessEvent) { + super.processTerminated(event) + + val slintServerService = project.service() + if (slintServerService.isRestarting) { + return + } + + slintServerService.setTerminatingStatus() + + val settingState = SlintSettingsState.getInstance().lspSettings + if (!settingState.isRestartLsp) { + return + } + + Timer().schedule(3000) { + slintServerService.restartServer() + } + } + + override fun processNotStarted() { + super.processNotStarted() + + val slintServerService = project.service() + slintServerService.setTerminatingStatus() + } + + override fun startNotified(event: ProcessEvent) { + super.startNotified(event) + + val slintServerService = project.service() + slintServerService.setRunningStatus() + } + }) + + return handler + } +} + +fun startServerProcessHandler(handler: OSProcessHandler, project: Project): OSProcessHandler { + handler.addProcessListener(object : ProcessAdapter() { + override fun processTerminated(event: ProcessEvent) { + super.processTerminated(event) + + val slintServerService = project.service() + if (slintServerService.isRestarting) { + return + } + + slintServerService.setTerminatingStatus() + + val settingState = SlintSettingsState.getInstance().lspSettings + if (!settingState.isRestartLsp) { + return + } + + Timer().schedule(3000) { + slintServerService.restartServer() + } + } + + override fun processNotStarted() { + super.processNotStarted() + + val slintServerService = project.service() + slintServerService.setTerminatingStatus() + } + + override fun startNotified(event: ProcessEvent) { + super.startNotified(event) + + val slintServerService = project.service() + slintServerService.setRunningStatus() + } + }) + + return handler +} \ No newline at end of file diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLspServerDescriptor.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLspServerDescriptor.kt index b330a51..5436263 100644 --- a/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLspServerDescriptor.kt +++ b/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLspServerDescriptor.kt @@ -1,7 +1,11 @@ package dev.slint.ideaplugin.ide.lsp import com.intellij.execution.configurations.GeneralCommandLine +import com.intellij.execution.process.OSProcessHandler +import com.intellij.execution.process.ProcessAdapter +import com.intellij.execution.process.ProcessEvent import com.intellij.ide.plugins.PluginManager +import com.intellij.openapi.components.service import com.intellij.openapi.extensions.PluginId import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile @@ -17,99 +21,24 @@ import dev.slint.ideaplugin.lang.SlintFileType import org.eclipse.lsp4j.services.LanguageServer import com.intellij.openapi.util.SystemInfo import dev.slint.ideaplugin.SlintBundle +import dev.slint.ideaplugin.ide.services.SlintServerService import java.nio.file.Path +import java.util.* +import kotlin.concurrent.schedule @Suppress("UnstableApiUsage") class SlintLspServerDescriptor(project: Project) : ProjectWideLspServerDescriptor(project, "Slint") { override fun isSupportedFile(file: VirtualFile) = file.fileType == SlintFileType - override fun createCommandLine(): GeneralCommandLine { - val settingState = SlintSettingsState.getInstance().lspSettings - - val parameters = mutableListOf() - if (settingState.args.isNotEmpty()) { - val args = settingState.args.split("\\s+".toRegex()) - parameters.addAll(args) - } - - if (settingState.includePaths.isNotEmpty()) { - parameters.add("-I") - settingState.includePaths.forEach { - parameters.add("'${it}'") - } - } - - if (settingState.backend != SlintBackend.DEFAULT) { - parameters.add("--backend") - parameters.add(settingState.backend.toString()) - } - - if (settingState.style != SlintStyle.DEFAULT) { - parameters.add("--style") - parameters.add(settingState.style.toString()) - } - - if (settingState.noToolbar) { - parameters.add("--no-toolbar") - } - - val path = if (settingState.useExternalLsp) { - settingState.path - } else { - getEmbeddedLspPath().toString() - } - - return GeneralCommandLine(path).apply { - addParameters(parameters) - withParentEnvironmentType(GeneralCommandLine.ParentEnvironmentType.CONSOLE) - withCharset(Charsets.UTF_8) - } - } - - private fun getEmbeddedLspPath(): Path? { - val pluginPath = PluginManager - .getInstance() - .findEnabledPlugin(PluginId.getId(dev.slint.ideaplugin.SLINT_PLUGIN_ID)) - ?.pluginPath - - val programName: String - - if (SystemInfo.isMac) { - programName = "Slint Live Preview.app/Contents/MacOS/slint-lsp" - } else if (SystemInfo.isLinux) { - programName = when (SystemInfo.OS_ARCH) { - "x64" -> { - "slint-lsp-x86_64-unknown-linux-gnu" - } - - "arm" -> { - "slint-lsp-armv7-unknown-linux-gnueabihf" - } - - "arm64" -> { - "slint-lsp-aarch64-unknown-linux-gnu" - } - - else -> { - return null - } - } - } else if (SystemInfo.isWindows) { - programName = "slint-lsp-x86_64-pc-windows-msvc.exe" - } else { - return null - } - - return pluginPath - ?.resolve("language-server/bin") - ?.resolve(programName) - } + override fun createCommandLine(): GeneralCommandLine = CommandLineHandler.createCommandLine() override fun createInitializationOptions(): Any = SlintSettingsState.getInstance().lspSettings override fun createLsp4jClient(handler: LspServerNotificationsHandler): Lsp4jClient = LspLanguageClient(handler, project) + override fun startServerProcess(): OSProcessHandler = ServerProcessHandler.addListeners(super.startServerProcess(), project) + override val lsp4jServerClass: Class = SlintLanguageServer::class.java override val lspServerListener: LspServerListener = SlintLspServerListener(project) override val lspCompletionSupport: LspCompletionSupport = SlintLspCompletionSupport() diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/services/SlintServerService.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/services/SlintServerService.kt index 58f74b2..730bbcf 100644 --- a/src/main/kotlin/dev/slint/ideaplugin/ide/services/SlintServerService.kt +++ b/src/main/kotlin/dev/slint/ideaplugin/ide/services/SlintServerService.kt @@ -11,13 +11,50 @@ import dev.slint.ideaplugin.ide.lsp.SlintLanguageServer import dev.slint.ideaplugin.ide.lsp.SlintLspServerSupportProvider @Service(Service.Level.PROJECT) +@Suppress("UnstableApiUsage") class SlintServerService(private val project: Project) { + private var status = Status.TERMINATING + + val isRunning get() = status == Status.RUNNING + + val isRestarting get() = status == Status.RESTARTING + + fun setRunningStatus() { + status = Status.RUNNING + } + + fun setTerminatingStatus() { + status = Status.TERMINATING + notifyTerminating() + } + fun restartServer() { LspServerManager.getInstance(project) .stopAndRestartIfNeeded(SlintLspServerSupportProvider::class.java) + + status = Status.RESTARTING + notifyRestart() + } + + fun getServers(): List { + val servers = LspServerManager.getInstance(project) + .getServersForProvider(SlintLspServerSupportProvider::class.java) + + return servers.filter { it.lsp4jServer is SlintLanguageServer } } - fun notifyRestart() { + private fun notifyRun() { + NotificationGroupManager.getInstance() + .getNotificationGroup("Slint") + .createNotification( + SlintBundle.message("slint.language.server.is.running"), + "", + NotificationType.INFORMATION + ) + .notify(project) + } + + private fun notifyRestart() { NotificationGroupManager.getInstance() .getNotificationGroup("Slint") .createNotification( @@ -28,10 +65,20 @@ class SlintServerService(private val project: Project) { .notify(project) } - fun getServers(): List { - val servers = LspServerManager.getInstance(project) - .getServersForProvider(SlintLspServerSupportProvider::class.java) + private fun notifyTerminating() { + NotificationGroupManager.getInstance() + .getNotificationGroup("Slint") + .createNotification( + SlintBundle.message("slint.language.server.is.stopped"), + "", + NotificationType.WARNING + ) + .notify(project) + } - return servers.filter { it.lsp4jServer is SlintLanguageServer } + private enum class Status { + RUNNING, + RESTARTING, + TERMINATING } } \ No newline at end of file diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/settings/SlintLspSettings.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/settings/SlintLspSettings.kt index a78e557..b3bb678 100644 --- a/src/main/kotlin/dev/slint/ideaplugin/ide/settings/SlintLspSettings.kt +++ b/src/main/kotlin/dev/slint/ideaplugin/ide/settings/SlintLspSettings.kt @@ -9,7 +9,8 @@ data class SlintLspSettings ( var backend: SlintBackend = SlintBackend.DEFAULT, var noToolbar: Boolean = false, var includePaths: MutableList = mutableListOf(), - var useExternalLsp: Boolean = false + var useExternalLsp: Boolean = false, + var isRestartLsp: Boolean = true, ) enum class SlintStyle { diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/settings/SlintSettingsComponent.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/settings/SlintSettingsComponent.kt index 21e3f70..d6bf4fb 100644 --- a/src/main/kotlin/dev/slint/ideaplugin/ide/settings/SlintSettingsComponent.kt +++ b/src/main/kotlin/dev/slint/ideaplugin/ide/settings/SlintSettingsComponent.kt @@ -9,18 +9,21 @@ class SlintSettingsComponent(lspSettings: SlintLspSettings) { init { panel = panel { - group("Lsp Settings") { + group("LSP Settings") { lateinit var useExternalLspCheckBox: Cell row { - useExternalLspCheckBox = checkBox("Use external lsp") + useExternalLspCheckBox = checkBox("Use external LSP server") .bindSelected(lspSettings::useExternalLsp) } - row("Lsp path:") { - textFieldWithBrowseButton() - .bindText(lspSettings::path) - .enabledIf(useExternalLspCheckBox.selected) - .align(AlignX.FILL) + indent { + row { + textFieldWithBrowseButton() + .label("LSP path:") + .bindText(lspSettings::path) + .enabledIf(useExternalLspCheckBox.selected) + .align(AlignX.FILL) + } } row("Args:") { expandableTextField() @@ -38,6 +41,15 @@ class SlintSettingsComponent(lspSettings: SlintLspSettings) { .onApply { pathsTablePanel.onApply(lspSettings.includePaths) } .onReset { pathsTablePanel.onReset(lspSettings.includePaths) } } + row { + checkBox("Restart LSP server") + .comment( + "Restarting the LSP server after a crash or shutdown. " + + "If there are critical errors in the LSP server, the server will restart indefinitely." + + "
Manually restart the server: 'Tools -> Restart Slint LSP'" + ) + .bindSelected(lspSettings::isRestartLsp) + } } group("Preview") { row { diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/settings/SlintSettingsConfigurableProvider.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/settings/SlintSettingsConfigurableProvider.kt index 6068c38..8e7e970 100644 --- a/src/main/kotlin/dev/slint/ideaplugin/ide/settings/SlintSettingsConfigurableProvider.kt +++ b/src/main/kotlin/dev/slint/ideaplugin/ide/settings/SlintSettingsConfigurableProvider.kt @@ -31,7 +31,6 @@ class SlintSettingsConfigurable(internal val project: Project) : Configurable, S val slintServerService = project.service() slintServerService.restartServer() - slintServerService.notifyRestart() } override fun reset() { diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/widgets/SlintStatusBarWidget.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/widgets/SlintStatusBarWidget.kt new file mode 100644 index 0000000..252a9e7 --- /dev/null +++ b/src/main/kotlin/dev/slint/ideaplugin/ide/widgets/SlintStatusBarWidget.kt @@ -0,0 +1,82 @@ +package dev.slint.ideaplugin.ide.widgets + +import com.intellij.openapi.actionSystem.ActionManager +import com.intellij.openapi.actionSystem.DataContext +import com.intellij.openapi.actionSystem.DefaultActionGroup +import com.intellij.openapi.components.service +import com.intellij.openapi.module.ModuleUtil +import com.intellij.openapi.project.Project +import com.intellij.openapi.project.ProjectLocator +import com.intellij.openapi.ui.popup.JBPopupFactory +import com.intellij.openapi.ui.popup.ListPopup +import com.intellij.openapi.util.IconLoader.getDisabledIcon +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.wm.CustomStatusBarWidget +import com.intellij.openapi.wm.StatusBarWidget +import com.intellij.openapi.wm.impl.status.EditorBasedStatusBarPopup +import com.intellij.ui.AnimatedIcon +import com.intellij.util.concurrency.EdtExecutorService +import dev.slint.ideaplugin.SlintBundle +import dev.slint.ideaplugin.SlintIcons +import dev.slint.ideaplugin.ide.actions.RestartLspAction +import dev.slint.ideaplugin.ide.services.SlintServerService +import dev.slint.ideaplugin.lang.SlintFileType +import java.util.concurrent.ScheduledFuture +import java.util.concurrent.TimeUnit + +class SlintStatusBarWidget(project: Project) : EditorBasedStatusBarPopup(project, false), CustomStatusBarWidget { + private companion object { + const val ID = "Slint.StatusBarWidget" + } + + private var future: ScheduledFuture<*>? = null + + init { + this.future = EdtExecutorService + .getScheduledExecutorInstance() + .scheduleWithFixedDelay({ this.update() }, 2, 2, TimeUnit.SECONDS) + } + + override fun ID(): String = ID + + override fun createInstance(project: Project): StatusBarWidget = SlintStatusBarWidget(project) + + override fun createPopup(context: DataContext): ListPopup? { + val group = DefaultActionGroup.createPopupGroupWithEmptyText() + group.add(ActionManager.getInstance().getAction(RestartLspAction.ID)) + + return JBPopupFactory.getInstance() + .createActionGroupPopup("Slint Actions", group, context, JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, true) + } + + override fun getWidgetState(file: VirtualFile?): WidgetState { + if (file?.fileType !is SlintFileType) return WidgetState.HIDDEN + + val project = ProjectLocator.getInstance().guessProjectForFile(file) + project?: return WidgetState.HIDDEN + val module = ModuleUtil.findModuleForFile(file, this.project) + module?: return WidgetState.HIDDEN + + val slintServerService = project.service() + + return when(slintServerService.isRunning) { + true -> { + val state = WidgetState(SlintBundle.message("slint.language.server.is.running"), "Slint", false) + state.icon = SlintIcons.SLINT + state + } + false -> { + val state = WidgetState(SlintBundle.message("slint.language.server.is.stopped"), "Slint", true) + state.icon = AnimatedIcon(1000, SlintIcons.SLINT, getDisabledIcon( SlintIcons.SLINT)) + state + } + } + } + + override fun dispose() { + this.future?.cancel(true) + this.future = null + + super.dispose() + } +} \ No newline at end of file diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/widgets/SlintStatusBarWidgetFactory.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/widgets/SlintStatusBarWidgetFactory.kt index c7087ab..1b34cd2 100644 --- a/src/main/kotlin/dev/slint/ideaplugin/ide/widgets/SlintStatusBarWidgetFactory.kt +++ b/src/main/kotlin/dev/slint/ideaplugin/ide/widgets/SlintStatusBarWidgetFactory.kt @@ -1,7 +1,6 @@ package dev.slint.ideaplugin.ide.widgets import com.intellij.openapi.project.Project -import com.intellij.openapi.wm.StatusBar import com.intellij.openapi.wm.StatusBarWidget import com.intellij.openapi.wm.StatusBarWidgetFactory @@ -15,6 +14,6 @@ class SlintStatusBarWidgetFactory : StatusBarWidgetFactory { } override fun createWidget(project: Project): StatusBarWidget { - return SlintWidget(project) + return SlintStatusBarWidget(project) } } \ No newline at end of file diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/widgets/SlintWidget.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/widgets/SlintWidget.kt deleted file mode 100644 index 5d7a913..0000000 --- a/src/main/kotlin/dev/slint/ideaplugin/ide/widgets/SlintWidget.kt +++ /dev/null @@ -1,93 +0,0 @@ -package dev.slint.ideaplugin.ide.widgets - -import com.intellij.openapi.diagnostic.Logger -import com.intellij.openapi.fileEditor.FileEditorManager -import com.intellij.openapi.fileEditor.FileEditorManagerListener -import com.intellij.openapi.project.Project -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.openapi.wm.StatusBarWidget -import com.intellij.openapi.wm.StatusBarWidget.WidgetPresentation -import com.intellij.openapi.wm.impl.status.EditorBasedWidget -import com.intellij.platform.lsp.api.LspServerManager -import dev.slint.ideaplugin.SlintIcons -import dev.slint.ideaplugin.ide.lsp.SlintLspServerSupportProvider -import dev.slint.ideaplugin.lang.SlintFileType -import javax.swing.Icon - -class SlintWidget(project: Project) : EditorBasedWidget(project), StatusBarWidget, - StatusBarWidget.MultipleTextValuesPresentation { - private val logger: Logger = Logger.getInstance(javaClass) - private var isShowWidget = false - - init { - project.messageBus.connect(this).subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, object : FileEditorManagerListener { - override fun fileOpened(source: FileEditorManager, file: VirtualFile) { - val isSlintFile = source.openFiles.any { - it.fileType == SlintFileType - } - - if (isShowWidget != isSlintFile) { - isShowWidget = isSlintFile - update() - } - } - - override fun fileClosed(source: FileEditorManager, file: VirtualFile) { - val isSlintFile = source.openFiles.any { - it.fileType == SlintFileType - } - - if (isShowWidget != isSlintFile) { - isShowWidget = isSlintFile - update() - } - } - }) - } - - override fun ID(): String { - return javaClass.name; - } - - override fun getIcon(): Icon { - return SlintIcons.SLINT - } - - override fun getPresentation(): WidgetPresentation { - return this - } - - override fun getSelectedValue(): String { - return if (isShowWidget) "slint-lsp" else "" - } - - override fun getTooltipText(): String { - val lspServerManager = LspServerManager.getInstance(project) - val lspServer = lspServerManager.getServersForProvider(SlintLspServerSupportProvider::class.java).firstOrNull() - -// return when (lspServer) { -// is LspServerImpl -> { -// if (lspServer.isRunning) { -// SlintBundle.message("slint.language.server.is.running") -// } else { -// SlintBundle.message("slint.language.server.is.stopped") -// } -// } -// -// else -> { -// SlintBundle.message("slint.language.server.is.stopped") -// } -// } - return "" - } - - private fun update() { - if (myStatusBar == null) { - logger.warn("Failed to update slint statusbar") - return - } - - myStatusBar!!.updateWidget(ID()) - } - -} \ No newline at end of file diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index c8a74f8..7f0b4ae 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -57,8 +57,8 @@ implementationClass="dev.slint.ideaplugin.ide.lineMarkers.PreviewRunLineMarkerContributor"/> - - + + + + + \ No newline at end of file