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