retrieve and init vamsas session from vdoc at URL
[jalview.git] / src / jalview / gui / Desktop.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Development Version 2.4.1)
3  * Copyright (C) 2009 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 jalview.io.*;
22
23 import java.awt.*;
24 import java.awt.datatransfer.*;
25 import java.awt.dnd.*;
26 import java.awt.event.*;
27 import java.io.BufferedInputStream;
28 import java.io.BufferedOutputStream;
29 import java.io.File;
30 import java.io.FileOutputStream;
31 import java.io.InputStream;
32 import java.lang.reflect.Constructor;
33 import java.net.URL;
34 import java.net.URLConnection;
35 import java.nio.channels.ReadableByteChannel;
36 import java.util.*;
37
38 import javax.swing.*;
39 import javax.swing.event.MenuEvent;
40 import javax.swing.event.MenuListener;
41
42 /**
43  * DOCUMENT ME!
44  * 
45  * @author $author$
46  * @version $Revision$
47  */
48 public class Desktop extends jalview.jbgui.GDesktop implements
49         DropTargetListener, ClipboardOwner, IProgressIndicator
50 {
51   /** DOCUMENT ME!! */
52   public static Desktop instance;
53
54   // Need to decide if the Memory Usage is to be included in
55   // Next release or not.
56   public static MyDesktopPane desktop;
57
58   // public static JDesktopPane desktop;
59
60   static int openFrameCount = 0;
61
62   static final int xOffset = 30;
63
64   static final int yOffset = 30;
65
66   public static jalview.ws.Discoverer discoverer;
67
68   public static Object[] jalviewClipboard;
69
70   public static boolean internalCopy = false;
71
72   static int fileLoadingCount = 0;
73
74   /**
75    * Creates a new Desktop object.
76    */
77   public Desktop()
78   {
79     /**
80      * A note to implementors. It is ESSENTIAL that any activities that might
81      * block are spawned off as threads rather than waited for during this
82      * constructor.
83      */
84     instance = this;
85     doVamsasClientCheck();
86     doGroovyCheck();
87
88     setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
89     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
90     boolean selmemusage = jalview.bin.Cache.getDefault("SHOW_MEMUSAGE",
91             false);
92     desktop = new MyDesktopPane(selmemusage);
93     showMemusage.setSelected(selmemusage);
94     desktop.setBackground(Color.white);
95     getContentPane().setLayout(new BorderLayout());
96     getContentPane().add(desktop, BorderLayout.CENTER);
97     desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
98
99     // This line prevents Windows Look&Feel resizing all new windows to maximum
100     // if previous window was maximised
101     desktop.setDesktopManager(new DefaultDesktopManager());
102
103     Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
104     String x = jalview.bin.Cache.getProperty("SCREEN_X");
105     String y = jalview.bin.Cache.getProperty("SCREEN_Y");
106     String width = jalview.bin.Cache.getProperty("SCREEN_WIDTH");
107     String height = jalview.bin.Cache.getProperty("SCREEN_HEIGHT");
108
109     if ((x != null) && (y != null) && (width != null) && (height != null))
110     {
111       setBounds(Integer.parseInt(x), Integer.parseInt(y), Integer
112               .parseInt(width), Integer.parseInt(height));
113     }
114     else
115     {
116       setBounds((int) (screenSize.width - 900) / 2,
117               (int) (screenSize.height - 650) / 2, 900, 650);
118     }
119
120     this.addWindowListener(new WindowAdapter()
121     {
122       public void windowClosing(WindowEvent evt)
123       {
124         quit();
125       }
126     });
127
128     this.addMouseListener(new MouseAdapter()
129     {
130       public void mousePressed(MouseEvent evt)
131       {
132         if (SwingUtilities.isRightMouseButton(evt))
133         {
134           showPasteMenu(evt.getX(), evt.getY());
135         }
136       }
137     });
138
139     this.setDropTarget(new java.awt.dnd.DropTarget(desktop, this));
140     // Spawn a thread that shows the splashscreen
141     new SplashScreen();
142
143     discoverer = new jalview.ws.Discoverer(); // Only gets started if gui is
144     // displayed.
145   }
146
147   private void doVamsasClientCheck()
148   {
149     if (jalview.bin.Cache.vamsasJarsPresent())
150     {
151       setupVamsasDisconnectedGui();
152       VamsasMenu.setVisible(true);
153       final Desktop us = this;
154       VamsasMenu.addMenuListener(new MenuListener()
155       {
156         // this listener remembers when the menu was first selected, and
157         // doesn't rebuild the session list until it has been cleared and
158         // reselected again.
159         boolean refresh = true;
160
161         public void menuCanceled(MenuEvent e)
162         {
163           refresh = true;
164         }
165
166         public void menuDeselected(MenuEvent e)
167         {
168           refresh = true;
169         }
170
171         public void menuSelected(MenuEvent e)
172         {
173           if (refresh)
174           {
175             us.buildVamsasStMenu();
176             refresh = false;
177           }
178         }
179       });
180       vamsasStart.setVisible(true);
181     }
182   }
183
184   void showPasteMenu(int x, int y)
185   {
186     JPopupMenu popup = new JPopupMenu();
187     JMenuItem item = new JMenuItem("Paste To New Window");
188     item.addActionListener(new ActionListener()
189     {
190       public void actionPerformed(ActionEvent evt)
191       {
192         paste();
193       }
194     });
195
196     popup.add(item);
197     popup.show(this, x, y);
198   }
199
200   public void paste()
201   {
202     try
203     {
204       Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
205       Transferable contents = c.getContents(this);
206
207       if (contents != null)
208       {
209         String file = (String) contents
210                 .getTransferData(DataFlavor.stringFlavor);
211
212         String format = new IdentifyFile().Identify(file,
213                 FormatAdapter.PASTE);
214
215         new FileLoader().LoadFile(file, FormatAdapter.PASTE, format);
216
217       }
218     } catch (Exception ex)
219     {
220       System.out
221               .println("Unable to paste alignment from system clipboard:\n"
222                       + ex);
223     }
224   }
225
226   /**
227    * DOCUMENT ME!
228    * 
229    * @param frame
230    *          DOCUMENT ME!
231    * @param title
232    *          DOCUMENT ME!
233    * @param w
234    *          DOCUMENT ME!
235    * @param h
236    *          DOCUMENT ME!
237    */
238   public static synchronized void addInternalFrame(
239           final JInternalFrame frame, String title, int w, int h)
240   {
241     addInternalFrame(frame, title, w, h, true);
242   }
243
244   /**
245    * DOCUMENT ME!
246    * 
247    * @param frame
248    *          DOCUMENT ME!
249    * @param title
250    *          DOCUMENT ME!
251    * @param w
252    *          DOCUMENT ME!
253    * @param h
254    *          DOCUMENT ME!
255    * @param resizable
256    *          DOCUMENT ME!
257    */
258   public static synchronized void addInternalFrame(
259           final JInternalFrame frame, String title, int w, int h,
260           boolean resizable)
261   {
262
263     // TODO: consider fixing method to update entries in the window submenu with
264     // the current window title
265
266     frame.setTitle(title);
267     if (frame.getWidth() < 1 || frame.getHeight() < 1)
268     {
269       frame.setSize(w, h);
270     }
271     // THIS IS A PUBLIC STATIC METHOD, SO IT MAY BE CALLED EVEN IN
272     // A HEADLESS STATE WHEN NO DESKTOP EXISTS. MUST RETURN
273     // IF JALVIEW IS RUNNING HEADLESS
274     // ///////////////////////////////////////////////
275     if (System.getProperty("java.awt.headless") != null
276             && System.getProperty("java.awt.headless").equals("true"))
277     {
278       return;
279     }
280
281     openFrameCount++;
282
283     frame.setVisible(true);
284     frame.setClosable(true);
285     frame.setResizable(resizable);
286     frame.setMaximizable(resizable);
287     frame.setIconifiable(resizable);
288     frame.setFrameIcon(null);
289
290     if (frame.getX() < 1 && frame.getY() < 1)
291     {
292       frame.setLocation(xOffset * openFrameCount, yOffset
293               * ((openFrameCount - 1) % 10) + yOffset);
294     }
295
296     final JMenuItem menuItem = new JMenuItem(title);
297     frame
298             .addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
299             {
300               public void internalFrameActivated(
301                       javax.swing.event.InternalFrameEvent evt)
302               {
303                 JInternalFrame itf = desktop.getSelectedFrame();
304                 if (itf != null)
305                 {
306                   itf.requestFocus();
307                 }
308
309               }
310
311               public void internalFrameClosed(
312                       javax.swing.event.InternalFrameEvent evt)
313               {
314                 PaintRefresher.RemoveComponent(frame);
315                 openFrameCount--;
316                 windowMenu.remove(menuItem);
317                 JInternalFrame itf = desktop.getSelectedFrame();
318                 if (itf != null)
319                 {
320                   itf.requestFocus();
321                 }
322                 System.gc();
323               };
324             });
325
326     menuItem.addActionListener(new ActionListener()
327     {
328       public void actionPerformed(ActionEvent e)
329       {
330         try
331         {
332           frame.setSelected(true);
333           frame.setIcon(false);
334         } catch (java.beans.PropertyVetoException ex)
335         {
336
337         }
338       }
339     });
340
341     windowMenu.add(menuItem);
342
343     desktop.add(frame);
344     frame.toFront();
345     try
346     {
347       frame.setSelected(true);
348       frame.requestFocus();
349     } catch (java.beans.PropertyVetoException ve)
350     {
351     }
352   }
353
354   public void lostOwnership(Clipboard clipboard, Transferable contents)
355   {
356     if (!internalCopy)
357     {
358       Desktop.jalviewClipboard = null;
359     }
360
361     internalCopy = false;
362   }
363
364   public void dragEnter(DropTargetDragEvent evt)
365   {
366   }
367
368   public void dragExit(DropTargetEvent evt)
369   {
370   }
371
372   public void dragOver(DropTargetDragEvent evt)
373   {
374   }
375
376   public void dropActionChanged(DropTargetDragEvent evt)
377   {
378   }
379
380   /**
381    * DOCUMENT ME!
382    * 
383    * @param evt
384    *          DOCUMENT ME!
385    */
386   public void drop(DropTargetDropEvent evt)
387   {
388     Transferable t = evt.getTransferable();
389     java.util.List files = null;
390
391     try
392     {
393       DataFlavor uriListFlavor = new DataFlavor(
394               "text/uri-list;class=java.lang.String");
395       if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
396       {
397         // Works on Windows and MacOSX
398         evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
399         files = (java.util.List) t
400                 .getTransferData(DataFlavor.javaFileListFlavor);
401       }
402       else if (t.isDataFlavorSupported(uriListFlavor))
403       {
404         // This is used by Unix drag system
405         evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
406         String data = (String) t.getTransferData(uriListFlavor);
407         files = new java.util.ArrayList(1);
408         for (java.util.StringTokenizer st = new java.util.StringTokenizer(
409                 data, "\r\n"); st.hasMoreTokens();)
410         {
411           String s = st.nextToken();
412           if (s.startsWith("#"))
413           {
414             // the line is a comment (as per the RFC 2483)
415             continue;
416           }
417
418           java.net.URI uri = new java.net.URI(s);
419           java.io.File file = new java.io.File(uri);
420           files.add(file);
421         }
422       }
423     } catch (Exception e)
424     {
425     }
426
427     if (files != null)
428     {
429       try
430       {
431         for (int i = 0; i < files.size(); i++)
432         {
433           String file = files.get(i).toString();
434           String protocol = FormatAdapter.FILE;
435           String format = null;
436
437           if (file.endsWith(".jar"))
438           {
439             format = "Jalview";
440
441           }
442           else
443           {
444             format = new IdentifyFile().Identify(file, protocol);
445           }
446
447           new FileLoader().LoadFile(file, protocol, format);
448
449         }
450       } catch (Exception ex)
451       {
452       }
453     }
454   }
455
456   /**
457    * DOCUMENT ME!
458    * 
459    * @param e
460    *          DOCUMENT ME!
461    */
462   public void inputLocalFileMenuItem_actionPerformed(AlignViewport viewport)
463   {
464     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
465             .getProperty("LAST_DIRECTORY"),
466             jalview.io.AppletFormatAdapter.READABLE_EXTENSIONS,
467             jalview.io.AppletFormatAdapter.READABLE_FNAMES,
468             jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
469
470     chooser.setFileView(new JalviewFileView());
471     chooser.setDialogTitle("Open local file");
472     chooser.setToolTipText("Open");
473
474     int value = chooser.showOpenDialog(this);
475
476     if (value == JalviewFileChooser.APPROVE_OPTION)
477     {
478       String choice = chooser.getSelectedFile().getPath();
479       jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
480               .getSelectedFile().getParent());
481
482       String format = null;
483       if (chooser.getSelectedFormat().equals("Jalview"))
484       {
485         format = "Jalview";
486       }
487       else
488       {
489         format = new IdentifyFile().Identify(choice, FormatAdapter.FILE);
490       }
491
492       if (viewport != null)
493       {
494         new FileLoader().LoadFile(viewport, choice, FormatAdapter.FILE,
495                 format);
496       }
497       else
498       {
499         new FileLoader().LoadFile(choice, FormatAdapter.FILE, format);
500       }
501     }
502   }
503
504   /**
505    * DOCUMENT ME!
506    * 
507    * @param e
508    *          DOCUMENT ME!
509    */
510   public void inputURLMenuItem_actionPerformed(AlignViewport viewport)
511   {
512     // This construct allows us to have a wider textfield
513     // for viewing
514     JLabel label = new JLabel("Enter URL of Input File");
515     final JComboBox history = new JComboBox();
516
517     JPanel panel = new JPanel(new GridLayout(2, 1));
518     panel.add(label);
519     panel.add(history);
520     history.setPreferredSize(new Dimension(400, 20));
521     history.setEditable(true);
522     history.addItem("http://www.");
523
524     String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
525
526     StringTokenizer st;
527
528     if (historyItems != null)
529     {
530       st = new StringTokenizer(historyItems, "\t");
531
532       while (st.hasMoreTokens())
533       {
534         history.addItem(st.nextElement());
535       }
536     }
537
538     int reply = JOptionPane.showInternalConfirmDialog(desktop, panel,
539             "Input Alignment From URL", JOptionPane.OK_CANCEL_OPTION);
540
541     if (reply != JOptionPane.OK_OPTION)
542     {
543       return;
544     }
545
546     String url = history.getSelectedItem().toString();
547
548     if (url.toLowerCase().endsWith(".jar"))
549     {
550       if (viewport != null)
551       {
552         new FileLoader().LoadFile(viewport, url, FormatAdapter.URL,
553                 "Jalview");
554       }
555       else
556       {
557         new FileLoader().LoadFile(url, FormatAdapter.URL, "Jalview");
558       }
559     }
560     else
561     {
562       String format = new IdentifyFile().Identify(url, FormatAdapter.URL);
563
564       if (format.equals("URL NOT FOUND"))
565       {
566         JOptionPane.showInternalMessageDialog(Desktop.desktop,
567                 "Couldn't locate " + url, "URL not found",
568                 JOptionPane.WARNING_MESSAGE);
569
570         return;
571       }
572
573       if (viewport != null)
574       {
575         new FileLoader().LoadFile(viewport, url, FormatAdapter.URL, format);
576       }
577       else
578       {
579         new FileLoader().LoadFile(url, FormatAdapter.URL, format);
580       }
581     }
582   }
583
584   /**
585    * DOCUMENT ME!
586    * 
587    * @param e
588    *          DOCUMENT ME!
589    */
590   public void inputTextboxMenuItem_actionPerformed(AlignViewport viewport)
591   {
592     CutAndPasteTransfer cap = new CutAndPasteTransfer();
593     cap.setForInput(viewport);
594     Desktop.addInternalFrame(cap, "Cut & Paste Alignment File", 600, 500);
595   }
596
597   /*
598    * Exit the program
599    */
600   public void quit()
601   {
602     jalview.bin.Cache.setProperty("SCREEN_X", getBounds().x + "");
603     jalview.bin.Cache.setProperty("SCREEN_Y", getBounds().y + "");
604     jalview.bin.Cache.setProperty("SCREEN_WIDTH", getWidth() + "");
605     jalview.bin.Cache.setProperty("SCREEN_HEIGHT", getHeight() + "");
606     System.exit(0);
607   }
608
609   /**
610    * DOCUMENT ME!
611    * 
612    * @param e
613    *          DOCUMENT ME!
614    */
615   public void aboutMenuItem_actionPerformed(ActionEvent e)
616   {
617     StringBuffer message = new StringBuffer("Jalview version "
618             + jalview.bin.Cache.getProperty("VERSION") + "; last updated: "
619             + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
620
621     if (!jalview.bin.Cache.getProperty("LATEST_VERSION").equals(
622             jalview.bin.Cache.getProperty("VERSION")))
623     {
624       message
625               .append("\n\n!! Jalview version "
626                       + jalview.bin.Cache.getProperty("LATEST_VERSION")
627                       + " is available for download from http://www.jalview.org !!\n");
628
629     }
630     // TODO: update this text for each release or centrally store it for lite
631     // and application
632     message
633             .append("\nAuthors:  Andrew Waterhouse, Jim Procter, Michele Clamp, James Cuff, Steve Searle,\n    David Martin & Geoff Barton."
634                     + "\nDevelopment managed by The Barton Group, University of Dundee, Scotland, UK.\n"
635                     + "\nFor help, see the FAQ at www.jalview.org and/or join the jalview-discuss@jalview.org mailing list\n"
636                     + "\nIf  you use Jalview, please cite:"
637                     + "\nWaterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
638                     + "\nJalview Version 2 - a multiple sequence alignment editor and analysis workbench"
639                     + "\nBioinformatics doi: 10.1093/bioinformatics/btp033");
640     JOptionPane.showInternalMessageDialog(Desktop.desktop,
641
642     message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
643   }
644
645   /**
646    * DOCUMENT ME!
647    * 
648    * @param e
649    *          DOCUMENT ME!
650    */
651   public void documentationMenuItem_actionPerformed(ActionEvent e)
652   {
653     try
654     {
655       ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
656       java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
657       javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
658
659       javax.help.HelpBroker hb = hs.createHelpBroker();
660       hb.setCurrentID("home");
661       hb.setDisplayed(true);
662     } catch (Exception ex)
663     {
664     }
665   }
666
667   public void closeAll_actionPerformed(ActionEvent e)
668   {
669     JInternalFrame[] frames = desktop.getAllFrames();
670     for (int i = 0; i < frames.length; i++)
671     {
672       try
673       {
674         frames[i].setClosed(true);
675       } catch (java.beans.PropertyVetoException ex)
676       {
677       }
678     }
679     System.out.println("ALL CLOSED");
680     if (v_client != null)
681     {
682       // TODO clear binding to vamsas document objects on close_all
683
684     }
685   }
686
687   public void raiseRelated_actionPerformed(ActionEvent e)
688   {
689     reorderAssociatedWindows(false, false);
690   }
691
692   public void minimizeAssociated_actionPerformed(ActionEvent e)
693   {
694     reorderAssociatedWindows(true, false);
695   }
696
697   void closeAssociatedWindows()
698   {
699     reorderAssociatedWindows(false, true);
700   }
701
702   /*
703    * (non-Javadoc)
704    * 
705    * @seejalview.jbgui.GDesktop#garbageCollect_actionPerformed(java.awt.event.
706    * ActionEvent)
707    */
708   protected void garbageCollect_actionPerformed(ActionEvent e)
709   {
710     // We simply collect the garbage
711     jalview.bin.Cache.log.debug("Collecting garbage...");
712     System.gc();
713     jalview.bin.Cache.log.debug("Finished garbage collection.");
714   }
715
716   /*
717    * (non-Javadoc)
718    * 
719    * @see
720    * jalview.jbgui.GDesktop#showMemusage_actionPerformed(java.awt.event.ActionEvent
721    * )
722    */
723   protected void showMemusage_actionPerformed(ActionEvent e)
724   {
725     desktop.showMemoryUsage(showMemusage.isSelected());
726   }
727
728   void reorderAssociatedWindows(boolean minimize, boolean close)
729   {
730     JInternalFrame[] frames = desktop.getAllFrames();
731     if (frames == null || frames.length < 1)
732     {
733       return;
734     }
735
736     AlignViewport source = null, target = null;
737     if (frames[0] instanceof AlignFrame)
738     {
739       source = ((AlignFrame) frames[0]).getCurrentView();
740     }
741     else if (frames[0] instanceof TreePanel)
742     {
743       source = ((TreePanel) frames[0]).getViewPort();
744     }
745     else if (frames[0] instanceof PCAPanel)
746     {
747       source = ((PCAPanel) frames[0]).av;
748     }
749     else if (frames[0].getContentPane() instanceof PairwiseAlignPanel)
750     {
751       source = ((PairwiseAlignPanel) frames[0].getContentPane()).av;
752     }
753
754     if (source != null)
755     {
756       for (int i = 0; i < frames.length; i++)
757       {
758         target = null;
759         if (frames[i] == null)
760         {
761           continue;
762         }
763         if (frames[i] instanceof AlignFrame)
764         {
765           target = ((AlignFrame) frames[i]).getCurrentView();
766         }
767         else if (frames[i] instanceof TreePanel)
768         {
769           target = ((TreePanel) frames[i]).getViewPort();
770         }
771         else if (frames[i] instanceof PCAPanel)
772         {
773           target = ((PCAPanel) frames[i]).av;
774         }
775         else if (frames[i].getContentPane() instanceof PairwiseAlignPanel)
776         {
777           target = ((PairwiseAlignPanel) frames[i].getContentPane()).av;
778         }
779
780         if (source == target)
781         {
782           try
783           {
784             if (close)
785             {
786               frames[i].setClosed(true);
787             }
788             else
789             {
790               frames[i].setIcon(minimize);
791               if (!minimize)
792               {
793                 frames[i].toFront();
794               }
795             }
796
797           } catch (java.beans.PropertyVetoException ex)
798           {
799           }
800         }
801       }
802     }
803   }
804
805   /**
806    * DOCUMENT ME!
807    * 
808    * @param e
809    *          DOCUMENT ME!
810    */
811   protected void preferences_actionPerformed(ActionEvent e)
812   {
813     new Preferences();
814   }
815
816   /**
817    * DOCUMENT ME!
818    * 
819    * @param e
820    *          DOCUMENT ME!
821    */
822   public void saveState_actionPerformed(ActionEvent e)
823   {
824     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
825             .getProperty("LAST_DIRECTORY"), new String[]
826     { "jar" }, new String[]
827     { "Jalview Project" }, "Jalview Project");
828
829     chooser.setFileView(new JalviewFileView());
830     chooser.setDialogTitle("Save State");
831
832     int value = chooser.showSaveDialog(this);
833
834     if (value == JalviewFileChooser.APPROVE_OPTION)
835     {
836       java.io.File choice = chooser.getSelectedFile();
837       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
838       new Jalview2XML().SaveState(choice);
839     }
840   }
841
842   /**
843    * DOCUMENT ME!
844    * 
845    * @param e
846    *          DOCUMENT ME!
847    */
848   public void loadState_actionPerformed(ActionEvent e)
849   {
850     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
851             .getProperty("LAST_DIRECTORY"), new String[]
852     { "jar" }, new String[]
853     { "Jalview Project" }, "Jalview Project");
854     chooser.setFileView(new JalviewFileView());
855     chooser.setDialogTitle("Restore state");
856
857     int value = chooser.showOpenDialog(this);
858
859     if (value == JalviewFileChooser.APPROVE_OPTION)
860     {
861       String choice = chooser.getSelectedFile().getAbsolutePath();
862       jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
863               .getSelectedFile().getParent());
864       new Jalview2XML().LoadJalviewAlign(choice);
865     }
866   }
867
868   public void inputSequence_actionPerformed(ActionEvent e)
869   {
870     new SequenceFetcher(this);
871   }
872
873   JPanel progressPanel;
874
875   public void startLoading(final String fileName)
876   {
877     if (fileLoadingCount == 0)
878     {
879       addProgressPanel("Loading File: " + fileName + "   ");
880
881     }
882     fileLoadingCount++;
883   }
884
885   private JProgressBar addProgressPanel(String string)
886   {
887     if (progressPanel == null)
888     {
889       progressPanel = new JPanel(new BorderLayout());
890       totalProgressCount = 0;
891     }
892     JProgressBar progressBar = new JProgressBar();
893     progressBar.setIndeterminate(true);
894
895     progressPanel.add(new JLabel(string), BorderLayout.WEST);
896
897     progressPanel.add(progressBar, BorderLayout.CENTER);
898
899     instance.getContentPane().add(progressPanel, BorderLayout.SOUTH);
900     totalProgressCount++;
901     validate();
902     return progressBar;
903   }
904
905   int totalProgressCount = 0;
906
907   private void removeProgressPanel(JProgressBar progbar)
908   {
909     if (progressPanel != null)
910     {
911       progressPanel.remove(progbar);
912       if (--totalProgressCount < 1)
913       {
914         this.getContentPane().remove(progressPanel);
915         progressPanel = null;
916       }
917     }
918     validate();
919   }
920
921   public void stopLoading()
922   {
923     fileLoadingCount--;
924     if (fileLoadingCount < 1)
925     {
926       if (progressPanel != null)
927       {
928         this.getContentPane().remove(progressPanel);
929         progressPanel = null;
930       }
931       fileLoadingCount = 0;
932     }
933     validate();
934   }
935
936   public static int getViewCount(String viewId)
937   {
938     AlignViewport[] aps = getViewports(viewId);
939     return (aps == null) ? 0 : aps.length;
940   }
941
942   /**
943    * 
944    * @param viewId
945    * @return all AlignmentPanels concerning the viewId sequence set
946    */
947   public static AlignmentPanel[] getAlignmentPanels(String viewId)
948   {
949     int count = 0;
950     JInternalFrame[] frames = Desktop.desktop.getAllFrames();
951     ArrayList aps = new ArrayList();
952     for (int t = 0; t < frames.length; t++)
953     {
954       if (frames[t] instanceof AlignFrame)
955       {
956         AlignFrame af = (AlignFrame) frames[t];
957         for (int a = 0; a < af.alignPanels.size(); a++)
958         {
959           if (viewId
960                   .equals(((AlignmentPanel) af.alignPanels.elementAt(a)).av
961                           .getSequenceSetId()))
962           {
963             aps.add(af.alignPanels.elementAt(a));
964           }
965         }
966       }
967     }
968     if (aps.size() == 0)
969     {
970       return null;
971     }
972     AlignmentPanel[] vap = new AlignmentPanel[aps.size()];
973     for (int t = 0; t < vap.length; t++)
974     {
975       vap[t] = (AlignmentPanel) aps.get(t);
976     }
977     return vap;
978   }
979
980   /**
981    * get all the viewports on an alignment.
982    * 
983    * @param sequenceSetId
984    *          unique alignment id
985    * @return all viewports on the alignment bound to sequenceSetId
986    */
987   public static AlignViewport[] getViewports(String sequenceSetId)
988   {
989     Vector viewp = new Vector();
990     if (desktop != null)
991     {
992       javax.swing.JInternalFrame[] frames = instance.getAllFrames();
993
994       for (int t = 0; t < frames.length; t++)
995       {
996         if (frames[t] instanceof AlignFrame)
997         {
998           AlignFrame afr = ((AlignFrame) frames[t]);
999           if (afr.getViewport().getSequenceSetId().equals(sequenceSetId))
1000           {
1001             if (afr.alignPanels != null)
1002             {
1003               for (int a = 0; a < afr.alignPanels.size(); a++)
1004               {
1005                 if (sequenceSetId.equals(((AlignmentPanel) afr.alignPanels
1006                         .elementAt(a)).av.getSequenceSetId()))
1007                 {
1008                   viewp.addElement(((AlignmentPanel) afr.alignPanels
1009                           .elementAt(a)).av);
1010                 }
1011               }
1012             }
1013             else
1014             {
1015               viewp.addElement(((AlignFrame) frames[t]).getViewport());
1016             }
1017           }
1018         }
1019       }
1020       if (viewp.size() > 0)
1021       {
1022         AlignViewport[] vp = new AlignViewport[viewp.size()];
1023         viewp.copyInto(vp);
1024         return vp;
1025       }
1026     }
1027     return null;
1028   }
1029
1030   public void explodeViews(AlignFrame af)
1031   {
1032     int size = af.alignPanels.size();
1033     if (size < 2)
1034     {
1035       return;
1036     }
1037
1038     for (int i = 0; i < size; i++)
1039     {
1040       AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(i);
1041       AlignFrame newaf = new AlignFrame(ap);
1042       if (ap.av.explodedPosition != null
1043               && !ap.av.explodedPosition.equals(af.getBounds()))
1044       {
1045         newaf.setBounds(ap.av.explodedPosition);
1046       }
1047
1048       ap.av.gatherViewsHere = false;
1049
1050       addInternalFrame(newaf, af.getTitle(), AlignFrame.DEFAULT_WIDTH,
1051               AlignFrame.DEFAULT_HEIGHT);
1052     }
1053
1054     af.alignPanels.clear();
1055     af.closeMenuItem_actionPerformed(true);
1056
1057   }
1058
1059   public void gatherViews(AlignFrame source)
1060   {
1061     source.viewport.gatherViewsHere = true;
1062     source.viewport.explodedPosition = source.getBounds();
1063     JInternalFrame[] frames = desktop.getAllFrames();
1064     String viewId = source.viewport.sequenceSetID;
1065
1066     for (int t = 0; t < frames.length; t++)
1067     {
1068       if (frames[t] instanceof AlignFrame && frames[t] != source)
1069       {
1070         AlignFrame af = (AlignFrame) frames[t];
1071         boolean gatherThis = false;
1072         for (int a = 0; a < af.alignPanels.size(); a++)
1073         {
1074           AlignmentPanel ap = (AlignmentPanel) af.alignPanels.elementAt(a);
1075           if (viewId.equals(ap.av.getSequenceSetId()))
1076           {
1077             gatherThis = true;
1078             ap.av.gatherViewsHere = false;
1079             ap.av.explodedPosition = af.getBounds();
1080             source.addAlignmentPanel(ap, false);
1081           }
1082         }
1083
1084         if (gatherThis)
1085         {
1086           af.alignPanels.clear();
1087           af.closeMenuItem_actionPerformed(true);
1088         }
1089       }
1090     }
1091
1092   }
1093
1094   jalview.gui.VamsasApplication v_client = null;
1095
1096   public void vamsasImport_actionPerformed(ActionEvent e)
1097   {
1098     if (v_client == null)
1099     {
1100       // Load and try to start a session.
1101       JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
1102               .getProperty("LAST_DIRECTORY"));
1103
1104       chooser.setFileView(new JalviewFileView());
1105       chooser.setDialogTitle("Open a saved VAMSAS session");
1106       chooser
1107               .setToolTipText("select a vamsas session to be opened as a new vamsas session.");
1108
1109       int value = chooser.showOpenDialog(this);
1110
1111       if (value == JalviewFileChooser.APPROVE_OPTION)
1112       {
1113         String fle = chooser.getSelectedFile().toString();
1114         if (!vamsasImport(chooser.getSelectedFile()))
1115         {
1116           JOptionPane.showInternalMessageDialog(Desktop.desktop,
1117                   "Couldn't import '" + fle + "' as a new vamsas session.",
1118                   "Vamsas Document Import Failed",
1119                   JOptionPane.ERROR_MESSAGE);
1120         }
1121       }
1122     }
1123     else
1124     {
1125       jalview.bin.Cache.log
1126               .error("Implementation error - load session from a running session is not supported.");
1127     }
1128   }
1129
1130   /**
1131    * import file into a new vamsas session (uses jalview.gui.VamsasApplication) 
1132    * @param file 
1133    * @return true if import was a success and a session was started.
1134    */
1135   public boolean vamsasImport(URL url)
1136   {
1137     // TODO: create progress bar
1138     if (v_client != null)
1139     {
1140       
1141       jalview.bin.Cache.log
1142       .error("Implementation error - load session from a running session is not supported.");
1143       return false;     
1144     }
1145     
1146     try
1147       {
1148       // copy the URL content to a temporary local file
1149       // TODO: be a bit cleverer here with nio (?!)
1150       File file = File.createTempFile("vdocfromurl", ".vdj");
1151       FileOutputStream fos = new FileOutputStream(file);
1152       BufferedInputStream bis = new BufferedInputStream(url.openStream());
1153       byte[] buffer = new byte[2048];
1154       int ln;
1155       while ((ln = bis.read(buffer))>-1)
1156       {
1157         fos.write(buffer,0,ln);
1158       }
1159       bis.close();
1160       fos.close();
1161       v_client = new jalview.gui.VamsasApplication(this, file, url.toExternalForm());
1162       } catch (Exception ex)
1163       {
1164         jalview.bin.Cache.log.error(
1165                 "Failed to create new vamsas session from contents of URL "+url,ex);
1166         return false;
1167       }
1168       setupVamsasConnectedGui();
1169       v_client.initial_update(); // TODO: thread ?
1170       return v_client.inSession();
1171     }
1172
1173   /**
1174    * import file into a new vamsas session (uses jalview.gui.VamsasApplication) 
1175    * @param file 
1176    * @return true if import was a success and a session was started.
1177    */
1178   public boolean vamsasImport(File file)
1179   {
1180     // TODO: create progress bar
1181     if (v_client != null)
1182     {
1183
1184       jalview.bin.Cache.log
1185               .error("Implementation error - load session from a running session is not supported.");
1186       return false;
1187     }
1188
1189     try
1190     {
1191       v_client = new jalview.gui.VamsasApplication(this, file,null);
1192     } catch (Exception ex)
1193     {
1194       jalview.bin.Cache.log.error(
1195               "New vamsas session from existing session file failed:", ex);
1196       return false;
1197     }
1198     setupVamsasConnectedGui();
1199     v_client.initial_update(); // TODO: thread ?
1200     return v_client.inSession();
1201   }
1202   public boolean joinVamsasSession(String mysesid) {
1203     if (v_client!=null)
1204     {
1205       throw new Error("Trying to join a vamsas session when another is already connected.");
1206     }
1207     if (mysesid==null)
1208     {
1209       throw new Error("Invalid vamsas session id.");
1210     }
1211     v_client = new VamsasApplication(this, mysesid);
1212     setupVamsasConnectedGui();
1213     v_client.initial_update();
1214     return (v_client.inSession());
1215   }
1216
1217   public void vamsasStart_actionPerformed(ActionEvent e)
1218   {
1219     if (v_client == null)
1220     {
1221       // Start a session.
1222       // we just start a default session for moment.
1223       /*
1224        * JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
1225        * getProperty("LAST_DIRECTORY"));
1226        * 
1227        * chooser.setFileView(new JalviewFileView());
1228        * chooser.setDialogTitle("Load Vamsas file");
1229        * chooser.setToolTipText("Import");
1230        * 
1231        * int value = chooser.showOpenDialog(this);
1232        * 
1233        * if (value == JalviewFileChooser.APPROVE_OPTION) { v_client = new
1234        * jalview.gui.VamsasApplication(this, chooser.getSelectedFile());
1235        */
1236       v_client = new VamsasApplication(this);
1237       setupVamsasConnectedGui();
1238       v_client.initial_update(); // TODO: thread ?
1239     }
1240     else
1241     {
1242       // store current data in session.
1243       v_client.push_update(); // TODO: thread
1244     }
1245   }
1246
1247   protected void setupVamsasConnectedGui()
1248   {
1249     vamsasStart.setText("Session Update");
1250     vamsasSave.setVisible(true);
1251     vamsasStop.setVisible(true);
1252     vamsasImport.setVisible(false); // Document import to existing session is
1253     // not possible for vamsas-client-1.0.
1254   }
1255
1256   protected void setupVamsasDisconnectedGui()
1257   {
1258     vamsasSave.setVisible(false);
1259     vamsasStop.setVisible(false);
1260     vamsasImport.setVisible(true);
1261     vamsasStart.setText("New Vamsas Session");
1262   }
1263
1264   public void vamsasStop_actionPerformed(ActionEvent e)
1265   {
1266     if (v_client != null)
1267     {
1268       v_client.end_session();
1269       v_client = null;
1270       setupVamsasDisconnectedGui();
1271     }
1272   }
1273
1274   protected void buildVamsasStMenu()
1275   {
1276     if (v_client == null)
1277     {
1278       String[] sess = null;
1279       try
1280       {
1281         sess = VamsasApplication.getSessionList();
1282       } catch (Exception e)
1283       {
1284         jalview.bin.Cache.log.warn(
1285                 "Problem getting current sessions list.", e);
1286         sess = null;
1287       }
1288       if (sess != null)
1289       {
1290         jalview.bin.Cache.log.debug("Got current sessions list: "
1291                 + sess.length + " entries.");
1292         VamsasStMenu.removeAll();
1293         for (int i = 0; i < sess.length; i++)
1294         {
1295           JMenuItem sessit = new JMenuItem();
1296           sessit.setText(sess[i]);
1297           sessit.setToolTipText("Connect to session " + sess[i]);
1298           final Desktop dsktp = this;
1299           final String mysesid = sess[i];
1300           sessit.addActionListener(new ActionListener()
1301           {
1302
1303             public void actionPerformed(ActionEvent e)
1304             {
1305               if (dsktp.v_client == null)
1306               {
1307                 Thread rthr = new Thread(new Runnable()
1308                 {
1309
1310                   public void run()
1311                   {
1312                     dsktp.v_client = new VamsasApplication(dsktp, mysesid);
1313                     dsktp.setupVamsasConnectedGui();
1314                     dsktp.v_client.initial_update();
1315                   }
1316
1317                 });
1318                 rthr.start();
1319               }
1320             };
1321           });
1322           VamsasStMenu.add(sessit);
1323         }
1324         // don't show an empty menu.
1325         VamsasStMenu.setVisible(sess.length > 0);
1326
1327       }
1328       else
1329       {
1330         jalview.bin.Cache.log.debug("No current vamsas sessions.");
1331         VamsasStMenu.removeAll();
1332         VamsasStMenu.setVisible(false);
1333       }
1334     }
1335     else
1336     {
1337       // Not interested in the content. Just hide ourselves.
1338       VamsasStMenu.setVisible(false);
1339     }
1340   }
1341
1342   public void vamsasSave_actionPerformed(ActionEvent e)
1343   {
1344     if (v_client != null)
1345     {
1346       JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
1347               .getProperty("LAST_DIRECTORY"), new String[]
1348       { "vdj" }, // TODO: VAMSAS DOCUMENT EXTENSION is VDJ
1349               new String[]
1350               { "Vamsas Document" }, "Vamsas Document");
1351
1352       chooser.setFileView(new JalviewFileView());
1353       chooser.setDialogTitle("Save Vamsas Document Archive");
1354
1355       int value = chooser.showSaveDialog(this);
1356
1357       if (value == JalviewFileChooser.APPROVE_OPTION)
1358       {
1359         java.io.File choice = chooser.getSelectedFile();
1360         jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
1361         String warnmsg = null;
1362         String warnttl = null;
1363         try
1364         {
1365           v_client.vclient.storeDocument(choice);
1366         } catch (Error ex)
1367         {
1368           warnttl = "Serious Problem saving Vamsas Document";
1369           warnmsg = ex.toString();
1370           jalview.bin.Cache.log.error("Error Whilst saving document to "
1371                   + choice, ex);
1372
1373         } catch (Exception ex)
1374         {
1375           warnttl = "Problem saving Vamsas Document.";
1376           warnmsg = ex.toString();
1377           jalview.bin.Cache.log.warn("Exception Whilst saving document to "
1378                   + choice, ex);
1379
1380         }
1381         if (warnmsg != null)
1382         {
1383           JOptionPane.showInternalMessageDialog(Desktop.desktop,
1384
1385           warnmsg, warnttl, JOptionPane.ERROR_MESSAGE);
1386         }
1387       }
1388     }
1389   }
1390
1391   JProgressBar vamUpdate = null;
1392
1393   /**
1394    * hide vamsas user gui bits when a vamsas document event is being handled.
1395    * 
1396    * @param b
1397    *          true to hide gui, false to reveal gui
1398    */
1399   public void setVamsasUpdate(boolean b)
1400   {
1401     jalview.bin.Cache.log.debug("Setting gui for Vamsas update "
1402             + (b ? "in progress" : "finished"));
1403
1404     if (vamUpdate != null)
1405     {
1406       this.removeProgressPanel(vamUpdate);
1407     }
1408     if (b)
1409     {
1410       vamUpdate = this.addProgressPanel("Updating vamsas session");
1411     }
1412     vamsasStart.setVisible(!b);
1413     vamsasStop.setVisible(!b);
1414     vamsasSave.setVisible(!b);
1415   }
1416
1417   public JInternalFrame[] getAllFrames()
1418   {
1419     return desktop.getAllFrames();
1420   }
1421
1422   /**
1423    * Checks the given url to see if it gives a response indicating that the user
1424    * should be informed of a new questionnaire.
1425    * 
1426    * @param url
1427    */
1428   public void checkForQuestionnaire(String url)
1429   {
1430     UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
1431     // javax.swing.SwingUtilities.invokeLater(jvq);
1432     new Thread(jvq).start();
1433   }
1434
1435   /**
1436    * Proxy class for JDesktopPane which optionally displays the current memory
1437    * usage and highlights the desktop area with a red bar if free memory runs
1438    * low.
1439    * 
1440    * @author AMW
1441    */
1442   public class MyDesktopPane extends JDesktopPane implements Runnable
1443   {
1444
1445     boolean showMemoryUsage = false;
1446
1447     Runtime runtime;
1448
1449     java.text.NumberFormat df;
1450
1451     float maxMemory, allocatedMemory, freeMemory, totalFreeMemory,
1452             percentUsage;
1453
1454     public MyDesktopPane(boolean showMemoryUsage)
1455     {
1456       showMemoryUsage(showMemoryUsage);
1457     }
1458
1459     public void showMemoryUsage(boolean showMemoryUsage)
1460     {
1461       this.showMemoryUsage = showMemoryUsage;
1462       if (showMemoryUsage)
1463       {
1464         Thread worker = new Thread(this);
1465         worker.start();
1466       }
1467     }
1468
1469     public boolean isShowMemoryUsage()
1470     {
1471       return showMemoryUsage;
1472     }
1473
1474     public void run()
1475     {
1476       df = java.text.NumberFormat.getNumberInstance();
1477       df.setMaximumFractionDigits(2);
1478       runtime = Runtime.getRuntime();
1479
1480       while (showMemoryUsage)
1481       {
1482         try
1483         {
1484           Thread.sleep(3000);
1485           maxMemory = runtime.maxMemory() / 1048576f;
1486           allocatedMemory = runtime.totalMemory() / 1048576f;
1487           freeMemory = runtime.freeMemory() / 1048576f;
1488           totalFreeMemory = freeMemory + (maxMemory - allocatedMemory);
1489
1490           percentUsage = (totalFreeMemory / maxMemory) * 100;
1491
1492           // if (percentUsage < 20)
1493           {
1494             // border1 = BorderFactory.createMatteBorder(12, 12, 12, 12,
1495             // Color.red);
1496             // instance.set.setBorder(border1);
1497           }
1498           repaint();
1499
1500         } catch (Exception ex)
1501         {
1502           ex.printStackTrace();
1503         }
1504       }
1505     }
1506
1507     public void paintComponent(Graphics g)
1508     {
1509       if (showMemoryUsage)
1510       {
1511         if (percentUsage < 20)
1512           g.setColor(Color.red);
1513
1514         g.drawString("Total Free Memory: " + df.format(totalFreeMemory)
1515                 + "MB; Max Memory: " + df.format(maxMemory) + "MB; "
1516                 + df.format(percentUsage) + "%", 10, getHeight()
1517                 - g.getFontMetrics().getHeight());
1518       }
1519     }
1520
1521   }
1522
1523   protected JMenuItem groovyShell;
1524
1525   public void doGroovyCheck()
1526   {
1527     if (jalview.bin.Cache.groovyJarsPresent())
1528     {
1529       groovyShell = new JMenuItem();
1530       groovyShell.setText("Groovy Console...");
1531       groovyShell.addActionListener(new ActionListener()
1532       {
1533         public void actionPerformed(ActionEvent e)
1534         {
1535           groovyShell_actionPerformed(e);
1536         }
1537       });
1538       toolsMenu.add(groovyShell);
1539       groovyShell.setVisible(true);
1540     }
1541   }
1542
1543   /**
1544    * Accessor method to quickly get all the AlignmentFrames loaded.
1545    */
1546   public static AlignFrame[] getAlignframes()
1547   {
1548     JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1549
1550     if (frames == null)
1551     {
1552       return null;
1553     }
1554     Vector avp = new Vector();
1555     try
1556     {
1557       // REVERSE ORDER
1558       for (int i = frames.length - 1; i > -1; i--)
1559       {
1560         if (frames[i] instanceof AlignFrame)
1561         {
1562           AlignFrame af = (AlignFrame) frames[i];
1563           avp.addElement(af);
1564         }
1565       }
1566     } catch (Exception ex)
1567     {
1568       ex.printStackTrace();
1569     }
1570     if (avp.size() == 0)
1571     {
1572       return null;
1573     }
1574     AlignFrame afs[] = new AlignFrame[avp.size()];
1575     for (int i = 0, j = avp.size(); i < j; i++)
1576     {
1577       afs[i] = (AlignFrame) avp.elementAt(i);
1578     }
1579     avp.clear();
1580     return afs;
1581   }
1582
1583   /**
1584    * Add Groovy Support to Jalview
1585    */
1586   public void groovyShell_actionPerformed(ActionEvent e)
1587   {
1588     // use reflection to avoid creating compilation dependency.
1589     if (!jalview.bin.Cache.groovyJarsPresent())
1590     {
1591       throw new Error(
1592               "Implementation Error. Cannot create groovyShell without Groovy on the classpath!");
1593     }
1594     try
1595     {
1596       Class gcClass = Desktop.class.getClassLoader().loadClass(
1597               "groovy.ui.Console");
1598       Constructor gccons = gcClass.getConstructor(null);
1599       java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
1600               new Class[]
1601               { String.class, Object.class });
1602       java.lang.reflect.Method run = gcClass.getMethod("run", null);
1603       Object gc = gccons.newInstance(null);
1604       setvar.invoke(gc, new Object[]
1605       { "Jalview", this });
1606       run.invoke(gc, null);
1607     } catch (Exception ex)
1608     {
1609       jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
1610       JOptionPane
1611               .showInternalMessageDialog(
1612                       Desktop.desktop,
1613
1614                       "Couldn't create the groovy Shell. Check the error log for the details of what went wrong.",
1615                       "Jalview Groovy Support Failed",
1616                       JOptionPane.ERROR_MESSAGE);
1617     }
1618   }
1619
1620   /**
1621    * Progress bars managed by the IProgressIndicator method.
1622    */
1623   private Hashtable progressBars, progressBarHandlers;
1624
1625   /*
1626    * (non-Javadoc)
1627    * 
1628    * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
1629    */
1630   public void setProgressBar(String message, long id)
1631   {
1632     if (progressBars == null)
1633     {
1634       progressBars = new Hashtable();
1635       progressBarHandlers = new Hashtable();
1636     }
1637
1638     if (progressBars.get(new Long(id)) != null)
1639     {
1640       JProgressBar progressPanel = (JProgressBar) progressBars
1641               .remove(new Long(id));
1642       if (progressBarHandlers.contains(new Long(id)))
1643       {
1644         progressBarHandlers.remove(new Long(id));
1645       }
1646       removeProgressPanel(progressPanel);
1647     }
1648     else
1649     {
1650       progressBars.put(new Long(id), addProgressPanel(message));
1651     }
1652   }
1653
1654   /*
1655    * (non-Javadoc)
1656    * 
1657    * @see jalview.gui.IProgressIndicator#registerHandler(long,
1658    * jalview.gui.IProgressIndicatorHandler)
1659    */
1660   public void registerHandler(final long id,
1661           final IProgressIndicatorHandler handler)
1662   {
1663     if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
1664     {
1665       throw new Error(
1666               "call setProgressBar before registering the progress bar's handler.");
1667     }
1668     progressBarHandlers.put(new Long(id), handler);
1669     final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
1670     if (handler.canCancel())
1671     {
1672       JButton cancel = new JButton("Cancel");
1673       final IProgressIndicator us = this;
1674       cancel.addActionListener(new ActionListener()
1675       {
1676
1677         public void actionPerformed(ActionEvent e)
1678         {
1679           handler.cancelActivity(id);
1680           us.setProgressBar("Cancelled "
1681                   + ((JLabel) progressPanel.getComponent(0)).getText(), id);
1682         }
1683       });
1684       progressPanel.add(cancel, BorderLayout.EAST);
1685     }
1686   }
1687
1688   /**
1689    * This will return the first AlignFrame viewing AlignViewport av. It will
1690    * break if there are more than one AlignFrames viewing a particular av. This
1691    * 
1692    * @param av
1693    * @return alignFrame for av
1694    */
1695   public static AlignFrame getAlignFrameFor(AlignViewport av)
1696   {
1697     if (desktop != null)
1698     {
1699       AlignmentPanel[] aps = getAlignmentPanels(av.getSequenceSetId());
1700       for (int panel = 0; aps != null && panel < aps.length; panel++)
1701       {
1702         if (aps[panel] != null && aps[panel].av == av)
1703         {
1704           return aps[panel].alignFrame;
1705         }
1706       }
1707     }
1708     return null;
1709   }
1710
1711   public VamsasApplication getVamsasApplication()
1712   {
1713     return v_client;
1714
1715   }
1716 }