@@ -4,10 +4,12 @@ import com.intellij.openapi.application.ApplicationManager
44import com.intellij.openapi.project.Project
55import com.intellij.ui.components.JBScrollPane
66import com.intellij.ui.components.JBTextArea
7+ import com.intellij.ui.JBColor
78import java.awt.BorderLayout
89import java.awt.Dimension
910import java.awt.FlowLayout
1011import javax.swing.*
12+ import javax.swing.text.html.HTMLEditorKit
1113import java.net.HttpURLConnection
1214import java.net.URL
1315import com.google.gson.Gson
@@ -157,24 +159,76 @@ class PicoCodeToolWindowContent(private val project: Project) {
157159 return panel
158160 }
159161
162+ /* *
163+ * Convert markdown to HTML for rendering
164+ */
165+ private fun markdownToHtml (markdown : String ): String {
166+ var html = markdown
167+ // Escape HTML special characters first
168+ .replace(" &" , " &" )
169+ .replace(" <" , " <" )
170+ .replace(" >" , " >" )
171+ // Code blocks (```)
172+ .replace(Regex (" ```([\\ s\\ S]*?)```" ), " <pre style='background-color: #f5f5f5; padding: 8px; border-radius: 4px;'><code>$1</code></pre>" )
173+ // Inline code (`)
174+ .replace(Regex (" `([^`]+)`" ), " <code style='background-color: #f0f0f0; padding: 2px 4px; border-radius: 3px;'>$1</code>" )
175+ // Bold (**text**)
176+ .replace(Regex (" \\ *\\ *([^*]+)\\ *\\ *" ), " <strong>$1</strong>" )
177+ // Italic (*text*)
178+ .replace(Regex (" \\ *([^*]+)\\ *" ), " <em>$1</em>" )
179+ // Headers
180+ .replace(Regex (" ^### (.+)$" , RegexOption .MULTILINE ), " <h3>$1</h3>" )
181+ .replace(Regex (" ^## (.+)$" , RegexOption .MULTILINE ), " <h2>$1</h2>" )
182+ .replace(Regex (" ^# (.+)$" , RegexOption .MULTILINE ), " <h1>$1</h1>" )
183+ // Lists
184+ .replace(Regex (" ^- (.+)$" , RegexOption .MULTILINE ), " <li>$1</li>" )
185+ .replace(Regex (" ^\\ * (.+)$" , RegexOption .MULTILINE ), " <li>$1</li>" )
186+ // Line breaks
187+ .replace(" \n " , " <br/>" )
188+
189+ // Wrap lists in <ul> tags
190+ html = html.replace(Regex (" (<li>.*?</li>)+" )) { matchResult ->
191+ " <ul>${matchResult.value} </ul>"
192+ }
193+
194+ return " <html><body style='font-family: sans-serif; font-size: 12px;'>$html </body></html>"
195+ }
196+
160197 private fun renderChatHistory () {
161198 chatPanel.removeAll()
162199
163200 for ((index, msg) in chatHistory.withIndex()) {
164201 val messagePanel = JPanel (BorderLayout ())
202+
203+ // Use theme-aware colors
204+ val borderColor = if (msg.sender == " You" )
205+ JBColor .BLUE
206+ else
207+ JBColor .GRAY
208+
165209 messagePanel.border = BorderFactory .createCompoundBorder(
166210 BorderFactory .createEmptyBorder(5 , 5 , 5 , 5 ),
167- BorderFactory .createLineBorder(if (msg.sender == " You " ) java.awt. Color . BLUE else java.awt. Color . GRAY , 1 )
211+ BorderFactory .createLineBorder(borderColor , 1 )
168212 )
169213
170- val textArea = JBTextArea (msg.message)
171- textArea.isEditable = false
172- textArea.lineWrap = true
173- textArea.wrapStyleWord = true
174- textArea.background = if (msg.sender == " You" ) java.awt.Color (230 , 240 , 255 ) else java.awt.Color .WHITE
214+ // Use JEditorPane for HTML/Markdown rendering
215+ val editorPane = JEditorPane ()
216+ editorPane.contentType = " text/html"
217+ editorPane.editorKit = HTMLEditorKit ()
218+ editorPane.text = markdownToHtml(msg.message)
219+ editorPane.isEditable = false
220+ editorPane.isOpaque = true
221+
222+ // Use theme-aware background colors
223+ editorPane.background = if (msg.sender == " You" )
224+ JBColor .namedColor(" EditorPane.inactiveBackground" , JBColor (0xE6F0FF , 0x2D3239 ))
225+ else
226+ JBColor .namedColor(" EditorPane.background" , JBColor .background())
227+
228+ editorPane.putClientProperty(JEditorPane .HONOR_DISPLAY_PROPERTIES , true )
175229
176230 val headerPanel = JPanel (BorderLayout ())
177- headerPanel.add(JLabel (" [$msg .sender]" ), BorderLayout .WEST )
231+ headerPanel.add(JLabel (" [${ msg.sender} ]" ), BorderLayout .WEST )
178232
179233 // Add delete button for each message
180234 val deleteBtn = JButton (" ×" )
@@ -186,7 +240,11 @@ class PicoCodeToolWindowContent(private val project: Project) {
186240 headerPanel.add(deleteBtn, BorderLayout .EAST )
187241
188242 messagePanel.add(headerPanel, BorderLayout .NORTH )
189- messagePanel.add(textArea, BorderLayout .CENTER )
243+
244+ // Wrap editorPane in a scroll pane for long messages
245+ val messageScrollPane = JBScrollPane (editorPane)
246+ messageScrollPane.border = null
247+ messagePanel.add(messageScrollPane, BorderLayout .CENTER )
190248
191249 // Add context information if available
192250 if (msg.contexts.isNotEmpty()) {
@@ -196,7 +254,8 @@ class PicoCodeToolWindowContent(private val project: Project) {
196254 }
197255 val contextArea = JBTextArea (contextText.toString())
198256 contextArea.isEditable = false
199- contextArea.background = java.awt.Color (250 , 250 , 250 )
257+ // Use theme-aware background for context
258+ contextArea.background = JBColor .namedColor(" Panel.background" , JBColor (0xFAFAFA , 0x3C3F41 ))
200259 messagePanel.add(contextArea, BorderLayout .SOUTH )
201260 }
202261
0 commit comments