Skip to content

Commit 31c1c0b

Browse files
committed
feat(planner): add editor mode and improve plan management #331
- Introduce editor mode with save/cancel functionality for plan editing - Refactor plan panel creation and reuse logic - Simplify plan update and rendering logic - Adjust UI settings for better readability and usability
1 parent 9c0edc8 commit 31c1c0b

File tree

3 files changed

+98
-50
lines changed

3 files changed

+98
-50
lines changed

core/src/main/kotlin/cc/unitmesh/devti/gui/AutoDevPlannerToolWindowFactory.kt

Lines changed: 95 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ import java.awt.BorderLayout
3737
import java.awt.Dimension
3838
import java.awt.FontMetrics
3939
import javax.swing.JComponent
40+
import javax.swing.JPanel
41+
import javax.swing.JButton
42+
import javax.swing.Box
4043
import java.util.concurrent.atomic.AtomicBoolean
4144

4245
class AutoDevPlannerToolWindowFactory : ToolWindowFactory, ToolWindowManagerListener, DumbAware {
@@ -74,7 +77,7 @@ class AutoDevPlanerTooWindow(val project: Project) : SimpleToolWindowPanel(true,
7477
override fun getName(): @NlsActions.ActionText String? = "AutoDev Planer"
7578
var connection = ApplicationManager.getApplication().messageBus.connect(this)
7679

77-
val content = """1. 分析当前Blog功能结构(✓)
80+
var content = """1. 分析当前Blog功能结构(✓)
7881
- 当前Blog功能分散在entity(BlogPost)、service、controller层,采用贫血模型
7982
- domain.Blog类存在但未充分使用,需要明确领域模型边界
8083
@@ -100,9 +103,28 @@ class AutoDevPlanerTooWindow(val project: Project) : SimpleToolWindowPanel(true,
100103
- 修改现有测试用例
101104
- 添加领域模型单元测试"""
102105
var planSketch: PlanSketch = PlanSketch(project, content, MarkdownPlanParser.parse(content).toMutableList(), true)
106+
107+
private var markdownEditor: MarkdownLanguageField? = null
108+
private val contentPanel = JPanel(BorderLayout())
109+
private var isEditorMode = false
110+
private var currentCallback: ((String) -> Unit)? = null
111+
private val planPanel: JPanel by lazy { createPlanPanel() }
103112

104113
init {
105-
val planPanel = panel {
114+
contentPanel.add(planPanel, BorderLayout.CENTER)
115+
add(contentPanel, BorderLayout.CENTER)
116+
117+
connection.subscribe(PlanUpdateListener.TOPIC, object : PlanUpdateListener {
118+
override fun onPlanUpdate(items: MutableList<AgentTaskEntry>) {
119+
if (!isEditorMode) {
120+
planSketch.updatePlan(items)
121+
}
122+
}
123+
})
124+
}
125+
126+
private fun createPlanPanel(): JPanel {
127+
return panel {
106128
row {
107129
cell(planSketch)
108130
.fullWidth()
@@ -115,48 +137,85 @@ class AutoDevPlanerTooWindow(val project: Project) : SimpleToolWindowPanel(true,
115137
)
116138
background = JBUI.CurrentTheme.ToolWindow.background()
117139
}
140+
}
118141

119-
add(planPanel, BorderLayout.CENTER)
120-
121-
connection.subscribe(PlanUpdateListener.TOPIC, object : PlanUpdateListener {
122-
override fun onPlanUpdate(items: MutableList<AgentTaskEntry>) {
123-
planSketch.updatePlan(items)
124-
}
125-
})
142+
private fun switchToEditorView() {
143+
if (isEditorMode) return
144+
145+
if (markdownEditor == null) {
146+
markdownEditor = MarkdownLanguageField(project, content, "Edit your plan here...", "plan.md")
147+
} else {
148+
markdownEditor?.text = content
149+
}
150+
151+
val buttonPanel = JPanel(BorderLayout())
152+
val buttonsBox = Box.createHorizontalBox().apply {
153+
add(JButton("Save").apply {
154+
addActionListener {
155+
val newContent = markdownEditor?.text ?: ""
156+
switchToPlanView(newContent)
157+
currentCallback?.invoke(newContent)
158+
}
159+
})
160+
add(Box.createHorizontalStrut(10))
161+
add(JButton("Cancel").apply {
162+
addActionListener {
163+
switchToPlanView()
164+
}
165+
})
166+
}
167+
buttonPanel.add(buttonsBox, BorderLayout.EAST)
168+
buttonPanel.border = JBUI.Borders.empty(5)
169+
170+
// Switch views
171+
contentPanel.removeAll()
172+
val editorPanel = JPanel(BorderLayout())
173+
editorPanel.add(JBScrollPane(markdownEditor), BorderLayout.CENTER)
174+
editorPanel.add(buttonPanel, BorderLayout.SOUTH)
175+
176+
contentPanel.add(editorPanel, BorderLayout.CENTER)
177+
contentPanel.revalidate()
178+
contentPanel.repaint()
179+
180+
isEditorMode = true
181+
}
182+
183+
private fun switchToPlanView(newContent: String? = null) {
184+
if (newContent != null && newContent != content) {
185+
content = newContent
186+
187+
val parsedItems = MarkdownPlanParser.parse(newContent).toMutableList()
188+
planSketch.updatePlan(parsedItems)
189+
}
190+
191+
contentPanel.removeAll()
192+
contentPanel.add(planPanel, BorderLayout.CENTER)
193+
contentPanel.revalidate()
194+
contentPanel.repaint()
195+
196+
isEditorMode = false
126197
}
127198

128199
override fun dispose() {
129-
200+
markdownEditor = null
130201
}
131202

132203
companion object {
133204
fun showPlanEditor(project: Project, planText: String, callback: (String) -> Unit) {
134-
val dialog = object : DialogWrapper(project) {
135-
private val markdownEditor =
136-
MarkdownLanguageField(project, planText, "Edit your plan here...", "plan.md")
137-
138-
init {
139-
title = "Edit Plan"
140-
// Ensure the text is properly set
141-
if (markdownEditor.text.isEmpty() && planText.isNotEmpty()) {
142-
markdownEditor.text = planText
205+
val toolWindow = ToolWindowManager.getInstance(project).getToolWindow(AutoDevPlannerToolWindowFactory.PlANNER_ID)
206+
if (toolWindow != null) {
207+
val content = toolWindow.contentManager.getContent(0)
208+
val plannerWindow = content?.component as? AutoDevPlanerTooWindow
209+
210+
plannerWindow?.let {
211+
it.currentCallback = callback
212+
if (planText.isNotEmpty() && planText != it.content) {
213+
it.content = planText
143214
}
144-
init()
145-
}
146-
147-
override fun createCenterPanel(): JComponent {
148-
val panel = JBScrollPane(markdownEditor)
149-
panel.preferredSize = Dimension(800, 600)
150-
return panel
151-
}
152-
153-
override fun doOKAction() {
154-
super.doOKAction()
155-
callback(markdownEditor.text)
215+
it.switchToEditorView()
216+
toolWindow.show()
156217
}
157218
}
158-
159-
dialog.show()
160219
}
161220
}
162221
}
@@ -188,14 +247,10 @@ private class MarkdownLanguageField(
188247
val scheme = EditorColorsUtil.getColorSchemeForBackground(this.colorsScheme.defaultBackground)
189248
this.colorsScheme = this.createBoundColorSchemeDelegate(scheme)
190249

191-
val metrics: FontMetrics = getFontMetrics(font)
192-
val columnWidth = metrics.charWidth('m')
193-
isOneLineMode = false
194-
preferredSize = Dimension(50 * columnWidth, 30 * metrics.height)
195-
196250
settings.isLineNumbersShown = true
197-
settings.isLineMarkerAreaShown = true
198-
settings.isFoldingOutlineShown = true
251+
settings.isLineMarkerAreaShown = false
252+
settings.isFoldingOutlineShown = false
253+
settings.isUseSoftWraps = true
199254
}
200255
}
201256
}

core/src/main/kotlin/cc/unitmesh/devti/observer/plan/MarkdownPlanParser.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ object MarkdownPlanParser {
362362
entries.forEachIndexed { index, entry ->
363363
stringBuilder.append("${index + 1}. ${entry.title}\n")
364364
entry.steps.forEach { step ->
365-
stringBuilder.append(" - [${if (step.completed) "x" else " "}] ${step.step}\n")
365+
stringBuilder.append(" - [${if (step.completed) "x" else " "}] ${step.step}\n")
366366
}
367367
}
368368
return stringBuilder.toString()

core/src/main/kotlin/cc/unitmesh/devti/sketch/ui/plan/PlanSketch.kt

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,7 @@ class PlanController(
4343
}
4444

4545
fun updatePlan(newPlanItems: List<AgentTaskEntry>) {
46-
if (newPlanItems.isEmpty()) {
47-
return
48-
}
46+
if (newPlanItems.isEmpty()) return
4947

5048
val taskStateMap = mutableMapOf<String, Pair<Boolean, TaskStatus>>()
5149
agentTaskItems.forEach { planItem ->
@@ -58,12 +56,7 @@ class PlanController(
5856

5957
newPlanItems.forEach { newItem ->
6058
agentTaskItems.add(newItem)
61-
newItem.steps.forEach { task ->
62-
taskStateMap[task.step]?.let { (completed, status) ->
63-
task.completed = completed
64-
task.status = status
65-
}
66-
}
59+
newItem.updateCompletionStatus()
6760
}
6861

6962
renderPlan()

0 commit comments

Comments
 (0)