[PyCharm] PY-74597 fix visual issues in presentation mode where cell background color extends to the gutter area

GitOrigin-RevId: 07ce4a901f913f93187ba8bbc12cbcd4134f91f6
This commit is contained in:
Bogdan Kirilenko
2024-09-12 16:57:01 +02:00
committed by intellij-monorepo-bot
parent beaf8878db
commit d59ddc340a
3 changed files with 35 additions and 76 deletions

View File

@@ -58,14 +58,17 @@ class MarkdownCellGutterLineMarkerRenderer(private val highlighter: RangeHighlig
} }
} }
class NotebookCodeCellBackgroundLineMarkerRenderer(private val highlighter: RangeHighlighter) : NotebookLineMarkerRenderer() { class NotebookCodeCellBackgroundLineMarkerRenderer(
private val highlighter: RangeHighlighter,
private val presentationModeMasking: Boolean = false,
) : NotebookLineMarkerRenderer() {
override fun paint(editor: Editor, g: Graphics, r: Rectangle) { override fun paint(editor: Editor, g: Graphics, r: Rectangle) {
editor as EditorImpl editor as EditorImpl
val lines = IntRange(editor.document.getLineNumber(highlighter.startOffset), editor.document.getLineNumber(highlighter.endOffset)) val lines = IntRange(editor.document.getLineNumber(highlighter.startOffset), editor.document.getLineNumber(highlighter.endOffset))
val top = editor.offsetToXY(editor.document.getLineStartOffset(lines.first)).y val top = editor.offsetToXY(editor.document.getLineStartOffset(lines.first)).y
val height = editor.offsetToXY(editor.document.getLineEndOffset(lines.last)).y + editor.lineHeight - top val height = editor.offsetToXY(editor.document.getLineEndOffset(lines.last)).y + editor.lineHeight - top
paintNotebookCellBackgroundGutter(editor, g, r, lines, top, height) { paintNotebookCellBackgroundGutter(editor, g, r, lines, top, height, presentationModeMasking) {
paintCaretRow(editor, g, lines) paintCaretRow(editor, g, lines)
} }
} }

View File

@@ -15,7 +15,6 @@ import java.awt.Rectangle
val Editor.notebookAppearance: NotebookEditorAppearance val Editor.notebookAppearance: NotebookEditorAppearance
get() = NOTEBOOK_APPEARANCE_KEY.get(this)!! get() = NOTEBOOK_APPEARANCE_KEY.get(this)!!
inline fun paintNotebookCellBackgroundGutter( inline fun paintNotebookCellBackgroundGutter(
editor: EditorImpl, editor: EditorImpl,
g: Graphics, g: Graphics,
@@ -23,6 +22,7 @@ inline fun paintNotebookCellBackgroundGutter(
lines: IntRange, lines: IntRange,
top: Int, top: Int,
height: Int, height: Int,
presentationModeMasking: Boolean = false, // PY-74597
crossinline actionBetweenBackgroundAndStripe: () -> Unit = {} crossinline actionBetweenBackgroundAndStripe: () -> Unit = {}
) { ) {
val diffViewOffset = 6 // randomly picked a number that fits well val diffViewOffset = 6 // randomly picked a number that fits well
@@ -30,14 +30,18 @@ inline fun paintNotebookCellBackgroundGutter(
val stripe = appearance.getCellStripeColor(editor, lines) val stripe = appearance.getCellStripeColor(editor, lines)
val stripeHover = appearance.getCellStripeHoverColor(editor, lines) val stripeHover = appearance.getCellStripeHoverColor(editor, lines)
val borderWidth = appearance.getLeftBorderWidth() val borderWidth = appearance.getLeftBorderWidth()
val rectBorderCellX = r.width - borderWidth val gutterWidth = editor.gutterComponentEx.width
g.color = appearance.getCodeCellBackground(editor.colorsScheme) val (fillX, fillWidth, fillColor) = when (presentationModeMasking) {
true -> Triple(r.width - borderWidth - gutterWidth, gutterWidth, editor.colorsScheme.defaultBackground)
else -> Triple(r.width - borderWidth, borderWidth, appearance.getCodeCellBackground(editor.colorsScheme))
}
if (editor.editorKind == EditorKind.DIFF) { g.color = fillColor
g.fillRect(rectBorderCellX + diffViewOffset, top, borderWidth - diffViewOffset, height)
} else { when (editor.editorKind == EditorKind.DIFF) {
g.fillRect(rectBorderCellX, top, borderWidth, height) true -> g.fillRect(fillX + diffViewOffset, top, fillWidth - diffViewOffset, height)
else -> g.fillRect(fillX, top, fillWidth, height)
} }
actionBetweenBackgroundAndStripe() actionBetweenBackgroundAndStripe()

View File

@@ -1,10 +1,8 @@
package com.intellij.notebooks.visualization.ui package com.intellij.notebooks.visualization.ui
import com.intellij.ide.DataManager import com.intellij.ide.DataManager
import com.intellij.notebooks.ui.visualization.NotebookCodeCellBackgroundLineMarkerRenderer import com.intellij.ide.ui.UISettings
import com.intellij.notebooks.ui.visualization.NotebookLineMarkerRenderer import com.intellij.notebooks.ui.visualization.*
import com.intellij.notebooks.ui.visualization.NotebookTextCellBackgroundLineMarkerRenderer
import com.intellij.notebooks.ui.visualization.notebookAppearance
import com.intellij.notebooks.visualization.* import com.intellij.notebooks.visualization.*
import com.intellij.notebooks.visualization.NotebookCellInlayController.InputFactory import com.intellij.notebooks.visualization.NotebookCellInlayController.InputFactory
import com.intellij.notebooks.visualization.context.NotebookDataContext import com.intellij.notebooks.visualization.context.NotebookDataContext
@@ -17,7 +15,6 @@ import com.intellij.openapi.diagnostic.thisLogger
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.EditorKind import com.intellij.openapi.editor.EditorKind
import com.intellij.openapi.editor.Inlay import com.intellij.openapi.editor.Inlay
import com.intellij.openapi.editor.VisualPosition
import com.intellij.openapi.editor.ex.RangeHighlighterEx import com.intellij.openapi.editor.ex.RangeHighlighterEx
import com.intellij.openapi.editor.impl.EditorImpl import com.intellij.openapi.editor.impl.EditorImpl
import com.intellij.openapi.editor.markup.* import com.intellij.openapi.editor.markup.*
@@ -25,8 +22,6 @@ import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.registry.Registry import com.intellij.openapi.util.registry.Registry
import com.intellij.util.asSafely import com.intellij.util.asSafely
import java.awt.Graphics import java.awt.Graphics
import java.awt.Graphics2D
import java.awt.Point
import java.awt.Rectangle import java.awt.Rectangle
import java.time.ZonedDateTime import java.time.ZonedDateTime
import javax.swing.JComponent import javax.swing.JComponent
@@ -49,6 +44,8 @@ class EditorCellView(
private val cellInlayManager: NotebookCellInlayManager, private val cellInlayManager: NotebookCellInlayManager,
) : EditorCellViewComponent(), Disposable { ) : EditorCellViewComponent(), Disposable {
private val uiSettings = UISettings.getInstance()
private var _controllers: List<NotebookCellInlayController> = emptyList() private var _controllers: List<NotebookCellInlayController> = emptyList()
private val controllers: List<NotebookCellInlayController> private val controllers: List<NotebookCellInlayController>
@@ -266,18 +263,7 @@ class EditorCellView(
removeCellHighlight() removeCellHighlight()
addCellHighlighter { // manages the cell background + clips background on the right below the scroll bar
editor.markupModel.addRangeHighlighter(
null,
startOffset,
endOffset,
HighlighterLayer.FIRST - 100, // Border should be seen behind any syntax highlighting, selection or any other effect.
HighlighterTargetArea.LINES_IN_RANGE
).apply {
lineMarkerRenderer = NotebookGutterLineMarkerRenderer(interval)
}
}
if (interval.type == NotebookCellLines.CellType.CODE) { if (interval.type == NotebookCellLines.CellType.CODE) {
addCellHighlighter { addCellHighlighter {
editor.markupModel.addRangeHighlighter( editor.markupModel.addRangeHighlighter(
@@ -295,26 +281,14 @@ class EditorCellView(
} }
} }
if (interval.type == NotebookCellLines.CellType.CODE && editor.notebookAppearance.shouldShowCellLineNumbers() && editor.editorKind != EditorKind.DIFF) { // draws gray vertical rectangles between line numbers and the leftmost border of the text
addCellHighlighter {
editor.markupModel.addRangeHighlighter(
null,
startOffset,
endOffset,
HighlighterLayer.FIRST - 99, // Border should be seen behind any syntax highlighting, selection or any other effect.
HighlighterTargetArea.LINES_IN_RANGE
)
}
}
if (interval.type == NotebookCellLines.CellType.CODE) { if (interval.type == NotebookCellLines.CellType.CODE) {
addCellHighlighter { addCellHighlighter {
editor.markupModel.addRangeHighlighterAndChangeAttributes(null, startOffset, endOffset, HighlighterLayer.FIRST - 100, HighlighterTargetArea.LINES_IN_RANGE, false) { o: RangeHighlighterEx -> editor.markupModel.addRangeHighlighterAndChangeAttributes(null, startOffset, endOffset, HighlighterLayer.FIRST - 100, HighlighterTargetArea.LINES_IN_RANGE, false) { o: RangeHighlighterEx ->
o.lineMarkerRenderer = NotebookCodeCellBackgroundLineMarkerRenderer(o) o.lineMarkerRenderer = NotebookCodeCellBackgroundLineMarkerRenderer(o)
} }
} }
} } else if (editor.editorKind != EditorKind.DIFF) {
else if (editor.editorKind != EditorKind.DIFF) {
addCellHighlighter { addCellHighlighter {
editor.markupModel.addRangeHighlighterAndChangeAttributes(null, startOffset, endOffset, HighlighterLayer.FIRST - 100, HighlighterTargetArea.LINES_IN_RANGE, false) { o: RangeHighlighterEx -> editor.markupModel.addRangeHighlighterAndChangeAttributes(null, startOffset, endOffset, HighlighterLayer.FIRST - 100, HighlighterTargetArea.LINES_IN_RANGE, false) { o: RangeHighlighterEx ->
o.lineMarkerRenderer = NotebookTextCellBackgroundLineMarkerRenderer(o) o.lineMarkerRenderer = NotebookTextCellBackgroundLineMarkerRenderer(o)
@@ -322,6 +296,14 @@ class EditorCellView(
} }
} }
if (uiSettings.presentationMode) { // See PY-74597
addCellHighlighter {
editor.markupModel.addRangeHighlighterAndChangeAttributes(null, startOffset, endOffset, HighlighterLayer.FIRST - 100, HighlighterTargetArea.LINES_IN_RANGE, false) { o: RangeHighlighterEx ->
o.lineMarkerRenderer = NotebookCodeCellBackgroundLineMarkerRenderer(o, presentationModeMasking = true)
}
}
}
for (controller: NotebookCellInlayController in controllers) { for (controller: NotebookCellInlayController in controllers) {
controller.createGutterRendererLineMarker(editor, interval, this) controller.createGutterRendererLineMarker(editor, interval, this)
} }
@@ -362,37 +344,6 @@ class EditorCellView(
input.runCellButton?.updateGutterAction(progressStatus) input.runCellButton?.updateGutterAction(progressStatus)
} }
inner class NotebookGutterLineMarkerRenderer(private val interval: NotebookCellLines.Interval) : NotebookLineMarkerRenderer() {
override fun paint(editor: Editor, g: Graphics, r: Rectangle) {
editor as EditorImpl
g.create().use { g2 ->
g2 as Graphics2D
val visualLineStart = editor.xyToVisualPosition(Point(0, g2.clip.bounds.y)).line
val visualLineEnd = editor.xyToVisualPosition(Point(0, g2.clip.bounds.run { y + height })).line
val logicalLineStart = editor.visualToLogicalPosition(VisualPosition(visualLineStart, 0)).line
val logicalLineEnd = editor.visualToLogicalPosition(VisualPosition(visualLineEnd, 0)).line
if (interval.lines.first > logicalLineEnd || interval.lines.last < logicalLineStart) return
paintBackground(editor, g2, r, interval)
}
}
private fun paintBackground(
editor: EditorImpl,
g: Graphics,
r: Rectangle,
interval: NotebookCellLines.Interval,
) {
for (controller: NotebookCellInlayController in controllers) {
controller.paintGutter(editor, g, r, interval)
}
outputs?.paintGutter(editor, g, r)
}
}
internal data class NotebookCellDataProvider( internal data class NotebookCellDataProvider(
val editor: Editor, val editor: Editor,
val component: JComponent, val component: JComponent,
@@ -417,13 +368,14 @@ class EditorCellView(
} }
/** /**
* Renders rectangle in the right part of editor to make filled code cells look like rectangles with margins. * Renders rectangle in the right part of the editor to make filled code cells look like rectangles with margins.
* But mostly it's used as a token to filter notebook cell highlighters. * But mostly it's used as a token to filter notebook cell highlighters.
*/ */
@Suppress("DuplicatedCode")
private object NotebookCellHighlighterRenderer : CustomHighlighterRenderer { private object NotebookCellHighlighterRenderer : CustomHighlighterRenderer {
override fun paint(editor: Editor, highlighter: RangeHighlighter, g: Graphics) { override fun paint(editor: Editor, highlighter: RangeHighlighter, graphics: Graphics) {
editor as EditorImpl editor as EditorImpl
@Suppress("NAME_SHADOWING") g.create().use { g -> graphics.create().use { g ->
val scrollbarWidth = editor.scrollPane.verticalScrollBar.width val scrollbarWidth = editor.scrollPane.verticalScrollBar.width
val oldBounds = g.clipBounds val oldBounds = g.clipBounds
val visibleArea = editor.scrollingModel.visibleArea val visibleArea = editor.scrollingModel.visibleArea