view java/src/uk/ac/qmul/eecs/ccmi/gui/filechooser/FileSystemTreeNode.java @ 1:e3935c01cde2 tip

moved license of PdPersistenceManager to the beginning of the file
author Fiore Martin <f.martin@qmul.ac.uk>
date Tue, 08 Jul 2014 19:52:03 +0100
parents 78b7fc5391a2
children
line wrap: on
line source
/*  
 CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
  
 Copyright (C) 2011  Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/  

package uk.ac.qmul.eecs.ccmi.gui.filechooser;

import java.io.File;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.ResourceBundle;

import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileSystemView;
import javax.swing.tree.TreeNode;

/*
 * The tree nodes of a FileSystemTree. Each nodes represent either a directory or a file 
 * in the local file system where the CCmI Editor is executed. 
 *
 */
class FileSystemTreeNode implements TreeNode {
	
	public static FileSystemTreeNode getRootNode(FileFilter filter){
		return new FileSystemTreeNode(filter){
			@Override
			public boolean getAllowsChildren(){
				return true;
			}
			@Override
			public String toString(){
				return ResourceBundle.getBundle(SpeechFileChooser.class.getName()).getString("tree_root.label");
			}
		};
	}
	
	private FileSystemTreeNode(FileFilter filter){ // constructor for root
		fileSystemView = FileSystemView.getFileSystemView();
		parent = null;
		this.filter = filter;
		containedFiles = File.listRoots();
		
		children = new FileSystemTreeNode[containedFiles.length];
		for(int i=0; i< children.length; i++){
			children[i] = new FileSystemTreeNode(this, containedFiles[i],filter);
			children[i].isFileSystemRoot = true;
		}
	}
	
	private FileSystemTreeNode(TreeNode parent, File file, FileFilter filter){
		fileSystemView = FileSystemView.getFileSystemView();
		this.file = file;
		this.parent = parent;
		this.filter = filter;
		
		if(file.isDirectory()){
			containedFiles = file.listFiles();
			if(containedFiles == null ) 
				containedFiles = new File[0];
			ArrayList<File> fileList = new ArrayList<File>(containedFiles.length);
			for(File f : containedFiles){
				if(f.isDirectory() || filter.accept(f))
					fileList.add(f);
			}
			Collections.sort(fileList,new FileSystemComparator());
			containedFiles = new File[fileList.size()];
			containedFiles = fileList.toArray(containedFiles);
		}else{
			containedFiles = new File[0];
		}
		children = new FileSystemTreeNode[containedFiles.length];
	}

	public FileSystemTreeNode getNextSibling(){
		if(parent == null)
			return null;
		int thisIndex = parent.getIndex(this);
		int numChildren = parent.getChildCount();
		if(thisIndex == numChildren-1)
			return null;
		return (FileSystemTreeNode)parent.getChildAt(thisIndex+1);
	}
	
	public FileSystemTreeNode getPreviousSibling(){
		if(parent == null)
			return null;
		int thisIndex = parent.getIndex(this);
		if(thisIndex == 0)
			return null;
		return (FileSystemTreeNode)parent.getChildAt(thisIndex-1);
	}
	
	public TreeNode[] getPath(){
		List<TreeNode> pathList = new LinkedList<TreeNode>();
		pathList.add(0, this);
		TreeNode parent = getParent();
		while(parent != null){
			pathList.add(0,parent);
			parent = parent.getParent();
		}
		TreeNode[] path = new TreeNode[pathList.size()];
		return pathList.toArray(path);
	}
	
	public File getFile(){
		return file;
	}
	
	public String spokenText(){
		String fileType = "dir";
		if(file != null && file.isFile())
			fileType = "file";
		return MessageFormat.format(
				ResourceBundle.getBundle(SpeechFileChooser.class.getName()).getString(fileType), 
				toString()
				); 
	}
	
	@Override
	public String toString(){
		if(isFileSystemRoot){
			String name = fileSystemView.getSystemDisplayName(file);
			if(name.isEmpty())
				name = file.toString();
			return name;
		}
		return file.getName();
	}
	
	/* --- TREE NODE INTEFACE IMPLEMENTATION --- */	
	@Override
	public Enumeration<FileSystemTreeNode> children() {
		return new Enumeration<FileSystemTreeNode>(){
			@Override
			public boolean hasMoreElements() {
				return (index < children.length);
			}

			@Override
			public FileSystemTreeNode nextElement() {
				return new FileSystemTreeNode(parent, containedFiles[index++],filter);
			}
			int index = 0;
		};
	}

	@Override
	public boolean getAllowsChildren() {
		return file.isFile();
	}

	@Override
	public FileSystemTreeNode getChildAt(int index) throws IndexOutOfBoundsException {
		/* builds the children lazily */
		if(children[index] == null)
			children[index] = new FileSystemTreeNode(this, containedFiles[index],filter);
		return children[index];
	}

	@Override
	public int getChildCount() {
		return containedFiles.length;
	}

	@Override
	public int getIndex(TreeNode n) {
		FileSystemTreeNode fileSystemTreeNode = (FileSystemTreeNode)n;
		for(int i=0; i< containedFiles.length; i++){
			if(fileSystemTreeNode.file.equals(containedFiles[i]))
				return i;
		}
		return -1;
	}

	@Override
	public TreeNode getParent() {
		return parent;
	}

	@Override
	public boolean isLeaf() {
		return (containedFiles.length == 0);
	}
	
	private File[] containedFiles;
	private File file;
	private FileSystemTreeNode[] children;
	private TreeNode parent;
	private FileSystemView fileSystemView;
	private FileFilter filter;
	private boolean isFileSystemRoot;
}

class FileSystemComparator implements Comparator<File>{
	@Override
	public int compare(File f1, File f2) {
		if(f1.isDirectory() && f2.isFile())
			return -1;
		else if(f1.isFile() && f2.isDirectory())
			return 1;
		else
			return f1.compareTo(f2);
	}
}