mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 14:23:28 +07:00
PY-74294: Make dependency on intellij.platform.images non-essential
GitOrigin-RevId: 74593ea0b9f72c9aa4ae896f277a3baf004a9f3f
This commit is contained in:
committed by
intellij-monorepo-bot
parent
88d09ecffd
commit
23e7f52620
1
.idea/modules.xml
generated
1
.idea/modules.xml
generated
@@ -551,6 +551,7 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/ml-local-models/intellij.ml.models.local.iml" filepath="$PROJECT_DIR$/plugins/ml-local-models/intellij.ml.models.local.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/ml-local-models/java/intellij.ml.models.local.java.iml" filepath="$PROJECT_DIR$/plugins/ml-local-models/java/intellij.ml.models.local.java.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/built-in-server/client/node-rpc-client/intellij.nodeRpcClient.iml" filepath="$PROJECT_DIR$/platform/built-in-server/client/node-rpc-client/intellij.nodeRpcClient.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/notebooks/images/intellij.notebooks.images.iml" filepath="$PROJECT_DIR$/notebooks/images/intellij.notebooks.images.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/jupyter/intellij.notebooks.jupyter.core.iml" filepath="$PROJECT_DIR$/jupyter/intellij.notebooks.jupyter.core.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/notebooks/notebook-ui/intellij.notebooks.ui.iml" filepath="$PROJECT_DIR$/notebooks/notebook-ui/intellij.notebooks.ui.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/notebooks/visualization/intellij.notebooks.visualization.iml" filepath="$PROJECT_DIR$/notebooks/visualization/intellij.notebooks.visualization.iml" />
|
||||
|
||||
18
notebooks/images/intellij.notebooks.images.iml
Normal file
18
notebooks/images/intellij.notebooks.images.iml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="kotlin-stdlib" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.util" />
|
||||
<orderEntry type="module" module-name="intellij.platform.core" />
|
||||
<orderEntry type="module" module-name="intellij.platform.ide.impl" />
|
||||
<orderEntry type="module" module-name="intellij.platform.images" />
|
||||
<orderEntry type="module" module-name="intellij.notebooks.visualization" />
|
||||
</component>
|
||||
</module>
|
||||
17
notebooks/images/resources/intellij.notebooks.images.xml
Normal file
17
notebooks/images/resources/intellij.notebooks.images.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<idea-plugin package="com.intellij.notebooks.images">
|
||||
|
||||
<dependencies>
|
||||
<plugin id="com.intellij.platform.images"/>
|
||||
<module name="intellij.notebooks.visualization"/>
|
||||
</dependencies>
|
||||
|
||||
<extensionPoints>
|
||||
<extensionPoint qualifiedName="com.intellij.notebooks.images.imageEditorFactory"
|
||||
interface="com.intellij.notebooks.images.ImageEditorFactory"
|
||||
dynamic="true"/>
|
||||
</extensionPoints>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij.notebooks.images">
|
||||
<imageEditorFactory implementation="com.intellij.notebooks.images.DefaultImageEditorFactory"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.intellij.notebooks.images
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.intellij.images.editor.ImageEditor
|
||||
import org.intellij.images.editor.impl.ImageEditorImpl
|
||||
|
||||
|
||||
class DefaultImageEditorFactory : ImageEditorFactory {
|
||||
override fun createImageEditor(project: Project, file: VirtualFile, graphicsPanel: GraphicsPanel): ImageEditor =
|
||||
ImageEditorImpl(project, file)
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.plugins.notebooks.visualization.r.inlays.components
|
||||
package com.intellij.notebooks.images
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl
|
||||
@@ -30,7 +30,9 @@ import org.intellij.images.ui.ImageComponent
|
||||
import org.jetbrains.annotations.Nls
|
||||
import org.jetbrains.concurrency.runAsync
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.VisualizationBundle
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.ui.UiCustomizer
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.components.EmptyComponentPanel
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.components.GraphicsManager
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.components.ImageInverter
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Component
|
||||
import java.awt.Dimension
|
||||
@@ -253,7 +255,7 @@ class GraphicsPanel(private val project: Project, private val disposableParent:
|
||||
return@runInEdt
|
||||
}
|
||||
closeEditor(VisualizationBundle.message("graphics.not.available"))
|
||||
val editor = UiCustomizer.instance.createImageEditor(project, file, this)
|
||||
val editor = ImageEditorFactory.instance.createImageEditor(project, file, this)
|
||||
adjustImageZoom(editor.zoomModel)
|
||||
removeImageInfoLabelAndActionToolBar(editor)
|
||||
currentImageFile = file
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.intellij.notebooks.images
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.intellij.images.editor.ImageEditor
|
||||
|
||||
|
||||
interface ImageEditorFactory {
|
||||
fun createImageEditor(project: Project,
|
||||
file: VirtualFile,
|
||||
graphicsPanel: GraphicsPanel): ImageEditor
|
||||
|
||||
companion object {
|
||||
val EP_NAME: ExtensionPointName<ImageEditorFactory> = ExtensionPointName("com.intellij.notebooks.images.imageEditorFactory")
|
||||
|
||||
val instance: ImageEditorFactory get() = EP_NAME.extensionList.first()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.intellij.notebooks.images
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import org.jetbrains.concurrency.Promise
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.ClipboardUtils
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.InlayDimensions
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.components.*
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.runAsyncInlay
|
||||
import java.io.File
|
||||
import javax.swing.SwingUtilities
|
||||
|
||||
class InlayOutputImg(parent: Disposable, editor: Editor, clearAction: () -> Unit)
|
||||
: InlayOutput(parent, editor, clearAction, loadActions(CopyImageToClipboardAction.ID, SaveOutputAction.ID, ClearOutputAction.ID)), InlayOutput.WithCopyImageToClipboard, InlayOutput.WithSaveAs {
|
||||
private val graphicsPanel = GraphicsPanel(project, parent).apply {
|
||||
isAdvancedMode = true
|
||||
}
|
||||
|
||||
override val isFullWidth = false
|
||||
|
||||
init {
|
||||
toolbarPane.dataComponent = graphicsPanel.component
|
||||
}
|
||||
|
||||
override fun addToolbar() {
|
||||
super.addToolbar()
|
||||
graphicsPanel.overlayComponent = toolbarPane.toolbarComponent
|
||||
}
|
||||
|
||||
override fun addData(data: String, type: String) {
|
||||
showImageAsync(data, type).onSuccess {
|
||||
SwingUtilities.invokeLater {
|
||||
val maxHeight = graphicsPanel.maximumSize?.height ?: 0
|
||||
val maxWidth = graphicsPanel.maximumSize?.width ?: 0
|
||||
val height = InlayDimensions.calculateInlayHeight(maxWidth, maxHeight, editor)
|
||||
onHeightCalculated?.invoke(height)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showImageAsync(data: String, type: String): Promise<Unit> {
|
||||
return runAsyncInlay {
|
||||
when (type) {
|
||||
"IMGBase64" -> graphicsPanel.showImageBase64(data)
|
||||
"IMGSVG" -> graphicsPanel.showSvgImage(data)
|
||||
"IMG" -> graphicsPanel.showImage(File(data))
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
}
|
||||
|
||||
override fun scrollToTop() {
|
||||
}
|
||||
|
||||
override fun getCollapsedDescription(): String {
|
||||
return "foo"
|
||||
}
|
||||
|
||||
override fun saveAs() {
|
||||
graphicsPanel.image?.let { image ->
|
||||
InlayOutputUtil.saveImageWithFileChooser(project, image)
|
||||
}
|
||||
}
|
||||
|
||||
override fun acceptType(type: String): Boolean {
|
||||
return type == "IMG" || type == "IMGBase64" || type == "IMGSVG"
|
||||
}
|
||||
|
||||
override fun copyImageToClipboard() {
|
||||
graphicsPanel.image?.let { image ->
|
||||
ClipboardUtils.copyImageToClipboard(image)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
<idea-plugin package="org.jetbrains.plugins.notebooks.visualization">
|
||||
<module value="com.intellij.modules.notebooks.visualization" />
|
||||
<dependencies>
|
||||
<plugin id="com.intellij.platform.images"/>
|
||||
<module name="intellij.notebooks.ui"/>
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -1,388 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.plugins.notebooks.visualization.r.inlays
|
||||
|
||||
import com.intellij.execution.process.ProcessOutputType
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.Inlay
|
||||
import com.intellij.openapi.editor.colors.EditorColors
|
||||
import com.intellij.openapi.editor.ex.EditorEx
|
||||
import com.intellij.openapi.editor.impl.EditorImpl
|
||||
import com.intellij.openapi.editor.markup.*
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import org.jetbrains.plugins.notebooks.ui.visualization.notebookAppearance
|
||||
import org.jetbrains.plugins.notebooks.visualization.NotebookIntervalPointer
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.components.*
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.components.progress.InlayProgressStatus
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.ui.UiCustomizer
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Cursor
|
||||
import java.awt.Graphics
|
||||
import java.awt.event.MouseEvent
|
||||
import java.awt.event.MouseListener
|
||||
import java.awt.event.MouseMotionListener
|
||||
import javax.swing.JComponent
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
class NotebookInlayComponentPsi(val cell: PsiElement, editor: EditorImpl) : NotebookInlayComponent(editor) {
|
||||
override fun updateCellSeparator() {
|
||||
if (!UiCustomizer.instance.showUpdateCellSeparator) {
|
||||
return
|
||||
}
|
||||
|
||||
if (separatorHighlighter != null &&
|
||||
separatorHighlighter!!.startOffset == cell.textRange.startOffset &&
|
||||
separatorHighlighter!!.endOffset == cell.textRange.endOffset) {
|
||||
return
|
||||
}
|
||||
|
||||
if (separatorHighlighter != null) {
|
||||
editor.markupModel.removeHighlighter(separatorHighlighter!!)
|
||||
}
|
||||
|
||||
// ToDo This is half-hack. The problem is that updateCellSeparator called from PSI change
|
||||
// but if we have a lot of sequential changes in editor.document (line Backspace button is hold)
|
||||
// document was updated but PSI update is async and that's why we have this check.
|
||||
if (cell.textRange.endOffset > editor.document.textLength) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
separatorHighlighter = createSeparatorHighlighter(editor, cell.textRange)
|
||||
}
|
||||
catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class NotebookInlayComponentInterval(val cell: NotebookIntervalPointer, editor: EditorImpl) : NotebookInlayComponent(editor) {
|
||||
override fun updateCellSeparator() {
|
||||
if (!UiCustomizer.instance.showUpdateCellSeparator) {
|
||||
return
|
||||
}
|
||||
|
||||
if (separatorHighlighter != null) {
|
||||
editor.markupModel.removeHighlighter(separatorHighlighter!!)
|
||||
}
|
||||
|
||||
try {
|
||||
val interval = cell.get() ?: return
|
||||
val doc = editor.document
|
||||
val textRange = TextRange(doc.getLineStartOffset(interval.lines.first), doc.getLineEndOffset(interval.lines.last))
|
||||
separatorHighlighter = createSeparatorHighlighter(editor, textRange)
|
||||
}
|
||||
catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createSeparatorHighlighter(editor: EditorImpl, textRange: TextRange) =
|
||||
editor.markupModel.addRangeHighlighter(textRange.startOffset, textRange.endOffset,
|
||||
HighlighterLayer.SYNTAX - 1, null,
|
||||
HighlighterTargetArea.LINES_IN_RANGE).apply {
|
||||
|
||||
customRenderer = NotebookInlayComponent.separatorRenderer
|
||||
lineMarkerRenderer = LineMarkerRenderer { _, g, r ->
|
||||
val gutterWidth = ((editor as EditorEx).gutterComponentEx as JComponent).width
|
||||
|
||||
val y = r.y + r.height - editor.lineHeight
|
||||
g.color = editor.colorsScheme.getColor(EditorColors.RIGHT_MARGIN_COLOR)
|
||||
g.drawLine(0, y, gutterWidth + 10, y)
|
||||
}
|
||||
}
|
||||
|
||||
abstract class NotebookInlayComponent(protected val editor: EditorImpl)
|
||||
: InlayComponent(), MouseListener, MouseMotionListener {
|
||||
companion object {
|
||||
val separatorRenderer = CustomHighlighterRenderer { editor, highlighter1, g ->
|
||||
val y1 = editor.offsetToPoint2D(highlighter1.endOffset).y.toInt()
|
||||
|
||||
g.color = editor.colorsScheme.getColor(EditorColors.RIGHT_MARGIN_COLOR)
|
||||
|
||||
g.drawLine(0, y1, editor.component.width, y1)
|
||||
}
|
||||
}
|
||||
|
||||
lateinit var beforeHeightChanged: () -> Unit
|
||||
lateinit var afterHeightChanged: () -> Unit
|
||||
var selected = false
|
||||
|
||||
private var state: NotebookInlayState? = null
|
||||
|
||||
private var expandedHeight = 0
|
||||
|
||||
/** Inlay short view, shown in collapsed state or in empty state. */
|
||||
private var toolbar: NotebookInlayToolbar? = null
|
||||
|
||||
private var gutter: JComponent? = null
|
||||
|
||||
private var mouseOverNewParagraphArea = false
|
||||
|
||||
protected var separatorHighlighter: RangeHighlighter? = null
|
||||
|
||||
private val disposable = Disposer.newDisposable()
|
||||
|
||||
/** If the value is `false`, the component won't limit its height and apply the height passed to [adjustSize] method directly. */
|
||||
private var shouldLimitMaxHeight = true
|
||||
|
||||
init {
|
||||
cursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)
|
||||
border = JBUI.Borders.empty(InlayDimensions.topBorderUnscaled,
|
||||
InlayDimensions.leftBorderUnscaled,
|
||||
InlayDimensions.bottomBorderUnscaled,
|
||||
InlayDimensions.rightBorderUnscaled)
|
||||
Disposer.register(editor.disposable, disposable)
|
||||
addMouseListener(this)
|
||||
addMouseMotionListener(this)
|
||||
}
|
||||
|
||||
// region MouseListener
|
||||
override fun mouseReleased(e: MouseEvent?) {}
|
||||
|
||||
override fun mouseEntered(e: MouseEvent?) {}
|
||||
|
||||
override fun mouseExited(e: MouseEvent?) {
|
||||
if (mouseOverNewParagraphArea) {
|
||||
mouseOverNewParagraphArea = false
|
||||
repaint(0, height - JBUI.scale(20), width, height)
|
||||
}
|
||||
}
|
||||
|
||||
override fun mousePressed(e: MouseEvent?) {}
|
||||
override fun mouseClicked(e: MouseEvent?) {}
|
||||
|
||||
// endregion
|
||||
|
||||
// region MouseMotionListener
|
||||
override fun mouseMoved(e: MouseEvent) {
|
||||
val value = e.y > height - JBUI.scale(20)
|
||||
if (value != mouseOverNewParagraphArea) {
|
||||
mouseOverNewParagraphArea = value
|
||||
repaint(0, height - JBUI.scale(20), width, height)
|
||||
}
|
||||
}
|
||||
|
||||
override fun mouseDragged(e: MouseEvent?) {}
|
||||
// endregion
|
||||
|
||||
private fun getOrAddToolbar(): NotebookInlayToolbar {
|
||||
toolbar?.let { return it }
|
||||
return NotebookInlayToolbar().also {
|
||||
toolbar = it
|
||||
add(it, BorderLayout.CENTER)
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeToolbar() {
|
||||
toolbar?.let { remove(it) }
|
||||
toolbar = null
|
||||
}
|
||||
|
||||
override fun paintComponent(g: Graphics) {
|
||||
/** Paints rounded rect panel - background of inlay component. */
|
||||
val g2d = g.create()
|
||||
|
||||
g2d.color = //if (selected) {
|
||||
//inlay!!.editor.colorsScheme.getAttributes(RMARKDOWN_CHUNK).backgroundColor
|
||||
//}
|
||||
//else {
|
||||
(inlay!!.editor as EditorImpl).let {
|
||||
it.notebookAppearance.getInlayBackgroundColor(it.colorsScheme) ?: it.backgroundColor
|
||||
}
|
||||
//}
|
||||
|
||||
g2d.fillRect(0, 0, width, InlayDimensions.topOffset + InlayDimensions.cornerRadius)
|
||||
g2d.fillRect(0, height - InlayDimensions.bottomOffset - InlayDimensions.cornerRadius, width,
|
||||
InlayDimensions.bottomOffset + InlayDimensions.cornerRadius)
|
||||
|
||||
|
||||
g2d.color = UIUtil.getLabelBackground()
|
||||
g2d.fillRoundRect(0, InlayDimensions.topOffset, width,
|
||||
height - InlayDimensions.bottomOffset - InlayDimensions.topOffset,
|
||||
InlayDimensions.cornerRadius, InlayDimensions.cornerRadius)
|
||||
|
||||
g2d.dispose()
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw separator line below cell. Also fills cell background
|
||||
*/
|
||||
protected abstract fun updateCellSeparator()
|
||||
|
||||
override fun assignInlay(inlay: Inlay<*>) {
|
||||
super.assignInlay(inlay)
|
||||
|
||||
updateCellSeparator()
|
||||
|
||||
gutter = editor.gutter as JComponent
|
||||
}
|
||||
|
||||
override fun disposeInlay() {
|
||||
if (separatorHighlighter != null && inlay != null) {
|
||||
editor.markupModel.removeHighlighter(separatorHighlighter!!)
|
||||
separatorHighlighter = null
|
||||
}
|
||||
super.disposeInlay()
|
||||
}
|
||||
|
||||
fun dispose() {
|
||||
Disposer.dispose(disposable)
|
||||
}
|
||||
|
||||
/** Changes size of component and also called updateSize for inlay. */
|
||||
override fun deltaSize(dx: Int, dy: Int) {
|
||||
if (dx == 0 && dy == 0) {
|
||||
return
|
||||
}
|
||||
|
||||
val newWidth = max(size.width + dx, InlayDimensions.minWidth)
|
||||
var newHeight = size.height + dy
|
||||
|
||||
newHeight = max(InlayDimensions.minHeight, newHeight)
|
||||
val newDx = newWidth - size.width
|
||||
val newDy = newHeight - size.height
|
||||
|
||||
super.deltaSize(newDx, newDy)
|
||||
}
|
||||
|
||||
/** Creates a component for displaying output. */
|
||||
private fun getOrCreateOutput(): NotebookInlayOutput {
|
||||
|
||||
if (state !is NotebookInlayOutput) {
|
||||
|
||||
if (state != null) {
|
||||
remove(state)
|
||||
}
|
||||
|
||||
state = NotebookInlayOutput(editor, disposable).apply {
|
||||
addToolbar()
|
||||
onHeightCalculated = { height ->
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
adjustSize(height)
|
||||
}
|
||||
}
|
||||
}.also { addState(it) }
|
||||
}
|
||||
resizable = true
|
||||
return state as NotebookInlayOutput
|
||||
}
|
||||
|
||||
fun updateProgressStatus(progressStatus: InlayProgressStatus) {
|
||||
state?.updateProgressStatus(progressStatus)
|
||||
}
|
||||
|
||||
private fun addState(state: NotebookInlayState) {
|
||||
add(state, BorderLayout.CENTER)
|
||||
|
||||
// Resizing only if inlay has minimal size or if we have expanded size set.
|
||||
if (expandedHeight != 0) {
|
||||
deltaSize(0, expandedHeight - size.height)
|
||||
expandedHeight = 0
|
||||
}
|
||||
else if (height < InlayDimensions.minHeight) {
|
||||
deltaSize(0, InlayDimensions.defaultHeight - height)
|
||||
}
|
||||
|
||||
revalidate()
|
||||
repaint()
|
||||
}
|
||||
|
||||
/** Adjusts size of notebook output. Method called when success data comes with inlay component desired height. */
|
||||
private fun adjustSize(height: Int) {
|
||||
beforeHeightChanged()
|
||||
|
||||
var desiredHeight = height + InlayDimensions.topBorder + InlayDimensions.bottomBorder
|
||||
if (shouldLimitMaxHeight) {
|
||||
desiredHeight = min(InlayDimensions.defaultHeight, desiredHeight)
|
||||
}
|
||||
|
||||
deltaSize(0, desiredHeight - size.height)
|
||||
|
||||
afterHeightChanged()
|
||||
}
|
||||
|
||||
/** Event from notebook with console output. This output contains intermediate data from console. */
|
||||
private fun onOutput(data: String, type: String, progressStatus: InlayProgressStatus?, cleanup: () -> Unit) {
|
||||
state?.clear()
|
||||
|
||||
val output = getOrCreateOutput()
|
||||
output.clearAction = cleanup
|
||||
if (output.addData(type, data, progressStatus)?.shouldLimitHeight() == false) {
|
||||
shouldLimitMaxHeight = false
|
||||
}
|
||||
|
||||
InlayStateCustomizer.customize(output)
|
||||
|
||||
if (UiCustomizer.instance.isResizeOutputToPreviewHeight && size.height == InlayDimensions.smallHeight) {
|
||||
deltaSize(0, InlayDimensions.previewHeight - size.height)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onMultiOutput(inlayOutputs: List<InlayOutput>, cleanup: () -> Unit) {
|
||||
state?.clear()
|
||||
removeToolbar()
|
||||
|
||||
shouldLimitMaxHeight = false
|
||||
|
||||
if (state !is NotebookInlayMultiOutput) {
|
||||
if (state != null) {
|
||||
remove(state)
|
||||
}
|
||||
state = TabbedMultiOutput(editor, disposable).also { st ->
|
||||
st.onHeightCalculated = { height ->
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
adjustSize(height)
|
||||
}
|
||||
}
|
||||
st.clearAction = cleanup
|
||||
addState(st)
|
||||
}
|
||||
}
|
||||
|
||||
resizable = true
|
||||
(state as? NotebookInlayMultiOutput)?.also { st ->
|
||||
st.onOutputs(inlayOutputs)
|
||||
InlayStateCustomizer.customize(st)
|
||||
}
|
||||
}
|
||||
|
||||
fun addInlayOutputs(inlayOutputs: List<InlayOutput>, cleanup: () -> Unit) {
|
||||
if (inlayOutputs.size > 1) {
|
||||
onMultiOutput(inlayOutputs, cleanup)
|
||||
}
|
||||
else {
|
||||
val inlay = inlayOutputs.first()
|
||||
onOutput(inlay.data, inlay.type, inlay.progressStatus, cleanup)
|
||||
}
|
||||
}
|
||||
|
||||
fun addText(message: String, outputType: Key<*>) {
|
||||
getOrCreateOutput().addText(message, outputType)
|
||||
if (size.height <= InlayDimensions.previewHeight * 3) {
|
||||
deltaSize(0, min(InlayDimensions.lineHeight * (message.lines().size - 1), InlayDimensions.previewHeight * 3 - size.height))
|
||||
}
|
||||
}
|
||||
|
||||
fun createOutputComponent() {
|
||||
getOrCreateOutput().addText("", ProcessOutputType.STDOUT)
|
||||
}
|
||||
|
||||
fun onViewportChange(isInViewport: Boolean) {
|
||||
state?.onViewportChange(isInViewport)
|
||||
}
|
||||
|
||||
fun clearOutputs() {
|
||||
state?.clear()
|
||||
removeToolbar()
|
||||
}
|
||||
}
|
||||
@@ -31,10 +31,7 @@ import com.intellij.util.ui.JBUI
|
||||
import org.cef.browser.CefBrowser
|
||||
import org.cef.handler.CefLoadHandlerAdapter
|
||||
import org.jetbrains.annotations.Nls
|
||||
import org.jetbrains.concurrency.Promise
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.VisualizationBundle
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.ClipboardUtils
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.InlayDimensions
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.components.progress.InlayProgressStatus
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.dataframe.DataFrameCSVAdapter
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.runAsyncInlay
|
||||
@@ -157,72 +154,6 @@ abstract class InlayOutput(
|
||||
}
|
||||
}
|
||||
|
||||
class InlayOutputImg(parent: Disposable, editor: Editor, clearAction: () -> Unit)
|
||||
: InlayOutput(parent, editor, clearAction, loadActions(CopyImageToClipboardAction.ID, SaveOutputAction.ID, ClearOutputAction.ID)), InlayOutput.WithCopyImageToClipboard, InlayOutput.WithSaveAs {
|
||||
private val graphicsPanel = GraphicsPanel(project, parent).apply {
|
||||
isAdvancedMode = true
|
||||
}
|
||||
|
||||
override val isFullWidth = false
|
||||
|
||||
init {
|
||||
toolbarPane.dataComponent = graphicsPanel.component
|
||||
}
|
||||
|
||||
override fun addToolbar() {
|
||||
super.addToolbar()
|
||||
graphicsPanel.overlayComponent = toolbarPane.toolbarComponent
|
||||
}
|
||||
|
||||
override fun addData(data: String, type: String) {
|
||||
showImageAsync(data, type).onSuccess {
|
||||
SwingUtilities.invokeLater {
|
||||
val maxHeight = graphicsPanel.maximumSize?.height ?: 0
|
||||
val maxWidth = graphicsPanel.maximumSize?.width ?: 0
|
||||
val height = InlayDimensions.calculateInlayHeight(maxWidth, maxHeight, editor)
|
||||
onHeightCalculated?.invoke(height)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showImageAsync(data: String, type: String): Promise<Unit> {
|
||||
return runAsyncInlay {
|
||||
when (type) {
|
||||
"IMGBase64" -> graphicsPanel.showImageBase64(data)
|
||||
"IMGSVG" -> graphicsPanel.showSvgImage(data)
|
||||
"IMG" -> graphicsPanel.showImage(File(data))
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
}
|
||||
|
||||
override fun scrollToTop() {
|
||||
}
|
||||
|
||||
override fun getCollapsedDescription(): String {
|
||||
return "foo"
|
||||
}
|
||||
|
||||
override fun saveAs() {
|
||||
graphicsPanel.image?.let { image ->
|
||||
InlayOutputUtil.saveImageWithFileChooser(project, image)
|
||||
}
|
||||
}
|
||||
|
||||
override fun acceptType(type: String): Boolean {
|
||||
return type == "IMG" || type == "IMGBase64" || type == "IMGSVG"
|
||||
}
|
||||
|
||||
override fun copyImageToClipboard() {
|
||||
graphicsPanel.image?.let { image ->
|
||||
ClipboardUtils.copyImageToClipboard(image)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class InlayOutputText(parent: Disposable, editor: Editor, clearAction: () -> Unit)
|
||||
: InlayOutput(parent, editor, clearAction, loadActions(SaveOutputAction.ID, ClearOutputAction.ID)), InlayOutput.WithSaveAs {
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ class ClearOutputAction private constructor() : DumbAwareAction() {
|
||||
}
|
||||
|
||||
|
||||
internal class SaveOutputAction private constructor() : DumbAwareAction() {
|
||||
class SaveOutputAction private constructor() : DumbAwareAction() {
|
||||
override fun update(e: AnActionEvent) {
|
||||
e.presentation.isEnabledAndVisible = getInlayOutput<InlayOutput.WithSaveAs>(e) != null
|
||||
}
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.plugins.notebooks.visualization.r.inlays.components
|
||||
|
||||
import com.intellij.execution.process.ProcessOutputType
|
||||
import com.intellij.execution.process.ProcessOutputTypes
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.ui.RelativeFont
|
||||
import com.intellij.util.ui.StartupUiUtil
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.components.progress.InlayProgressStatus
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Font
|
||||
import java.awt.Rectangle
|
||||
import java.awt.event.ComponentAdapter
|
||||
import java.awt.event.ComponentEvent
|
||||
import kotlin.math.min
|
||||
|
||||
class ProcessOutput(val text: String, kind: Key<*>) {
|
||||
private val kindValue: Int = when(kind) {
|
||||
ProcessOutputTypes.STDOUT -> 1
|
||||
ProcessOutputTypes.STDERR -> 2
|
||||
else -> 3
|
||||
}
|
||||
|
||||
val kind: Key<*>
|
||||
get() = when (kindValue) {
|
||||
1 -> ProcessOutputType.STDOUT
|
||||
2 -> ProcessOutputType.STDERR
|
||||
else -> ProcessOutputType.SYSTEM
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Notebook console logs, HTML, and table result view. */
|
||||
class NotebookInlayOutput(private val editor: Editor, private val parent: Disposable) : NotebookInlayState(), ToolBarProvider {
|
||||
|
||||
init {
|
||||
layout = BorderLayout()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val RESIZE_TASK_NAME = "Resize graphics"
|
||||
private const val RESIZE_TASK_IDENTITY = "Resizing graphics"
|
||||
private const val RESIZE_TIME_SPAN = 500
|
||||
|
||||
private val monospacedFont = RelativeFont.NORMAL.family(Font.MONOSPACED)
|
||||
private val outputFont = monospacedFont.derive(StartupUiUtil.labelFont.deriveFont(UIUtil.getFontSize(UIUtil.FontSize.SMALL)))
|
||||
}
|
||||
|
||||
private var output: InlayOutput? = null
|
||||
|
||||
|
||||
private fun addTableOutput() = createOutput { parent, editor, clearAction -> InlayOutputTable(parent, editor, clearAction) }
|
||||
|
||||
private fun addTextOutput() = createOutput { parent, editor, clearAction -> InlayOutputText(parent, editor, clearAction) }
|
||||
|
||||
private fun addHtmlOutput() = createOutput { parent, editor, clearAction -> InlayOutputHtml(parent, editor, clearAction) }
|
||||
|
||||
private fun addImgOutput() = createOutput { parent, editor, clearAction -> InlayOutputImg(parent, editor, clearAction) }
|
||||
|
||||
private inline fun <T: InlayOutput> createOutput(constructor: (Disposable, Editor, () -> Unit) -> T) =
|
||||
constructor(parent, editor, clearAction).apply { setupOutput(this) }
|
||||
|
||||
private fun setupOutput(output: InlayOutput) {
|
||||
this.output?.let { remove(it.getComponent()) }
|
||||
this.output = output
|
||||
output.onHeightCalculated = { height -> onHeightCalculated?.invoke(height) }
|
||||
add(output.getComponent(), BorderLayout.CENTER)
|
||||
|
||||
addComponentListener(object : ComponentAdapter() {
|
||||
override fun componentResized(e: ComponentEvent) {
|
||||
if (output.isFullWidth) {
|
||||
output.getComponent().bounds = Rectangle(0, 0, e.component.bounds.width, e.component.bounds.height)
|
||||
} else {
|
||||
output.getComponent().bounds = Rectangle(0, 0, min(output.getComponent().preferredSize.width, e.component.bounds.width),
|
||||
e.component.bounds.height)
|
||||
}
|
||||
}
|
||||
})
|
||||
if (addToolbar) {
|
||||
output.addToolbar()
|
||||
}
|
||||
}
|
||||
|
||||
private var addToolbar = false
|
||||
|
||||
fun addToolbar() {
|
||||
addToolbar = true
|
||||
output?.addToolbar()
|
||||
}
|
||||
|
||||
private fun getOrAddTextOutput(): InlayOutputText {
|
||||
(output as? InlayOutputText)?.let { return it }
|
||||
return addTextOutput()
|
||||
}
|
||||
|
||||
fun addData(type: String, data: String, progressStatus: InlayProgressStatus?): InlayOutputProvider? {
|
||||
val provider = InlayOutputProvider.EP.extensionList.asSequence().filter { it.acceptType(type) }.firstOrNull()
|
||||
val inlayOutput: InlayOutput
|
||||
if (provider != null) {
|
||||
inlayOutput = output.takeIf { it?.acceptType(type) == true } ?: createOutput { parent, editor, clearAction ->
|
||||
provider.create(parent, editor, clearAction)
|
||||
}
|
||||
}
|
||||
else {
|
||||
inlayOutput = when (type) {
|
||||
"TABLE" -> output?.takeIf { it is InlayOutputTable } ?: addTableOutput()
|
||||
"HTML", "URL" -> output?.takeIf { it is InlayOutputHtml } ?: addHtmlOutput()
|
||||
"IMG", "IMGBase64", "IMGSVG" -> output?.takeIf { it is InlayOutputImg } ?: addImgOutput()
|
||||
else -> getOrAddTextOutput()
|
||||
}
|
||||
}
|
||||
progressStatus?.let {
|
||||
inlayOutput.updateProgressStatus(editor, it)
|
||||
}
|
||||
inlayOutput.addData(data, type)
|
||||
return provider
|
||||
}
|
||||
|
||||
fun addText(message: String, outputType: Key<*>) {
|
||||
getOrAddTextOutput().addData(message, outputType)
|
||||
}
|
||||
|
||||
override fun updateProgressStatus(progressStatus: InlayProgressStatus) {
|
||||
output?.updateProgressStatus(editor, progressStatus)
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
output?.clear()
|
||||
}
|
||||
|
||||
override fun getCollapsedDescription(): String {
|
||||
return if (output == null) "" else output!!.getCollapsedDescription()
|
||||
}
|
||||
|
||||
override fun onViewportChange(isInViewport: Boolean) {
|
||||
output?.onViewportChange(isInViewport)
|
||||
}
|
||||
|
||||
override fun createActions(): List<AnAction> = output?.actions?.filterNot { it is ClearOutputAction } ?: emptyList()
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.plugins.notebooks.visualization.r.inlays.components
|
||||
|
||||
import com.intellij.execution.process.ProcessOutputType
|
||||
import com.intellij.execution.process.ProcessOutputTypes
|
||||
import com.intellij.openapi.util.Key
|
||||
|
||||
class ProcessOutput(val text: String, kind: Key<*>) {
|
||||
private val kindValue: Int = when(kind) {
|
||||
ProcessOutputTypes.STDOUT -> 1
|
||||
ProcessOutputTypes.STDERR -> 2
|
||||
else -> 3
|
||||
}
|
||||
|
||||
val kind: Key<*>
|
||||
get() = when (kindValue) {
|
||||
1 -> ProcessOutputType.STDOUT
|
||||
2 -> ProcessOutputType.STDERR
|
||||
else -> ProcessOutputType.SYSTEM
|
||||
}
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.plugins.notebooks.visualization.r.inlays.components
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.actionSystem.ActionPlaces
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup
|
||||
import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.ui.Gray
|
||||
import com.intellij.ui.tabs.TabInfo
|
||||
import com.intellij.ui.tabs.TabsListener
|
||||
import com.intellij.ui.tabs.impl.JBTabsImpl
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.InlayOutput
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.components.progress.InlayProgressStatus
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.ui.ToolbarUtil
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Dimension
|
||||
import java.awt.Rectangle
|
||||
import java.awt.event.ComponentAdapter
|
||||
import java.awt.event.ComponentEvent
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JPanel
|
||||
|
||||
/** A multi-output inlay that puts outputs from different sources to separate tabbed pane tabs. */
|
||||
internal class TabbedMultiOutput(private val editor: Editor, parent: Disposable) : NotebookInlayMultiOutput() {
|
||||
/** Page control for result viewing. */
|
||||
private val tabs: JBTabsImpl
|
||||
|
||||
var onChange: (() -> Unit)? = null
|
||||
|
||||
private val disposable = Disposer.newDisposable()
|
||||
|
||||
private var maxHeight: Int = -1
|
||||
|
||||
private val project = editor.project!!
|
||||
|
||||
private val tabsOutput: MutableSet<NotebookInlayOutput> = mutableSetOf()
|
||||
|
||||
@Volatile
|
||||
private var isInViewport: Boolean = false
|
||||
|
||||
init {
|
||||
Disposer.register(parent, disposable)
|
||||
tabs = JBTabsImpl(project, disposable)
|
||||
tabs.addListener(object : TabsListener {
|
||||
override fun selectionChanged(oldSelection: TabInfo?, newSelection: TabInfo?) {
|
||||
oldSelection?.onViewportChange(false) // Definitely false
|
||||
newSelection?.onViewportChange(isInViewport) // Might be true
|
||||
onChange?.invoke()
|
||||
}
|
||||
})
|
||||
|
||||
tabs.component.isOpaque = false
|
||||
tabs.component.background = Gray.TRANSPARENT
|
||||
|
||||
add(tabs.component, BorderLayout.CENTER)
|
||||
|
||||
// To make it possible to use JLayeredPane as a parent of NotebookInlayState.
|
||||
addComponentListener(object : ComponentAdapter() {
|
||||
override fun componentResized(e: ComponentEvent) {
|
||||
tabs.component.bounds = Rectangle(0, 0, e.component.bounds.width, e.component.bounds.height)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun setCurrentPage(currentPage: String) {
|
||||
val tabToSelect = tabs.tabs.find { it.text == currentPage }
|
||||
if(tabToSelect != null) {
|
||||
tabs.select(tabToSelect, false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOutputs(inlayOutputs: List<InlayOutput>) {
|
||||
tabs.removeAllTabs()
|
||||
tabsOutput.clear()
|
||||
for (inlayOutput in inlayOutputs) {
|
||||
NotebookInlayOutput(editor, disposable).apply {
|
||||
setupOnHeightCalculated()
|
||||
addData(inlayOutput.type, inlayOutput.data, inlayOutput.progressStatus)
|
||||
tabsOutput.add(this)
|
||||
addTab(inlayOutput)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateProgressStatus(progressStatus: InlayProgressStatus) {
|
||||
tabsOutput.forEach { output ->
|
||||
output.updateProgressStatus(progressStatus)
|
||||
}
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
}
|
||||
|
||||
override fun getCollapsedDescription(): String {
|
||||
return "foooo"
|
||||
}
|
||||
|
||||
override fun onViewportChange(isInViewport: Boolean) {
|
||||
this.isInViewport = isInViewport
|
||||
tabs.selectedInfo?.onViewportChange(isInViewport)
|
||||
}
|
||||
|
||||
private fun TabInfo.onViewportChange(isInViewport: Boolean) {
|
||||
(component as NotebookInlayState?)?.onViewportChange(isInViewport)
|
||||
}
|
||||
|
||||
private fun NotebookInlayState.setupOnHeightCalculated() {
|
||||
onHeightCalculated = {
|
||||
tabs.findInfo(this)?.let { tab ->
|
||||
updateMaxHeight(it + tabs.getTabLabel(tab)!!.preferredSize.height)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun NotebookInlayState.addTab(inlayOutput: InlayOutput) {
|
||||
addTab(TabInfo(this).apply {
|
||||
inlayOutput.preview?.let {
|
||||
setIcon(it)
|
||||
setText("")
|
||||
}
|
||||
inlayOutput.title?.let {
|
||||
setText(it)
|
||||
}
|
||||
}).apply {
|
||||
tabs.getTabLabel(this)?.apply {
|
||||
if (inlayOutput.preferredWidth != 0) {
|
||||
preferredSize = Dimension(inlayOutput.preferredWidth, 0)
|
||||
}
|
||||
}
|
||||
if (tabs.selectedInfo == null) {
|
||||
tabs.select(this, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addTab(tabInfo: TabInfo, select: Boolean = false): TabInfo {
|
||||
// We need to set empty DefaultActionGroup to move sideComponent to the right.
|
||||
tabInfo.setActions(DefaultActionGroup(), ActionPlaces.UNKNOWN)
|
||||
tabInfo.setSideComponent(createTabToolbar(tabInfo))
|
||||
tabs.addTab(tabInfo)
|
||||
if (select) {
|
||||
tabs.select(tabInfo, false)
|
||||
}
|
||||
return tabInfo
|
||||
}
|
||||
|
||||
private fun createTabToolbar(tabInfo: TabInfo): JComponent {
|
||||
val actionGroups = createTabActionGroups(tabInfo)
|
||||
val toolbar = ToolbarUtil.createActionToolbar(javaClass.simpleName, actionGroups).component
|
||||
if (toolbar is ActionToolbarImpl) {
|
||||
toolbar.setForceMinimumSize(true)
|
||||
}
|
||||
return JPanel().apply { // Align toolbar to top
|
||||
add(toolbar)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createTabActionGroups(tabInfo: TabInfo): List<List<AnAction>> {
|
||||
return mutableListOf<List<AnAction>>().also { groups ->
|
||||
(tabInfo.component as? ToolBarProvider)?.let { provider ->
|
||||
groups.add(provider.createActions())
|
||||
}
|
||||
groups.add(listOf(createClearAction()))
|
||||
}
|
||||
}
|
||||
|
||||
private fun createClearAction(): AnAction {
|
||||
return ToolbarUtil.createAnActionButton(ClearOutputAction.ID, clearAction::invoke)
|
||||
}
|
||||
|
||||
private fun updateMaxHeight(height: Int) {
|
||||
if (maxHeight < height) {
|
||||
maxHeight = height
|
||||
onHeightCalculated?.invoke(maxHeight)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,7 @@
|
||||
package org.jetbrains.plugins.notebooks.visualization.r.ui
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import org.intellij.images.editor.ImageEditor
|
||||
import org.intellij.images.editor.impl.ImageEditorImpl
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.components.GraphicsPanel
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.components.ToolbarPane
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.components.progress.InlayProgressStatus
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.components.progress.JupyterProgressStatus
|
||||
@@ -14,9 +9,6 @@ import javax.swing.JComponent
|
||||
import javax.swing.JPanel
|
||||
|
||||
class DefaultUiCustomizer : UiCustomizer {
|
||||
override fun createImageEditor(project: Project, file: VirtualFile, graphicsPanel: GraphicsPanel): ImageEditor =
|
||||
ImageEditorImpl(project, file)
|
||||
|
||||
override fun toolbarPaneProgressComponentChanged(toolbarPane: ToolbarPane, component: JComponent?): Unit = Unit
|
||||
|
||||
override fun toolbarPaneToolbarComponentChanged(toolbarPane: ToolbarPane, component: JComponent?): Unit = Unit
|
||||
@@ -30,4 +22,4 @@ class DefaultUiCustomizer : UiCustomizer {
|
||||
}
|
||||
|
||||
override val showUpdateCellSeparator: Boolean = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,6 @@ package org.jetbrains.plugins.notebooks.visualization.r.ui
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.intellij.images.editor.ImageEditor
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.components.GraphicsPanel
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.components.ToolbarPane
|
||||
import org.jetbrains.plugins.notebooks.visualization.r.inlays.components.progress.InlayProgressStatus
|
||||
import java.awt.Color
|
||||
@@ -13,9 +9,6 @@ import javax.swing.JComponent
|
||||
import javax.swing.JPanel
|
||||
|
||||
interface UiCustomizer {
|
||||
fun createImageEditor(project: Project,
|
||||
file: VirtualFile,
|
||||
graphicsPanel: GraphicsPanel): ImageEditor
|
||||
|
||||
fun toolbarPaneToolbarComponentChanged(toolbarPane: ToolbarPane, component: JComponent?)
|
||||
|
||||
@@ -37,4 +30,4 @@ interface UiCustomizer {
|
||||
|
||||
val instance: UiCustomizer get() = EP_NAME.extensionList.first()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user