Merge: 497958b 68dcaa7
[jalview.git] / src / ext / edu / ucsf / rbvi / strucviz2 / ChimeraTreeModel.java
1 /* vim: set ts=2: */
2 /**
3  * Copyright (c) 2006 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *   1. Redistributions of source code must retain the above copyright
10  *      notice, this list of conditions, and the following disclaimer.
11  *   2. Redistributions in binary form must reproduce the above
12  *      copyright notice, this list of conditions, and the following
13  *      disclaimer in the documentation and/or other materials provided
14  *      with the distribution.
15  *   3. Redistributions must acknowledge that this software was
16  *      originally developed by the UCSF Computer Graphics Laboratory
17  *      under support by the NIH National Center for Research Resources,
18  *      grant P41-RR01081.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
21  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  */
33 package ext.edu.ucsf.rbvi.strucviz2;
34
35 // System imports
36 import java.util.ArrayList;
37 import java.util.Collection;
38 import java.util.Collections;
39 import java.util.List;
40
41 import javax.swing.JTree;
42 import javax.swing.tree.DefaultMutableTreeNode;
43 import javax.swing.tree.DefaultTreeModel;
44 import javax.swing.tree.TreePath;
45 // Cytoscape imports
46 // StructureViz imports
47
48 /**
49  * The ChimeraTreeModel class provides the underlying model
50  * for the navigation tree in the ModelNavigatorDialog.
51  *
52  * @author scooter
53  * @see ModelNavigatorDialog
54          */
55 public class ChimeraTreeModel extends DefaultTreeModel {
56         private ChimeraManager chimeraManager;
57         private JTree navigationTree;
58         private int residueDisplay = ChimeraResidue.THREE_LETTER;
59
60         /**
61          * Constructor for the ChimeraTreeModel.
62          *
63          * @param chimeraObject the Chimera object that this tree represents
64          * @param tree the JTree used to display the object
65          * @see Chimera
66          */
67         public ChimeraTreeModel (ChimeraManager chimeraManager, JTree tree) {
68                 super(new DefaultMutableTreeNode());
69                 this.chimeraManager = chimeraManager;
70                 this.navigationTree = tree;
71                 DefaultMutableTreeNode rootNode = buildTree();
72                 this.setRoot(rootNode);
73         }
74
75         /**
76          * Set the display type for the residues.  The display type
77          * must be one of:
78          *
79          *      ChimeraResidue.THREE_LETTER
80          *      ChimeraResidue.SINGLE_LETTER
81          *      ChimeraResidue.FULL_NAME
82          *
83          * @param newDisplay the display type
84          * @see ChimeraResidue
85          */
86         public void setResidueDisplay(int newDisplay) {
87                 this.residueDisplay = newDisplay;
88         }
89                 
90         /**
91          * This method is called to rebuild the tree model "from scratch"
92          */
93         public void reload() {
94                 // First, rebuild the tree with the new data
95                 DefaultMutableTreeNode rootNode = buildTree();
96                 this.setRoot(rootNode);
97
98                 // Now let the superclass do all of the work
99                 super.reload();
100         }
101
102         /**
103          * Rebuild an existing tree
104          */
105         public void rebuildTree() {
106                 DefaultMutableTreeNode rootNode = buildTree();
107                 DefaultTreeModel model = (DefaultTreeModel)navigationTree.getModel();
108                 model.setRoot(rootNode);
109                 model.reload();
110         }
111
112         /**
113          * Build the tree from the current Chimera data
114          *
115          * @return DefaultMutableTreeNode that represents the currently loaded Chimera models
116          */
117         private DefaultMutableTreeNode buildTree() {
118                 int modelCount = chimeraManager.getChimeraModelsCount(true);
119                 DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(modelCount+" Open Chimera Models");
120                 TreePath rootPath = new TreePath(rootNode);
121
122                 TreePath path = null;
123                 DefaultMutableTreeNode model = null;
124
125                 // Add all of the Chimera models
126                 for (ChimeraModel chimeraModel: chimeraManager.getChimeraModels()) {
127                         model = new DefaultMutableTreeNode(chimeraModel);
128                         path = rootPath.pathByAddingChild(model);
129                         chimeraModel.setUserData(path);
130                         addChainNodes(chimeraModel, model, path);
131                         rootNode.add(model);
132                 }
133                 return rootNode;
134         }
135
136         /**
137          * add chains to a tree model
138          *
139          * @param chimeraModel the ChimeraModel to get the chains from
140          * @param treeModel the tree model to add the chains to
141          * @param treePath the tree path where the chains should be added
142          */
143         private void addChainNodes(ChimeraModel chimeraModel, 
144                                                                                                                  DefaultMutableTreeNode treeModel,
145                                                                                                                  TreePath treePath) {
146                 DefaultMutableTreeNode chain = null;
147                 TreePath chainPath = null;
148
149                 // Get the list of chains
150                 Collection<ChimeraChain> chainList = chimeraModel.getChains();
151
152                 if (chainList.size() == 0) {
153                         // No chains!  Just add the residues
154                         addResidues(chimeraModel.getResidues(), treeModel, treePath);   
155                         return;
156                 }
157
158                 // Iterate over the chains and add the chain and all of
159                 // the chain's residues
160                 for (ChimeraChain chimeraChain: chainList) {
161                         chain = new DefaultMutableTreeNode(chimeraChain);
162                         chainPath = treePath.pathByAddingChild(chain);
163                         chimeraChain.setUserData(chainPath);
164                         addResidues(chimeraChain.getResidues(), chain, chainPath);
165                         treeModel.add(chain);   
166                 }
167         }
168
169         /**
170          * add residues to a tree model
171          *
172          * @param residues the residues to add
173          * @param treeModel the tree model to add the residues to
174          * @param treePath the tree path where the residues should be added
175          */
176         private void addResidues(Collection<ChimeraResidue> residues, 
177                                                                                                          DefaultMutableTreeNode treeModel,
178                                                                                                          TreePath treePath) {
179                 DefaultMutableTreeNode residue = null;
180                 TreePath residuePath = null;
181
182                 List<ChimeraResidue> sortedResidues = new ArrayList<ChimeraResidue>(residues);
183                 Collections.sort(sortedResidues);
184
185                 // Iterate over all residues & add them to the tree
186                 for (ChimeraResidue res: sortedResidues) {
187                         res.setDisplayType(this.residueDisplay);
188                         residue = new DefaultMutableTreeNode(res);
189                         residuePath = treePath.pathByAddingChild(residue);
190                         res.setUserData(residuePath);
191                         treeModel.add(residue);
192                 }
193         }       
194 }