Chain might be null
[jalview.git] / src / jalview / gui / AppJMol.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer
3  * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19 package jalview.gui;
20
21 import java.util.regex.*;
22 import java.util.*;
23 import java.awt.*;
24 import javax.swing.*;
25 import javax.swing.event.*;
26 import java.awt.event.*;
27 import java.io.*;
28
29 import jalview.jbgui.GStructureViewer;
30 import jalview.datamodel.*;
31 import jalview.gui.*;
32 import jalview.structure.*;
33 import jalview.datamodel.PDBEntry;
34 import jalview.io.*;
35 import jalview.schemes.*;
36
37 import org.jmol.api.*;
38 import org.jmol.adapter.smarter.SmarterJmolAdapter;
39 import org.jmol.popup.*;
40
41
42 public class AppJMol
43     extends GStructureViewer
44     implements StructureListener, JmolStatusListener, Runnable
45
46 {
47   JmolViewer viewer;
48   JmolPopup jmolpopup;
49   ScriptWindow scriptWindow;
50   PDBEntry pdbentry;
51   SequenceI[] sequence;
52   StructureSelectionManager ssm;
53   JSplitPane splitPane;
54   RenderPanel renderPanel;
55   AlignmentPanel ap;
56   String fileLoadingError;
57   boolean colourBySequence = true;
58   boolean loadingFromArchive = false;
59   Vector atomsPicked = new Vector();
60
61   public AppJMol(String file, String id,
62                  SequenceI[] seq,
63                  AlignmentPanel ap,
64                  String loadStatus,
65                  Rectangle bounds)
66   {
67     loadingFromArchive = true;
68     pdbentry = new PDBEntry();
69     pdbentry.setFile(file);
70     pdbentry.setId(id);
71     this.sequence = seq;
72     this.ap = ap;
73     this.setBounds(bounds);
74
75     colourBySequence = false;
76     seqColour.setSelected(false);
77
78     jalview.gui.Desktop.addInternalFrame(this, "Loading File",
79                                          bounds.width,bounds.height);
80
81     initJmol(loadStatus);
82
83     this.addInternalFrameListener(new InternalFrameAdapter()
84     {
85       public void internalFrameClosing(InternalFrameEvent internalFrameEvent)
86       {
87         closeViewer();
88       }
89     });
90   }
91
92 public synchronized void addSequence(SequenceI [] seq)
93    {
94     Vector v = new Vector();
95      for(int i=0; i<sequence.length; i++)
96        v.addElement(sequence[i]);
97
98      for(int i=0; i<seq.length; i++)
99       if(!v.contains(seq[i]))
100           v.addElement(seq[i]);
101
102      SequenceI [] tmp = new SequenceI[v.size()];
103      v.copyInto(tmp);
104      sequence = tmp;
105    }
106
107   public AppJMol(PDBEntry pdbentry, SequenceI[] seq, AlignmentPanel ap)
108   {
109     //////////////////////////////////
110     //Is the pdb file already loaded?
111     String alreadyMapped = StructureSelectionManager
112         .getStructureSelectionManager()
113         .alreadyMappedToFile(pdbentry.getId());
114
115     if (alreadyMapped != null)
116     {
117       int option = JOptionPane.showInternalConfirmDialog(Desktop.desktop,
118           pdbentry.getId() + " is already displayed."
119           + "\nDo you want to map sequences to the visible structure?",
120           "Map Sequences to Visible Window: " + pdbentry.getId(),
121           JOptionPane.YES_NO_OPTION);
122
123       if (option == JOptionPane.YES_OPTION)
124       {
125         StructureSelectionManager.getStructureSelectionManager()
126             .setMapping(seq, alreadyMapped, AppletFormatAdapter.FILE);
127         ap.seqPanel.seqCanvas.fr.featuresAdded();
128         ap.paintAlignment(true);
129         return;
130       }
131     }
132     ///////////////////////////////////
133
134     this.ap = ap;
135     this.pdbentry = pdbentry;
136     this.sequence = seq;
137
138     jalview.gui.Desktop.addInternalFrame(this, "Loading File", 400, 400);
139
140     if (pdbentry.getFile() != null)
141     {
142       initJmol("load \""+pdbentry.getFile()+"\"");
143     }
144     else
145     {
146       Thread worker = new Thread(this);
147       worker.start();
148     }
149
150     this.addInternalFrameListener(new InternalFrameAdapter()
151     {
152       public void internalFrameClosing(InternalFrameEvent internalFrameEvent)
153       {
154         closeViewer();
155       }
156     });
157   }
158
159
160   void initJmol(String command)
161   {
162     renderPanel = new RenderPanel();
163
164     this.getContentPane().add(renderPanel, java.awt.BorderLayout.CENTER);
165
166     StringBuffer title = new StringBuffer(sequence[0].getName() + ":" +
167                                           pdbentry.getId());
168
169     if (pdbentry.getProperty() != null)
170     {
171       if (pdbentry.getProperty().get("method") != null)
172       {
173         title.append(" Method: ");
174         title.append(pdbentry.getProperty().get("method"));
175       }
176       if (pdbentry.getProperty().get("chains") != null)
177       {
178         title.append(" Chain:");
179         title.append(pdbentry.getProperty().get("chains"));
180       }
181     }
182
183     this.setTitle(title.toString());
184
185     viewer = org.jmol.api.JmolViewer.allocateViewer(renderPanel,
186         new SmarterJmolAdapter());
187
188
189     viewer.setAppletContext("", null, null, "");
190
191     viewer.setJmolStatusListener(this);
192
193     jmolpopup = JmolPopup.newJmolPopup(viewer);
194
195     viewer.evalStringQuiet(command);
196   }
197
198
199   void setChainMenuItems(Vector chains)
200   {
201     chainMenu.removeAll();
202
203     JMenuItem menuItem = new JMenuItem("All");
204     menuItem.addActionListener(new ActionListener()
205         {
206           public void actionPerformed(ActionEvent evt)
207           {
208             allChainsSelected = true;
209             for(int i=0; i<chainMenu.getItemCount(); i++)
210             {
211               if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
212                 ( (JCheckBoxMenuItem) chainMenu.getItem(i)).setSelected(true);
213             }
214             centerViewer();
215             allChainsSelected = false;
216           }
217         });
218
219     chainMenu.add(menuItem);
220
221     for (int c = 0; c < chains.size(); c++)
222     {
223       menuItem = new JCheckBoxMenuItem(chains.elementAt(c).toString(), true);
224       menuItem.addItemListener(new ItemListener()
225       {
226         public void itemStateChanged(ItemEvent evt)
227         {
228           if (!allChainsSelected)
229             centerViewer();
230         }
231       });
232
233       chainMenu.add(menuItem);
234     }
235   }
236
237   boolean allChainsSelected = false;
238   void centerViewer()
239   {
240     StringBuffer cmd = new StringBuffer();
241     for(int i=0; i<chainMenu.getItemCount(); i++)
242     {
243       if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
244       {
245        JCheckBoxMenuItem item = (JCheckBoxMenuItem) chainMenu.getItem(i);
246        if(item.isSelected())
247          cmd.append(":"+item.getText()+" or ");
248       }
249     }
250
251     if (cmd.length() > 0)
252       cmd.setLength(cmd.length() - 4);
253
254     viewer.evalStringQuiet("select *;restrict "
255                       +cmd+";cartoon;center "+cmd);
256   }
257
258   void closeViewer()
259   {
260     viewer.setModeMouse(org.jmol.viewer.JmolConstants.MOUSE_NONE);
261     viewer.evalStringQuiet("zap");
262     viewer.setJmolStatusListener(null);
263     viewer = null;
264
265     //We'll need to find out what other
266     // listeners need to be shut down in Jmol
267     StructureSelectionManager
268         .getStructureSelectionManager()
269         .removeStructureViewerListener(this, pdbentry.getFile());
270   }
271
272   public void run()
273   {
274     try
275     {
276       EBIFetchClient ebi = new EBIFetchClient();
277       String query = "pdb:" + pdbentry.getId();
278       pdbentry.setFile(ebi.fetchDataAsFile(query, "default", "raw")
279                        .getAbsolutePath());
280       initJmol("load "+pdbentry.getFile());
281     }
282     catch (Exception ex)
283     {
284       ex.printStackTrace();
285     }
286   }
287
288   public void pdbFile_actionPerformed(ActionEvent actionEvent)
289   {
290     JalviewFileChooser chooser = new JalviewFileChooser(
291         jalview.bin.Cache.getProperty(
292             "LAST_DIRECTORY"));
293
294     chooser.setFileView(new JalviewFileView());
295     chooser.setDialogTitle("Save PDB File");
296     chooser.setToolTipText("Save");
297
298     int value = chooser.showSaveDialog(this);
299
300     if (value == JalviewFileChooser.APPROVE_OPTION)
301     {
302       try
303       {
304         BufferedReader in = new BufferedReader(new FileReader(pdbentry.getFile()));
305         File outFile = chooser.getSelectedFile();
306
307         PrintWriter out = new PrintWriter(new FileOutputStream(outFile));
308         String data;
309         while ( (data = in.readLine()) != null)
310         {
311           if (
312               ! (data.indexOf("<PRE>") > -1 || data.indexOf("</PRE>") > -1)
313               )
314           {
315             out.println(data);
316           }
317         }
318         out.close();
319       }
320       catch (Exception ex)
321       {
322         ex.printStackTrace();
323       }
324     }
325   }
326
327   public void viewMapping_actionPerformed(ActionEvent actionEvent)
328   {
329     jalview.gui.CutAndPasteTransfer cap = new jalview.gui.CutAndPasteTransfer();
330     jalview.gui.Desktop.addInternalFrame(cap, "PDB - Sequence Mapping", 550,
331                                          600);
332     cap.setText(
333         StructureSelectionManager.getStructureSelectionManager().printMapping(
334             pdbentry.getFile())
335         );
336   }
337
338   /**
339    * DOCUMENT ME!
340    *
341    * @param e DOCUMENT ME!
342    */
343   public void eps_actionPerformed(ActionEvent e)
344   {
345     makePDBImage(jalview.util.ImageMaker.EPS);
346   }
347
348   /**
349    * DOCUMENT ME!
350    *
351    * @param e DOCUMENT ME!
352    */
353   public void png_actionPerformed(ActionEvent e)
354   {
355     makePDBImage(jalview.util.ImageMaker.PNG);
356   }
357
358   void makePDBImage(int type)
359   {
360     int width = getWidth();
361     int height = getHeight();
362
363     jalview.util.ImageMaker im;
364
365     if (type == jalview.util.ImageMaker.PNG)
366     {
367       im = new jalview.util.ImageMaker(this,
368                                        jalview.util.ImageMaker.PNG,
369                                        "Make PNG image from view",
370                                        width, height,
371                                        null, null);
372     }
373     else
374     {
375       im = new jalview.util.ImageMaker(this,
376                                        jalview.util.ImageMaker.EPS,
377                                        "Make EPS file from view",
378                                        width, height,
379                                        null, this.getTitle());
380     }
381
382     if (im.getGraphics() != null)
383     {
384       Rectangle rect = new Rectangle(width, height);
385       viewer.renderScreenImage(im.getGraphics(),
386                                rect.getSize(), rect);
387       im.writeImage();
388     }
389   }
390
391
392   public void seqColour_actionPerformed(ActionEvent actionEvent)
393   {
394     colourBySequence = seqColour.isSelected();
395     colourBySequence(ap);
396   }
397
398   public void chainColour_actionPerformed(ActionEvent actionEvent)
399   {
400     colourBySequence = false;
401     seqColour.setSelected(false);
402     viewer.evalStringQuiet("select *;color chain");
403   }
404
405   public void chargeColour_actionPerformed(ActionEvent actionEvent)
406   {
407     colourBySequence = false;
408     seqColour.setSelected(false);
409     viewer.evalStringQuiet("select *;color white;select ASP,GLU;color red;"
410                       +"select LYS,ARG;color blue;select CYS;color yellow");
411   }
412
413   public void zappoColour_actionPerformed(ActionEvent actionEvent)
414   {
415     setJalviewColourScheme(new ZappoColourScheme());
416   }
417
418   public void taylorColour_actionPerformed(ActionEvent actionEvent)
419   {
420     setJalviewColourScheme(new TaylorColourScheme());
421   }
422
423   public void hydroColour_actionPerformed(ActionEvent actionEvent)
424   {
425     setJalviewColourScheme(new HydrophobicColourScheme());
426   }
427
428   public void helixColour_actionPerformed(ActionEvent actionEvent)
429   {
430     setJalviewColourScheme(new HelixColourScheme());
431   }
432
433   public void strandColour_actionPerformed(ActionEvent actionEvent)
434   {
435     setJalviewColourScheme(new StrandColourScheme());
436   }
437
438   public void turnColour_actionPerformed(ActionEvent actionEvent)
439   {
440     setJalviewColourScheme(new TurnColourScheme());
441   }
442
443   public void buriedColour_actionPerformed(ActionEvent actionEvent)
444   {
445     setJalviewColourScheme(new BuriedColourScheme());
446   }
447
448   public void setJalviewColourScheme(ColourSchemeI cs)
449   {
450     colourBySequence = false;
451     seqColour.setSelected(false);
452
453     if(cs==null)
454       return;
455
456     String res;
457     int index;
458     Color col;
459
460     Enumeration en = ResidueProperties.aa3Hash.keys();
461     StringBuffer command = new StringBuffer("select *;color white;");
462     while(en.hasMoreElements())
463     {
464       res = en.nextElement().toString();
465       index = ((Integer) ResidueProperties.aa3Hash.get(res)).intValue();
466       if(index>20)
467         continue;
468
469       col = cs.findColour(ResidueProperties.aa[index].charAt(0));
470
471       command.append("select "+res+";color["
472                         + col.getRed() + ","
473                         + col.getGreen() + ","
474                         + col.getBlue() + "];");
475     }
476
477     viewer.evalStringQuiet(command.toString());
478   }
479
480   public void userColour_actionPerformed(ActionEvent actionEvent)
481   {
482     new UserDefinedColours(this, null);
483   }
484
485   public void backGround_actionPerformed(ActionEvent actionEvent)
486   {
487     java.awt.Color col = JColorChooser.showDialog(this,
488                                                   "Select Background Colour",
489                                                   null);
490
491     if (col != null)
492     {
493       viewer.evalStringQuiet("background ["
494                         + col.getRed() + ","
495                         + col.getGreen() + ","
496                         + col.getBlue() + "];");
497     }
498   }
499
500
501   public void jmolHelp_actionPerformed(ActionEvent actionEvent)
502   {
503        try{
504          jalview.util.BrowserLauncher.openURL(
505              "http://jmol.sourceforge.net/docs/JmolUserGuide/");
506        }catch(Exception ex){}
507    }
508
509
510   //////////////////////////////////
511   ///StructureListener
512   public String getPdbFile()
513   {
514     return pdbentry.getFile();
515   }
516
517   Pattern pattern = Pattern.compile(
518       "\\[(.*)\\]([0-9]+)(:[a-zA-Z]*)?\\.([a-zA-Z]+)(/[0-9]*)?"
519       );
520
521   String lastMessage;
522   public void mouseOverStructure(int atomIndex, String strInfo)
523   {
524     Matcher matcher = pattern.matcher(strInfo);
525     matcher.find();
526     matcher.group(1);
527     int pdbResNum = Integer.parseInt(matcher.group(2));
528     String chainId = matcher.group(3);
529
530     if (chainId != null)
531       chainId = chainId.substring(1, chainId.length());
532     else
533     {
534       chainId = " ";
535     }
536
537     if (lastMessage == null || !lastMessage.equals(strInfo))
538       ssm.mouseOverStructure(pdbResNum, chainId, pdbentry.getFile());
539
540     lastMessage = strInfo;
541   }
542
543   StringBuffer resetLastRes = new StringBuffer();
544   StringBuffer eval = new StringBuffer();
545
546   public void highlightAtom(int atomIndex, int pdbResNum, String chain, String pdbfile)
547   {
548     if (!pdbfile.equals(pdbentry.getFile()))
549       return;
550
551     if (resetLastRes.length() > 0)
552     {
553       viewer.evalStringQuiet(resetLastRes.toString());
554     }
555
556     eval.setLength(0);
557     eval.append("select " + pdbResNum);
558
559     resetLastRes.setLength(0);
560     resetLastRes.append("select " + pdbResNum);
561
562     if (!chain.equals(" "))
563     {
564       eval.append(":" + chain);
565       resetLastRes.append(":" + chain);
566     }
567
568     eval.append(";color gold;wireframe 100");
569
570     Color col = new Color(viewer.getAtomArgb(atomIndex));
571
572     resetLastRes.append(";color["
573                         + col.getRed() + ","
574                         + col.getGreen() + ","
575                         + col.getBlue() + "];wireframe 0");
576
577     viewer.evalStringQuiet(eval.toString());
578
579   }
580
581   public void updateColours(Object source)
582   {
583     colourBySequence( (AlignmentPanel) source);
584   }
585
586
587 //End StructureListener
588 ////////////////////////////
589
590   FeatureRenderer fr;
591   public void colourBySequence(AlignmentPanel ap)
592   {
593     if(!colourBySequence)
594       return;
595
596
597     StructureMapping[] mapping = ssm.getMapping(pdbentry.getFile());
598
599     if (mapping.length < 1)
600       return;
601
602     SequenceRenderer sr = ap.seqPanel.seqCanvas.getSequenceRenderer();
603
604     boolean showFeatures = false;
605     if (ap.av.showSequenceFeatures)
606     {
607       showFeatures = true;
608       if (fr == null)
609       {
610         fr = new jalview.gui.FeatureRenderer(ap.av);
611       }
612
613       fr.transferSettings(ap.seqPanel.seqCanvas.getFeatureRenderer());
614     }
615
616     StringBuffer command = new StringBuffer();
617
618     int lastPos = -1;
619     for (int s = 0; s < sequence.length; s++)
620     {
621       for (int m = 0; m < mapping.length; m++)
622       {
623         if (mapping[m].getSequence() == sequence[s])
624         {
625           for (int r = 0; r < sequence[s].getLength(); r++)
626           {
627             int pos = mapping[m].getPDBResNum(
628                 sequence[s].findPosition(r));
629
630             if (pos < 1 || pos==lastPos)
631               continue;
632
633             lastPos = pos;
634
635             Color col = sr.getResidueBoxColour(sequence[s], r);
636
637             if (showFeatures)
638               col = fr.findFeatureColour(col, sequence[s], r);
639
640             if (command.toString().endsWith(":" + mapping[m].getChain()+
641                                             ";color["
642                                             + col.getRed() + ","
643                                             + col.getGreen() + ","
644                                             + col.getBlue() + "]"))
645             {
646               command = condenseCommand(command, pos);
647               continue;
648             }
649
650             command.append(";select " + pos);
651
652             if (!mapping[m].getChain().equals(" "))
653             {
654               command.append(":" + mapping[m].getChain());
655             }
656
657             command.append(";color["
658                              + col.getRed() + ","
659                              + col.getGreen() + ","
660                              + col.getBlue() + "]");
661
662           }
663           break;
664         }
665       }
666     }
667
668     viewer.evalStringQuiet(command.toString());
669   }
670
671   StringBuffer condenseCommand(StringBuffer command, int pos)
672   {
673     StringBuffer sb = new StringBuffer(command.substring(0, command.lastIndexOf("select")+7));
674
675     command.delete(0, sb.length());
676
677     String start;
678
679     if (command.indexOf("-") > -1)
680     {
681       start = command.substring(0,command.indexOf("-"));
682     }
683     else
684     {
685       start = command.substring(0, command.indexOf(":"));
686     }
687
688     sb.append(start+"-"+pos+command.substring(command.indexOf(":")));
689
690     return sb;
691   }
692
693   /////////////////////////////////
694   //JmolStatusListener
695
696   public String eval(String strEval)
697   {
698    // System.out.println(strEval);
699    //"# 'eval' is implemented only for the applet.";
700     return null;
701   }
702
703   public void createImage(String file, String type, int quality)
704   {
705     System.out.println("JMOL CREATE IMAGE");
706   }
707
708   public void setCallbackFunction(String callbackType,
709                                   String callbackFunction)
710   {}
711
712   public void notifyFileLoaded(String fullPathName, String fileName,
713                                String modelName, Object clientFile,
714                                String errorMsg)
715   {
716     if(errorMsg!=null)
717     {
718       fileLoadingError = errorMsg;
719       repaint();
720       return;
721     }
722
723     fileLoadingError = null;
724
725     if (fileName != null)
726     {
727
728       //FILE LOADED OK
729       ssm = StructureSelectionManager.getStructureSelectionManager();
730       MCview.PDBfile pdbFile = ssm.setMapping(sequence, pdbentry.getFile(), AppletFormatAdapter.FILE);
731       ssm.addStructureViewerListener(this);
732
733       Vector chains = new Vector();
734       for(int i=0; i<pdbFile.chains.size(); i++)
735       {
736         chains.addElement(((MCview.PDBChain)pdbFile.chains.elementAt(i)).id);
737       }
738       setChainMenuItems(chains);
739
740       jmolpopup.updateComputedMenus();
741
742       if(!loadingFromArchive)
743       {
744         viewer.evalStringQuiet(
745              "select backbone;restrict;cartoon;wireframe off;spacefill off");
746
747         colourBySequence(ap);
748       }
749
750       loadingFromArchive = false;
751     }
752     else
753       return;
754   }
755
756   public void notifyFrameChanged(int frameNo)
757   {
758     boolean isAnimationRunning = (frameNo <= -2);
759   }
760
761   public void notifyScriptStart(String statusMessage, String additionalInfo)
762   {}
763
764   public void sendConsoleEcho(String strEcho)
765   {
766     if (scriptWindow != null)
767       scriptWindow.sendConsoleEcho(strEcho);
768   }
769
770   public void sendConsoleMessage(String strStatus)
771   {
772     if (scriptWindow != null)
773       scriptWindow.sendConsoleMessage(strStatus);
774   }
775
776   public void notifyScriptTermination(String strStatus, int msWalltime)
777   {
778     if (scriptWindow != null)
779       scriptWindow.notifyScriptTermination(strStatus, msWalltime);
780   }
781
782   public void handlePopupMenu(int x, int y)
783   {
784     jmolpopup.show(x, y);
785   }
786
787   public void notifyNewPickingModeMeasurement(int iatom, String strMeasure)
788   {
789     notifyAtomPicked(iatom, strMeasure);
790   }
791
792   public void notifyNewDefaultModeMeasurement(int count, String strInfo)
793   {}
794
795   public void notifyAtomPicked(int atomIndex, String strInfo)
796   {
797     Matcher matcher = pattern.matcher(strInfo);
798     matcher.find();
799
800     matcher.group(1);
801     String resnum = new String(matcher.group(2));
802     String chainId = matcher.group(3);
803
804     String picked = resnum;
805
806     if (chainId != null)
807       picked+=(":"+chainId.substring(1, chainId.length()));
808
809     picked+=".C";
810
811     if (!atomsPicked.contains(picked))
812     {
813       if(chainId!=null)
814       viewer.evalString("select "+picked+";label %n %r:%c");
815     else
816       viewer.evalString("select "+picked+";label %n %r");
817       atomsPicked.addElement(picked);
818     }
819     else
820     {
821       viewer.evalString("select "+picked+";label off");
822       atomsPicked.removeElement(picked);
823     }
824
825     if (scriptWindow != null)
826     {
827       scriptWindow.sendConsoleMessage(strInfo);
828       scriptWindow.sendConsoleMessage("\n");
829     }
830   }
831
832   public void notifyAtomHovered(int atomIndex, String strInfo)
833   {
834     mouseOverStructure(atomIndex, strInfo);
835   }
836
837   public void sendSyncScript(String script, String appletName)
838   {}
839
840   public void showUrl(String url)
841   {}
842
843   public void showConsole(boolean showConsole)
844   {
845     if (scriptWindow == null)
846       scriptWindow = new ScriptWindow(this);
847
848     if(showConsole)
849     {
850       if(splitPane==null)
851       {
852         splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
853         splitPane.setTopComponent(renderPanel);
854         splitPane.setBottomComponent(scriptWindow);
855         this.getContentPane().add(splitPane, BorderLayout.CENTER);
856       }
857
858       splitPane.setDividerLocation(getHeight()-200);
859       splitPane.validate();
860     }
861     else
862     {
863       if (splitPane != null)
864         splitPane.setVisible(false);
865
866       splitPane = null;
867
868       this.getContentPane().add(renderPanel, BorderLayout.CENTER);
869     }
870
871     validate();
872   }
873
874   public float functionXY(String functionName, int x, int y)
875   {
876     return 0;
877   }
878
879   ///End JmolStatusListener
880   ///////////////////////////////
881
882
883   class RenderPanel
884       extends JPanel
885   {
886     final Dimension currentSize = new Dimension();
887     final Rectangle rectClip = new Rectangle();
888
889     public void paintComponent(Graphics g)
890     {
891       getSize(currentSize);
892       g.getClipBounds(rectClip);
893
894       if (viewer == null)
895       {
896         g.setColor(Color.black);
897         g.fillRect(0, 0, currentSize.width, currentSize.height);
898         g.setColor(Color.white);
899         g.setFont(new Font("Verdana", Font.BOLD, 14));
900         g.drawString("Retrieving PDB data....", 20, currentSize.height / 2);
901       }
902       else if(fileLoadingError!=null)
903       {
904         g.setColor(Color.black);
905         g.fillRect(0, 0, currentSize.width, currentSize.height);
906         g.setColor(Color.white);
907         g.setFont(new Font("Verdana", Font.BOLD, 14));
908         g.drawString("Error loading file..." + pdbentry.getId(), 20,
909                      currentSize.height / 2);
910       }
911       else
912       {
913         viewer.renderScreenImage(g, currentSize, rectClip);
914       }
915     }
916   }
917
918 }