首页 > 技术文章 > java疯狂演义----简单java IDE工具

lyunyu 2013-10-25 13:45 原文

file:commons

 1 package org.crazyit.editor.commons;
 2 
 3 import org.crazyit.editor.EditorFrame;
 4 import org.crazyit.editor.handler.add.AddHandler;
 5 
 6 /**
 7  * 添加的信息对象
 8  * 
 9  * @author yangenxiong yangenxiong2009@gmail.com
10  * @version  1.0
11  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
12  * <br>Copyright (C), 2009-2010, yangenxiong
13  * <br>This program is protected by copyright laws.
14  */
15 public class AddInfo {
16 
17     //字符串, 在新增界面的text前显示, 例如: 文件名称
18     private String info;
19     
20     //受新增操作影响的主frame
21     private EditorFrame editorFrame;
22     
23     //新增完后的处理类
24     private AddHandler handler;
25     
26     public AddInfo(String info, EditorFrame editorFrame, AddHandler handler) {
27         this.info = info;
28         this.editorFrame = editorFrame;
29         this.handler = handler;
30     }
31 
32     public AddHandler getHandler() {
33         return handler;
34     }
35 
36     public void setHandler(AddHandler handler) {
37         this.handler = handler;
38     }
39 
40     public String getInfo() {
41         return info;
42     }
43 
44     public void setInfo(String info) {
45         this.info = info;
46     }
47 
48     public EditorFrame getEditorFrame() {
49         return editorFrame;
50     }
51 
52     public void setEditorFrame(EditorFrame editorFrame) {
53         this.editorFrame = editorFrame;
54     }
55 
56 }
AddInfo
 1 package org.crazyit.editor.commons;
 2 
 3 import java.io.File;
 4 
 5 import javax.swing.JInternalFrame;
 6 
 7 import org.crazyit.editor.EditPane;
 8 
 9 /**
10  * 编辑的文件对象
11  * 
12  * @author yangenxiong yangenxiong2009@gmail.com
13  * @version  1.0
14  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
15  * <br>Copyright (C), 2009-2010, yangenxiong
16  * <br>This program is protected by copyright laws.
17  */
18 public class EditFile {
19 
20     //当前编辑的文件
21     private File file;
22     
23     //该文件是否已经被保存
24     private boolean saved;
25     
26     //该文件对应的窗口
27     private JInternalFrame iframe;
28     
29     //该文件所对应的编辑器
30     private EditPane editPane;
31     
32     public EditFile(File file, boolean saved, JInternalFrame iframe, 
33             EditPane editPane) {
34         this.file = file;
35         this.saved = saved;
36         this.iframe = iframe;
37         this.editPane = editPane;
38     }
39 
40     public EditPane getEditPane() {
41         return editPane;
42     }
43 
44     public void setEditPane(EditPane editPane) {
45         this.editPane = editPane;
46     }
47 
48     public JInternalFrame getIframe() {
49         return iframe;
50     }
51 
52 
53     public void setIframe(JInternalFrame iframe) {
54         this.iframe = iframe;
55     }
56 
57 
58     public boolean isSaved() {
59         return saved;
60     }
61 
62     public void setSaved(boolean saved) {
63         this.saved = saved;
64     }
65 
66     public File getFile() {
67         return file;
68     }
69 
70     public void setFile(File file) {
71         this.file = file;
72     }
73 
74     
75     
76 }
EditFile
 1 package org.crazyit.editor.commons;
 2 
 3 import java.io.File;
 4 
 5 import javax.swing.JInternalFrame;
 6 
 7 import org.crazyit.editor.EditPane;
 8 
 9 /**
10  * 编辑的文件对象
11  * 
12  * @author yangenxiong yangenxiong2009@gmail.com
13  * @version  1.0
14  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
15  * <br>Copyright (C), 2009-2010, yangenxiong
16  * <br>This program is protected by copyright laws.
17  */
18 public class EditFile {
19 
20     //当前编辑的文件
21     private File file;
22     
23     //该文件是否已经被保存
24     private boolean saved;
25     
26     //该文件对应的窗口
27     private JInternalFrame iframe;
28     
29     //该文件所对应的编辑器
30     private EditPane editPane;
31     
32     public EditFile(File file, boolean saved, JInternalFrame iframe, 
33             EditPane editPane) {
34         this.file = file;
35         this.saved = saved;
36         this.iframe = iframe;
37         this.editPane = editPane;
38     }
39 
40     public EditPane getEditPane() {
41         return editPane;
42     }
43 
44     public void setEditPane(EditPane editPane) {
45         this.editPane = editPane;
46     }
47 
48     public JInternalFrame getIframe() {
49         return iframe;
50     }
51 
52 
53     public void setIframe(JInternalFrame iframe) {
54         this.iframe = iframe;
55     }
56 
57 
58     public boolean isSaved() {
59         return saved;
60     }
61 
62     public void setSaved(boolean saved) {
63         this.saved = saved;
64     }
65 
66     public File getFile() {
67         return file;
68     }
69 
70     public void setFile(File file) {
71         this.file = file;
72     }
73 
74     
75     
76 }
WorkSpace

file:config

 1 package org.crazyit.editor.config;
 2 
 3 /**
 4  * 编译配置对象
 5  * 
 6  * @author yangenxiong yangenxiong2009@gmail.com
 7  * @version  1.0
 8  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
 9  * <br>Copyright (C), 2009-2010, yangenxiong
10  * <br>This program is protected by copyright laws.
11  */
12 public class CompileConfig {
13 
14     //记录源文件的目录
15     public final static String SRC_DIR = "src";
16     
17     //记录项目编译目录
18     public final static String OUTPUT_DIR = "classes";
19 }
CompileConfig

file:expection

 1 package org.crazyit.editor.exception;
 2 
 3 /**
 4  * 文件异常类
 5  * 
 6  * @author yangenxiong yangenxiong2009@gmail.com
 7  * @version  1.0
 8  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
 9  * <br>Copyright (C), 2009-2010, yangenxiong
10  * <br>This program is protected by copyright laws.
11  */
12 public class FileException extends RuntimeException {
13 
14     public FileException(String message) {
15         super(message);
16     }
17 }
Expection

file:handler

 1 package org.crazyit.editor.handler.add;
 2 
 3 import java.io.File;
 4 
 5 import javax.swing.JOptionPane;
 6 
 7 import org.crazyit.editor.AddFrame;
 8 import org.crazyit.editor.EditorFrame;
 9 import org.crazyit.editor.exception.FileException;
10 import org.crazyit.editor.tree.ProjectTreeModel;
11 import org.crazyit.editor.tree.ProjectTreeNode;
12 
13 /**
14  * 添加文件处理类
15  * 
16  * @author yangenxiong yangenxiong2009@gmail.com
17  * @version  1.0
18  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
19  * <br>Copyright (C), 2009-2010, yangenxiong
20  * <br>This program is protected by copyright laws.
21  */
22 public class AddFileHandler implements AddHandler {
23 
24     public void afterAdd(EditorFrame editorFrame, AddFrame addFrame, Object data) {
25         try {
26             //获得当前所选择的树节点
27             ProjectTreeNode selectNode = editorFrame.getSelectNode();
28             //获取当前选择节点所对应的文件
29             File folder = selectNode.getFile();
30             //如果folder不是一个目录,则用selectNode的父节点(是一个目录)作为新文件的存放目录
31             if (!folder.isDirectory()) {
32                 ProjectTreeNode parent = (ProjectTreeNode)selectNode.getParent();
33                 selectNode = parent;
34                 folder = parent.getFile();
35             }
36             //创建文件,放到folder下
37             File newFile = new File(folder.getAbsoluteFile() + File.separator + data);
38             //如果文件已经存在,就弹出提示并返回
39             if (newFile.exists()) {
40                 JOptionPane.showMessageDialog(addFrame, "文件已经存在");
41                 return;
42             }
43             newFile.createNewFile();
44             editorFrame.reloadNode(selectNode);
45             //使主编辑frame可用
46             editorFrame.setEnabled(true);
47             ///让添加的frame不可见
48             addFrame.setVisible(false);
49         } catch (Exception e) {
50             throw new FileException("create file error: " + e.getMessage());
51         }
52     }
53 
54 }
AddFileHandler
 1 package org.crazyit.editor.handler.add;
 2 
 3 import java.io.File;
 4 
 5 import javax.swing.JOptionPane;
 6 
 7 import org.crazyit.editor.AddFrame;
 8 import org.crazyit.editor.EditorFrame;
 9 import org.crazyit.editor.exception.FileException;
10 import org.crazyit.editor.tree.ProjectTreeNode;
11 
12 /**
13  * 添加目录处理类
14  * 
15  * @author yangenxiong yangenxiong2009@gmail.com
16  * @version  1.0
17  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
18  * <br>Copyright (C), 2009-2010, yangenxiong
19  * <br>This program is protected by copyright laws.
20  */
21 public class AddFolderHandler implements AddHandler {
22 
23     public void afterAdd(EditorFrame editorFrame, AddFrame addFrame, Object data) {
24         try {
25             //获得树中所选取的节点
26             ProjectTreeNode selectNode = editorFrame.getSelectNode();
27             //获取该节点所对应的文件对象
28             File folder = selectNode.getFile();
29             //如果folder不是一个目录,则用selectNode的父节点(是一个目录)作为新目录的父目录
30             if (!folder.isDirectory()) {
31                 ProjectTreeNode parent = (ProjectTreeNode)selectNode.getParent();
32                 //让当前所选择的文件的父目录作为当前选择的目录
33                 selectNode = parent;
34                 folder = parent.getFile();
35             }
36             //创建一个文件目录对象
37             File newFolder = new File(folder.getAbsoluteFile() + File.separator + data);
38             //如果该目录已经存在,弹出提示并返回
39             if (newFolder.exists()) {
40                 JOptionPane.showMessageDialog(addFrame, "目录已经存在");
41                 return;
42             }
43             //创建新的目录
44             newFolder.mkdir();
45             //刷新树的节点
46             editorFrame.reloadNode(selectNode);
47             //让EditorFrame可用
48             editorFrame.setEnabled(true);
49             //让添加的frame不可见
50             addFrame.setVisible(false);
51         } catch (Exception e) {
52             throw new FileException("create folder error: " + e.getMessage());
53         }
54     }
55 
56 }
AddFolderHandler
 1 package org.crazyit.editor.handler.add;
 2 
 3 import org.crazyit.editor.AddFrame;
 4 import org.crazyit.editor.EditorFrame;
 5 
 6 /**
 7  * 添加事件的接口
 8  * 
 9  * @author yangenxiong yangenxiong2009@gmail.com
10  * @version  1.0
11  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
12  * <br>Copyright (C), 2009-2010, yangenxiong
13  * <br>This program is protected by copyright laws.
14  */
15 public interface AddHandler {
16 
17     //新增完后需要做的事情,需要做的事情由实现类去实现
18     //参数为EditorFrame,AddFrame,输入的信息data
19     void afterAdd(EditorFrame editorFrame, AddFrame addFrame, Object data);
20 }
AddHandler
 1 package org.crazyit.editor.handler.add;
 2 
 3 import java.io.File;
 4 
 5 import javax.swing.JOptionPane;
 6 import javax.swing.JTree;
 7 
 8 import org.crazyit.editor.AddFrame;
 9 import org.crazyit.editor.EditorFrame;
