[jupyter] PY-72701 better "run cell" button UX

GitOrigin-RevId: 3a14c64d4c398b14eb1c76688f0f2702d008bc61
This commit is contained in:
Bogdan Kirilenko
2024-05-17 18:11:49 +02:00
committed by intellij-monorepo-bot
parent 9bdb4dc826
commit b704bec09a
4 changed files with 106 additions and 0 deletions

View File

@@ -56,6 +56,8 @@ class EditorCellInput(
})
}
private val runCellButton = EditorCellRunButton(editor)
val component: EditorCellViewComponent
get() = _component
@@ -107,6 +109,7 @@ class EditorCellInput(
fun dispose() {
folding.dispose()
runCellButton.dispose()
_component.dispose()
}
@@ -140,6 +143,14 @@ class EditorCellInput(
folding.show()
}
fun showRunButton() {
runCellButton.showRunButton(interval, interval.type)
}
fun hideRunButton() {
runCellButton.hideRunButton()
}
fun addViewComponentListener(listener: EditorCellViewComponentListener) {
cellEventListeners.addListener(listener)
}

View File

@@ -0,0 +1,42 @@
package org.jetbrains.plugins.notebooks.visualization.ui
import com.intellij.openapi.editor.ex.EditorEx
import com.intellij.openapi.editor.markup.HighlighterLayer
import com.intellij.openapi.editor.markup.HighlighterTargetArea
import com.intellij.openapi.editor.markup.RangeHighlighter
import org.jetbrains.plugins.notebooks.visualization.NotebookCellLines
class EditorCellRunButton(private val editor: EditorEx) {
private var cellRangeHighlighter: RangeHighlighter? = null
fun showRunButton(interval: NotebookCellLines.Interval, type: NotebookCellLines.CellType) {
hideRunButton()
if (type != NotebookCellLines.CellType.CODE) return
val linesRange = interval.lines
val startOffset = editor.document.getLineStartOffset(linesRange.first)
val endOffset = editor.document.getLineEndOffset(linesRange.last)
cellRangeHighlighter = editor.markupModel.addRangeHighlighter(
startOffset,
endOffset,
HighlighterLayer.ERROR + 1,
null,
HighlighterTargetArea.LINES_IN_RANGE
)
cellRangeHighlighter?.gutterIconRenderer = EditorRunCellGutterIconRenderer(linesRange)
}
fun hideRunButton() {
cellRangeHighlighter?.let {
editor.markupModel.removeHighlighter(it)
cellRangeHighlighter = null
}
}
fun dispose() {
hideRunButton()
}
}

View File

@@ -203,11 +203,13 @@ class EditorCellView(
fun mouseExited() {
mouseOver = false
updateFolding()
updateRunButton()
}
fun mouseEntered() {
mouseOver = true
updateFolding()
updateRunButton()
}
inline fun <reified T : Any> getExtension(): T? {
@@ -296,6 +298,14 @@ class EditorCellView(
}
}
private fun updateRunButton() {
if (mouseOver || selected) {
input.showRunButton()
} else {
input.hideRunButton()
}
}
inner class NotebookGutterLineMarkerRenderer(private val interval: NotebookCellLines.Interval) : NotebookLineMarkerRenderer() {
override fun paint(editor: Editor, g: Graphics, r: Rectangle) {
editor as EditorImpl

View File

@@ -0,0 +1,43 @@
package org.jetbrains.plugins.notebooks.visualization.ui
import com.intellij.icons.AllIcons
import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.editor.markup.GutterIconRenderer
import org.jetbrains.annotations.ApiStatus
import javax.swing.Icon
@ApiStatus.Internal
class EditorRunCellGutterIconRenderer(private val lines: IntRange) : GutterIconRenderer() {
// PY-72142 & PY-69788 & PY-72701 - adds "Run cell" button to the gutter
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as EditorRunCellGutterIconRenderer
return lines == other.lines
}
override fun getClickAction(): AnAction = CellRunAction(lines, action)
override fun getTooltipText(): String? = action.templateText
override fun hashCode(): Int = lines.hashCode()
override fun isNavigateAction(): Boolean = true
override fun getIcon(): Icon = AllIcons.RunConfigurations.TestState.Run
private class CellRunAction(private val lines: IntRange,
private val action: AnAction) : AnAction() {
override fun actionPerformed(e: AnActionEvent) {
val editor = e.getData(CommonDataKeys.EDITOR)
editor?.caretModel?.moveToOffset(editor.document.getLineStartOffset(lines.first))
action.actionPerformed(e)
}
}
companion object {
private const val RUN_CELL_ACTION_ID = "NotebookRunCellAction"
private val action = ActionManager.getInstance().getAction(RUN_CELL_ACTION_ID)
}
}