Skip to content

Commit

Permalink
refactor: Move scrollable container into ConversationPanel
Browse files Browse the repository at this point in the history
  • Loading branch information
fmueller committed May 30, 2024
1 parent 952fdc2 commit d56709e
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand All @@ -43,44 +44,9 @@ class ConversationWindowFactory : ToolWindowFactory {
private val project = toolWindow.project
private val ollama = project.service<OllamaService>()

// 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 {
Expand Down Expand Up @@ -145,7 +111,7 @@ class ConversationWindowFactory : ToolWindowFactory {
}
})

addToCenter(scrollableConversationPanel)
addToCenter(conversationPanel.scrollableContainer)

addToBottom(BorderLayoutPanel().apply {
addToCenter(JPanel(BorderLayout()).apply {
Expand Down

0 comments on commit d56709e

Please sign in to comment.