@@ -13,25 +13,27 @@ import javax.swing.*
1313import javax.swing.border.TitledBorder
1414import javax.swing.filechooser.FileNameExtensionFilter
1515
16- class DevInsEditorFrame : JFrame (" DevIns Editor " ) {
17-
16+ class DevInsEditorFrame : JFrame (" AutoDev Desktop " ) {
17+
1818 private val sourceEditor = RSyntaxTextArea (20 , 60 )
1919 private val outputArea = JTextArea (10 , 60 )
20- private val variablePanel = VariablePanel ()
2120 private val statusLabel = JLabel (" Ready" )
2221 private val compileButton = JButton (" Compile" )
2322 private val clearButton = JButton (" Clear" )
24-
23+ private val fileTreePanel = FileTreePanel { file -> openFileInEditor(file) }
24+
2525 private val scope = CoroutineScope (Dispatchers .Main + SupervisorJob ())
2626 private var currentFile: File ? = null
27+ private var mainPanel: JSplitPane ? = null
28+ private var outputPanel: JComponent ? = null
2729
2830 init {
2931 setupUI()
3032 setupActions()
3133 setupDefaultContent()
3234
3335 defaultCloseOperation = EXIT_ON_CLOSE
34- setSize(1200 , 800 )
36+ setSize(1400 , 900 )
3537 setLocationRelativeTo(null )
3638 }
3739
@@ -42,12 +44,8 @@ class DevInsEditorFrame : JFrame("DevIns Editor") {
4244 val toolbar = createToolbar()
4345 add(toolbar, BorderLayout .NORTH )
4446
45- // 主面板
46- val mainPanel = JSplitPane (JSplitPane .HORIZONTAL_SPLIT )
47- mainPanel.leftComponent = createLeftPanel()
48- mainPanel.rightComponent = createRightPanel()
49- mainPanel.dividerLocation = 800
50- add(mainPanel, BorderLayout .CENTER )
47+ // 初始化主面板
48+ setupMainPanel(false )
5149
5250 // 状态栏
5351 val statusPanel = JPanel (FlowLayout (FlowLayout .LEFT ))
@@ -60,46 +58,46 @@ class DevInsEditorFrame : JFrame("DevIns Editor") {
6058 toolbar.isFloatable = false
6159
6260 // 文件操作
63- val openButton = JButton (" Open" )
64- openButton.addActionListener { openFile() }
65- toolbar.add(openButton)
61+ val openProjectButton = JButton (" Open Project" )
62+ openProjectButton.addActionListener { openProject() }
63+ toolbar.add(openProjectButton)
64+
65+ val openFileButton = JButton (" Open File" )
66+ openFileButton.addActionListener { openFile() }
67+ toolbar.add(openFileButton)
6668
6769 val saveButton = JButton (" Save" )
6870 saveButton.addActionListener { saveFile() }
6971 toolbar.add(saveButton)
7072
7173 toolbar.addSeparator()
7274
73- // 编译操作
75+ // 编译操作(初始隐藏)
76+ compileButton.isVisible = false
77+ clearButton.isVisible = false
7478 toolbar.add(compileButton)
7579 toolbar.add(clearButton)
7680
7781 return toolbar
7882 }
7983
80- private fun createLeftPanel (): JComponent {
81- val leftPanel = JSplitPane (JSplitPane .VERTICAL_SPLIT )
82-
84+ private fun createEditorPanel (): JComponent {
8385 // 代码编辑器
84- sourceEditor.syntaxEditingStyle = SyntaxConstants .SYNTAX_STYLE_MARKDOWN
86+ sourceEditor.syntaxEditingStyle = SyntaxConstants .SYNTAX_STYLE_NONE
8587 sourceEditor.isCodeFoldingEnabled = true
8688 sourceEditor.antiAliasingEnabled = true
8789 sourceEditor.font = Font (" JetBrains Mono" , Font .PLAIN , 14 )
8890 sourceEditor.tabSize = 2
89-
91+
9092 val editorScrollPane = RTextScrollPane (sourceEditor)
9193 editorScrollPane.lineNumbersEnabled = true
9294 editorScrollPane.isFoldIndicatorEnabled = true
93- editorScrollPane.border = TitledBorder (" DevIns Source" )
94-
95- leftPanel.topComponent = editorScrollPane
96- leftPanel.bottomComponent = variablePanel
97- leftPanel.dividerLocation = 400
98-
99- return leftPanel
95+ editorScrollPane.border = TitledBorder (" 📝 Editor" )
96+
97+ return editorScrollPane
10098 }
10199
102- private fun createRightPanel (): JComponent {
100+ private fun createOutputPanel (): JComponent {
103101 outputArea.isEditable = false
104102 outputArea.font = Font (" JetBrains Mono" , Font .PLAIN , 12 )
105103 outputArea.background = Color .WHITE
@@ -128,29 +126,29 @@ class DevInsEditorFrame : JFrame("DevIns Editor") {
128126 variables:
129127 greeting: "Hello"
130128 target: "World"
129+ author: "DevIns Team"
130+ version: "1.0.0"
131131 ---
132-
132+
133133 # DevIns Template Example
134-
134+
135135 ${' $' } greeting, ${' $' } target! Welcome to DevIns.
136-
136+
137137 This is a simple example showing:
138138 - Variable substitution: ${' $' } greeting and ${' $' } target
139139 - Front matter configuration
140140 - Markdown-like syntax
141-
141+
142142 ## Variables in Action
143-
143+
144144 You can use variables like ${' $' } greeting anywhere in your template.
145145 The compiler will replace them with the actual values.
146-
147- Try editing the variables in the panel below!
146+
147+ Edit the variables in the front matter above to see changes!
148+
149+ Author: ${' $' } author
150+ Version: ${' $' } version
148151 """ .trimIndent()
149-
150- variablePanel.addVariable(" greeting" , " Hello" )
151- variablePanel.addVariable(" target" , " World" )
152- variablePanel.addVariable(" author" , " DevIns Team" )
153- variablePanel.addVariable(" version" , " 1.0.0" )
154152 }
155153
156154 private fun compile () {
@@ -162,10 +160,7 @@ class DevInsEditorFrame : JFrame("DevIns Editor") {
162160 val startTime = System .currentTimeMillis()
163161
164162 val result = withContext(Dispatchers .IO ) {
165- DevInsCompilerFacade .compile(
166- sourceEditor.text,
167- variablePanel.getVariables()
168- )
163+ DevInsCompilerFacade .compile(sourceEditor.text)
169164 }
170165
171166 val executionTime = System .currentTimeMillis() - startTime
@@ -200,25 +195,14 @@ class DevInsEditorFrame : JFrame("DevIns Editor") {
200195
201196 private fun openFile () {
202197 val fileChooser = JFileChooser ().apply {
203- fileFilter = FileNameExtensionFilter (" DevIns Files" , " devin" , " devins" , " txt" )
198+ fileFilter = FileNameExtensionFilter (" All Supported Files" ,
199+ " devin" , " devins" , " kt" , " java" , " js" , " ts" , " py" , " json" , " yaml" , " yml" , " md" , " txt" )
204200 currentDirectory = File (System .getProperty(" user.home" ))
205201 }
206-
202+
207203 if (fileChooser.showOpenDialog(this ) == JFileChooser .APPROVE_OPTION ) {
208204 val file = fileChooser.selectedFile
209- try {
210- sourceEditor.text = file.readText()
211- currentFile = file
212- title = " DevIns Editor - ${file.name} "
213- statusLabel.text = " Opened: ${file.name} "
214- } catch (e: Exception ) {
215- JOptionPane .showMessageDialog(
216- this ,
217- " Failed to open file: ${e.message} " ,
218- " Error" ,
219- JOptionPane .ERROR_MESSAGE
220- )
221- }
205+ openFileInEditor(file)
222206 }
223207 }
224208
@@ -251,4 +235,126 @@ class DevInsEditorFrame : JFrame("DevIns Editor") {
251235 )
252236 }
253237 }
238+
239+ private fun setupMainPanel (showOutput : Boolean ) {
240+ // 移除现有的主面板
241+ if (mainPanel != null ) {
242+ remove(mainPanel)
243+ }
244+
245+ mainPanel = JSplitPane (JSplitPane .HORIZONTAL_SPLIT )
246+
247+ // 左侧:文件树 + 编辑器
248+ val leftPanel = JSplitPane (JSplitPane .HORIZONTAL_SPLIT )
249+ leftPanel.leftComponent = fileTreePanel
250+ leftPanel.rightComponent = createEditorPanel()
251+ leftPanel.dividerLocation = 250
252+ leftPanel.resizeWeight = 0.0 // 文件树固定宽度
253+
254+ if (showOutput) {
255+ // 三栏布局:文件树 + 编辑器 + 输出
256+ outputPanel = createOutputPanel()
257+ mainPanel!! .leftComponent = leftPanel
258+ mainPanel!! .rightComponent = outputPanel
259+ mainPanel!! .dividerLocation = 900
260+ mainPanel!! .resizeWeight = 0.7
261+ } else {
262+ // 两栏布局:文件树 + 编辑器
263+ mainPanel!! .leftComponent = leftPanel
264+ mainPanel!! .rightComponent = null
265+ mainPanel!! .dividerLocation = 0
266+ mainPanel!! .resizeWeight = 1.0
267+ }
268+
269+ add(mainPanel, BorderLayout .CENTER )
270+ revalidate()
271+ repaint()
272+ }
273+
274+ private fun isDevInsFile (file : File ): Boolean {
275+ val extension = file.extension.lowercase()
276+ return extension in setOf (" devin" , " devins" )
277+ }
278+
279+ private fun updateUIForFileType (file : File ) {
280+ val isDevIns = isDevInsFile(file)
281+
282+ // 更新工具栏按钮可见性
283+ compileButton.isVisible = isDevIns
284+ clearButton.isVisible = isDevIns
285+
286+ // 更新编辑器标题
287+ val editorScrollPane = sourceEditor.parent.parent as RTextScrollPane
288+ val fileIcon = when {
289+ isDevIns -> " 📄"
290+ file.extension.lowercase() in setOf (" kt" , " java" ) -> " ☕"
291+ file.extension.lowercase() in setOf (" js" , " ts" ) -> " 🟨"
292+ file.extension.lowercase() in setOf (" py" ) -> " 🐍"
293+ file.extension.lowercase() in setOf (" json" , " yaml" , " yml" ) -> " ⚙️"
294+ file.extension.lowercase() in setOf (" md" ) -> " 📝"
295+ else -> " 📄"
296+ }
297+
298+ val title = if (isDevIns) " $fileIcon DevIns Source" else " $fileIcon ${file.name} "
299+ editorScrollPane.border = TitledBorder (title)
300+
301+ // 更新布局
302+ setupMainPanel(isDevIns)
303+
304+ // 重新绘制工具栏
305+ (compileButton.parent as JToolBar ).revalidate()
306+ (compileButton.parent as JToolBar ).repaint()
307+ }
308+
309+ private fun openProject () {
310+ val fileChooser = JFileChooser ().apply {
311+ fileSelectionMode = JFileChooser .DIRECTORIES_ONLY
312+ dialogTitle = " Select Project Directory"
313+ currentDirectory = File (System .getProperty(" user.home" ))
314+ }
315+
316+ if (fileChooser.showOpenDialog(this ) == JFileChooser .APPROVE_OPTION ) {
317+ val selectedDir = fileChooser.selectedFile
318+ fileTreePanel.loadProject(selectedDir)
319+ statusLabel.text = " Opened project: ${selectedDir.name} "
320+ }
321+ }
322+
323+ private fun openFileInEditor (file : File ) {
324+ try {
325+ val content = file.readText()
326+ sourceEditor.text = content
327+ currentFile = file
328+ title = " DevIns Editor - ${file.name} "
329+ statusLabel.text = " Opened: ${file.name} "
330+
331+ // 根据文件扩展名设置语法高亮
332+ when (file.extension.lowercase()) {
333+ " devin" , " devins" -> sourceEditor.syntaxEditingStyle = SyntaxConstants .SYNTAX_STYLE_MARKDOWN
334+ " md" -> sourceEditor.syntaxEditingStyle = SyntaxConstants .SYNTAX_STYLE_MARKDOWN
335+ " kt" -> sourceEditor.syntaxEditingStyle = SyntaxConstants .SYNTAX_STYLE_KOTLIN
336+ " java" -> sourceEditor.syntaxEditingStyle = SyntaxConstants .SYNTAX_STYLE_JAVA
337+ " js" -> sourceEditor.syntaxEditingStyle = SyntaxConstants .SYNTAX_STYLE_JAVASCRIPT
338+ " ts" -> sourceEditor.syntaxEditingStyle = SyntaxConstants .SYNTAX_STYLE_TYPESCRIPT
339+ " py" -> sourceEditor.syntaxEditingStyle = SyntaxConstants .SYNTAX_STYLE_PYTHON
340+ " json" -> sourceEditor.syntaxEditingStyle = SyntaxConstants .SYNTAX_STYLE_JSON
341+ " yaml" , " yml" -> sourceEditor.syntaxEditingStyle = SyntaxConstants .SYNTAX_STYLE_YAML
342+ " xml" -> sourceEditor.syntaxEditingStyle = SyntaxConstants .SYNTAX_STYLE_XML
343+ " html" -> sourceEditor.syntaxEditingStyle = SyntaxConstants .SYNTAX_STYLE_HTML
344+ " css" -> sourceEditor.syntaxEditingStyle = SyntaxConstants .SYNTAX_STYLE_CSS
345+ else -> sourceEditor.syntaxEditingStyle = SyntaxConstants .SYNTAX_STYLE_NONE
346+ }
347+
348+ // 根据文件类型更新 UI
349+ updateUIForFileType(file)
350+
351+ } catch (e: Exception ) {
352+ JOptionPane .showMessageDialog(
353+ this ,
354+ " Failed to open file: ${e.message} " ,
355+ " Error" ,
356+ JOptionPane .ERROR_MESSAGE
357+ )
358+ }
359+ }
254360}
0 commit comments