/*******************************************************************************
* Copyright (c) 2015 - 2016
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*******************************************************************************/
package jsettlers.main.swing.foldertree;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import javax.swing.SwingUtilities;
import javax.swing.tree.TreeNode;
import jsettlers.main.swing.resources.SettlersFolderChecker;
/**
* Node to display file / folders
*
* @author Andreas Butti
*/
public class FilesystemTreeNode implements TreeNode {
/**
* If the children are already loaded
*/
protected boolean loaded = false;
/**
* If this is a settler folder
*/
private boolean settlersFolder = false;
/**
* To expand the node on the first selection
*/
private boolean wasExpanded = false;
/**
* Current child list
*/
private List<FilesystemTreeNode> children = new ArrayList<>();
/**
* Parent node
*/
private TreeNode parent;
/**
* The file represented by this node
*/
private final File file;
/**
* Constructor
*
* @param file
* The file to represent
*/
public FilesystemTreeNode(File file) {
this.file = file;
}
/**
* @return The file
*/
public File getFile() {
return file;
}
/**
* @return Root node
*/
private RootTreeNode findRoot() {
TreeNode node = getParent();
while (true) {
if (node == null) {
return null;
}
if (node instanceof RootTreeNode) {
return (RootTreeNode) node;
}
node = node.getParent();
}
}
/**
* Load the children of this folder, if a folder
*/
private void loadChildren() {
RootTreeNode root = findRoot();
if (root == null) {
this.children = calculateChildrenNodes();
} else {
root.loadAsynchron(this);
}
}
/**
* @return true if this node already was expanded
*/
public boolean wasExpanded() {
return wasExpanded;
}
/**
* @param wasExpanded
* true if this node already was expanded
*/
public void setWasExpanded(boolean wasExpanded) {
this.wasExpanded = wasExpanded;
}
/**
* @return if this is a settler folder
*/
public boolean isSettlersFolder() {
return settlersFolder;
}
/**
* Load children if not loaded
*/
private synchronized void loadIfNotLoaded() {
if (!loaded) {
loaded = true;
loadChildren();
}
}
@Override
public boolean isLeaf() {
loadIfNotLoaded();
if (children != null) {
return children.isEmpty();
}
return true;
}
@Override
public int getChildCount() {
loadIfNotLoaded();
return children.size();
}
/**
* Add a node
*
* @param node
* Node
*/
public void add(FilesystemTreeNode node) {
children.add(node);
node.setParent(this);
}
/**
* Calculates the children and returns them.
*
* @return
*/
private List<FilesystemTreeNode> calculateChildrenNodes() {
if (file == null) {
return Collections.emptyList();
}
if (!file.isDirectory()) {
return Collections.emptyList();
}
File[] files = file.listFiles();
if (files == null) {
return Collections.emptyList();
}
boolean snd = false;
boolean gfx = false;
List<FilesystemTreeNode> list = new ArrayList<FilesystemTreeNode>();
for (File file : files) {
if (file.isDirectory()) {
FilesystemTreeNode node = new FilesystemTreeNode(file);
list.add(node);
node.setParent(this);
if ("gfx".equalsIgnoreCase(file.getName())) {
gfx = true;
} else if ("snd".equalsIgnoreCase(file.getName())) {
snd = true;
}
}
}
if (snd && gfx) {
settlersFolder = SettlersFolderChecker.checkSettlersFolder(file.getAbsolutePath()).isValidSettlersFolder();
} else {
settlersFolder = false;
}
Collections.sort(list, new Comparator<FilesystemTreeNode>() {
@Override
public int compare(FilesystemTreeNode o1, FilesystemTreeNode o2) {
return o1.getFile().getName().compareTo(o2.getFile().getName());
}
});
return list;
}
public void loadChildrenNodesAsync() {
final List<FilesystemTreeNode> childrenNodes = this.calculateChildrenNodes();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
FilesystemTreeNode.this.children = childrenNodes;
findRoot().nodeStructureChanged(FilesystemTreeNode.this);
}
});
}
@Override
public TreeNode getChildAt(int childIndex) {
return children.get(childIndex);
}
@Override
public TreeNode getParent() {
return parent;
}
/**
* @param parent
* The parent tree node
*/
public void setParent(TreeNode parent) {
this.parent = parent;
}
@Override
public int getIndex(TreeNode node) {
return children.indexOf(node);
}
@Override
public boolean getAllowsChildren() {
return true;
}
@Override
public Enumeration<?> children() {
return Collections.enumeration(children);
}
}