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:
@@ -3,7 +3,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
project.version = "0.0.3"
|
project.version = "0.0.4"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package app.termora.plugins.bg
|
package app.termora.plugins.bg
|
||||||
|
|
||||||
import app.termora.GlassPaneExtension
|
import app.termora.GlassPaneExtension
|
||||||
|
import app.termora.WindowScope
|
||||||
import com.formdev.flatlaf.FlatLaf
|
import com.formdev.flatlaf.FlatLaf
|
||||||
import java.awt.AlphaComposite
|
import java.awt.AlphaComposite
|
||||||
import java.awt.Graphics2D
|
import java.awt.Graphics2D
|
||||||
@@ -11,12 +12,9 @@ class BGGlassPaneExtension private constructor() : GlassPaneExtension {
|
|||||||
val instance = BGGlassPaneExtension()
|
val instance = BGGlassPaneExtension()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun paint(
|
override fun paint(scope: WindowScope, c: JComponent, g2d: Graphics2D) {
|
||||||
c: JComponent,
|
|
||||||
g2d: Graphics2D
|
|
||||||
): Boolean {
|
|
||||||
|
|
||||||
val img = BackgroundManager.getInstance().getBackgroundImage() ?: return false
|
val img = BackgroundManager.getInstance().getBackgroundImage() ?: return
|
||||||
g2d.composite = AlphaComposite.getInstance(
|
g2d.composite = AlphaComposite.getInstance(
|
||||||
AlphaComposite.SRC_OVER,
|
AlphaComposite.SRC_OVER,
|
||||||
if (FlatLaf.isLafDark()) 0.2f else 0.1f
|
if (FlatLaf.isLafDark()) 0.2f else 0.1f
|
||||||
@@ -24,6 +22,5 @@ class BGGlassPaneExtension private constructor() : GlassPaneExtension {
|
|||||||
g2d.drawImage(img, 0, 0, c.width, c.height, null)
|
g2d.drawImage(img, 0, 0, c.width, c.height, null)
|
||||||
g2d.composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER)
|
g2d.composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER)
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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 {
|
interface GlassPaneExtension : Extension {
|
||||||
|
|
||||||
/**
|
|
||||||
* 渲染背景,如果返回 true 会立即退出。(当有多个扩展的时候,只会执行一个)
|
fun paint(scope: WindowScope, c: JComponent, g2d: Graphics2D)
|
||||||
*
|
|
||||||
* @return true:渲染了背景,false:没有渲染背景
|
|
||||||
*/
|
|
||||||
fun paint(c: JComponent, g2d: Graphics2D): Boolean
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -43,5 +43,7 @@ fun Graphics2D.restore() {
|
|||||||
|
|
||||||
fun setupAntialiasing(graphics: Graphics2D) {
|
fun setupAntialiasing(graphics: Graphics2D) {
|
||||||
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
|
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 {
|
init {
|
||||||
isFocusable = false
|
isFocusable = false
|
||||||
@@ -266,9 +266,8 @@ class TermoraFrame : JFrame(), DataProvider {
|
|||||||
if (extensions.isNotEmpty()) {
|
if (extensions.isNotEmpty()) {
|
||||||
for (extension in extensions) {
|
for (extension in extensions) {
|
||||||
g2d.save()
|
g2d.save()
|
||||||
val painted = extension.paint(this, g2d)
|
extension.paint(windowScope, this, g2d)
|
||||||
g2d.restore()
|
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
|
package app.termora.plugin.internal.badge
|
||||||
|
|
||||||
import app.termora.BadgeGlassPaneExtension
|
|
||||||
import app.termora.GlassPaneExtension
|
import app.termora.GlassPaneExtension
|
||||||
import app.termora.plugin.Extension
|
import app.termora.plugin.Extension
|
||||||
import app.termora.plugin.InternalPlugin
|
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.AnAction
|
||||||
import app.termora.actions.AnActionEvent
|
import app.termora.actions.AnActionEvent
|
||||||
import app.termora.actions.DataProviders
|
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
|
||||||
import app.termora.plugin.internal.ssh.SSHTerminalTab.Companion.SSHSession
|
import app.termora.plugin.internal.ssh.SSHTerminalTab.Companion.SSHSession
|
||||||
import app.termora.terminal.DataKey
|
import app.termora.terminal.DataKey
|
||||||
@@ -61,8 +62,9 @@ class TransferVisualWindow(tab: SSHTerminalTab, visualWindowManager: VisualWindo
|
|||||||
private val disposable = Disposer.newDisposable()
|
private val disposable = Disposer.newDisposable()
|
||||||
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 badgeIcon = BadgeIcon(Icons.download)
|
private val downloadBtn = JButton(Icons.download)
|
||||||
private val downloadBtn = JButton(badgeIcon)
|
private val badgePresentation = Badge.getInstance(tab.windowScope)
|
||||||
|
.addBadge(downloadBtn).apply { visible = false }
|
||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -86,6 +88,7 @@ class TransferVisualWindow(tab: SSHTerminalTab, visualWindowManager: VisualWindo
|
|||||||
Disposer.register(tab, this)
|
Disposer.register(tab, this)
|
||||||
Disposer.register(this, disposable)
|
Disposer.register(this, disposable)
|
||||||
Disposer.register(disposable, transferManager)
|
Disposer.register(disposable, transferManager)
|
||||||
|
Disposer.register(disposable, badgePresentation)
|
||||||
|
|
||||||
connectingPanel.busyLabel.isBusy = true
|
connectingPanel.busyLabel.isBusy = true
|
||||||
|
|
||||||
@@ -115,10 +118,10 @@ class TransferVisualWindow(tab: SSHTerminalTab, visualWindowManager: VisualWindo
|
|||||||
|
|
||||||
transferManager.addTransferListener(object : TransferListener {
|
transferManager.addTransferListener(object : TransferListener {
|
||||||
override fun onTransferCountChanged() {
|
override fun onTransferCountChanged() {
|
||||||
val oldVisible = badgeIcon.visible
|
val oldVisible = badgePresentation.visible
|
||||||
val newVisible = transferManager.getTransferCount() > 0
|
val newVisible = transferManager.getTransferCount() > 0
|
||||||
if (oldVisible != newVisible) {
|
if (oldVisible != newVisible) {
|
||||||
badgeIcon.visible = newVisible
|
badgePresentation.visible = newVisible
|
||||||
downloadBtn.repaint()
|
downloadBtn.repaint()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user