@@ -25,8 +25,12 @@ import com.intellij.openapi.ui.popup.JBPopupFactory
25
25
import com.intellij.openapi.ui.popup.JBPopup
26
26
import com.intellij.openapi.roots.ProjectRootManager
27
27
import com.intellij.openapi.vfs.VfsUtil
28
+ import com.intellij.ui.awt.RelativePoint
28
29
import com.intellij.util.ui.UIUtil
29
30
import org.jetbrains.annotations.NotNull
31
+ import javax.swing.Box
32
+ import javax.swing.BoxLayout
33
+ import javax.swing.JComponent
30
34
31
35
class WorkspacePanel (
32
36
private val project : Project ,
@@ -52,15 +56,16 @@ class WorkspacePanel(
52
56
addButton.border = JBUI .Borders .empty(2 , 4 )
53
57
addButton.background = JBColor (0xEDF4FE , 0x313741 )
54
58
addButton.isOpaque = true
59
+
55
60
addButton.addMouseListener(object : MouseAdapter () {
56
61
override fun mouseClicked (e : MouseEvent ) {
57
- showFileSearchPopup(e.component )
62
+ showFileSearchPopup(this @WorkspacePanel )
58
63
}
59
64
})
60
65
return addButton
61
66
}
62
67
63
- private fun showFileSearchPopup (component : Component ) {
68
+ private fun showFileSearchPopup (component : JComponent ) {
64
69
val popup = FileSearchPopup (project) { files ->
65
70
for (file in files) {
66
71
addFileToWorkspace(file)
@@ -135,6 +140,7 @@ class FileSearchPopup(
135
140
private val searchField = JTextField ()
136
141
private val contentPanel = JPanel (BorderLayout ())
137
142
private val allProjectFiles = mutableListOf<FileItem >()
143
+ private val minPopupSize = Dimension (435 , 300 )
138
144
139
145
init {
140
146
loadProjectFiles()
@@ -157,7 +163,6 @@ class FileSearchPopup(
157
163
}
158
164
159
165
private fun setupUI () {
160
- // Setup search field
161
166
searchField.document.addDocumentListener(object : DocumentListener {
162
167
override fun insertUpdate (e : DocumentEvent ) = updateSearch()
163
168
override fun removeUpdate (e : DocumentEvent ) = updateSearch()
@@ -185,7 +190,7 @@ class FileSearchPopup(
185
190
// Layout components
186
191
contentPanel.add(searchField, BorderLayout .NORTH )
187
192
contentPanel.add(JScrollPane (fileList), BorderLayout .CENTER )
188
- contentPanel.preferredSize = Dimension ( 400 , 300 )
193
+ contentPanel.preferredSize = minPopupSize
189
194
}
190
195
191
196
private fun updateFileList (searchText : String ) {
@@ -203,16 +208,21 @@ class FileSearchPopup(
203
208
filteredFiles.forEach { fileListModel.addElement(it) }
204
209
}
205
210
206
- fun show (component : Component ) {
211
+ fun show (component : JComponent ) {
207
212
popup = JBPopupFactory .getInstance()
208
213
.createComponentPopupBuilder(contentPanel, searchField)
209
214
.setTitle(" Search Files" )
210
215
.setMovable(true )
211
216
.setResizable(true )
212
217
.setRequestFocus(true )
218
+ .setFocusable(true )
219
+ .setMinSize(minPopupSize)
213
220
.createPopup()
214
221
215
- popup?.showUnderneathOf(component)
222
+ val topOffset = (component.border?.getBorderInsets(component)?.top ? : 0 )
223
+ val leftOffset = (component.border?.getBorderInsets(component)?.left ? : 0 )
224
+
225
+ popup?.show(RelativePoint (component, Point (leftOffset, - minPopupSize.height + topOffset)))
216
226
}
217
227
218
228
data class FileItem (val file : VirtualFile ) {
@@ -234,15 +244,23 @@ class FileSearchPopup(
234
244
): Component {
235
245
val panel = JPanel (BorderLayout ())
236
246
value?.let {
247
+ // Create a panel with horizontal layout to display file name and path inline
248
+ val infoPanel = JPanel ()
249
+ infoPanel.layout = BoxLayout (infoPanel, BoxLayout .X_AXIS )
250
+ infoPanel.isOpaque = false
251
+
252
+ // File name with icon
237
253
val fileLabel = JBLabel (it.name, it.icon, JBLabel .LEFT )
238
- val pathLabel = JBLabel (it.path, JBLabel .LEFT )
254
+ fileLabel.border = JBUI .Borders .emptyRight(8 )
255
+
256
+ // Path with smaller, grayed-out text
257
+ val pathLabel = JBLabel (" - ${getRelativePath(it)} " , JBLabel .LEFT )
239
258
pathLabel.font = UIUtil .getFont(UIUtil .FontSize .SMALL , pathLabel.font)
240
259
pathLabel.foreground = UIUtil .getContextHelpForeground()
241
260
242
- val infoPanel = JPanel (BorderLayout ())
243
- infoPanel.add(fileLabel, BorderLayout .NORTH )
244
- infoPanel.add(pathLabel, BorderLayout .SOUTH )
245
- infoPanel.isOpaque = false
261
+ infoPanel.add(fileLabel)
262
+ infoPanel.add(pathLabel)
263
+ infoPanel.add(Box .createHorizontalGlue()) // This makes the layout adapt to width
246
264
247
265
panel.add(infoPanel, BorderLayout .CENTER )
248
266
@@ -263,6 +281,16 @@ class FileSearchPopup(
263
281
264
282
return panel
265
283
}
284
+
285
+ private fun getRelativePath (item : FileItem ): String {
286
+ // Try to make the path shorter for display purposes
287
+ return try {
288
+ val basePath = item.path.substringBeforeLast(item.name, " " )
289
+ if (basePath.isEmpty()) item.path else basePath
290
+ } catch (e: Exception ) {
291
+ item.path
292
+ }
293
+ }
266
294
}
267
295
}
268
296
@@ -382,3 +410,4 @@ class WrapLayout : FlowLayout {
382
410
}
383
411
}
384
412
}
413
+
0 commit comments