mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-20 13:31:28 +07:00
[terminal] IJPL-182032 Keep the cursor visible on the screen when the port forwarding panel appears
Previously, when the port forwarding panel appeared on top, the editor was scrolled down, so the cursor position was hidden. Let's react on port forwarding panel size changes and update the scroll position. Move top panel management from `ReworkedTerminalWidget` to the `ReworkedTerminalView`. Refactor the TerminalPanel to extract the layered pane logic to the separate `TerminalLayeredPane`. (cherry picked from commit 78992a106db33e5861d362d5aca00942dbf0382c) IJ-CR-159801 GitOrigin-RevId: 7bb54ad4cdb89c7f8765b06d340ed3b6eec0a5a4
This commit is contained in:
committed by
intellij-monorepo-bot
parent
a2a9631b60
commit
df7a682006
@@ -13,7 +13,6 @@ import com.intellij.openapi.editor.Document
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.EditorFactory
|
||||
import com.intellij.openapi.editor.ex.EditorEx
|
||||
import com.intellij.openapi.editor.ex.util.EditorUtil
|
||||
import com.intellij.openapi.editor.impl.DocumentImpl
|
||||
import com.intellij.openapi.editor.impl.EditorImpl
|
||||
import com.intellij.openapi.editor.impl.SoftWrapModelImpl
|
||||
@@ -27,6 +26,7 @@ import com.intellij.terminal.JBTerminalSystemSettingsProviderBase
|
||||
import com.intellij.terminal.session.TerminalSession
|
||||
import com.intellij.ui.components.JBLayeredPane
|
||||
import com.intellij.util.asDisposable
|
||||
import com.intellij.util.ui.components.BorderLayoutPanel
|
||||
import com.jediterm.core.util.TermSize
|
||||
import com.jediterm.terminal.TtyConnector
|
||||
import kotlinx.coroutines.*
|
||||
@@ -66,6 +66,7 @@ internal class ReworkedTerminalView(
|
||||
|
||||
private val outputEditor: EditorEx
|
||||
private val alternateBufferEditor: EditorEx
|
||||
private val scrollingModel: TerminalOutputScrollingModel
|
||||
|
||||
private val terminalPanel: TerminalPanel
|
||||
|
||||
@@ -101,7 +102,7 @@ internal class ReworkedTerminalView(
|
||||
|
||||
outputEditor = createOutputEditor(settings, parentDisposable = this)
|
||||
val outputModel = TerminalOutputModelImpl(outputEditor.document, maxOutputLength = TerminalUiUtils.getDefaultMaxOutputLength())
|
||||
val scrollingModel = TerminalOutputScrollingModelImpl(outputEditor, outputModel, sessionModel, coroutineScope.childScope("TerminalOutputScrollingModel"))
|
||||
scrollingModel = TerminalOutputScrollingModelImpl(outputEditor, outputModel, sessionModel, coroutineScope.childScope("TerminalOutputScrollingModel"))
|
||||
outputEditor.putUserData(TerminalOutputScrollingModel.KEY, scrollingModel)
|
||||
|
||||
configureOutputEditor(
|
||||
@@ -175,6 +176,23 @@ internal class ReworkedTerminalView(
|
||||
return component.hasFocus()
|
||||
}
|
||||
|
||||
fun setTopComponent(component: JComponent, disposable: Disposable) {
|
||||
val resizeListener = object : ComponentAdapter() {
|
||||
override fun componentResized(e: ComponentEvent) {
|
||||
// Update scroll position on top component size change
|
||||
// to always keep the cursor visible
|
||||
scrollingModel.scrollToCursor(force = false)
|
||||
}
|
||||
}
|
||||
component.addComponentListener(resizeListener)
|
||||
terminalPanel.setTopComponent(component)
|
||||
|
||||
Disposer.register(disposable) {
|
||||
component.removeComponentListener(resizeListener)
|
||||
terminalPanel.remoteTopComponent(component)
|
||||
}
|
||||
}
|
||||
|
||||
private fun listenSearchController() {
|
||||
terminalSearchController.addListener(object : TerminalSearchControllerListener {
|
||||
override fun searchSessionStarted(session: TerminalSearchSession) {
|
||||
@@ -349,9 +367,13 @@ internal class ReworkedTerminalView(
|
||||
terminalPanel.addFocusListener(parentDisposable, listener)
|
||||
}
|
||||
|
||||
private inner class TerminalPanel(initialContent: Editor) : JBLayeredPane(), UiDataProvider {
|
||||
private inner class TerminalPanel(initialContent: Editor) : BorderLayoutPanel(), UiDataProvider {
|
||||
private val layeredPane = TerminalLayeredPane(initialContent)
|
||||
private var curEditor: Editor = initialContent
|
||||
|
||||
val preferredFocusableComponent: JComponent
|
||||
get() = layeredPane.preferredFocusableComponent
|
||||
|
||||
private val delegatingFocusListener = object : FocusListener {
|
||||
override fun focusGained(e: FocusEvent) {
|
||||
focusListeners.forEach { it.focusGained(e) }
|
||||
@@ -363,24 +385,8 @@ internal class ReworkedTerminalView(
|
||||
}
|
||||
|
||||
init {
|
||||
setTerminalContent(initialContent)
|
||||
}
|
||||
|
||||
val preferredFocusableComponent: JComponent
|
||||
get() = curEditor.contentComponent
|
||||
|
||||
fun setTerminalContent(editor: Editor) {
|
||||
val prevEditor = curEditor
|
||||
@Suppress("SENSELESS_COMPARISON") // called from init when curEditor == null
|
||||
if (prevEditor != null) {
|
||||
prevEditor.contentComponent.removeFocusListener(delegatingFocusListener)
|
||||
remove(curEditor.component)
|
||||
}
|
||||
curEditor = editor
|
||||
addToLayer(editor.component, DEFAULT_LAYER)
|
||||
editor.contentComponent.addFocusListener(delegatingFocusListener)
|
||||
revalidate()
|
||||
repaint()
|
||||
addToCenter(layeredPane)
|
||||
updateFocusListeners(initialContent, initialContent)
|
||||
}
|
||||
|
||||
override fun uiDataSnapshot(sink: DataSink) {
|
||||
@@ -389,6 +395,61 @@ internal class ReworkedTerminalView(
|
||||
sink[TerminalSearchController.KEY] = terminalSearchController
|
||||
}
|
||||
|
||||
fun setTerminalContent(editor: Editor) {
|
||||
layeredPane.setTerminalContent(editor)
|
||||
updateFocusListeners(curEditor, editor)
|
||||
curEditor = editor
|
||||
}
|
||||
|
||||
fun installSearchComponent(component: SearchReplaceComponent) {
|
||||
layeredPane.installSearchComponent(component)
|
||||
}
|
||||
|
||||
fun removeSearchComponent(component: SearchReplaceComponent) {
|
||||
layeredPane.removeSearchComponent(component)
|
||||
}
|
||||
|
||||
fun setTopComponent(component: JComponent) {
|
||||
addToTop(component)
|
||||
revalidate()
|
||||
repaint()
|
||||
}
|
||||
|
||||
fun remoteTopComponent(component: JComponent) {
|
||||
remove(component)
|
||||
revalidate()
|
||||
repaint()
|
||||
}
|
||||
|
||||
private fun updateFocusListeners(prevEditor: Editor, newEditor: Editor) {
|
||||
prevEditor.contentComponent.removeFocusListener(delegatingFocusListener)
|
||||
newEditor.contentComponent.addFocusListener(delegatingFocusListener)
|
||||
}
|
||||
}
|
||||
|
||||
private class TerminalLayeredPane(initialContent: Editor) : JBLayeredPane() {
|
||||
private var curEditor: Editor = initialContent
|
||||
|
||||
val preferredFocusableComponent: JComponent
|
||||
get() = curEditor.contentComponent
|
||||
|
||||
init {
|
||||
setTerminalContent(initialContent)
|
||||
}
|
||||
|
||||
fun setTerminalContent(editor: Editor) {
|
||||
val prevEditor = curEditor
|
||||
@Suppress("SENSELESS_COMPARISON") // called from init when curEditor == null
|
||||
if (prevEditor != null) {
|
||||
remove(curEditor.component)
|
||||
}
|
||||
curEditor = editor
|
||||
addToLayer(editor.component, DEFAULT_LAYER)
|
||||
|
||||
revalidate()
|
||||
repaint()
|
||||
}
|
||||
|
||||
fun installSearchComponent(component: SearchReplaceComponent) {
|
||||
addToLayer(component, POPUP_LAYER)
|
||||
revalidate()
|
||||
|
||||
@@ -8,12 +8,10 @@ import com.intellij.terminal.TerminalTitle
|
||||
import com.intellij.terminal.session.TerminalSession
|
||||
import com.intellij.terminal.ui.TerminalWidget
|
||||
import com.intellij.terminal.ui.TtyConnectorAccessor
|
||||
import com.intellij.util.ui.components.BorderLayoutPanel
|
||||
import com.jediterm.core.util.TermSize
|
||||
import com.jediterm.terminal.TtyConnector
|
||||
import org.jetbrains.annotations.Nls
|
||||
import org.jetbrains.plugins.terminal.JBTerminalSystemSettingsProvider
|
||||
import org.jetbrains.plugins.terminal.block.TerminalContentView
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import javax.swing.JComponent
|
||||
|
||||
@@ -23,9 +21,7 @@ internal class ReworkedTerminalWidget(
|
||||
parentDisposable: Disposable,
|
||||
) : TerminalWidget {
|
||||
private val sessionFuture = CompletableFuture<TerminalSession>()
|
||||
private val view: TerminalContentView = ReworkedTerminalView(project, settings, sessionFuture)
|
||||
|
||||
private val panel: BorderLayoutPanel = BorderLayoutPanel()
|
||||
private val view = ReworkedTerminalView(project, settings, sessionFuture)
|
||||
|
||||
override val terminalTitle: TerminalTitle = TerminalTitle()
|
||||
|
||||
@@ -40,8 +36,6 @@ internal class ReworkedTerminalWidget(
|
||||
init {
|
||||
Disposer.register(parentDisposable, this)
|
||||
Disposer.register(this, view)
|
||||
|
||||
panel.addToCenter(view.component)
|
||||
}
|
||||
|
||||
override fun connectToSession(session: TerminalSession) {
|
||||
@@ -53,7 +47,7 @@ internal class ReworkedTerminalWidget(
|
||||
}
|
||||
|
||||
override fun getComponent(): JComponent {
|
||||
return panel
|
||||
return view.component
|
||||
}
|
||||
|
||||
override fun getPreferredFocusableComponent(): JComponent {
|
||||
@@ -81,10 +75,7 @@ internal class ReworkedTerminalWidget(
|
||||
}
|
||||
|
||||
override fun addNotification(notificationComponent: JComponent, disposable: Disposable) {
|
||||
panel.addToTop(notificationComponent)
|
||||
Disposer.register(disposable) {
|
||||
panel.remove(notificationComponent)
|
||||
}
|
||||
view.setTopComponent(notificationComponent, disposable)
|
||||
}
|
||||
|
||||
override fun writePlainMessage(message: @Nls String) {
|
||||
|
||||
Reference in New Issue
Block a user