gt:         if (data.getAbstractLayer() == layer) return node;
context: // 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);
  