Skip to content

Commit 7e37799

Browse files
authored
refactor: Optimized the components of the tool window (#233)
1 parent 17afaa9 commit 7e37799

File tree

10 files changed

+76
-40
lines changed

10 files changed

+76
-40
lines changed

src/main/kotlin/cc/unitmesh/devti/actions/chat/CodeCompleteChatAction.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import com.intellij.openapi.actionSystem.CommonDataKeys
1414
import com.intellij.openapi.application.ApplicationManager
1515
import com.intellij.openapi.diagnostic.logger
1616
import com.intellij.openapi.project.IndexNotReadyException
17-
import com.intellij.openapi.wm.ToolWindowManager
1817
import com.intellij.temporary.getElementToAction
1918

2019
class CodeCompleteChatAction : AnAction() {

src/main/kotlin/cc/unitmesh/devti/actions/groups/AutoChatDynamicActionGroup.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package cc.unitmesh.devti.actions.groups
22

3-
import cc.unitmesh.devti.settings.LanguageChangedCallback
3+
import cc.unitmesh.devti.settings.LanguageChangedCallback.presentationText
44
import com.intellij.openapi.actionSystem.ActionGroupUtil
55
import com.intellij.openapi.actionSystem.ActionUpdateThread
66
import com.intellij.openapi.actionSystem.AnActionEvent
@@ -18,8 +18,7 @@ import com.intellij.openapi.project.DumbAware
1818
class AutoChatDynamicActionGroup : DefaultActionGroup(), DumbAware {
1919

2020
init {
21-
LanguageChangedCallback.presentationText("autodev.chat",
22-
templatePresentation.also { it.isHideGroupIfEmpty = true })
21+
presentationText("autodev.chat", templatePresentation.also { it.isHideGroupIfEmpty = true }, 1)
2322
}
2423

2524
override fun getActionUpdateThread() = ActionUpdateThread.BGT

src/main/kotlin/cc/unitmesh/devti/gui/AutoDevToolWindowFactory.kt

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
package cc.unitmesh.devti.gui
22

3-
import cc.unitmesh.devti.AutoDevBundle
43
import cc.unitmesh.devti.gui.chat.ChatActionType
54
import cc.unitmesh.devti.gui.chat.ChatCodingPanel
65
import cc.unitmesh.devti.gui.chat.ChatCodingService
6+
import cc.unitmesh.devti.settings.LanguageChangedCallback.componentStateChanged
77
import com.intellij.openapi.actionSystem.ex.ActionUtil
88
import com.intellij.openapi.application.ApplicationManager
99
import com.intellij.openapi.project.DumbAware
1010
import com.intellij.openapi.project.Project
1111
import com.intellij.openapi.wm.ToolWindow
1212
import com.intellij.openapi.wm.ToolWindowFactory
1313
import com.intellij.openapi.wm.ToolWindowManager
14+
import com.intellij.ui.content.Content
1415
import com.intellij.ui.content.ContentFactory
1516

1617
class AutoDevToolWindowFactory : ToolWindowFactory, DumbAware {
@@ -21,9 +22,9 @@ class AutoDevToolWindowFactory : ToolWindowFactory, DumbAware {
2122
override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) {
2223
val chatCodingService = ChatCodingService(ChatActionType.CHAT, project)
2324
val contentPanel = ChatCodingPanel(chatCodingService, toolWindow.disposable)
24-
val content =
25-
ContentFactory.getInstance()
26-
.createContent(contentPanel, AutoDevBundle.message("autodev.chat"), false)
25+
val content = ContentFactory.getInstance().createContent(contentPanel, "", false).apply {
26+
setInitialDisplayName(this)
27+
}
2728

2829
ApplicationManager.getApplication().invokeLater {
2930
toolWindow.contentManager.addContent(content)
@@ -38,5 +39,9 @@ class AutoDevToolWindowFactory : ToolWindowFactory, DumbAware {
3839
fun getToolWindow(project: Project): ToolWindow? {
3940
return ToolWindowManager.getInstance(project).getToolWindow(Util.id)
4041
}
42+
43+
fun setInitialDisplayName(content: Content) {
44+
componentStateChanged("autodev.chat", content, 2) { c, d -> c.displayName = d }
45+
}
4146
}
4247
}

src/main/kotlin/cc/unitmesh/devti/gui/chat/AutoDevInput.kt

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package cc.unitmesh.devti.gui.chat
22

3-
import cc.unitmesh.devti.AutoDevBundle
3+
import cc.unitmesh.devti.settings.LanguageChangedCallback.placeholder
44
import cc.unitmesh.devti.util.parser.Code.Companion.findLanguage
55
import com.intellij.openapi.Disposable
66
import com.intellij.openapi.actionSystem.*
@@ -50,7 +50,7 @@ class AutoDevInput(
5050

5151
init {
5252
isOneLineMode = false
53-
updatePlaceholderText()
53+
placeholder("chat.panel.initial.text", this)
5454
setFontInheritedFromLAF(true)
5555
addSettingsProvider {
5656
it.putUserData(IncrementalFindAction.SEARCH_DISABLED, true)
@@ -101,11 +101,6 @@ class AutoDevInput(
101101
editorListeners.multicaster.editorAdded((editor as EditorEx))
102102
}
103103

104-
private fun updatePlaceholderText() {
105-
setPlaceholder(AutoDevBundle.message("chat.panel.initial.text"))
106-
repaint()
107-
}
108-
109104
public override fun createEditor(): EditorEx {
110105
val editor = super.createEditor()
111106
editor.setVerticalScrollbarVisible(true)

src/main/kotlin/cc/unitmesh/devti/gui/chat/AutoDevInputSection.kt

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import cc.unitmesh.devti.agent.model.CustomAgentState
88
import cc.unitmesh.devti.llms.tokenizer.Tokenizer
99
import cc.unitmesh.devti.llms.tokenizer.TokenizerFactory
1010
import cc.unitmesh.devti.settings.AutoDevSettingsState
11+
import com.intellij.ide.IdeTooltip
12+
import com.intellij.ide.IdeTooltipManager
1113
import com.intellij.openapi.Disposable
1214
import com.intellij.openapi.actionSystem.AnActionEvent
1315
import com.intellij.openapi.actionSystem.Presentation
@@ -21,9 +23,12 @@ import com.intellij.openapi.project.Project
2123
import com.intellij.openapi.ui.ComboBox
2224
import com.intellij.openapi.ui.ComponentValidator
2325
import com.intellij.openapi.ui.ValidationInfo
26+
import com.intellij.openapi.ui.popup.Balloon.Position
27+
import com.intellij.openapi.util.NlsContexts
2428
import com.intellij.openapi.wm.IdeFocusManager
2529
import com.intellij.openapi.wm.impl.InternalDecorator
2630
import com.intellij.temporary.gui.block.AutoDevCoolBorder
31+
import com.intellij.ui.HintHint
2732
import com.intellij.ui.MutableCollectionComboBoxModel
2833
import com.intellij.ui.SimpleListCellRenderer
2934
import com.intellij.ui.components.JBLabel
@@ -35,6 +40,7 @@ import com.intellij.util.ui.components.BorderLayoutPanel
3540
import java.awt.CardLayout
3641
import java.awt.Color
3742
import java.awt.Dimension
43+
import java.awt.Point
3844
import java.awt.event.MouseAdapter
3945
import java.awt.event.MouseEvent
4046
import java.util.function.Supplier
@@ -91,7 +97,6 @@ class AutoDevInputSection(private val project: Project, val disposable: Disposab
9197
DumbAwareAction.create {
9298
object : DumbAwareAction("") {
9399
override fun actionPerformed(e: AnActionEvent) {
94-
showStopButton()
95100
editorListeners.multicaster.onSubmit(this@AutoDevInputSection, AutoDevInputTrigger.Button)
96101
}
97102
}.actionPerformed(it)
@@ -179,6 +184,19 @@ class AutoDevInputSection(private val project: Project, val disposable: Disposab
179184
stopButton.isEnabled = true
180185
}
181186

187+
fun showTooltip(text: @NlsContexts.Tooltip String) {
188+
showTooltip(input, Position.above, text)
189+
}
190+
191+
fun showTooltip(component: JComponent, position: Position, text: @NlsContexts.Tooltip String) {
192+
val point = Point(component.x, component.y)
193+
val tipComponent = IdeTooltipManager.initPane(
194+
text, HintHint(component, point).setAwtTooltip(true).setPreferredPosition(position), null
195+
)
196+
val tooltip = IdeTooltip(component, point, tipComponent)
197+
IdeTooltipManager.getInstance().show(tooltip, true)
198+
}
199+
182200
fun showSendButton() {
183201
(buttonPanel.layout as? CardLayout)?.show(buttonPanel, "Send")
184202
buttonPanel.isEnabled = true
@@ -254,6 +272,7 @@ class AutoDevInputSection(private val project: Project, val disposable: Disposab
254272
}
255273

256274
customRag.selectedItem = defaultRag
275+
text = ""
257276
}
258277

259278
fun moveCursorToStart() {

src/main/kotlin/cc/unitmesh/devti/gui/chat/ChatCodingPanel.kt

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import cc.unitmesh.devti.gui.chat.welcome.WelcomePanel
88
import cc.unitmesh.devti.provider.ContextPrompter
99
import cc.unitmesh.devti.provider.devins.LanguagePromptProcessor
1010
import cc.unitmesh.devti.settings.AutoDevSettingsState
11+
import cc.unitmesh.devti.settings.LanguageChangedCallback.componentStateChanged
1112
import com.intellij.lang.html.HTMLLanguage
1213
import com.intellij.openapi.Disposable
1314
import com.intellij.openapi.diagnostic.logger
@@ -63,8 +64,7 @@ class ChatCodingPanel(private val chatCodingService: ChatCodingService, val disp
6364
}
6465
}
6566

66-
val panel = WelcomePanel()
67-
myList.add(panel)
67+
myList.add(WelcomePanel())
6868

6969
myTitle.foreground = JBColor.namedColor("Label.infoForeground", JBColor(Gray.x80, Gray.x8C))
7070
myTitle.font = JBFont.label()
@@ -84,24 +84,26 @@ class ChatCodingPanel(private val chatCodingService: ChatCodingService, val disp
8484

8585
val actionLink = panel {
8686
row {
87-
text(AutoDevBundle.message("label.submit.issue"))
87+
text("").apply {
88+
componentStateChanged("label.submit.issue", this.component) { c, d -> c.text = d }
89+
}
8890
}
8991
}
9092

9193
inputSection = AutoDevInputSection(chatCodingService.project, disposable)
9294
inputSection.addListener(object : AutoDevInputListener {
9395
override fun onStop(component: AutoDevInputSection) {
9496
chatCodingService.stop()
95-
inputSection.showSendButton()
97+
hiddenProgressBar()
9698
}
9799

98100
override fun onSubmit(component: AutoDevInputSection, trigger: AutoDevInputTrigger) {
99101
var prompt = component.text
100102
component.text = ""
101103

102-
inputSection.showStopButton()
103104

104-
if (prompt.isEmpty() || prompt == "\n") {
105+
if (prompt.isEmpty() || prompt.isBlank()) {
106+
component.showTooltip(AutoDevBundle.message("chat.input.tips"))
105107
return
106108
}
107109

@@ -175,12 +177,12 @@ class ChatCodingPanel(private val chatCodingService: ChatCodingService, val disp
175177
myList.remove(myList.componentCount - 1)
176178
}
177179

178-
progressBar.isVisible = true
180+
showProgressBar()
179181

180182
val result = updateMessageInUi(content)
181183

182184
progressBar.isIndeterminate = false
183-
progressBar.isVisible = false
185+
hiddenProgressBar()
184186
updateUI()
185187

186188
return result
@@ -206,10 +208,11 @@ class ChatCodingPanel(private val chatCodingService: ChatCodingService, val disp
206208
*/
207209
suspend fun updateReplaceableContent(content: Flow<String>, postAction: (text: String) -> Unit) {
208210
myList.remove(myList.componentCount - 1)
211+
showProgressBar()
209212
val text = updateMessageInUi(content)
210213

211214
progressBar.isIndeterminate = false
212-
progressBar.isVisible = false
215+
hiddenProgressBar()
213216
updateUI()
214217

215218
postAction(text)
@@ -223,7 +226,7 @@ class ChatCodingPanel(private val chatCodingService: ChatCodingService, val disp
223226
var text = ""
224227
content.onCompletion {
225228
logger.info("onCompletion ${it?.message}")
226-
inputSection.showSendButton()
229+
hiddenProgressBar()
227230
}.catch {
228231
it.printStackTrace()
229232
}.collect {
@@ -258,9 +261,11 @@ class ChatCodingPanel(private val chatCodingService: ChatCodingService, val disp
258261
* Resets the chat session by clearing the current session and updating the UI.
259262
*/
260263
fun resetChatSession() {
264+
chatCodingService.stop()
265+
suggestionPanel.removeAll()
261266
chatCodingService.clearSession()
262-
progressBar.isVisible = false
263267
myList.removeAll()
268+
myList.add(WelcomePanel())
264269
this.hiddenProgressBar()
265270
this.resetAgent()
266271
updateUI()
@@ -280,6 +285,12 @@ class ChatCodingPanel(private val chatCodingService: ChatCodingService, val disp
280285

281286
fun hiddenProgressBar() {
282287
progressBar.isVisible = false
288+
inputSection.showSendButton()
289+
}
290+
291+
fun showProgressBar() {
292+
progressBar.isVisible = true
293+
inputSection.showStopButton()
283294
}
284295

285296
fun removeLastMessage() {

src/main/kotlin/cc/unitmesh/devti/gui/chat/welcome/WelcomePanel.kt

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,40 @@
11
package cc.unitmesh.devti.gui.chat.welcome
22

3-
import cc.unitmesh.devti.AutoDevBundle
43
import cc.unitmesh.devti.AutoDevIcons
4+
import cc.unitmesh.devti.settings.LanguageChangedCallback.componentStateChanged
55
import com.intellij.ui.dsl.builder.RightGap
66
import com.intellij.ui.dsl.builder.panel
77
import java.awt.BorderLayout
88
import javax.swing.JPanel
99

1010
class WelcomePanel: JPanel(BorderLayout()) {
1111
private val welcomeItems: List<WelcomeItem> = listOf(
12-
WelcomeItem(AutoDevBundle.message("settings.welcome.feature.context")),
13-
WelcomeItem(AutoDevBundle.message("settings.welcome.feature.lifecycle")),
14-
WelcomeItem(AutoDevBundle.message("settings.welcome.feature.custom.action")),
15-
WelcomeItem(AutoDevBundle.message("settings.welcome.feature.custom.agent")),
12+
WelcomeItem("settings.welcome.feature.context"),
13+
WelcomeItem("settings.welcome.feature.lifecycle"),
14+
WelcomeItem("settings.welcome.feature.custom.action"),
15+
WelcomeItem("settings.welcome.feature.custom.agent"),
1616
)
1717

1818
init {
1919
val panel = panel {
2020
row {
21-
text(AutoDevBundle.message("settings.welcome.message"))
21+
text("").apply {
22+
componentStateChanged("settings.welcome.message", this.component) { c, d -> c.text = d }
23+
}
2224
}
2325
welcomeItems.forEach {
2426
row {
2527
// icon
2628
icon(AutoDevIcons.AI_COPILOT).gap(RightGap.SMALL)
27-
text(it.text)
29+
text(it.text).apply {
30+
componentStateChanged(it.text, this.component) { c, d -> c.text = d }
31+
}
2832
}
2933
}
3034
row {
31-
text(AutoDevBundle.message("settings.welcome.feature.features"))
35+
text("").apply {
36+
componentStateChanged("settings.welcome.feature.features", this.component) { c, d -> c.text = d }
37+
}
3238
}
3339
}.apply {
3440
border = javax.swing.BorderFactory.createEmptyBorder(20, 20, 20, 20)

src/main/kotlin/cc/unitmesh/devti/gui/toolbar/NewChatAction.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
package cc.unitmesh.devti.gui.toolbar
22

3-
import cc.unitmesh.devti.AutoDevBundle
43
import cc.unitmesh.devti.gui.AutoDevToolWindowFactory
54
import cc.unitmesh.devti.gui.chat.ChatCodingPanel
5+
import cc.unitmesh.devti.settings.LanguageChangedCallback.componentStateChanged
66
import com.intellij.openapi.actionSystem.*
77
import com.intellij.openapi.actionSystem.ex.CustomComponentAction
88
import com.intellij.openapi.diagnostic.logger
99
import com.intellij.openapi.project.DumbAwareAction
10-
import com.intellij.openapi.wm.ToolWindowManager
1110
import com.intellij.ui.components.panels.Wrapper
1211
import com.intellij.util.ui.JBInsets
1312
import com.intellij.util.ui.JBUI
@@ -20,8 +19,7 @@ class NewChatAction : DumbAwareAction(), CustomComponentAction {
2019
override fun actionPerformed(e: AnActionEvent) = Unit
2120

2221
override fun createCustomComponent(presentation: Presentation, place: String): JComponent {
23-
val message = AutoDevBundle.message("chat.panel.new")
24-
val button: JButton = object : JButton(message) {
22+
val button: JButton = object : JButton() {
2523
init {
2624
putClientProperty("ActionToolbar.smallVariant", true)
2725
putClientProperty("customButtonInsets", JBInsets(1, 1, 1, 1).asUIResource())
@@ -47,12 +45,14 @@ class NewChatAction : DumbAwareAction(), CustomComponentAction {
4745

4846
// change content displayName AutoDevBundle.message("autodev.chat")
4947
contentManager.contents.forEach {
50-
it.displayName = AutoDevBundle.message("autodev.chat")
48+
AutoDevToolWindowFactory.setInitialDisplayName(it)
5149
}
5250

5351
codingPanel.resetChatSession()
5452
}
5553
}
54+
}.apply {
55+
componentStateChanged("chat.panel.new", this) { b, d -> b.text = d }
5656
}
5757

5858
return Wrapper(button).also {

src/main/resources/messages/AutoDevBundle_en.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ chat.panel.new=New Chat
1010
chat.panel.replaceSelection=Replace Selection
1111
chat.panel.initial.text='Enter' to start, 'Shift+Enter' for a new line
1212
chat.too.long.user.message=Message has is {0} tokens too looooooooooooooooooong
13+
chat.input.tips=Content cannot be blank
1314

1415
intention.category.llm=AutoDev
1516
intentions.write.action=Generate code

src/main/resources/messages/AutoDevBundle_zh.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ chat.panel.new=新建聊天
1010
chat.panel.replaceSelection=替换选择的代码
1111
chat.panel.initial.text='Enter' 发送,'Shift+Enter' 开启新行
1212
chat.too.long.user.message=消息长度太长,包含{0}个 Token
13+
chat.input.tips=内容不能为空
1314

1415
intention.category.llm=AutoDev
1516
intentions.write.action=生成代码

0 commit comments

Comments
 (0)