feat: blink (#273)

This commit is contained in:
hstyi
2025-02-19 13:17:59 +08:00
committed by GitHub
parent 503cfa9a4e
commit 57547c95cb
11 changed files with 251 additions and 37 deletions

View File

@@ -400,10 +400,10 @@ class Database private constructor(private val env: Environment) : Disposable {
protected inner class CursorStylePropertyDelegate(defaultValue: CursorStyle) : protected inner class CursorStylePropertyDelegate(defaultValue: CursorStyle) :
PropertyDelegate<CursorStyle>(defaultValue) { PropertyDelegate<CursorStyle>(defaultValue) {
override fun convertValue(value: String): CursorStyle { override fun convertValue(value: String): CursorStyle {
try { return try {
return CursorStyle.valueOf(value) CursorStyle.valueOf(value)
} catch (e: Exception) { } catch (_: Exception) {
return initializer.invoke() initializer.invoke()
} }
} }
} }
@@ -458,6 +458,11 @@ class Database private constructor(private val env: Environment) : Disposable {
*/ */
var beep by BooleanPropertyDelegate(true) var beep by BooleanPropertyDelegate(true)
/**
* 光标闪烁
*/
var cursorBlink by BooleanPropertyDelegate(false)
/** /**
* 选中复制 * 选中复制
*/ */

View File

@@ -1,6 +1,7 @@
package app.termora package app.termora
import app.termora.actions.AnActionEvent import app.termora.actions.AnActionEvent
import app.termora.actions.DataProvider
import app.termora.actions.DataProviders import app.termora.actions.DataProviders
import com.formdev.flatlaf.extras.components.FlatTabbedPane import com.formdev.flatlaf.extras.components.FlatTabbedPane
import org.apache.commons.lang3.StringUtils import org.apache.commons.lang3.StringUtils
@@ -13,11 +14,13 @@ import kotlin.math.abs
class MyTabbedPane : FlatTabbedPane() { class MyTabbedPane : FlatTabbedPane() {
private val owner: Window get() = SwingUtilities.getWindowAncestor(this)
private val dragMouseAdaptor = DragMouseAdaptor() private val dragMouseAdaptor = DragMouseAdaptor()
private val terminalTabbedManager private val terminalTabbedManager
get() = AnActionEvent(this, StringUtils.EMPTY, EventObject(this)) get() = AnActionEvent(this, StringUtils.EMPTY, EventObject(this))
.getData(DataProviders.TerminalTabbedManager) .getData(DataProviders.TerminalTabbedManager)
private val owner
get() = AnActionEvent(this, StringUtils.EMPTY, EventObject(this))
.getData(DataProviders.TermoraFrame) as TermoraFrame
init { init {
initEvents() initEvents()
@@ -145,11 +148,11 @@ class MyTabbedPane : FlatTabbedPane() {
// 如果等于 null 表示在空地方释放,那么单独一个窗口 // 如果等于 null 表示在空地方释放,那么单独一个窗口
if (c == null) { if (c == null) {
val window = TermoraFrameManager.getInstance().createWindow() val window = TermoraFrameManager.getInstance().createWindow()
dragToAnotherWindow(window) dragToAnotherWindow(owner, window)
window.location = releasedPoint window.location = releasedPoint
window.isVisible = true window.isVisible = true
} else if (c != owner && c is TermoraFrame) { // 如果在某个窗口内释放,那么就移动到某个窗口内 } else if (c != owner && c is TermoraFrame) { // 如果在某个窗口内释放,那么就移动到某个窗口内
dragToAnotherWindow(c) dragToAnotherWindow(owner, c)
} else { } else {
val tab = this.terminalTab val tab = this.terminalTab
val terminalTabbedManager = terminalTabbedManager val terminalTabbedManager = terminalTabbedManager
@@ -224,20 +227,29 @@ class MyTabbedPane : FlatTabbedPane() {
} }
private fun dragToAnotherWindow(frame: TermoraFrame) { private fun dragToAnotherWindow(oldFrame: TermoraFrame, frame: TermoraFrame) {
val tab = this.terminalTab ?: return val tab = this.terminalTab ?: return
val terminalPanel = (tab as DataProvider?)?.getData(DataProviders.TerminalPanel) ?: return
val tabbedManager = frame.getData(DataProviders.TerminalTabbed) ?: return val tabbedManager = frame.getData(DataProviders.TerminalTabbed) ?: return
val tabbedPane = frame.getData(DataProviders.TabbedPane) ?: return val tabbedPane = frame.getData(DataProviders.TabbedPane) ?: return
val windowScope = frame.getData(DataProviders.WindowScope) ?: return
val oldWindowScope = oldFrame.getData(DataProviders.WindowScope) ?: return
val location = Point(MouseInfo.getPointerInfo().location) val location = Point(MouseInfo.getPointerInfo().location)
SwingUtilities.convertPointFromScreen(location, tabbedPane) SwingUtilities.convertPointFromScreen(location, tabbedPane)
val index = tabbedPane.indexAtLocation(location.x, location.y) val index = tabbedPane.indexAtLocation(location.x, location.y)
moveTab( moveTab(
tabbedManager, tabbedManager,
tab, tab,
index index
) )
TerminalPanelFactory.getInstance(oldWindowScope).removeTerminalPanel(terminalPanel)
TerminalPanelFactory.getInstance(windowScope).addTerminalPanel(terminalPanel)
if (frame.hasFocus()) { if (frame.hasFocus()) {
return return
} }

View File

@@ -305,6 +305,7 @@ class SettingsOptionsPane : OptionsPane() {
private val cursorStyleComboBox = FlatComboBox<CursorStyle>() private val cursorStyleComboBox = FlatComboBox<CursorStyle>()
private val debugComboBox = YesOrNoComboBox() private val debugComboBox = YesOrNoComboBox()
private val beepComboBox = YesOrNoComboBox() private val beepComboBox = YesOrNoComboBox()
private val cursorBlinkComboBox = YesOrNoComboBox()
private val fontComboBox = FlatComboBox<String>() private val fontComboBox = FlatComboBox<String>()
private val shellComboBox = FlatComboBox<String>() private val shellComboBox = FlatComboBox<String>()
private val maxRowsTextField = IntSpinner(0, 0) private val maxRowsTextField = IntSpinner(0, 0)
@@ -390,6 +391,12 @@ class SettingsOptionsPane : OptionsPane() {
} }
} }
cursorBlinkComboBox.addItemListener { e ->
if (e.stateChange == ItemEvent.SELECTED) {
terminalSetting.cursorBlink = cursorBlinkComboBox.selectedItem as Boolean
}
}
shellComboBox.addItemListener { shellComboBox.addItemListener {
if (it.stateChange == ItemEvent.SELECTED) { if (it.stateChange == ItemEvent.SELECTED) {
@@ -478,6 +485,7 @@ class SettingsOptionsPane : OptionsPane() {
fontComboBox.selectedItem = terminalSetting.font fontComboBox.selectedItem = terminalSetting.font
debugComboBox.selectedItem = terminalSetting.debug debugComboBox.selectedItem = terminalSetting.debug
beepComboBox.selectedItem = terminalSetting.beep beepComboBox.selectedItem = terminalSetting.beep
cursorBlinkComboBox.selectedItem = terminalSetting.cursorBlink
cursorStyleComboBox.selectedItem = terminalSetting.cursor cursorStyleComboBox.selectedItem = terminalSetting.cursor
selectCopyComboBox.selectedItem = terminalSetting.selectCopy selectCopyComboBox.selectedItem = terminalSetting.selectCopy
autoCloseTabComboBox.selectedItem = terminalSetting.autoCloseTabWhenDisconnected autoCloseTabComboBox.selectedItem = terminalSetting.autoCloseTabWhenDisconnected
@@ -499,7 +507,7 @@ class SettingsOptionsPane : OptionsPane() {
private fun getCenterComponent(): JComponent { private fun getCenterComponent(): JComponent {
val layout = FormLayout( val layout = FormLayout(
"left:pref, $formMargin, default:grow, $formMargin, left:pref, $formMargin, pref, default:grow", "left:pref, $formMargin, default:grow, $formMargin, left:pref, $formMargin, pref, default:grow",
"pref, $formMargin, pref, $formMargin, pref, $formMargin, pref, $formMargin, pref, $formMargin, pref, $formMargin, pref, $formMargin, pref, $formMargin, pref" "pref, $formMargin, pref, $formMargin, pref, $formMargin, pref, $formMargin, pref, $formMargin, pref, $formMargin, pref, $formMargin, pref, $formMargin, pref, $formMargin, pref"
) )
val beepBtn = JButton(Icons.run) val beepBtn = JButton(Icons.run)
@@ -526,6 +534,8 @@ class SettingsOptionsPane : OptionsPane() {
.add(selectCopyComboBox).xy(3, rows).apply { rows += step } .add(selectCopyComboBox).xy(3, rows).apply { rows += step }
.add("${I18n.getString("termora.settings.terminal.cursor-style")}:").xy(1, rows) .add("${I18n.getString("termora.settings.terminal.cursor-style")}:").xy(1, rows)
.add(cursorStyleComboBox).xy(3, rows).apply { rows += step } .add(cursorStyleComboBox).xy(3, rows).apply { rows += step }
.add("${I18n.getString("termora.settings.terminal.cursor-blink")}:").xy(1, rows)
.add(cursorBlinkComboBox).xy(3, rows).apply { rows += step }
.add("${I18n.getString("termora.settings.terminal.floating-toolbar")}:").xy(1, rows) .add("${I18n.getString("termora.settings.terminal.floating-toolbar")}:").xy(1, rows)
.add(floatingToolbarComboBox).xy(3, rows).apply { rows += step } .add(floatingToolbarComboBox).xy(3, rows).apply { rows += step }
.add("${I18n.getString("termora.settings.terminal.auto-close-tab")}:").xy(1, rows) .add("${I18n.getString("termora.settings.terminal.auto-close-tab")}:").xy(1, rows)

View File

@@ -1,50 +1,67 @@
package app.termora package app.termora
import app.termora.highlight.KeywordHighlightPaintListener import app.termora.highlight.KeywordHighlightPaintListener
import app.termora.terminal.DataKey
import app.termora.terminal.PtyConnector import app.termora.terminal.PtyConnector
import app.termora.terminal.Terminal import app.termora.terminal.Terminal
import app.termora.terminal.panel.TerminalHyperlinkPaintListener import app.termora.terminal.panel.TerminalHyperlinkPaintListener
import app.termora.terminal.panel.TerminalPanel import app.termora.terminal.panel.TerminalPanel
import kotlinx.coroutines.*
import java.awt.event.ComponentEvent import java.awt.event.ComponentEvent
import java.awt.event.ComponentListener import java.awt.event.ComponentListener
import javax.swing.SwingUtilities import javax.swing.SwingUtilities
import kotlin.time.Duration.Companion.milliseconds
class TerminalPanelFactory { class TerminalPanelFactory : Disposable {
private val terminalPanels = mutableListOf<TerminalPanel>() private val terminalPanels = mutableListOf<TerminalPanel>()
companion object { companion object {
private val Factory = DataKey(TerminalPanelFactory::class)
fun getInstance(scope: Scope): TerminalPanelFactory { fun getInstance(scope: Scope): TerminalPanelFactory {
return scope.getOrCreate(TerminalPanelFactory::class) { TerminalPanelFactory() } return scope.getOrCreate(TerminalPanelFactory::class) { TerminalPanelFactory() }
} }
fun getAllTerminalPanel(): List<TerminalPanel> { fun getAllTerminalPanel(): Array<TerminalPanel> {
return ApplicationScope.forApplicationScope().windowScopes() return ApplicationScope.forApplicationScope().windowScopes()
.map { getInstance(it) } .map { getInstance(it) }
.flatMap { it.getTerminalPanels() } .flatMap { it.terminalPanels }.toTypedArray()
} }
} }
init {
// repaint
Painter.getInstance()
}
fun createTerminalPanel(terminal: Terminal, ptyConnector: PtyConnector): TerminalPanel { fun createTerminalPanel(terminal: Terminal, ptyConnector: PtyConnector): TerminalPanel {
val terminalPanel = TerminalPanel(terminal, ptyConnector) val terminalPanel = TerminalPanel(terminal, ptyConnector)
terminalPanel.addTerminalPaintListener(MultipleTerminalListener()) terminalPanel.addTerminalPaintListener(MultipleTerminalListener())
terminalPanel.addTerminalPaintListener(KeywordHighlightPaintListener.getInstance()) terminalPanel.addTerminalPaintListener(KeywordHighlightPaintListener.getInstance())
terminalPanel.addTerminalPaintListener(TerminalHyperlinkPaintListener.getInstance()) terminalPanel.addTerminalPaintListener(TerminalHyperlinkPaintListener.getInstance())
terminal.getTerminalModel().setData(Factory, this)
Disposer.register(terminalPanel, object : Disposable { Disposer.register(terminalPanel, object : Disposable {
override fun dispose() { override fun dispose() {
terminalPanels.remove(terminalPanel) if (terminal.getTerminalModel().hasData(Factory)) {
terminal.getTerminalModel().getData(Factory).removeTerminalPanel(terminalPanel)
}
} }
}) })
terminalPanels.add(terminalPanel)
addTerminalPanel(terminalPanel)
return terminalPanel return terminalPanel
} }
fun getTerminalPanels(): List<TerminalPanel> { fun getTerminalPanels(): Array<TerminalPanel> {
return terminalPanels return terminalPanels.toTypedArray()
} }
fun repaintAll() { fun repaintAll() {
if (SwingUtilities.isEventDispatchThread()) { if (SwingUtilities.isEventDispatchThread()) {
terminalPanels.forEach { it.repaintImmediate() } getTerminalPanels().forEach { it.repaintImmediate() }
} else { } else {
SwingUtilities.invokeLater { repaintAll() } SwingUtilities.invokeLater { repaintAll() }
} }
@@ -62,4 +79,35 @@ class TerminalPanelFactory {
terminalPanels.remove(terminalPanel) terminalPanels.remove(terminalPanel)
} }
fun addTerminalPanel(terminalPanel: TerminalPanel) {
terminalPanels.add(terminalPanel)
terminalPanel.terminal.getTerminalModel().setData(Factory, this)
}
private class Painter : Disposable {
companion object {
fun getInstance(): Painter {
return ApplicationScope.forApplicationScope().getOrCreate(Painter::class) { Painter() }
}
}
private val coroutineScope = CoroutineScope(Dispatchers.IO)
init {
coroutineScope.launch {
while (coroutineScope.isActive) {
delay(500.milliseconds)
SwingUtilities.invokeLater {
ApplicationScope.forApplicationScope().windowScopes()
.map { getInstance(it) }.forEach { it.repaintAll() }
}
}
}
}
override fun dispose() {
coroutineScope.cancel()
}
}
} }

View File

@@ -45,7 +45,9 @@ class TermoraFrameManager {
frames.remove(window) frames.remove(window)
// dispose windowScope // dispose windowScope
Disposer.dispose(ApplicationScope.forWindowScope(e.window)) val windowScope = ApplicationScope.forWindowScope(e.window)
Disposer.disposeChildren(windowScope, null)
Disposer.dispose(windowScope)
val windowScopes = ApplicationScope.windowScopes() val windowScopes = ApplicationScope.windowScopes()

View File

@@ -0,0 +1,119 @@
package app.termora.terminal.panel
import app.termora.ApplicationScope
import app.termora.Database
import app.termora.Disposable
import app.termora.terminal.*
import kotlinx.coroutines.*
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.time.Duration.Companion.milliseconds
class TerminalBlink(terminal: Terminal) : Disposable {
private var cursorBlinkJob: Job? = null
private val terminalSettings get() = Database.getDatabase().terminal
private val isDisposed = AtomicBoolean(false)
private val globalBlink get() = GlobalBlink.getInstance()
private val coroutineScope get() = globalBlink.coroutineScope
/**
* 返回 true 表示可以显示某些内容 [TextStyle.blink]
*/
val blink get() = globalBlink.blink
/**
* 这个与 [blink] 不同的是它是控制光标的
*/
@Volatile
var cursorBlink = true
private set
init {
reset()
// 如果有写入,那么显示光标 N 秒
terminal.getTerminalModel().addDataListener(object : DataListener {
override fun onChanged(key: DataKey<*>, data: Any) {
// 写入后,重置光标
if (key == VisualTerminal.Written) {
reset()
} else if (key == TerminalPanel.Focused) {
// 获取焦点的一瞬间则立即重置
if (data == true) {
reset()
}
}
}
})
}
private fun reset() {
if (isDisposed.get()) {
return
}
cursorBlink = true
cursorBlinkJob?.cancel()
cursorBlinkJob = coroutineScope.launch {
while (coroutineScope.isActive) {
delay(500.milliseconds)
if (isDisposed.get()) {
break
}
// 如果开启了光标闪烁才闪速
cursorBlink = if (terminalSettings.cursorBlink) {
!cursorBlink
} else {
true
}
}
}
}
override fun dispose() {
if (isDisposed.compareAndSet(false, true)) {
cursorBlinkJob?.cancel()
}
}
private class GlobalBlink : Disposable {
companion object {
fun getInstance(): GlobalBlink {
return ApplicationScope.forApplicationScope()
.getOrCreate(GlobalBlink::class) { GlobalBlink() }
}
}
val coroutineScope by lazy { CoroutineScope(Dispatchers.IO) }
/**
* 返回 true 表示可以显示某些内容 [TextStyle.blink]
*/
@Volatile
var blink = true
private set
init {
coroutineScope.launch {
while (coroutineScope.isActive) {
delay(500)
blink = !blink
}
}
}
override fun dispose() {
coroutineScope.cancel()
}
}
}

View File

@@ -17,6 +17,7 @@ import kotlin.time.Duration
class TerminalDisplay( class TerminalDisplay(
private val terminalPanel: TerminalPanel, private val terminalPanel: TerminalPanel,
private val terminal: Terminal, private val terminal: Terminal,
private val terminalBlink: TerminalBlink
) : JComponent() { ) : JComponent() {
companion object { companion object {
@@ -136,12 +137,13 @@ class TerminalDisplay(
val lineHeight = getLineHeight() val lineHeight = getLineHeight()
val style = if (inputMethodData.isNoTyping) val style = if (inputMethodData.isNoTyping)
terminal.getTerminalModel().getData(DataKey.CursorStyle) else CursorStyle.Bar terminal.getTerminalModel().getData(DataKey.CursorStyle) else CursorStyle.Bar
val hasFocus = terminal.getTerminalModel().getData(TerminalPanel.Focused, false)
// background // background
g.color = Color(colorPalette.getColor(TerminalColor.Cursor.BACKGROUND)) g.color = Color(colorPalette.getColor(TerminalColor.Cursor.BACKGROUND))
if (style == CursorStyle.Block) { if (style == CursorStyle.Block) {
if (terminalPanel.hasFocus()) { if (hasFocus) {
g.fillRect(xOffset, (y - 1) * lineHeight, width, lineHeight) g.fillRect(xOffset, (y - 1) * lineHeight, width, lineHeight)
} else { } else {
g.drawRect(xOffset, (y - 1) * lineHeight, width, lineHeight) g.drawRect(xOffset, (y - 1) * lineHeight, width, lineHeight)
@@ -217,19 +219,23 @@ class TerminalDisplay(
} }
private fun drawCharacters(g: Graphics2D) { private fun drawCharacters(g: Graphics2D) {
val reverseVideo = terminal.getTerminalModel().getData(DataKey.ReverseVideo, false) val terminalModel = terminal.getTerminalModel()
val rows = terminal.getTerminalModel().getRows() val reverseVideo = terminalModel.getData(DataKey.ReverseVideo, false)
val cols = terminal.getTerminalModel().getCols() val rows = terminalModel.getRows()
val cols = terminalModel.getCols()
val triple = Triple(Char.Space.toString(), TextStyle.Default, 1) val triple = Triple(Char.Space.toString(), TextStyle.Default, 1)
val cursorPosition = terminal.getCursorModel().getPosition() val cursorPosition = terminal.getCursorModel().getPosition()
val averageCharWidth = getAverageCharWidth() val averageCharWidth = getAverageCharWidth()
val maxVerticalScrollOffset = terminal.getScrollingModel().getMaxVerticalScrollOffset() val maxVerticalScrollOffset = terminal.getScrollingModel().getMaxVerticalScrollOffset()
val verticalScrollOffset = terminal.getScrollingModel().getVerticalScrollOffset() val verticalScrollOffset = terminal.getScrollingModel().getVerticalScrollOffset()
val selectionModel = terminal.getSelectionModel() val selectionModel = terminal.getSelectionModel()
val cursorStyle = terminal.getTerminalModel().getData(DataKey.CursorStyle) val cursorStyle = terminalModel.getData(DataKey.CursorStyle)
val showCursor = terminal.getTerminalModel().getData(DataKey.ShowCursor) val showCursor = terminalModel.getData(DataKey.ShowCursor)
val markupModel = terminal.getMarkupModel() val markupModel = terminal.getMarkupModel()
val lineHeight = getLineHeight() val lineHeight = getLineHeight()
val blink = terminalBlink.blink
val cursorBlink = terminalBlink.cursorBlink
val hasFocus = terminalModel.getData(TerminalPanel.Focused, false)
for (i in 1..rows) { for (i in 1..rows) {
@@ -269,6 +275,13 @@ class TerminalDisplay(
background = colorPalette.getColor(TerminalColor.Basic.SELECTION_BACKGROUND) background = colorPalette.getColor(TerminalColor.Basic.SELECTION_BACKGROUND)
} }
// 如果启用了闪烁
if (textStyle.blink) {
if (!blink) {
continue
}
}
// 设置字体 // 设置字体
g.font = getDisplayFont(text, textStyle) g.font = getDisplayFont(text, textStyle)
val charWidth = min( val charWidth = min(
@@ -310,14 +323,17 @@ class TerminalDisplay(
// 渲染光标 // 渲染光标
if (caret) { if (caret) {
// 这几种情况光标才会渲染:输入中、闪烁中、没有焦点
if (inputMethodData.isTyping || cursorBlink || !hasFocus) {
drawCursor(g, i, xOffset, charWidth) drawCursor(g, i, xOffset, charWidth)
// 如果是获取焦点状态,那么颜色互换 // 如果是获取焦点状态,那么颜色互换
if (terminalPanel.hasFocus() && cursorStyle == CursorStyle.Block && inputMethodData.isNoTyping) { if (hasFocus && cursorStyle == CursorStyle.Block && inputMethodData.isNoTyping) {
g.color = Color(colorPalette.getColor(TerminalColor.Basic.BACKGROUND)) g.color = Color(colorPalette.getColor(TerminalColor.Basic.BACKGROUND))
} else { } else {
g.color = Color(foreground) g.color = Color(foreground)
} }
} }
}
// 渲染文本 // 渲染文本
g.drawString(text, xOffset, i * lineHeight - g.fontMetrics.descent) g.drawString(text, xOffset, i * lineHeight - g.fontMetrics.descent)

View File

@@ -37,12 +37,14 @@ class TerminalPanel(val terminal: Terminal, private val ptyConnector: PtyConnect
companion object { companion object {
val Debug = DataKey(Boolean::class) val Debug = DataKey(Boolean::class)
val Finding = DataKey(Boolean::class) val Finding = DataKey(Boolean::class)
val Focused = DataKey(Boolean::class)
val SelectCopy = DataKey(Boolean::class) val SelectCopy = DataKey(Boolean::class)
} }
private val terminalBlink = TerminalBlink(terminal)
private val terminalFindPanel = TerminalFindPanel(this, terminal) private val terminalFindPanel = TerminalFindPanel(this, terminal)
private val floatingToolbar = FloatingToolbarPanel() private val floatingToolbar = FloatingToolbarPanel()
private val terminalDisplay = TerminalDisplay(this, terminal) private val terminalDisplay = TerminalDisplay(this, terminal, terminalBlink)
private val dataProviderSupport = DataProviderSupport() private val dataProviderSupport = DataProviderSupport()
val scrollBar = TerminalScrollBar(this@TerminalPanel, terminalFindPanel, terminal) val scrollBar = TerminalScrollBar(this@TerminalPanel, terminalFindPanel, terminal)
@@ -140,10 +142,12 @@ class TerminalPanel(val terminal: Terminal, private val ptyConnector: PtyConnect
this.addFocusListener(object : FocusAdapter() { this.addFocusListener(object : FocusAdapter() {
override fun focusLost(e: FocusEvent) { override fun focusLost(e: FocusEvent) {
terminal.getTerminalModel().setData(Focused, false)
repaintImmediate() repaintImmediate()
} }
override fun focusGained(e: FocusEvent) { override fun focusGained(e: FocusEvent) {
terminal.getTerminalModel().setData(Focused, true)
repaintImmediate() repaintImmediate()
} }
}) })
@@ -386,6 +390,7 @@ class TerminalPanel(val terminal: Terminal, private val ptyConnector: PtyConnect
} }
override fun dispose() { override fun dispose() {
Disposer.dispose(terminalBlink)
Disposer.dispose(floatingToolbar) Disposer.dispose(floatingToolbar)
} }

View File

@@ -69,6 +69,7 @@ termora.settings.terminal.debug=Debug mode
termora.settings.terminal.beep=Beep termora.settings.terminal.beep=Beep
termora.settings.terminal.select-copy=Select copy termora.settings.terminal.select-copy=Select copy
termora.settings.terminal.cursor-style=Cursor type termora.settings.terminal.cursor-style=Cursor type
termora.settings.terminal.cursor-blink=Cursor blink
termora.settings.terminal.local-shell=Local shell termora.settings.terminal.local-shell=Local shell
termora.settings.terminal.floating-toolbar=Floating Toolbar termora.settings.terminal.floating-toolbar=Floating Toolbar
termora.settings.terminal.auto-close-tab=Auto Close Tab termora.settings.terminal.auto-close-tab=Auto Close Tab
@@ -123,8 +124,6 @@ termora.find-everywhere.groups.opened-hosts=Opened hosts
termora.find-everywhere.groups.tools=Tools termora.find-everywhere.groups.tools=Tools
termora.find-everywhere.groups.settings=${termora.setting} termora.find-everywhere.groups.settings=${termora.setting}
termora.find-everywhere.quick-command.local-terminal=Local Terminal termora.find-everywhere.quick-command.local-terminal=Local Terminal
termora.find-everywhere.double-shift-deprecated=The double-click Shift shortcut will be removed in a future version
termora.find-everywhere.double-shift-deprecated-instead=${termora.find-everywhere.double-shift-deprecated}, use {0} instead
# Welcome # Welcome
termora.welcome.my-hosts=My hosts termora.welcome.my-hosts=My hosts

View File

@@ -65,8 +65,6 @@ termora.find-everywhere.groups.opened-hosts=已打开的主机
termora.find-everywhere.groups.tools=工具 termora.find-everywhere.groups.tools=工具
termora.find-everywhere.groups.settings=${termora.setting} termora.find-everywhere.groups.settings=${termora.setting}
termora.find-everywhere.quick-command.local-terminal=本地终端 termora.find-everywhere.quick-command.local-terminal=本地终端
termora.find-everywhere.double-shift-deprecated=双击 Shift 快捷键将会在未来的版本中移除
termora.find-everywhere.double-shift-deprecated-instead=${termora.find-everywhere.double-shift-deprecated},请使用 {0} 代替
termora.settings.terminal=终端 termora.settings.terminal=终端
termora.settings.terminal.font=字体 termora.settings.terminal.font=字体
@@ -76,6 +74,7 @@ termora.settings.terminal.debug=调试模式
termora.settings.terminal.beep=蜂鸣声 termora.settings.terminal.beep=蜂鸣声
termora.settings.terminal.select-copy=选中复制 termora.settings.terminal.select-copy=选中复制
termora.settings.terminal.cursor-style=光标样式 termora.settings.terminal.cursor-style=光标样式
termora.settings.terminal.cursor-blink=光标闪烁
termora.settings.terminal.local-shell=本地终端 termora.settings.terminal.local-shell=本地终端
termora.settings.terminal.floating-toolbar=悬浮工具栏 termora.settings.terminal.floating-toolbar=悬浮工具栏
termora.settings.terminal.auto-close-tab=自动关闭标签 termora.settings.terminal.auto-close-tab=自动关闭标签

View File

@@ -74,8 +74,6 @@ termora.find-everywhere.groups.opened-hosts=已開啟的主機
termora.find-everywhere.groups.tools=工具 termora.find-everywhere.groups.tools=工具
termora.find-everywhere.groups.settings=${termora.setting} termora.find-everywhere.groups.settings=${termora.setting}
termora.find-everywhere.quick-command.local-terminal=本地端 termora.find-everywhere.quick-command.local-terminal=本地端
termora.find-everywhere.double-shift-deprecated=雙擊 Shift 快捷鍵將會在未來的版本中移除
termora.find-everywhere.double-shift-deprecated-instead=${termora.find-everywhere.double-shift-deprecated},請使用 {0} 代替
termora.settings.terminal=終端 termora.settings.terminal=終端
termora.settings.terminal.font=字體 termora.settings.terminal.font=字體
@@ -85,6 +83,7 @@ termora.settings.terminal.debug=偵錯模式
termora.settings.terminal.beep=蜂鳴聲 termora.settings.terminal.beep=蜂鳴聲
termora.settings.terminal.select-copy=選取複製 termora.settings.terminal.select-copy=選取複製
termora.settings.terminal.cursor-style=遊標風格 termora.settings.terminal.cursor-style=遊標風格
termora.settings.terminal.cursor-blink=遊標閃爍
termora.settings.terminal.local-shell=本地端 termora.settings.terminal.local-shell=本地端
termora.settings.terminal.floating-toolbar=懸浮工具列 termora.settings.terminal.floating-toolbar=懸浮工具列
termora.settings.terminal.auto-close-tab=自動關閉標籤 termora.settings.terminal.auto-close-tab=自動關閉標籤