1
1
package cc.unitmesh.devti.gui.planner
2
2
3
+ import com.intellij.icons.AllIcons
3
4
import com.intellij.openapi.project.Project
4
5
import com.intellij.openapi.vcs.changes.Change
6
+ import com.intellij.ui.HyperlinkLabel
5
7
import com.intellij.ui.components.JBLabel
6
8
import com.intellij.ui.components.JBScrollPane
7
9
import com.intellij.util.ui.JBUI
8
10
import com.intellij.util.ui.UIUtil
9
11
import java.awt.BorderLayout
12
+ import java.awt.FlowLayout
10
13
import java.awt.GridLayout
14
+ import java.awt.event.MouseAdapter
15
+ import java.awt.event.MouseEvent
11
16
import javax.swing.JPanel
17
+ import javax.swing.event.HyperlinkEvent
18
+ import javax.swing.event.HyperlinkListener
12
19
13
20
class PlannerResultSummary (
14
21
private val project : Project ,
15
22
private var changes : List <Change >
16
23
) : JPanel(BorderLayout ()) {
17
- private val changesPanel = JPanel (GridLayout (0 , 1 , 0 , 5 ))
24
+ private val changesPanel = JPanel (GridLayout (0 , 1 , 0 , 1 ))
18
25
private val statsLabel = JBLabel (" No changes" )
26
+
27
+ interface ChangeActionListener {
28
+ fun onView (change : Change )
29
+ fun onDiscard (change : Change )
30
+ fun onAccept (change : Change )
31
+ fun onRemove (change : Change )
32
+ }
33
+
34
+ interface GlobalActionListener {
35
+ fun onDiscardAll ()
36
+ fun onAcceptAll ()
37
+ }
38
+
39
+ private var changeActionListener: ChangeActionListener ? = null
40
+ private var globalActionListener: GlobalActionListener ? = null
19
41
20
42
init {
21
43
background = JBUI .CurrentTheme .ToolWindow .background()
@@ -24,20 +46,61 @@ class PlannerResultSummary(
24
46
val titlePanel = JPanel (BorderLayout ()).apply {
25
47
isOpaque = false
26
48
border = JBUI .Borders .emptyBottom(10 )
27
- add(JBLabel (" Change list" ).apply {
28
- foreground = UIUtil .getLabelForeground()
29
- }, BorderLayout .WEST )
30
- add(statsLabel, BorderLayout .EAST )
49
+
50
+ val titleLabelPanel = JPanel (BorderLayout ()).apply {
51
+ isOpaque = false
52
+ add(JBLabel (" Change list" ).apply {
53
+ foreground = UIUtil .getLabelForeground()
54
+ font = JBUI .Fonts .label().asBold()
55
+ }, BorderLayout .WEST )
56
+ add(statsLabel, BorderLayout .EAST )
57
+ }
58
+
59
+ val actionsPanel = JPanel (FlowLayout (FlowLayout .RIGHT , 5 , 0 )).apply {
60
+ isOpaque = false
61
+
62
+ val discardAllButton = HyperlinkLabel (" Discard all" ).apply {
63
+ icon = AllIcons .Actions .Cancel
64
+ addHyperlinkListener(object : HyperlinkListener {
65
+ override fun hyperlinkUpdate (e : HyperlinkEvent ) {
66
+ if (e.eventType == HyperlinkEvent .EventType .ACTIVATED ) {
67
+ globalActionListener?.onDiscardAll()
68
+ }
69
+ }
70
+ })
71
+ }
72
+
73
+ val acceptAllButton = HyperlinkLabel (" Accept all" ).apply {
74
+ icon = AllIcons .Actions .Commit
75
+ addHyperlinkListener(object : HyperlinkListener {
76
+ override fun hyperlinkUpdate (e : HyperlinkEvent ) {
77
+ if (e.eventType == HyperlinkEvent .EventType .ACTIVATED ) {
78
+ globalActionListener?.onAcceptAll()
79
+ }
80
+ }
81
+ })
82
+ }
83
+
84
+ add(discardAllButton)
85
+ add(acceptAllButton)
86
+ }
87
+
88
+ add(titleLabelPanel, BorderLayout .WEST )
89
+ add(actionsPanel, BorderLayout .EAST )
31
90
}
32
91
33
92
add(titlePanel, BorderLayout .NORTH )
34
93
35
94
changesPanel.isOpaque = false
36
- add(JBScrollPane (changesPanel).apply {
95
+ changesPanel.border = JBUI .Borders .empty(1 )
96
+
97
+ val scrollPane = JBScrollPane (changesPanel).apply {
37
98
border = JBUI .Borders .empty()
38
99
background = background
39
- }, BorderLayout .CENTER )
40
-
100
+ viewport.background = background
101
+ }
102
+
103
+ add(scrollPane, BorderLayout .CENTER )
41
104
updateChanges(changes.toMutableList())
42
105
}
43
106
@@ -46,27 +109,19 @@ class PlannerResultSummary(
46
109
changesPanel.removeAll()
47
110
48
111
if (changes.isEmpty()) {
49
- statsLabel.text = " No changes"
112
+ statsLabel.text = " No changes"
50
113
changesPanel.add(JBLabel (" No code changes" ).apply {
51
114
foreground = UIUtil .getLabelDisabledForeground()
115
+ border = JBUI .Borders .empty(10 )
52
116
})
53
117
} else {
54
- statsLabel.text = " total ${changes.size} files changed"
55
-
118
+ statsLabel.text = " (Total ${changes.size} files changed)"
56
119
changes.forEach { change ->
57
120
val filePath = change.virtualFile?.path ? : " Unknown"
58
121
val fileName = filePath.substringAfterLast(' /' )
59
122
60
- val changeType = when {
61
- change.type == Change .Type .NEW -> " Add"
62
- change.type == Change .Type .DELETED -> " Delete"
63
- change.type == Change .Type .MOVED -> " Move"
64
- else -> " Modify"
65
- }
66
-
67
- changesPanel.add(JBLabel (" $changeType : $fileName " ).apply {
68
- toolTipText = filePath
69
- })
123
+ val changePanel = createChangeItemPanel(change, fileName, filePath)
124
+ changesPanel.add(changePanel)
70
125
}
71
126
}
72
127
@@ -77,4 +132,111 @@ class PlannerResultSummary(
77
132
revalidate()
78
133
repaint()
79
134
}
135
+
136
+ private fun createChangeItemPanel (change : Change , fileName : String , filePath : String ): JPanel {
137
+ return JPanel (BorderLayout ()).apply {
138
+ isOpaque = true
139
+ background = UIUtil .getListBackground()
140
+ border = JBUI .Borders .empty(5 , 8 )
141
+
142
+ val changeIcon = when (change.type) {
143
+ Change .Type .NEW -> AllIcons .Actions .New
144
+ Change .Type .DELETED -> AllIcons .Actions .GC
145
+ Change .Type .MOVED -> AllIcons .Actions .Forward
146
+ else -> AllIcons .Actions .Edit
147
+ }
148
+
149
+ val infoPanel = JPanel (BorderLayout ()).apply {
150
+ isOpaque = false
151
+
152
+ val fileLabel = JBLabel (fileName, changeIcon, JBLabel .LEFT ).apply {
153
+ toolTipText = filePath
154
+ }
155
+
156
+ add(fileLabel, BorderLayout .CENTER )
157
+ }
158
+
159
+ val actionsPanel = JPanel (FlowLayout (FlowLayout .RIGHT , 2 , 0 )).apply {
160
+ isOpaque = false
161
+
162
+ val viewButton = HyperlinkLabel (" " ).apply {
163
+ icon = AllIcons .Actions .Preview
164
+ toolTipText = " View changes"
165
+ addHyperlinkListener(object : HyperlinkListener {
166
+ override fun hyperlinkUpdate (e : HyperlinkEvent ) {
167
+ if (e.eventType == HyperlinkEvent .EventType .ACTIVATED ) {
168
+ changeActionListener?.onView(change)
169
+ }
170
+ }
171
+ })
172
+ }
173
+
174
+ val discardButton = HyperlinkLabel (" " ).apply {
175
+ icon = AllIcons .Actions .Cancel
176
+ toolTipText = " Discard changes"
177
+ addHyperlinkListener(object : HyperlinkListener {
178
+ override fun hyperlinkUpdate (e : HyperlinkEvent ) {
179
+ if (e.eventType == HyperlinkEvent .EventType .ACTIVATED ) {
180
+ changeActionListener?.onDiscard(change)
181
+ }
182
+ }
183
+ })
184
+ }
185
+
186
+ val acceptButton = HyperlinkLabel (" " ).apply {
187
+ icon = AllIcons .Actions .Commit
188
+ toolTipText = " Accept changes"
189
+ addHyperlinkListener(object : HyperlinkListener {
190
+ override fun hyperlinkUpdate (e : HyperlinkEvent ) {
191
+ if (e.eventType == HyperlinkEvent .EventType .ACTIVATED ) {
192
+ changeActionListener?.onAccept(change)
193
+ }
194
+ }
195
+ })
196
+ }
197
+
198
+ val removeButton = HyperlinkLabel (" " ).apply {
199
+ icon = AllIcons .Actions .GC
200
+ toolTipText = " Remove from list"
201
+ addHyperlinkListener(object : HyperlinkListener {
202
+ override fun hyperlinkUpdate (e : HyperlinkEvent ) {
203
+ if (e.eventType == HyperlinkEvent .EventType .ACTIVATED ) {
204
+ changeActionListener?.onRemove(change)
205
+ }
206
+ }
207
+ })
208
+ }
209
+
210
+ add(viewButton)
211
+ add(discardButton)
212
+ add(acceptButton)
213
+ add(removeButton)
214
+ }
215
+
216
+ add(infoPanel, BorderLayout .CENTER )
217
+ add(actionsPanel, BorderLayout .EAST )
218
+
219
+ // Add hover effect
220
+ addMouseListener(object : MouseAdapter () {
221
+ override fun mouseEntered (e : MouseEvent ) {
222
+ background = UIUtil .getListSelectionBackground(false )
223
+ repaint()
224
+ }
225
+
226
+ override fun mouseExited (e : MouseEvent ) {
227
+ background = UIUtil .getListBackground()
228
+ repaint()
229
+ }
230
+ })
231
+ }
232
+ }
233
+
234
+ // Set action listeners
235
+ fun setChangeActionListener (listener : ChangeActionListener ) {
236
+ this .changeActionListener = listener
237
+ }
238
+
239
+ fun setGlobalActionListener (listener : GlobalActionListener ) {
240
+ this .globalActionListener = listener
241
+ }
80
242
}
0 commit comments