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