Merge branch 'features/JAL-1333' into Release_2_8_2_Branch
[jalview.git] / src / ext / edu / ucsf / rbvi / strucviz2 / ChimeraTreeModel.java
diff --git a/src/ext/edu/ucsf/rbvi/strucviz2/ChimeraTreeModel.java b/src/ext/edu/ucsf/rbvi/strucviz2/ChimeraTreeModel.java
new file mode 100644 (file)
index 0000000..f3447ce
--- /dev/null
@@ -0,0 +1,194 @@
+/* vim: set ts=2: */
+/**
+ * Copyright (c) 2006 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions, and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions, and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *   3. Redistributions must acknowledge that this software was
+ *      originally developed by the UCSF Computer Graphics Laboratory
+ *      under support by the NIH National Center for Research Resources,
+ *      grant P41-RR01081.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+package ext.edu.ucsf.rbvi.strucviz2;
+
+// System imports
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import javax.swing.JTree;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreePath;
+// Cytoscape imports
+// StructureViz imports
+
+/**
+ * The ChimeraTreeModel class provides the underlying model
+ * for the navigation tree in the ModelNavigatorDialog.
+ *
+ * @author scooter
+ * @see ModelNavigatorDialog
+        */
+public class ChimeraTreeModel extends DefaultTreeModel {
+       private ChimeraManager chimeraManager;
+       private JTree navigationTree;
+       private int residueDisplay = ChimeraResidue.THREE_LETTER;
+
+       /**
+        * Constructor for the ChimeraTreeModel.
+        *
+        * @param chimeraObject the Chimera object that this tree represents
+        * @param tree the JTree used to display the object
+        * @see Chimera
+        */
+       public ChimeraTreeModel (ChimeraManager chimeraManager, JTree tree) {
+               super(new DefaultMutableTreeNode());
+               this.chimeraManager = chimeraManager;
+               this.navigationTree = tree;
+               DefaultMutableTreeNode rootNode = buildTree();
+               this.setRoot(rootNode);
+       }
+
+       /**
+        * Set the display type for the residues.  The display type
+        * must be one of:
+        *
+        *      ChimeraResidue.THREE_LETTER
+        *      ChimeraResidue.SINGLE_LETTER
+        *      ChimeraResidue.FULL_NAME
+        *
+        * @param newDisplay the display type
+        * @see ChimeraResidue
+        */
+       public void setResidueDisplay(int newDisplay) {
+               this.residueDisplay = newDisplay;
+       }
+               
+       /**
+        * This method is called to rebuild the tree model "from scratch"
+        */
+       public void reload() {
+               // First, rebuild the tree with the new data
+               DefaultMutableTreeNode rootNode = buildTree();
+               this.setRoot(rootNode);
+
+               // Now let the superclass do all of the work
+               super.reload();
+       }
+
+       /**
+        * Rebuild an existing tree
+        */
+       public void rebuildTree() {
+               DefaultMutableTreeNode rootNode = buildTree();
+               DefaultTreeModel model = (DefaultTreeModel)navigationTree.getModel();
+               model.setRoot(rootNode);
+               model.reload();
+       }
+
+       /**
+        * Build the tree from the current Chimera data
+        *
+        * @return DefaultMutableTreeNode that represents the currently loaded Chimera models
+        */
+       private DefaultMutableTreeNode buildTree() {
+               int modelCount = chimeraManager.getChimeraModelsCount(true);
+               DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(modelCount+" Open Chimera Models");
+               TreePath rootPath = new TreePath(rootNode);
+
+               TreePath path = null;
+               DefaultMutableTreeNode model = null;
+
+               // Add all of the Chimera models
+               for (ChimeraModel chimeraModel: chimeraManager.getChimeraModels()) {
+                       model = new DefaultMutableTreeNode(chimeraModel);
+                       path = rootPath.pathByAddingChild(model);
+                       chimeraModel.setUserData(path);
+                       addChainNodes(chimeraModel, model, path);
+                       rootNode.add(model);
+               }
+               return rootNode;
+       }
+
+       /**
+        * add chains to a tree model
+        *
+        * @param chimeraModel the ChimeraModel to get the chains from
+        * @param treeModel the tree model to add the chains to
+        * @param treePath the tree path where the chains should be added
+        */
+       private void addChainNodes(ChimeraModel chimeraModel, 
+                                                                                                                DefaultMutableTreeNode treeModel,
+                                                                                                                TreePath treePath) {
+               DefaultMutableTreeNode chain = null;
+               TreePath chainPath = null;
+
+               // Get the list of chains
+               Collection<ChimeraChain> chainList = chimeraModel.getChains();
+
+               if (chainList.size() == 0) {
+                       // No chains!  Just add the residues
+                       addResidues(chimeraModel.getResidues(), treeModel, treePath);   
+                       return;
+               }
+
+               // Iterate over the chains and add the chain and all of
+               // the chain's residues
+               for (ChimeraChain chimeraChain: chainList) {
+                       chain = new DefaultMutableTreeNode(chimeraChain);
+                       chainPath = treePath.pathByAddingChild(chain);
+                       chimeraChain.setUserData(chainPath);
+                       addResidues(chimeraChain.getResidues(), chain, chainPath);
+                       treeModel.add(chain);   
+               }
+       }
+
+       /**
+        * add residues to a tree model
+        *
+        * @param residues the residues to add
+        * @param treeModel the tree model to add the residues to
+        * @param treePath the tree path where the residues should be added
+        */
+       private void addResidues(Collection<ChimeraResidue> residues, 
+                                                                                                        DefaultMutableTreeNode treeModel,
+                                                                                                        TreePath treePath) {
+               DefaultMutableTreeNode residue = null;
+               TreePath residuePath = null;
+
+               List<ChimeraResidue> sortedResidues = new ArrayList<ChimeraResidue>(residues);
+               Collections.sort(sortedResidues);
+
+               // Iterate over all residues & add them to the tree
+               for (ChimeraResidue res: sortedResidues) {
+                       res.setDisplayType(this.residueDisplay);
+                       residue = new DefaultMutableTreeNode(res);
+                       residuePath = treePath.pathByAddingChild(residue);
+                       res.setUserData(residuePath);
+                       treeModel.add(residue);
+               }
+       }       
+}