@@ -5,6 +5,8 @@ import cc.unitmesh.devti.gui.AutoDevToolWindowFactory
5
5
import cc.unitmesh.devti.gui.chat.message.ChatActionType
6
6
import cc.unitmesh.devti.observer.agent.AgentStateService
7
7
import cc.unitmesh.devti.observer.agent.PlanList
8
+ import cc.unitmesh.devti.observer.agent.PlanTask
9
+ import cc.unitmesh.devti.observer.agent.TaskStatus
8
10
import cc.unitmesh.devti.observer.plan.PlanBoard
9
11
import cc.unitmesh.devti.sketch.ui.code.CodeHighlightSketch
10
12
import cc.unitmesh.devti.sketch.ui.plan.MarkdownPlanParser
@@ -119,18 +121,34 @@ class PlanSketch(
119
121
border = JBUI .Borders .empty()
120
122
}
121
123
122
- val checkbox = JBCheckBox ().apply {
123
- isSelected = task.completed
124
- addActionListener {
125
- task.completed = isSelected
124
+ // First create task label with appropriate styling based on status
125
+ val taskLabel = createStyledTaskLabel(task)
126
+
127
+ // Create a custom status indicator based on task status
128
+ val statusIcon = when (task.status) {
129
+ TaskStatus .COMPLETED -> JLabel (AllIcons .Actions .Checked )
130
+ TaskStatus .FAILED -> JLabel (AllIcons .General .Error )
131
+ TaskStatus .IN_PROGRESS -> JLabel (AllIcons .Actions .Execute )
132
+ TaskStatus .TODO -> JBCheckBox ().apply {
133
+ isSelected = task.completed
134
+ addActionListener {
135
+ task.completed = isSelected
136
+ if (isSelected) {
137
+ task.updateStatus(TaskStatus .COMPLETED )
138
+ } else {
139
+ task.updateStatus(TaskStatus .TODO )
140
+ }
141
+ updateTaskLabel(taskLabel, task)
142
+ }
143
+ isBorderPainted = false
144
+ isContentAreaFilled = false
126
145
}
127
- isBorderPainted = false
128
- isContentAreaFilled = false
129
146
}
147
+
148
+ taskPanel.add(statusIcon)
130
149
131
- taskPanel.add(checkbox)
132
-
133
- if (! task.completed) {
150
+ // Add execute button for incomplete tasks
151
+ if (task.status == TaskStatus .TODO || task.status == TaskStatus .IN_PROGRESS ) {
134
152
val executeButton = JButton (AllIcons .Actions .Execute ).apply {
135
153
border = BorderFactory .createEmptyBorder()
136
154
preferredSize = Dimension (24 , 24 )
@@ -145,23 +163,51 @@ class PlanSketch(
145
163
146
164
taskPanel.add(executeButton)
147
165
}
148
-
149
- val taskLabel = JLabel (if (task.completed)
150
- " <html><strike>${task.description} </strike></html>"
151
- else task.description
152
- ).apply {
153
- border = JBUI .Borders .emptyLeft(5 )
166
+
167
+ taskPanel.add(taskLabel)
168
+
169
+ // Add context menu for changing task status
170
+ val taskPopupMenu = JPopupMenu ()
171
+ val markCompletedItem = JMenuItem (" Mark as Completed [✓]" )
172
+ val markInProgressItem = JMenuItem (" Mark as In Progress [*]" )
173
+ val markFailedItem = JMenuItem (" Mark as Failed [!]" )
174
+ val markTodoItem = JMenuItem (" Mark as Todo [ ]" )
175
+
176
+ markCompletedItem.addActionListener {
177
+ task.updateStatus(TaskStatus .COMPLETED )
178
+ updateTaskLabel(taskLabel, task)
179
+ contentPanel.revalidate()
180
+ contentPanel.repaint()
154
181
}
155
182
156
- checkbox .addActionListener {
157
- taskLabel.text = if (checkbox.isSelected )
158
- " <html><strike> ${ task.description} </strike></html> "
159
- else
160
- task.description
183
+ markInProgressItem .addActionListener {
184
+ task.updateStatus( TaskStatus . IN_PROGRESS )
185
+ updateTaskLabel(taskLabel, task)
186
+ contentPanel.revalidate()
187
+ contentPanel.repaint()
161
188
}
162
189
163
- taskPanel.add(taskLabel)
164
-
190
+ markFailedItem.addActionListener {
191
+ task.updateStatus(TaskStatus .FAILED )
192
+ updateTaskLabel(taskLabel, task)
193
+ contentPanel.revalidate()
194
+ contentPanel.repaint()
195
+ }
196
+
197
+ markTodoItem.addActionListener {
198
+ task.updateStatus(TaskStatus .TODO )
199
+ updateTaskLabel(taskLabel, task)
200
+ contentPanel.revalidate()
201
+ contentPanel.repaint()
202
+ }
203
+
204
+ taskPopupMenu.add(markCompletedItem)
205
+ taskPopupMenu.add(markInProgressItem)
206
+ taskPopupMenu.add(markFailedItem)
207
+ taskPopupMenu.add(markTodoItem)
208
+
209
+ taskLabel.componentPopupMenu = taskPopupMenu
210
+
165
211
contentPanel.add(taskPanel)
166
212
}
167
213
@@ -171,6 +217,30 @@ class PlanSketch(
171
217
}
172
218
}
173
219
220
+ // Helper method to create a styled task label based on status
221
+ private fun createStyledTaskLabel (task : PlanTask ): JLabel {
222
+ val labelText = when (task.status) {
223
+ TaskStatus .COMPLETED -> " <html><strike>${task.description} </strike></html>"
224
+ TaskStatus .FAILED -> " <html><span style='color:red'>${task.description} </span></html>"
225
+ TaskStatus .IN_PROGRESS -> " <html><span style='color:blue;font-style:italic'>${task.description} </span></html>"
226
+ TaskStatus .TODO -> task.description
227
+ }
228
+
229
+ return JLabel (labelText).apply {
230
+ border = JBUI .Borders .emptyLeft(5 )
231
+ }
232
+ }
233
+
234
+ // Helper method to update the task label based on current status
235
+ private fun updateTaskLabel (label : JLabel , task : PlanTask ) {
236
+ label.text = when (task.status) {
237
+ TaskStatus .COMPLETED -> " <html><strike>${task.description} </strike></html>"
238
+ TaskStatus .FAILED -> " <html><span style='color:red'>${task.description} </span></html>"
239
+ TaskStatus .IN_PROGRESS -> " <html><span style='color:blue;font-style:italic'>${task.description} </span></html>"
240
+ TaskStatus .TODO -> task.description
241
+ }
242
+ }
243
+
174
244
override fun getExtensionName (): String = " ThoughtPlan"
175
245
176
246
override fun getViewText (): String = content
@@ -186,11 +256,12 @@ class PlanSketch(
186
256
187
257
fun updatePlan (newPlanItems : List <PlanList >) {
188
258
if (newPlanItems.isNotEmpty()) {
189
- val completionState = mutableMapOf<String , Boolean >()
259
+ // Save current states of all tasks
260
+ val taskStateMap = mutableMapOf<String , Pair <Boolean , TaskStatus >>()
190
261
191
262
planLists.forEach { planItem ->
192
263
planItem.planTasks.forEach { task ->
193
- completionState [task.description] = task.completed
264
+ taskStateMap [task.description] = Pair ( task.completed, task.status)
194
265
}
195
266
}
196
267
@@ -201,9 +272,10 @@ class PlanSketch(
201
272
planLists.add(newItem)
202
273
203
274
newItem.planTasks.forEach { task ->
204
- val savedCompletionState = completionState[task.description]
205
- if (savedCompletionState != null ) {
206
- task.completed = savedCompletionState
275
+ // Restore saved states if available
276
+ taskStateMap[task.description]?.let { (completed, status) ->
277
+ task.completed = completed
278
+ task.status = status
207
279
}
208
280
}
209
281
}
0 commit comments