From 79ed6d3858c6f3edd7da0f8fa2bd2c1c2f1c4749 Mon Sep 17 00:00:00 2001 From: hstyi Date: Fri, 1 Aug 2025 15:43:06 +0800 Subject: [PATCH] feat: support right click copy and paste --- .../kotlin/app/termora/SettingsOptionsPane.kt | 33 ++++++++++++++++++- .../app/termora/database/DatabaseManager.kt | 5 +++ .../TerminalPanelMouseSelectionAdapter.kt | 18 +++++++++- src/main/resources/i18n/messages.properties | 3 ++ .../resources/i18n/messages_ru_RU.properties | 2 ++ .../resources/i18n/messages_zh_CN.properties | 2 ++ .../resources/i18n/messages_zh_TW.properties | 4 ++- 7 files changed, 64 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/app/termora/SettingsOptionsPane.kt b/src/main/kotlin/app/termora/SettingsOptionsPane.kt index df00efa..e46f1f2 100644 --- a/src/main/kotlin/app/termora/SettingsOptionsPane.kt +++ b/src/main/kotlin/app/termora/SettingsOptionsPane.kt @@ -404,6 +404,7 @@ class SettingsOptionsPane : OptionsPane() { private val fontSizeTextField = IntSpinner(0, 9, 99) private val terminalSetting get() = DatabaseManager.getInstance().terminal private val selectCopyComboBox = YesOrNoComboBox() + private val rightClickComboBox = OutlineComboBox() private val autoCloseTabComboBox = YesOrNoComboBox() private val floatingToolbarComboBox = YesOrNoComboBox() private val hyperlinkComboBox = YesOrNoComboBox() @@ -417,6 +418,12 @@ class SettingsOptionsPane : OptionsPane() { } } + rightClickComboBox.addItemListener { + if (it.stateChange == ItemEvent.SELECTED) { + terminalSetting.rightClick = rightClickComboBox.selectedItem as String + } + } + fallbackFontComboBox.addItemListener { if (it.stateChange == ItemEvent.SELECTED) { terminalSetting.fallbackFont = fallbackFontComboBox.selectedItem as String @@ -518,6 +525,10 @@ class SettingsOptionsPane : OptionsPane() { fontSizeTextField.value = terminalSetting.fontSize maxRowsTextField.value = terminalSetting.maxRows + rightClickComboBox.addItem("Copy") + rightClickComboBox.addItem("CopyAndPaste") + + rightClickComboBox.selectedItem = terminalSetting.rightClick cursorStyleComboBox.renderer = object : DefaultListCellRenderer() { override fun getListCellRendererComponent( @@ -532,6 +543,24 @@ class SettingsOptionsPane : OptionsPane() { } } + rightClickComboBox.renderer = object : DefaultListCellRenderer() { + override fun getListCellRendererComponent( + list: JList<*>?, + value: Any?, + index: Int, + isSelected: Boolean, + cellHasFocus: Boolean + ): Component { + var text = value?.toString() + if (value == "Copy") { + text = I18n.getString("termora.settings.terminal.right-click.copy") + } else if (value == "CopyAndPaste") { + text = I18n.getString("termora.settings.terminal.right-click.copy-and-paste") + } + return super.getListCellRendererComponent(list, text, index, isSelected, cellHasFocus) + } + } + cursorStyleComboBox.addItem(CursorStyle.Block) cursorStyleComboBox.addItem(CursorStyle.Bar) cursorStyleComboBox.addItem(CursorStyle.Underline) @@ -595,7 +624,7 @@ class SettingsOptionsPane : OptionsPane() { private fun getCenterComponent(): JComponent { val layout = FormLayout( "left:pref, $FORM_MARGIN, default:grow, $FORM_MARGIN, left:pref, $FORM_MARGIN, pref, default:grow", - "pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref" + "pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref, $FORM_MARGIN, pref" ) val beepBtn = JButton(Icons.run) @@ -624,6 +653,8 @@ class SettingsOptionsPane : OptionsPane() { .add(hyperlinkComboBox).xy(3, rows).apply { rows += step } .add("${I18n.getString("termora.settings.terminal.select-copy")}:").xy(1, rows) .add(selectCopyComboBox).xy(3, rows).apply { rows += step } + .add("${I18n.getString("termora.settings.terminal.right-click")}:").xy(1, rows) + .add(rightClickComboBox).xy(3, rows).apply { rows += step } .add("${I18n.getString("termora.settings.terminal.cursor-style")}:").xy(1, rows) .add(cursorStyleComboBox).xy(3, rows).apply { rows += step } .add("${I18n.getString("termora.settings.terminal.cursor-blink")}:").xy(1, rows) diff --git a/src/main/kotlin/app/termora/database/DatabaseManager.kt b/src/main/kotlin/app/termora/database/DatabaseManager.kt index e4091a4..201d869 100644 --- a/src/main/kotlin/app/termora/database/DatabaseManager.kt +++ b/src/main/kotlin/app/termora/database/DatabaseManager.kt @@ -666,6 +666,11 @@ class DatabaseManager private constructor() : Disposable { */ var selectCopy by BooleanPropertyDelegate(false) + /** + * 右键点击:Copy、CopyAndPaste + */ + var rightClick by StringPropertyDelegate("Copy") + /** * 光标样式 */ diff --git a/src/main/kotlin/app/termora/terminal/panel/TerminalPanelMouseSelectionAdapter.kt b/src/main/kotlin/app/termora/terminal/panel/TerminalPanelMouseSelectionAdapter.kt index 369d18e..f454ddb 100644 --- a/src/main/kotlin/app/termora/terminal/panel/TerminalPanelMouseSelectionAdapter.kt +++ b/src/main/kotlin/app/termora/terminal/panel/TerminalPanelMouseSelectionAdapter.kt @@ -3,6 +3,7 @@ package app.termora.terminal.panel import app.termora.actions.AnActionEvent import app.termora.actions.TerminalCopyAction import app.termora.actions.TerminalPasteAction +import app.termora.database.DatabaseManager import app.termora.terminal.* import org.apache.commons.lang3.StringUtils import org.jdesktop.swingx.action.ActionManager @@ -27,6 +28,7 @@ class TerminalPanelMouseSelectionAdapter(private val terminalPanel: TerminalPane private val isSelectCopy get() = terminalModel.getData(TerminalPanel.SelectCopy, false) private val selectionModel get() = terminal.getSelectionModel() private val wordBreakIterator = BreakIterator.getWordInstance() + private val rightClickMode get() = DatabaseManager.getInstance().terminal.rightClick companion object { private val log = LoggerFactory.getLogger(TerminalPanelMouseSelectionAdapter::class.java) @@ -50,7 +52,7 @@ class TerminalPanelMouseSelectionAdapter(private val terminalPanel: TerminalPane if (SwingUtilities.isRightMouseButton(e)) { // 如果有选中并且开启了选中复制,那么右键直接是粘贴 - if (selectionModel.hasSelection() && !isSelectCopy) { + if (selectionModel.hasSelection() && isSelectCopy.not()) { triggerCopyAction( KeyEvent( e.component, @@ -61,6 +63,20 @@ class TerminalPanelMouseSelectionAdapter(private val terminalPanel: TerminalPane 'C' ) ) + + if (rightClickMode == "CopyAndPaste") { + triggerPasteAction( + KeyEvent( + e.component, + KeyEvent.KEY_PRESSED, + e.`when`, + e.modifiersEx, + KeyEvent.VK_V, + 'V' + ) + ) + } + } else { // paste triggerPasteAction( diff --git a/src/main/resources/i18n/messages.properties b/src/main/resources/i18n/messages.properties index 18037ed..42950a8 100644 --- a/src/main/resources/i18n/messages.properties +++ b/src/main/resources/i18n/messages.properties @@ -56,6 +56,9 @@ termora.settings.terminal.debug=Debug mode termora.settings.terminal.beep=Beep termora.settings.terminal.hyperlink=Hyperlink termora.settings.terminal.select-copy=Select copy +termora.settings.terminal.right-click=Right click +termora.settings.terminal.right-click.copy-and-paste=Copy and Paste +termora.settings.terminal.right-click.copy=${termora.copy} termora.settings.terminal.cursor-style=Cursor type termora.settings.terminal.cursor-blink=Cursor blink termora.settings.terminal.local-shell=Local shell diff --git a/src/main/resources/i18n/messages_ru_RU.properties b/src/main/resources/i18n/messages_ru_RU.properties index ad07054..f37a120 100644 --- a/src/main/resources/i18n/messages_ru_RU.properties +++ b/src/main/resources/i18n/messages_ru_RU.properties @@ -59,6 +59,8 @@ termora.settings.terminal.debug=Режим отладки termora.settings.terminal.beep=Сигнал termora.settings.terminal.hyperlink=Ссылки termora.settings.terminal.select-copy=Копировать выделенное +termora.settings.terminal.right-click=правой кнопкой мыши +termora.settings.terminal.right-click.copy-and-paste=Копировать и вставить termora.settings.terminal.cursor-style=Вид курсора termora.settings.terminal.cursor-blink=Мигать курсором termora.settings.terminal.local-shell=Локальный терминал diff --git a/src/main/resources/i18n/messages_zh_CN.properties b/src/main/resources/i18n/messages_zh_CN.properties index 65e78cd..8aa29aa 100644 --- a/src/main/resources/i18n/messages_zh_CN.properties +++ b/src/main/resources/i18n/messages_zh_CN.properties @@ -70,6 +70,8 @@ termora.settings.terminal.debug=调试模式 termora.settings.terminal.beep=蜂鸣声 termora.settings.terminal.hyperlink=超链接 termora.settings.terminal.select-copy=选中复制 +termora.settings.terminal.right-click=右键点击 +termora.settings.terminal.right-click.copy-and-paste=复制 & 粘贴 termora.settings.terminal.cursor-style=光标样式 termora.settings.terminal.cursor-blink=光标闪烁 termora.settings.terminal.local-shell=本地终端 diff --git a/src/main/resources/i18n/messages_zh_TW.properties b/src/main/resources/i18n/messages_zh_TW.properties index 0edd9ab..c1489b2 100644 --- a/src/main/resources/i18n/messages_zh_TW.properties +++ b/src/main/resources/i18n/messages_zh_TW.properties @@ -79,8 +79,10 @@ termora.settings.terminal.size=大小 termora.settings.terminal.max-rows=最大行數 termora.settings.terminal.debug=偵錯模式 termora.settings.terminal.beep=超連結 -termora.settings.terminal.hyperlink=Hyperlink +termora.settings.terminal.hyperlink=超連結 termora.settings.terminal.select-copy=選取複製 +termora.settings.terminal.right-click=右鍵點擊 +termora.settings.terminal.right-click.copy-and-paste=複製 & 貼上 termora.settings.terminal.cursor-style=遊標風格 termora.settings.terminal.cursor-blink=遊標閃爍 termora.settings.terminal.local-shell=本地端