f9d5dd0ba7fc40dcd2537b1e7e18bc9ccb18d306
[jalview.git] / src / jalview / javascript / MouseOverStructureListener.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
3  * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
10  *  
11  * Jalview is distributed in the hope that it will be useful, but 
12  * WITHOUT ANY WARRANTY; without even the implied warranty 
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14  * PURPOSE.  See the GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 package jalview.javascript;
19
20 import java.awt.Color;
21 import java.util.ArrayList;
22
23 import jalview.api.AlignmentViewPanel;
24 import jalview.api.FeatureRenderer;
25 import jalview.api.SequenceRenderer;
26 import jalview.appletgui.AlignFrame;
27 import jalview.bin.JalviewLite;
28 import jalview.datamodel.SequenceI;
29 import jalview.ext.jmol.JmolCommands;
30 import jalview.structure.StructureListener;
31 import jalview.structure.StructureMapping;
32 import jalview.structure.StructureMappingcommandSet;
33 import jalview.structure.StructureSelectionManager;
34
35 /**
36  * Propagate events involving PDB structures associated with sequences to a
37  * javascript function. Generally, the javascript handler is called with a
38  * series of arguments like (eventname, ... ). As of Jalview 2.7, the following
39  * different types of events are supported:
40  * <ul>
41  * <li>mouseover: javascript function called with arguments
42  * 
43  * <pre>
44  * ['mouseover',String(pdb file URI), String(pdb file chain ID), String(residue
45  * number moused over), String(atom index corresponding to residue)]
46  * </pre>
47  * 
48  * </li>
49  * <li>colourstruct: javascript function called with arguments
50  * 
51  * <pre>
52  * ['colourstruct',String(alignment view id),String(number of javascript message
53  * chunks to collect),String(length of first chunk in set of messages - or zero
54  * for null message)]
55  * </pre>
56  * 
57  * <br>
58  * The message contains a series of Jmol script commands that will colour
59  * structures according to their associated sequences in the current view. Use
60  * jalview
61  * .javascript.JalviewLiteJsApi.getJsMessage('colourstruct',String(alignment
62  * view id)) to retrieve successive chunks of the message.</li>
63  * </ul>
64  * 
65  * @author Jim Procter (jprocter)
66  * 
67  */
68 public class MouseOverStructureListener extends JSFunctionExec implements
69         JsCallBack, StructureListener
70 {
71
72   String _listenerfn;
73
74   String[] modelSet;
75
76   public MouseOverStructureListener(JalviewLite jalviewLite,
77           String listener, String[] modelList)
78   {
79     super(jalviewLite);
80     _listenerfn = listener;
81     modelSet = modelList;
82     if (modelSet != null)
83     {
84       for (int i = 0; i < modelSet.length; i++)
85       {
86         // resolve a real filename
87         try
88         {
89           if (new java.net.URL(modelSet[i]).openConnection() != null)
90           {
91             continue;
92           }
93         } catch (Exception x)
94         {
95         }
96         ;
97         try
98         {
99           String db = jvlite.getDocumentBase().toString();
100           db = db.substring(0, db.lastIndexOf("/"));
101           if (new java.net.URL(db + "/" + modelSet[i]).openConnection() != null)
102           {
103             modelSet[i] = db + "/" + modelSet[i];
104             continue;
105           }
106         } catch (Exception x)
107         {
108         }
109         ;
110         try
111         {
112           if (new java.net.URL(jvlite.getCodeBase() + modelSet[i])
113                   .openConnection() != null)
114           {
115             modelSet[i] = jvlite.getCodeBase() + modelSet[i];
116             continue;
117           }
118         } catch (Exception x)
119         {
120         }
121         ;
122
123       }
124     }
125   }
126
127   @Override
128   public String[] getPdbFile()
129   {
130     return modelSet;
131   }
132
133   @Override
134   public void mouseOverStructure(int atomIndex, String strInfo)
135   {
136
137     // StructureSelectionManager.getStructureSelectionManager().mouseOverStructure(atomIndex,
138     // chain, pdbfile)
139     // TODO Auto-generated method stub
140
141   }
142
143   @Override
144   public void highlightAtom(int atomIndex, int pdbResNum, String chain,
145           String pdbId)
146   {
147     String[] st = new String[0];
148     try
149     {
150       executeJavascriptFunction(_listenerfn, st = new String[]
151       { "mouseover", "" + pdbId, "" + chain, "" + (pdbResNum),
152           "" + atomIndex });
153     } catch (Exception ex)
154     {
155       System.err.println("Couldn't execute callback with " + _listenerfn
156               + " using args { " + st[0] + ", " + st[1] + ", " + st[2]
157               + "," + st[3] + "\n");
158       ex.printStackTrace();
159
160     }
161
162   }
163
164   @Override
165   public synchronized void updateColours(Object srce)
166   {
167     final Object source = srce;
168     StructureSelectionManager ssm = StructureSelectionManager
169             .getStructureSelectionManager(jvlite);
170     // if (jvlite.debug)
171     // {
172     // ssm.reportMapping();
173     // }
174     if (source instanceof jalview.api.AlignmentViewPanel)
175     {
176       SequenceI[][] sequence = new SequenceI[modelSet.length][];
177       for (int m = 0; m < modelSet.length; m++)
178       {
179         StructureMapping[] sm = ssm.getMapping(modelSet[m]);
180         if (sm != null && sm.length > 0)
181         {
182           sequence[m] = new SequenceI[sm.length];
183           for (int i = 0; i < sm.length; i++)
184           {
185             sequence[m][i] = sm[i].getSequence();
186           }
187         }
188         else
189         {
190           sequence[m] = new SequenceI[0];
191         }
192         // if (jvlite.debug)
193         // {
194         // System.err.println("Mapped '" + modelSet[m] + "' to "
195         // + sequence[m].length + " sequences.");
196         // }
197       }
198
199       SequenceRenderer sr = ((jalview.appletgui.AlignmentPanel) source)
200               .getSequenceRenderer();
201       FeatureRenderer fr = ((jalview.appletgui.AlignmentPanel) source).av
202               .getShowSequenceFeatures() ? new jalview.appletgui.FeatureRenderer(
203               ((jalview.appletgui.AlignmentPanel) source).av) : null;
204       if (fr != null)
205       {
206         ((jalview.appletgui.FeatureRenderer) fr)
207                 .transferSettings(((jalview.appletgui.AlignmentPanel) source)
208                         .getFeatureRenderer());
209       }
210       ;
211
212       // Form a colour command from the given alignment panel for each distinct
213       // structure
214       ArrayList<String[]> ccomands = new ArrayList<String[]>();
215       ArrayList<String> pdbfn = new ArrayList<String>();
216       StructureMappingcommandSet[] colcommands = JmolCommands
217               .getColourBySequenceCommand(ssm, modelSet, sequence, sr, fr,
218                       ((AlignmentViewPanel) source).getAlignment());
219       if (colcommands == null)
220       {
221         return;
222       }
223       int sz = 0;
224       for (jalview.structure.StructureMappingcommandSet ccset : colcommands)
225       {
226         sz += ccset.commands.length;
227         ccomands.add(ccset.commands);
228         pdbfn.add(ccset.mapping);
229       }
230
231       String mclass, mhandle;
232       String ccomandset[] = new String[sz];
233       sz = 0;
234       for (String[] ccset : ccomands)
235       {
236         System.arraycopy(ccset, 0, ccomandset, sz, ccset.length);
237         sz += ccset.length;
238       }
239       if (jvlite.isJsMessageSetChanged(
240               mclass = "colourstruct",
241               mhandle = ((jalview.appletgui.AlignmentPanel) source).av
242                       .getViewId(), ccomandset))
243       {
244         jvlite.setJsMessageSet(mclass, mhandle, ccomandset);
245         // and notify javascript handler
246         String st[] = new String[]
247         {
248             "colourstruct",
249             "" + ((jalview.appletgui.AlignmentPanel) source).av.getViewId(),
250             "" + ccomandset.length,
251             jvlite.arrayToSeparatorList(pdbfn.toArray(new String[pdbfn
252                     .size()])) };
253         try
254         {
255           executeJavascriptFunction(true, _listenerfn, st);
256         } catch (Exception ex)
257         {
258           System.err.println("Couldn't execute callback with "
259                   + _listenerfn + " using args { " + st[0] + ", " + st[1]
260                   + ", " + st[2] + "," + st[3] + "}"); // + ","+st[4]+"\n");
261           ex.printStackTrace();
262
263         }
264       }
265       /*
266        * new Thread(new Runnable() { public void run() { // and send to
267        * javascript handler String st[] = new String[0]; int i = 0; for (String
268        * colcommand : colcommands) { // do sync execution for each chunk try {
269        * executeJavascriptFunction( false, _listenerfn, st = new String[] {
270        * "colourstruct", "" + ((jalview.appletgui.AlignmentPanel) source).av
271        * .getViewId(), handle, "" }); } catch (Exception ex) {
272        * System.err.println("Couldn't execute callback with " + _listenerfn +
273        * " using args { " + st[0] + ", " + st[1] + ", " + st[2] + "," + st[3] +
274        * "\n"); ex.printStackTrace();
275        * 
276        * } } } }).start();
277        */
278     }
279
280   }
281
282   @Override
283   public Color getColour(int atomIndex, int pdbResNum, String chain,
284           String pdbId)
285   {
286     return null;
287   }
288
289   @Override
290   public AlignFrame getAlignFrame()
291   {
292     // associated with all alignframes, always.
293     return null;
294   }
295
296   @Override
297   public String getListenerFunction()
298   {
299     return _listenerfn;
300   }
301
302   public void finalise()
303   {
304     jvlite = null;
305     super.finalize();
306   }
307
308   @Override
309   public void releaseReferences(Object svl)
310   {
311
312     // TODO Auto-generated method stub
313
314   }
315
316 }