10 import org.crazyit.editor.commons.WorkSpace;
11 import org.crazyit.editor.config.CompileConfig;
12 import org.crazyit.editor.exception.FileException;
13 
14 /**
15  * 添加项目处理类
16  * 
17  * @author yangenxiong yangenxiong2009@gmail.com
18  * @version  1.0
19  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
20  * <br>Copyright (C), 2009-2010, yangenxiong
21  * <br>This program is protected by copyright laws.
22  */
23 public class AddProjectHandler implements AddHandler {
24 
25     public void afterAdd(EditorFrame editorFrame, AddFrame addFrame, Object data) {
26         try {
27             //获取工作空间所在的目录
28             File spaceFolder = editorFrame.getWorkSpace().getFolder();
29             //创建.project文件
30             File projectFile = new File(spaceFolder.getAbsoluteFile() + 
31                     File.separator + data + ".project");
32             //创建项目目录
33             File projectFolder = new File(spaceFolder.getAbsoluteFile() + File.separator + data);
34             //项目已经存在,弹出警告并返回
35             if (projectFile.exists() && projectFolder.exists()) {
36                 JOptionPane.showMessageDialog(addFrame, "项目已经存在");
37                 return;
38             }
39             //项目文件不存在, 创建项目文件
40             if (!projectFile.exists()) projectFile.createNewFile();
41             //项目目录不存在, 创建项目文件目录
42             if (!projectFolder.exists()) projectFolder.mkdir();
43             //创建项目的src目录和编译目录
44             File src = new File(projectFolder.getAbsoluteFile() + 
45                     File.separator + CompileConfig.SRC_DIR);
46             //Java文件编译的输入目录
47             File output = new File(projectFolder.getAbsoluteFile() + 
48                     File.separator + CompileConfig.OUTPUT_DIR);
49             //创建src和output两个目录
50             src.mkdir();
51             output.mkdir();
52             //刷新整棵树
53             JTree newTree = editorFrame.getTreeCreator().createTree(editorFrame);
54             editorFrame.refreshTree(newTree); 
55             //让EditorFrame变得可用
56             editorFrame.setEnabled(true);
57             //让添加的frame不可见
58             addFrame.setVisible(false);
59         } catch (Exception e) {
60             throw new FileException("create project error: " + e.getMessage());
61         }
62     }
63 
64 }
AddProjectHandler

file:run

 1 package org.crazyit.editor.handler.run;
 2 
 3 import java.io.File;
 4 
 5 import org.crazyit.editor.EditorFrame;
 6 import org.crazyit.editor.config.CompileConfig;
 7 import org.crazyit.editor.util.CommandUtil;
 8 
 9 /**
10  * 运行Java文件处理类
11  * 
12  * @author yangenxiong yangenxiong2009@gmail.com
13  * @version  1.0
14  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
15  * <br>Copyright (C), 2009-2010, yangenxiong
16  * <br>This program is protected by copyright laws.
17  */
18 public class JavaRunHandler {
19 
20     public String run(EditorFrame editorFrame) {
21         try {
22             //获得项目目录的路径
23             String projectPath = editorFrame.getCurrentProject().getAbsolutePath();
24             //获得源文件的全路径
25             String sourcePath = editorFrame.getCurrentFile().getFile().getAbsolutePath();
26             //获得项目的编译路径,项目目录加CompileConfig中配置的输出目录
27             String classPath = editorFrame.getCurrentProject().getAbsolutePath() 
28                 + File.separator + CompileConfig.OUTPUT_DIR;
29             //获取类名
30             String className = getClassName(projectPath, sourcePath);
31             //拼装命令
32             String command = "java -cp \"" + classPath + "\" " + className;
33             Process p = CommandUtil.executeCommand(command);
34             return CommandUtil.getRunString(p);
35         } catch (Exception e) {
36             return e.getMessage();
37         }
38     }
39     
40     //根据项目目录的路径和Java源文件的路径获取一个类的全限定类名
41     private String getClassName(String projectPath, String sourcePath) {
42         String temp = projectPath + File.separator + CompileConfig.SRC_DIR + 
43         File.separator;
44         String result = sourcePath.replace(temp, "");
45         result = result.replace(".java", "");
46         result = result.replace(String.valueOf(File.separatorChar), ".");
47         return result;
48     }
49     
50 
51 }
JavaRunHandler

file:save

 1 package org.crazyit.editor.handler.save;
 2 
 3 import org.crazyit.editor.EditorFrame;
 4 import org.crazyit.editor.commons.EditFile;
 5 import org.crazyit.editor.util.FileUtil;
 6 
 7 /**
 8  * 执行普通保存的处理类
 9  * 
10  * @author yangenxiong yangenxiong2009@gmail.com
11  * @version  1.0
12  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
13  * <br>Copyright (C), 2009-2010, yangenxiong
14  * <br>This program is protected by copyright laws.
15  */
16 public class CommonSaveHandler implements SaveHandler {
17 
18     //提供一个保存方法,作为普通的保存
19     public String save(EditorFrame editorFrame) {
20         EditFile editFile = editorFrame.getCurrentFile();
21         FileUtil.writeFile(editFile.getFile(), editFile.getEditPane().getText());
22         return null; 
23     }
24 
25 }
CommonSaveHandler
 1 package org.crazyit.editor.handler.save;
 2 
 3 import java.io.File;
 4 import java.io.FileWriter;
 5 import java.io.InputStream;
 6 
 7 import org.crazyit.editor.EditorFrame;
 8 import org.crazyit.editor.config.CompileConfig;
 9 import org.crazyit.editor.util.CommandUtil;
10 
11 /**
12  * 保存Java文件的处理类
13  * 
14  * @author yangenxiong yangenxiong2009@gmail.com
15  * @version  1.0
16  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
17  * <br>Copyright (C), 2009-2010, yangenxiong
18  * <br>This program is protected by copyright laws.
19  */
20 public class JavaSaveHandler extends CommonSaveHandler {
21 
22     
23     
24     public String save(EditorFrame editorFrame) {
25         //调用父类的保存方法
26         super.save(editorFrame);
27         return javac(editorFrame);
28     }
29 
30     //执行javac命令
31     private String javac(EditorFrame editorFrame) {
32         try {
33             //获得项目的编译路径,项目目录加CompileConfig中配置的输出目录
34             String classPath = editorFrame.getCurrentProject().getAbsolutePath() 
35                 + File.separator + CompileConfig.OUTPUT_DIR;
36             //获得源文件的文件路径
37             String filePath = editorFrame.getCurrentFile().getFile().getAbsolutePath();
38             //拼装字符串命令,该命令只可在windows下运行
39             String command = "javac -d \"" + classPath + "\" \"" + filePath + "\"";
40             Process p = CommandUtil.executeCommand(command);
41             return CommandUtil.getProcessString(p);
42         } catch (Exception e) {
43             return e.getMessage();
44         }
45     }
46     
47 
48 }
JavaSaveHandler
 1 package org.crazyit.editor.handler.save;
 2 
 3 import org.crazyit.editor.EditorFrame;
 4 
 5 /**
 6  * 保存处理接口
 7  * 
 8  * @author yangenxiong yangenxiong2009@gmail.com
 9  * @version  1.0
10  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
11  * <br>Copyright (C), 2009-2010, yangenxiong
12  * <br>This program is protected by copyright laws.
13  */
14 public interface SaveHandler {
15 
16     //执行保存的接口方法
17     String save(EditorFrame editorFrame);
18 }
SaveHandler
 1 package org.crazyit.editor.handler.save;
 2 
 3 import org.crazyit.editor.EditorFrame;
 4 
 5 /**
 6  * 保存的中介者
 7  * 
 8  * @author yangenxiong yangenxiong2009@gmail.com
 9  * @version  1.0
10  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
11  * <br>Copyright (C), 2009-2010, yangenxiong
12  * <br>This program is protected by copyright laws.
13  */
14 public abstract class SaveMediator {
15 
16     //需要子类去实现的保存方法
17     public abstract String doSave(EditorFrame editorFramet);
18 }
SaveMediator
 1 package org.crazyit.editor.handler.save;
 2 
 3 import org.crazyit.editor.EditorFrame;
 4 import org.crazyit.editor.commons.EditFile;
 5 
 6 /**
 7  * 保存动作的中介者实现
 8  * 
 9  * @author yangenxiong yangenxiong2009@gmail.com
10  * @version  1.0
11  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
12  * <br>Copyright (C), 2009-2010, yangenxiong
13  * <br>This program is protected by copyright laws.
14  */
15 public class SaveMediatorConcrete extends SaveMediator {
16 
17     private SaveHandler commonHandler;
18     
19     private SaveHandler javaHandler;
20     
21     //构造两个处理保存的对象
22     public SaveMediatorConcrete() {
23         this.commonHandler = new CommonSaveHandler();
24         this.javaHandler = new JavaSaveHandler();
25     }
26     
27     public String doSave(EditorFrame editorFrame) {
28         //获得当前编辑的文件名
29         String fileName = editorFrame.getCurrentFile().getFile().getName();
30         String result = null;
31         //判断文件是否为Java文件, 再决定处理类
32         if (fileName.endsWith(".java")) {//保存java文件
33             result = javaHandler.save(editorFrame);
34         } else {//执行普通的保存
35             result = commonHandler.save(editorFrame);
36         }
37         return result;
38     }
39 
40 }
SaveMediatorConcrete

