Merge branch 'develop' into menard
[jalview.git] / src / MCview / PDBViewer.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 MCview;
19
20 import java.io.*;
21
22 import java.awt.event.*;
23 import javax.swing.*;
24 import javax.xml.parsers.ParserConfigurationException;
25
26 import org.xml.sax.SAXException;
27
28 import fr.orsay.lri.varna.exceptions.ExceptionFileFormatOrSyntax;
29 import fr.orsay.lri.varna.exceptions.ExceptionLoadingFailed;
30 import fr.orsay.lri.varna.exceptions.ExceptionPermissionDenied;
31 import fr.orsay.lri.varna.exceptions.ExceptionUnmatchedClosingParentheses;
32
33 import jalview.datamodel.*;
34 import jalview.gui.*;
35 import jalview.io.*;
36 import jalview.schemes.*;
37 import jalview.ws.ebi.EBIFetchClient;
38
39 public class PDBViewer extends JInternalFrame implements Runnable
40 {
41
42   /**
43    * The associated sequence in an alignment
44    */
45   PDBCanvas pdbcanvas;
46
47   PDBEntry pdbentry;
48
49   SequenceI[] seq;
50
51   String[] chains;
52
53   AlignmentPanel ap;
54
55   String protocol;
56
57   String tmpPDBFile;
58
59   public PDBViewer(PDBEntry pdbentry, SequenceI[] seq, String[] chains,
60           AlignmentPanel ap, String protocol) throws ExceptionFileFormatOrSyntax, ParserConfigurationException, SAXException, ExceptionPermissionDenied, ExceptionLoadingFailed, InterruptedException, ExceptionUnmatchedClosingParentheses
61
62   {
63     this.pdbentry = pdbentry;
64     this.seq = seq;
65     this.chains = chains;
66     this.ap = ap;
67     this.protocol = protocol;
68
69     try
70     {
71       jbInit();
72     } catch (Exception ex)
73     {
74       ex.printStackTrace();
75     }
76
77     StringBuffer title = new StringBuffer(seq[0].getName() + ":"
78             + pdbentry.getFile());
79
80     pdbcanvas = new PDBCanvas();
81
82     setContentPane(pdbcanvas);
83
84     if (pdbentry.getFile() != null)
85     {
86       try
87       {
88         tmpPDBFile = pdbentry.getFile();
89         PDBfile pdbfile = new PDBfile(tmpPDBFile,
90                 jalview.io.AppletFormatAdapter.FILE);
91
92         pdbcanvas.init(pdbentry, seq, chains, ap, protocol);
93
94       } catch (java.io.IOException ex)
95       {
96         ex.printStackTrace();
97       }
98     }
99     else
100     {
101       Thread worker = new Thread(this);
102       worker.start();
103     }
104
105     if (pdbentry.getProperty() != null)
106     {
107       if (pdbentry.getProperty().get("method") != null)
108       {
109         title.append(" Method: ");
110         title.append(pdbentry.getProperty().get("method"));
111       }
112       if (pdbentry.getProperty().get("chains") != null)
113       {
114         title.append(" Chain:");
115         title.append(pdbentry.getProperty().get("chains"));
116       }
117     }
118     Desktop.addInternalFrame(this, title.toString(), 400, 400);
119   }
120
121   public void run()
122   {
123     try
124     {
125       EBIFetchClient ebi = new EBIFetchClient();
126       String query = "pdb:" + pdbentry.getId();
127       pdbentry.setFile(ebi.fetchDataAsFile(query, "default", "raw")
128               .getAbsolutePath());
129
130       if (pdbentry.getFile() != null)
131         pdbcanvas.init(pdbentry, seq, chains, ap, protocol);
132     } catch (Exception ex)
133     {
134       pdbcanvas.errorMessage = "Error retrieving file: " + pdbentry.getId();
135       ex.printStackTrace();
136     }
137   }
138
139   private void jbInit() throws Exception
140   {
141     this.addKeyListener(new KeyAdapter()
142     {
143       public void keyPressed(KeyEvent evt)
144       {
145         pdbcanvas.keyPressed(evt);
146       }
147     });
148
149     this.setJMenuBar(jMenuBar1);
150     fileMenu.setText("File");
151     coloursMenu.setText("Colours");
152     saveMenu.setActionCommand("Save Image");
153     saveMenu.setText("Save As");
154     png.setText("PNG");
155     png.addActionListener(new ActionListener()
156     {
157       public void actionPerformed(ActionEvent e)
158       {
159         png_actionPerformed(e);
160       }
161     });
162     eps.setText("EPS");
163     eps.addActionListener(new ActionListener()
164     {
165       public void actionPerformed(ActionEvent e)
166       {
167         eps_actionPerformed(e);
168       }
169     });
170     mapping.setText("View Mapping");
171     mapping.addActionListener(new ActionListener()
172     {
173       public void actionPerformed(ActionEvent e)
174       {
175         mapping_actionPerformed(e);
176       }
177     });
178     wire.setText("Wireframe");
179     wire.addActionListener(new ActionListener()
180     {
181       public void actionPerformed(ActionEvent e)
182       {
183         wire_actionPerformed(e);
184       }
185     });
186     depth.setSelected(true);
187     depth.setText("Depthcue");
188     depth.addActionListener(new ActionListener()
189     {
190       public void actionPerformed(ActionEvent e)
191       {
192         depth_actionPerformed(e);
193       }
194     });
195     zbuffer.setSelected(true);
196     zbuffer.setText("Z Buffering");
197     zbuffer.addActionListener(new ActionListener()
198     {
199       public void actionPerformed(ActionEvent e)
200       {
201         zbuffer_actionPerformed(e);
202       }
203     });
204     charge.setText("Charge & Cysteine");
205     charge.addActionListener(new ActionListener()
206     {
207       public void actionPerformed(ActionEvent e)
208       {
209         charge_actionPerformed(e);
210       }
211     });
212     chain.setText("By Chain");
213     chain.addActionListener(new ActionListener()
214     {
215       public void actionPerformed(ActionEvent e)
216       {
217         chain_actionPerformed(e);
218       }
219     });
220     seqButton.setSelected(true);
221     seqButton.setText("By Sequence");
222     seqButton.addActionListener(new ActionListener()
223     {
224       public void actionPerformed(ActionEvent e)
225       {
226         seqButton_actionPerformed(e);
227       }
228     });
229     allchains.setSelected(true);
230     allchains.setText("Show All Chains");
231     allchains.addItemListener(new ItemListener()
232     {
233       public void itemStateChanged(ItemEvent e)
234       {
235         allchains_itemStateChanged(e);
236       }
237     });
238     zappo.setText("Zappo");
239     zappo.addActionListener(new ActionListener()
240     {
241       public void actionPerformed(ActionEvent e)
242       {
243         zappo_actionPerformed(e);
244       }
245     });
246     taylor.setText("Taylor");
247     taylor.addActionListener(new ActionListener()
248     {
249       public void actionPerformed(ActionEvent e)
250       {
251         taylor_actionPerformed(e);
252       }
253     });
254     hydro.setText("Hydro");
255     hydro.addActionListener(new ActionListener()
256     {
257       public void actionPerformed(ActionEvent e)
258       {
259         hydro_actionPerformed(e);
260       }
261     });
262     helix.setText("Helix");
263     helix.addActionListener(new ActionListener()
264     {
265       public void actionPerformed(ActionEvent e)
266       {
267         helix_actionPerformed(e);
268       }
269     });
270     strand.setText("Strand");
271     strand.addActionListener(new ActionListener()
272     {
273       public void actionPerformed(ActionEvent e)
274       {
275         strand_actionPerformed(e);
276       }
277     });
278     turn.setText("Turn");
279     turn.addActionListener(new ActionListener()
280     {
281       public void actionPerformed(ActionEvent e)
282       {
283         turn_actionPerformed(e);
284       }
285     });
286     buried.setText("Buried");
287     buried.addActionListener(new ActionListener()
288     {
289       public void actionPerformed(ActionEvent e)
290       {
291         buried_actionPerformed(e);
292       }
293     });
294     user.setText("User Defined...");
295     user.addActionListener(new ActionListener()
296     {
297       public void actionPerformed(ActionEvent e)
298       {
299         user_actionPerformed(e);
300       }
301     });
302     viewMenu.setText("View");
303     background.setText("Background Colour...");
304     background.addActionListener(new ActionListener()
305     {
306       public void actionPerformed(ActionEvent e)
307       {
308         background_actionPerformed(e);
309       }
310     });
311     savePDB.setText("PDB File");
312     savePDB.addActionListener(new ActionListener()
313     {
314       public void actionPerformed(ActionEvent e)
315       {
316         savePDB_actionPerformed(e);
317       }
318     });
319     jMenuBar1.add(fileMenu);
320     jMenuBar1.add(coloursMenu);
321     jMenuBar1.add(viewMenu);
322     fileMenu.add(saveMenu);
323     fileMenu.add(mapping);
324     saveMenu.add(savePDB);
325     saveMenu.add(png);
326     saveMenu.add(eps);
327     coloursMenu.add(seqButton);
328     coloursMenu.add(chain);
329     coloursMenu.add(charge);
330     coloursMenu.add(zappo);
331     coloursMenu.add(taylor);
332     coloursMenu.add(hydro);
333     coloursMenu.add(helix);
334     coloursMenu.add(strand);
335     coloursMenu.add(turn);
336     coloursMenu.add(buried);
337     coloursMenu.add(user);
338     coloursMenu.add(background);
339     ButtonGroup bg = new ButtonGroup();
340     bg.add(seqButton);
341     bg.add(chain);
342     bg.add(charge);
343     bg.add(zappo);
344     bg.add(taylor);
345     bg.add(hydro);
346     bg.add(helix);
347     bg.add(strand);
348     bg.add(turn);
349     bg.add(buried);
350     bg.add(user);
351
352     if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)
353     {
354       java.util.Enumeration userColours = jalview.gui.UserDefinedColours
355               .getUserColourSchemes().keys();
356
357       while (userColours.hasMoreElements())
358       {
359         final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(
360                 userColours.nextElement().toString());
361         radioItem.setName("USER_DEFINED");
362         radioItem.addMouseListener(new MouseAdapter()
363         {
364           public void mousePressed(MouseEvent evt)
365           {
366             if (evt.isControlDown()
367                     || SwingUtilities.isRightMouseButton(evt))
368             {
369               radioItem.removeActionListener(radioItem.getActionListeners()[0]);
370
371               int option = JOptionPane.showInternalConfirmDialog(
372                       jalview.gui.Desktop.desktop,
373                       "Remove from default list?",
374                       "Remove user defined colour",
375                       JOptionPane.YES_NO_OPTION);
376               if (option == JOptionPane.YES_OPTION)
377               {
378                 jalview.gui.UserDefinedColours
379                         .removeColourFromDefaults(radioItem.getText());
380                 coloursMenu.remove(radioItem);
381               }
382               else
383               {
384                 radioItem.addActionListener(new ActionListener()
385                 {
386                   public void actionPerformed(ActionEvent evt)
387                   {
388                     user_actionPerformed(evt);
389                   }
390                 });
391               }
392             }
393           }
394         });
395         radioItem.addActionListener(new ActionListener()
396         {
397           public void actionPerformed(ActionEvent evt)
398           {
399             user_actionPerformed(evt);
400           }
401         });
402         coloursMenu.add(radioItem);
403         bg.add(radioItem);
404       }
405     }
406
407     viewMenu.add(wire);
408     viewMenu.add(depth);
409     viewMenu.add(zbuffer);
410     viewMenu.add(allchains);
411   }
412
413   JMenuBar jMenuBar1 = new JMenuBar();
414
415   JMenu fileMenu = new JMenu();
416
417   JMenu coloursMenu = new JMenu();
418
419   JMenu saveMenu = new JMenu();
420
421   JMenuItem png = new JMenuItem();
422
423   JMenuItem eps = new JMenuItem();
424
425   JMenuItem mapping = new JMenuItem();
426
427   JCheckBoxMenuItem wire = new JCheckBoxMenuItem();
428
429   JCheckBoxMenuItem depth = new JCheckBoxMenuItem();
430
431   JCheckBoxMenuItem zbuffer = new JCheckBoxMenuItem();
432
433   JCheckBoxMenuItem allchains = new JCheckBoxMenuItem();
434
435   JRadioButtonMenuItem charge = new JRadioButtonMenuItem();
436
437   JRadioButtonMenuItem chain = new JRadioButtonMenuItem();
438
439   JRadioButtonMenuItem seqButton = new JRadioButtonMenuItem();
440
441   JRadioButtonMenuItem hydro = new JRadioButtonMenuItem();
442
443   JRadioButtonMenuItem taylor = new JRadioButtonMenuItem();
444
445   JRadioButtonMenuItem zappo = new JRadioButtonMenuItem();
446
447   JRadioButtonMenuItem user = new JRadioButtonMenuItem();
448
449   JRadioButtonMenuItem buried = new JRadioButtonMenuItem();
450
451   JRadioButtonMenuItem turn = new JRadioButtonMenuItem();
452
453   JRadioButtonMenuItem strand = new JRadioButtonMenuItem();
454
455   JRadioButtonMenuItem helix = new JRadioButtonMenuItem();
456
457   JMenu viewMenu = new JMenu();
458
459   JMenuItem background = new JMenuItem();
460
461   JMenuItem savePDB = new JMenuItem();
462
463   /**
464    * DOCUMENT ME!
465    * 
466    * @param e
467    *          DOCUMENT ME!
468    */
469   public void eps_actionPerformed(ActionEvent e)
470   {
471     makePDBImage(jalview.util.ImageMaker.EPS);
472   }
473
474   /**
475    * DOCUMENT ME!
476    * 
477    * @param e
478    *          DOCUMENT ME!
479    */
480   public void png_actionPerformed(ActionEvent e)
481   {
482     makePDBImage(jalview.util.ImageMaker.PNG);
483   }
484
485   void makePDBImage(int type)
486   {
487     int width = pdbcanvas.getWidth();
488     int height = pdbcanvas.getHeight();
489
490     jalview.util.ImageMaker im;
491
492     if (type == jalview.util.ImageMaker.PNG)
493     {
494       im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.PNG,
495               "Make PNG image from view", width, height, null, null);
496     }
497     else
498     {
499       im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.EPS,
500               "Make EPS file from view", width, height, null,
501               this.getTitle());
502     }
503
504     if (im.getGraphics() != null)
505     {
506       pdbcanvas.drawAll(im.getGraphics(), width, height);
507       im.writeImage();
508     }
509   }
510
511   public void charge_actionPerformed(ActionEvent e)
512   {
513     pdbcanvas.bysequence = false;
514     pdbcanvas.pdb.setChargeColours();
515     pdbcanvas.redrawneeded = true;
516     pdbcanvas.repaint();
517   }
518
519   public void hydro_actionPerformed(ActionEvent e)
520   {
521     pdbcanvas.bysequence = false;
522     pdbcanvas.pdb.setColours(new HydrophobicColourScheme());
523     pdbcanvas.redrawneeded = true;
524     pdbcanvas.repaint();
525   }
526
527   public void chain_actionPerformed(ActionEvent e)
528   {
529     pdbcanvas.bysequence = false;
530     pdbcanvas.pdb.setChainColours();
531     pdbcanvas.redrawneeded = true;
532     pdbcanvas.repaint();
533   }
534
535   public void zbuffer_actionPerformed(ActionEvent e)
536   {
537     pdbcanvas.zbuffer = !pdbcanvas.zbuffer;
538     pdbcanvas.redrawneeded = true;
539     pdbcanvas.repaint();
540   }
541
542   public void molecule_actionPerformed(ActionEvent e)
543   {
544     pdbcanvas.bymolecule = !pdbcanvas.bymolecule;
545     pdbcanvas.redrawneeded = true;
546     pdbcanvas.repaint();
547   }
548
549   public void depth_actionPerformed(ActionEvent e)
550   {
551     pdbcanvas.depthcue = !pdbcanvas.depthcue;
552     pdbcanvas.redrawneeded = true;
553     pdbcanvas.repaint();
554   }
555
556   public void wire_actionPerformed(ActionEvent e)
557   {
558     pdbcanvas.wire = !pdbcanvas.wire;
559     pdbcanvas.redrawneeded = true;
560     pdbcanvas.repaint();
561   }
562
563   public void seqButton_actionPerformed(ActionEvent e)
564   {
565     pdbcanvas.bysequence = true;
566     pdbcanvas.updateSeqColours();
567   }
568
569   public void mapping_actionPerformed(ActionEvent e)
570   {
571     jalview.gui.CutAndPasteTransfer cap = new jalview.gui.CutAndPasteTransfer();
572     try
573     {
574       cap.setText(pdbcanvas.mappingDetails.toString());
575       Desktop.addInternalFrame(cap, "PDB - Sequence Mapping", 550, 600);
576     } catch (OutOfMemoryError oom)
577     {
578       new OOMWarning("Opening sequence to structure mapping report", oom);
579       cap.dispose();
580     }
581   }
582
583   public void allchains_itemStateChanged(ItemEvent e)
584   {
585     pdbcanvas.setAllchainsVisible(allchains.getState());
586   }
587
588   public void zappo_actionPerformed(ActionEvent e)
589   {
590     pdbcanvas.bysequence = false;
591     pdbcanvas.pdb.setColours(new ZappoColourScheme());
592     pdbcanvas.redrawneeded = true;
593     pdbcanvas.repaint();
594   }
595
596   public void taylor_actionPerformed(ActionEvent e)
597   {
598     pdbcanvas.bysequence = false;
599     pdbcanvas.pdb.setColours(new TaylorColourScheme());
600     pdbcanvas.redrawneeded = true;
601     pdbcanvas.repaint();
602   }
603
604   public void helix_actionPerformed(ActionEvent e)
605   {
606     pdbcanvas.bysequence = false;
607     pdbcanvas.pdb.setColours(new HelixColourScheme());
608     pdbcanvas.redrawneeded = true;
609     pdbcanvas.repaint();
610   }
611
612   public void strand_actionPerformed(ActionEvent e)
613   {
614     pdbcanvas.bysequence = false;
615     pdbcanvas.pdb.setColours(new StrandColourScheme());
616     pdbcanvas.redrawneeded = true;
617     pdbcanvas.repaint();
618   }
619
620   public void turn_actionPerformed(ActionEvent e)
621   {
622     pdbcanvas.bysequence = false;
623     pdbcanvas.pdb.setColours(new TurnColourScheme());
624     pdbcanvas.redrawneeded = true;
625     pdbcanvas.repaint();
626   }
627
628   public void buried_actionPerformed(ActionEvent e)
629   {
630     pdbcanvas.bysequence = false;
631     pdbcanvas.pdb.setColours(new BuriedColourScheme());
632     pdbcanvas.redrawneeded = true;
633     pdbcanvas.repaint();
634   }
635
636   public void user_actionPerformed(ActionEvent e)
637   {
638     if (e.getActionCommand().equals("User Defined..."))
639     {
640       // new UserDefinedColours(pdbcanvas, null);
641     }
642     else
643     {
644       UserColourScheme udc = (UserColourScheme) UserDefinedColours
645               .getUserColourSchemes().get(e.getActionCommand());
646
647       pdbcanvas.pdb.setColours(udc);
648       pdbcanvas.redrawneeded = true;
649       pdbcanvas.repaint();
650     }
651   }
652
653   public void background_actionPerformed(ActionEvent e)
654   {
655     java.awt.Color col = JColorChooser.showDialog(this,
656             "Select Background Colour", pdbcanvas.backgroundColour);
657
658     if (col != null)
659     {
660       pdbcanvas.backgroundColour = col;
661       pdbcanvas.redrawneeded = true;
662       pdbcanvas.repaint();
663     }
664   }
665
666   public void savePDB_actionPerformed(ActionEvent e)
667   {
668     JalviewFileChooser chooser = new JalviewFileChooser(
669             jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
670
671     chooser.setFileView(new JalviewFileView());
672     chooser.setDialogTitle("Save PDB File");
673     chooser.setToolTipText("Save");
674
675     int value = chooser.showSaveDialog(this);
676
677     if (value == JalviewFileChooser.APPROVE_OPTION)
678     {
679       try
680       {
681         BufferedReader in = new BufferedReader(new FileReader(tmpPDBFile));
682         File outFile = chooser.getSelectedFile();
683
684         PrintWriter out = new PrintWriter(new FileOutputStream(outFile));
685         String data;
686         while ((data = in.readLine()) != null)
687         {
688           if (!(data.indexOf("<PRE>") > -1 || data.indexOf("</PRE>") > -1))
689           {
690             out.println(data);
691           }
692         }
693         out.close();
694         in.close();
695       } catch (Exception ex)
696       {
697         ex.printStackTrace();
698       }
699     }
700   }
701 }