mirror of
https://github.com/TermoraDev/termora.git
synced 2026-01-15 18:02:58 +08:00
chore: improve terminal options
This commit is contained in:
@@ -4,7 +4,7 @@ plugins {
|
||||
|
||||
|
||||
|
||||
project.version = "0.0.1"
|
||||
project.version = "0.0.2"
|
||||
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package app.termora.plugins.serial
|
||||
|
||||
import app.termora.*
|
||||
import app.termora.plugin.internal.AltKeyModifier
|
||||
import app.termora.plugin.internal.BasicGeneralOption
|
||||
import app.termora.plugin.internal.BasicTerminalOption
|
||||
import com.fazecast.jSerialComm.SerialPort
|
||||
import com.formdev.flatlaf.FlatClientProperties
|
||||
import com.jgoodies.forms.builder.FormBuilder
|
||||
@@ -15,12 +17,15 @@ import java.awt.BorderLayout
|
||||
import java.awt.Component
|
||||
import java.awt.event.ComponentAdapter
|
||||
import java.awt.event.ComponentEvent
|
||||
import java.nio.charset.Charset
|
||||
import javax.swing.*
|
||||
|
||||
class SerialHostOptionsPane : OptionsPane() {
|
||||
private val generalOption = BasicGeneralOption()
|
||||
private val terminalOption = TerminalOption()
|
||||
private val terminalOption = BasicTerminalOption().apply {
|
||||
showCharsetComboBox = true
|
||||
showStartupCommandTextField = true
|
||||
init()
|
||||
}
|
||||
private val serialCommOption = SerialCommOption()
|
||||
|
||||
init {
|
||||
@@ -48,6 +53,10 @@ class SerialHostOptionsPane : OptionsPane() {
|
||||
encoding = terminalOption.charsetComboBox.selectedItem as String,
|
||||
startupCommand = terminalOption.startupCommandTextField.text,
|
||||
serialComm = serialComm,
|
||||
extras = mutableMapOf(
|
||||
"altModifier" to (terminalOption.altModifierComboBox.selectedItem?.toString()
|
||||
?: AltKeyModifier.EightBit.name),
|
||||
)
|
||||
)
|
||||
|
||||
return Host(
|
||||
@@ -128,67 +137,6 @@ class SerialHostOptionsPane : OptionsPane() {
|
||||
}
|
||||
|
||||
|
||||
protected inner class TerminalOption : JPanel(BorderLayout()), Option {
|
||||
val charsetComboBox = JComboBox<String>()
|
||||
val startupCommandTextField = OutlineTextField()
|
||||
|
||||
|
||||
init {
|
||||
initView()
|
||||
initEvents()
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
add(getCenterComponent(), BorderLayout.CENTER)
|
||||
|
||||
|
||||
for (e in Charset.availableCharsets()) {
|
||||
charsetComboBox.addItem(e.key)
|
||||
}
|
||||
|
||||
charsetComboBox.selectedItem = "UTF-8"
|
||||
|
||||
}
|
||||
|
||||
private fun initEvents() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
override fun getIcon(isSelected: Boolean): Icon {
|
||||
return Icons.terminal
|
||||
}
|
||||
|
||||
override fun getTitle(): String {
|
||||
return I18n.getString("termora.new-host.terminal")
|
||||
}
|
||||
|
||||
override fun getJComponent(): JComponent {
|
||||
return this
|
||||
}
|
||||
|
||||
private fun getCenterComponent(): JComponent {
|
||||
val layout = FormLayout(
|
||||
"left:pref, $FORM_MARGIN, default:grow",
|
||||
"pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref"
|
||||
)
|
||||
|
||||
var rows = 1
|
||||
val step = 2
|
||||
val panel = FormBuilder.create().layout(layout)
|
||||
.add("${I18n.getString("termora.new-host.terminal.encoding")}:").xy(1, rows)
|
||||
.add(charsetComboBox).xy(3, rows).apply { rows += step }
|
||||
.add("${I18n.getString("termora.new-host.terminal.startup-commands")}:").xy(1, rows)
|
||||
.add(startupCommandTextField).xy(3, rows).apply { rows += step }
|
||||
.apply { rows += step }
|
||||
.build()
|
||||
|
||||
|
||||
return panel
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected inner class SerialCommOption : JPanel(BorderLayout()), Option {
|
||||
val serialPortComboBox = OutlineComboBox<String>()
|
||||
val baudRateComboBox = OutlineComboBox<Int>()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package app.termora
|
||||
|
||||
import app.termora.actions.DataProviders
|
||||
import app.termora.plugin.internal.AltKeyModifier
|
||||
import app.termora.terminal.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.swing.Swing
|
||||
@@ -46,6 +47,9 @@ abstract class PtyHostTerminalTab(
|
||||
// 开启 reader
|
||||
startPtyConnectorReader()
|
||||
|
||||
// 修饰
|
||||
terminalKeyModifiers()
|
||||
|
||||
// 启动命令
|
||||
if (host.options.startupCommand.isNotBlank()) {
|
||||
coroutineScope.launch(Dispatchers.IO) {
|
||||
@@ -155,6 +159,15 @@ abstract class PtyHostTerminalTab(
|
||||
ptyConnector.write(bytes)
|
||||
}
|
||||
|
||||
open fun terminalKeyModifiers() {
|
||||
val altModifier = host.options.extras["altModifier"]
|
||||
if (altModifier == AltKeyModifier.CharactersPrecededByESC.name) {
|
||||
terminalModel.setData(DataKey.AltModifier, AltKeyModifier.CharactersPrecededByESC)
|
||||
} else {
|
||||
terminalModel.setData(DataKey.AltModifier, AltKeyModifier.EightBit)
|
||||
}
|
||||
}
|
||||
|
||||
override fun canReconnect(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package app.termora.plugin.internal
|
||||
|
||||
enum class AltKeyModifier {
|
||||
EightBit,
|
||||
CharactersPrecededByESC,
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
package app.termora.plugin.internal
|
||||
|
||||
import app.termora.*
|
||||
import app.termora.OptionsPane.Companion.FORM_MARGIN
|
||||
import app.termora.OptionsPane.Option
|
||||
import app.termora.plugin.internal.telnet.TelnetHostOptionsPane.Backspace
|
||||
import com.formdev.flatlaf.extras.components.FlatTabbedPane
|
||||
import com.formdev.flatlaf.ui.FlatTextBorder
|
||||
import com.jgoodies.forms.builder.FormBuilder
|
||||
import com.jgoodies.forms.layout.FormLayout
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Component
|
||||
import java.awt.KeyboardFocusManager
|
||||
import java.nio.charset.Charset
|
||||
import javax.swing.*
|
||||
|
||||
class BasicTerminalOption() : JPanel(BorderLayout()), Option {
|
||||
|
||||
var showCharsetComboBox: Boolean = false
|
||||
var showStartupCommandTextField: Boolean = false
|
||||
var showHeartbeatIntervalTextField: Boolean = false
|
||||
var showEnvironmentTextArea: Boolean = false
|
||||
var showLoginScripts: Boolean = false
|
||||
var showBackspaceComboBox: Boolean = false
|
||||
var showCharacterAtATimeTextField: Boolean = false
|
||||
var showAltModifierComboBox: Boolean = true
|
||||
|
||||
val charsetComboBox = JComboBox<String>()
|
||||
val startupCommandTextField = OutlineTextField()
|
||||
val heartbeatIntervalTextField = IntSpinner(30, minimum = 3, maximum = Int.MAX_VALUE)
|
||||
val environmentTextArea = FixedLengthTextArea(2048)
|
||||
val loginScripts = mutableListOf<LoginScript>()
|
||||
val backspaceComboBox = JComboBox<Backspace>()
|
||||
val altModifierComboBox = JComboBox<AltKeyModifier>()
|
||||
val characterAtATimeTextField = YesOrNoComboBox()
|
||||
|
||||
|
||||
private val loginScriptPanel = LoginScriptPanel(loginScripts)
|
||||
private val tabbed = FlatTabbedPane()
|
||||
|
||||
fun init() {
|
||||
initView()
|
||||
initEvents()
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
|
||||
if (showLoginScripts) {
|
||||
tabbed.styleMap = mapOf(
|
||||
"focusColor" to DynamicColor("TabbedPane.background"),
|
||||
"hoverColor" to DynamicColor("TabbedPane.background"),
|
||||
)
|
||||
tabbed.tabHeight = UIManager.getInt("TabbedPane.tabHeight") - 4
|
||||
putClientProperty("ContentPanelBorder", BorderFactory.createEmptyBorder())
|
||||
tabbed.addTab(I18n.getString("termora.new-host.general"), getCenterComponent())
|
||||
tabbed.addTab(I18n.getString("termora.new-host.terminal.login-scripts"), loginScriptPanel)
|
||||
add(tabbed, BorderLayout.CENTER)
|
||||
} else {
|
||||
add(getCenterComponent(), BorderLayout.CENTER)
|
||||
}
|
||||
|
||||
if (showAltModifierComboBox) {
|
||||
altModifierComboBox.addItem(AltKeyModifier.EightBit)
|
||||
altModifierComboBox.addItem(AltKeyModifier.CharactersPrecededByESC)
|
||||
|
||||
altModifierComboBox.renderer = object : DefaultListCellRenderer() {
|
||||
override fun getListCellRendererComponent(
|
||||
list: JList<*>?,
|
||||
value: Any?,
|
||||
index: Int,
|
||||
isSelected: Boolean,
|
||||
cellHasFocus: Boolean
|
||||
): Component? {
|
||||
var text = value?.toString() ?: value
|
||||
if (value == AltKeyModifier.CharactersPrecededByESC) {
|
||||
text = I18n.getString("termora.new-host.terminal.alt-modifier.by-esc")
|
||||
} else if (value == AltKeyModifier.EightBit) {
|
||||
text = I18n.getString("termora.new-host.terminal.alt-modifier.eight-bit")
|
||||
}
|
||||
return super.getListCellRendererComponent(list, text, index, isSelected, cellHasFocus)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (showBackspaceComboBox) {
|
||||
backspaceComboBox.addItem(Backspace.Delete)
|
||||
backspaceComboBox.addItem(Backspace.Backspace)
|
||||
backspaceComboBox.addItem(Backspace.VT220)
|
||||
}
|
||||
|
||||
if (showCharacterAtATimeTextField) {
|
||||
characterAtATimeTextField.selectedItem = false
|
||||
}
|
||||
|
||||
environmentTextArea.setFocusTraversalKeys(
|
||||
KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager()
|
||||
.getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS)
|
||||
)
|
||||
environmentTextArea.setFocusTraversalKeys(
|
||||
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager()
|
||||
.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS)
|
||||
)
|
||||
|
||||
environmentTextArea.rows = 8
|
||||
environmentTextArea.lineWrap = true
|
||||
environmentTextArea.border = BorderFactory.createEmptyBorder(4, 4, 4, 4)
|
||||
|
||||
for (e in Charset.availableCharsets()) {
|
||||
charsetComboBox.addItem(e.key)
|
||||
}
|
||||
|
||||
charsetComboBox.selectedItem = "UTF-8"
|
||||
|
||||
}
|
||||
|
||||
private fun initEvents() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
override fun getIcon(isSelected: Boolean): Icon {
|
||||
return Icons.terminal
|
||||
}
|
||||
|
||||
override fun getTitle(): String {
|
||||
return I18n.getString("termora.new-host.terminal")
|
||||
}
|
||||
|
||||
override fun getJComponent(): JComponent {
|
||||
return this
|
||||
}
|
||||
|
||||
private fun getCenterComponent(): JComponent {
|
||||
val layout = FormLayout(
|
||||
"left:pref, $FORM_MARGIN, default:grow",
|
||||
"pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref"
|
||||
)
|
||||
|
||||
var rows = 1
|
||||
val step = 2
|
||||
val builder = FormBuilder.create().layout(layout)
|
||||
if (showLoginScripts) {
|
||||
builder.border(BorderFactory.createEmptyBorder(6, 8, 6, 8))
|
||||
}
|
||||
|
||||
if (showCharsetComboBox) {
|
||||
builder.add("${I18n.getString("termora.new-host.terminal.encoding")}:").xy(1, rows)
|
||||
.add(charsetComboBox).xy(3, rows).apply { rows += step }
|
||||
}
|
||||
|
||||
if (showAltModifierComboBox) {
|
||||
builder.add("${I18n.getString("termora.new-host.terminal.alt-modifier")}:").xy(1, rows)
|
||||
.add(altModifierComboBox).xy(3, rows).apply { rows += step }
|
||||
}
|
||||
|
||||
if (showBackspaceComboBox) {
|
||||
builder.add("${I18n.getString("termora.new-host.terminal.backspace")}:").xy(1, rows)
|
||||
.add(backspaceComboBox).xy(3, rows).apply { rows += step }
|
||||
}
|
||||
|
||||
if (showCharacterAtATimeTextField) {
|
||||
builder
|
||||
.add("${I18n.getString("termora.new-host.terminal.character-mode")}:").xy(1, rows)
|
||||
.add(characterAtATimeTextField).xy(3, rows).apply { rows += step }
|
||||
}
|
||||
|
||||
if (showHeartbeatIntervalTextField) {
|
||||
builder.add("${I18n.getString("termora.new-host.terminal.heartbeat-interval")}:").xy(1, rows)
|
||||
.add(heartbeatIntervalTextField).xy(3, rows).apply { rows += step }
|
||||
}
|
||||
|
||||
if (showStartupCommandTextField) {
|
||||
builder.add("${I18n.getString("termora.new-host.terminal.startup-commands")}:").xy(1, rows)
|
||||
.add(startupCommandTextField).xy(3, rows).apply { rows += step }
|
||||
}
|
||||
|
||||
|
||||
if (showEnvironmentTextArea) {
|
||||
builder.add("${I18n.getString("termora.new-host.terminal.env")}:").xy(1, rows)
|
||||
.add(JScrollPane(environmentTextArea).apply { border = FlatTextBorder() }).xy(3, rows)
|
||||
.apply { rows += step }
|
||||
}
|
||||
|
||||
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,20 +1,25 @@
|
||||
package app.termora.plugin.internal.local
|
||||
|
||||
import app.termora.*
|
||||
import app.termora.Host
|
||||
import app.termora.Options
|
||||
import app.termora.OptionsPane
|
||||
import app.termora.SerialComm
|
||||
import app.termora.plugin.internal.AltKeyModifier
|
||||
import app.termora.plugin.internal.BasicGeneralOption
|
||||
import app.termora.plugin.internal.BasicTerminalOption
|
||||
import com.formdev.flatlaf.FlatClientProperties
|
||||
import com.formdev.flatlaf.ui.FlatTextBorder
|
||||
import com.jgoodies.forms.builder.FormBuilder
|
||||
import com.jgoodies.forms.layout.FormLayout
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.KeyboardFocusManager
|
||||
import java.awt.Window
|
||||
import java.nio.charset.Charset
|
||||
import javax.swing.*
|
||||
import javax.swing.JTextField
|
||||
import javax.swing.SwingUtilities
|
||||
|
||||
internal open class LocalHostOptionsPane : OptionsPane() {
|
||||
protected val generalOption = BasicGeneralOption()
|
||||
protected val terminalOption = TerminalOption()
|
||||
private val terminalOption = BasicTerminalOption().apply {
|
||||
showCharsetComboBox = true
|
||||
showEnvironmentTextArea = true
|
||||
showStartupCommandTextField = true
|
||||
init()
|
||||
}
|
||||
protected val owner: Window get() = SwingUtilities.getWindowAncestor(this)
|
||||
|
||||
init {
|
||||
@@ -35,6 +40,10 @@ internal open class LocalHostOptionsPane : OptionsPane() {
|
||||
env = terminalOption.environmentTextArea.text,
|
||||
startupCommand = terminalOption.startupCommandTextField.text,
|
||||
serialComm = serialComm,
|
||||
extras = mutableMapOf(
|
||||
"altModifier" to (terminalOption.altModifierComboBox.selectedItem?.toString()
|
||||
?: AltKeyModifier.EightBit.name),
|
||||
)
|
||||
)
|
||||
|
||||
return Host(
|
||||
@@ -77,83 +86,4 @@ internal open class LocalHostOptionsPane : OptionsPane() {
|
||||
textField.requestFocusInWindow()
|
||||
}
|
||||
|
||||
protected inner class TerminalOption : JPanel(BorderLayout()), Option {
|
||||
val charsetComboBox = JComboBox<String>()
|
||||
val startupCommandTextField = OutlineTextField()
|
||||
val environmentTextArea = FixedLengthTextArea(2048)
|
||||
|
||||
|
||||
init {
|
||||
initView()
|
||||
initEvents()
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
add(getCenterComponent(), BorderLayout.CENTER)
|
||||
|
||||
|
||||
environmentTextArea.setFocusTraversalKeys(
|
||||
KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager()
|
||||
.getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS)
|
||||
)
|
||||
environmentTextArea.setFocusTraversalKeys(
|
||||
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager()
|
||||
.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS)
|
||||
)
|
||||
|
||||
environmentTextArea.rows = 8
|
||||
environmentTextArea.lineWrap = true
|
||||
environmentTextArea.border = BorderFactory.createEmptyBorder(4, 4, 4, 4)
|
||||
|
||||
for (e in Charset.availableCharsets()) {
|
||||
charsetComboBox.addItem(e.key)
|
||||
}
|
||||
|
||||
charsetComboBox.selectedItem = "UTF-8"
|
||||
|
||||
}
|
||||
|
||||
private fun initEvents() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
override fun getIcon(isSelected: Boolean): Icon {
|
||||
return Icons.terminal
|
||||
}
|
||||
|
||||
override fun getTitle(): String {
|
||||
return I18n.getString("termora.new-host.terminal")
|
||||
}
|
||||
|
||||
override fun getJComponent(): JComponent {
|
||||
return this
|
||||
}
|
||||
|
||||
private fun getCenterComponent(): JComponent {
|
||||
val layout = FormLayout(
|
||||
"left:pref, $FORM_MARGIN, default:grow",
|
||||
"pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref"
|
||||
)
|
||||
|
||||
var rows = 1
|
||||
val step = 2
|
||||
val panel = FormBuilder.create().layout(layout)
|
||||
.add("${I18n.getString("termora.new-host.terminal.encoding")}:").xy(1, rows)
|
||||
.add(charsetComboBox).xy(3, rows).apply { rows += step }
|
||||
.add("${I18n.getString("termora.new-host.terminal.startup-commands")}:").xy(1, rows)
|
||||
.add(startupCommandTextField).xy(3, rows).apply { rows += step }
|
||||
.add("${I18n.getString("termora.new-host.terminal.env")}:").xy(1, rows)
|
||||
.add(JScrollPane(environmentTextArea).apply { border = FlatTextBorder() }).xy(3, rows)
|
||||
.apply { rows += step }
|
||||
.build()
|
||||
|
||||
|
||||
return panel
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -4,13 +4,14 @@ import app.termora.*
|
||||
import app.termora.account.AccountOwner
|
||||
import app.termora.keymgr.KeyManager
|
||||
import app.termora.keymgr.KeyManagerDialog
|
||||
import app.termora.plugin.internal.AltKeyModifier
|
||||
import app.termora.plugin.internal.BasicProxyOption
|
||||
import app.termora.plugin.internal.BasicTerminalOption
|
||||
import app.termora.tree.Filter
|
||||
import app.termora.tree.HostTreeNode
|
||||
import app.termora.tree.NewHostTreeDialog
|
||||
import com.formdev.flatlaf.FlatClientProperties
|
||||
import com.formdev.flatlaf.extras.components.FlatComboBox
|
||||
import com.formdev.flatlaf.extras.components.FlatTabbedPane
|
||||
import com.formdev.flatlaf.ui.FlatTextBorder
|
||||
import com.formdev.flatlaf.util.SystemInfo
|
||||
import com.jgoodies.forms.builder.FormBuilder
|
||||
@@ -21,20 +22,26 @@ import org.eclipse.jgit.internal.transport.sshd.agent.connector.UnixDomainSocket
|
||||
import org.eclipse.jgit.internal.transport.sshd.agent.connector.WinPipeConnector
|
||||
import java.awt.*
|
||||
import java.awt.event.*
|
||||
import java.nio.charset.Charset
|
||||
import javax.swing.*
|
||||
import javax.swing.table.DefaultTableCellRenderer
|
||||
import javax.swing.table.DefaultTableModel
|
||||
|
||||
@Suppress("CascadeIf")
|
||||
open class SSHHostOptionsPane(private val accountOwner: AccountOwner) : OptionsPane() {
|
||||
protected val tunnelingOption = TunnelingOption()
|
||||
protected val generalOption = GeneralOption()
|
||||
protected val proxyOption = BasicProxyOption()
|
||||
protected val terminalOption = TerminalOption()
|
||||
protected val jumpHostsOption = JumpHostsOption()
|
||||
protected val sftpOption = SFTPOption()
|
||||
protected val owner: Window get() = SwingUtilities.getWindowAncestor(this)
|
||||
internal class SSHHostOptionsPane(private val accountOwner: AccountOwner) : OptionsPane() {
|
||||
private val tunnelingOption = TunnelingOption()
|
||||
private val generalOption = GeneralOption()
|
||||
private val proxyOption = BasicProxyOption()
|
||||
private val terminalOption = BasicTerminalOption().apply {
|
||||
showCharsetComboBox = true
|
||||
showLoginScripts = true
|
||||
showEnvironmentTextArea = true
|
||||
showStartupCommandTextField = true
|
||||
showHeartbeatIntervalTextField = true
|
||||
init()
|
||||
}
|
||||
private val jumpHostsOption = JumpHostsOption()
|
||||
private val sftpOption = SFTPOption()
|
||||
private val owner: Window get() = SwingUtilities.getWindowAncestor(this)
|
||||
|
||||
init {
|
||||
addOption(generalOption)
|
||||
@@ -47,7 +54,7 @@ open class SSHHostOptionsPane(private val accountOwner: AccountOwner) : OptionsP
|
||||
}
|
||||
|
||||
|
||||
open fun getHost(): Host {
|
||||
fun getHost(): Host {
|
||||
val name = generalOption.nameTextField.text
|
||||
val protocol = SSHProtocolProvider.PROTOCOL
|
||||
val host = generalOption.hostTextField.text
|
||||
@@ -98,6 +105,10 @@ open class SSHHostOptionsPane(private val accountOwner: AccountOwner) : OptionsP
|
||||
enableX11Forwarding = tunnelingOption.x11ForwardingCheckBox.isSelected,
|
||||
x11Forwarding = tunnelingOption.x11ServerTextField.text,
|
||||
loginScripts = terminalOption.loginScripts,
|
||||
extras = mutableMapOf(
|
||||
"altModifier" to (terminalOption.altModifierComboBox.selectedItem?.toString()
|
||||
?: AltKeyModifier.EightBit.name),
|
||||
)
|
||||
)
|
||||
|
||||
return Host(
|
||||
@@ -486,102 +497,6 @@ open class SSHHostOptionsPane(private val accountOwner: AccountOwner) : OptionsP
|
||||
}
|
||||
|
||||
|
||||
protected inner class TerminalOption : JPanel(BorderLayout()), Option {
|
||||
val charsetComboBox = JComboBox<String>()
|
||||
val startupCommandTextField = OutlineTextField()
|
||||
val heartbeatIntervalTextField = IntSpinner(30, minimum = 3, maximum = Int.MAX_VALUE)
|
||||
val environmentTextArea = FixedLengthTextArea(2048)
|
||||
val loginScripts = mutableListOf<LoginScript>()
|
||||
|
||||
private val loginScriptPanel = LoginScriptPanel(loginScripts)
|
||||
private val tabbed = FlatTabbedPane()
|
||||
|
||||
init {
|
||||
initView()
|
||||
initEvents()
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
|
||||
|
||||
tabbed.styleMap = mapOf(
|
||||
"focusColor" to DynamicColor("TabbedPane.background"),
|
||||
"hoverColor" to DynamicColor("TabbedPane.background"),
|
||||
)
|
||||
tabbed.tabHeight = UIManager.getInt("TabbedPane.tabHeight") - 4
|
||||
putClientProperty("ContentPanelBorder", BorderFactory.createEmptyBorder())
|
||||
tabbed.addTab(I18n.getString("termora.new-host.general"), getCenterComponent())
|
||||
tabbed.addTab(I18n.getString("termora.new-host.terminal.login-scripts"), loginScriptPanel)
|
||||
add(tabbed, BorderLayout.CENTER)
|
||||
|
||||
|
||||
environmentTextArea.setFocusTraversalKeys(
|
||||
KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager()
|
||||
.getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS)
|
||||
)
|
||||
environmentTextArea.setFocusTraversalKeys(
|
||||
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager()
|
||||
.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS)
|
||||
)
|
||||
|
||||
environmentTextArea.rows = 8
|
||||
environmentTextArea.lineWrap = true
|
||||
environmentTextArea.border = BorderFactory.createEmptyBorder(4, 4, 4, 4)
|
||||
|
||||
for (e in Charset.availableCharsets()) {
|
||||
charsetComboBox.addItem(e.key)
|
||||
}
|
||||
|
||||
charsetComboBox.selectedItem = "UTF-8"
|
||||
|
||||
}
|
||||
|
||||
private fun initEvents() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
override fun getIcon(isSelected: Boolean): Icon {
|
||||
return Icons.terminal
|
||||
}
|
||||
|
||||
override fun getTitle(): String {
|
||||
return I18n.getString("termora.new-host.terminal")
|
||||
}
|
||||
|
||||
override fun getJComponent(): JComponent {
|
||||
return this
|
||||
}
|
||||
|
||||
private fun getCenterComponent(): JComponent {
|
||||
val layout = FormLayout(
|
||||
"left:pref, $FORM_MARGIN, default:grow",
|
||||
"pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref"
|
||||
)
|
||||
|
||||
var rows = 1
|
||||
val step = 2
|
||||
val panel = FormBuilder.create().layout(layout)
|
||||
.border(BorderFactory.createEmptyBorder(6, 8, 6, 8))
|
||||
.add("${I18n.getString("termora.new-host.terminal.encoding")}:").xy(1, rows)
|
||||
.add(charsetComboBox).xy(3, rows).apply { rows += step }
|
||||
.add("${I18n.getString("termora.new-host.terminal.heartbeat-interval")}:").xy(1, rows)
|
||||
.add(heartbeatIntervalTextField).xy(3, rows).apply { rows += step }
|
||||
.add("${I18n.getString("termora.new-host.terminal.startup-commands")}:").xy(1, rows)
|
||||
.add(startupCommandTextField).xy(3, rows).apply { rows += step }
|
||||
.add("${I18n.getString("termora.new-host.terminal.env")}:").xy(1, rows)
|
||||
.add(JScrollPane(environmentTextArea).apply { border = FlatTextBorder() }).xy(3, rows)
|
||||
.apply { rows += step }
|
||||
.build()
|
||||
|
||||
|
||||
return panel
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected inner class SFTPOption : JPanel(BorderLayout()), Option {
|
||||
val defaultDirectoryField = OutlineTextField(255)
|
||||
|
||||
|
||||
@@ -2,9 +2,10 @@ package app.termora.plugin.internal.telnet
|
||||
|
||||
import app.termora.*
|
||||
import app.termora.account.AccountOwner
|
||||
import app.termora.plugin.internal.AltKeyModifier
|
||||
import app.termora.plugin.internal.BasicProxyOption
|
||||
import app.termora.plugin.internal.BasicTerminalOption
|
||||
import com.formdev.flatlaf.FlatClientProperties
|
||||
import com.formdev.flatlaf.extras.components.FlatTabbedPane
|
||||
import com.formdev.flatlaf.ui.FlatTextBorder
|
||||
import com.jgoodies.forms.builder.FormBuilder
|
||||
import com.jgoodies.forms.layout.FormLayout
|
||||
@@ -12,7 +13,6 @@ import java.awt.BorderLayout
|
||||
import java.awt.KeyboardFocusManager
|
||||
import java.awt.event.ComponentAdapter
|
||||
import java.awt.event.ComponentEvent
|
||||
import java.nio.charset.Charset
|
||||
import javax.swing.*
|
||||
|
||||
class TelnetHostOptionsPane(private val accountOwner: AccountOwner) : OptionsPane() {
|
||||
@@ -20,7 +20,16 @@ class TelnetHostOptionsPane(private val accountOwner: AccountOwner) : OptionsPan
|
||||
|
||||
// telnet 不支持代理密码
|
||||
private val proxyOption = BasicProxyOption(authenticationTypes = listOf())
|
||||
private val terminalOption = TerminalOption()
|
||||
private val terminalOption = BasicTerminalOption().apply {
|
||||
showCharsetComboBox = true
|
||||
showBackspaceComboBox = true
|
||||
showStartupCommandTextField = true
|
||||
showCharacterAtATimeTextField = true
|
||||
showEnvironmentTextArea = true
|
||||
showLoginScripts = true
|
||||
init()
|
||||
}
|
||||
|
||||
|
||||
init {
|
||||
addOption(generalOption)
|
||||
@@ -58,7 +67,9 @@ class TelnetHostOptionsPane(private val accountOwner: AccountOwner) : OptionsPan
|
||||
serialComm = serialComm,
|
||||
extras = mutableMapOf(
|
||||
"backspace" to (terminalOption.backspaceComboBox.selectedItem as Backspace).name,
|
||||
"character-at-a-time" to (terminalOption.characterAtATimeTextField.selectedItem?.toString() ?: "false")
|
||||
"character-at-a-time" to (terminalOption.characterAtATimeTextField.selectedItem?.toString() ?: "false"),
|
||||
"altModifier" to (terminalOption.altModifierComboBox.selectedItem?.toString()
|
||||
?: AltKeyModifier.EightBit.name),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -226,108 +237,6 @@ class TelnetHostOptionsPane(private val accountOwner: AccountOwner) : OptionsPan
|
||||
}
|
||||
|
||||
|
||||
private inner class TerminalOption : JPanel(BorderLayout()), Option {
|
||||
val charsetComboBox = JComboBox<String>()
|
||||
val backspaceComboBox = JComboBox<Backspace>()
|
||||
val startupCommandTextField = OutlineTextField()
|
||||
val characterAtATimeTextField = YesOrNoComboBox()
|
||||
val environmentTextArea = FixedLengthTextArea(2048)
|
||||
val loginScripts = mutableListOf<LoginScript>()
|
||||
|
||||
private val loginScriptPanel = LoginScriptPanel(loginScripts)
|
||||
|
||||
init {
|
||||
initView()
|
||||
initEvents()
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
|
||||
backspaceComboBox.addItem(Backspace.Delete)
|
||||
backspaceComboBox.addItem(Backspace.Backspace)
|
||||
backspaceComboBox.addItem(Backspace.VT220)
|
||||
|
||||
characterAtATimeTextField.selectedItem = false
|
||||
|
||||
environmentTextArea.setFocusTraversalKeys(
|
||||
KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager()
|
||||
.getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS)
|
||||
)
|
||||
environmentTextArea.setFocusTraversalKeys(
|
||||
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager()
|
||||
.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS)
|
||||
)
|
||||
|
||||
environmentTextArea.rows = 8
|
||||
environmentTextArea.lineWrap = true
|
||||
environmentTextArea.border = BorderFactory.createEmptyBorder(4, 4, 4, 4)
|
||||
|
||||
for (e in Charset.availableCharsets()) {
|
||||
charsetComboBox.addItem(e.key)
|
||||
}
|
||||
|
||||
charsetComboBox.selectedItem = "UTF-8"
|
||||
|
||||
val tabbed = FlatTabbedPane()
|
||||
tabbed.styleMap = mapOf(
|
||||
"focusColor" to DynamicColor("TabbedPane.background"),
|
||||
"hoverColor" to DynamicColor("TabbedPane.background"),
|
||||
)
|
||||
tabbed.tabHeight = UIManager.getInt("TabbedPane.tabHeight") - 4
|
||||
putClientProperty("ContentPanelBorder", BorderFactory.createEmptyBorder())
|
||||
tabbed.addTab(I18n.getString("termora.new-host.general"), getCenterComponent())
|
||||
tabbed.addTab(I18n.getString("termora.new-host.terminal.login-scripts"), loginScriptPanel)
|
||||
add(tabbed, BorderLayout.CENTER)
|
||||
|
||||
}
|
||||
|
||||
private fun initEvents() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
override fun getIcon(isSelected: Boolean): Icon {
|
||||
return Icons.terminal
|
||||
}
|
||||
|
||||
override fun getTitle(): String {
|
||||
return I18n.getString("termora.new-host.terminal")
|
||||
}
|
||||
|
||||
override fun getJComponent(): JComponent {
|
||||
return this
|
||||
}
|
||||
|
||||
private fun getCenterComponent(): JComponent {
|
||||
val layout = FormLayout(
|
||||
"left:pref, $FORM_MARGIN, default:grow",
|
||||
"pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref"
|
||||
)
|
||||
|
||||
var rows = 1
|
||||
val step = 2
|
||||
val panel = FormBuilder.create().layout(layout)
|
||||
.border(BorderFactory.createEmptyBorder(6, 8, 6, 8))
|
||||
.add("${I18n.getString("termora.new-host.terminal.encoding")}:").xy(1, rows)
|
||||
.add(charsetComboBox).xy(3, rows).apply { rows += step }
|
||||
.add("${I18n.getString("termora.new-host.terminal.backspace")}:").xy(1, rows)
|
||||
.add(backspaceComboBox).xy(3, rows).apply { rows += step }
|
||||
.add("${I18n.getString("termora.new-host.terminal.character-mode")}:").xy(1, rows)
|
||||
.add(characterAtATimeTextField).xy(3, rows).apply { rows += step }
|
||||
.add("${I18n.getString("termora.new-host.terminal.startup-commands")}:").xy(1, rows)
|
||||
.add(startupCommandTextField).xy(3, rows).apply { rows += step }
|
||||
.add("${I18n.getString("termora.new-host.terminal.env")}:").xy(1, rows)
|
||||
.add(JScrollPane(environmentTextArea).apply { border = FlatTextBorder() }).xy(3, rows)
|
||||
.apply { rows += step }
|
||||
.build()
|
||||
|
||||
|
||||
return panel
|
||||
}
|
||||
}
|
||||
|
||||
enum class Backspace {
|
||||
/**
|
||||
* 0x08
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package app.termora.plugin.internal.wsl
|
||||
|
||||
import app.termora.*
|
||||
import app.termora.plugin.internal.AltKeyModifier
|
||||
import app.termora.plugin.internal.BasicTerminalOption
|
||||
import com.formdev.flatlaf.FlatClientProperties
|
||||
import com.formdev.flatlaf.ui.FlatTextBorder
|
||||
import com.jgoodies.forms.builder.FormBuilder
|
||||
@@ -12,12 +14,17 @@ import java.awt.KeyboardFocusManager
|
||||
import java.awt.Window
|
||||
import java.awt.event.ComponentAdapter
|
||||
import java.awt.event.ComponentEvent
|
||||
import java.nio.charset.Charset
|
||||
import javax.swing.*
|
||||
|
||||
internal open class WSLHostOptionsPane : OptionsPane() {
|
||||
protected val generalOption = GeneralOption()
|
||||
protected val terminalOption = TerminalOption()
|
||||
protected val terminalOption = BasicTerminalOption().apply {
|
||||
showCharsetComboBox = true
|
||||
showStartupCommandTextField = true
|
||||
showEnvironmentTextArea = true
|
||||
init()
|
||||
}
|
||||
|
||||
protected val owner: Window get() = SwingUtilities.getWindowAncestor(this)
|
||||
|
||||
init {
|
||||
@@ -36,7 +43,11 @@ internal open class WSLHostOptionsPane : OptionsPane() {
|
||||
encoding = terminalOption.charsetComboBox.selectedItem as String,
|
||||
env = terminalOption.environmentTextArea.text,
|
||||
startupCommand = terminalOption.startupCommandTextField.text,
|
||||
extras = mutableMapOf("wsl-guid" to wsl.guid, "wsl-flavor" to wsl.flavor)
|
||||
extras = mutableMapOf(
|
||||
"wsl-guid" to wsl.guid, "wsl-flavor" to wsl.flavor,
|
||||
"altModifier" to (terminalOption.altModifierComboBox.selectedItem?.toString()
|
||||
?: AltKeyModifier.EightBit.name),
|
||||
)
|
||||
)
|
||||
|
||||
return Host(
|
||||
@@ -216,85 +227,5 @@ internal open class WSLHostOptionsPane : OptionsPane() {
|
||||
|
||||
}
|
||||
|
||||
protected inner class TerminalOption : JPanel(BorderLayout()), Option {
|
||||
val charsetComboBox = JComboBox<String>()
|
||||
val startupCommandTextField = OutlineTextField()
|
||||
val environmentTextArea = FixedLengthTextArea(2048)
|
||||
|
||||
|
||||
init {
|
||||
initView()
|
||||
initEvents()
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
add(getCenterComponent(), BorderLayout.CENTER)
|
||||
|
||||
startupCommandTextField.placeholderText = "--cd ~"
|
||||
|
||||
|
||||
environmentTextArea.setFocusTraversalKeys(
|
||||
KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager()
|
||||
.getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS)
|
||||
)
|
||||
environmentTextArea.setFocusTraversalKeys(
|
||||
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager()
|
||||
.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS)
|
||||
)
|
||||
|
||||
environmentTextArea.rows = 8
|
||||
environmentTextArea.lineWrap = true
|
||||
environmentTextArea.border = BorderFactory.createEmptyBorder(4, 4, 4, 4)
|
||||
|
||||
for (e in Charset.availableCharsets()) {
|
||||
charsetComboBox.addItem(e.key)
|
||||
}
|
||||
|
||||
charsetComboBox.selectedItem = "UTF-8"
|
||||
|
||||
}
|
||||
|
||||
private fun initEvents() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
override fun getIcon(isSelected: Boolean): Icon {
|
||||
return Icons.terminal
|
||||
}
|
||||
|
||||
override fun getTitle(): String {
|
||||
return I18n.getString("termora.new-host.terminal")
|
||||
}
|
||||
|
||||
override fun getJComponent(): JComponent {
|
||||
return this
|
||||
}
|
||||
|
||||
private fun getCenterComponent(): JComponent {
|
||||
val layout = FormLayout(
|
||||
"left:pref, $FORM_MARGIN, default:grow",
|
||||
"pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref"
|
||||
)
|
||||
|
||||
var rows = 1
|
||||
val step = 2
|
||||
val panel = FormBuilder.create().layout(layout)
|
||||
.add("${I18n.getString("termora.new-host.terminal.encoding")}:").xy(1, rows)
|
||||
.add(charsetComboBox).xy(3, rows).apply { rows += step }
|
||||
.add("${I18n.getString("termora.new-host.terminal.startup-commands")}:").xy(1, rows)
|
||||
.add(startupCommandTextField).xy(3, rows).apply { rows += step }
|
||||
.add("${I18n.getString("termora.new-host.terminal.env")}:").xy(1, rows)
|
||||
.add(JScrollPane(environmentTextArea).apply { border = FlatTextBorder() }).xy(3, rows)
|
||||
.apply { rows += step }
|
||||
.build()
|
||||
|
||||
|
||||
return panel
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package app.termora.terminal
|
||||
|
||||
import app.termora.plugin.internal.AltKeyModifier
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
|
||||
@@ -192,6 +193,11 @@ class DataKey<T : Any>(val clazz: KClass<T>) {
|
||||
* TerminalWriter
|
||||
*/
|
||||
val TerminalWriter = DataKey(app.termora.terminal.panel.TerminalWriter::class)
|
||||
|
||||
/**
|
||||
* [app.termora.plugin.internal.AltKeyModifier]
|
||||
*/
|
||||
val AltModifier = DataKey(AltKeyModifier::class)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,9 @@ package app.termora.terminal.panel
|
||||
|
||||
import app.termora.keymap.KeyShortcut
|
||||
import app.termora.keymap.KeymapManager
|
||||
import app.termora.plugin.internal.AltKeyModifier
|
||||
import app.termora.terminal.ControlCharacters
|
||||
import app.termora.terminal.DataKey
|
||||
import app.termora.terminal.Terminal
|
||||
import com.formdev.flatlaf.util.SystemInfo
|
||||
import org.slf4j.LoggerFactory
|
||||
@@ -89,8 +91,10 @@ class TerminalPanelKeyAdapter(
|
||||
return
|
||||
}
|
||||
|
||||
// https://github.com/TermoraDev/termora/issues/865
|
||||
val modifier = terminal.getTerminalModel().getData(DataKey.AltModifier, AltKeyModifier.EightBit)
|
||||
// https://github.com/TermoraDev/termora/issues/331
|
||||
if (isAltPressedOnly(e) && Character.isDefined(e.keyChar)) {
|
||||
if (isAltPressedOnly(e) && Character.isDefined(e.keyChar) && modifier == AltKeyModifier.CharactersPrecededByESC) {
|
||||
val c = String(charArrayOf(ASCII_ESC, simpleMapKeyCodeToChar(e)))
|
||||
writer.write(TerminalWriter.WriteRequest.fromBytes(c.toByteArray(writer.getCharset())))
|
||||
// scroll to bottom
|
||||
|
||||
@@ -186,6 +186,9 @@ termora.new-host.terminal.backspace=Backspace
|
||||
termora.new-host.terminal.character-mode=Character-at-a-time
|
||||
termora.new-host.terminal.heartbeat-interval=Heartbeat Interval
|
||||
termora.new-host.terminal.startup-commands=Startup Command
|
||||
termora.new-host.terminal.alt-modifier=Alt modifier
|
||||
termora.new-host.terminal.alt-modifier.eight-bit=8-bit characters
|
||||
termora.new-host.terminal.alt-modifier.by-esc=Characters preceded by ESC
|
||||
termora.new-host.terminal.env=Environment
|
||||
termora.new-host.terminal.login-scripts=Login Scripts
|
||||
termora.new-host.terminal.expect=Expect
|
||||
|
||||
@@ -178,6 +178,9 @@ termora.new-host.terminal.backspace=退格键
|
||||
termora.new-host.terminal.character-mode=单字符模式
|
||||
termora.new-host.terminal.heartbeat-interval=心跳间隔
|
||||
termora.new-host.terminal.startup-commands=启动命令
|
||||
termora.new-host.terminal.alt-modifier=Alt 键修饰
|
||||
termora.new-host.terminal.alt-modifier.eight-bit=8 位字符
|
||||
termora.new-host.terminal.alt-modifier.by-esc=ESC 键作为前缀
|
||||
termora.new-host.terminal.env=环境
|
||||
termora.new-host.terminal.login-scripts=登录脚本
|
||||
termora.new-host.terminal.expect=预期
|
||||
|
||||
@@ -175,6 +175,9 @@ termora.new-host.terminal.encoding=編碼
|
||||
termora.new-host.terminal.backspace=退格鍵
|
||||
termora.new-host.terminal.character-mode=單字元模式
|
||||
termora.new-host.terminal.startup-commands=啟動命令
|
||||
termora.new-host.terminal.alt-modifier=Alt 鍵修飾
|
||||
termora.new-host.terminal.alt-modifier.eight-bit=8 位元字符
|
||||
termora.new-host.terminal.alt-modifier.by-esc=ESC 鍵作為前綴
|
||||
termora.new-host.terminal.heartbeat-interval=心跳間隔
|
||||
termora.new-host.terminal.env=環境
|
||||
termora.new-host.terminal.login-scripts=登入腳本
|
||||
|
||||
Reference in New Issue
Block a user