@@ -149,6 +149,7 @@ class McpConfigPopup {
149149 .setResizable(true )
150150 .setMovable(true )
151151 .setRequestFocus(true )
152+ .setCancelOnClickOutside(false )
152153 .createPopup()
153154
154155 if (component != null ) {
@@ -183,7 +184,7 @@ class McpConfigPopup {
183184 rootNode.removeAllChildren()
184185 val loadingNode = CheckedTreeNode (" Loading tools..." )
185186 rootNode.add(loadingNode)
186- treeModel.reload()
187+ treeModel.reload(rootNode) // Reload to show the loading node
187188 expandAllNodes(tree)
188189
189190 CoroutineScope (Dispatchers .IO ).launch {
@@ -193,35 +194,59 @@ class McpConfigPopup {
193194 val selectedTools = configService.getSelectedTools()
194195
195196 invokeLater {
196- rootNode.removeAllChildren()
197+ rootNode.removeAllChildren() // Remove "Loading tools..." node
197198
198- allTools.forEach { (serverName, tools) ->
199- val serverNode = ServerTreeNode (serverName)
200- rootNode.add(serverNode)
199+ if (allTools.isEmpty()) {
200+ val noToolsNode = CheckedTreeNode (" No tools available." )
201+ rootNode.add(noToolsNode)
202+ } else {
203+ allTools.forEach { (serverName, tools) ->
204+ val serverNode = ServerTreeNode (serverName)
205+ rootNode.add(serverNode)
201206
202- tools.forEach { tool ->
203- val toolNode = ToolTreeNode (serverName, tool)
204- val isSelected = selectedTools[serverName]?.contains(tool.name) == true
205- toolNode.isChecked = isSelected
206- serverNode.add(toolNode)
207+ if (tools.isEmpty()) {
208+ val noToolsForServerNode = CheckedTreeNode (" No tools from this server." )
209+ serverNode.add(noToolsForServerNode)
210+ } else {
211+ tools.forEach { tool ->
212+ val toolNode = ToolTreeNode (serverName, tool)
213+ val isSelected = selectedTools[serverName]?.contains(tool.name) == true
214+ toolNode.isChecked = isSelected
215+ serverNode.add(toolNode)
216+ }
217+ }
207218 }
208219 }
209220
210- treeModel.reload()
221+ treeModel.nodeStructureChanged(rootNode) // Notify that rootNode's children changed
211222 expandAllNodes(tree)
212- tree.repaint() // 添加显式重绘
223+
213224 loadingPanel.stopLoading()
214- loadingPanel.revalidate() // 确保布局更新
225+
226+ tree.revalidate() // Ensure tree layout is updated
227+ tree.repaint()
228+ loadingPanel.revalidate()
229+ loadingPanel.repaint()
230+ // Also revalidate and repaint parent in case its layout depends on loadingPanel
231+ (loadingPanel.parent as ? JComponent )?.revalidate()
232+ (loadingPanel.parent as ? JComponent )?.repaint()
215233 }
216234 } catch (e: Exception ) {
217235 invokeLater {
218236 rootNode.removeAllChildren()
219237 val errorNode = CheckedTreeNode (" Error loading tools: ${e.message} " )
220238 rootNode.add(errorNode)
221- treeModel.reload()
222- tree.repaint() // 添加显式重绘
239+ treeModel.nodeStructureChanged(rootNode) // Notify change
240+ expandAllNodes(tree)
241+
223242 loadingPanel.stopLoading()
224- loadingPanel.revalidate() // 确保布局更新
243+
244+ tree.revalidate()
245+ tree.repaint()
246+ loadingPanel.revalidate()
247+ loadingPanel.repaint()
248+ (loadingPanel.parent as ? JComponent )?.revalidate()
249+ (loadingPanel.parent as ? JComponent )?.repaint()
225250 }
226251 }
227252 }
@@ -248,15 +273,12 @@ class McpConfigPopup {
248273 }
249274
250275 private fun filterTree (tree : CheckboxTree , rootNode : CheckedTreeNode , searchText : String ) {
251- // Simple implementation - in a real scenario, you might want more sophisticated filtering
252276 tree.expandPath(TreePath (rootNode.path))
253277 }
254278
255279 private fun expandAllNodes (tree : CheckboxTree ) {
256280 for (i in 0 until tree.rowCount) {
257281 tree.expandRow(i)
258282 }
259-
260- tree.updateUI()
261283 }
262- }
284+ }
0 commit comments