From e7ef68a6d9e72be25f2e49679f723549f9559022 Mon Sep 17 00:00:00 2001 From: "Nikita.Ashihmin" Date: Thu, 10 Apr 2025 00:36:34 +0400 Subject: [PATCH] PY-79420 Jupyter: Refactor BelowCellInlayController. Split to separate components and local listeners for each component We need to do it to not force gloval update on each change. Now each cmponent can be updated separatly and call on own disposable listeners GitOrigin-RevId: 9d2d2191a4d69525de9f3bfd5e80aaea1c81a024 --- .../NotebookCellInlayController.kt | 1 + .../ui/CellExecutionStatusView.kt | 7 ---- .../notebooks/visualization/ui/EditorCell.kt | 20 +--------- .../visualization/ui/EditorCellView.kt | 38 +++++++++++-------- .../visualization/ui/EditorNotebook.kt | 2 +- .../ui/NotebookVisibleCellsBatchUpdater.kt | 2 +- .../ui/cell/frame/CellFrameState.kt | 7 ++++ .../frame}/EditorCellFrameManager.kt | 11 +++++- .../ui/components/kotlin/NotebookEditor.kt | 2 +- 9 files changed, 44 insertions(+), 46 deletions(-) delete mode 100644 notebooks/visualization/src/com/intellij/notebooks/visualization/ui/CellExecutionStatusView.kt create mode 100644 notebooks/visualization/src/com/intellij/notebooks/visualization/ui/cell/frame/CellFrameState.kt rename notebooks/visualization/src/com/intellij/notebooks/visualization/ui/{ => cell/frame}/EditorCellFrameManager.kt (92%) diff --git a/notebooks/visualization/src/com/intellij/notebooks/visualization/NotebookCellInlayController.kt b/notebooks/visualization/src/com/intellij/notebooks/visualization/NotebookCellInlayController.kt index ddc4a5b8362e..26f96eb0d0ff 100644 --- a/notebooks/visualization/src/com/intellij/notebooks/visualization/NotebookCellInlayController.kt +++ b/notebooks/visualization/src/com/intellij/notebooks/visualization/NotebookCellInlayController.kt @@ -84,6 +84,7 @@ interface NotebookCellInlayController { val inlay: Inlay<*> val factory: Factory + get() = error("It is not used keep with AIA compatibility") fun onViewportChange(): Unit = Unit diff --git a/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/CellExecutionStatusView.kt b/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/CellExecutionStatusView.kt deleted file mode 100644 index 85ef5d2e66f6..000000000000 --- a/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/CellExecutionStatusView.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.intellij.notebooks.visualization.ui - -import java.time.ZonedDateTime - -interface CellExecutionStatusView { - fun updateExecutionStatus(executionCount: Int?, progressStatus: ProgressStatus?, startTime: ZonedDateTime?, endTime: ZonedDateTime?) -} \ No newline at end of file diff --git a/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/EditorCell.kt b/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/EditorCell.kt index 4644e8dd0737..8bbb8fe3d34c 100644 --- a/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/EditorCell.kt +++ b/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/EditorCell.kt @@ -6,7 +6,6 @@ import com.intellij.notebooks.visualization.NotebookCellLines.CellType import com.intellij.notebooks.visualization.NotebookCellLines.Interval import com.intellij.notebooks.visualization.NotebookIntervalPointer import com.intellij.notebooks.visualization.UpdateContext -import com.intellij.notebooks.visualization.execution.ExecutionEvent import com.intellij.notebooks.visualization.outputs.NotebookOutputDataKey import com.intellij.notebooks.visualization.outputs.NotebookOutputDataKeyExtractor import com.intellij.openapi.Disposable @@ -26,7 +25,7 @@ private val CELL_EXTENSION_CONTAINER_KEY = Key, EditorCellE class EditorCell( val notebook: EditorNotebook, var intervalPointer: NotebookIntervalPointer, - private val editor: EditorImpl, + val editor: EditorImpl, ) : Disposable, UserDataHolder by UserDataHolderBase() { val source: AtomicProperty = AtomicProperty(getSource()) @@ -34,6 +33,7 @@ class EditorCell( val type: CellType = interval.type val interval: Interval get() = intervalPointer.get() ?: error("Invalid interval") + val intervalOrNull: Interval? get() = intervalPointer.get() val view: EditorCellView? get() = NotebookCellInlayManager.get(editor)!!.views[this] @@ -117,22 +117,6 @@ class EditorCell( outputs.updateOutputs() } - fun onExecutionEvent(event: ExecutionEvent) { - when (event) { - is ExecutionEvent.ExecutionStarted -> { - executionStatus.set(executionStatus.get().copy(status = event.status, startTime = event.startTime)) - } - is ExecutionEvent.ExecutionStopped -> { - executionStatus.set(executionStatus.get().copy(status = event.status, endTime = event.endTime, count = event.executionCount)) - } - is ExecutionEvent.ExecutionSubmitted -> { - executionStatus.set(executionStatus.get().copy(status = event.status)) - } - is ExecutionEvent.ExecutionReset -> { - executionStatus.set(executionStatus.get().copy(status = event.status)) - } - } - } fun requestCaret() { view?.requestCaret() diff --git a/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/EditorCellView.kt b/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/EditorCellView.kt index 932fbf21e114..0dbfcb04b2e2 100644 --- a/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/EditorCellView.kt +++ b/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/EditorCellView.kt @@ -10,6 +10,8 @@ import com.intellij.notebooks.ui.visualization.markerRenderers.NotebookCodeCellB import com.intellij.notebooks.visualization.* import com.intellij.notebooks.visualization.NotebookCellInlayController.InputFactory import com.intellij.notebooks.visualization.context.NotebookDataContext +import com.intellij.notebooks.visualization.ui.EditorCell.ExecutionStatus +import com.intellij.notebooks.visualization.ui.cell.frame.EditorCellFrameManager import com.intellij.notebooks.visualization.ui.cellsDnD.DropHighlightableCellPanel import com.intellij.notebooks.visualization.ui.jupyterToolbars.NotebookCellActionsToolbarStateTracker import com.intellij.openapi.Disposable @@ -32,7 +34,6 @@ import com.intellij.openapi.util.registry.Registry import com.intellij.util.asSafely import java.awt.Color import java.awt.Rectangle -import java.time.ZonedDateTime import javax.swing.JComponent import kotlin.reflect.KClass @@ -73,10 +74,11 @@ class EditorCellView( var outputs: EditorCellOutputsView? = null private set - val myEditorCellFrameManager: EditorCellFrameManager? = + val cellFrameManager: EditorCellFrameManager? = if (interval.type == NotebookCellLines.CellType.MARKDOWN && Registry.`is`("jupyter.markdown.cells.border")) { EditorCellFrameManager(editor, this, NotebookCellLines.CellType.MARKDOWN) - } else if (interval.type == NotebookCellLines.CellType.CODE && Registry.`is`("jupyter.code.cells.border")) { + } + else if (Registry.`is`("jupyter.code.cells.border")) { EditorCellFrameManager(editor, this, NotebookCellLines.CellType.CODE) } else null @@ -91,7 +93,7 @@ class EditorCellView( updateRunButtonVisibility() updateCellHighlight() updateCellActionsToolbarVisibility() - myEditorCellFrameManager?.updateCellFrameShow(value, mouseOver) + cellFrameManager?.updateCellFrameShow(value, mouseOver) } private var mouseOver = false @@ -122,10 +124,9 @@ class EditorCellView( } this.selected = cell.selected.get() cell.executionStatus.afterChange(this) { execution -> - updateExecutionStatus(execution.count, execution.status, execution.startTime, execution.endTime) + updateExecutionStatus(execution) } - val executionStatus = cell.executionStatus.get() - updateExecutionStatus(executionStatus.count, executionStatus.status, executionStatus.startTime, executionStatus.endTime) + updateExecutionStatus(cell.executionStatus.get()) editor.notebookAppearance.codeCellBackgroundColor.afterChange(this) { backgroundColor -> updateCellHighlight(force = true) } @@ -151,7 +152,7 @@ class EditorCellView( _controllers.forEach { controller -> disposeController(controller) } - myEditorCellFrameManager?.let { Disposer.dispose(it) } + cellFrameManager?.let { Disposer.dispose(it) } removeCellHighlight() } @@ -190,7 +191,14 @@ class EditorCellView( .filter { it !is InputFactory } val controllersToDispose = _controllers.toMutableSet() _controllers = if (!editor.isDisposed) { - otherFactories.mapNotNull { factory -> failSafeCompute(factory, editor, _controllers, intervals.intervals.listIterator(interval.ordinal)) } + otherFactories.mapNotNull { factory -> + val intervalIterator = intervals.intervals.listIterator(interval.ordinal) + val cellInlayController = failSafeCompute(factory, editor, _controllers, intervalIterator) + if (cellInlayController is Disposable) { + Disposer.register(this, cellInlayController) + } + cellInlayController + } } else { emptyList() @@ -284,7 +292,7 @@ class EditorCellView( mouseOver = false updateFolding() updateRunButtonVisibility() - myEditorCellFrameManager?.updateCellFrameShow(selected, mouseOver) + cellFrameManager?.updateCellFrameShow(selected, mouseOver) updateCellActionsToolbarVisibility() } @@ -292,7 +300,7 @@ class EditorCellView( mouseOver = true updateFolding() updateRunButtonVisibility() - myEditorCellFrameManager?.updateCellFrameShow(selected, mouseOver) + cellFrameManager?.updateCellFrameShow(selected, mouseOver) updateCellActionsToolbarVisibility() } @@ -374,7 +382,7 @@ class EditorCellView( selected = value updateFolding() updateCellHighlight() - myEditorCellFrameManager?.updateCellFrameShow(selected, mouseOver) + cellFrameManager?.updateCellFrameShow(selected, mouseOver) } private fun updateFolding() { @@ -426,10 +434,8 @@ class EditorCellView( it.updateFrameVisibility(selected, interval, color) } - private fun updateExecutionStatus(executionCount: Int?, progressStatus: ProgressStatus?, startTime: ZonedDateTime?, endTime: ZonedDateTime?) { - _controllers.filterIsInstance().firstOrNull() - ?.updateExecutionStatus(executionCount, progressStatus, startTime, endTime) - input.runCellButton?.updateGutterAction(progressStatus) + private fun updateExecutionStatus(executionStatus: ExecutionStatus) { + input.runCellButton?.updateGutterAction(executionStatus.status) } fun addDropHighlightIfApplicable(): Unit? = diff --git a/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/EditorNotebook.kt b/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/EditorNotebook.kt index 8a66e0933fb0..2b239b4b8f24 100644 --- a/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/EditorNotebook.kt +++ b/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/EditorNotebook.kt @@ -19,7 +19,7 @@ import com.intellij.openapi.util.Key import com.intellij.util.EventDispatcher import kotlin.reflect.KClass -class EditorNotebook(private val editor: EditorImpl) : Disposable { +class EditorNotebook(val editor: EditorImpl) : Disposable { private var _cells = mutableListOf() diff --git a/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/NotebookVisibleCellsBatchUpdater.kt b/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/NotebookVisibleCellsBatchUpdater.kt index 79786c9aa4e4..d26d67ea0707 100644 --- a/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/NotebookVisibleCellsBatchUpdater.kt +++ b/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/NotebookVisibleCellsBatchUpdater.kt @@ -45,7 +45,7 @@ class NotebookVisibleCellsBatchUpdater( } private fun updateCell(cell: EditorCell) { - cell.view?.myEditorCellFrameManager?.redrawBorders() + cell.view?.cellFrameManager?.redrawBorders() cell.view?.input?.cellActionsToolbar?.updateToolbarPosition() } override fun dispose() { diff --git a/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/cell/frame/CellFrameState.kt b/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/cell/frame/CellFrameState.kt new file mode 100644 index 000000000000..326b45d400fb --- /dev/null +++ b/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/cell/frame/CellFrameState.kt @@ -0,0 +1,7 @@ +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.notebooks.visualization.ui.cell.frame + +import com.intellij.ui.JBColor +import java.awt.Color + +data class CellFrameState(val isVisible: Boolean = false, val color: Color = JBColor.background()) \ No newline at end of file diff --git a/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/EditorCellFrameManager.kt b/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/cell/frame/EditorCellFrameManager.kt similarity index 92% rename from notebooks/visualization/src/com/intellij/notebooks/visualization/ui/EditorCellFrameManager.kt rename to notebooks/visualization/src/com/intellij/notebooks/visualization/ui/cell/frame/EditorCellFrameManager.kt index 1b29a0fd32b5..5c2623fc0dd4 100644 --- a/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/EditorCellFrameManager.kt +++ b/notebooks/visualization/src/com/intellij/notebooks/visualization/ui/cell/frame/EditorCellFrameManager.kt @@ -1,9 +1,11 @@ // Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package com.intellij.notebooks.visualization.ui +package com.intellij.notebooks.visualization.ui.cell.frame import com.intellij.notebooks.ui.visualization.NotebookUtil.notebookAppearance import com.intellij.notebooks.ui.visualization.markerRenderers.NotebookMarkdownCellLeftBorderRenderer import com.intellij.notebooks.visualization.NotebookCellLines +import com.intellij.notebooks.visualization.ui.EditorCellView +import com.intellij.notebooks.visualization.ui.EditorLayerController import com.intellij.notebooks.visualization.ui.EditorLayerController.Companion.getLayerController import com.intellij.openapi.Disposable import com.intellij.openapi.editor.ex.RangeHighlighterEx @@ -11,6 +13,7 @@ import com.intellij.openapi.editor.impl.EditorImpl import com.intellij.openapi.editor.markup.HighlighterLayer import com.intellij.openapi.editor.markup.HighlighterTargetArea import com.intellij.openapi.editor.markup.RangeHighlighter +import com.intellij.openapi.observable.properties.AtomicProperty import java.awt.Color import java.awt.geom.Line2D @@ -26,6 +29,8 @@ class EditorCellFrameManager( private var isSelected = false private var isHovered = false + val state: AtomicProperty = AtomicProperty(CellFrameState()) + init { if (cellType == NotebookCellLines.CellType.CODE) redrawBorders(editor.notebookAppearance.cellFrameHoveredColor.get()) } @@ -68,6 +73,7 @@ class EditorCellFrameManager( currentColor = color val layerController = editor.getLayerController() + state.set(CellFrameState(true, currentColor)) view.updateFrameVisibility(true, currentColor) redrawLeftBorder() @@ -105,6 +111,7 @@ class EditorCellFrameManager( } private fun clearFrame() { + state.set(CellFrameState(false, currentColor)) view.updateFrameVisibility(false, currentColor) removeLeftBorder() removeRightBorder(editor.getLayerController()) @@ -144,4 +151,4 @@ class EditorCellFrameManager( removeLeftBorder() removeRightBorder(editor.getLayerController()) } -} +} \ No newline at end of file diff --git a/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/kotlin/NotebookEditor.kt b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/kotlin/NotebookEditor.kt index 1ed75720d01e..500c1bbd1ab6 100644 --- a/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/kotlin/NotebookEditor.kt +++ b/platform/remote-driver/test-sdk/src/com/intellij/driver/sdk/ui/components/kotlin/NotebookEditor.kt @@ -74,7 +74,7 @@ class NotebookEditorUiComponent(private val data: ComponentData) : JEditorUiComp get() = xx("//div[@class='FullEditorWidthRenderer']//div[@class='JupyterMarkdownHtmlPane']").list() val notebookCellExecutionInfos: List - get() = xx("//div[@class='FullEditorWidthRenderer']/div[@class='NotebookBelowCellDelimiterPanel']/div[@class='JLabel']", JLabelUiComponent::class.java).list() + get() = xx("//div[@accessiblename='ExecutionLabel']", JLabelUiComponent::class.java).list() val notebookTables: List get() = xx("//div[@class='TableResultView']", JTableUiComponent::class.java).list()