Skip to content

Commit d2036fb

Browse files
committed
feat(ui): refactor CodeHighlightSketch for unified collapse view #408
- Replace DevIns-specific collapsed panel with generic collapsible view - Add shouldUseCollapsedView() to determine when to use collapsed mode - Support command-specific icons for different file types - Rename variables from devIns* to generic names for reusability - Update BuiltinCommand EDIT_FILE with additional boolean parameter
1 parent 937cd23 commit d2036fb

File tree

2 files changed

+105
-65
lines changed

2 files changed

+105
-65
lines changed

core/src/main/kotlin/cc/unitmesh/devti/command/dataprovider/BuiltinCommand.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ enum class BuiltinCommand(
6060
"edit_file",
6161
"Apply structured file edits using target_file, instructions, and code_edit parameters. Designed for precise code modifications with clear context markers. Use // ... existing code ... to represent unchanged sections. Ideal for targeted edits with explicit instructions.",
6262
AllIcons.Actions.Edit,
63-
false
63+
false,
64+
true
6465
),
6566
RUN(
6667
"run",

core/src/main/kotlin/cc/unitmesh/devti/sketch/ui/code/CodeHighlightSketch.kt

Lines changed: 103 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import javax.swing.BoxLayout
4949
import javax.swing.JButton
5050
import javax.swing.JComponent
5151
import javax.swing.JPanel
52+
import javax.swing.Icon
5253

5354
open class CodeHighlightSketch(
5455
open val project: Project,
@@ -62,10 +63,9 @@ open class CodeHighlightSketch(
6263
) : JBPanel<CodeHighlightSketch>(VerticalLayout(2)), DataProvider, LangSketch, Disposable {
6364
private val minDevinLineThreshold = 1
6465
private var isDevIns = false
65-
private var devInsCollapsedPanel: JPanel? = null
66-
private var devInsExpandedPanel: JPanel? = null
67-
private var isCollapsed = false
68-
private var runButton: ActionButton? = null
66+
private var collapsedPanel: JPanel? = null
67+
private var isCollapsed = true // 默认折叠状态
68+
private var actionButton: ActionButton? = null
6969
private var isComplete = isUser
7070

7171
private var textLanguage: String? = if (ideaLanguage != null) ideaLanguage?.displayName else null
@@ -84,17 +84,22 @@ open class CodeHighlightSketch(
8484
return this != null && this.trim().isNotEmpty()
8585
}
8686

87+
private fun shouldUseCollapsedView(): Boolean {
88+
val displayName = ideaLanguage?.displayName
89+
return when {
90+
displayName == "Markdown" -> false
91+
ideaLanguage == PlainTextLanguage.INSTANCE -> false
92+
displayName == plainText -> false
93+
else -> true
94+
}
95+
}
96+
8797
private var toolbar: ActionToolbar? = null
8898

8999
fun initEditor(text: String, fileName: String? = null) {
90100
if (hasSetupAction) return
91101
hasSetupAction = true
92102

93-
if (isUser) {
94-
setupSimpleEditor(text, fileName)
95-
return
96-
}
97-
98103
val editor = EditorUtil.createCodeViewerEditor(project, text, ideaLanguage, fileName, this)
99104

100105
border = if (withLeftRightBorder) {
@@ -108,34 +113,24 @@ open class CodeHighlightSketch(
108113
if (ideaLanguage?.displayName == "DevIn") {
109114
isDevIns = true
110115
editorFragment = EditorFragment(editor, minDevinLineThreshold, previewEditor)
111-
setupDevInsView(text)
112116
} else {
113-
setupRegularEditor(editor)
117+
editorFragment = EditorFragment(editor, editorLineThreshold, previewEditor)
114118
}
115119

116-
setupToolbarAndStyling(fileName, editor)
117-
}
118-
119-
private fun setupSimpleEditor(text: String, fileName: String?) {
120-
val editor = EditorUtil.createCodeViewerEditor(project, text, ideaLanguage, fileName, this)
121-
122-
border = if (withLeftRightBorder) {
123-
JBEmptyBorder(4, 4, 4, 4)
120+
// 检查是否需要折叠视图
121+
val needsCollapsedView = shouldUseCollapsedView()
122+
if (needsCollapsedView) {
123+
setupCollapsedView(text)
124124
} else {
125-
JBEmptyBorder(4, 0, 0, 0)
125+
// 直接添加编辑器内容,不使用折叠
126+
add(editorFragment!!.getContent())
127+
isCollapsed = false
126128
}
127129

128-
editor.component.isOpaque = true
129-
editorFragment = EditorFragment(editor, editorLineThreshold, previewEditor)
130-
add(editorFragment!!.getContent())
131-
132130
setupToolbarAndStyling(fileName, editor)
133131
}
134132

135-
private fun setupRegularEditor(editor: EditorEx) {
136-
editorFragment = EditorFragment(editor, editorLineThreshold, previewEditor)
137-
add(editorFragment!!.getContent())
138-
}
133+
139134

140135
private val plainText = PlainTextLanguage.INSTANCE.displayName
141136

@@ -147,7 +142,7 @@ open class CodeHighlightSketch(
147142

148143
if (textLanguage != null && lowercase != "markdown" && textLanguage != plainText) {
149144
if (showToolbar && lowercase != devinLanguageId) {
150-
val isShowBottomBorder = devInsCollapsedPanel != null
145+
val isShowBottomBorder = collapsedPanel != null
151146
toolbar = setupActionBar(project, editor, isPackageFile, isShowBottomBorder)
152147
}
153148
} else {
@@ -163,10 +158,16 @@ open class CodeHighlightSketch(
163158
}
164159
}
165160

166-
private fun setupDevInsView(text: String) {
167-
devInsCollapsedPanel = JPanel(BorderLayout()).apply {
161+
private fun setupCollapsedView(text: String) {
162+
collapsedPanel = JPanel(BorderLayout()).apply {
168163
border = JBUI.Borders.empty(2)
169-
runButton = createRunButton(text)
164+
165+
// 根据是否为 DevIns 创建不同的按钮
166+
actionButton = if (isDevIns) {
167+
createDevInsButton(text)
168+
} else {
169+
createGenericButton()
170+
}
170171

171172
val firstLine = text.lines().firstOrNull() ?: ""
172173
val previewLabel = JBLabel(firstLine).apply {
@@ -189,7 +190,7 @@ open class CodeHighlightSketch(
189190
}
190191

191192
val leftPanel = JPanel(FlowLayout(FlowLayout.LEFT, 2, 0)).apply {
192-
add(runButton!!)
193+
add(actionButton!!)
193194
}
194195

195196
val rightPanel = JPanel(BorderLayout()).apply {
@@ -201,21 +202,17 @@ open class CodeHighlightSketch(
201202
add(rightPanel, BorderLayout.CENTER)
202203
}
203204

204-
devInsExpandedPanel = JPanel(VerticalLayout(0)).apply {
205-
add(editorFragment!!.getContent())
206-
207-
val fewerLinesLabel = createFewerLinesLabel()
208-
add(fewerLinesLabel)
209-
}
210-
211-
add(devInsCollapsedPanel!!)
205+
add(collapsedPanel!!)
212206
isCollapsed = true
213-
updateRunButtonIcon()
207+
updateActionButtonIcon()
214208
}
215209

216-
var devinRunButtonPresentation = Presentation()
217-
private fun createRunButton(newText: String): ActionButton {
218-
devinRunButtonPresentation?.icon = AutoDevIcons.RUN
210+
private var actionButtonPresentation = Presentation()
211+
212+
private fun createDevInsButton(newText: String): ActionButton {
213+
val commandIcon = getDevInsCommandIcon(newText)
214+
actionButtonPresentation = Presentation()
215+
actionButtonPresentation.icon = commandIcon
219216
return ActionButton(
220217
DumbAwareAction.create {
221218
if (isComplete) return@create
@@ -226,28 +223,67 @@ open class CodeHighlightSketch(
226223
sketchService.send(newText)
227224
}
228225
},
229-
devinRunButtonPresentation,
226+
actionButtonPresentation,
230227
"AutoDevToolbar",
231228
JBUI.size(24, 24)
232229
)
233230
}
234231

235-
private fun updateRunButtonIcon() {
236-
runButton?.let { button: ActionButton ->
237-
val icon = if (isComplete) AutoDevIcons.RUN else AutoDevIcons.LOADING
238-
devinRunButtonPresentation?.setIcon(icon)
232+
private fun createGenericButton(): ActionButton {
233+
actionButtonPresentation = Presentation()
234+
actionButtonPresentation.icon = AllIcons.General.ArrowRight
235+
return ActionButton(
236+
DumbAwareAction.create {
237+
// 普通编辑器的按钮行为,可以根据需要扩展
238+
},
239+
actionButtonPresentation,
240+
"AutoDevToolbar",
241+
JBUI.size(24, 24)
242+
)
243+
}
244+
245+
private fun getDevInsCommandIcon(text: String): Icon {
246+
val firstLine = text.lines().firstOrNull() ?: ""
247+
if (firstLine.startsWith("/")) {
248+
val commandName = firstLine.substring(1).split(":").firstOrNull()?.trim()
249+
if (commandName != null) {
250+
val command = BuiltinCommand.entries.find { it.commandName == commandName }
251+
if (command != null) {
252+
return command.icon
253+
}
254+
}
255+
}
256+
return AutoDevIcons.RUN // 默认图标
257+
}
258+
259+
private fun updateActionButtonIcon() {
260+
actionButton?.let { button: ActionButton ->
261+
if (isDevIns) {
262+
val icon = if (isComplete) {
263+
getDevInsCommandIcon(getViewText())
264+
} else {
265+
AutoDevIcons.LOADING
266+
}
267+
actionButtonPresentation.setIcon(icon)
268+
}
239269
button.repaint()
240270
}
241271
}
242272

243273
private fun toggleEditorVisibility() {
244274
if (isCollapsed) {
245-
remove(devInsCollapsedPanel)
246-
add(devInsExpandedPanel!!)
275+
// 展开:移除折叠面板,添加编辑器内容和折叠标签
276+
remove(collapsedPanel)
277+
add(editorFragment!!.getContent())
278+
279+
val fewerLinesLabel = createFewerLinesLabel()
280+
add(fewerLinesLabel)
281+
247282
isCollapsed = false
248283
} else {
249-
remove(devInsExpandedPanel)
250-
add(devInsCollapsedPanel!!)
284+
// 折叠:移除所有内容,只显示折叠面板
285+
removeAll()
286+
add(collapsedPanel!!)
251287
isCollapsed = true
252288
}
253289

@@ -302,16 +338,19 @@ open class CodeHighlightSketch(
302338
try {
303339
document?.replaceString(0, document.textLength, normalizedText)
304340

305-
// Update DevIns collapsed panel preview text if applicable
306-
if (isDevIns && devInsCollapsedPanel != null) {
341+
// Update collapsed panel preview text if applicable
342+
if (collapsedPanel != null && shouldUseCollapsedView()) {
307343
val firstLine = normalizedText.lines().firstOrNull() ?: ""
308-
val components = devInsCollapsedPanel!!.components
344+
val components = collapsedPanel!!.components
309345
for (comp in components) {
310346
if (comp is JPanel && comp.layout is BorderLayout) {
311347
val centerComp = (comp.layout as BorderLayout).getLayoutComponent(BorderLayout.CENTER)
312-
if (centerComp is JBLabel) {
313-
centerComp.text = firstLine
314-
break
348+
if (centerComp is JPanel && centerComp.layout is BorderLayout) {
349+
val labelComp = (centerComp.layout as BorderLayout).getLayoutComponent(BorderLayout.CENTER)
350+
if (labelComp is JBLabel) {
351+
labelComp.text = firstLine
352+
break
353+
}
315354
}
316355
}
317356
}
@@ -320,16 +359,16 @@ open class CodeHighlightSketch(
320359
logger<CodeHighlightSketch>().error("Error updating editor text", e)
321360
}
322361

323-
// Update run button icon state for DevIns
324-
updateRunButtonIcon()
362+
// Update action button icon state
363+
updateActionButtonIcon()
325364

326365
val lineCount = document?.lineCount ?: 0
327366
if (lineCount > editorLineThreshold) {
328367
editorFragment?.updateExpandCollapseLabel()
329368
}
330369

331-
// Auto-collapse DevIns view when complete
332-
if (complete && isDevIns && !isCollapsed) {
370+
// Auto-collapse view when complete (only for collapsible views)
371+
if (complete && !isCollapsed && shouldUseCollapsedView()) {
333372
toggleEditorVisibility()
334373
}
335374
}

0 commit comments

Comments
 (0)