file:tree

 1 package org.crazyit.editor.tree;
 2 
 3 import javax.swing.tree.DefaultTreeModel;
 4 import javax.swing.tree.TreeNode;
 5 
 6 /**
 7  * 项目树的Model对象
 8  * 
 9  * @author yangenxiong yangenxiong2009@gmail.com
10  * @version  1.0
11  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
12  * <br>Copyright (C), 2009-2010, yangenxiong
13  * <br>This program is protected by copyright laws.
14  */
15 public class ProjectTreeModel extends DefaultTreeModel {
16     
17     public ProjectTreeModel(ProjectTreeNode arg0) {
18         super(arg0);
19     }
20 
21     public void reload(ProjectTreeNode node, TreeCreator creator) {
22         //获取node节点的父节点
23         ProjectTreeNode parent = (ProjectTreeNode)node.getParent();
24         //父节点为null,返回,不需要reload
25         if (parent == null) return;
26         //获取node节点在父节点的索引
27         int index = parent.getIndex(node);
28         //先装node节点从parent中删除
29         parent.remove(index);
30         //再通过TreeCreator获取新的节点
31         node = creator.createNode(node.getFile());
32         //添加到父节点中
33         parent.insert(node, index);
34         //调用DefaultTreeModel的reload方法
35         super.reload(node);
36     }
37 
38     
39     
40     
41     
42 }
ProjectTreeModel
 1 package org.crazyit.editor.tree;
 2 
 3 import java.io.File;
 4 import java.util.ArrayList;
 5 import java.util.List;
 6 
 7 import javax.swing.tree.DefaultMutableTreeNode;
 8 
 9 /**
10  * 项目树的节点对象
11  * 
12  * @author yangenxiong yangenxiong2009@gmail.com
13  * @version  1.0
14  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
15  * <br>Copyright (C), 2009-2010, yangenxiong
16  * <br>This program is protected by copyright laws.
17  */
18 public class ProjectTreeNode extends DefaultMutableTreeNode {
19 
20     //该节点对应的文件
21     private File file;
22     
23     //该节点下的子节点
24     private List<ProjectTreeNode> children;
25 
26     //ProjectTreeNode的构造器,参数分别时该节点对应的文件,是否允许有子节点
27     public ProjectTreeNode(File file, boolean allowsChildren) {
28         super(file.getName(), allowsChildren);
29         this.file = file;
30         //初始化该节点下的子节点集合
31         children = new ArrayList<ProjectTreeNode>();
32     }
33     
34     public File getFile() {
35         return file;
36     }
37 
38     public void setFile(File file) {
39         this.file = file;
40     }
41     
42     public List<ProjectTreeNode> getChildren() {
43         //清空children, 再重新获取一次
44         children.removeAll(children);
45         for (int i = 0; i < getChildCount(); i++) {
46             children.add((ProjectTreeNode)getChildAt(i));
47         }
48         return this.children;
49     }
50 
51 
52 
53     
54     
55 }
ProjectTreeNode
 1 package org.crazyit.editor.tree;
 2 
 3 import java.awt.event.MouseAdapter;
 4 import java.awt.event.MouseEvent;
 5 
 6 import javax.swing.event.TreeSelectionEvent;
 7 
 8 import org.crazyit.editor.EditorFrame;
 9 
10 /**
11  * 项目树选择监听器
12  * 
13  * @author yangenxiong yangenxiong2009@gmail.com
14  * @version  1.0
15  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
16  * <br>Copyright (C), 2009-2010, yangenxiong
17  * <br>This program is protected by copyright laws.
18  */
19 public class ProjectTreeSelectionListener extends MouseAdapter {
20 
21     //主界面的frame
22     private EditorFrame editorFrame;
23     
24     //将主界面的frame(EditorFrame)作为构造参数传入监听器
25     public ProjectTreeSelectionListener(EditorFrame editorFrame) {
26         this.editorFrame = editorFrame;
27     }
28 
29     public void mousePressed(MouseEvent e) {
30         //得到当前所选择的节点
31         ProjectTreeNode selectNode = this.editorFrame.getSelectNode();
32         //如果没有选择节点,就返回
33         if (selectNode == null) return;
34         //如果选择的是一个目录,返回
35         if (selectNode.getFile().isDirectory()) return;
36         //使用EditorFrame的方法来打开文件
37         this.editorFrame.openFile(selectNode.getFile());
38     }
39 
40 }
ProjectTreeSelectionListener
 1 package org.crazyit.editor.tree;
 2 
 3 import java.io.File;
 4 
 5 import javax.swing.JTree;
 6 
 7 import org.crazyit.editor.EditorFrame;
 8 
 9 /**
10  * 树创建接口
11  * 
12  * @author yangenxiong yangenxiong2009@gmail.com
13  * @version  1.0
14  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
15  * <br>Copyright (C), 2009-2010, yangenxiong
16  * <br>This program is protected by copyright laws.
17  */
18 public interface TreeCreator {
19 
20     /**
21      * 根据编辑的EditorFrame对象创建项目树
22      * @param editorFrame
23      * @return
24      */
25     JTree createTree(EditorFrame editorFrame);
26     
27     /**
28      * 根据一个目录创建它的节点
29      * @param folder
30      * @return
31      */
32     ProjectTreeNode createNode(File folder);
33 }
TreeCreator
  1 package org.crazyit.editor.tree;
  2 
  3 import java.io.File;
  4 import java.util.ArrayList;
  5 import java.util.List;
  6 
  7 import javax.swing.JTree;
  8 import javax.swing.tree.DefaultTreeCellRenderer;
  9 import javax.swing.tree.TreePath;
 10 
 11 import org.crazyit.editor.EditorFrame;
 12 import org.crazyit.editor.util.ImageUtil;
 13 
 14 /**
 15  * 树创建实现类
 16  * 
 17  * @author yangenxiong yangenxiong2009@gmail.com
 18  * @version  1.0
 19  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
 20  * <br>Copyright (C), 2009-2010, yangenxiong
 21  * <br>This program is protected by copyright laws.
 22  */
 23 public class TreeCreatorImpl implements TreeCreator {
 24 
 25     
 26     @Override
 27     public JTree createTree(EditorFrame editorFrame) {
 28         File spaceFolder = editorFrame.getWorkSpace().getFolder();
 29         ProjectTreeNode root = new ProjectTreeNode(spaceFolder, true);
 30         ProjectTreeModel treeModel = new ProjectTreeModel(root);
 31         JTree tree = new JTree(treeModel);
 32         //获取工作空间下面所有的目录(即与有projectName.project相对应的目录),也就是项目目录
 33         List<File> projectFolders = getProjectFolders(spaceFolder);
 34         //遍历项目目录集合,并为其创建子节点
 35         for (int i = 0; i < projectFolders.size(); i++) {
 36             //获取循环中的目录
 37             File projectFolder = projectFolders.get(i);
 38             //调用createNode创建它所有的子节点
 39             ProjectTreeNode node = createNode(projectFolder);
 40             //向根节点添加子节点(项目目录)
 41             root.add(node);
 42         }
 43 
 44         //定制节点图片
 45         DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
 46         //目录打开时的图片
 47         renderer.setOpenIcon(ImageUtil.getImageIcon(ImageUtil.FOLDER_OPEN));
 48         //节点没有子节点的图片
 49         renderer.setLeafIcon(ImageUtil.getImageIcon(ImageUtil.FILE));
 50         //目录关闭时的图片
 51         renderer.setClosedIcon(ImageUtil.getImageIcon(ImageUtil.FOLDER_CLOSE));
 52         //设置树的部件处理类为上面的renderer
 53         tree.setCellRenderer(renderer);
 54         //为项目树添加一个树选择监听器
 55         tree.addMouseListener(new ProjectTreeSelectionListener(editorFrame));
 56         //创建根在项目树中的路径
 57         TreePath path = new TreePath(root);
 58         //让树默认展开根节点
 59         tree.expandPath(path);
 60         //设置树的根节点不可见
 61         tree.setRootVisible(false);
 62         return tree;
 63     }
 64     
 65     /*
 66      * 根据一个目录创建它的所有直接节点
 67      */
 68     private List<ProjectTreeNode> createNodes(File folder) {
 69         //获取该目录下的所有文件
 70         File[] files = folder.listFiles();
 71         List<ProjectTreeNode> result = new ArrayList<ProjectTreeNode>();
 72         //对该目录下的所有文件的数组进行两次遍历
 73         for (File file : files) {
 74             //第一次遍历,如果是目录的话,就加入到结果集合中
 75             if (file.isDirectory()) {
 76                 result.add(new ProjectTreeNode(file, true));
 77             }
 78         }
 79         for (File file : files) {
 80             //第二次遍历,如果非目录的话,就加入到结果集合中
 81             if (!file.isDirectory()) {//再加普通文件
 82                 result.add(new ProjectTreeNode(file, false));
 83             }
 84         }
 85         return result;
 86     }
 87     
 88     //根据一个目录去创建该目录所对应的节点对象,该对象的所有的子节点都已经创建
 89     public ProjectTreeNode createNode(File folder) {
 90         //创建一个父节点,即本方法即将返回的节点对象
 91         ProjectTreeNode parent = null;
 92         //如果参数foler不是一个目录的话,创建一个ProjectTreeNode对象并返回,表明它不允许拥有子节点
 93         if (!folder.isDirectory()) {
 94             return new ProjectTreeNode(folder, false);
 95         } else {
 96             //如果是一个目录的话,则创建上面的parent,表明它是一个目录,可以拥有子节点
 97             parent = new ProjectTreeNode(folder, true);
 98         }
 99         //利用上面的parent节点去查找它下面所有的直接节点
100         List<ProjectTreeNode> nodes = createNodes(parent.getFile());
101         //获取到parent下面的所有直接子节点后,再去循环递归调用本方法
102         for (ProjectTreeNode node : nodes) {
103             //递归创建子节点,并将返回的节点添加到parent中
104             parent.add(createNode(node.getFile()));
105         }
106         return parent;
107     }
108     
109     
110     /**
111      * 获取工作空间目录下所有的项目名称
112      * @return
113      */
114     private List<String> getProjectNames(File spaceFolder) {
115         List<String> result = new ArrayList<String>();
116         for (File file : spaceFolder.listFiles()) {
117             if (file.getName().endsWith(".project")) {//取以.project结尾的文件
118                 result.add(file.getName().substring(0, file.getName().indexOf(".project")));
119             }
120         }
121         return result;
122     }
123     
124     /*
125      * 获取工作空间目录下所有的项目目录
126      */
127     private List<File> getProjectFolders(File spaceFolder) {
128         List<String> projectNames = getProjectNames(spaceFolder);
129         List<File> result = new ArrayList<File>();
130         //获取工作空间下面所有的文件
131         File[] files = spaceFolder.listFiles();
132         for (String projectName : projectNames) {
133             for (File file : files) {
134                 if (file.isDirectory()) {//如果工作空间下面的文件是目录,再去判断是否是项目目录
135                     if (projectName.equals(file.getName())) {
136                         result.add(file);
137                     }
138                 }
139             }
140         }
141         return result;
142     }
143 }
TreeCreatorImpl

