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