[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) {
editor as EditorImpl
val lines = IntRange(editor.document.getLineNumber(highlighter.startOffset), editor.document.getLineNumber(highlighter.endOffset))
val top = editor.offsetToXY(editor.document.getLineStartOffset(lines.first)).y
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)
}
}

View File

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

View File

@@ -1,10 +1,8 @@
package com.intellij.notebooks.visualization.ui
import com.intellij.ide.DataManager
import com.intellij.notebooks.ui.visualization.NotebookCodeCellBackgroundLineMarkerRenderer
import com.intellij.notebooks.ui.visualization.NotebookLineMarkerRenderer
import com.intellij.notebooks.ui.visualization.NotebookTextCellBackgroundLineMarkerRenderer
import com.intellij.notebooks.ui.visualization.notebookAppearance
import com.intellij.ide.ui.UISettings
import com.intellij.notebooks.ui.visualization.*
import com.intellij.notebooks.visualization.*
import com.intellij.notebooks.visualization.NotebookCellInlayController.InputFactory
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.EditorKind
import com.intellij.openapi.editor.Inlay
import com.intellij.openapi.editor.VisualPosition
import com.intellij.openapi.editor.ex.RangeHighlighterEx
import com.intellij.openapi.editor.impl.EditorImpl
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.util.asSafely
import java.awt.Graphics
import java.awt.Graphics2D
import java.awt.Point
import java.awt.Rectangle
import java.time.ZonedDateTime
import javax.swing.JComponent
@@ -49,6 +44,8 @@ class EditorCellView(
private val cellInlayManager: NotebookCellInlayManager,
) : EditorCellViewComponent(), Disposable {
private val uiSettings = UISettings.getInstance()
private var _controllers: List<NotebookCellInlayController> = emptyList()
private val controllers: List<NotebookCellInlayController>
@@ -266,18 +263,7 @@ class EditorCellView(
removeCellHighlight()
addCellHighlighter {
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)
}
}
// manages the cell background + clips background on the right below the scroll bar
if (interval.type == NotebookCellLines.CellType.CODE) {
addCellHighlighter {
editor.markupModel.addRangeHighlighter(
@@ -295,26 +281,14 @@ class EditorCellView(
}
}
if (interval.type == NotebookCellLines.CellType.CODE && editor.notebookAppearance.shouldShowCellLineNumbers() && editor.editorKind != EditorKind.DIFF) {
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
)
}
}
// draws gray vertical rectangles between line numbers and the leftmost border of the text
if (interval.type == NotebookCellLines.CellType.CODE) {
addCellHighlighter {
editor.markupModel.addRangeHighlighterAndChangeAttributes(null, startOffset, endOffset, HighlighterLayer.FIRST - 100, HighlighterTargetArea.LINES_IN_RANGE, false) { o: RangeHighlighterEx ->
o.lineMarkerRenderer = NotebookCodeCellBackgroundLineMarkerRenderer(o)
}
}
}
else if (editor.editorKind != EditorKind.DIFF) {
} else if (editor.editorKind != EditorKind.DIFF) {
addCellHighlighter {
editor.markupModel.addRangeHighlighterAndChangeAttributes(null, startOffset, endOffset, HighlighterLayer.FIRST - 100, HighlighterTargetArea.LINES_IN_RANGE, false) { o: RangeHighlighterEx ->
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) {
controller.createGutterRendererLineMarker(editor, interval, this)
}
@@ -362,37 +344,6 @@ class EditorCellView(
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(
val editor: Editor,
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.
*/
@Suppress("DuplicatedCode")
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
@Suppress("NAME_SHADOWING") g.create().use { g ->
graphics.create().use { g ->
val scrollbarWidth = editor.scrollPane.verticalScrollBar.width
val oldBounds = g.clipBounds
val visibleArea = editor.scrollingModel.visibleArea