file: util

 1 package org.crazyit.editor.util;
 2 
 3 import java.io.File;
 4 import java.io.FileWriter;
 5 import java.io.IOException;
 6 import java.io.InputStream;
 7 
 8 /**
 9  * 命令工具类
10  * 
11  * @author yangenxiong yangenxiong2009@gmail.com
12  * @version  1.0
13  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
14  * <br>Copyright (C), 2009-2010, yangenxiong
15  * <br>This program is protected by copyright laws.
16  */
17 public class CommandUtil {
18     
19     public final static String WINDOWS_COMMAND = "cmd /c ";
20     
21     //返回进程process的错误信息
22     public static String getErrorMessage(Process process) {
23         return getProcessString(process.getErrorStream());
24     }
25     
26     private static String getProcessString(InputStream is) {
27         try {
28             StringBuffer buffer = new StringBuffer();
29             byte[] b = new byte[4096];
30             for (int n; (n = is.read(b)) != -1;)  
31                 buffer.append(new String(b, 0, n));
32             is.close();
33             return buffer.toString();
34         } catch (Exception e) {
35             return e.getMessage();
36         }
37     }
38     
39     //获取一个进程的错误信息
40     public static String getProcessString(Process process) {
41         StringBuffer result = new StringBuffer();
42         //调用CommandUtil的方法
43         String errorString = getErrorMessage(process);
44         if (errorString.length() != 0) result.append("错误: " + errorString);
45         else result.append("执行完成");
46         return result.toString();
47     }
48     
49     //返回一个进程的信息
50     public static String getRunString(Process process) {
51         String error = getErrorMessage(process);
52         String message = getProcessString(process.getInputStream());
53         return error + message;
54     }
55     
56     //执行一个命令并返回相应的信息
57     public static Process executeCommand(String command) {
58         try {
59             //在windows下将命令生成一份bat文件, 再执行该bat文件
60             File batFile = new File("dump.bat");
61             if (!batFile.exists()) batFile.createNewFile();
62             //将命令写入文件中
63             FileWriter writer = new FileWriter(batFile);
64             writer.write(command);
65             writer.close();
66             //执行该bat文件
67             Process process =Runtime.getRuntime().exec(WINDOWS_COMMAND + batFile.getAbsolutePath());
68             process.waitFor();
69             //将bat文件删除
70             batFile.delete();
71             return process;
72         } catch (Exception e) {
73             return null;
74         }
75     }
76 }
CommandUtil
 1 package org.crazyit.editor.util;
 2 
 3 import java.io.File;
 4 import java.io.FileInputStream;
 5 import java.io.FileOutputStream;
 6 import java.io.IOException;
 7 import java.io.PrintStream;
 8 
 9 import javax.swing.JTextArea;
10 
11 import org.crazyit.editor.exception.FileException;
12 
13 /**
14  * 文件处理工具类
15  * 
16  * @author yangenxiong yangenxiong2009@gmail.com
17  * @version  1.0
18  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
19  * <br>Copyright (C), 2009-2010, yangenxiong
20  * <br>This program is protected by copyright laws.
21  */
22 public class FileUtil {
23     
24     //读取一个文件的内容
25     public static String readFile(File file) {
26         StringBuffer result = new StringBuffer();
27         try    {
28             //使用IO流读取文件
29             FileInputStream fis= new FileInputStream(file);
30             String content = null;
31             byte[] arr = new byte[1024];
32             int readLength ;
33             while ((readLength = fis.read(arr)) > 0) {
34                 content = new String(arr, 0, readLength);
35                 result.append(content);
36             }
37             fis.close();
38         }
39         catch(IOException e) {
40             throw new FileException("read '" + file.getAbsolutePath() + "' file error");
41         }
42         return result.toString();
43     }
44     
45     //使用IO流将参数content写入到参数file中
46     public static void writeFile(File file, String content) {
47         try {
48             FileOutputStream fos = new FileOutputStream(file);
49             PrintStream ps = new PrintStream(fos);
50             ps.print(content);
51             ps.close();
52             fos.close();
53         } catch (IOException e) {
54             throw new FileException("write file error");
55         }
56     }
57 }
FileUtil
 1 package org.crazyit.editor.util;
 2 
 3 import java.awt.Image;
 4 import java.io.File;
 5 
 6 import javax.imageio.ImageIO;
 7 import javax.swing.ImageIcon;
 8 
 9 /**
10  * 图片工具类
11  * 
12  * @author yangenxiong yangenxiong2009@gmail.com
13  * @version  1.0
14  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
15  * <br>Copyright (C), 2009-2010, yangenxiong
16  * <br>This program is protected by copyright laws.
17  */
18 public class ImageUtil {
19     
20     //目录关闭图片
21     public static String FOLDER_CLOSE = "images/folder-close.gif";
22     //目录打开图片
23     public static String FOLDER_OPEN = "images/folder-open.gif";
24     //无子节点的文件图片
25     public static String FILE = "images/file.gif";
26     //使用ImageIO流读取图片
27     public static Image getImage(String path) {
28         try {
29             return ImageIO.read(new File(path));
30         } catch (Exception e) {
31             e.printStackTrace();
32             return null;
33         }
34     }
35     
36     public static ImageIcon getImageIcon(String path) {
37         return new ImageIcon(getImage(path));
38     }
39 }
ImageUtil

