mirror of
https://github.com/TermoraDev/termora.git
synced 2026-01-16 02:12:58 +08:00
chore: improve badge
This commit is contained in:
@@ -1,18 +0,0 @@
|
||||
package app.termora
|
||||
|
||||
import java.awt.Graphics2D
|
||||
import javax.swing.JComponent
|
||||
|
||||
class BadgeGlassPaneExtension private constructor() : GlassPaneExtension {
|
||||
companion object {
|
||||
val instance = BadgeGlassPaneExtension()
|
||||
}
|
||||
|
||||
override fun paint(c: JComponent, g2d: Graphics2D): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun ordered(): Long {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
@@ -9,11 +9,7 @@ import javax.swing.JComponent
|
||||
*/
|
||||
interface GlassPaneExtension : Extension {
|
||||
|
||||
/**
|
||||
* 渲染背景,如果返回 true 会立即退出。(当有多个扩展的时候,只会执行一个)
|
||||
*
|
||||
* @return true:渲染了背景,false:没有渲染背景
|
||||
*/
|
||||
fun paint(c: JComponent, g2d: Graphics2D): Boolean
|
||||
|
||||
fun paint(scope: WindowScope, c: JComponent, g2d: Graphics2D)
|
||||
|
||||
}
|
||||
@@ -43,5 +43,7 @@ fun Graphics2D.restore() {
|
||||
|
||||
fun setupAntialiasing(graphics: Graphics2D) {
|
||||
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
|
||||
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON)
|
||||
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY)
|
||||
}
|
||||
|
||||
|
||||
@@ -253,7 +253,7 @@ class TermoraFrame : JFrame(), DataProvider {
|
||||
}
|
||||
|
||||
|
||||
private class GlassPane : JComponent() {
|
||||
private inner class GlassPane : JComponent() {
|
||||
|
||||
init {
|
||||
isFocusable = false
|
||||
@@ -266,9 +266,8 @@ class TermoraFrame : JFrame(), DataProvider {
|
||||
if (extensions.isNotEmpty()) {
|
||||
for (extension in extensions) {
|
||||
g2d.save()
|
||||
val painted = extension.paint(this, g2d)
|
||||
extension.paint(windowScope, this, g2d)
|
||||
g2d.restore()
|
||||
if (painted) break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
41
src/main/kotlin/app/termora/plugin/internal/badge/Badge.kt
Normal file
41
src/main/kotlin/app/termora/plugin/internal/badge/Badge.kt
Normal file
@@ -0,0 +1,41 @@
|
||||
package app.termora.plugin.internal.badge
|
||||
|
||||
import app.termora.WindowScope
|
||||
import java.awt.Color
|
||||
import java.util.*
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.UIManager
|
||||
|
||||
class Badge private constructor() {
|
||||
companion object {
|
||||
fun getInstance(scope: WindowScope): Badge {
|
||||
return scope.getOrCreate(Badge::class) { Badge() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private val map = WeakHashMap<JComponent, BadgePresentation>()
|
||||
|
||||
fun addBadge(component: JComponent): BadgePresentation {
|
||||
val presentation = object : BadgePresentation {
|
||||
override var visible: Boolean = true
|
||||
override var color: Color = UIManager.getColor("Component.error.focusedBorderColor")
|
||||
|
||||
override fun dispose() {
|
||||
removeBadge(component)
|
||||
}
|
||||
}
|
||||
map[component] = presentation
|
||||
return presentation
|
||||
}
|
||||
|
||||
fun removeBadge(component: JComponent) {
|
||||
map.remove(component)
|
||||
}
|
||||
|
||||
fun getBadges(): Map<JComponent, BadgePresentation> {
|
||||
return map.toMap()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package app.termora.plugin.internal.badge
|
||||
|
||||
import app.termora.GlassPaneExtension
|
||||
import app.termora.WindowScope
|
||||
import app.termora.setupAntialiasing
|
||||
import java.awt.Graphics2D
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.SwingUtilities
|
||||
|
||||
class BadgeGlassPaneExtension private constructor() : GlassPaneExtension {
|
||||
companion object {
|
||||
val instance = BadgeGlassPaneExtension()
|
||||
}
|
||||
|
||||
override fun paint(scope: WindowScope, c: JComponent, g2d: Graphics2D) {
|
||||
val badges = Badge.getInstance(scope).getBadges()
|
||||
if (badges.isEmpty()) return
|
||||
|
||||
setupAntialiasing(g2d)
|
||||
|
||||
for ((comp, presentation) in badges) {
|
||||
if (comp.isShowing.not()) continue
|
||||
if (presentation.visible.not()) continue
|
||||
paintBadge(c, comp, g2d, presentation)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun paintBadge(root: JComponent, c: JComponent, g2d: Graphics2D, presentation: BadgePresentation) {
|
||||
val point = c.locationOnScreen
|
||||
SwingUtilities.convertPointFromScreen(point, root)
|
||||
val size = 6
|
||||
g2d.color = presentation.color
|
||||
g2d.fillRoundRect(c.width - size - 4 + point.x, point.y + 4, size, size, size, size)
|
||||
}
|
||||
|
||||
|
||||
override fun ordered(): Long {
|
||||
return Long.MAX_VALUE
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package app.termora.plugin.internal.badge
|
||||
|
||||
import app.termora.BadgeGlassPaneExtension
|
||||
import app.termora.GlassPaneExtension
|
||||
import app.termora.plugin.Extension
|
||||
import app.termora.plugin.InternalPlugin
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package app.termora.plugin.internal.badge
|
||||
|
||||
import app.termora.Disposable
|
||||
import java.awt.Color
|
||||
|
||||
interface BadgePresentation : Disposable {
|
||||
|
||||
/**
|
||||
* 是否显示
|
||||
*/
|
||||
var visible: Boolean
|
||||
|
||||
/**
|
||||
* 颜色
|
||||
*/
|
||||
var color: Color
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import app.termora.*
|
||||
import app.termora.actions.AnAction
|
||||
import app.termora.actions.AnActionEvent
|
||||
import app.termora.actions.DataProviders
|
||||
import app.termora.plugin.internal.badge.Badge
|
||||
import app.termora.plugin.internal.ssh.SSHTerminalTab
|
||||
import app.termora.plugin.internal.ssh.SSHTerminalTab.Companion.SSHSession
|
||||
import app.termora.terminal.DataKey
|
||||
@@ -61,8 +62,9 @@ class TransferVisualWindow(tab: SSHTerminalTab, visualWindowManager: VisualWindo
|
||||
private val disposable = Disposer.newDisposable()
|
||||
private val owner get() = SwingUtilities.getWindowAncestor(this)
|
||||
private val questionBtn = JButton(Icons.questionMark)
|
||||
private val badgeIcon = BadgeIcon(Icons.download)
|
||||
private val downloadBtn = JButton(badgeIcon)
|
||||
private val downloadBtn = JButton(Icons.download)
|
||||
private val badgePresentation = Badge.getInstance(tab.windowScope)
|
||||
.addBadge(downloadBtn).apply { visible = false }
|
||||
|
||||
|
||||
init {
|
||||
@@ -86,6 +88,7 @@ class TransferVisualWindow(tab: SSHTerminalTab, visualWindowManager: VisualWindo
|
||||
Disposer.register(tab, this)
|
||||
Disposer.register(this, disposable)
|
||||
Disposer.register(disposable, transferManager)
|
||||
Disposer.register(disposable, badgePresentation)
|
||||
|
||||
connectingPanel.busyLabel.isBusy = true
|
||||
|
||||
@@ -115,10 +118,10 @@ class TransferVisualWindow(tab: SSHTerminalTab, visualWindowManager: VisualWindo
|
||||
|
||||
transferManager.addTransferListener(object : TransferListener {
|
||||
override fun onTransferCountChanged() {
|
||||
val oldVisible = badgeIcon.visible
|
||||
val oldVisible = badgePresentation.visible
|
||||
val newVisible = transferManager.getTransferCount() > 0
|
||||
if (oldVisible != newVisible) {
|
||||
badgeIcon.visible = newVisible
|
||||
badgePresentation.visible = newVisible
|
||||
downloadBtn.repaint()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user