file:commons
package org.crazyit.editor.commons; import org.crazyit.editor.EditorFrame;
import org.crazyit.editor.handler.add.AddHandler; /**
* 添加的信息对象
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class AddInfo { //字符串, 在新增界面的text前显示, 例如: 文件名称
private String info; //受新增操作影响的主frame
private EditorFrame editorFrame; //新增完后的处理类
private AddHandler handler; public AddInfo(String info, EditorFrame editorFrame, AddHandler handler) {
this.info = info;
this.editorFrame = editorFrame;
this.handler = handler;
} public AddHandler getHandler() {
return handler;
} public void setHandler(AddHandler handler) {
this.handler = handler;
} public String getInfo() {
return info;
} public void setInfo(String info) {
this.info = info;
} public EditorFrame getEditorFrame() {
return editorFrame;
} public void setEditorFrame(EditorFrame editorFrame) {
this.editorFrame = editorFrame;
} }
AddInfo
package org.crazyit.editor.commons; import java.io.File; import javax.swing.JInternalFrame; import org.crazyit.editor.EditPane; /**
* 编辑的文件对象
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class EditFile { //当前编辑的文件
private File file; //该文件是否已经被保存
private boolean saved; //该文件对应的窗口
private JInternalFrame iframe; //该文件所对应的编辑器
private EditPane editPane; public EditFile(File file, boolean saved, JInternalFrame iframe,
EditPane editPane) {
this.file = file;
this.saved = saved;
this.iframe = iframe;
this.editPane = editPane;
} public EditPane getEditPane() {
return editPane;
} public void setEditPane(EditPane editPane) {
this.editPane = editPane;
} public JInternalFrame getIframe() {
return iframe;
} public void setIframe(JInternalFrame iframe) {
this.iframe = iframe;
} public boolean isSaved() {
return saved;
} public void setSaved(boolean saved) {
this.saved = saved;
} public File getFile() {
return file;
} public void setFile(File file) {
this.file = file;
} }
EditFile
package org.crazyit.editor.commons; import java.io.File; import javax.swing.JInternalFrame; import org.crazyit.editor.EditPane; /**
* 编辑的文件对象
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class EditFile { //当前编辑的文件
private File file; //该文件是否已经被保存
private boolean saved; //该文件对应的窗口
private JInternalFrame iframe; //该文件所对应的编辑器
private EditPane editPane; public EditFile(File file, boolean saved, JInternalFrame iframe,
EditPane editPane) {
this.file = file;
this.saved = saved;
this.iframe = iframe;
this.editPane = editPane;
} public EditPane getEditPane() {
return editPane;
} public void setEditPane(EditPane editPane) {
this.editPane = editPane;
} public JInternalFrame getIframe() {
return iframe;
} public void setIframe(JInternalFrame iframe) {
this.iframe = iframe;
} public boolean isSaved() {
return saved;
} public void setSaved(boolean saved) {
this.saved = saved;
} public File getFile() {
return file;
} public void setFile(File file) {
this.file = file;
} }
WorkSpace
file:config
package org.crazyit.editor.config; /**
* 编译配置对象
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class CompileConfig { //记录源文件的目录
public final static String SRC_DIR = "src"; //记录项目编译目录
public final static String OUTPUT_DIR = "classes";
}
CompileConfig
file:expection
package org.crazyit.editor.exception; /**
* 文件异常类
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class FileException extends RuntimeException { public FileException(String message) {
super(message);
}
}
Expection
file:handler
package org.crazyit.editor.handler.add; import java.io.File; import javax.swing.JOptionPane; import org.crazyit.editor.AddFrame;
import org.crazyit.editor.EditorFrame;
import org.crazyit.editor.exception.FileException;
import org.crazyit.editor.tree.ProjectTreeModel;
import org.crazyit.editor.tree.ProjectTreeNode; /**
* 添加文件处理类
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class AddFileHandler implements AddHandler { public void afterAdd(EditorFrame editorFrame, AddFrame addFrame, Object data) {
try {
//获得当前所选择的树节点
ProjectTreeNode selectNode = editorFrame.getSelectNode();
//获取当前选择节点所对应的文件
File folder = selectNode.getFile();
//如果folder不是一个目录,则用selectNode的父节点(是一个目录)作为新文件的存放目录
if (!folder.isDirectory()) {
ProjectTreeNode parent = (ProjectTreeNode)selectNode.getParent();
selectNode = parent;
folder = parent.getFile();
}
//创建文件,放到folder下
File newFile = new File(folder.getAbsoluteFile() + File.separator + data);
//如果文件已经存在,就弹出提示并返回
if (newFile.exists()) {
JOptionPane.showMessageDialog(addFrame, "文件已经存在");
return;
}
newFile.createNewFile();
editorFrame.reloadNode(selectNode);
//使主编辑frame可用
editorFrame.setEnabled(true);
///让添加的frame不可见
addFrame.setVisible(false);
} catch (Exception e) {
throw new FileException("create file error: " + e.getMessage());
}
} }
AddFileHandler
package org.crazyit.editor.handler.add; import java.io.File; import javax.swing.JOptionPane; import org.crazyit.editor.AddFrame;
import org.crazyit.editor.EditorFrame;
import org.crazyit.editor.exception.FileException;
import org.crazyit.editor.tree.ProjectTreeNode; /**
* 添加目录处理类
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class AddFolderHandler implements AddHandler { public void afterAdd(EditorFrame editorFrame, AddFrame addFrame, Object data) {
try {
//获得树中所选取的节点
ProjectTreeNode selectNode = editorFrame.getSelectNode();
//获取该节点所对应的文件对象
File folder = selectNode.getFile();
//如果folder不是一个目录,则用selectNode的父节点(是一个目录)作为新目录的父目录
if (!folder.isDirectory()) {
ProjectTreeNode parent = (ProjectTreeNode)selectNode.getParent();
//让当前所选择的文件的父目录作为当前选择的目录
selectNode = parent;
folder = parent.getFile();
}
//创建一个文件目录对象
File newFolder = new File(folder.getAbsoluteFile() + File.separator + data);
//如果该目录已经存在,弹出提示并返回
if (newFolder.exists()) {
JOptionPane.showMessageDialog(addFrame, "目录已经存在");
return;
}
//创建新的目录
newFolder.mkdir();
//刷新树的节点
editorFrame.reloadNode(selectNode);
//让EditorFrame可用
editorFrame.setEnabled(true);
//让添加的frame不可见
addFrame.setVisible(false);
} catch (Exception e) {
throw new FileException("create folder error: " + e.getMessage());
}
} }
AddFolderHandler
package org.crazyit.editor.handler.add; import org.crazyit.editor.AddFrame;
import org.crazyit.editor.EditorFrame; /**
* 添加事件的接口
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public interface AddHandler { //新增完后需要做的事情,需要做的事情由实现类去实现
//参数为EditorFrame,AddFrame,输入的信息data
void afterAdd(EditorFrame editorFrame, AddFrame addFrame, Object data);
}
AddHandler
package org.crazyit.editor.handler.add; import java.io.File; import javax.swing.JOptionPane;
import javax.swing.JTree; import org.crazyit.editor.AddFrame;
import org.crazyit.editor.EditorFrame;
import org.crazyit.editor.commons.WorkSpace;
import org.crazyit.editor.config.CompileConfig;
import org.crazyit.editor.exception.FileException; /**
* 添加项目处理类
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class AddProjectHandler implements AddHandler { public void afterAdd(EditorFrame editorFrame, AddFrame addFrame, Object data) {
try {
//获取工作空间所在的目录
File spaceFolder = editorFrame.getWorkSpace().getFolder();
//创建.project文件
File projectFile = new File(spaceFolder.getAbsoluteFile() +
File.separator + data + ".project");
//创建项目目录
File projectFolder = new File(spaceFolder.getAbsoluteFile() + File.separator + data);
//项目已经存在,弹出警告并返回
if (projectFile.exists() && projectFolder.exists()) {
JOptionPane.showMessageDialog(addFrame, "项目已经存在");
return;
}
//项目文件不存在, 创建项目文件
if (!projectFile.exists()) projectFile.createNewFile();
//项目目录不存在, 创建项目文件目录
if (!projectFolder.exists()) projectFolder.mkdir();
//创建项目的src目录和编译目录
File src = new File(projectFolder.getAbsoluteFile() +
File.separator + CompileConfig.SRC_DIR);
//Java文件编译的输入目录
File output = new File(projectFolder.getAbsoluteFile() +
File.separator + CompileConfig.OUTPUT_DIR);
//创建src和output两个目录
src.mkdir();
output.mkdir();
//刷新整棵树
JTree newTree = editorFrame.getTreeCreator().createTree(editorFrame);
editorFrame.refreshTree(newTree);
//让EditorFrame变得可用
editorFrame.setEnabled(true);
//让添加的frame不可见
addFrame.setVisible(false);
} catch (Exception e) {
throw new FileException("create project error: " + e.getMessage());
}
} }
AddProjectHandler
file:run
package org.crazyit.editor.handler.run; import java.io.File; import org.crazyit.editor.EditorFrame;
import org.crazyit.editor.config.CompileConfig;
import org.crazyit.editor.util.CommandUtil; /**
* 运行Java文件处理类
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class JavaRunHandler { public String run(EditorFrame editorFrame) {
try {
//获得项目目录的路径
String projectPath = editorFrame.getCurrentProject().getAbsolutePath();
//获得源文件的全路径
String sourcePath = editorFrame.getCurrentFile().getFile().getAbsolutePath();
//获得项目的编译路径,项目目录加CompileConfig中配置的输出目录
String classPath = editorFrame.getCurrentProject().getAbsolutePath()
+ File.separator + CompileConfig.OUTPUT_DIR;
//获取类名
String className = getClassName(projectPath, sourcePath);
//拼装命令
String command = "java -cp \"" + classPath + "\" " + className;
Process p = CommandUtil.executeCommand(command);
return CommandUtil.getRunString(p);
} catch (Exception e) {
return e.getMessage();
}
} //根据项目目录的路径和Java源文件的路径获取一个类的全限定类名
private String getClassName(String projectPath, String sourcePath) {
String temp = projectPath + File.separator + CompileConfig.SRC_DIR +
File.separator;
String result = sourcePath.replace(temp, "");
result = result.replace(".java", "");
result = result.replace(String.valueOf(File.separatorChar), ".");
return result;
} }
JavaRunHandler
file:save
package org.crazyit.editor.handler.save; import org.crazyit.editor.EditorFrame;
import org.crazyit.editor.commons.EditFile;
import org.crazyit.editor.util.FileUtil; /**
* 执行普通保存的处理类
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class CommonSaveHandler implements SaveHandler { //提供一个保存方法,作为普通的保存
public String save(EditorFrame editorFrame) {
EditFile editFile = editorFrame.getCurrentFile();
FileUtil.writeFile(editFile.getFile(), editFile.getEditPane().getText());
return null;
} }
CommonSaveHandler
package org.crazyit.editor.handler.save; import java.io.File;
import java.io.FileWriter;
import java.io.InputStream; import org.crazyit.editor.EditorFrame;
import org.crazyit.editor.config.CompileConfig;
import org.crazyit.editor.util.CommandUtil; /**
* 保存Java文件的处理类
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class JavaSaveHandler extends CommonSaveHandler { public String save(EditorFrame editorFrame) {
//调用父类的保存方法
super.save(editorFrame);
return javac(editorFrame);
} //执行javac命令
private String javac(EditorFrame editorFrame) {
try {
//获得项目的编译路径,项目目录加CompileConfig中配置的输出目录
String classPath = editorFrame.getCurrentProject().getAbsolutePath()
+ File.separator + CompileConfig.OUTPUT_DIR;
//获得源文件的文件路径
String filePath = editorFrame.getCurrentFile().getFile().getAbsolutePath();
//拼装字符串命令,该命令只可在windows下运行
String command = "javac -d \"" + classPath + "\" \"" + filePath + "\"";
Process p = CommandUtil.executeCommand(command);
return CommandUtil.getProcessString(p);
} catch (Exception e) {
return e.getMessage();
}
} }
JavaSaveHandler
package org.crazyit.editor.handler.save; import org.crazyit.editor.EditorFrame; /**
* 保存处理接口
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public interface SaveHandler { //执行保存的接口方法
String save(EditorFrame editorFrame);
}
SaveHandler
package org.crazyit.editor.handler.save; import org.crazyit.editor.EditorFrame; /**
* 保存的中介者
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public abstract class SaveMediator { //需要子类去实现的保存方法
public abstract String doSave(EditorFrame editorFramet);
}
SaveMediator
package org.crazyit.editor.handler.save; import org.crazyit.editor.EditorFrame;
import org.crazyit.editor.commons.EditFile; /**
* 保存动作的中介者实现
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class SaveMediatorConcrete extends SaveMediator { private SaveHandler commonHandler; private SaveHandler javaHandler; //构造两个处理保存的对象
public SaveMediatorConcrete() {
this.commonHandler = new CommonSaveHandler();
this.javaHandler = new JavaSaveHandler();
} public String doSave(EditorFrame editorFrame) {
//获得当前编辑的文件名
String fileName = editorFrame.getCurrentFile().getFile().getName();
String result = null;
//判断文件是否为Java文件, 再决定处理类
if (fileName.endsWith(".java")) {//保存java文件
result = javaHandler.save(editorFrame);
} else {//执行普通的保存
result = commonHandler.save(editorFrame);
}
return result;
} }
SaveMediatorConcrete
file:tree
package org.crazyit.editor.tree; import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode; /**
* 项目树的Model对象
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class ProjectTreeModel extends DefaultTreeModel { public ProjectTreeModel(ProjectTreeNode arg0) {
super(arg0);
} public void reload(ProjectTreeNode node, TreeCreator creator) {
//获取node节点的父节点
ProjectTreeNode parent = (ProjectTreeNode)node.getParent();
//父节点为null,返回,不需要reload
if (parent == null) return;
//获取node节点在父节点的索引
int index = parent.getIndex(node);
//先装node节点从parent中删除
parent.remove(index);
//再通过TreeCreator获取新的节点
node = creator.createNode(node.getFile());
//添加到父节点中
parent.insert(node, index);
//调用DefaultTreeModel的reload方法
super.reload(node);
} }
ProjectTreeModel
package org.crazyit.editor.tree; import java.io.File;
import java.util.ArrayList;
import java.util.List; import javax.swing.tree.DefaultMutableTreeNode; /**
* 项目树的节点对象
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class ProjectTreeNode extends DefaultMutableTreeNode { //该节点对应的文件
private File file; //该节点下的子节点
private List<ProjectTreeNode> children; //ProjectTreeNode的构造器,参数分别时该节点对应的文件,是否允许有子节点
public ProjectTreeNode(File file, boolean allowsChildren) {
super(file.getName(), allowsChildren);
this.file = file;
//初始化该节点下的子节点集合
children = new ArrayList<ProjectTreeNode>();
} public File getFile() {
return file;
} public void setFile(File file) {
this.file = file;
} public List<ProjectTreeNode> getChildren() {
//清空children, 再重新获取一次
children.removeAll(children);
for (int i = 0; i < getChildCount(); i++) {
children.add((ProjectTreeNode)getChildAt(i));
}
return this.children;
} }
ProjectTreeNode
package org.crazyit.editor.tree; import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import javax.swing.event.TreeSelectionEvent; import org.crazyit.editor.EditorFrame; /**
* 项目树选择监听器
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class ProjectTreeSelectionListener extends MouseAdapter { //主界面的frame
private EditorFrame editorFrame; //将主界面的frame(EditorFrame)作为构造参数传入监听器
public ProjectTreeSelectionListener(EditorFrame editorFrame) {
this.editorFrame = editorFrame;
} public void mousePressed(MouseEvent e) {
//得到当前所选择的节点
ProjectTreeNode selectNode = this.editorFrame.getSelectNode();
//如果没有选择节点,就返回
if (selectNode == null) return;
//如果选择的是一个目录,返回
if (selectNode.getFile().isDirectory()) return;
//使用EditorFrame的方法来打开文件
this.editorFrame.openFile(selectNode.getFile());
} }
ProjectTreeSelectionListener
package org.crazyit.editor.tree; import java.io.File; import javax.swing.JTree; import org.crazyit.editor.EditorFrame; /**
* 树创建接口
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public interface TreeCreator { /**
* 根据编辑的EditorFrame对象创建项目树
* @param editorFrame
* @return
*/
JTree createTree(EditorFrame editorFrame); /**
* 根据一个目录创建它的节点
* @param folder
* @return
*/
ProjectTreeNode createNode(File folder);
}
TreeCreator
package org.crazyit.editor.tree; import java.io.File;
import java.util.ArrayList;
import java.util.List; import javax.swing.JTree;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreePath; import org.crazyit.editor.EditorFrame;
import org.crazyit.editor.util.ImageUtil; /**
* 树创建实现类
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class TreeCreatorImpl implements TreeCreator { @Override
public JTree createTree(EditorFrame editorFrame) {
File spaceFolder = editorFrame.getWorkSpace().getFolder();
ProjectTreeNode root = new ProjectTreeNode(spaceFolder, true);
ProjectTreeModel treeModel = new ProjectTreeModel(root);
JTree tree = new JTree(treeModel);
//获取工作空间下面所有的目录(即与有projectName.project相对应的目录),也就是项目目录
List<File> projectFolders = getProjectFolders(spaceFolder);
//遍历项目目录集合,并为其创建子节点
for (int i = 0; i < projectFolders.size(); i++) {
//获取循环中的目录
File projectFolder = projectFolders.get(i);
//调用createNode创建它所有的子节点
ProjectTreeNode node = createNode(projectFolder);
//向根节点添加子节点(项目目录)
root.add(node);
} //定制节点图片
DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
//目录打开时的图片
renderer.setOpenIcon(ImageUtil.getImageIcon(ImageUtil.FOLDER_OPEN));
//节点没有子节点的图片
renderer.setLeafIcon(ImageUtil.getImageIcon(ImageUtil.FILE));
//目录关闭时的图片
renderer.setClosedIcon(ImageUtil.getImageIcon(ImageUtil.FOLDER_CLOSE));
//设置树的部件处理类为上面的renderer
tree.setCellRenderer(renderer);
//为项目树添加一个树选择监听器
tree.addMouseListener(new ProjectTreeSelectionListener(editorFrame));
//创建根在项目树中的路径
TreePath path = new TreePath(root);
//让树默认展开根节点
tree.expandPath(path);
//设置树的根节点不可见
tree.setRootVisible(false);
return tree;
} /*
* 根据一个目录创建它的所有直接节点
*/
private List<ProjectTreeNode> createNodes(File folder) {
//获取该目录下的所有文件
File[] files = folder.listFiles();
List<ProjectTreeNode> result = new ArrayList<ProjectTreeNode>();
//对该目录下的所有文件的数组进行两次遍历
for (File file : files) {
//第一次遍历,如果是目录的话,就加入到结果集合中
if (file.isDirectory()) {
result.add(new ProjectTreeNode(file, true));
}
}
for (File file : files) {
//第二次遍历,如果非目录的话,就加入到结果集合中
if (!file.isDirectory()) {//再加普通文件
result.add(new ProjectTreeNode(file, false));
}
}
return result;
} //根据一个目录去创建该目录所对应的节点对象,该对象的所有的子节点都已经创建
public ProjectTreeNode createNode(File folder) {
//创建一个父节点,即本方法即将返回的节点对象
ProjectTreeNode parent = null;
//如果参数foler不是一个目录的话,创建一个ProjectTreeNode对象并返回,表明它不允许拥有子节点
if (!folder.isDirectory()) {
return new ProjectTreeNode(folder, false);
} else {
//如果是一个目录的话,则创建上面的parent,表明它是一个目录,可以拥有子节点
parent = new ProjectTreeNode(folder, true);
}
//利用上面的parent节点去查找它下面所有的直接节点
List<ProjectTreeNode> nodes = createNodes(parent.getFile());
//获取到parent下面的所有直接子节点后,再去循环递归调用本方法
for (ProjectTreeNode node : nodes) {
//递归创建子节点,并将返回的节点添加到parent中
parent.add(createNode(node.getFile()));
}
return parent;
} /**
* 获取工作空间目录下所有的项目名称
* @return
*/
private List<String> getProjectNames(File spaceFolder) {
List<String> result = new ArrayList<String>();
for (File file : spaceFolder.listFiles()) {
if (file.getName().endsWith(".project")) {//取以.project结尾的文件
result.add(file.getName().substring(0, file.getName().indexOf(".project")));
}
}
return result;
} /*
* 获取工作空间目录下所有的项目目录
*/
private List<File> getProjectFolders(File spaceFolder) {
List<String> projectNames = getProjectNames(spaceFolder);
List<File> result = new ArrayList<File>();
//获取工作空间下面所有的文件
File[] files = spaceFolder.listFiles();
for (String projectName : projectNames) {
for (File file : files) {
if (file.isDirectory()) {//如果工作空间下面的文件是目录,再去判断是否是项目目录
if (projectName.equals(file.getName())) {
result.add(file);
}
}
}
}
return result;
}
}
TreeCreatorImpl
file: util
package org.crazyit.editor.util; import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream; /**
* 命令工具类
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class CommandUtil { public final static String WINDOWS_COMMAND = "cmd /c "; //返回进程process的错误信息
public static String getErrorMessage(Process process) {
return getProcessString(process.getErrorStream());
} private static String getProcessString(InputStream is) {
try {
StringBuffer buffer = new StringBuffer();
byte[] b = new byte[4096];
for (int n; (n = is.read(b)) != -1;)
buffer.append(new String(b, 0, n));
is.close();
return buffer.toString();
} catch (Exception e) {
return e.getMessage();
}
} //获取一个进程的错误信息
public static String getProcessString(Process process) {
StringBuffer result = new StringBuffer();
//调用CommandUtil的方法
String errorString = getErrorMessage(process);
if (errorString.length() != 0) result.append("错误: " + errorString);
else result.append("执行完成");
return result.toString();
} //返回一个进程的信息
public static String getRunString(Process process) {
String error = getErrorMessage(process);
String message = getProcessString(process.getInputStream());
return error + message;
} //执行一个命令并返回相应的信息
public static Process executeCommand(String command) {
try {
//在windows下将命令生成一份bat文件, 再执行该bat文件
File batFile = new File("dump.bat");
if (!batFile.exists()) batFile.createNewFile();
//将命令写入文件中
FileWriter writer = new FileWriter(batFile);
writer.write(command);
writer.close();
//执行该bat文件
Process process =Runtime.getRuntime().exec(WINDOWS_COMMAND + batFile.getAbsolutePath());
process.waitFor();
//将bat文件删除
batFile.delete();
return process;
} catch (Exception e) {
return null;
}
}
}
CommandUtil
package org.crazyit.editor.util; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream; import javax.swing.JTextArea; import org.crazyit.editor.exception.FileException; /**
* 文件处理工具类
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class FileUtil { //读取一个文件的内容
public static String readFile(File file) {
StringBuffer result = new StringBuffer();
try {
//使用IO流读取文件
FileInputStream fis= new FileInputStream(file);
String content = null;
byte[] arr = new byte[1024];
int readLength ;
while ((readLength = fis.read(arr)) > 0) {
content = new String(arr, 0, readLength);
result.append(content);
}
fis.close();
}
catch(IOException e) {
throw new FileException("read '" + file.getAbsolutePath() + "' file error");
}
return result.toString();
} //使用IO流将参数content写入到参数file中
public static void writeFile(File file, String content) {
try {
FileOutputStream fos = new FileOutputStream(file);
PrintStream ps = new PrintStream(fos);
ps.print(content);
ps.close();
fos.close();
} catch (IOException e) {
throw new FileException("write file error");
}
}
}
FileUtil
package org.crazyit.editor.util; import java.awt.Image;
import java.io.File; import javax.imageio.ImageIO;
import javax.swing.ImageIcon; /**
* 图片工具类
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class ImageUtil { //目录关闭图片
public static String FOLDER_CLOSE = "images/folder-close.gif";
//目录打开图片
public static String FOLDER_OPEN = "images/folder-open.gif";
//无子节点的文件图片
public static String FILE = "images/file.gif";
//使用ImageIO流读取图片
public static Image getImage(String path) {
try {
return ImageIO.read(new File(path));
} catch (Exception e) {
e.printStackTrace();
return null;
}
} public static ImageIcon getImageIcon(String path) {
return new ImageIcon(getImage(path));
}
}
ImageUtil
file:src
package org.crazyit.editor; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter; import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField; import org.crazyit.editor.commons.AddInfo; /**
* 添加界面
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class AddFrame extends JFrame { //该Frame的JPanel
private JPanel mainPanel; //项目名称
private JPanel namePanel; //显示文件的JLabel
private JLabel nameLabel; //输入名称的JTextField
private JTextField nameText; //放按钮的Panel
private JPanel buttonPanel; //确定按钮
private JButton confirmButton; //取消按钮
private JButton cancelButton; public AddFrame(final AddInfo info) {
mainPanel = new JPanel();
namePanel = new JPanel();
//设置nameLabel的文字
nameLabel = new JLabel(info.getInfo());
nameText = new JTextField("", 20);
buttonPanel = new JPanel();
confirmButton = new JButton("确定");
cancelButton = new JButton("取消"); mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
addWindowListener(new WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent e) {
cancel(info);
}
});
setLocation(200, 200);
setResizable(false);
//文本框前面的字
namePanel.setLayout(new BoxLayout(namePanel, BoxLayout.X_AXIS));
namePanel.add(nameLabel);
namePanel.add(nameText);
nameText.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
//判断项目路径与名称是否有值, 如果两个text field都有值, 则确定按钮可用
if (nameText.getText().equals("")) {
confirmButton.setEnabled(false);
} else {
confirmButton.setEnabled(true);
}
}
}); //确定和取消的按钮
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
confirmButton.setEnabled(false);
buttonPanel.add(confirmButton);
buttonPanel.add(new JLabel(" "));
buttonPanel.add(cancelButton); //为取消按钮添加监听器
cancelButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
cancel(info);
}
});
//为确定按钮添加监听器
confirmButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//如果输入框没有值,返回
if (nameText.getText() == "") return;
handerConfirm(info);
}
});
mainPanel.add(namePanel);
mainPanel.add(buttonPanel);
add(mainPanel);
pack();
} //处理确定按钮的点击
private void handerConfirm(AddInfo info) {
//获取得用户输入
String data = nameText.getText();
//新增后会涉及的一些与业务相关的操作留给Handler类处理
info.getHandler().afterAdd(info.getEditorFrame(), this, data);
} private void cancel(AddInfo info) {
//设置EditorFrame可用
info.getEditorFrame().setEnabled(true);
//让本窗口不可见
setVisible(false);
} }
AddFrame
package org.crazyit.editor; import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener; /**
* 文档监听器
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class EditDocumentListener implements DocumentListener {
//主界面对象
private EditorFrame editorFrame;
public EditDocumentListener(EditorFrame editorFrame) {
this.editorFrame = editorFrame;
}
public void changedUpdate(DocumentEvent e) {
}
public void insertUpdate(DocumentEvent e) {
//设置当前编辑的文件的saved属性为false
this.editorFrame.getCurrentFile().setSaved(false);
}
public void removeUpdate(DocumentEvent e) {
}
}
EditDocumentListener
package org.crazyit.editor; import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.List; import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JDesktopPane;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.tree.TreePath; import org.crazyit.editor.commons.AddInfo;
import org.crazyit.editor.commons.EditFile;
import org.crazyit.editor.commons.WorkSpace;
import org.crazyit.editor.handler.add.AddFileHandler;
import org.crazyit.editor.handler.add.AddFolderHandler;
import org.crazyit.editor.handler.add.AddProjectHandler;
import org.crazyit.editor.handler.run.JavaRunHandler;
import org.crazyit.editor.handler.save.SaveMediator;
import org.crazyit.editor.handler.save.SaveMediatorConcrete;
import org.crazyit.editor.tree.ProjectTreeModel;
import org.crazyit.editor.tree.ProjectTreeNode;
import org.crazyit.editor.tree.TreeCreator; /**
* 编辑界面
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class EditorFrame extends JFrame { //多文件的tab标题
private JTabbedPane tabPane; //存放tabPane与desk
private Box box; //创建一个多文档的桌面容器
private JDesktopPane desk; //用于分隔主编辑区和信息显示区的容器
private JSplitPane editorSplitPane; //可以滚动的JScrollPane对象,用于放infoArea
private JScrollPane infoPane; //用于显示信息的文本域
private JTextArea infoArea; //存放树的可滚动容器
private JScrollPane treePane; //整个界面的分隔组件的容器
private JSplitPane mainSplitPane; //项目树对象
private JTree tree; //菜单栏对象
private JMenuBar menuBar; //编辑菜单对象
private JMenu editMenu; //文件菜单
private JMenu fileMenu; //工具条
private JToolBar toolBar; private WorkSpace workSpace; private TreeCreator treeCreator; //添加的界面
private AddFrame addFrame; //文件选择器
private FileChooser fileChooser; //当前正在编辑的文件对象
private EditFile currentFile; //窗口监听器
private IFrameListener iframeListener; //打开文件的集合
private List<EditFile> openFiles = new ArrayList<EditFile>(); //中介者对象
private SaveMediator saveMediator; //运行class文件的处理类
private JavaRunHandler runHandler; //新建文件的Action对象
private Action fileNew = new AbstractAction("新建文件", new ImageIcon("images/newFile.gif")) {
public void actionPerformed(ActionEvent e) {
newFile();
}
};
//新建目录的Action对象
private Action folerNew = new AbstractAction("新建目录", new ImageIcon("images/newFile.gif")) {
public void actionPerformed(ActionEvent e) {
newFolder();
}
};
//新建项目的Action对象
private Action projectNew = new AbstractAction("新建项目", new ImageIcon("images/newFile.gif")) {
public void actionPerformed(ActionEvent e) {
newProject();
}
};
//打开文件的Action对象
private Action open = new AbstractAction("打 开", new ImageIcon("images/open.gif")) {
public void actionPerformed(ActionEvent e) {
selectFile();
}
};
//保存文件的Action对象
private Action save = new AbstractAction("保 存", new ImageIcon("images/save.gif")) {
public void actionPerformed(ActionEvent e) {
saveFile(getCurrentFile());
}
};
//刷新树的Action对象
private Action refresh = new AbstractAction("刷 新", new ImageIcon("images/refresh.gif")) {
public void actionPerformed(ActionEvent e) {
reloadNode(getSelectNode());
}
};
//运行文件的Action对象
private Action run = new AbstractAction("运 行", new ImageIcon("images/run.gif")) {
public void actionPerformed(ActionEvent e) {
run();
}
};
//退出的Action对象
private Action exit = new AbstractAction("退 出") {
public void actionPerformed(ActionEvent e) {
System.exit(0);//直接退出
}
};
//复制文本的Action对象
private Action copy = new AbstractAction("复 制", new ImageIcon("images/copy.gif")) {
public void actionPerformed(ActionEvent e) {
if (getCurrentFile() != null) {
getCurrentFile().getEditPane().copy();
}
}
};
//剪切文本的Action对象
private Action cut = new AbstractAction("剪 切", new ImageIcon("images/cut.gif")) {
public void actionPerformed(ActionEvent e) {
if (getCurrentFile() != null) {
getCurrentFile().getEditPane().cut();
}
}
};
//粘贴文本的Action对象
private Action paste = new AbstractAction("粘 贴", new ImageIcon("images/paste.gif")) {
public void actionPerformed(ActionEvent e) {
if (getCurrentFile() != null) {
getCurrentFile().getEditPane().paste();
}
}
}; public EditorFrame(String title, TreeCreator treeCreator) {
super(title); //设置标题
this.treeCreator = treeCreator;
this.iframeListener = new IFrameListener(this);
this.saveMediator = new SaveMediatorConcrete();
this.runHandler = new JavaRunHandler();
} public void initFrame(WorkSpace space) {
this.workSpace = space;
//设置窗口关闭,退出程序
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//创建主编辑区的tabPane
tabPane = new JTabbedPane(JTabbedPane.TOP, JTabbedPane.SCROLL_TAB_LAYOUT );
desk = new JDesktopPane();//创建JDesktopPane对象
desk.setBackground(Color.GRAY);//设置desk的背景颜色为灰色
box = new Box(BoxLayout.Y_AXIS);//设置box的布局
box.add(tabPane);
box.add(desk);
//创建信息显示区的文本域
infoArea = new JTextArea("", 5, 50);
//将infoArea文本域作为组件放到infoPane中
infoPane = new JScrollPane(infoArea);
//设置信息区不可编辑
infoArea.setEditable(false);
//创建这个分隔组件的容器,并将box对象和infoPane放置其中
editorSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, box, infoPane);
editorSplitPane.setDividerSize(3);
editorSplitPane.setDividerLocation(500);
//创建树
tree = treeCreator.createTree(this);
//创建可滚动的容器对象
treePane = new JScrollPane(tree);
//创建主界面的JSplitPane,横向,左边为treePane,右边为editorSplitPane
mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, treePane,
editorSplitPane);
//设置分隔条的位置
mainSplitPane.setDividerLocation(200);
//设置分隔条的粗细
mainSplitPane.setDividerSize(3);
add(mainSplitPane); //创建菜单栏对象
menuBar = new JMenuBar();
//创建编辑菜单对象
editMenu = new JMenu("编辑");
//创建文件菜单
fileMenu = new JMenu("文件");
//将文件菜单添加到菜单栏中
menuBar.add(fileMenu);
//将编辑菜单添加到菜单栏中
menuBar.add(editMenu);
//设置JFrame的菜单栏
setJMenuBar(menuBar); toolBar = new JToolBar();
toolBar.setFloatable(false);//设置工具栏不可移动
toolBar.setMargin(new Insets(0, 10, 5, 5));//设置工具栏的边距
add(toolBar, BorderLayout.NORTH);//将工具栏添加到EditorFrame中 pack();//使JFrame调整最佳大小
addListeners();
} public TreeCreator getTreeCreator() {
return treeCreator;
} //为EditorFrame中的组件添加监听器
public void addListeners() {
//新建文件的监听器
fileMenu.add(fileNew).setAccelerator(KeyStroke.getKeyStroke('N', InputEvent.CTRL_MASK));
//新建目录的监听器
fileMenu.add(folerNew).setAccelerator(KeyStroke.getKeyStroke('F', InputEvent.CTRL_MASK));
//新建项目的监听器
fileMenu.add(projectNew).setAccelerator(KeyStroke.getKeyStroke('P', InputEvent.CTRL_MASK));
//打开菜单添加监听器
fileMenu.add(open).setAccelerator(KeyStroke.getKeyStroke('O', InputEvent.CTRL_MASK));
//为保存菜单添加监听器
fileMenu.add(save).setAccelerator(KeyStroke.getKeyStroke('S', InputEvent.CTRL_MASK));
//为刷新菜单添加监听器
fileMenu.add(refresh).setAccelerator(KeyStroke.getKeyStroke("F5"));
//为运行菜单添加监听器
fileMenu.add(run).setAccelerator(KeyStroke.getKeyStroke('R', InputEvent.CTRL_MASK));
fileMenu.add(exit);
//添加复制监听器
editMenu.add(copy).setAccelerator(KeyStroke.getKeyStroke('C', InputEvent.CTRL_MASK));
//添加剪切监听器
editMenu.add(cut).setAccelerator(KeyStroke.getKeyStroke('X', InputEvent.CTRL_MASK));
//添加粘贴监听器
editMenu.add(paste).setAccelerator(KeyStroke.getKeyStroke('V', InputEvent.CTRL_MASK)); //为工具条添加各个操作
toolBar.add(fileNew).setToolTipText("新建文件");
toolBar.add(open).setToolTipText("打开");
toolBar.add(save).setToolTipText("保存");
toolBar.add(refresh).setToolTipText("刷新");
toolBar.add(run).setToolTipText("运行");
toolBar.add(copy).setToolTipText("复制");
toolBar.add(cut).setToolTipText("剪切");
toolBar.add(paste).setToolTipText("粘贴"); //为tabPane添加监听器
tabPane.addChangeListener(new TabListener(this));
} //获取编辑器主界面项目树中所选中的节点
public ProjectTreeNode getSelectNode() {
//获得当前树选择的节点在树中的路径
TreePath path = tree.getSelectionPath();
//如果当前选择了节点
if (path != null) {
//创建一个ProjectTreeNode对象并用于返回
ProjectTreeNode selectNode = (ProjectTreeNode)path.getLastPathComponent();
return selectNode;
}
//当前没有选择节就返回null
return null;
} //显示iframe对象
public void showIFrame(JInternalFrame iframe) {
try {
iframe.setSelected(true);
iframe.toFront();
} catch (Exception ex) {
}
} //打开文件的方法
public void openFile(File file) {
if (currentFile != null) {
//如果参数file是当前正在编辑的文件
if (file.equals(currentFile.getFile())) return;
}
//在打开文件的集合中查找该文件, 再判断该文件是否已经打开
EditFile openedFile = getOpenFile(file);
//如果文件已经打开了,调用打开方法(打开已经在编辑tab页面中显示的文件)
if (openedFile != null) {
openExistFile(openedFile, file);
return;
}
//打开新的文件
openNewFile(file);
} //从本类中记录已经打开的文件集合中得到与参数file一样的EditFile对象
private EditFile getOpenFile(File file) {
for (EditFile openFile : openFiles) {
if (openFile.getFile().equals(file)) return openFile;
}
return null;
} //根据参数file获取该file对应的tab页中的索引
private int getFileIndex(File file) {
//如果从打开文件的集合中找不到与参数file对应的EditFile对象,返回-1
EditFile openFile = getEditFile(file);
if (openFile == null) return -1;
return getTabIndex(openFile.getIframe().getToolTipText());
} //在打开的文件中获得文件是file的EditFile对象
private EditFile getEditFile(File file) {
for (EditFile openFile : openFiles) {
if (openFile.getFile().equals(file)) return openFile;
}
return null;
} //根据tab页中的tips找到所对应的在tabPane的索引
public int getTabIndex(String tips) {
for (int i = 0; i < this.tabPane.getTabCount(); i++) {
if (this.tabPane.getToolTipTextAt(i).equals(tips)) return i;
}
return -1;
} //打开已经存在的文件(已经在编辑文件集合中的文件),openFiles集合中的文件
public void openExistFile(EditFile openedFile, File willOpenFile) {
//将tab页变成当前所选择文件的索引
tabPane.setSelectedIndex(getFileIndex(willOpenFile));
//显示iframe
showIFrame(openedFile.getIframe());
//设置当前打开文件
this.currentFile = openedFile;
//添加到当前打开的文件集合中
this.openFiles.add(openedFile);
} //打开一个不在编辑集合中的文件
public void openNewFile(File file) {
//设置EditorFrame的标题为该文件的全路径
setTitle(file.getAbsolutePath());
//创建一个JInternalFrame对象,title为文件的绝对路径
JInternalFrame iframe = new JInternalFrame(file.getAbsolutePath(), true, true, true, true); //新建一个EditPane对象
EditPane editPane = new EditPane(file); //为EditPane添加键盘监听器
editPane.getDocument().addDocumentListener(new EditDocumentListener(this));
iframe.add(new JScrollPane(editPane));
//为JInternalFrame添加窗口监听器
iframe.addInternalFrameListener(this.iframeListener);
desk.add(iframe);
iframe.show();
iframe.reshape(0, 0, 400, 300);
tabPane.addTab(file.getName(), null, null, file.getAbsolutePath());
tabPane.setSelectedIndex(tabPane.getTabCount() - 1);
//设置当前的文件对象
this.currentFile = new EditFile(file, true, iframe, editPane);
//将当前的文件加到打开的文件集合中
this.openFiles.add(this.currentFile);
} public void selectFile() {
fileChooser = new FileChooser(this);
} //新建文件的方法
public void newFile() {
//当没有选择一个节点而新建目录的时候,需要提醒
if (getSelectNode() == null) {
JOptionPane.showMessageDialog(this, "请选择目录");
return;
}
AddInfo info = new AddInfo("文件名称:", this, new AddFileHandler());
showAddFrame(info);
}
//显示新增的界面
private void showAddFrame(AddInfo info) {
//使EditorFrame变为不可用
setEnabled(false);
addFrame = new AddFrame(info);
addFrame.pack();
addFrame.setVisible(true);
} //刷新树节点
public void reloadNode(ProjectTreeNode selectNode) {
if (selectNode == null) return;
//刷新树的节点
ProjectTreeModel model = (ProjectTreeModel)getTree().getModel();
//重新加载所选择的节点
model.reload(selectNode, treeCreator);
} public WorkSpace getWorkSpace() {
return workSpace;
} public JTree getTree() {
return this.tree;
} //新建目录的方法
public void newFolder() {
//当没有选择一个节点而新建目录的时候,需要提醒
if (getSelectNode() == null) {
JOptionPane.showMessageDialog(this, "请选择目录");
return;
}
AddInfo info = new AddInfo("目录名称:", this, new AddFolderHandler());
showAddFrame(info);
} //新建项目的方法
public void newProject() {
AddInfo info = new AddInfo("项目名称:", this, new AddProjectHandler());
showAddFrame(info);
} //重新在treePane中构造一次树
public void refreshTree(JTree newTree) {
//将tree对象变为参数中的newTree
this.tree = newTree;
//让treePane(放树的容器)设置newTree为新的视图
treePane.setViewportView(newTree);
//更新界面
treePane.updateUI();
} public EditFile getCurrentFile() {
return currentFile;
} public void setCurrentFile(EditFile currentFile) {
this.currentFile = currentFile;
} public List<EditFile> getOpenFiles() {
return openFiles;
} public JDesktopPane getDesk() {
return desk;
} public JTabbedPane getTabPane() {
return tabPane;
} //根据JInternalFrame标题找到JInternalFrame对象
public JInternalFrame getIFrame(String title) {
JInternalFrame[] iframes = desk.getAllFrames();
for (JInternalFrame iframe : iframes) {
if (iframe.getTitle().equals(title)) return iframe;
}
return null;
} //根据JInternalFrame在打开的文件集合中获取相应的文件对象
public EditFile getEditFile(JInternalFrame iframe) {
for (EditFile openFile : openFiles) {
if (openFile.getIframe().equals(iframe)) return openFile;
}
return null;
} //询问是否要保存, 参数为将被打开的文件
public void askSave(EditFile file) {
//该份文件修改过没有保存
if (!file.isSaved()) {
//弹出询问
int val = JOptionPane.showConfirmDialog(this, "是否要保存?", "询问",
JOptionPane.YES_NO_OPTION);
//点击了需要保存
if (JOptionPane.YES_OPTION == val) {
//调用EditorFrame的保存方法对文件进行保存
saveFile(file);
}
}
} //用于保存当前所打开的文件
public void saveFile(EditFile file) {
if (file == null) return;
//调用中介者对象的方法去保存文件
String result = saveMediator.doSave(this);
//将结果放到信息显示区的文本域中
infoArea.setText(result);
//写完文件后,设置当前文件的保存状态为true,表示已经保存
file.setSaved(true);
} //关闭一个窗口
public void closeIFrame(JInternalFrame iframe) {
//获得当前的文件,即要关闭的文件对象
EditFile closeFile = getEditFile(iframe);
//设置本类中的currentFile属性
afterClose(closeFile);
//获得该iframe在tab页中对应的索引
int index = getTabIndex(iframe.getTitle());
//从tab页中删除
getTabPane().remove(index);
//从打开的文件集合中删除这个关闭的文件
openFiles.remove(closeFile);
} //当关闭一份文件后,设置本对象的currentFile属性
private void afterClose(EditFile closeFile) {
//获取关闭文件在打开文件集合中的索引
int openFilesIndex = getEditFileIndex(closeFile);
//如果该文件已经是所有打开的文件的最后一份
if (this.openFiles.size() == 1) {
this.currentFile = null;
} else {//如果还有其他文件,判断关闭的文件位置
if (openFilesIndex == 0) {
//如果关闭的文件是第一份,拿集合中的第二份
this.currentFile = openFiles.get(openFilesIndex + 1);
} else if (openFilesIndex == (openFiles.size() - 1)) {
//如果关闭的是最后一份,取倒数第二份
this.currentFile = openFiles.get(openFiles.size() - 2);
} else {
//不是第一份,也不是最后一份
this.currentFile = openFiles.get(openFilesIndex - 1);
}
}
} //获取editFile在打开的文件集合中的索引
private int getEditFileIndex(EditFile editFile) {
for (int i = 0; i < this.openFiles.size(); i++) {
if (openFiles.get(i).equals(editFile)) return i;
}
return -1;
} //返回项目树当前所选中的节点所属的项目节点对应的目录
public File getCurrentProject() {
//获取根节点(工作空间)
ProjectTreeNode root = (ProjectTreeNode)getSelectNode().getRoot();
//获取根节点下的所有子节点(即项目节点集合)
List<ProjectTreeNode> projects = root.getChildren();
ProjectTreeNode selectNode = getSelectNode();
if (selectNode != null) {
for (ProjectTreeNode project : projects) {
//当前先中节点是该project下的子节点
if (selectNode.isNodeAncestor(project)) {
return project.getFile();
}
}
}
return null;
} //运行文件的方法
public void run() {
//运行前先保存
saveFile(getCurrentFile());
//将结果显示
String result = runHandler.run(this);
infoArea.setText(result);
} }
class FileChooser extends JFileChooser { private EditorFrame editorFrame; public FileChooser(EditorFrame editorFrame){
//调用父类的构造器
//利用editorFrame的工作空间作为文件选择器打开时的默认目录
super(editorFrame.getWorkSpace().getFolder());
this.editorFrame = editorFrame;
showOpenDialog(editorFrame);
} public void approveSelection() {
File file = getSelectedFile();
//设置树当前选择的节点为null, 即树没有被选中
this.editorFrame.getTree().setSelectionPath(null);
this.editorFrame.openFile(file);
super.approveSelection();
}
}
EditorFrame
package org.crazyit.editor; import java.awt.Color;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner; import javax.swing.JTextPane;
import javax.swing.text.Element;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument; import org.crazyit.editor.util.FileUtil; /**
* 编辑界面
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class EditPane extends JTextPane { //样式文档对象
protected StyledDocument doc;
//构造一个文本格式器
protected SyntaxFormatter formatter = new SyntaxFormatter("java.stx");
private SimpleAttributeSet quotAttr = new SimpleAttributeSet();
//保存文档改变的开始位置
private int docChangeStart = 0;
//保存文档改变的长度
private int docChangeLength = 0;
//定义文档中行数文本的外观属性
private SimpleAttributeSet lineAttr = new SimpleAttributeSet(); public EditPane(File file) {
this.setText(FileUtil.readFile(file));
this.doc = getStyledDocument();
//设置该文档的页边距
this.setMargin(new Insets(3, 40, 0, 0));
syntaxParse();
//添加按键监听器,当按键松开时进行语法分析
this.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent ke)
{
syntaxParse();
}
});
}
//
// //重写父类方法,使JTextPane不会自动换行
// public boolean getScrollableTracksViewportWidth() {
// return (getSize().width < getParent().getSize().width - 100);
// }
//
// //重写父类方法,使JTextPane不会自动换行
// public void setSize(Dimension d) {
// if (d.width < getParent().getSize().width) {
// d.width = getParent().getSize().width;
// }
// d.width += 100;
// super.setSize(d);
// } public void syntaxParse() {
try {
//获取文档的根元素,即文档内的全部内容
Element root = doc.getDefaultRootElement();
//获取文档中光标插入符的位置
int cursorPos = this.getCaretPosition();
int line = root.getElementIndex(cursorPos);
//获取光标所在位置的行
Element para = root.getElement(line);
//定义光标所在行的行头在文档中位置
int start = para.getStartOffset();
//如果文档修改位置比当前行还前
if (start > docChangeStart) {
start = docChangeStart;
}
//定义被修改部分的长度
int length = para.getEndOffset() - start;
if (length < docChangeLength) {
length = docChangeLength + 1;
}
//取出所有被修改的字符串
String s = doc.getText(start, length);
//以空格、点号等作为分隔符
String[] tokens = s.split("\\s+|\\.|\\(|\\)|\\{|\\}|\\[|\\]");
//定义当前分析单词的在s字符串中的开始位置
int curStart = 0;
boolean isQuot = false;
for (String token : tokens) {
//找出当前分析单词在s字符串的中位置
int tokenPos = s.indexOf(token , curStart);
if (isQuot && (token.endsWith("\"") || token.endsWith("\'"))) {
doc.setCharacterAttributes(start + tokenPos, token.length(), quotAttr, false);
isQuot = false;
}
else if (isQuot && !(token.endsWith("\"") || token.endsWith("\'"))) {
doc.setCharacterAttributes(start + tokenPos, token.length(), quotAttr, false);
}
else if ((token.startsWith("\"") || token.startsWith("\'"))
&& (token.endsWith("\"") || token.endsWith("\'"))) {
doc.setCharacterAttributes(start + tokenPos, token.length(), quotAttr, false);
}
else if ((token.startsWith("\"") || token.startsWith("\'"))
&& !(token.endsWith("\"") || token.endsWith("\'"))) {
doc.setCharacterAttributes(start + tokenPos, token.length(), quotAttr, false);
isQuot = true;
}
else {
//使用格式器对当前单词设置颜色
formatter.setHighLight(doc , token , start + tokenPos, token.length());
}
//开始分析下一个单词
curStart = tokenPos + token.length();
}
}
catch (Exception ex) {
ex.printStackTrace();
}
}
//重画该组件,设置行号
public void paint(Graphics g){
super.paint(g);
Element root = doc.getDefaultRootElement();
//获得行号
int line = root.getElementIndex(doc.getLength());
//设置颜色
g.setColor(new Color(230, 230, 230));
//绘制行数矩形框
g.fillRect(0, 0, this.getMargin().left - 10, getSize().height);
//设置行号的颜色
g.setColor(new Color(40, 40, 40));
//每行绘制一个行号
for (int count = 0, j = 1; count <= line; count++, j++) {
g.drawString(String.valueOf(j), 3,
(int)((count + 1) * 1.5020 * StyleConstants.getFontSize(lineAttr)));
}
}
}
class SyntaxFormatter {
//以一个Map保存关键字和颜色的对应关系
private Map<SimpleAttributeSet , ArrayList> attMap
= new HashMap<SimpleAttributeSet , ArrayList>();
//定义文档的正常文本的外观属性
SimpleAttributeSet normalAttr = new SimpleAttributeSet();
public SyntaxFormatter(String syntaxFile) {
//设置正常文本的颜色、大小
StyleConstants.setForeground(normalAttr, Color.BLACK);
//StyleConstants.setFontSize(normalAttr, 14);
//创建一个Scanner对象,负责根据语法文件加载颜色信息
Scanner scaner = null;
try {
scaner = new Scanner(new File(syntaxFile));
}
catch (FileNotFoundException e) {
throw new RuntimeException("丢失语法文件:" + e.getMessage());
}
int color = -1;
ArrayList<String> keywords = new ArrayList<String>();
//不断读取语法文件的内容行
while(scaner.hasNextLine()) {
String line = scaner.nextLine();
//如果当前行以#开头
if (line.startsWith("#")) {
if (keywords.size() > 0 && color > -1) {
//取出当前行的颜色值,并封装成SimpleAttributeSet对象
SimpleAttributeSet att = new SimpleAttributeSet();
StyleConstants.setForeground(att, new Color(color));
//StyleConstants.setFontSize(att, 14);
//将当前颜色和关键字List对应起来
attMap.put(att , keywords);
}
//重新创建新的关键字List,为下一个语法格式准备
keywords = new ArrayList<String>();
color = Integer.parseInt(line.substring(1) , 16);
} else {
//对于普通行,每行内容添加到关键字List里
if (line.trim().length() > 0) {
keywords.add(line.trim());
}
}
}
//把最后的关键字和颜色对应起来
if (keywords.size() > 0 && color > -1) {
SimpleAttributeSet att = new SimpleAttributeSet();
StyleConstants.setForeground(att, new Color(color));
attMap.put(att , keywords);
}
}
//返回该格式器里正常文本的外观属性
public SimpleAttributeSet getNormalAttributeSet() {
return normalAttr;
}
//设置语法高亮
public void setHighLight(StyledDocument doc , String token ,
int start , int length) {
//保存需要对当前单词对应的外观属性
SimpleAttributeSet currentAttributeSet = null;
outer :
for (SimpleAttributeSet att : attMap.keySet())
{
//取出当前颜色对应的所有关键字
ArrayList keywords = attMap.get(att);
//遍历所有关键字
for (Object keyword : keywords)
{
//如果该关键字与当前单词相同
if (keyword.toString().equals(token))
{
//跳出循环,并设置当前单词对应的外观属性
currentAttributeSet = att;
break outer;
}
}
}
//如果当前单词对应的外观属性不为空
if (currentAttributeSet != null){
//设置当前单词的颜色
doc.setCharacterAttributes(start, length, currentAttributeSet, false);
} else {//否则使用普通外观来设置该单词
doc.setCharacterAttributes(start, length, normalAttr, false);
}
}
}
EditPane
package org.crazyit.editor; import javax.swing.JInternalFrame;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent; import org.crazyit.editor.commons.EditFile; /**
* 窗口监听器
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class IFrameListener extends InternalFrameAdapter { private EditorFrame editorFrame; public IFrameListener(EditorFrame editorFrame) {
this.editorFrame = editorFrame;
} public void internalFrameActivated(InternalFrameEvent e) {
JInternalFrame iframe = editorFrame.getDesk().getSelectedFrame();
int tapIndex = editorFrame.getTabIndex(iframe.getTitle());
editorFrame.getTabPane().setSelectedIndex(tapIndex);
} public void internalFrameClosing(InternalFrameEvent e) {
//获取当前关闭操作所对应的JInternalFrame
JInternalFrame iframe = (JInternalFrame)e.getSource();
//获取当前操作的文件
EditFile editFile = editorFrame.getCurrentFile();
//询问是否要保存
editorFrame.askSave(editFile);
//关闭当前的iframe
editorFrame.closeIFrame(iframe);
}
}
IFrameListener
package org.crazyit.editor; import java.awt.Label;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File; import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField; import org.crazyit.editor.commons.WorkSpace; /**
* 工作空间界面
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class SpaceFrame extends JFrame { private JPanel mainPanel; private JLabel infoLabel; private JPanel chosePanel; private JLabel workTextLabel; //工作空间中显示用户选择文件目录的JTextField
private JTextField pathText; private JButton choseButton; private JPanel buttonPanel; //工作空间中的确定按钮
private JButton confirmButton; private JButton cancelButton; private SpaceChooser chooser; //用户选择的文件目录对象
private File folder; public SpaceFrame(EditorFrame editorFrame) {
mainPanel = new JPanel();
infoLabel = new JLabel("请选择工作空间");
chosePanel = new JPanel();
workTextLabel = new JLabel("工作空间: ");
pathText = new JTextField("", 40);
choseButton = new JButton("选择");
buttonPanel = new JPanel();
confirmButton = new JButton("确定");
cancelButton = new JButton("取消");
chooser = new SpaceChooser(this); //设置主Panel的布局
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
mainPanel.add(infoLabel);
//设置选择区的布局
chosePanel.setLayout(new BoxLayout(chosePanel, BoxLayout.X_AXIS));
choseButton.addActionListener(new ChoseButtonListener(chooser));
pathText.setEditable(false);
chosePanel.add(workTextLabel);
chosePanel.add(pathText);
chosePanel.add(choseButton);
mainPanel.add(chosePanel); confirmButton.setEnabled(false);
//为确定按钮添加确定的事件, 即创建一个WorkSpace对象
confirmButton.addActionListener(new ConfirmButtonListener(this, editorFrame));
buttonPanel.add(confirmButton);
buttonPanel.add(new Label(" "));
buttonPanel.add(cancelButton);
//为取消按钮添加退出事件
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
System.exit(0);
}
});
mainPanel.add(buttonPanel);
add(mainPanel);
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocation(300, 200);
setResizable(false);
} public File getFolder() {
return folder;
} public void setFolder(File folder) {
this.folder = folder;
} public JTextField getPathText() {
return pathText;
} public JButton getConfirmButton() {
return confirmButton;
}
} /**
* 确定按钮的监听器
* @author hp
*
*/
class ConfirmButtonListener implements ActionListener { private SpaceFrame spaceFrame; private EditorFrame editorFrame; public ConfirmButtonListener(SpaceFrame spaceFrame, EditorFrame editorFrame) {
this.spaceFrame = spaceFrame;
this.editorFrame = editorFrame;
} public void actionPerformed(ActionEvent arg0) {
//调EditorFrame的initFrame方法初始化界面
editorFrame.initFrame(new WorkSpace(spaceFrame.getFolder(), editorFrame));
//将EditorFrame设为可见
editorFrame.setVisible(true);
editorFrame.setSize(900, 600);
//让工作选择空间界面不可见
spaceFrame.setVisible(false);
}
} /**
* 选择按钮的监听器
* @author hp
*
*/
class ChoseButtonListener implements ActionListener { private JFileChooser chooser; public ChoseButtonListener(JFileChooser chooser) {
this.chooser = chooser;
} @Override
public void actionPerformed(ActionEvent arg0) {
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.showOpenDialog(null);
} } /**
* 文件选择器
* @author hp
*
*/
class SpaceChooser extends JFileChooser { private SpaceFrame spaceFrame; //需要将SpaceFrame作为构造参数
public SpaceChooser(SpaceFrame spaceFrame) {
//设置选择器打开时的目录
super("/");
this.spaceFrame = spaceFrame;
} //重写父类的选择文件方法
public void approveSelection() {
//获取用户选择的文件
File folder = getSelectedFile();
//设置SpaceFrame的属性folder的值
spaceFrame.setFolder(folder);
//设置SpaceFrame文本框
spaceFrame.getPathText().setText(folder.getAbsolutePath());
//设置确定按钮可用
spaceFrame.getConfirmButton().setEnabled(true);
//调用父类的选择文件方法
super.approveSelection();
}
}
SpaceFrame
package org.crazyit.editor; import javax.swing.JInternalFrame;
import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener; import org.crazyit.editor.commons.EditFile; /**
* tab页转换监听器
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class TabListener implements ChangeListener { private EditorFrame editorFrame; public TabListener(EditorFrame editorFrame) {
this.editorFrame = editorFrame;
} public void stateChanged(ChangeEvent e) {
//获得当前点击tab页对象
JTabbedPane tab = (JTabbedPane)e.getSource();
//获得tab页的索引
int index = tab.getSelectedIndex();
if (index == -1) return;
//根据tab页的tips(文件的绝对路径)获得当前的JInternalFrame对象
JInternalFrame currentFrame = editorFrame.getIFrame(tab.getToolTipTextAt(index));
//让当前点击的JInternalFrame对象可见
editorFrame.showIFrame(currentFrame);
//根据当前的JInternalFrame对象获得对应的文件
EditFile currentFile = editorFrame.getEditFile(currentFrame);
//设置EditorFrame当前编辑的文件为tab对应的文件
editorFrame.setCurrentFile(currentFile);
} }
TabListener
package org.crazyit.editor; import org.crazyit.editor.tree.TreeCreator;
import org.crazyit.editor.tree.TreeCreatorImpl; /**
* 程序入口类
*
* @author yangenxiong yangenxiong2009@gmail.com
* @version 1.0
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br>Copyright (C), 2009-2010, yangenxiong
* <br>This program is protected by copyright laws.
*/
public class Main { public static void main(String[] args) {
TreeCreator treeCreator = new TreeCreatorImpl();
//创建EditorFrame,暂时不用设置可见
EditorFrame editorFrame = new EditorFrame("ide", treeCreator);
//将editorFrame对象作为SpaceFrame的构造参数
SpaceFrame spaceFrame = new SpaceFrame(editorFrame);
//让SpaceFrame可见
spaceFrame.setVisible(true);
}
}
Main