diff --git a/src/main/kotlin/ee/carlrobert/codegpt/ui/textarea/UserInputPanel.kt b/src/main/kotlin/ee/carlrobert/codegpt/ui/textarea/UserInputPanel.kt index f7fff641..7b4caa20 100644 --- a/src/main/kotlin/ee/carlrobert/codegpt/ui/textarea/UserInputPanel.kt +++ b/src/main/kotlin/ee/carlrobert/codegpt/ui/textarea/UserInputPanel.kt @@ -65,7 +65,7 @@ class UserInputPanel @JvmOverloads constructor( private val onAcceptAll: (() -> Unit)? = null, private val onRejectAll: (() -> Unit)? = null, private val showModeSelector: Boolean = true, - withRemovableSelectedEditorTag: Boolean = false, + withRemovableSelectedEditorTag: Boolean = true, ) : BorderLayoutPanel() { constructor( diff --git a/src/main/kotlin/ee/carlrobert/codegpt/ui/textarea/header/UserInputHeaderPanel.kt b/src/main/kotlin/ee/carlrobert/codegpt/ui/textarea/header/UserInputHeaderPanel.kt index ec106c7e..1ce46935 100644 --- a/src/main/kotlin/ee/carlrobert/codegpt/ui/textarea/header/UserInputHeaderPanel.kt +++ b/src/main/kotlin/ee/carlrobert/codegpt/ui/textarea/header/UserInputHeaderPanel.kt @@ -3,7 +3,6 @@ package ee.carlrobert.codegpt.ui.textarea.header import com.intellij.icons.AllIcons import com.intellij.openapi.application.runInEdt import com.intellij.openapi.application.runUndoTransparentWriteAction -import com.intellij.openapi.components.service import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.EditorKind import com.intellij.openapi.editor.SelectionModel @@ -18,7 +17,6 @@ import com.intellij.util.IconUtil import com.intellij.util.ui.JBUI import ee.carlrobert.codegpt.CodeGPTBundle import ee.carlrobert.codegpt.EditorNotifier -import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings import ee.carlrobert.codegpt.toolwindow.chat.ui.textarea.TotalTokensPanel import ee.carlrobert.codegpt.ui.WrapLayout import ee.carlrobert.codegpt.ui.textarea.PromptTextField @@ -35,6 +33,7 @@ import java.awt.* import java.awt.event.ActionListener import javax.swing.JButton import javax.swing.JPanel +import javax.swing.SwingUtilities class UserInputHeaderPanel( private val project: Project, @@ -172,7 +171,12 @@ class UserInputHeaderPanel( private fun addInitialTags() { val selectedFile = getSelectedEditor(project)?.virtualFile if (selectedFile != null) { - tagManager.addTag(EditorTagDetails(selectedFile, isRemovable = withRemovableSelectedEditorTag)) + tagManager.addTag( + EditorTagDetails( + selectedFile, + isRemovable = withRemovableSelectedEditorTag + ) + ) } EditorUtil.getOpenLocalFiles(project) @@ -265,13 +269,24 @@ class UserInputHeaderPanel( val hasTag = tagManager.getTags() .any { it is EditorTagDetails && it.virtualFile == newFile } if (!hasTag) { - tagManager.addTag(EditorTagDetails(newFile, isRemovable = false)) + tagManager.addTag( + EditorTagDetails( + newFile, + isRemovable = withRemovableSelectedEditorTag + ) + ) } else { tagManager.getTags() .filterIsInstance() - .firstOrNull { it.virtualFile == newFile && it.isRemovable }?.let { existing -> + .firstOrNull { it.virtualFile == newFile && it.isRemovable } + ?.let { existing -> tagManager.remove(existing) - tagManager.addTag(EditorTagDetails(newFile, isRemovable = false)) + tagManager.addTag( + EditorTagDetails( + newFile, + isRemovable = withRemovableSelectedEditorTag + ) + ) } } @@ -280,7 +295,9 @@ class UserInputHeaderPanel( .filter { it.virtualFile != newFile && !it.isRemovable } .forEach { prev -> tagManager.remove(prev) - tagManager.addTag(EditorTagDetails(prev.virtualFile).apply { selected = false }) + tagManager.addTag(EditorTagDetails(prev.virtualFile).apply { + selected = false + }) } emptyText.isVisible = false @@ -293,7 +310,9 @@ class UserInputHeaderPanel( createPopupMenuItem(CodeGPTBundle.get("tagPopupMenuItem.close")) { val tagPanel = invoker as? TagPanel tagPanel?.let { - tagManager.remove(it.tagDetails) + if (it.tagDetails.isRemovable) { + tagManager.remove(it.tagDetails) + } } } @@ -303,14 +322,16 @@ class UserInputHeaderPanel( tagPanel?.let { currentPanel -> val currentTag = currentPanel.tagDetails tagManager.getTags() - .filter { it != currentTag } + .filter { it != currentTag && it.isRemovable } .forEach { tagManager.remove(it) } } } private val closeAllTagsMenuItem = createPopupMenuItem(CodeGPTBundle.get("tagPopupMenuItem.closeAll")) { - tagManager.clear() + tagManager.getTags() + .filter { it.isRemovable } + .forEach { tagManager.remove(it) } } private val closeTagsToLeftMenuItem = @@ -343,7 +364,9 @@ class UserInputHeaderPanel( rangeSelector(components, currentIndex) .filterIsInstance() - .forEach { tagManager.remove(it.tagDetails) } + .map { it.tagDetails } + .filter { it.isRemovable } + .forEach { tagManager.remove(it) } } } @@ -356,17 +379,35 @@ class UserInputHeaderPanel( } override fun show(invoker: Component, x: Int, y: Int) { - if (invoker is TagPanel) { - if (!invoker.isEnabled) return - val components = this@UserInputHeaderPanel.components.filterIsInstance() - val currentIndex = components.indexOf(invoker) + val tagPanel = when (invoker) { + is TagPanel -> invoker + else -> SwingUtilities.getAncestorOfClass( + TagPanel::class.java, + invoker + ) as? TagPanel + } ?: return + if (!tagPanel.isEnabled) return + val components = this@UserInputHeaderPanel.components.filterIsInstance() + val currentIndex = components.indexOf(tagPanel) - closeTagsToLeftMenuItem.isEnabled = currentIndex > 0 - closeTagsToRightMenuItem.isEnabled = currentIndex < components.size - 1 - closeOtherTagsMenuItem.isEnabled = components.size > 1 + val removableLeft = if (currentIndex > 0) { + components.take(currentIndex).any { it.tagDetails.isRemovable } + } else false + val removableRight = if (currentIndex >= 0 && currentIndex < components.size - 1) { + components.drop(currentIndex + 1).any { it.tagDetails.isRemovable } + } else false + val removableOthers = components + .filterIndexed { index, _ -> index != currentIndex } + .any { it.tagDetails.isRemovable } + val anyRemovable = components.any { it.tagDetails.isRemovable } - super.show(invoker, x, y) - } + closeMenuItem.isEnabled = tagPanel.tagDetails.isRemovable + closeTagsToLeftMenuItem.isEnabled = removableLeft + closeTagsToRightMenuItem.isEnabled = removableRight + closeOtherTagsMenuItem.isEnabled = removableOthers + closeAllTagsMenuItem.isEnabled = anyRemovable + + super.show(tagPanel, x, y) } private fun createPopupMenuItem(label: String, listener: ActionListener): JBMenuItem { diff --git a/src/main/kotlin/ee/carlrobert/codegpt/ui/textarea/header/tag/TagPanel.kt b/src/main/kotlin/ee/carlrobert/codegpt/ui/textarea/header/tag/TagPanel.kt index 541d0b2c..581bf37c 100644 --- a/src/main/kotlin/ee/carlrobert/codegpt/ui/textarea/header/tag/TagPanel.kt +++ b/src/main/kotlin/ee/carlrobert/codegpt/ui/textarea/header/tag/TagPanel.kt @@ -10,15 +10,10 @@ import com.intellij.util.IconUtil import com.intellij.util.ui.JBUI import ee.carlrobert.codegpt.ui.textarea.PromptTextField import ee.carlrobert.codegpt.ui.textarea.header.PaintUtil -import java.awt.Cursor -import java.awt.Dimension -import java.awt.Graphics -import java.awt.GridBagConstraints -import java.awt.GridBagLayout -import javax.swing.BorderFactory -import javax.swing.Icon -import javax.swing.JButton -import javax.swing.JToggleButton +import java.awt.* +import java.awt.event.MouseAdapter +import java.awt.event.MouseEvent +import javax.swing.* abstract class TagPanel( var tagDetails: TagDetails, @@ -42,7 +37,7 @@ abstract class TagPanel( abstract fun onClose() fun update(text: String, icon: Icon? = null) { - closeButton.isVisible = isSelected && tagDetails.isRemovable + closeButton.isVisible = tagDetails.isRemovable label.update(text, icon, isSelected) tagDetails.getTooltipText()?.let { tooltip -> val relativeTooltipText = toProjectRelative(tooltip) @@ -72,7 +67,7 @@ abstract class TagPanel( border = JBUI.Borders.empty(2, 6) cursor = Cursor(Cursor.HAND_CURSOR) isSelected = tagDetails.selected - closeButton.isVisible = isSelected && tagDetails.isRemovable + closeButton.isVisible = tagDetails.isRemovable tagDetails.getTooltipText()?.let { tooltip -> val relativeTooltipText = toProjectRelative(tooltip) this.toolTipText = relativeTooltipText @@ -90,6 +85,18 @@ abstract class TagPanel( gbc.gridx = 1 add(closeButton, gbc) + label.inheritsPopupMenu = true + closeButton.inheritsPopupMenu = true + + label.addMouseListener(object : MouseAdapter() { + override fun mousePressed(e: MouseEvent) { + if (SwingUtilities.isLeftMouseButton(e)) { + this@TagPanel.doClick() + e.consume() + } + } + }) + addActionListener { if (isRevertingSelection) return@addActionListener @@ -101,7 +108,7 @@ abstract class TagPanel( isRevertingSelection = false } - closeButton.isVisible = isSelected && tagDetails.isRemovable + closeButton.isVisible = tagDetails.isRemovable tagDetails.selected = isSelected tagManager.notifySelectionChanged(tagDetails) label.update(isSelected)