JAL-3949 Complete new abstracted logging framework in jalview.log. Updated log calls...
[jalview.git] / src / jalview / gui / AppJmolBinding.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ 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.gui;
22
23 import java.awt.Container;
24 import java.io.File;
25 import java.util.ArrayList;
26 import java.util.List;
27 import java.util.Map;
28
29 import javax.swing.JComponent;
30
31 import org.jmol.api.JmolAppConsoleInterface;
32 import org.openscience.jmol.app.jmolpanel.console.AppConsole;
33
34 import jalview.api.AlignmentViewPanel;
35 import jalview.api.structures.JalviewStructureDisplayI;
36 import jalview.bin.Cache;
37 import jalview.datamodel.AlignmentI;
38 import jalview.datamodel.PDBEntry;
39 import jalview.datamodel.SequenceI;
40 import jalview.ext.jmol.JalviewJmolBinding;
41 import jalview.io.DataSourceType;
42 import jalview.structure.StructureSelectionManager;
43 import jalview.util.MessageManager;
44 import jalview.util.Platform;
45 import jalview.ws.dbsources.EBIAlfaFold;
46 import jalview.ws.dbsources.Pdb;
47 import jalview.ws.utils.UrlDownloadClient;
48 import javajs.util.BS;
49
50 public class AppJmolBinding extends JalviewJmolBinding
51 {
52   public AppJmolBinding(AppJmol appJmol, StructureSelectionManager sSm,
53           PDBEntry[] pdbentry, SequenceI[][] sequenceIs,
54           DataSourceType protocol)
55   {
56     super(sSm, pdbentry, sequenceIs, protocol);
57     setViewer(appJmol);
58   }
59
60   @Override
61   public SequenceRenderer getSequenceRenderer(AlignmentViewPanel alignment)
62   {
63     return new SequenceRenderer(((AlignmentPanel) alignment).av);
64   }
65
66   @Override
67   public void sendConsoleEcho(String strEcho)
68   {
69     if (console != null)
70     {
71       console.sendConsoleEcho(strEcho);
72     }
73   }
74
75   @Override
76   public void sendConsoleMessage(String strStatus)
77   {
78     if (console != null && strStatus != null)
79     // && !strStatus.equals("Script completed"))
80     // should we squash the script completed string ?
81     {
82       console.sendConsoleMessage(strStatus);
83     }
84   }
85
86   @Override
87   public void showUrl(String url, String target)
88   {
89     try
90     {
91       jalview.util.BrowserLauncher.openURL(url);
92     } catch (Exception e)
93     {
94       Cache.error("Failed to launch Jmol-associated url " + url, e);
95       // TODO: 2.6 : warn user if browser was not configured.
96     }
97   }
98
99   @Override
100   public void refreshGUI()
101   {
102     if (getMappedStructureCount() == 0)
103     {
104       // too soon!
105       return;
106     }
107     // appJmolWindow.repaint();
108     javax.swing.SwingUtilities.invokeLater(new Runnable()
109     {
110       @Override
111       public void run()
112       {
113         JalviewStructureDisplayI theViewer = getViewer();
114         // invokes colourbySequence() via seqColour_ActionPerformed()
115         theViewer.updateTitleAndMenus();
116         ((JComponent) theViewer).revalidate();
117       }
118     });
119   }
120
121   @Override
122   public void notifyScriptTermination(String strStatus, int msWalltime)
123   {
124     // todo - script termination doesn't happen ?
125     // if (console != null)
126     // console.notifyScriptTermination(strStatus,
127     // msWalltime);
128   }
129
130   @Override
131   public void showUrl(String url)
132   {
133     showUrl(url, "jmol");
134   }
135
136   public void newJmolPopup(String menuName)
137   {
138     // jmolpopup = new JmolAwtPopup();
139     // jmolpopup.jpiInitialize((viewer), menuName);
140   }
141
142   @Override
143   public void selectionChanged(BS arg0)
144   {
145   }
146
147   @Override
148   public void showConsole(boolean b)
149   {
150     getViewer().showConsole(b);
151   }
152
153   @Override
154   protected JmolAppConsoleInterface createJmolConsole(
155           Container consolePanel, String buttonsToShow)
156   {
157     jmolViewer.setJmolCallbackListener(this);
158     // BH comment: can't do this yet [for JS only, or generally?]
159     return Platform.isJS() ? null
160             : new AppConsole(jmolViewer, consolePanel, buttonsToShow);
161   }
162
163   @Override
164   protected void releaseUIResources()
165   {
166     setViewer(null);
167     closeConsole();
168   }
169
170   @Override
171   public void releaseReferences(Object svl)
172   {
173     if (svl instanceof SeqPanel)
174     {
175       getViewer().removeAlignmentPanel(((SeqPanel) svl).ap);
176     }
177   }
178
179   @Override
180   public Map<String, Object> getJSpecViewProperty(String arg0)
181   {
182     // TODO Auto-generated method stub
183     return null;
184   }
185
186   @SuppressWarnings("unused")
187   public void cacheFiles(List<File> files)
188   {
189     if (files == null)
190     {
191       return;
192     }
193     for (File f : files)
194     {
195       Platform.cacheFileData(f);
196     }
197   }
198
199   /**
200    * Retrieves and saves as file any modelled PDB entries for which we do not
201    * already have a file saved. Returns a list of absolute paths to structure
202    * files which were either retrieved, or already stored but not modelled in
203    * the structure viewer (i.e. files to add to the viewer display).
204    * 
205    * Currently only used by Jmol - similar but different code used for Chimera/X
206    * and Pymol so still need to refactor
207    * 
208    * @param structureViewer
209    *          UI proxy for the structure viewer
210    * @return list of absolute paths to structures retrieved that need to be
211    *         added to the display
212    */
213   public List<String> fetchPdbFiles(StructureViewerBase structureViewer)
214   {
215     // todo - record which pdbids were successfully imported.
216     StringBuilder errormsgs = new StringBuilder();
217   
218     List<String> files = new ArrayList<>();
219     String pdbid = "";
220     try
221     {
222       String[] filesInViewer = getStructureFiles();
223       // TODO: replace with reference fetching/transfer code (validate PDBentry
224       // as a DBRef?)
225       
226       for (int pi = 0; pi < getPdbCount(); pi++)
227       {
228         PDBEntry strucEntry = getPdbEntry(pi);
229
230         String file = strucEntry.getFile();
231         if (file == null)
232         {
233           pdbid = strucEntry.getId();
234           try{ 
235             file = structureViewer.fetchPdbFile(strucEntry);
236           } catch (OutOfMemoryError oomerror)
237           {
238             new OOMWarning("Retrieving PDB id " + pdbid, oomerror);
239           } catch (Exception ex)
240           {
241             ex.printStackTrace();
242             errormsgs.append("'").append(pdbid).append("'");
243           }
244           if (file!=null)
245           {
246             // success
247             files.add(file);
248           }
249           else
250           {
251             errormsgs.append("'").append(pdbid).append("' ");
252           }
253         }
254         else
255         {
256           if (filesInViewer != null && filesInViewer.length > 0)
257           {
258             structureViewer.setAddingStructures(true); // already files loaded.
259             for (int c = 0; c < filesInViewer.length; c++)
260             {
261               if (Platform.pathEquals(filesInViewer[c], file))
262               {
263                 file = null;
264                 break;
265               }
266             }
267           }
268           if (file != null)
269           {
270             files.add(file);
271           }
272         }
273       }
274     } catch (OutOfMemoryError oomerror)
275     {
276       new OOMWarning("Retrieving PDB files: " + pdbid, oomerror);
277     } catch (Exception ex)
278     {
279       ex.printStackTrace();
280       errormsgs.append("When retrieving pdbfiles : current was: '")
281               .append(pdbid).append("'");
282     }
283     if (errormsgs.length() > 0)
284     {
285       JvOptionPane.showInternalMessageDialog(Desktop.desktop,
286               MessageManager.formatMessage(
287                       "label.pdb_entries_couldnt_be_retrieved", new String[]
288                       { errormsgs.toString() }),
289               MessageManager.getString("label.couldnt_load_file"),
290               JvOptionPane.ERROR_MESSAGE);
291     }
292     return files;
293   }
294
295 }