file:src

  1 package org.crazyit.editor;
  2 
  3 import java.awt.event.ActionEvent;
  4 import java.awt.event.ActionListener;
  5 import java.awt.event.KeyAdapter;
  6 import java.awt.event.KeyEvent;
  7 import java.awt.event.WindowAdapter;
  8 
  9 import javax.swing.BoxLayout;
 10 import javax.swing.JButton;
 11 import javax.swing.JFrame;
 12 import javax.swing.JLabel;
 13 import javax.swing.JPanel;
 14 import javax.swing.JTextField;
 15 
 16 import org.crazyit.editor.commons.AddInfo;
 17 
 18 /**
 19  * 添加界面
 20  * 
 21  * @author yangenxiong yangenxiong2009@gmail.com
 22  * @version  1.0
 23  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
 24  * <br>Copyright (C), 2009-2010, yangenxiong
 25  * <br>This program is protected by copyright laws.
 26  */
 27 public class AddFrame extends JFrame {
 28 
 29     //该Frame的JPanel
 30     private JPanel mainPanel;
 31     
 32     //项目名称
 33     private JPanel namePanel;
 34     
 35     //显示文件的JLabel
 36     private JLabel nameLabel;
 37     
 38     //输入名称的JTextField
 39     private JTextField nameText;
 40     
 41     //放按钮的Panel
 42     private JPanel buttonPanel;
 43     
 44     //确定按钮
 45     private JButton confirmButton;
 46     
 47     //取消按钮
 48     private JButton cancelButton;
 49     
 50     
 51     public AddFrame(final AddInfo info) {
 52         mainPanel = new JPanel();
 53         namePanel = new JPanel();
 54         //设置nameLabel的文字
 55         nameLabel = new JLabel(info.getInfo());
 56         nameText = new JTextField("", 20);
 57         buttonPanel = new JPanel();
 58         confirmButton = new JButton("确定");
 59         cancelButton = new JButton("取消");
 60         
 61         mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
 62         addWindowListener(new WindowAdapter() {
 63             public void windowClosing(java.awt.event.WindowEvent e) {
 64                 cancel(info);
 65             }
 66         });
 67         setLocation(200, 200);
 68         setResizable(false);
 69         //文本框前面的字
 70         namePanel.setLayout(new BoxLayout(namePanel, BoxLayout.X_AXIS));        
 71         namePanel.add(nameLabel);
 72         namePanel.add(nameText);
 73         nameText.addKeyListener(new KeyAdapter() {
 74             public void keyReleased(KeyEvent e) {
 75                 //判断项目路径与名称是否有值, 如果两个text field都有值, 则确定按钮可用
 76                 if (nameText.getText().equals("")) {
 77                     confirmButton.setEnabled(false);
 78                 } else {
 79                     confirmButton.setEnabled(true);
 80                 }
 81             }
 82         });
 83         
 84         //确定和取消的按钮
 85         buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
 86         confirmButton.setEnabled(false);
 87         buttonPanel.add(confirmButton);
 88         buttonPanel.add(new JLabel("    "));
 89         buttonPanel.add(cancelButton);
 90         
 91         //为取消按钮添加监听器
 92         cancelButton.addActionListener(new ActionListener(){
 93             public void actionPerformed(ActionEvent e) {
 94                 cancel(info);
 95             }
 96         });
 97         //为确定按钮添加监听器
 98         confirmButton.addActionListener(new ActionListener() {
 99             public void actionPerformed(ActionEvent e) {
100                 //如果输入框没有值,返回
101                 if (nameText.getText() == "") return;
102                 handerConfirm(info);
103             }
104         });
105         mainPanel.add(namePanel);
106         mainPanel.add(buttonPanel);
107         add(mainPanel);
108         pack();
109     }
110     
111     //处理确定按钮的点击
112     private void handerConfirm(AddInfo info) {
113         //获取得用户输入
114         String data = nameText.getText();
115         //新增后会涉及的一些与业务相关的操作留给Handler类处理
116         info.getHandler().afterAdd(info.getEditorFrame(), this, data);
117     }
118     
119     private void cancel(AddInfo info) {
120         //设置EditorFrame可用
121         info.getEditorFrame().setEnabled(true);
122         //让本窗口不可见
123         setVisible(false);
124     }
125     
126 
127     
128 }
AddFrame
 1 package org.crazyit.editor;
 2 
 3 import javax.swing.event.DocumentEvent;
 4 import javax.swing.event.DocumentListener;
 5 
 6 /**
 7  * 文档监听器
 8  * 
 9  * @author yangenxiong yangenxiong2009@gmail.com
10  * @version  1.0
11  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
12  * <br>Copyright (C), 2009-2010, yangenxiong
13  * <br>This program is protected by copyright laws.
14  */
15 public class EditDocumentListener implements DocumentListener {
16     //主界面对象
17     private EditorFrame editorFrame;
18     public EditDocumentListener(EditorFrame editorFrame) {
19         this.editorFrame = editorFrame;
20     }
21     public void changedUpdate(DocumentEvent e) {
22     }
23     public void insertUpdate(DocumentEvent e) {
24         //设置当前编辑的文件的saved属性为false
25         this.editorFrame.getCurrentFile().setSaved(false);
26     }
27     public void removeUpdate(DocumentEvent e) {
28     }
29 }
EditDocumentListener
  1 package org.crazyit.editor;
  2 
  3 import java.awt.BorderLayout;
  4 import java.awt.Color;
  5 import java.awt.Insets;
  6 import java.awt.event.ActionEvent;
  7 import java.awt.event.InputEvent;
  8 import java.io.File;
  9 import java.util.ArrayList;
 10 import java.util.List;
 11 
 12 import javax.swing.AbstractAction;
 13 import javax.swing.Action;
 14 import javax.swing.Box;
 15 import javax.swing.BoxLayout;
 16 import javax.swing.ImageIcon;
 17 import javax.swing.JDesktopPane;
 18 import javax.swing.JFileChooser;
 19 import javax.swing.JFrame;
 20 import javax.swing.JInternalFrame;
 21 import javax.swing.JMenu;
 22 import javax.swing.JMenuBar;
 23 import javax.swing.JOptionPane;
 24 import javax.swing.JScrollPane;
 25 import javax.swing.JSplitPane;
 26 import javax.swing.JTabbedPane;
 27 import javax.swing.JTextArea;
 28 import javax.swing.JToolBar;
 29 import javax.swing.JTree;
 30 import javax.swing.KeyStroke;
 31 import javax.swing.tree.TreePath;
 32 
 33 import org.crazyit.editor.commons.AddInfo;
 34 import org.crazyit.editor.commons.EditFile;
 35 import org.crazyit.editor.commons.WorkSpace;
 36 import org.crazyit.editor.handler.add.AddFileHandler;
 37 import org.crazyit.editor.handler.add.AddFolderHandler;
 38 import org.crazyit.editor.handler.add.AddProjectHandler;
 39 import org.crazyit.editor.handler.run.JavaRunHandler;
 40 import org.crazyit.editor.handler.save.SaveMediator;
 41 import org.crazyit.editor.handler.save.SaveMediatorConcrete;
 42 import org.crazyit.editor.tree.ProjectTreeModel;
 43 import org.crazyit.editor.tree.ProjectTreeNode;
 44 import org.crazyit.editor.tree.TreeCreator;
 45 
 46 /**
 47  * 编辑界面
 48  * 
 49  * @author yangenxiong yangenxiong2009@gmail.com
 50  * @version  1.0
 51  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
 52  * <br>Copyright (C), 2009-2010, yangenxiong
 53  * <br>This program is protected by copyright laws.
 54  */
 55 public class EditorFrame extends JFrame {
 56     
 57     //多文件的tab标题
 58     private JTabbedPane tabPane;
 59     
 60     //存放tabPane与desk
 61     private Box box;
 62     
 63     //创建一个多文档的桌面容器
 64     private JDesktopPane desk;
 65     
 66     //用于分隔主编辑区和信息显示区的容器
 67     private JSplitPane editorSplitPane;
 68     
 69     //可以滚动的JScrollPane对象,用于放infoArea
 70     private JScrollPane infoPane;
 71     
 72     //用于显示信息的文本域
 73     private JTextArea infoArea;
 74     
 75     //存放树的可滚动容器
 76     private JScrollPane treePane;
 77     
 78     //整个界面的分隔组件的容器
 79     private JSplitPane mainSplitPane;
 80     
 81     //项目树对象
 82     private JTree tree;
 83     
 84     //菜单栏对象
 85     private JMenuBar menuBar;
 86     
 87     //编辑菜单对象
 88     private JMenu editMenu;
 89     
 90     //文件菜单
 91     private JMenu fileMenu;
 92     
 93     //工具条
 94     private JToolBar toolBar;
 95     
 96     private WorkSpace workSpace;
 97     
 98     private TreeCreator treeCreator;
 99     
100     //添加的界面
101     private AddFrame addFrame;
102     
103     //文件选择器
104     private FileChooser fileChooser;
105     
106     //当前正在编辑的文件对象
107     private EditFile currentFile;
108     
109     //窗口监听器
110     private IFrameListener iframeListener;
111     
112     //打开文件的集合
113     private List<EditFile> openFiles = new ArrayList<EditFile>();
114 
115     //中介者对象
116     private SaveMediator saveMediator;
117     
118     //运行class文件的处理类
119     private JavaRunHandler runHandler;
120     
121     //新建文件的Action对象
122     private Action fileNew = new AbstractAction("新建文件", new ImageIcon("images/newFile.gif")) {
123         public void actionPerformed(ActionEvent e) {
124             newFile();
125         }
126     };
127     //新建目录的Action对象
128     private Action folerNew = new AbstractAction("新建目录", new ImageIcon("images/newFile.gif")) {
129         public void actionPerformed(ActionEvent e) {
130             newFolder();
131         }
132     };
133     //新建项目的Action对象
134     private Action projectNew = new AbstractAction("新建项目", new ImageIcon("images/newFile.gif")) {
135         public void actionPerformed(ActionEvent e) {
136             newProject();
137         }
138     };
139     //打开文件的Action对象
140     private Action open = new AbstractAction("打     开", new ImageIcon("images/open.gif")) {
141         public void actionPerformed(ActionEvent e) {
142             selectFile();
143         }
144     };
145     //保存文件的Action对象
146     private Action save = new AbstractAction("保     存", new ImageIcon("images/save.gif")) {
147         public void actionPerformed(ActionEvent e) {
148             saveFile(getCurrentFile());
149         }
150     };
151     //刷新树的Action对象
152     private Action refresh = new AbstractAction("刷     新", new ImageIcon("images/refresh.gif")) {
153         public void actionPerformed(ActionEvent e) {
154             reloadNode(getSelectNode());
155         }
156     };
157     //运行文件的Action对象
158     private Action run = new AbstractAction("运     行", new ImageIcon("images/run.gif")) {
159         public void actionPerformed(ActionEvent e) {
160             run();
161         }
162     };
163     //退出的Action对象
164     private Action exit = new AbstractAction("退     出") {
165         public void actionPerformed(ActionEvent e) {
166             System.exit(0);//直接退出
167         }
168     };
169     //复制文本的Action对象
170     private Action copy = new AbstractAction("复     制", new ImageIcon("images/copy.gif")) {
171         public void actionPerformed(ActionEvent e) {
172             if (getCurrentFile() != null) {
173                 getCurrentFile().getEditPane().copy();
174             }
175         }
176     };
177     //剪切文本的Action对象
178     private Action cut = new AbstractAction("剪     切", new ImageIcon("images/cut.gif")) {
179         public void actionPerformed(ActionEvent e) {
180             if (getCurrentFile() != null) {
181                 getCurrentFile().getEditPane().cut();
182             }
183         }
184     };
185     //粘贴文本的Action对象
186     private Action paste = new AbstractAction("粘     贴", new ImageIcon("images/paste.gif")) {
187         public void actionPerformed(ActionEvent e) {
188             if (getCurrentFile() != null) {
189                 getCurrentFile().getEditPane().paste();
190             }
191         }
192     };
193     
194     public EditorFrame(String title, TreeCreator treeCreator) {
195         super(title); //设置标题
196         this.treeCreator = treeCreator;
197         this.iframeListener = new IFrameListener(this);
198         this.saveMediator = new SaveMediatorConcrete();
199         this.runHandler = new JavaRunHandler();
200     }
201     
202     public void initFrame(WorkSpace space) {
203         this.workSpace = space;
204         //设置窗口关闭,退出程序
205         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
206         //创建主编辑区的tabPane
207         tabPane = new JTabbedPane(JTabbedPane.TOP, JTabbedPane.SCROLL_TAB_LAYOUT );
208         desk = new JDesktopPane();//创建JDesktopPane对象
209         desk.setBackground(Color.GRAY);//设置desk的背景颜色为灰色
210         box = new Box(BoxLayout.Y_AXIS);//设置box的布局
211         box.add(tabPane);
212         box.add(desk);
213         //创建信息显示区的文本域
214         infoArea = new JTextArea("", 5, 50);
215         //将infoArea文本域作为组件放到infoPane中
216         infoPane = new JScrollPane(infoArea);
217         //设置信息区不可编辑
218         infoArea.setEditable(false);
219         //创建这个分隔组件的容器,并将box对象和infoPane放置其中
220         editorSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, box, infoPane);
221         editorSplitPane.setDividerSize(3);
222         editorSplitPane.setDividerLocation(500);
223         //创建树
224         tree = treeCreator.createTree(this);
225         //创建可滚动的容器对象
226         treePane = new JScrollPane(tree);
227         //创建主界面的JSplitPane,横向,左边为treePane,右边为editorSplitPane
228         mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, treePane, 
229                 editorSplitPane);
230         //设置分隔条的位置
231         mainSplitPane.setDividerLocation(200);
232         //设置分隔条的粗细
233         mainSplitPane.setDividerSize(3);
234         add(mainSplitPane);
235         
236         //创建菜单栏对象
237         menuBar = new JMenuBar();
238         //创建编辑菜单对象
239         editMenu = new JMenu("编辑");
240         //创建文件菜单
241         fileMenu = new JMenu("文件");
242         //将文件菜单添加到菜单栏中
243         menuBar.add(fileMenu);
244         //将编辑菜单添加到菜单栏中
245         menuBar.add(editMenu);
246         //设置JFrame的菜单栏
247         setJMenuBar(menuBar);
248         
249         toolBar = new JToolBar();
250         toolBar.setFloatable(false);//设置工具栏不可移动
251         toolBar.setMargin(new Insets(0, 10, 5, 5));//设置工具栏的边距
252         add(toolBar, BorderLayout.NORTH);//将工具栏添加到EditorFrame中
253         
254         pack();//使JFrame调整最佳大小
255         addListeners();
256     }
257     
258     public TreeCreator getTreeCreator() {
259         return treeCreator;
260     }
261     
262     //为EditorFrame中的组件添加监听器
263     public void addListeners() {
264         //新建文件的监听器
265         fileMenu.add(fileNew).setAccelerator(KeyStroke.getKeyStroke('N', InputEvent.CTRL_MASK));
266         //新建目录的监听器
267         fileMenu.add(folerNew).setAccelerator(KeyStroke.getKeyStroke('F', InputEvent.CTRL_MASK));
268         //新建项目的监听器
269         fileMenu.add(projectNew).setAccelerator(KeyStroke.getKeyStroke('P', InputEvent.CTRL_MASK));
270         //打开菜单添加监听器
271         fileMenu.add(open).setAccelerator(KeyStroke.getKeyStroke('O', InputEvent.CTRL_MASK));
272         //为保存菜单添加监听器
273         fileMenu.add(save).setAccelerator(KeyStroke.getKeyStroke('S', InputEvent.CTRL_MASK));
274         //为刷新菜单添加监听器
275         fileMenu.add(refresh).setAccelerator(KeyStroke.getKeyStroke("F5"));
276         //为运行菜单添加监听器
277         fileMenu.add(run).setAccelerator(KeyStroke.getKeyStroke('R', InputEvent.CTRL_MASK));
278         fileMenu.add(exit);
279         //添加复制监听器
280         editMenu.add(copy).setAccelerator(KeyStroke.getKeyStroke('C', InputEvent.CTRL_MASK));
281         //添加剪切监听器
282         editMenu.add(cut).setAccelerator(KeyStroke.getKeyStroke('X', InputEvent.CTRL_MASK));
283         //添加粘贴监听器
284         editMenu.add(paste).setAccelerator(KeyStroke.getKeyStroke('V', InputEvent.CTRL_MASK));
285     
286         //为工具条添加各个操作
287         toolBar.add(fileNew).setToolTipText("新建文件");
288         toolBar.add(open).setToolTipText("打开");
289         toolBar.add(save).setToolTipText("保存");
290         toolBar.add(refresh).setToolTipText("刷新");
291         toolBar.add(run).setToolTipText("运行");
292         toolBar.add(copy).setToolTipText("复制");
293         toolBar.add(cut).setToolTipText("剪切");
294         toolBar.add(paste).setToolTipText("粘贴");
295         
296         //为tabPane添加监听器
297         tabPane.addChangeListener(new TabListener(this));
298     }
299     
300     //获取编辑器主界面项目树中所选中的节点
301     public ProjectTreeNode getSelectNode() {
302         //获得当前树选择的节点在树中的路径
303         TreePath path = tree.getSelectionPath();
304         //如果当前选择了节点
305         if (path != null) {
306             //创建一个ProjectTreeNode对象并用于返回
307             ProjectTreeNode selectNode = (ProjectTreeNode)path.getLastPathComponent();
308             return selectNode;
309         }
310         //当前没有选择节就返回null
311         return null;
312     }
313     
314     //显示iframe对象
315     public void showIFrame(JInternalFrame iframe) {
316         try {
317             iframe.setSelected(true);
318             iframe.toFront();
319         } catch (Exception ex) {
320         }
321     }
322     
323     //打开文件的方法
324     public void openFile(File file) {
325         if (currentFile != null) {
326             //如果参数file是当前正在编辑的文件
327             if (file.equals(currentFile.getFile())) return;
328         }
329         //在打开文件的集合中查找该文件, 再判断该文件是否已经打开
330         EditFile openedFile = getOpenFile(file);
331         //如果文件已经打开了,调用打开方法(打开已经在编辑tab页面中显示的文件)
332         if (openedFile != null) {
333             openExistFile(openedFile, file);
334             return;
335         }
336         //打开新的文件
337         openNewFile(file);
338     }
339     
340     //从本类中记录已经打开的文件集合中得到与参数file一样的EditFile对象
341     private EditFile getOpenFile(File file) {
342         for (EditFile openFile : openFiles) {
343             if (openFile.getFile().equals(file)) return openFile;
344         }
345         return null;
346     }
347     
348     //根据参数file获取该file对应的tab页中的索引
349     private int getFileIndex(File file) {
350         //如果从打开文件的集合中找不到与参数file对应的EditFile对象,返回-1
351         EditFile openFile = getEditFile(file);
352         if (openFile == null) return -1;
353         return getTabIndex(openFile.getIframe().getToolTipText());
354     }
355     
356     //在打开的文件中获得文件是file的EditFile对象
357     private EditFile getEditFile(File file) {
358         for (EditFile openFile : openFiles) {
359             if (openFile.getFile().equals(file)) return openFile;
360         }
361         return null;
362     }
363     
364     //根据tab页中的tips找到所对应的在tabPane的索引
365     public int getTabIndex(String tips) {
366         for (int i = 0; i < this.tabPane.getTabCount(); i++) {
367             if (this.tabPane.getToolTipTextAt(i).equals(tips)) return i;
368         }
369         return -1;
370     }
371     
372     //打开已经存在的文件(已经在编辑文件集合中的文件),openFiles集合中的文件
373     public void openExistFile(EditFile openedFile, File willOpenFile) {
374         //将tab页变成当前所选择文件的索引
375         tabPane.setSelectedIndex(getFileIndex(willOpenFile));
376         //显示iframe
377         showIFrame(openedFile.getIframe());
378         //设置当前打开文件
379         this.currentFile = openedFile;
380         //添加到当前打开的文件集合中
381         this.openFiles.add(openedFile);
382     }
383     
384     //打开一个不在编辑集合中的文件
385     public void openNewFile(File file) {
386         //设置EditorFrame的标题为该文件的全路径
387         setTitle(file.getAbsolutePath());
388         //创建一个JInternalFrame对象,title为文件的绝对路径
389         JInternalFrame iframe = new JInternalFrame(file.getAbsolutePath(), true, true, true, true);
390         
391         //新建一个EditPane对象
392         EditPane editPane = new EditPane(file);
393         
394         //为EditPane添加键盘监听器
395         editPane.getDocument().addDocumentListener(new EditDocumentListener(this));
396         iframe.add(new JScrollPane(editPane));
397         //为JInternalFrame添加窗口监听器
398         iframe.addInternalFrameListener(this.iframeListener);
399         desk.add(iframe);
400         iframe.show();
401         iframe.reshape(0, 0, 400, 300);
402         tabPane.addTab(file.getName(), null, null, file.getAbsolutePath());
403         tabPane.setSelectedIndex(tabPane.getTabCount() - 1);
404         //设置当前的文件对象
405         this.currentFile = new EditFile(file, true, iframe, editPane);
406         //将当前的文件加到打开的文件集合中
407         this.openFiles.add(this.currentFile);
408     }
409     
410     public void selectFile() {
411         fileChooser = new FileChooser(this);
412     }
413     
414     //新建文件的方法
415     public void newFile() {
416         //当没有选择一个节点而新建目录的时候,需要提醒
417         if (getSelectNode() == null) {
418             JOptionPane.showMessageDialog(this, "请选择目录"); 
419             return;
420         }
421         AddInfo info = new AddInfo("文件名称:", this, new AddFileHandler());
422         showAddFrame(info);
423     }
424     //显示新增的界面
425     private void showAddFrame(AddInfo info) {
426         //使EditorFrame变为不可用
427         setEnabled(false);
428         addFrame = new AddFrame(info);
429         addFrame.pack();
430         addFrame.setVisible(true);
431     }
432     
433     //刷新树节点
434     public void reloadNode(ProjectTreeNode selectNode) {
435         if (selectNode == null) return; 
436         //刷新树的节点
437         ProjectTreeModel model = (ProjectTreeModel)getTree().getModel();
438         //重新加载所选择的节点
439         model.reload(selectNode, treeCreator);
440     }
441     
442     public WorkSpace getWorkSpace() {
443         return workSpace;
444     }
445     
446     public JTree getTree() {
447         return this.tree;
448     }
449     
450     //新建目录的方法
451     public void newFolder() {
452         //当没有选择一个节点而新建目录的时候,需要提醒
453         if (getSelectNode() == null) {
454             JOptionPane.showMessageDialog(this, "请选择目录"); 
455             return;
456         }
457         AddInfo info = new AddInfo("目录名称:", this, new AddFolderHandler());
458         showAddFrame(info);
459     }
460     
461     //新建项目的方法
462     public void newProject() {
463         AddInfo info = new AddInfo("项目名称:", this, new AddProjectHandler());
464         showAddFrame(info);
465     }
466     
467     //重新在treePane中构造一次树
468     public void refreshTree(JTree newTree) {
469         //将tree对象变为参数中的newTree
470         this.tree = newTree;
471         //让treePane(放树的容器)设置newTree为新的视图
472         treePane.setViewportView(newTree);
473         //更新界面
474         treePane.updateUI();
475     }
476 
477     public EditFile getCurrentFile() {
478         return currentFile;
479     }
480 
481     public void setCurrentFile(EditFile currentFile) {
482         this.currentFile = currentFile;
483     }
484 
485     public List<EditFile> getOpenFiles() {
486         return openFiles;
487     }
488 
489     public JDesktopPane getDesk() {
490         return desk;
491     }
492 
493     public JTabbedPane getTabPane() {
494         return tabPane;
495     }
496     
497     //根据JInternalFrame标题找到JInternalFrame对象
498     public JInternalFrame getIFrame(String title) {
499         JInternalFrame[] iframes = desk.getAllFrames();
500         for (JInternalFrame iframe : iframes) {
501             if (iframe.getTitle().equals(title)) return iframe;
502         }
503         return null;
504     }
505     
506     //根据JInternalFrame在打开的文件集合中获取相应的文件对象
507     public EditFile getEditFile(JInternalFrame iframe) {
508         for (EditFile openFile : openFiles) {
509             if (openFile.getIframe().equals(iframe)) return openFile;
510         }
511         return null;
512     }
513     
514     //询问是否要保存, 参数为将被打开的文件
515     public void askSave(EditFile file) {
516         //该份文件修改过没有保存
517         if (!file.isSaved()) {
518             //弹出询问
519             int val = JOptionPane.showConfirmDialog(this, "是否要保存?", "询问", 
520                     JOptionPane.YES_NO_OPTION);
521             //点击了需要保存
522             if (JOptionPane.YES_OPTION == val) {
523                 //调用EditorFrame的保存方法对文件进行保存
524                 saveFile(file);
525             }
526         }
527     }
528     
529     //用于保存当前所打开的文件
530     public void saveFile(EditFile file) {
531         if (file == null) return;
532         //调用中介者对象的方法去保存文件
533         String result = saveMediator.doSave(this);
534         //将结果放到信息显示区的文本域中
535         infoArea.setText(result);
536         //写完文件后,设置当前文件的保存状态为true,表示已经保存
537         file.setSaved(true);
538     }
539     
540     //关闭一个窗口
541     public void closeIFrame(JInternalFrame iframe) {
542         //获得当前的文件,即要关闭的文件对象
543         EditFile closeFile = getEditFile(iframe);
544         //设置本类中的currentFile属性
545         afterClose(closeFile);
546         //获得该iframe在tab页中对应的索引
547         int index = getTabIndex(iframe.getTitle());
548         //从tab页中删除
549         getTabPane().remove(index);
550         //从打开的文件集合中删除这个关闭的文件
551         openFiles.remove(closeFile);
552     }
553     
554     //当关闭一份文件后,设置本对象的currentFile属性
555     private void afterClose(EditFile closeFile) {
556         //获取关闭文件在打开文件集合中的索引
557         int openFilesIndex = getEditFileIndex(closeFile);
558         //如果该文件已经是所有打开的文件的最后一份
559         if (this.openFiles.size() == 1) {
560             this.currentFile = null;
561         } else {//如果还有其他文件,判断关闭的文件位置
562             if (openFilesIndex == 0) {
563                 //如果关闭的文件是第一份,拿集合中的第二份
564                 this.currentFile = openFiles.get(openFilesIndex + 1);
565             } else if (openFilesIndex == (openFiles.size() - 1)) {
566                 //如果关闭的是最后一份,取倒数第二份
567                 this.currentFile = openFiles.get(openFiles.size() - 2);
568             } else {
569                 //不是第一份,也不是最后一份
570                 this.currentFile = openFiles.get(openFilesIndex - 1);
571             }
572         }
573     }
574     
575     //获取editFile在打开的文件集合中的索引
576     private int getEditFileIndex(EditFile editFile) {
577         for (int i = 0; i < this.openFiles.size(); i++) {
578             if (openFiles.get(i).equals(editFile)) return i;
579         }
580         return -1;
581     }
582     
583     //返回项目树当前所选中的节点所属的项目节点对应的目录
584     public File getCurrentProject() {
585         //获取根节点(工作空间)
586         ProjectTreeNode root = (ProjectTreeNode)getSelectNode().getRoot();
587         //获取根节点下的所有子节点(即项目节点集合)
588         List<ProjectTreeNode> projects = root.getChildren();
589         ProjectTreeNode selectNode = getSelectNode();
590         if (selectNode != null) {
591             for (ProjectTreeNode project : projects) {
592                 //当前先中节点是该project下的子节点
593                 if (selectNode.isNodeAncestor(project)) {
594                     return project.getFile();
595                 }
596             }
597         }
598         return null;
599     }
600     
601     //运行文件的方法
602     public void run() {
603         //运行前先保存
604         saveFile(getCurrentFile());
605         //将结果显示
606         String result = runHandler.run(this);
607         infoArea.setText(result);
608     }
609     
610 }
611 class FileChooser extends JFileChooser {
612     
613     private EditorFrame editorFrame;
614     
615     
616     public FileChooser(EditorFrame editorFrame){
617         //调用父类的构造器
618         //利用editorFrame的工作空间作为文件选择器打开时的默认目录
619         super(editorFrame.getWorkSpace().getFolder());
620         this.editorFrame = editorFrame;
621         showOpenDialog(editorFrame);
622     }
623     
624     public void approveSelection() {
625         File file = getSelectedFile();
626         //设置树当前选择的节点为null, 即树没有被选中
627         this.editorFrame.getTree().setSelectionPath(null);
628         this.editorFrame.openFile(file);
629         super.approveSelection();
630     }
631 }
EditorFrame
  1 package org.crazyit.editor;
  2 
  3 import java.awt.Color;
  4 import java.awt.Graphics;
  5 import java.awt.Insets;
  6 import java.awt.event.KeyAdapter;
  7 import java.awt.event.KeyEvent;
  8 import java.io.File;
  9 import java.io.FileNotFoundException;
 10 import java.util.ArrayList;
 11 import java.util.HashMap;
 12 import java.util.Map;
 13 import java.util.Scanner;
 14 
 15 import javax.swing.JTextPane;
 16 import javax.swing.text.Element;
 17 import javax.swing.text.SimpleAttributeSet;
 18 import javax.swing.text.StyleConstants;
 19 import javax.swing.text.StyledDocument;
 20 
 21 import org.crazyit.editor.util.FileUtil;
 22 
 23 /**
 24  * 编辑界面
 25  * 
 26  * @author yangenxiong yangenxiong2009@gmail.com
 27  * @version  1.0
 28  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
 29  * <br>Copyright (C), 2009-2010, yangenxiong
 30  * <br>This program is protected by copyright laws.
 31  */
 32 public class EditPane extends JTextPane {
 33 
 34     //样式文档对象
 35     protected StyledDocument doc;
 36     //构造一个文本格式器
 37     protected SyntaxFormatter formatter = new SyntaxFormatter("java.stx");
 38     private SimpleAttributeSet quotAttr = new SimpleAttributeSet();
 39     //保存文档改变的开始位置
 40     private int docChangeStart = 0;
 41     //保存文档改变的长度
 42     private int docChangeLength = 0;
 43     //定义文档中行数文本的外观属性
 44     private SimpleAttributeSet lineAttr = new SimpleAttributeSet();
 45     
 46     public EditPane(File file) {
 47         this.setText(FileUtil.readFile(file));
 48         this.doc = getStyledDocument();
 49         //设置该文档的页边距
 50         this.setMargin(new Insets(3, 40, 0, 0));
 51         syntaxParse();
 52         //添加按键监听器,当按键松开时进行语法分析
 53         this.addKeyListener(new KeyAdapter() {
 54             public void keyReleased(KeyEvent ke)
 55             {
 56                 syntaxParse();
 57             }
 58         });
 59     }
 60 //    
 61 //    //重写父类方法,使JTextPane不会自动换行
 62 //    public boolean getScrollableTracksViewportWidth() { 
 63 //        return (getSize().width < getParent().getSize().width - 100); 
 64 //    } 
 65 //
 66 //    //重写父类方法,使JTextPane不会自动换行
 67 //    public void setSize(Dimension d) { 
 68 //        if (d.width < getParent().getSize().width) { 
 69 //           d.width = getParent().getSize().width; 
 70 //        } 
 71 //        d.width += 100; 
 72 //        super.setSize(d); 
 73 //    } 
 74     
 75     public void syntaxParse() {
 76         try {
 77             //获取文档的根元素,即文档内的全部内容
 78             Element root = doc.getDefaultRootElement();
 79             //获取文档中光标插入符的位置
 80             int cursorPos = this.getCaretPosition();
 81             int line = root.getElementIndex(cursorPos);
 82             //获取光标所在位置的行
 83             Element para = root.getElement(line);
 84             //定义光标所在行的行头在文档中位置
 85             int start = para.getStartOffset();
 86             //如果文档修改位置比当前行还前
 87             if (start > docChangeStart)    {
 88                 start = docChangeStart;
 89             }
 90             //定义被修改部分的长度
 91             int length = para.getEndOffset() - start;
 92             if (length < docChangeLength) {
 93                 length = docChangeLength + 1;
 94             }
 95             //取出所有被修改的字符串
 96             String s = doc.getText(start, length);
 97             //以空格、点号等作为分隔符
 98             String[] tokens = s.split("\\s+|\\.|\\(|\\)|\\{|\\}|\\[|\\]");
 99             //定义当前分析单词的在s字符串中的开始位置
100             int curStart = 0;
101             boolean isQuot = false;
102             for (String token : tokens) {
103                 //找出当前分析单词在s字符串的中位置
104                 int tokenPos = s.indexOf(token , curStart);
105                 if (isQuot && (token.endsWith("\"") || token.endsWith("\'"))) {
106                     doc.setCharacterAttributes(start + tokenPos, token.length(), quotAttr, false);
107                     isQuot = false;
108                 }
109                 else if (isQuot && !(token.endsWith("\"") || token.endsWith("\'"))) {
110                     doc.setCharacterAttributes(start + tokenPos, token.length(), quotAttr, false);
111                 }
112                 else if ((token.startsWith("\"") || token.startsWith("\'"))
113                     && (token.endsWith("\"") || token.endsWith("\'"))) {
114                     doc.setCharacterAttributes(start + tokenPos, token.length(), quotAttr, false);
115                 }
116                 else if ((token.startsWith("\"") || token.startsWith("\'"))
117                     && !(token.endsWith("\"") || token.endsWith("\'"))) {
118                     doc.setCharacterAttributes(start + tokenPos, token.length(), quotAttr, false);
119                     isQuot = true;
120                 }
121                 else {
122                     //使用格式器对当前单词设置颜色
123                     formatter.setHighLight(doc , token , start + tokenPos, token.length());
124                 }
125                 //开始分析下一个单词
126                 curStart = tokenPos + token.length();
127             }
128         }
129         catch (Exception ex) {
130             ex.printStackTrace();
131         }
132     }
133     //重画该组件,设置行号
134     public void paint(Graphics g){
135         super.paint(g);
136         Element root = doc.getDefaultRootElement(); 
137         //获得行号
138         int line = root.getElementIndex(doc.getLength());
139         //设置颜色
140         g.setColor(new Color(230, 230, 230));
141         //绘制行数矩形框
142         g.fillRect(0, 0, this.getMargin().left - 10, getSize().height);
143         //设置行号的颜色
144         g.setColor(new Color(40, 40, 40));
145         //每行绘制一个行号
146         for (int count = 0, j = 1; count <= line; count++, j++) {
147             g.drawString(String.valueOf(j), 3, 
148                         (int)((count + 1) * 1.5020 * StyleConstants.getFontSize(lineAttr)));
149         }
150     }
151 }
152 class SyntaxFormatter {
153     //以一个Map保存关键字和颜色的对应关系
154     private Map<SimpleAttributeSet , ArrayList> attMap
155         = new HashMap<SimpleAttributeSet , ArrayList>();
156     //定义文档的正常文本的外观属性
157     SimpleAttributeSet normalAttr = new SimpleAttributeSet();
158     public SyntaxFormatter(String syntaxFile) {
159         //设置正常文本的颜色、大小
160         StyleConstants.setForeground(normalAttr, Color.BLACK);
161         //StyleConstants.setFontSize(normalAttr, 14);
162         //创建一个Scanner对象,负责根据语法文件加载颜色信息
163         Scanner scaner = null;
164         try    {
165             scaner = new Scanner(new File(syntaxFile));
166         }
167         catch (FileNotFoundException e)    {
168             throw new RuntimeException("丢失语法文件:" + e.getMessage());
169         }
170         int color = -1;
171         ArrayList<String> keywords = new ArrayList<String>();
172         //不断读取语法文件的内容行
173         while(scaner.hasNextLine())    {
174             String line = scaner.nextLine();
175             //如果当前行以#开头
176             if (line.startsWith("#")) {
177                 if (keywords.size() > 0 && color > -1) {
178                     //取出当前行的颜色值,并封装成SimpleAttributeSet对象
179                     SimpleAttributeSet att = new SimpleAttributeSet();
180                     StyleConstants.setForeground(att, new Color(color));
181                     //StyleConstants.setFontSize(att, 14);
182                     //将当前颜色和关键字List对应起来
183                     attMap.put(att , keywords);
184                 }
185                 //重新创建新的关键字List,为下一个语法格式准备
186                 keywords = new ArrayList<String>();
187                 color = Integer.parseInt(line.substring(1) , 16);
188             } else {
189                 //对于普通行,每行内容添加到关键字List里
190                 if (line.trim().length() > 0) {
191                     keywords.add(line.trim());
192                 }
193             }
194         }
195         //把最后的关键字和颜色对应起来
196         if (keywords.size() > 0 && color > -1) {
197             SimpleAttributeSet att = new SimpleAttributeSet();
198             StyleConstants.setForeground(att, new Color(color));
199             attMap.put(att , keywords);
200         }
201     }
202     //返回该格式器里正常文本的外观属性
203     public SimpleAttributeSet getNormalAttributeSet() {
204         return normalAttr;
205     }
206     //设置语法高亮
207     public void setHighLight(StyledDocument doc , String token , 
208         int start , int length)    {
209         //保存需要对当前单词对应的外观属性
210         SimpleAttributeSet currentAttributeSet = null;
211         outer :
212         for (SimpleAttributeSet att : attMap.keySet())
213         {
214             //取出当前颜色对应的所有关键字
215             ArrayList keywords = attMap.get(att);
216             //遍历所有关键字
217             for (Object keyword : keywords)
218             {
219                 //如果该关键字与当前单词相同
220                 if (keyword.toString().equals(token))
221                 {
222                     //跳出循环,并设置当前单词对应的外观属性
223                     currentAttributeSet = att;
224                     break outer;
225                 }
226             }
227         }
228         //如果当前单词对应的外观属性不为空
229         if (currentAttributeSet != null){
230             //设置当前单词的颜色
231             doc.setCharacterAttributes(start, length, currentAttributeSet, false);
232         } else {//否则使用普通外观来设置该单词
233             doc.setCharacterAttributes(start, length, normalAttr, false);
234         }
235     }
236 }
EditPane
 1 package org.crazyit.editor;
 2 
 3 import javax.swing.JInternalFrame;
 4 import javax.swing.event.InternalFrameAdapter;
 5 import javax.swing.event.InternalFrameEvent;
 6 
 7 import org.crazyit.editor.commons.EditFile;
 8 
 9 /**
10  * 窗口监听器
11  * 
12  * @author yangenxiong yangenxiong2009@gmail.com
13  * @version  1.0
14  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
15  * <br>Copyright (C), 2009-2010, yangenxiong
16  * <br>This program is protected by copyright laws.
17  */
18 public class IFrameListener extends InternalFrameAdapter {
19 
20     private EditorFrame editorFrame;
21     
22     public IFrameListener(EditorFrame editorFrame) {
23         this.editorFrame = editorFrame;
24     }
25 
26     public void internalFrameActivated(InternalFrameEvent e) {
27         JInternalFrame iframe = editorFrame.getDesk().getSelectedFrame();
28         int tapIndex = editorFrame.getTabIndex(iframe.getTitle());
29         editorFrame.getTabPane().setSelectedIndex(tapIndex);
30     }
31 
32     public void internalFrameClosing(InternalFrameEvent e) {
33         //获取当前关闭操作所对应的JInternalFrame
34         JInternalFrame iframe = (JInternalFrame)e.getSource();
35         //获取当前操作的文件
36         EditFile editFile = editorFrame.getCurrentFile();
37         //询问是否要保存
38         editorFrame.askSave(editFile); 
39         //关闭当前的iframe
40         editorFrame.closeIFrame(iframe);
41     }
42 }
IFrameListener
  1 package org.crazyit.editor;
  2 
  3 import java.awt.Label;
  4 import java.awt.event.ActionEvent;
  5 import java.awt.event.ActionListener;
  6 import java.io.File;
  7 
  8 import javax.swing.BoxLayout;
  9 import javax.swing.JButton;
 10 import javax.swing.JFileChooser;
 11 import javax.swing.JFrame;
 12 import javax.swing.JLabel;
 13 import javax.swing.JPanel;
 14 import javax.swing.JTextField;
 15 
 16 import org.crazyit.editor.commons.WorkSpace;
 17 
 18 /**
 19  * 工作空间界面
 20  * 
 21  * @author yangenxiong yangenxiong2009@gmail.com
 22  * @version  1.0
 23  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
 24  * <br>Copyright (C), 2009-2010, yangenxiong
 25  * <br>This program is protected by copyright laws.
 26  */
 27 public class SpaceFrame extends JFrame {
 28 
 29     private JPanel mainPanel;
 30     
 31     private JLabel infoLabel;
 32     
 33     private JPanel chosePanel;
 34     
 35     private JLabel workTextLabel;
 36     
 37     //工作空间中显示用户选择文件目录的JTextField
 38     private JTextField pathText;
 39     
 40     private JButton choseButton;
 41     
 42     
 43     private JPanel buttonPanel;
 44     
 45     //工作空间中的确定按钮
 46     private JButton confirmButton;
 47     
 48     private JButton cancelButton;
 49     
 50     private SpaceChooser chooser;
 51     
 52     //用户选择的文件目录对象
 53     private File folder;
 54     
 55     public SpaceFrame(EditorFrame editorFrame) {
 56         mainPanel = new JPanel();
 57         infoLabel = new JLabel("请选择工作空间");
 58         chosePanel = new JPanel();
 59         workTextLabel = new JLabel("工作空间: ");
 60         pathText = new JTextField("", 40);
 61         choseButton = new JButton("选择");
 62         buttonPanel = new JPanel();
 63         confirmButton = new JButton("确定");
 64         cancelButton = new JButton("取消");
 65         chooser = new SpaceChooser(this);
 66         
 67         //设置主Panel的布局
 68         mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
 69         mainPanel.add(infoLabel);
 70         //设置选择区的布局
 71         chosePanel.setLayout(new BoxLayout(chosePanel, BoxLayout.X_AXIS));
 72         choseButton.addActionListener(new ChoseButtonListener(chooser));
 73         pathText.setEditable(false);
 74         chosePanel.add(workTextLabel);
 75         chosePanel.add(pathText);
 76         chosePanel.add(choseButton);
 77         mainPanel.add(chosePanel);
 78 
 79         confirmButton.setEnabled(false);
 80         //为确定按钮添加确定的事件, 即创建一个WorkSpace对象
 81         confirmButton.addActionListener(new ConfirmButtonListener(this, editorFrame));
 82         buttonPanel.add(confirmButton);
 83         buttonPanel.add(new Label("    "));
 84         buttonPanel.add(cancelButton);
 85         //为取消按钮添加退出事件
 86         cancelButton.addActionListener(new ActionListener() {
 87             public void actionPerformed(ActionEvent arg0) {
 88                 System.exit(0);
 89             }
 90         });
 91         mainPanel.add(buttonPanel);
 92         add(mainPanel);
 93         pack();
 94         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 95         setLocation(300, 200);
 96         setResizable(false);
 97     }
 98 
 99     public File getFolder() {
100         return folder;
101     }
102 
103     public void setFolder(File folder) {
104         this.folder = folder;
105     }
106         
107     public JTextField getPathText() {
108         return pathText;
109     }
110 
111     public JButton getConfirmButton() {
112         return confirmButton;
113     }
114 }
115 
116 /**
117  * 确定按钮的监听器
118  * @author hp
119  *
120  */
121 class ConfirmButtonListener implements ActionListener {
122     
123     private SpaceFrame spaceFrame;
124     
125     private EditorFrame editorFrame;
126     
127     public ConfirmButtonListener(SpaceFrame spaceFrame, EditorFrame editorFrame) {
128         this.spaceFrame = spaceFrame;
129         this.editorFrame = editorFrame;
130     }
131     
132     public void actionPerformed(ActionEvent arg0) {
133         //调EditorFrame的initFrame方法初始化界面
134         editorFrame.initFrame(new WorkSpace(spaceFrame.getFolder(), editorFrame));
135         //将EditorFrame设为可见
136         editorFrame.setVisible(true);
137         editorFrame.setSize(900, 600);
138         //让工作选择空间界面不可见
139         spaceFrame.setVisible(false);
140     }
141 }
142 
143 /**
144  * 选择按钮的监听器
145  * @author hp
146  *
147  */
148 class ChoseButtonListener implements ActionListener {
149 
150     private JFileChooser chooser;
151     
152     public ChoseButtonListener(JFileChooser chooser) {
153         this.chooser = chooser;
154     }
155     
156     @Override
157     public void actionPerformed(ActionEvent arg0) {
158         chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
159         chooser.showOpenDialog(null);
160     }
161     
162 }
163 
164 /**
165  * 文件选择器
166  * @author hp
167  *
168  */
169 class SpaceChooser extends JFileChooser {
170     
171     private SpaceFrame spaceFrame;
172     
173     //需要将SpaceFrame作为构造参数
174     public SpaceChooser(SpaceFrame spaceFrame) {
175         //设置选择器打开时的目录
176         super("/");
177         this.spaceFrame = spaceFrame;
178     }
179     
180     //重写父类的选择文件方法
181     public void approveSelection() {
182         //获取用户选择的文件
183         File folder = getSelectedFile();
184         //设置SpaceFrame的属性folder的值
185         spaceFrame.setFolder(folder);
186         //设置SpaceFrame文本框
187         spaceFrame.getPathText().setText(folder.getAbsolutePath());
188         //设置确定按钮可用
189         spaceFrame.getConfirmButton().setEnabled(true);
190         //调用父类的选择文件方法
191         super.approveSelection();
192     }
193 }
SpaceFrame
 1 package org.crazyit.editor;
 2 
 3 import javax.swing.JInternalFrame;
 4 import javax.swing.JTabbedPane;
 5 import javax.swing.event.ChangeEvent;
 6 import javax.swing.event.ChangeListener;
 7 
 8 import org.crazyit.editor.commons.EditFile;
 9 
