java疯狂演义----简单java IDE工具
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }