diff --git a/src/main/kotlin/com/github/fmueller/jarvis/conversation/ConversationPanel.kt b/src/main/kotlin/com/github/fmueller/jarvis/conversation/ConversationPanel.kt index 9ac6878..ee72180 100644 --- a/src/main/kotlin/com/github/fmueller/jarvis/conversation/ConversationPanel.kt +++ b/src/main/kotlin/com/github/fmueller/jarvis/conversation/ConversationPanel.kt @@ -2,24 +2,66 @@ package com.github.fmueller.jarvis.conversation import com.github.fmueller.jarvis.conversation.ColorHelper.darker import com.intellij.openapi.project.Project +import com.intellij.ui.components.JBScrollPane import com.intellij.util.ui.UIUtil import org.jdesktop.swingx.VerticalLayout +import java.awt.event.MouseAdapter +import java.awt.event.MouseEvent import javax.swing.JPanel +import javax.swing.SwingUtilities -class ConversationPanel(private val project: Project) : JPanel() { +class ConversationPanel(private val conversation: Conversation, private val project: Project) { - init { + private val panel = JPanel().apply { layout = VerticalLayout(1) background = UIUtil.getPanelBackground().darker(0.75) } + // we are exposing the scrollable container here and keep it in the panel + // because we need to adjust the scroll position when new messages are added + val scrollableContainer = JBScrollPane(panel).apply { + verticalScrollBarPolicy = JBScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED + horizontalScrollBarPolicy = JBScrollPane.HORIZONTAL_SCROLLBAR_NEVER + } + + init { + var isUserScrolling = false + + scrollableContainer.verticalScrollBar.addAdjustmentListener { e -> + if (!isUserScrolling) { + e.adjustable.value = e.adjustable.maximum + } + } + + scrollableContainer.addMouseListener(object : MouseAdapter() { + override fun mousePressed(e: MouseEvent?) { + isUserScrolling = true + } + }) + + scrollableContainer.addMouseWheelListener { + isUserScrolling = true + } + + conversation.addPropertyChangeListener { + if (it.propertyName == "messages") { + SwingUtilities.invokeLater { + isUserScrolling = false + update(conversation) + } + } + } + + conversation.addMessage(Message(Role.ASSISTANT, "Hello! How can I help you?")) + } + // TODO recalculate colors on theme change and don't set darker panel background for bright themes - fun update(conversation: Conversation) { - removeAll() + private fun update(conversation: Conversation) { + panel.removeAll() conversation.getMessages().forEach { message -> - add(MessagePanel(message, project)) + panel.add(MessagePanel(message, project)) } - revalidate() - repaint() + panel.revalidate() + panel.repaint() } } diff --git a/src/main/kotlin/com/github/fmueller/jarvis/toolWindow/ConversationWindowFactory.kt b/src/main/kotlin/com/github/fmueller/jarvis/toolWindow/ConversationWindowFactory.kt index 3122c18..acff8ff 100644 --- a/src/main/kotlin/com/github/fmueller/jarvis/toolWindow/ConversationWindowFactory.kt +++ b/src/main/kotlin/com/github/fmueller/jarvis/toolWindow/ConversationWindowFactory.kt @@ -11,7 +11,6 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.wm.ToolWindow import com.intellij.openapi.wm.ToolWindowFactory import com.intellij.ui.JBColor -import com.intellij.ui.components.JBScrollPane import com.intellij.ui.components.JBTextArea import com.intellij.ui.content.ContentFactory import com.intellij.util.ui.JBUI @@ -21,10 +20,12 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import java.awt.* -import java.awt.event.* +import java.awt.event.FocusEvent +import java.awt.event.FocusListener +import java.awt.event.KeyAdapter +import java.awt.event.KeyEvent import javax.swing.BorderFactory import javax.swing.JPanel -import javax.swing.SwingUtilities import javax.swing.UIManager import javax.swing.border.AbstractBorder @@ -43,44 +44,9 @@ class ConversationWindowFactory : ToolWindowFactory { private val project = toolWindow.project private val ollama = project.service() - // TODO conversationPanel should have a reference to the conversation and register the property change listener private val conversation = Conversation() - private val conversationPanel = ConversationPanel(project) - private val scrollableConversationPanel = JBScrollPane(conversationPanel).apply { - verticalScrollBarPolicy = JBScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED - horizontalScrollBarPolicy = JBScrollPane.HORIZONTAL_SCROLLBAR_NEVER - } - - init { - var isUserScrolling = false - - scrollableConversationPanel.verticalScrollBar.addAdjustmentListener { e -> - if (!isUserScrolling) { - e.adjustable.value = e.adjustable.maximum - } - } - - scrollableConversationPanel.addMouseListener(object : MouseAdapter() { - override fun mousePressed(e: MouseEvent?) { - isUserScrolling = true - } - }) + private val conversationPanel = ConversationPanel(conversation, project) - scrollableConversationPanel.addMouseWheelListener { - isUserScrolling = true - } - - conversation.addPropertyChangeListener { - if (it.propertyName == "messages") { - SwingUtilities.invokeLater { - isUserScrolling = false - conversationPanel.update(conversation) - } - } - } - - conversation.addMessage(Message(Role.ASSISTANT, "Hello! How can I help you?")) - } @OptIn(DelicateCoroutinesApi::class) fun getContent() = BorderLayoutPanel().apply { @@ -145,7 +111,7 @@ class ConversationWindowFactory : ToolWindowFactory { } }) - addToCenter(scrollableConversationPanel) + addToCenter(conversationPanel.scrollableContainer) addToBottom(BorderLayoutPanel().apply { addToCenter(JPanel(BorderLayout()).apply {