[jupyter] PY-66455 improved toolbar disappearance logic

GitOrigin-RevId: 7410c1146e7fbdc674d95523185ea348a9880afc
This commit is contained in:
Bogdan Kirilenko
2024-03-09 12:53:12 +01:00
committed by intellij-monorepo-bot
parent da982277a1
commit 72a7ea91f7
3 changed files with 62 additions and 42 deletions

View File

@@ -8,6 +8,7 @@ import com.intellij.ui.JBColor
import com.intellij.ui.RoundedLineBorder
import com.intellij.util.ui.JBUI
import com.intellij.util.ui.StartupUiUtil
import java.awt.AlphaComposite
import java.awt.Cursor
import java.awt.Graphics
import java.awt.Graphics2D
@@ -20,11 +21,13 @@ import javax.swing.BorderFactory
class JupyterToolbar(actionGroup: ActionGroup,
firstLine: Int = 0
) : ActionToolbarImpl(ActionPlaces.EDITOR_INLAY, actionGroup, true) {
var alpha = 1.0f
init {
border = BorderFactory.createCompoundBorder(RoundedLineBorder(JBColor.LIGHT_GRAY, TOOLBAR_ARC_SIZE, TOOLBAR_BORDER_THICKNESS),
BorderFactory.createEmptyBorder(2, 3, 2, 3))
cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)
isOpaque = false
cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)
border = BorderFactory.createCompoundBorder(RoundedLineBorder(JBColor.LIGHT_GRAY, TOOLBAR_ARC_SIZE, TOOLBAR_BORDER_THICKNESS),
BorderFactory.createEmptyBorder(OUTER_PADDING, OUTER_PADDING, OUTER_PADDING, OUTER_PADDING))
// todo: it would be preferable to set NotebookCellLines.Interval right here
putClientProperty(JUPYTER_TOOLBAR_LINE_POSITION_KEY, firstLine)
setSkipWindowAdjustments(false)
@@ -33,6 +36,7 @@ class JupyterToolbar(actionGroup: ActionGroup,
override fun paintComponent(g: Graphics) {
val g2 = g.create() as Graphics2D
try {
g2.composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha)
g2.color = this.background
g2.fillRoundRect(0, 0, width, height, TOOLBAR_ARC_SIZE, TOOLBAR_ARC_SIZE)
}
@@ -51,6 +55,7 @@ class JupyterToolbar(actionGroup: ActionGroup,
companion object {
private val TOOLBAR_ARC_SIZE = JBUI.scale(14)
private val TOOLBAR_BORDER_THICKNESS = JBUI.scale(1)
private val OUTER_PADDING = JBUI.scale(3)
val JUPYTER_TOOLBAR_LINE_POSITION_KEY = Key.create<Int>("JUPYTER_TOOLBAR_LINE_POSITION_KEY")
}
}

View File

@@ -5,12 +5,10 @@ import com.intellij.openapi.actionSystem.ActionGroup
import com.intellij.openapi.editor.impl.EditorImpl
import com.intellij.ui.scale.JBUIScale
import java.awt.Dimension
import java.awt.MouseInfo
import java.awt.Point
import java.awt.Rectangle
import java.awt.event.ComponentAdapter
import java.awt.event.ComponentEvent
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import java.awt.event.*
import javax.swing.JPanel
import javax.swing.SwingUtilities
import javax.swing.Timer
@@ -20,14 +18,15 @@ class JupyterToolbarManager(
private val panel: JPanel,
private val actionGroupId: String,
private val firstLine: Int = 0
) { // PY-66455
) { // See PY-66455
private var toolbar: JupyterToolbar? = null
private var hideToolbarTimer = Timer(TOOLBAR_HIDE_DELAY) { hideToolBar() }
private var mouseEnteredTbFlag = false
private var hideToolbarTimer = Timer(TOOLBAR_HIDE_DELAY) { conditionallyHideToolBar() }
init {
initPanelMouseListeners()
addPanelComponentListener()
addEditorKeyListener()
addEditorComponentListener()
}
private fun initPanelMouseListeners() {
@@ -38,29 +37,11 @@ class JupyterToolbarManager(
}
override fun mouseExited(e: MouseEvent) {
if (!mouseEnteredTbFlag) {
hideToolbarTimer.restart()
}
}
}
panel.addMouseListener(mouseAdapter)
}
private fun addToolbarListeners() {
val toolbarListener = object : MouseAdapter() {
override fun mouseEntered(e: MouseEvent) {
mouseEnteredTbFlag = true
hideToolbarTimer.stop()
}
override fun mouseExited(e: MouseEvent) {
mouseEnteredTbFlag = false
hideToolbarTimer.restart()
}
}
toolbar?.addMouseListener(toolbarListener)
panel.addMouseListener(mouseAdapter)
}
private fun addPanelComponentListener() {
@@ -86,6 +67,51 @@ class JupyterToolbarManager(
panel.addComponentListener(componentListener)
}
private fun addEditorKeyListener() {
val keyAdapter = object : KeyAdapter() {
override fun keyTyped(e: KeyEvent) = hideToolBar()
override fun keyPressed(e: KeyEvent) = hideToolBar()
}
editor.contentComponent.addKeyListener(keyAdapter)
}
private fun addEditorComponentListener() {
editor.contentComponent.addComponentListener(object : ComponentAdapter() {
override fun componentResized(e: ComponentEvent?) = hideToolBar()
})
}
/**
* Checks if the mouse is over the toolbar before hiding it.
* This is necessary because mouseExited events on the panel can trigger even when the mouse
* is over the toolbar due to its position in the Z-stack.
* If the mouse is indeed over the toolbar, hiding is deferred to prevent an unintended disappearance,
* acting as an additional safeguard for better user experience.
*/
private fun conditionallyHideToolBar() {
toolbar?.let { tb ->
val mousePos = MouseInfo.getPointerInfo().location
SwingUtilities.convertPointFromScreen(mousePos, editor.contentComponent)
if (tb.bounds.contains(mousePos)) {
hideToolbarTimer.restart()
} else {
hideToolBar() // mouse is not over the toolbar - we may hide it
}
}
}
fun hideToolBar() {
toolbar?.let {
editor.contentComponent.remove(it)
editor.contentComponent.revalidate()
editor.contentComponent.repaint()
toolbar = null
JupyterToolbarVisibilityManager.notifyToolbarHidden(this)
}
}
private fun showToolbar() {
if (toolbar == null) {
val actionGroup = createActionGroup() ?: return
@@ -96,17 +122,6 @@ class JupyterToolbarManager(
JupyterToolbarVisibilityManager.requestToolbarDisplay(this)
editor.contentComponent.add(toolbar, 0)
positionToolbar()
addToolbarListeners()
}
fun hideToolBar() {
toolbar?.let {
editor.contentComponent.remove(it)
editor.contentComponent.revalidate()
editor.contentComponent.repaint()
}
toolbar = null
JupyterToolbarVisibilityManager.notifyToolbarHidden(this)
}
private fun positionToolbar() {
@@ -122,7 +137,7 @@ class JupyterToolbarManager(
companion object {
private val DEFAULT_Y_OFFSET = JBUIScale.scale(-10)
private const val TOOLBAR_HIDE_DELAY = 3000
private const val TOOLBAR_HIDE_DELAY = 800
fun calculateToolbarBounds(
editor: EditorImpl,