10 /**
11  * tab页转换监听器
12  * 
13  * @author yangenxiong yangenxiong2009@gmail.com
14  * @version  1.0
15  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
16  * <br>Copyright (C), 2009-2010, yangenxiong
17  * <br>This program is protected by copyright laws.
18  */
19 public class TabListener implements ChangeListener {
20 
21     private EditorFrame editorFrame;
22     
23     public TabListener(EditorFrame editorFrame) {
24         this.editorFrame = editorFrame;
25     }
26     
27     public void stateChanged(ChangeEvent e) {
28         //获得当前点击tab页对象
29         JTabbedPane tab = (JTabbedPane)e.getSource();
30         //获得tab页的索引
31         int index = tab.getSelectedIndex();
32         if (index == -1) return; 
33         //根据tab页的tips(文件的绝对路径)获得当前的JInternalFrame对象
34         JInternalFrame currentFrame = editorFrame.getIFrame(tab.getToolTipTextAt(index));
35         //让当前点击的JInternalFrame对象可见
36         editorFrame.showIFrame(currentFrame);
37         //根据当前的JInternalFrame对象获得对应的文件
38         EditFile currentFile = editorFrame.getEditFile(currentFrame);
39         //设置EditorFrame当前编辑的文件为tab对应的文件
40         editorFrame.setCurrentFile(currentFile);
41     }
42 
43 }
TabListener
 1 package org.crazyit.editor;
 2 
 3 import org.crazyit.editor.tree.TreeCreator;
 4 import org.crazyit.editor.tree.TreeCreatorImpl;
 5 
 6 /**
 7  * 程序入口类
 8  * 
 9  * @author yangenxiong yangenxiong2009@gmail.com
10  * @version  1.0
11  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
12  * <br>Copyright (C), 2009-2010, yangenxiong
13  * <br>This program is protected by copyright laws.
14  */
15 public class Main {
16 
17     public static void main(String[] args) {
18         TreeCreator treeCreator = new TreeCreatorImpl();
19         //创建EditorFrame,暂时不用设置可见
20         EditorFrame editorFrame = new EditorFrame("ide", treeCreator);
21         //将editorFrame对象作为SpaceFrame的构造参数
22         SpaceFrame spaceFrame = new SpaceFrame(editorFrame);
23         //让SpaceFrame可见
24         spaceFrame.setVisible(true);
25     }
26 }
Main

 

 

推荐阅读