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