@@ -12,35 +12,70 @@ import com.intellij.openapi.ui.popup.LightweightWindowEvent
1212import com.intellij.openapi.wm.StatusBar
1313import com.intellij.openapi.wm.StatusBarWidget
1414import com.intellij.openapi.wm.StatusBarWidgetFactory
15- import com.intellij.ui.CollectionListModel
1615import com.intellij.ui.SimpleListCellRenderer
1716import com.intellij.ui.components.JBList
17+ import com.intellij.ui.treeStructure.Tree
1818import com.simiacryptus.jopenai.models.ChatModel
1919import com.simiacryptus.skyenet.core.platform.Session
2020import icons.MyIcons
2121import kotlinx.coroutines.CoroutineScope
22- import java.awt.BorderLayout
23- import java.awt.Component
24- import java.awt.Cursor
25- import java.awt.FlowLayout
26- import java.awt.GridLayout
27- import java.awt.Toolkit
22+ import java.awt.*
2823import java.awt.datatransfer.StringSelection
2924import java.awt.event.MouseAdapter
3025import java.awt.event.MouseEvent
3126import java.net.URI
3227import javax.swing.*
28+ import javax.swing.tree.DefaultMutableTreeNode
29+ import javax.swing.tree.DefaultTreeModel
30+ import javax.swing.tree.TreePath
31+ import javax.swing.tree.TreeSelectionModel
3332
3433class SettingsWidgetFactory : StatusBarWidgetFactory {
3534
3635 class SettingsWidget : StatusBarWidget , StatusBarWidget .MultipleTextValuesPresentation {
3736
3837 private var statusBar: StatusBar ? = null
39- private val smartModelList = createModelList()
40- private val fastModelList = createModelList()
38+ private val smartModelTree by lazy { createModelTree( " Smart Model " , AppSettingsState .instance.smartModel) }
39+ private val fastModelTree by lazy { createModelTree( " Fast Model " , AppSettingsState .instance.fastModel) }
4140 private var project: Project ? = null
42- private val sessionsList = JList <Session >()
41+ private val sessionsList = JBList <Session >()
4342 private val sessionsListModel = DefaultListModel <Session >()
43+ private fun createModelTree (title : String , selectedModel : String? ): JTree {
44+ val root = DefaultMutableTreeNode (title)
45+ val providers = models().groupBy { it.second.provider }
46+ for ((provider, models) in providers) {
47+ val providerNode = DefaultMutableTreeNode (provider.name)
48+ for (model in models) {
49+ val modelNode = DefaultMutableTreeNode (model.second.modelName)
50+ providerNode.add(modelNode)
51+ }
52+ root.add(providerNode)
53+ }
54+ val treeModel = DefaultTreeModel (root)
55+ val tree = Tree (treeModel)
56+ tree.selectionModel.selectionMode = TreeSelectionModel .SINGLE_TREE_SELECTION
57+ tree.isRootVisible = false
58+ tree.showsRootHandles = true
59+ tree.addTreeSelectionListener {
60+ val selectedPath = tree.selectionPath
61+ if (selectedPath != null && selectedPath.pathCount == 3 ) { // Provider -> Model
62+ val modelName = selectedPath.lastPathComponent.toString()
63+ when (title) {
64+ " Smart Model" -> AppSettingsState .instance.smartModel = modelName
65+ " Fast Model" -> AppSettingsState .instance.fastModel = modelName
66+ }
67+ statusBar?.updateWidget(ID ())
68+ }
69+ }
70+ // Expand and select the node if a model is selected
71+ if (selectedModel != null ) {
72+ SwingUtilities .invokeLater {
73+ setSelectedModel(tree, selectedModel)
74+ }
75+ }
76+ return tree
77+ }
78+
4479 private val temperatureSlider by lazy {
4580 val slider = JSlider (0 , 100 , (AppSettingsState .instance.temperature * 100 ).toInt())
4681 slider.addChangeListener { AppSettingsState .instance.temperature = slider.value / 100.0 }
@@ -150,25 +185,28 @@ class SettingsWidgetFactory : StatusBarWidgetFactory {
150185 }
151186 }
152187
153- private fun createModelList (): JBList <String > {
154- val list = JBList (CollectionListModel (models().map { it?.modelName ? : " " }))
155- list.cellRenderer = getRenderer()
156- list.visibleRowCount = 20
157- return list
158- }
188+ // Removed createModelList() as we are using tree views instead
159189
160190
161191 init {
162192 AppSettingsState .instance.addOnSettingsLoadedListener {
163193 statusBar?.updateWidget(ID ())
164194 }
165- // Initialize selection for both lists
166- smartModelList.setSelectedValue(AppSettingsState .instance.smartModel, true )
167- fastModelList.setSelectedValue(AppSettingsState .instance.fastModel, true )
195+ // Initialize selection for both trees on EDT
196+ if (AppSettingsState .instance.smartModel.isNotEmpty()) {
197+ SwingUtilities .invokeLater {
198+ setSelectedModel(smartModelTree, AppSettingsState .instance.smartModel)
199+ }
200+ }
201+ if (AppSettingsState .instance.fastModel.isNotEmpty()) {
202+ SwingUtilities .invokeLater {
203+ setSelectedModel(fastModelTree, AppSettingsState .instance.fastModel)
204+ }
205+ }
168206 }
169207
170- fun models () = ChatModel .values().filter { it.value != null && isVisible(it.value!! ) }
171- .entries. sortedBy { " ${it.value !! .provider.name} - ${it.value !! .modelName} " }.map { it.value }.toList()
208+ fun models () = ChatModel .values().filter { it.value != null && isVisible(it.value!! ) }.toList()
209+ .sortedBy { " ${it.second .provider.name} - ${it.second .modelName} " }
172210
173211 override fun ID (): String {
174212 return " AICodingAssistant.SettingsWidget"
@@ -214,12 +252,30 @@ class SettingsWidgetFactory : StatusBarWidgetFactory {
214252 ) {
215253 text = value // Here you can add more customization if needed
216254 if (value != null ) {
217- val model = models().find { it?.modelName == value }
218- text = " <html><b>${model?.provider?.name} </b> - <i>$value </i></html>" // Enhance label formatting
255+ val model = models().find { it.second.modelName == value }
256+ text = " <html><b>${model?.second?.provider?.name} </b> - <i>$value </i></html>" // Enhance label formatting
257+ }
258+ }
259+ }
260+
261+ private fun setSelectedModel (tree : JTree , modelName : String ) {
262+ val root = tree.model as DefaultTreeModel
263+ val rootNode = root.root as DefaultMutableTreeNode
264+ for (i in 0 until rootNode.childCount) {
265+ val providerNode = rootNode.getChildAt(i) as DefaultMutableTreeNode
266+ for (j in 0 until providerNode.childCount) {
267+ val modelNode = providerNode.getChildAt(j) as DefaultMutableTreeNode
268+ if (modelNode.userObject == modelName) {
269+ val path = TreePath (modelNode.path)
270+ tree.selectionPath = path
271+ tree.scrollPathToVisible(path)
272+ break
273+ }
219274 }
220275 }
221276 }
222277
278+
223279 override fun getPopup (): JBPopup {
224280
225281 val panel = JPanel (BorderLayout ())
@@ -228,11 +284,11 @@ class SettingsWidgetFactory : StatusBarWidgetFactory {
228284 val tabbedPane = JTabbedPane ()
229285 // Smart model tab
230286 val smartModelPanel = JPanel (BorderLayout ())
231- smartModelPanel.add(JScrollPane (smartModelList ), BorderLayout .CENTER )
287+ smartModelPanel.add(JScrollPane (smartModelTree ), BorderLayout .CENTER )
232288 tabbedPane.addTab(" Smart Model" , smartModelPanel)
233289 // Fast model tab
234290 val fastModelPanel = JPanel (BorderLayout ())
235- fastModelPanel.add(JScrollPane (fastModelList ), BorderLayout .CENTER )
291+ fastModelPanel.add(JScrollPane (fastModelTree ), BorderLayout .CENTER )
236292 tabbedPane.addTab(" Fast Model" , fastModelPanel)
237293 // Add server control tab
238294 tabbedPane.addTab(" Server" , createServerControlPanel())
@@ -250,27 +306,16 @@ class SettingsWidgetFactory : StatusBarWidgetFactory {
250306 }
251307 })
252308
253- smartModelList.addListSelectionListener {
254- val selectedValue = smartModelList.selectedValue
255- if (selectedValue != null ) {
256- AppSettingsState .instance.smartModel = selectedValue
257- statusBar?.updateWidget(ID ())
258- }
259- }
309+ // Removed smartModelList selection listener as tree handles it
260310
261- fastModelList.addListSelectionListener {
262- val selectedValue = fastModelList.selectedValue
263- if (selectedValue != null ) {
264- AppSettingsState .instance.fastModel = selectedValue
265- statusBar?.updateWidget(ID ())
266- }
267- }
311+ // Removed fastModelList selection listener as tree handles it
268312 return popup
269313 }
270314
315+ // Optionally, update getSelectedValue to reflect selected models from trees
271316 override fun getSelectedValue (): String {
272- // return "${AppSettingsState.instance.smartModel} / ${AppSettingsState.instance.fastModel}"
273- return " ${ AppSettingsState .instance.smartModel} "
317+ // return "Smart: ${AppSettingsState.instance.smartModel} | Fast: ${AppSettingsState.instance.fastModel}"
318+ return AppSettingsState .instance.smartModel
274319 }
275320
276321 override fun getTooltipText (): String {
@@ -285,12 +330,10 @@ class SettingsWidgetFactory : StatusBarWidgetFactory {
285330 serverStatus
286331 }
287332
288- companion object {
289- fun isVisible (it : ChatModel ): Boolean {
290- val hasApiKey =
291- AppSettingsState .instance.apiKey?.filter { it.value.isNotBlank() }?.keys?.contains(it.provider.name)
292- return false != hasApiKey
293- }
333+ // Companion object removed, making isVisible a regular function
334+ private fun isVisible (it : ChatModel ): Boolean {
335+ // Temporarily allow all models to be visible for debugging
336+ return true
294337 }
295338
296339 }
@@ -303,16 +346,12 @@ class SettingsWidgetFactory : StatusBarWidgetFactory {
303346 return " AI Coding Assistant Settings"
304347 }
305348
306- companion object {
307- val settingsWidget = SettingsWidget ()
308- }
309-
310349 override fun createWidget (project : Project , scope : CoroutineScope ): StatusBarWidget {
311- return settingsWidget
350+ return SettingsWidget ()
312351 }
313352
314353 override fun createWidget (project : Project ): StatusBarWidget {
315- return settingsWidget
354+ return SettingsWidget ()
316355 }
317356
318357 override fun isAvailable (project : Project ): Boolean {
0 commit comments