001// License: GPL. For details, see Readme.txt file. 002package org.openstreetmap.gui.jmapviewer.checkBoxTree; 003 004import java.awt.BorderLayout; 005import java.awt.event.MouseAdapter; 006 007import javax.swing.JFrame; 008import javax.swing.JScrollPane; 009import javax.swing.JTree; 010import javax.swing.event.TreeModelEvent; 011import javax.swing.event.TreeModelListener; 012import javax.swing.tree.DefaultMutableTreeNode; 013import javax.swing.tree.DefaultTreeModel; 014 015import org.openstreetmap.gui.jmapviewer.AbstractLayer; 016import org.openstreetmap.gui.jmapviewer.Layer; 017import org.openstreetmap.gui.jmapviewer.LayerGroup; 018 019/** 020 * JTree for checkBox Tree Layers 021 * 022 * @author galo 023 */ 024public class CheckBoxTree extends JTree { 025 /** Serial Version UID */ 026 private static final long serialVersionUID = 6943401106938034256L; 027 028 private final CheckBoxNodeEditor editor; 029 030 public CheckBoxTree(AbstractLayer layer) { 031 this(new CheckBoxNodeData(layer)); 032 } 033 034 public CheckBoxTree(String rootName) { 035 this(new CheckBoxNodeData(rootName)); 036 } 037 038 public CheckBoxTree(CheckBoxNodeData root) { 039 this(new DefaultMutableTreeNode(root)); 040 } 041 042 public CheckBoxTree(DefaultMutableTreeNode node) { 043 super(new DefaultTreeModel(node)); 044 045 final CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer(); 046 setCellRenderer(renderer); 047 048 editor = new CheckBoxNodeEditor(this); 049 setCellEditor(editor); 050 setEditable(true); 051 052 // listen for changes in the model (including check box toggles) 053 getModel().addTreeModelListener(new TreeModelListener() { 054 @Override 055 public void treeNodesChanged(final TreeModelEvent e) { 056 DefaultTreeModel model = (DefaultTreeModel) e.getSource(); 057 Object[] nodes = e.getChildren(); 058 DefaultMutableTreeNode node; 059 if (nodes == null || nodes.length == 0) { 060 node = node(model.getRoot()); 061 } else { 062 node = node(nodes[0]); 063 } 064 nodeChanged(node); 065 repaint(); 066 } 067 068 @Override 069 public void treeNodesInserted(final TreeModelEvent e) { 070 //System.out.println("nodes inserted"); 071 } 072 073 @Override 074 public void treeNodesRemoved(final TreeModelEvent e) { 075 //System.out.println("nodes removed"); 076 } 077 078 @Override 079 public void treeStructureChanged(final TreeModelEvent e) { 080 //System.out.println("structure changed"); 081 } 082 }); 083 } 084 085 public void addNodeListener(MouseAdapter listener) { 086 editor.addNodeListener(listener); 087 } 088 089 public static void main(final String[] args) { 090 final DefaultMutableTreeNode root = new DefaultMutableTreeNode(new CheckBoxNodeData("Root", Boolean.TRUE)); 091 092 final DefaultMutableTreeNode accessibility = 093 add(root, "Accessibility", true); 094 add(accessibility, "Move system caret with focus/selection changes", false); 095 add(accessibility, "Always expand alt text for images", true); 096 root.add(accessibility); 097 098 final DefaultMutableTreeNode browsing = 099 new DefaultMutableTreeNode(new CheckBoxNodeData("Browsing", null)); 100 add(browsing, "Notify when downloads complete", true); 101 add(browsing, "Disable script debugging", true); 102 add(browsing, "Use AutoComplete", true); 103 add(browsing, "Browse in a new process", false); 104 root.add(browsing); 105 106 final CheckBoxTree tree = new CheckBoxTree(root); 107 ((DefaultMutableTreeNode) tree.getModel().getRoot()).add(new DefaultMutableTreeNode(new CheckBoxNodeData("gggg", null))); 108 ((DefaultTreeModel) tree.getModel()).reload(); 109 // show the tree on screen 110 final JFrame frame = new JFrame("CheckBox Tree"); 111 final JScrollPane scrollPane = new JScrollPane(tree); 112 frame.getContentPane().add(scrollPane, BorderLayout.CENTER); 113 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 114 frame.setSize(300, 150); 115 frame.setVisible(true); 116 } 117 118 private static Boolean childStatus(DefaultMutableTreeNode node) { 119 Boolean status = data(node.getChildAt(0)).isSelected(); 120 for (int i = 1; i < node.getChildCount() && status != null; i++) { 121 if (!status.equals( 122 data(node.getChildAt(i)).isSelected() 123 )) 124 return null; 125 } 126 return status; 127 } 128 129 private static void changeParents(DefaultMutableTreeNode node) { 130 if (node != null) { 131 DefaultMutableTreeNode parent = node(node.getParent()); 132 if (parent != null) { 133 CheckBoxNodeData dataParent = data(parent); 134 Boolean childStatus = childStatus(parent); 135 if (childStatus != null && !childStatus.equals(dataParent.isSelected())) { 136 dataParent.setSelected(childStatus); 137 changeParents(parent); 138 } 139 } 140 } 141 } 142 143 private static void nodeChanged(DefaultMutableTreeNode node) { 144 if (node != null) { 145 changeParents(node); 146 setChildrens(node, data(node).isSelected()); 147 } 148 } 149 150 private static void setChildrens(DefaultMutableTreeNode node, Boolean value) { 151 for (int i = 0; i < node.getChildCount(); i++) { 152 DefaultMutableTreeNode childNode = node(node.getChildAt(i)); 153 if (!data(childNode).isSelected().equals(data(node).isSelected())) { 154 data(childNode).setSelected(data(node).isSelected()); 155 setChildrens(childNode, value); 156 } 157 } 158 } 159 160 public DefaultMutableTreeNode rootNode() { 161 return node(getModel().getRoot()); 162 } 163 164 public LayerGroup rootLayer() { 165 return (LayerGroup) rootData().getAbstractLayer(); 166 } 167 168 public CheckBoxNodeData rootData() { 169 return data(rootNode()); 170 } 171 172 private static DefaultMutableTreeNode node(Object node) { 173 return (DefaultMutableTreeNode) node; 174 } 175 176 public static CheckBoxNodeData data(DefaultMutableTreeNode node) { 177 return node == null ? null : (CheckBoxNodeData) node.getUserObject(); 178 } 179 180 private static CheckBoxNodeData data(Object node) { 181 return data(node(node)); 182 } 183 184 private static DefaultMutableTreeNode add(final DefaultMutableTreeNode parent, final String text, final boolean checked) { 185 final CheckBoxNodeData data = new CheckBoxNodeData(text, checked); 186 final DefaultMutableTreeNode node = new DefaultMutableTreeNode(data); 187 parent.add(node); 188 return node; 189 } 190 191 public static CheckBoxNodeData createNodeData(AbstractLayer layer) { 192 return new CheckBoxNodeData(layer); 193 } 194 195 public static DefaultMutableTreeNode createNode(AbstractLayer layer) { 196 return new DefaultMutableTreeNode(createNodeData(layer)); 197 } 198 199 /*public DefaultMutableTreeNode addLayerGroup(LayerGroup group) { 200 if (group != null){ 201 if (group.getParent() == null){ 202 return add(rootNode(), group); 203 } else { 204 DefaultMutableTreeNode parentGroup = searchNode(group.getParent()); 205 if(parentGroup==null) parentGroup = addLayerGroup(group.getParent()); 206 DefaultMutableTreeNode node = add(parentGroup, group); 207 return node; 208 } 209 }else return null; 210 }*/ 211 212 public Layer addLayer(String name) { 213 Layer layer = new Layer(name); 214 addLayer(layer); 215 return layer; 216 } 217 218 public DefaultMutableTreeNode addLayer(AbstractLayer layer) { 219 if (layer != null) { 220 DefaultMutableTreeNode parent; 221 if (layer.getParent() == null) { 222 rootLayer().add(layer); 223 parent = rootNode(); 224 } else { 225 parent = searchNode(layer.getParent()); 226 if (parent == null) 227 parent = addLayer(layer.getParent()); 228 } 229 return add(parent, layer); 230 } else return null; 231 } 232 233 public DefaultMutableTreeNode add(DefaultMutableTreeNode parent, final AbstractLayer layer) { 234 layer.setVisible(data(parent).isSelected()); 235 DefaultMutableTreeNode node = createNode(layer); 236 parent.add(node); 237 ((DefaultTreeModel) getModel()).reload(); 238 //System.out.println("Created node "+layer+" upper of "+data(parent)); 239 return node; 240 } 241 242 public DefaultMutableTreeNode searchNode(AbstractLayer layer) { 243 return searchNode(rootNode(), layer); 244 } 245 246 public DefaultMutableTreeNode searchNode(DefaultMutableTreeNode node, AbstractLayer layer) { 247 CheckBoxNodeData data = CheckBoxTree.data(node); 248 if (data.getAbstractLayer() == layer) return node; 249 else { 250 DefaultMutableTreeNode found = null; 251 for (int i = 0; i < node.getChildCount() && found == null; i++) { 252 found = searchNode((DefaultMutableTreeNode) node.getChildAt(i), layer); 253 } 254 return found; 255 } 256 } 257}