@@ -9,6 +9,7 @@ import com.intellij.openapi.project.Project
9
9
import com.intellij.openapi.vfs.VirtualFile
10
10
import java.util.EventListener
11
11
import javax.swing.DefaultListModel
12
+ import java.awt.Point
12
13
13
14
/* *
14
15
* ViewModel for managing the list of file presentations.
@@ -22,6 +23,12 @@ class FileListViewModel(private val project: Project) : Disposable {
22
23
fun onListCleared ()
23
24
}
24
25
26
+ enum class FileActionType {
27
+ INSERT ,
28
+ REMOVE ,
29
+ NONE
30
+ }
31
+
25
32
private val listeners = mutableListOf<FileListChangeListener >()
26
33
27
34
fun addChangeListener (listener : FileListChangeListener ) {
@@ -91,6 +98,73 @@ class FileListViewModel(private val project: Project) : Disposable {
91
98
}
92
99
}
93
100
101
+ /* *
102
+ * Handles file operations based on the action type.
103
+ *
104
+ * @param filePresentation The file presentation to operate on
105
+ * @param actionType The type of action to perform
106
+ * @param callback Callback to handle UI-specific operations
107
+ * @return True if an action was performed, false otherwise
108
+ */
109
+ fun handleFileAction (filePresentation : FilePresentation ,
110
+ actionType : FileActionType ,
111
+ callback : (VirtualFile , String? ) -> Unit ): Boolean {
112
+ when (actionType) {
113
+ FileActionType .INSERT -> {
114
+ val vfile = filePresentation.virtualFile
115
+ if (! vfile.isValid) return false
116
+
117
+ // Get relative path for display
118
+ val relativePath = try {
119
+ project.basePath?.let { basePath ->
120
+ vfile.path.substringAfter(basePath).removePrefix(" /" )
121
+ } ? : vfile.path
122
+ } catch (e: Exception ) {
123
+ vfile.path
124
+ }
125
+
126
+ // Remove and re-add to prioritize
127
+ removeFile(filePresentation)
128
+ addFileIfAbsent(vfile)
129
+
130
+ // Call back to UI with file and path
131
+ callback(vfile, relativePath)
132
+
133
+ // Remove from list after processing
134
+ removeFileByVirtualFile(vfile)
135
+ return true
136
+ }
137
+ FileActionType .REMOVE -> {
138
+ removeFile(filePresentation)
139
+ return true
140
+ }
141
+ FileActionType .NONE -> return false
142
+ }
143
+ }
144
+
145
+ /* *
146
+ * Determines the appropriate action for a file based on component coordinates.
147
+ *
148
+ * @param filePresentation The file presentation
149
+ * @param componentPoint The local point in the component
150
+ * @param componentBounds The bounds of the component cell
151
+ * @return The appropriate action type
152
+ */
153
+ fun determineFileAction (filePresentation : FilePresentation , componentPoint : Point ,
154
+ componentBounds : java.awt.Rectangle ): FileActionType {
155
+ // Extract component hit detection logic
156
+ val hitComponent = filePresentation.panel?.components?.firstOrNull {
157
+ it.contains(componentPoint.x - componentBounds.x - it.x, it.height - 1 )
158
+ }
159
+
160
+ return when {
161
+ hitComponent is javax.swing.JPanel -> FileActionType .INSERT
162
+ hitComponent is javax.swing.JLabel &&
163
+ hitComponent.icon == com.intellij.icons.AllIcons .Actions .Close -> FileActionType .REMOVE
164
+ else -> FileActionType .NONE
165
+ }
166
+ }
167
+
94
168
override fun dispose () {
95
169
listeners.clear()
96
170
}
0 commit comments