package app.navigps.gui.searchServices.swing;
import java.awt.Rectangle;
import java.util.Hashtable;
import java.util.Vector;
import javax.swing.JTree;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
/**
*
* @author wara
*/
public class JCheckBoxTree extends JTree{
Vector checkedPaths = new Vector();
JCheckBoxTreeRenderer checkBoxCellRenderer;
/**
*
* @param value
*/
public JCheckBoxTree(Object[] value) {
super(value);
}
/**
*
* @param value
*/
public JCheckBoxTree(Vector<?> value){
super(value);
}
/**
*
* @param value
*/
public JCheckBoxTree(Hashtable<?,?> value){
super(value);
}
/**
*
* @param root
*/
public JCheckBoxTree(TreeNode root){
super(root);
}
/**
*
* @param root
* @param asksAllowsChildren
*/
public JCheckBoxTree(TreeNode root, boolean asksAllowsChildren){
super(root, asksAllowsChildren);
}
/**
*
* @param newModel
*/
public JCheckBoxTree(TreeModel newModel){
super(newModel);
}
/**
*
*/
public JCheckBoxTree() {
super();
init();
}
private void init(){
getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
checkBoxCellRenderer= new JCheckBoxTreeRenderer();
setCellRenderer(checkBoxCellRenderer);
addMouseListener(new JCheckBoxTreeMouseListener(this));
}
/**
*
* @param path
*/
public void setChecked(TreePath path) {
if(checkedPaths.contains(path)) {
checkedPaths.remove(path);
setParentsUnchecked(path);
setDescendantsUnchecked(path);
} else {
checkedPaths.add(path);
setParentsChecked(path);
setDescendantsChecked(path);
}
setParentsChecked(path);
repaintPath(path);
}
private void setDescendantsChecked(TreePath path) {
if(!hasBeenExpanded(path)) {
return;
}
Object component = path.getLastPathComponent();
int childCount = getModel().getChildCount(component);
for(int i = 0; i < childCount; i++) {
Object childComponent = getModel().getChild(component, i);
TreePath childComponentPath = path.pathByAddingChild(childComponent);
if(!checkedPaths.contains(childComponentPath)) {
checkedPaths.add(childComponentPath);
repaintPath(childComponentPath);
}
setDescendantsChecked(childComponentPath);
}
}
private void setDescendantsUnchecked(TreePath path) {
if(hasBeenExpanded(path)) {
Object cmp = path.getLastPathComponent();
int component = getModel().getChildCount(cmp);
for(int i = 0; i < component; i++) {
Object childComponent = getModel().getChild(cmp, i);
TreePath childComponentPath = path.pathByAddingChild(childComponent);
if(checkedPaths.contains(childComponentPath)) {
checkedPaths.remove(childComponentPath);
repaintPath(childComponentPath);
}
setDescendantsUnchecked(childComponentPath);
}
}
}
/**
*
* @param path
* @return
*/
public boolean isAnyChildChecked(TreePath path) {
if ((path != null) && (checkedPaths != null)) {
for(int i=0; i < checkedPaths.size(); i++) {
TreePath checkedPath = (TreePath)checkedPaths.elementAt(i);
if(path.isDescendant(checkedPath)) {
return true;
}
}
}
return false;
}
private boolean isParentChecked(TreePath path) {
if ((path != null) || (checkedPaths != null)){
if (checkedPaths == null) return false;
TreePath parentPath = path.getParentPath();
if(checkedPaths.contains(parentPath)) {
return true;
}
}
return false;
}
private void setParentsChecked(TreePath path) {
TreePath parentPath = path.getParentPath();
if(parentPath != null){
boolean shouldAdd = true;
Object component = parentPath.getLastPathComponent();
int childCount = getModel().getChildCount(component);
for(int i=0; i<childCount;i++) {
Object childComponent = getModel().getChild(component, i);
TreePath childPath = parentPath.pathByAddingChild(childComponent);
if(!checkedPaths.contains(childPath)) {
shouldAdd = false;
}
}
if(shouldAdd) {
checkedPaths.add(parentPath);
}
repaintPath(parentPath);
setParentsChecked(parentPath);
}
}
private void setParentsUnchecked(TreePath path) {
TreePath parentPath = path.getParentPath();
if (parentPath != null){
if(checkedPaths.contains(parentPath)) {
checkedPaths.remove(parentPath);
}
repaintPath(parentPath);
setParentsUnchecked(parentPath);
}
}
/**
*
* @param path
* @return
*/
public boolean isChecked(TreePath path) {
return (checkedPaths.contains(path));
}
private void repaintPath(TreePath path) {
Rectangle pathRect = getPathBounds(path);
if(pathRect != null){
repaint(pathRect.x, pathRect.y, pathRect.width, pathRect.height);
}
}
}