fix: virtual window auto hiding

This commit is contained in:
hstyi
2025-09-08 11:00:17 +08:00
committed by hstyi
parent 30e245f7a3
commit 2fc381caa5
2 changed files with 51 additions and 5 deletions

View File

@@ -30,6 +30,8 @@ import java.nio.file.Path
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
import java.util.concurrent.Executors import java.util.concurrent.Executors
import javax.swing.* import javax.swing.*
import javax.swing.event.PopupMenuEvent
import javax.swing.event.PopupMenuListener
import kotlin.io.path.absolutePathString import kotlin.io.path.absolutePathString
import kotlin.math.max import kotlin.math.max
import kotlin.reflect.cast import kotlin.reflect.cast
@@ -58,12 +60,24 @@ internal class TransferVisualWindow(tab: SSHTerminalTab, visualWindowManager: Vi
private val connectFailedPanel = ConnectFailedPanel() private val connectFailedPanel = ConnectFailedPanel()
private val transferManager = TransferTableModel(coroutineScope) private val transferManager = TransferTableModel(coroutineScope)
private val disposable = Disposer.newDisposable() private val disposable = Disposer.newDisposable()
private val focusedWindow get() = KeyboardFocusManager.getCurrentKeyboardFocusManager().focusedWindow
private val owner get() = SwingUtilities.getWindowAncestor(this) private val owner get() = SwingUtilities.getWindowAncestor(this)
private val questionBtn = JButton(Icons.questionMark) private val questionBtn = JButton(Icons.questionMark)
private val downloadBtn = JButton(Icons.download) private val downloadBtn = JButton(Icons.download)
private val badgePresentation = Badge.getInstance(tab.windowScope) private val badgePresentation = Badge.getInstance(tab.windowScope)
.addBadge(downloadBtn).apply { visible = false } .addBadge(downloadBtn).apply { visible = false }
private val support = DataProviderSupport() private val support = DataProviderSupport()
private var isShowPopupMenu = false
override var isStickHover: Boolean
get() = super.isStickHover
set(value) {
if (isShowPopupMenu || owner != focusedWindow) {
super.isStickHover = true
} else {
super.isStickHover = value
}
}
init { init {
initViews() initViews()
@@ -135,6 +149,8 @@ internal class TransferVisualWindow(tab: SSHTerminalTab, visualWindowManager: Vi
} }
}) })
questionBtn.toolTipText = I18n.getString("termora.visual-window.transport.question")
// 立即连接 // 立即连接
connect() connect()
} }
@@ -151,7 +167,7 @@ internal class TransferVisualWindow(tab: SSHTerminalTab, visualWindowManager: Vi
val support = DefaultTransportSupport(fileSystem, fileSystem.defaultDir) val support = DefaultTransportSupport(fileSystem, fileSystem.defaultDir)
withContext(Dispatchers.Swing) { withContext(Dispatchers.Swing) {
val internalTransferManager = MyInternalTransferManager() val internalTransferManager = MyInternalTransferManager()
val transportPanel = TransportPanel( val transportPanel = object : TransportPanel(
internalTransferManager, tab.host, internalTransferManager, tab.host,
object : TransportSupportLoader { object : TransportSupportLoader {
override suspend fun getTransportSupport(): TransportSupport { override suspend fun getTransportSupport(): TransportSupport {
@@ -165,7 +181,27 @@ internal class TransferVisualWindow(tab: SSHTerminalTab, visualWindowManager: Vi
override fun isLoaded(): Boolean { override fun isLoaded(): Boolean {
return true return true
} }
}) {
override fun customizeContextmenu(
rows: Array<Int>,
e: MouseEvent,
popupMenu: TransportPopupMenu
) {
popupMenu.addPopupMenuListener(object : PopupMenuListener {
override fun popupMenuWillBecomeVisible(e: PopupMenuEvent?) {
isShowPopupMenu = true
}
override fun popupMenuWillBecomeInvisible(e: PopupMenuEvent?) {
isShowPopupMenu = false
}
override fun popupMenuCanceled(e: PopupMenuEvent?) {
isShowPopupMenu = false
}
}) })
}
}
internalTransferManager.setTransferPanel(transportPanel) internalTransferManager.setTransferPanel(transportPanel)
Disposer.register(transportPanel, object : Disposable { Disposer.register(transportPanel, object : Disposable {
override fun dispose() { override fun dispose() {
@@ -240,6 +276,10 @@ internal class TransferVisualWindow(tab: SSHTerminalTab, visualWindowManager: Vi
super.dispose() super.dispose()
} }
override fun reassemble() {
super.reassemble()
}
override fun <T : Any> getData(dataKey: DataKey<T>): T? { override fun <T : Any> getData(dataKey: DataKey<T>): T? {
return support.getData(dataKey) return support.getData(dataKey)
} }

View File

@@ -36,6 +36,7 @@ open class VisualWindowPanel(protected val id: String, protected val visualWindo
private var dialog: VisualWindowDialog? = null private var dialog: VisualWindowDialog? = null
private var oldBounds = Rectangle() private var oldBounds = Rectangle()
private var toggleWindowBtn = JButton(Icons.openInNewWindow) private var toggleWindowBtn = JButton(Icons.openInNewWindow)
private val closeBtn = JButton(Icons.close)
private var isAlwaysTop private var isAlwaysTop
get() = properties.getString("VisualWindow.${id}.dialog.isAlwaysTop", "false").toBoolean() get() = properties.getString("VisualWindow.${id}.dialog.isAlwaysTop", "false").toBoolean()
set(value) = properties.putString("VisualWindow.${id}.dialog.isAlwaysTop", value.toString()) set(value) = properties.putString("VisualWindow.${id}.dialog.isAlwaysTop", value.toString())
@@ -47,8 +48,8 @@ open class VisualWindowPanel(protected val id: String, protected val visualWindo
} }
} }
protected var isStickHover = false protected open var isStickHover = false
private set(value) { set(value) {
if (value == field) return if (value == field) return
field = value field = value
reassemble() reassemble()
@@ -92,6 +93,8 @@ open class VisualWindowPanel(protected val id: String, protected val visualWindo
oldBounds = bounds oldBounds = bounds
alwaysTopBtn.isSelected = isAlwaysTop alwaysTopBtn.isSelected = isAlwaysTop
alwaysTopBtn.isVisible = false alwaysTopBtn.isVisible = false
closeBtn.toolTipText = I18n.getString("termora.tabbed.contextmenu.close")
} }
protected open fun toolbarButtons(): List<Pair<JButton, Position>> { protected open fun toolbarButtons(): List<Pair<JButton, Position>> {
@@ -134,6 +137,7 @@ open class VisualWindowPanel(protected val id: String, protected val visualWindo
addMouseListener(object : MouseAdapter() {}) addMouseListener(object : MouseAdapter() {})
toggleWindowBtn.addActionListener { toggleWindow() } toggleWindowBtn.addActionListener { toggleWindow() }
toggleWindowBtn.toolTipText = I18n.getString("termora.visual-window.toggle-window")
addPropertyChangeListener("isWindow") { addPropertyChangeListener("isWindow") {
if (isWindow) { if (isWindow) {
@@ -165,6 +169,8 @@ open class VisualWindowPanel(protected val id: String, protected val visualWindo
dialog?.isAlwaysOnTop = isAlwaysTop dialog?.isAlwaysOnTop = isAlwaysTop
} }
} }
closeBtn.addActionListener { if (beforeClose()) Disposer.dispose(visualWindow) }
} }
private fun initToolBar() { private fun initToolBar() {
@@ -180,7 +186,7 @@ open class VisualWindowPanel(protected val id: String, protected val visualWindo
buttons.filter { it.second == Position.Right }.forEach { toolbar.add(it.first) } buttons.filter { it.second == Position.Right }.forEach { toolbar.add(it.first) }
toolbar.add(toggleWindowBtn) toolbar.add(toggleWindowBtn)
toolbar.add(JButton(Icons.close).apply { addActionListener { if (beforeClose()) Disposer.dispose(visualWindow) } }) toolbar.add(closeBtn)
toolbar.border = BorderFactory.createMatteBorder(0, 0, 1, 0, DynamicColor.BorderColor) toolbar.border = BorderFactory.createMatteBorder(0, 0, 1, 0, DynamicColor.BorderColor)
add(toolbar, BorderLayout.NORTH) add(toolbar, BorderLayout.NORTH)
} }