mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[gh] IJPL-214797 Add tooltip on the code outline of a new comment
GitOrigin-RevId: e8702711a48314f40accf75a9733fe6f36ccef23
This commit is contained in:
committed by
intellij-monorepo-bot
parent
dd9616d40a
commit
954e2d55a1
@@ -146,6 +146,9 @@ com.intellij.ide.IdeEventQueue$EventDispatcher
|
||||
- a:dispatch(java.awt.AWTEvent):Z
|
||||
com.intellij.ide.IdeEventQueue$NonLockedEventDispatcher
|
||||
- com.intellij.ide.IdeEventQueue$EventDispatcher
|
||||
c:com.intellij.ide.IdeTooltip
|
||||
- isCalloutEnabled():Z
|
||||
- setShowCallout(Z):com.intellij.ide.IdeTooltip
|
||||
com.intellij.ide.IdeTooltip$Ui
|
||||
- a:getShowingPoint():com.intellij.ui.awt.RelativePoint
|
||||
- a:isInside(com.intellij.ui.awt.RelativePoint):Z
|
||||
|
||||
@@ -50,6 +50,7 @@ public class IdeTooltip extends ComparableObject.Impl {
|
||||
|
||||
private int myCalloutShift = 4;
|
||||
private boolean myExplicitClose;
|
||||
private boolean isCalloutEnabled = true;
|
||||
|
||||
private int myPositionChangeX;
|
||||
private int myPositionChangeY;
|
||||
@@ -240,6 +241,15 @@ public class IdeTooltip extends ComparableObject.Impl {
|
||||
return this;
|
||||
}
|
||||
|
||||
public IdeTooltip setShowCallout(boolean showCallout) {
|
||||
isCalloutEnabled = showCallout;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isCalloutEnabled() {
|
||||
return isCalloutEnabled;
|
||||
}
|
||||
|
||||
public void setComponent(Component component) {
|
||||
myComponent = component;
|
||||
}
|
||||
|
||||
@@ -638,7 +638,7 @@ class IdeTooltipManager(coroutineScope: CoroutineScope) : Disposable {
|
||||
.setBorderColor(borderColor)
|
||||
.setBorderInsets(tooltip.borderInsets)
|
||||
.setAnimationCycle(if (animationEnabled) RegistryManager.getInstance().intValue("ide.tooltip.animationCycle") else 0)
|
||||
.setShowCallout(true)
|
||||
.setShowCallout(tooltip.isCalloutEnabled)
|
||||
.setPointerSize(tooltip.pointerSize)
|
||||
.setCalloutShift(if (small && tooltip.calloutShift == 0) 2 else tooltip.calloutShift)
|
||||
.setPositionChangeXShift(tooltip.positionChangeX)
|
||||
|
||||
+61
-49
@@ -11,7 +11,8 @@ import com.intellij.collaboration.ui.codereview.editor.CodeReviewEditorGutterCon
|
||||
import com.intellij.collaboration.ui.codereview.editor.CodeReviewEditorInlaysModel
|
||||
import com.intellij.diff.util.LineRange
|
||||
import com.intellij.diff.util.Side
|
||||
import com.intellij.ide.HelpTooltip
|
||||
import com.intellij.ide.IdeTooltip
|
||||
import com.intellij.ide.IdeTooltipManager
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.event.EditorMouseEvent
|
||||
import com.intellij.openapi.editor.event.EditorMouseListener
|
||||
@@ -21,6 +22,7 @@ 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.project.Project
|
||||
import com.intellij.openapi.ui.popup.Balloon
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.openapi.wm.IdeGlassPaneUtil
|
||||
import com.intellij.platform.util.coroutines.childScope
|
||||
@@ -36,9 +38,9 @@ import org.jetbrains.plugins.github.i18n.GithubBundle
|
||||
import org.jetbrains.plugins.github.pullrequest.ui.comment.CommentedCodeFrameRenderer
|
||||
import org.jetbrains.plugins.github.pullrequest.ui.editor.GHPREditorMappedComponentModel
|
||||
import java.awt.*
|
||||
import java.awt.event.MouseEvent
|
||||
import java.beans.PropertyChangeListener
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JLabel
|
||||
import javax.swing.JLayer
|
||||
import javax.swing.SwingUtilities
|
||||
import javax.swing.plaf.LayerUI
|
||||
@@ -57,10 +59,10 @@ internal object GHPRInlayUtils {
|
||||
var activeLineHighlighter: RangeHighlighter? = null
|
||||
val multilineCommentsDisabled = Registry.get("github.pr.new.multiline.comments.disabled").asBoolean()
|
||||
val frameResizer = if (vm is GHPREditorMappedComponentModel.NewComment<*> && !(isUnifiedDiff && multilineCommentsDisabled)) {
|
||||
val frameResizer = ResizingFrameListener(editor, vm)
|
||||
editor.addEditorMouseMotionListener(frameResizer)
|
||||
editor.addEditorMouseListener(frameResizer)
|
||||
frameResizer
|
||||
ResizingFrameListener(editor, vm).also {
|
||||
editor.addEditorMouseMotionListener(it)
|
||||
editor.addEditorMouseListener(it)
|
||||
}
|
||||
}
|
||||
else null
|
||||
|
||||
@@ -112,7 +114,10 @@ internal object GHPRInlayUtils {
|
||||
private const val OUTLINE_OUTSIDE_DETECTION_MARGIN = 3
|
||||
private const val OUTLINE_DETECTION_LINE_FRACTION = 0.3f
|
||||
|
||||
private class ResizingFrameListener(val editor: Editor, val vm: GHPREditorMappedComponentModel.NewComment<*>) : EditorMouseListener, EditorMouseMotionListener {
|
||||
private class ResizingFrameListener(
|
||||
private val editor: Editor,
|
||||
private val vm: GHPREditorMappedComponentModel.NewComment<*>,
|
||||
) : EditorMouseListener, EditorMouseMotionListener {
|
||||
private val editorEx = editor as EditorEx
|
||||
private val model: CodeReviewEditorGutterControlsModel.WithMultilineComments?
|
||||
get() = editorEx.getUserData(CodeReviewCommentableEditorModel.KEY) as? CodeReviewEditorGutterControlsModel.WithMultilineComments
|
||||
@@ -134,8 +139,9 @@ internal object GHPRInlayUtils {
|
||||
Cursor.getDefaultCursor()
|
||||
}
|
||||
|
||||
private var currentTooltip: IdeTooltip? = null
|
||||
|
||||
init {
|
||||
setupTooltips()
|
||||
SwingUtilities.invokeLater {
|
||||
val gutterComponent = editorEx.gutterComponentEx
|
||||
val gutterMousePos = gutterComponent.mousePosition ?: return@invokeLater
|
||||
@@ -143,52 +149,13 @@ internal object GHPRInlayUtils {
|
||||
|
||||
if (gutterMousePos.getEdge(yBorders) != null) {
|
||||
gutterComponent.cursor = resizeCursor
|
||||
forceTooltip(gutterMousePos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupTooltips() {
|
||||
val condition: () -> Boolean = {
|
||||
val yBorders = getYAxisBorders()
|
||||
val mousePos = editorEx.gutterComponentEx.mousePosition ?: editor.contentComponent.mousePosition
|
||||
yBorders != null && mousePos != null && mousePos.getEdge(yBorders) != null
|
||||
}
|
||||
listOf(editorEx.gutterComponentEx, editor.contentComponent).forEach { component ->
|
||||
HelpTooltip()
|
||||
.setDescription(GithubBundle.message("pull.request.review.new.comment.code.outline.tooltip"))
|
||||
.setLocation(HelpTooltip.Alignment.CURSOR)
|
||||
.setInitialDelay(100)
|
||||
.installOn(component)
|
||||
|
||||
HelpTooltip.setMasterPopupOpenCondition(component, condition)
|
||||
}
|
||||
}
|
||||
|
||||
private fun forceTooltip(gutterMousePos: Point) {
|
||||
val gutterComponent = editorEx.gutterComponentEx
|
||||
val mouseEvent = MouseEvent(
|
||||
gutterComponent,
|
||||
MouseEvent.MOUSE_ENTERED,
|
||||
System.currentTimeMillis(),
|
||||
0,
|
||||
gutterMousePos.x,
|
||||
gutterMousePos.y,
|
||||
0,
|
||||
false,
|
||||
)
|
||||
gutterComponent.dispatchEvent(mouseEvent)
|
||||
}
|
||||
|
||||
private fun hideTooltip() {
|
||||
HelpTooltip.hide(editor.contentComponent)
|
||||
HelpTooltip.hide(editorEx.gutterComponentEx)
|
||||
}
|
||||
|
||||
override fun mouseDragged(e: EditorMouseEvent) {
|
||||
if (!isDraggingFrame || edge == null || oldRange == null) return
|
||||
e.consume() // to prevent selecting text while dragging
|
||||
hideTooltip()
|
||||
val mouseY = e.mouseEvent.y.toFloat()
|
||||
val dragDelta = mouseY - dragStart
|
||||
val direction = if (dragDelta > 0) 1 else -1
|
||||
@@ -245,19 +212,41 @@ internal object GHPRInlayUtils {
|
||||
isDraggingFrame = true
|
||||
}
|
||||
|
||||
override fun mouseEntered(e: EditorMouseEvent) {
|
||||
if (isDraggingFrame) return
|
||||
val yBorders = getYAxisBorders() ?: return
|
||||
val point = e.mouseEvent.point
|
||||
val onEdge = point.getEdge(yBorders) != null
|
||||
if (onEdge) {
|
||||
showTooltip(e.mouseEvent.component, point)
|
||||
}
|
||||
}
|
||||
|
||||
override fun mouseMoved(e: EditorMouseEvent) {
|
||||
val yBorders = getYAxisBorders() ?: return
|
||||
val onEdge = e.mouseEvent.point.getEdge(yBorders) != null
|
||||
val point = e.mouseEvent.point
|
||||
val onEdge = point.getEdge(yBorders) != null
|
||||
val gutterGlassComp = IdeGlassPaneUtil.find(editorEx.gutterComponentEx)
|
||||
|
||||
if (onEdge) {
|
||||
editorEx.setCustomCursor(this, resizeCursor)
|
||||
gutterGlassComp.setCursor(resizeCursor, this)
|
||||
}
|
||||
else {
|
||||
hideTooltip()
|
||||
editorEx.setCustomCursor(this, null)
|
||||
gutterGlassComp.setCursor(null, this)
|
||||
}
|
||||
|
||||
if (onEdge && !isDraggingFrame) {
|
||||
showTooltip(e.mouseEvent.component, point)
|
||||
}
|
||||
else {
|
||||
hideTooltip()
|
||||
}
|
||||
}
|
||||
|
||||
override fun mouseExited(event: EditorMouseEvent) {
|
||||
hideTooltip()
|
||||
}
|
||||
|
||||
private fun Point.getEdge(frameCoords: Pair<Float, Float>): Edge? {
|
||||
@@ -284,6 +273,29 @@ internal object GHPRInlayUtils {
|
||||
return topY to bottomY
|
||||
}
|
||||
|
||||
private fun showTooltip(component: Component, point: Point) {
|
||||
val offsetPoint = Point(point.x, point.y + editor.lineHeight) // offset for tooltip placement
|
||||
currentTooltip?.let {
|
||||
it.component = component
|
||||
it.point = offsetPoint
|
||||
}
|
||||
|
||||
if (currentTooltip == null) {
|
||||
val label = JLabel(GithubBundle.message("pull.request.review.new.comment.code.outline.tooltip"))
|
||||
currentTooltip = IdeTooltip(component, offsetPoint, label)
|
||||
.setPreferredPosition(Balloon.Position.below)
|
||||
.setShowCallout(false)
|
||||
}
|
||||
IdeTooltipManager.getInstance().show(currentTooltip!!, false)
|
||||
}
|
||||
|
||||
private fun hideTooltip() {
|
||||
currentTooltip?.let {
|
||||
IdeTooltipManager.getInstance().hide(it)
|
||||
}
|
||||
currentTooltip = null
|
||||
}
|
||||
|
||||
private enum class Edge {
|
||||
TOP, BOTTOM
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user