From 4a2c9d196916a50f414a93032180828ddc3bf7e0 Mon Sep 17 00:00:00 2001 From: Joachim Ansorg Date: Wed, 28 Sep 2022 10:00:39 +0200 Subject: [PATCH] demo how to add multiple navigate actions to the gutter icons --- .../jetbrains/editor/ContextAnnotator.kt | 56 +++++++++++++++++-- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/plugin-core/src/main/kotlin/com/usecodex/jetbrains/editor/ContextAnnotator.kt b/plugin-core/src/main/kotlin/com/usecodex/jetbrains/editor/ContextAnnotator.kt index c6f4c6a3..f196310d 100644 --- a/plugin-core/src/main/kotlin/com/usecodex/jetbrains/editor/ContextAnnotator.kt +++ b/plugin-core/src/main/kotlin/com/usecodex/jetbrains/editor/ContextAnnotator.kt @@ -5,12 +5,17 @@ import com.intellij.codeInspection.ProblemHighlightType import com.intellij.lang.annotation.AnnotationHolder import com.intellij.lang.annotation.ExternalAnnotator import com.intellij.lang.annotation.HighlightSeverity +import com.intellij.openapi.actionSystem.ActionGroup +import com.intellij.openapi.actionSystem.AnAction +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.actionSystem.DefaultActionGroup import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.colors.EditorColors import com.intellij.openapi.editor.markup.GutterIconRenderer import com.intellij.openapi.project.DumbAware import com.intellij.openapi.project.Project +import com.intellij.openapi.ui.Messages import com.intellij.openapi.util.TextRange import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiDocumentManager @@ -28,8 +33,8 @@ import com.usecodex.jetbrains.CodexIcons import com.usecodex.jetbrains.Debouncer import com.usecodex.jetbrains.Errors import com.usecodex.jetbrains.context.ContextStore -import com.usecodex.jetbrains.events.messages.runWithUser import com.usecodex.jetbrains.editor.util.EditorFilesHandler +import com.usecodex.jetbrains.events.messages.runWithUser import com.usecodex.jetbrains.git.CodexGitService import com.usecodex.jetbrains.settings.CodexApplicationSettings import com.usecodex.jetbrains.toErrorCtx @@ -150,7 +155,7 @@ class ContextAnnotator : ExternalAnnotator(), LOG.debug("${scope.startLine} - ${scope.endLine} for ${scope.file?.name}") - // Substract 1 from the line numbers to get 0-based offsets required by the IDE + // Subtract 1 from the line numbers to get 0-based offsets required by the IDE val startLine = scope.startLine!! - 1 val endLine = scope.endLine?.let { it - 1 } ?: startLine context.id to TextRange( @@ -182,7 +187,7 @@ class ContextAnnotator : ExternalAnnotator(), // Only render one gutter icon per start line if (contextId in contextIdsToRenderGutterIconFor) { contextIdGutterIconGroupedByOffset[textRange.startOffset]?.let { contextIds -> - gutterIconRenderer(ContextGutterIconRenderer(contextIds)) + gutterIconRenderer(ContextGutterIconRenderer(contextIds, highlightingData)) } } create() @@ -192,13 +197,56 @@ class ContextAnnotator : ExternalAnnotator(), } } -class ContextGutterIconRenderer(val contextIds: List) : GutterIconRenderer() { +class ContextGutterIconRenderer(val contextIds: List, private val highlightingData: CodexHighlightingData) : GutterIconRenderer() { override fun equals(other: Any?): Boolean = when (other) { is ContextGutterIconRenderer -> contextIds == other.contextIds else -> false } + // popup menu with actions to allow navigating to multiple codexes + override fun getPopupMenuActions(): ActionGroup? { + return when (contextIds.size) { + 0, 1 -> null + else -> contextIds.mapNotNull { contextId -> + // fixme: slow lookup! only for demo purposes + highlightingData.contexts.firstOrNull { it.id == contextId }?.let(::NavigateToCodexAction) + }.toList().takeIf { it.isNotEmpty() }?.let(::DefaultActionGroup) + } + } + + // show hand cursor on hover, but only if there's just one context (i.e. the same condition as for getClickAction()) + override fun isNavigateAction(): Boolean { + return contextIds.size == 1 + } + + // navigate on left-click, but only if there's just one context + override fun getClickAction(): AnAction? { + return when (contextIds.size) { + 1 -> { + // fixme slow lookup + val codex = highlightingData.contexts.firstOrNull { it.id == contextIds[0] } + codex?.let(::NavigateToCodexAction) + } + + else -> null + } + } + + override fun getTooltipText(): String? { + return highlightingData.contexts.firstOrNull { it.id == contextIds[0] }?.let { + "Navigate to ${it.scope?.file?.name}" + } + } + + override fun isDumbAware(): Boolean = true + override fun hashCode(): Int = this.contextIds.hashCode() override fun getIcon(): Icon = CodexIcons.GutterIcon +} + +class NavigateToCodexAction(val context: Context) : AnAction("Navigate to ${context.codex?.name ?: context.id}") { + override fun actionPerformed(e: AnActionEvent) { + Messages.showInfoMessage("Navigating to $context...", "Codex") + } } \ No newline at end of file