// License: GPL. For details, see Readme.txt file.
package org.openstreetmap.gui.jmapviewer.checkBoxTree;
import java.awt.BorderLayout;
import java.awt.event.MouseAdapter;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import org.openstreetmap.gui.jmapviewer.AbstractLayer;
import org.openstreetmap.gui.jmapviewer.Layer;
import org.openstreetmap.gui.jmapviewer.LayerGroup;
/**
* JTree for checkBox Tree Layers
*
* @author galo
*/
public class CheckBoxTree extends JTree {
/** Serial Version UID */
private static final long serialVersionUID = 6943401106938034256L;
private final CheckBoxNodeEditor editor;
public CheckBoxTree(AbstractLayer layer) {
this(new CheckBoxNodeData(layer));
}
public CheckBoxTree(String rootName) {
this(new CheckBoxNodeData(rootName));
}
public CheckBoxTree(CheckBoxNodeData root) {
this(new DefaultMutableTreeNode(root));
}
public CheckBoxTree(DefaultMutableTreeNode node) {
super(new DefaultTreeModel(node));
final CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer();
setCellRenderer(renderer);
editor = new CheckBoxNodeEditor(this);
setCellEditor(editor);
setEditable(true);
// listen for changes in the model (including check box toggles)
getModel().addTreeModelListener(new TreeModelListener() {
@Override
public void treeNodesChanged(final TreeModelEvent e) {
DefaultTreeModel model = (DefaultTreeModel) e.getSource();
Object[] nodes = e.getChildren();
DefaultMutableTreeNode node;
if (nodes == null || nodes.length == 0) {
node = node(model.getRoot());
} else {
node = node(nodes[0]);
}
nodeChanged(node);
repaint();
}
@Override
public void treeNodesInserted(final TreeModelEvent e) {
//System.out.println("nodes inserted");
}
@Override
public void treeNodesRemoved(final TreeModelEvent e) {
//System.out.println("nodes removed");
}
@Override
public void treeStructureChanged(final TreeModelEvent e) {
//System.out.println("structure changed");
}
});
}
public void addNodeListener(MouseAdapter listener) {
editor.addNodeListener(listener);
}
public static void main(final String[] args) {
final DefaultMutableTreeNode root = new DefaultMutableTreeNode(new CheckBoxNodeData("Root", Boolean.TRUE));
final DefaultMutableTreeNode accessibility =
add(root, "Accessibility", true);
add(accessibility, "Move system caret with focus/selection changes", false);
add(accessibility, "Always expand alt text for images", true);
root.add(accessibility);
final DefaultMutableTreeNode browsing =
new DefaultMutableTreeNode(new CheckBoxNodeData("Browsing", null));
add(browsing, "Notify when downloads complete", true);
add(browsing, "Disable script debugging", true);
add(browsing, "Use AutoComplete", true);
add(browsing, "Browse in a new process", false);
root.add(browsing);
final CheckBoxTree tree = new CheckBoxTree(root);
((DefaultMutableTreeNode) tree.getModel().getRoot()).add(new DefaultMutableTreeNode(new CheckBoxNodeData("gggg", null)));
((DefaultTreeModel) tree.getModel()).reload();
// listen for changes in the selection
tree.addTreeSelectionListener(new TreeSelectionListener() {
@Override
public void valueChanged(final TreeSelectionEvent e) {
//System.out.println("selection changed");
}
});
// show the tree on screen
final JFrame frame = new JFrame("CheckBox Tree");
final JScrollPane scrollPane = new JScrollPane(tree);
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 150);
frame.setVisible(true);
}
private static Boolean childStatus(DefaultMutableTreeNode node) {
Boolean status = data(node.getChildAt(0)).isSelected();
for (int i = 1; i < node.getChildCount() && status != null; i++) {
if (!status.equals(
data(node.getChildAt(i)).isSelected()
))
return null;
}
return status;
}
private static void changeParents(DefaultMutableTreeNode node) {
if (node != null) {
DefaultMutableTreeNode parent = node(node.getParent());
if (parent != null) {
CheckBoxNodeData dataParent = data(parent);
Boolean childStatus = childStatus(parent);
if (childStatus != null && !childStatus.equals(dataParent.isSelected())) {
dataParent.setSelected(childStatus);
changeParents(parent);
}
}
}
}
private static void nodeChanged(DefaultMutableTreeNode node) {
if (node != null) {
changeParents(node);
setChildrens(node, data(node).isSelected());
}
}
private static void setChildrens(DefaultMutableTreeNode node, Boolean value) {
for (int i = 0; i < node.getChildCount(); i++) {
DefaultMutableTreeNode childNode = node(node.getChildAt(i));
if (!data(childNode).isSelected().equals(data(node).isSelected())) {
data(childNode).setSelected(data(node).isSelected());
setChildrens(childNode, value);
}
}
}
public DefaultMutableTreeNode rootNode() {
return node(getModel().getRoot());
}
public LayerGroup rootLayer() {
return (LayerGroup) rootData().getAbstractLayer();
}
public CheckBoxNodeData rootData() {
return data(rootNode());
}
private static DefaultMutableTreeNode node(Object node) {
return (DefaultMutableTreeNode) node;
}
public static CheckBoxNodeData data(DefaultMutableTreeNode node) {
return node == null ? null : (CheckBoxNodeData) node.getUserObject();
}
private static CheckBoxNodeData data(Object node) {
return data(node(node));
}
private static DefaultMutableTreeNode add(final DefaultMutableTreeNode parent, final String text, final boolean checked) {
final CheckBoxNodeData data = new CheckBoxNodeData(text, checked);
final DefaultMutableTreeNode node = new DefaultMutableTreeNode(data);
parent.add(node);
return node;
}
public static CheckBoxNodeData createNodeData(AbstractLayer layer) {
return new CheckBoxNodeData(layer);
}
public static DefaultMutableTreeNode createNode(AbstractLayer layer) {
return new DefaultMutableTreeNode(createNodeData(layer));
}
/*public DefaultMutableTreeNode addLayerGroup(LayerGroup group) {
if (group != null){
if (group.getParent() == null){
return add(rootNode(), group);
} else {
DefaultMutableTreeNode parentGroup = searchNode(group.getParent());
if(parentGroup==null) parentGroup = addLayerGroup(group.getParent());
DefaultMutableTreeNode node = add(parentGroup, group);
return node;
}
}else return null;
}*/
public Layer addLayer(String name) {
Layer layer = new Layer(name);
addLayer(layer);
return layer;
}
public DefaultMutableTreeNode addLayer(AbstractLayer layer) {
if (layer != null) {
DefaultMutableTreeNode parent;
if (layer.getParent() == null) {
rootLayer().add(layer);
parent = rootNode();
} else {
parent = searchNode(layer.getParent());
if (parent == null)
parent = addLayer(layer.getParent());
}
return add(parent, layer);
} else return null;
}
public DefaultMutableTreeNode add(DefaultMutableTreeNode parent, final AbstractLayer layer) {
layer.setVisible(data(parent).isSelected());
DefaultMutableTreeNode node = createNode(layer);
parent.add(node);
((DefaultTreeModel) getModel()).reload();
//System.out.println("Created node "+layer+" upper of "+data(parent));
return node;
}
public DefaultMutableTreeNode searchNode(AbstractLayer layer) {
return searchNode(rootNode(), layer);
}
public DefaultMutableTreeNode searchNode(DefaultMutableTreeNode node, AbstractLayer layer) {
CheckBoxNodeData data = CheckBoxTree.data(node);
if (data.getAbstractLayer() == layer) return node;
else {
DefaultMutableTreeNode found = null;
for (int i = 0; i < node.getChildCount() && found == null; i++) {
found = searchNode((DefaultMutableTreeNode) node.getChildAt(i), layer);
}
return found;
}
}
}