package com.framsticks.gui; // import java.util.Enumeration; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import javax.swing.event.TreeModelEvent; import javax.swing.event.TreeModelListener; import javax.swing.tree.TreePath; import org.apache.log4j.Logger; import com.framsticks.core.Node; import com.framsticks.core.Path; import com.framsticks.util.FramsticksException; import com.framsticks.util.UnsupportedOperationException; import com.framsticks.util.lang.Casting; public class TreeModel implements javax.swing.tree.TreeModel { private static final Logger log = Logger.getLogger(TreeModel.class); protected List listeners = new LinkedList<>(); protected final Frame frame; /** * @param frame */ public TreeModel(Frame frame) { this.frame = frame; } @Override public void addTreeModelListener(TreeModelListener listener) { listeners.add(listener); } @Override public AbstractNode getChild(Object parent, int number) { return Casting.assertCast(AbstractNode.class, parent).getChild(number); } @Override public int getChildCount(Object parent) { return Casting.assertCast(AbstractNode.class, parent).getChildCount(); } @Override public int getIndexOfChild(Object parent, Object child) { if ((parent == null) || (child == null)) { return -1; } return Casting.assertCast(AbstractNode.class, parent).getIndexOfChild(Casting.assertCast(AbstractNode.class, child)); } @Override public MetaNode getRoot() { return frame.rootNode; } @Override public boolean isLeaf(Object node) { return Casting.assertCast(AbstractNode.class, node).isLeaf(); } @Override public void removeTreeModelListener(TreeModelListener listener) { listeners.remove(listener); } @Override public void valueForPathChanged(TreePath path, Object value) { throw new UnsupportedOperationException().msg("changing value of tree node"); } protected boolean changing = false; public void nodeStructureChanged(TreePath treePath) { if (treePath == null) { return; } assert frame.isActive(); changing = true; log.debug("changing: " + treePath); // Enumeration expanded = frame.jtree.getExpandedDescendants(treePath); // TreePath selection = frame.jtree.getSelectionPath(); for (TreeModelListener listener : listeners) { listener.treeStructureChanged(new TreeModelEvent(this, treePath)); } // if (expanded != null) { // while (expanded.hasMoreElements()) { // TreePath expansion = expanded.nextElement(); // // log.info("reexpanding: " + expansion); // frame.jtree.expandPath(expansion); // } // } // if (selection != null) { // frame.jtree.setSelectionPath(selection); // } changing = false; } public Path convertToPath(TreePath treePath) { final Object[] components = treePath.getPath(); assert components[0] == frame.rootNode; if (components.length == 1) { return null; } Path.PathBuilder builder = Path.build(); builder.tree(Casting.assertCast(TreeNode.class, components[1]).getTree()); List nodes = new LinkedList<>(); for (int i = 1; i < components.length; ++i) { TreeNode treeNode = Casting.tryCast(TreeNode.class, components[i]); if (treeNode == null) { return null; } Node node = treeNode.tryCreateNode(); if (node == null) { throw new FramsticksException().msg("failed to recreate path").arg("treePath", treePath); } nodes.add(node); } builder.buildUpTo(nodes, null); return builder.finish(); } public TreePath convertToTreePath(Path path) { assert frame.isActive(); List accumulator = new LinkedList(); accumulator.add(frame.rootNode); for (AbstractNode r : frame.rootNode.getChildren()) { if (r instanceof TreeNode) { TreeNode root = (TreeNode) r; if (root.getTree() == path.getTree()) { accumulator.add(root); Iterator i = path.getNodes().iterator(); i.next(); TreeNode treeNode = root; while (i.hasNext()) { Node node = i.next(); treeNode = treeNode.getTreeNodeForChild(node.getObject()); if (treeNode == null) { break; } accumulator.add(treeNode); } break; } } } return new TreePath(accumulator.toArray()); } /** * @return the changing */ public boolean isChanging() { return changing; } }