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